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.
This commit is contained in:
Daniel Grunwald
2020-08-06 23:18:12 +02:00
parent 5bd47c171f
commit b788441c78
3 changed files with 42 additions and 18 deletions
@@ -224,24 +224,26 @@ namespace ICSharpCode.Decompiler.TypeSystem
var mainModuleWithOptions = mainModule.WithOptions(typeSystemOptions);
var referencedAssembliesWithOptions = referencedAssemblies.Select(file => file.WithOptions(typeSystemOptions));
// Primitive types are necessary to avoid assertions in ILReader.
// Fallback to MinimalCorlib to provide the primitive types.
if (!HasType(KnownTypeCode.Void) || !HasType(KnownTypeCode.Int32)) {
Init(mainModule.WithOptions(typeSystemOptions), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.Instance }));
// Other known types are necessary in order for transforms to work (e.g. Task<T> for async transform).
// Figure out which known types are missing from our type system so far:
var missingKnownTypes = KnownTypeReference.AllKnownTypes.Where(IsMissing).ToList();
if (missingKnownTypes.Count > 0) {
Init(mainModule.WithOptions(typeSystemOptions), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.CreateWithTypes(missingKnownTypes) }));
} else {
Init(mainModuleWithOptions, referencedAssembliesWithOptions);
}
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)
return true;
return false;
foreach (var file in referencedAssemblies) {
if (!file.GetTypeDefinition(name).IsNil)
return true;
return false;
}
return false;
return true;
}
}