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 @@ -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;
}
}

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

@ -31,22 +31,25 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -31,22 +31,25 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
/// </summary>
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; }
CorlibTypeDefinition[] typeDefinitions;
readonly CorlibNamespace rootNamespace;
private MinimalCorlib(ICompilation compilation)
private MinimalCorlib(ICompilation compilation, IEnumerable<KnownTypeReference> types)
{
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);
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;
@ -65,7 +68,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -65,7 +68,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
public ITypeDefinition GetTypeDefinition(TopLevelTypeName topLevelTypeName)
{
foreach (var typeDef in typeDefinitions) {
if (typeDef != null && typeDef.FullTypeName == topLevelTypeName)
if (typeDef.FullTypeName == topLevelTypeName)
return typeDef;
}
return null;
@ -81,9 +84,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -81,9 +84,16 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
sealed class CorlibModuleReference : IModuleReference
{
readonly IEnumerable<KnownTypeReference> types;
public CorlibModuleReference(IEnumerable<KnownTypeReference> types)
{
this.types = types;
}
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 @@ @@ -17,6 +17,7 @@
// DEALINGS IN THE SOFTWARE.
using System;
using System.Collections.Generic;
namespace ICSharpCode.Decompiler.TypeSystem
{
@ -235,6 +236,17 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -235,6 +236,17 @@ namespace ICSharpCode.Decompiler.TypeSystem
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 string namespaceName;
readonly string name;

Loading…
Cancel
Save