Browse Source

DecompilerTypeSystem: If some known types are present in referenced assemblies but others are missing; add the missing known types to the compilation.

This ensures that FindType(KnownTypeCode).GetDefinition() always returns a usable definition.
pull/2113/head
Daniel Grunwald 5 years ago
parent
commit
b788441c78
  1. 18
      ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs
  2. 30
      ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs
  3. 12
      ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs

18
ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs

@ -224,24 +224,26 @@ namespace ICSharpCode.Decompiler.TypeSystem
var mainModuleWithOptions = mainModule.WithOptions(typeSystemOptions); var mainModuleWithOptions = mainModule.WithOptions(typeSystemOptions);
var referencedAssembliesWithOptions = referencedAssemblies.Select(file => file.WithOptions(typeSystemOptions)); var referencedAssembliesWithOptions = referencedAssemblies.Select(file => file.WithOptions(typeSystemOptions));
// Primitive types are necessary to avoid assertions in ILReader. // Primitive types are necessary to avoid assertions in ILReader.
// Fallback to MinimalCorlib to provide the primitive types. // Other known types are necessary in order for transforms to work (e.g. Task<T> for async transform).
if (!HasType(KnownTypeCode.Void) || !HasType(KnownTypeCode.Int32)) { // Figure out which known types are missing from our type system so far:
Init(mainModule.WithOptions(typeSystemOptions), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.Instance })); var missingKnownTypes = KnownTypeReference.AllKnownTypes.Where(IsMissing).ToList();
if (missingKnownTypes.Count > 0) {
Init(mainModule.WithOptions(typeSystemOptions), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.CreateWithTypes(missingKnownTypes) }));
} else { } else {
Init(mainModuleWithOptions, referencedAssembliesWithOptions); Init(mainModuleWithOptions, referencedAssembliesWithOptions);
} }
this.MainModule = (MetadataModule)base.MainModule; this.MainModule = (MetadataModule)base.MainModule;
bool HasType(KnownTypeCode code) bool IsMissing(KnownTypeReference knownType)
{ {
TopLevelTypeName name = KnownTypeReference.Get(code).TypeName; var name = knownType.TypeName;
if (!mainModule.GetTypeDefinition(name).IsNil) if (!mainModule.GetTypeDefinition(name).IsNil)
return true; return false;
foreach (var file in referencedAssemblies) { foreach (var file in referencedAssemblies) {
if (!file.GetTypeDefinition(name).IsNil) if (!file.GetTypeDefinition(name).IsNil)
return true; return false;
} }
return false; return true;
} }
} }

30
ICSharpCode.Decompiler/TypeSystem/Implementation/MinimalCorlib.cs

@ -31,22 +31,25 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
/// </summary> /// </summary>
public sealed class MinimalCorlib : IModule public sealed class MinimalCorlib : IModule
{ {
public static readonly IModuleReference Instance = new CorlibModuleReference(); /// <summary>
/// Minimal corlib instance containing all known types.
/// </summary>
public static readonly IModuleReference Instance = new CorlibModuleReference(KnownTypeReference.AllKnownTypes);
public static IModuleReference CreateWithTypes(IEnumerable<KnownTypeReference> types)
{
return new CorlibModuleReference(types);
}
public ICompilation Compilation { get; } public ICompilation Compilation { get; }
CorlibTypeDefinition[] typeDefinitions; CorlibTypeDefinition[] typeDefinitions;
readonly CorlibNamespace rootNamespace; readonly CorlibNamespace rootNamespace;
private MinimalCorlib(ICompilation compilation) private MinimalCorlib(ICompilation compilation, IEnumerable<KnownTypeReference> types)
{ {
this.Compilation = compilation; this.Compilation = compilation;
this.typeDefinitions = new CorlibTypeDefinition[KnownTypeReference.KnownTypeCodeCount]; this.typeDefinitions = types.Select(ktr => new CorlibTypeDefinition(this, ktr.KnownTypeCode)).ToArray();
this.rootNamespace = new CorlibNamespace(this, null, string.Empty, string.Empty); this.rootNamespace = new CorlibNamespace(this, null, string.Empty, string.Empty);
for (int i = 0; i < KnownTypeReference.KnownTypeCodeCount; i++) {
if (KnownTypeReference.Get((KnownTypeCode)i) != null) {
typeDefinitions[i] = new CorlibTypeDefinition(this, (KnownTypeCode)i);
}
}
} }
bool IModule.IsMainModule => Compilation.MainModule == this; bool IModule.IsMainModule => Compilation.MainModule == this;
@ -65,7 +68,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName) public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName)
{ {
foreach (var typeDef in typeDefinitions) { foreach (var typeDef in typeDefinitions) {
if (typeDef != null && typeDef.FullTypeName == topLevelTypeName) if (typeDef.FullTypeName == topLevelTypeName)
return typeDef; return typeDef;
} }
return null; return null;
@ -81,9 +84,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
sealed class CorlibModuleReference : IModuleReference sealed class CorlibModuleReference : IModuleReference
{ {
readonly IEnumerable<KnownTypeReference> types;
public CorlibModuleReference(IEnumerable<KnownTypeReference> types)
{
this.types = types;
}
IModule IModuleReference.Resolve(ITypeResolveContext context) IModule IModuleReference.Resolve(ITypeResolveContext context)
{ {
return new MinimalCorlib(context.Compilation); return new MinimalCorlib(context.Compilation, types);
} }
} }

12
ICSharpCode.Decompiler/TypeSystem/KnownTypeReference.cs

@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.TypeSystem namespace ICSharpCode.Decompiler.TypeSystem
{ {
@ -235,6 +236,17 @@ namespace ICSharpCode.Decompiler.TypeSystem
return knownTypeReferences[(int)typeCode]; return knownTypeReferences[(int)typeCode];
} }
public static IEnumerable<KnownTypeReference> AllKnownTypes {
get {
for (int i = 0; i < KnownTypeCodeCount; i++) {
var ktr = Get((KnownTypeCode)i);
if (ktr == null)
continue;
yield return ktr;
}
}
}
readonly KnownTypeCode knownTypeCode; readonly KnownTypeCode knownTypeCode;
readonly string namespaceName; readonly string namespaceName;
readonly string name; readonly string name;

Loading…
Cancel
Save