From b396d203bd2f01ac2731ebac20d9fbd7014fc70c Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sat, 14 Jul 2018 16:50:36 +0200 Subject: [PATCH] Merge IDecompilerTypeSystem with ICompilation. --- .../TypeSystem/TypeSystemLoaderTests.cs | 2 +- .../Util/SequencePointTests.cs | 3 +- .../CSharp/CSharpDecompiler.cs | 12 +-- .../CSharp/StatementBuilder.cs | 2 +- .../Transforms/IntroduceExtensionMethods.cs | 4 +- .../Transforms/IntroduceUsingDeclarations.cs | 2 +- .../DebugInfo/PortablePdbWriter.cs | 2 +- .../IL/ControlFlow/AsyncAwaitDecompiler.cs | 4 +- .../IL/Transforms/CopyPropagation.cs | 2 +- .../IL/Transforms/IILTransform.cs | 2 +- .../IL/Transforms/NullPropagationTransform.cs | 2 +- .../IL/Transforms/NullableLiftingTransform.cs | 4 +- ...ransformCollectionAndObjectInitializers.cs | 2 +- .../IL/Transforms/TransformExpressionTrees.cs | 20 ++--- .../TypeSystem/DecompilerTypeSystem.cs | 82 ++++++++++--------- .../TypeSystem/ICompilation.cs | 11 +-- .../TypeSystem/IDecompilerTypeSystem.cs | 9 +- .../Implementation/SimpleCompilation.cs | 46 ++++++----- .../TypeSystem/ReflectionHelper.cs | 2 +- ILSpy.BamlDecompiler/CecilTypeResolver.cs | 6 +- .../ConnectMethodDecompiler.cs | 2 +- 21 files changed, 113 insertions(+), 108 deletions(-) diff --git a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs index ddc11afa1..dd8945797 100644 --- a/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs +++ b/ICSharpCode.Decompiler.Tests/TypeSystem/TypeSystemLoaderTests.cs @@ -1811,7 +1811,7 @@ namespace ICSharpCode.Decompiler.Tests.TypeSystem var compilationWithSystemCore = new SimpleCompilation(SystemCore, Mscorlib); var typeRef = ReflectionHelper.ParseReflectionName("System.Func`2, System.Core"); - ITypeDefinition c = typeRef.Resolve(compilationWithSystemCore.TypeResolveContext).GetDefinition(); + ITypeDefinition c = typeRef.Resolve(new SimpleTypeResolveContext(compilationWithSystemCore)).GetDefinition(); Assert.IsNotNull(c, "System.Func<,> not found"); Assert.AreEqual("mscorlib", c.ParentModule.AssemblyName); } diff --git a/ICSharpCode.Decompiler.Tests/Util/SequencePointTests.cs b/ICSharpCode.Decompiler.Tests/Util/SequencePointTests.cs index 138a1623b..1212469b9 100644 --- a/ICSharpCode.Decompiler.Tests/Util/SequencePointTests.cs +++ b/ICSharpCode.Decompiler.Tests/Util/SequencePointTests.cs @@ -24,8 +24,7 @@ namespace ICSharpCode.Decompiler.Tests.Util { var decompiler = Tester.GetDecompilerForSnippet(code); - var firstType = decompiler.TypeSystem.Compilation.GetTopLevelTypeDefinitions().First(t => code.Contains(t.Name)); - var tree = decompiler.DecompileType(firstType.FullTypeName); + var tree = decompiler.DecompileType(new FullTypeName("C")); var output = new StringWriter(); tree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }); diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index 7c684bf1e..f4e7cb5b9 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -397,13 +397,13 @@ namespace ICSharpCode.Decompiler.CSharp void DoDecompileModuleAndAssemblyAttributes(DecompileRun decompileRun, ITypeResolveContext decompilationContext, SyntaxTree syntaxTree) { - foreach (var a in typeSystem.Compilation.MainModule.GetAssemblyAttributes()) { + foreach (var a in typeSystem.MainModule.GetAssemblyAttributes()) { var astBuilder = CreateAstBuilder(decompilationContext); var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a)); attrSection.AttributeTarget = "assembly"; syntaxTree.AddChild(attrSection, SyntaxTree.MemberRole); } - foreach (var a in typeSystem.Compilation.MainModule.GetModuleAttributes()) { + foreach (var a in typeSystem.MainModule.GetModuleAttributes()) { var astBuilder = CreateAstBuilder(decompilationContext); var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a)); attrSection.AttributeTarget = "module"; @@ -603,7 +603,7 @@ namespace ICSharpCode.Decompiler.CSharp /// public SyntaxTree DecompileType(FullTypeName fullTypeName) { - var type = typeSystem.Compilation.FindType(fullTypeName.TopLevelTypeName).GetDefinition(); + var type = typeSystem.FindType(fullTypeName.TopLevelTypeName).GetDefinition(); if (type == null) throw new InvalidOperationException($"Could not find type definition {fullTypeName} in type system."); var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule); @@ -933,12 +933,12 @@ namespace ICSharpCode.Decompiler.CSharp MethodDeclaration method = new MethodDeclaration(); method.Name = name; method.Modifiers = Modifiers.Private | Modifiers.Static; - method.Parameters.Add(new ParameterDeclaration(typeSystemAstBuilder.ConvertType(typeSystem.Compilation.FindType(source)), "input")); - method.ReturnType = typeSystemAstBuilder.ConvertType(typeSystem.Compilation.FindType(target)); + method.Parameters.Add(new ParameterDeclaration(typeSystemAstBuilder.ConvertType(typeSystem.FindType(source)), "input")); + method.ReturnType = typeSystemAstBuilder.ConvertType(typeSystem.FindType(target)); method.Body = new BlockStatement { new IfElseStatement { Condition = new BinaryOperatorExpression { - Left = new MemberReferenceExpression(new TypeReferenceExpression(typeSystemAstBuilder.ConvertType(typeSystem.Compilation.FindType(KnownTypeCode.IntPtr))), "Size"), + Left = new MemberReferenceExpression(new TypeReferenceExpression(typeSystemAstBuilder.ConvertType(typeSystem.FindType(KnownTypeCode.IntPtr))), "Size"), Operator = BinaryOperatorType.Equality, Right = new PrimitiveExpression(4) }, diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index 91189da95..03dedc00a 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -290,7 +290,7 @@ namespace ICSharpCode.Decompiler.CSharp protected internal override Statement VisitYieldReturn(YieldReturn inst) { - var elementType = currentFunction.ReturnType.GetElementTypeFromIEnumerable(typeSystem.Compilation, true, out var isGeneric); + var elementType = currentFunction.ReturnType.GetElementTypeFromIEnumerable(typeSystem, true, out var isGeneric); return new YieldReturnStatement { Expression = exprBuilder.Translate(inst.Value, typeHint: elementType).ConvertTo(elementType, exprBuilder) }; diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs index 38ab708d6..a695d9457 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs @@ -41,7 +41,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms public void Run(AstNode rootNode, TransformContext context) { this.context = context; - this.conversions = CSharpConversions.Get(context.TypeSystem.Compilation); + this.conversions = CSharpConversions.Get(context.TypeSystem); InitializeContext(rootNode.Annotation()); rootNode.AcceptVisitor(this); } @@ -56,7 +56,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms usingScope = new UsingScope(usingScope, ns); } } - var currentContext = new CSharpTypeResolveContext(context.TypeSystem.MainModule, usingScope.Resolve(context.TypeSystem.Compilation), context.DecompiledTypeDefinition); + var currentContext = new CSharpTypeResolveContext(context.TypeSystem.MainModule, usingScope.Resolve(context.TypeSystem), context.DecompiledTypeDefinition); this.resolveContextStack.Push(currentContext); this.resolver = new CSharpResolver(currentContext); } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs index 2ebb89fa2..da121ea17 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs @@ -130,7 +130,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms usingScope = new UsingScope(usingScope, ns); } } - var currentContext = new CSharpTypeResolveContext(context.TypeSystem.MainModule, usingScope.Resolve(context.TypeSystem.Compilation), context.DecompiledTypeDefinition); + var currentContext = new CSharpTypeResolveContext(context.TypeSystem.MainModule, usingScope.Resolve(context.TypeSystem), context.DecompiledTypeDefinition); this.context.Push(currentContext); this.astBuilder = CreateAstBuilder(currentContext); } diff --git a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs index e2981f22a..f20552316 100644 --- a/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs +++ b/ICSharpCode.Decompiler/DebugInfo/PortablePdbWriter.cs @@ -75,7 +75,7 @@ namespace ICSharpCode.Decompiler.DebugInfo sequencePointBlobs.Add(method, (default, default)); else sequencePointBlobs.Add(method, (document, EncodeSequencePoints(metadata, localSignatureRowId, points))); - importScopeBlobs.Add(method, (document, EncodeImportScope(metadata, reader, ast, decompiler.TypeSystem.Compilation))); + importScopeBlobs.Add(method, (document, EncodeImportScope(metadata, reader, ast, decompiler.TypeSystem))); } foreach (var nestedTypeHandle in type.GetNestedTypes()) { diff --git a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs index 9673df3a6..3fa4db4a5 100644 --- a/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs +++ b/ICSharpCode.Decompiler/IL/ControlFlow/AsyncAwaitDecompiler.cs @@ -197,12 +197,12 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow return false; } else if (taskType.IsKnownType(KnownTypeCode.Task)) { methodType = AsyncMethodType.Task; - underlyingReturnType = context.TypeSystem.Compilation.FindType(KnownTypeCode.Void); + underlyingReturnType = context.TypeSystem.FindType(KnownTypeCode.Void); if (builderType?.FullTypeName != new TopLevelTypeName(ns, "AsyncTaskMethodBuilder", 0)) return false; } else if (taskType.IsKnownType(KnownTypeCode.TaskOfT)) { methodType = AsyncMethodType.TaskOfT; - underlyingReturnType = TaskType.UnpackTask(context.TypeSystem.Compilation, taskType); + underlyingReturnType = TaskType.UnpackTask(context.TypeSystem, taskType); if (builderType?.FullTypeName != new TopLevelTypeName(ns, "AsyncTaskMethodBuilder", 1)) return false; } else { diff --git a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs index ae9523251..9b17c41eb 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/CopyPropagation.cs @@ -109,7 +109,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms ILVariable[] uninlinedArgs = new ILVariable[copiedExpr.Children.Count]; for (int j = 0; j < uninlinedArgs.Length; j++) { var arg = copiedExpr.Children[j]; - var type = context.TypeSystem.Compilation.FindType(arg.ResultType.ToKnownTypeCode()); + var type = context.TypeSystem.FindType(arg.ResultType.ToKnownTypeCode()); uninlinedArgs[j] = new ILVariable(VariableKind.StackSlot, type, arg.ResultType, arg.ILRange.Start) { Name = "C_" + arg.ILRange.Start }; diff --git a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs index 5c5e6a9da..8025aa8fd 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs @@ -50,7 +50,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms public Metadata.PEFile PEFile => TypeSystem.MainModule.PEFile; internal DecompileRun DecompileRun { get; set; } - internal ResolvedUsingScope UsingScope => DecompileRun.UsingScope.Resolve(TypeSystem.Compilation); + internal ResolvedUsingScope UsingScope => DecompileRun.UsingScope.Resolve(TypeSystem); public ILTransformContext(ILFunction function, IDecompilerTypeSystem typeSystem, IDebugInfoProvider debugInfo, DecompilerSettings settings = null) { diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs index 94a416901..e2b707086 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs @@ -260,7 +260,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { return CSharp.Transforms.IntroduceExtensionMethods.CanTransformToExtensionMethodCall( call.Method, new CSharp.TypeSystem.CSharpTypeResolveContext( - context.TypeSystem.Compilation.MainModule, context.UsingScope + context.TypeSystem.MainModule, context.UsingScope ) ); } diff --git a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs index 526bc4441..92ddf4dad 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/NullableLiftingTransform.cs @@ -542,7 +542,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms bool isNullCoalescingWithNonNullableFallback = false; if (!MatchNullableCtor(trueInst, out var utype, out var exprToLift)) { isNullCoalescingWithNonNullableFallback = true; - utype = context.TypeSystem.Compilation.FindType(trueInst.ResultType.ToKnownTypeCode()); + utype = context.TypeSystem.FindType(trueInst.ResultType.ToKnownTypeCode()); exprToLift = trueInst; if (nullableVars.Count == 1 && exprToLift.MatchLdLoc(nullableVars[0])) { // v.HasValue ? ldloc v : fallback @@ -779,7 +779,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (underlyingType == SpecialType.UnknownType) return inst; - var nullable = context.TypeSystem.Compilation.FindType(KnownTypeCode.NullableOfT).GetDefinition(); + var nullable = context.TypeSystem.FindType(KnownTypeCode.NullableOfT).GetDefinition(); var ctor = nullable?.Methods.FirstOrDefault(m => m.IsConstructor && m.Parameters.Count == 1); if (ctor != null) { ctor = ctor.Specialize(new TypeParameterSubstitution(new[] { underlyingType }, null)); diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs index 871f415fc..6fc0f22da 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformCollectionAndObjectInitializers.cs @@ -178,7 +178,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms possibleIndexVariables.Add(stloc.Variable, (stloc.ChildIndex, stloc.Value)); return true; } - var resolveContext = new CSharpTypeResolveContext(context.TypeSystem.Compilation.MainModule, context.UsingScope); + var resolveContext = new CSharpTypeResolveContext(context.TypeSystem.MainModule, context.UsingScope); (var kind, var newPath, var values, var targetVariable) = AccessPathElement.GetAccessPath(instructions[pos], rootType, context.Settings, resolveContext, possibleIndexVariables); if (kind == AccessPathKind.Invalid || target != targetVariable) return false; diff --git a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs index dc712685a..dba75bd17 100644 --- a/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs +++ b/ICSharpCode.Decompiler/IL/Transforms/TransformExpressionTrees.cs @@ -98,8 +98,8 @@ namespace ICSharpCode.Decompiler.IL.Transforms { if (!context.Settings.ExpressionTrees) return; this.context = context; - this.conversions = CSharpConversions.Get(context.TypeSystem.Compilation); - this.resolver = new CSharpResolver(context.TypeSystem.Compilation); + this.conversions = CSharpConversions.Get(context.TypeSystem); + this.resolver = new CSharpResolver(context.TypeSystem); this.parameters = new Dictionary(); this.parameterMapping = new Dictionary(); this.instructionsToRemove = new List(); @@ -377,7 +377,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms var (converted, arrayType) = ConvertInstruction(invocation.Arguments[0]); if (converted == null) return (null, SpecialType.UnknownType); - return (new LdLen(StackType.I4, converted), context.TypeSystem.Compilation.FindType(KnownTypeCode.Int32)); + return (new LdLen(StackType.I4, converted), context.TypeSystem.FindType(KnownTypeCode.Int32)); } (ILInstruction, IType) ConvertBinaryNumericOperator(CallInstruction invocation, BinaryNumericOperator op, bool? isChecked = null) @@ -589,7 +589,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms } return (new Call(operatorMethod) { Arguments = { left, right } }, operatorMethod.ReturnType); } - var resultType = context.TypeSystem.Compilation.FindType(KnownTypeCode.Boolean); + var resultType = context.TypeSystem.FindType(KnownTypeCode.Boolean); return (new Comp(kind, NullableType.IsNullable(leftType) ? ComparisonLiftingKind.CSharp : ComparisonLiftingKind.None, leftType.GetStackType(), leftType.GetSign(), left, right), resultType); } @@ -739,7 +739,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms IMember method; switch (invocation.Arguments.Count) { case 2: - var resultType = context.TypeSystem.Compilation.FindType(KnownTypeCode.Boolean); + var resultType = context.TypeSystem.FindType(KnownTypeCode.Boolean); return (and ? IfInstruction.LogicAnd(left, right) : IfInstruction.LogicOr(left, right), resultType); case 3: if (!MatchGetMethodFromHandle(invocation.Arguments[2], out method)) @@ -810,7 +810,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms return (null, SpecialType.UnknownType); indices[i] = index; } - return (new NewArr(type, indices), new ArrayType(context.TypeSystem.Compilation, type, arguments.Count)); + return (new NewArr(type, indices), new ArrayType(context.TypeSystem, type, arguments.Count)); } (ILInstruction, IType) ConvertNewArrayInit(CallInstruction invocation) @@ -821,7 +821,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms return (null, SpecialType.UnknownType); if (!MatchArgumentList(invocation.Arguments[1], out var arguments)) return (null, SpecialType.UnknownType); - ArrayType arrayType = new ArrayType(context.BlockContext.TypeSystem.Compilation, type); + ArrayType arrayType = new ArrayType(context.BlockContext.TypeSystem, type); if (arguments.Count == 0) return (new NewArr(type, new LdcI4(0)), arrayType); var block = (Block)invocation.Arguments[1]; @@ -959,7 +959,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms var converted = ConvertInstruction(invocation.Arguments[0]).Item1; if (!MatchGetTypeFromHandle(invocation.Arguments[1], out var type)) return (null, SpecialType.UnknownType); - var resultType = context.TypeSystem.Compilation.FindType(KnownTypeCode.Boolean); + var resultType = context.TypeSystem.FindType(KnownTypeCode.Boolean); if (converted != null) return (new Comp(ComparisonKind.Inequality, Sign.None, new IsInst(converted, type), new LdNull()), resultType); return (null, SpecialType.UnknownType); @@ -1061,7 +1061,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms //castclass System.Reflection.MethodInfo(call GetMethodFromHandle(ldmembertoken op_Addition)) if (!inst.MatchCastClass(out var arg, out var type)) return false; - if (!type.Equals(context.TypeSystem.Compilation.FindType(new FullTypeName("System.Reflection.MethodInfo")))) + if (!type.Equals(context.TypeSystem.FindType(new FullTypeName("System.Reflection.MethodInfo")))) return false; if (!(arg is CallInstruction call && call.Method.FullName == "System.Reflection.MethodBase.GetMethodFromHandle")) return false; @@ -1086,7 +1086,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms //castclass System.Reflection.ConstructorInfo(call GetMethodFromHandle(ldmembertoken op_Addition)) if (!inst.MatchCastClass(out var arg, out var type)) return false; - if (!type.Equals(context.TypeSystem.Compilation.FindType(new FullTypeName("System.Reflection.ConstructorInfo")))) + if (!type.Equals(context.TypeSystem.FindType(new FullTypeName("System.Reflection.ConstructorInfo")))) return false; if (!(arg is CallInstruction call && call.Method.FullName == "System.Reflection.MethodBase.GetMethodFromHandle")) return false; diff --git a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs index 6f69b0ed1..16a095ae6 100644 --- a/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/DecompilerTypeSystem.cs @@ -74,51 +74,54 @@ namespace ICSharpCode.Decompiler.TypeSystem /// /// This class is thread-safe. /// - public class DecompilerTypeSystem : IDecompilerTypeSystem + public class DecompilerTypeSystem : SimpleCompilation, IDecompilerTypeSystem { - readonly Metadata.PEFile moduleDefinition; - readonly ICompilation compilation; - readonly IAssemblyResolver assemblyResolver; - readonly TypeSystemOptions typeSystemOptions; - readonly MetadataModule mainModule; - - public DecompilerTypeSystem(Metadata.PEFile moduleDefinition, IAssemblyResolver assemblyResolver) - : this(moduleDefinition, assemblyResolver, new DecompilerSettings()) + public DecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver) + : this(mainModule, assemblyResolver, TypeSystemOptions.Default) { } - public DecompilerTypeSystem(PEFile moduleDefinition, IAssemblyResolver assemblyResolver, DecompilerSettings settings) + static TypeSystemOptions GetOptions(DecompilerSettings settings) { - if (settings == null) - throw new ArgumentNullException(nameof(settings)); - this.moduleDefinition = moduleDefinition ?? throw new ArgumentNullException(nameof(moduleDefinition)); - this.assemblyResolver = assemblyResolver ?? throw new ArgumentNullException(nameof(assemblyResolver)); - typeSystemOptions = TypeSystemOptions.None; + var typeSystemOptions = TypeSystemOptions.None; if (settings.Dynamic) typeSystemOptions |= TypeSystemOptions.Dynamic; if (settings.TupleTypes) typeSystemOptions |= TypeSystemOptions.Tuple; if (settings.ExtensionMethods) typeSystemOptions |= TypeSystemOptions.ExtensionMethods; - var mainAssembly = moduleDefinition.WithOptions(typeSystemOptions); + return typeSystemOptions; + } + + public DecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver, DecompilerSettings settings) + : this(mainModule, assemblyResolver, GetOptions(settings ?? throw new ArgumentNullException(nameof(settings)))) + { + } + + public DecompilerTypeSystem(PEFile mainModule, IAssemblyResolver assemblyResolver, TypeSystemOptions typeSystemOptions) + { + if (mainModule == null) + throw new ArgumentNullException(nameof(mainModule)); + if (assemblyResolver == null) + throw new ArgumentNullException(nameof(assemblyResolver)); // Load referenced assemblies and type-forwarder references. // This is necessary to make .NET Core/PCL binaries work better. - var referencedAssemblies = new List(); + var referencedAssemblies = new List(); var assemblyReferenceQueue = new Queue<(bool IsAssembly, PEFile MainModule, object Reference)>(); - var mainMetadata = moduleDefinition.Metadata; + var mainMetadata = mainModule.Metadata; foreach (var h in mainMetadata.GetModuleReferences()) { var moduleRef = mainMetadata.GetModuleReference(h); var moduleName = mainMetadata.GetString(moduleRef.Name); foreach (var fileHandle in mainMetadata.AssemblyFiles) { var file = mainMetadata.GetAssemblyFile(fileHandle); if (mainMetadata.StringComparer.Equals(file.Name, moduleName) && file.ContainsMetadata) { - assemblyReferenceQueue.Enqueue((false, moduleDefinition, moduleName)); + assemblyReferenceQueue.Enqueue((false, mainModule, moduleName)); break; } } } - foreach (var refs in moduleDefinition.AssemblyReferences) { - assemblyReferenceQueue.Enqueue((true, moduleDefinition, refs)); + foreach (var refs in mainModule.AssemblyReferences) { + assemblyReferenceQueue.Enqueue((true, mainModule, refs)); } var comparer = KeyComparer.Create(((bool IsAssembly, PEFile MainModule, object Reference) reference) => reference.IsAssembly ? "A:" + ((AssemblyReference)reference.Reference).FullName : @@ -135,7 +138,7 @@ namespace ICSharpCode.Decompiler.TypeSystem asm = assemblyResolver.ResolveModule(asmRef.MainModule, (string)asmRef.Reference); } if (asm != null) { - referencedAssemblies.Add(asm.WithOptions(typeSystemOptions)); + referencedAssemblies.Add(asm); var metadata = asm.Metadata; foreach (var h in metadata.ExportedTypes) { var exportedType = metadata.GetExportedType(h); @@ -151,27 +154,30 @@ namespace ICSharpCode.Decompiler.TypeSystem } } } - compilation = new SimpleCompilation(mainAssembly, referencedAssemblies); + 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 (compilation.FindType(KnownTypeCode.Void).Kind == TypeKind.Unknown || compilation.FindType(KnownTypeCode.Int32).Kind == TypeKind.Unknown) { - referencedAssemblies.Add(MinimalCorlib.Instance); - compilation = new SimpleCompilation(mainAssembly, referencedAssemblies); + if (!HasType(KnownTypeCode.Void) || !HasType(KnownTypeCode.Int32)) { + Init(mainModule.WithOptions(typeSystemOptions), referencedAssembliesWithOptions.Concat(new[] { MinimalCorlib.Instance })); + } else { + Init(mainModuleWithOptions, referencedAssembliesWithOptions); } - this.mainModule = (MetadataModule)compilation.MainModule; - } + this.MainModule = (MetadataModule)base.MainModule; - public ICompilation Compilation { - get { return compilation; } + bool HasType(KnownTypeCode code) + { + TopLevelTypeName name = KnownTypeReference.Get(code).TypeName; + if (mainModule.GetTypeDefinition(name) != null) + return true; + foreach (var file in referencedAssemblies) { + if (file.GetTypeDefinition(name) != null) + return true; + } + return false; + } } - public MetadataModule MainModule { - get { return mainModule; } - } - - public Metadata.PEFile ModuleDefinition { - get { return moduleDefinition; } - } - + public new MetadataModule MainModule { get; } } } diff --git a/ICSharpCode.Decompiler/TypeSystem/ICompilation.cs b/ICSharpCode.Decompiler/TypeSystem/ICompilation.cs index ebae2b04f..1fd554d5d 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ICompilation.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ICompilation.cs @@ -31,24 +31,19 @@ namespace ICSharpCode.Decompiler.TypeSystem /// IModule MainModule { get; } - /// - /// Gets the type resolve context that specifies this compilation and no current assembly or entity. - /// - ITypeResolveContext TypeResolveContext { get; } - /// /// Gets the list of all modules in the compilation. /// /// /// This main module is the first entry in the list. /// - IList Modules { get; } - + IReadOnlyList Modules { get; } + /// /// Gets the referenced modules. /// This list does not include the main module. /// - IList ReferencedModules { get; } + IReadOnlyList ReferencedModules { get; } /// /// Gets the root namespace of this compilation. diff --git a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs index df510516e..51c1f7241 100644 --- a/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/TypeSystem/IDecompilerTypeSystem.cs @@ -23,11 +23,12 @@ using ICSharpCode.Decompiler.Metadata; namespace ICSharpCode.Decompiler.TypeSystem { /// - /// Allows resolving cecil types into the NRefactory type system. + /// Main interface for the decompiler type system. + /// + /// The MetadataModule class allows decoding/resolving metadata tokens into type system entities. /// - public interface IDecompilerTypeSystem + public interface IDecompilerTypeSystem : ICompilation { - ICompilation Compilation { get; } - MetadataModule MainModule { get; } + new MetadataModule MainModule { get; } } } diff --git a/ICSharpCode.Decompiler/TypeSystem/Implementation/SimpleCompilation.cs b/ICSharpCode.Decompiler/TypeSystem/Implementation/SimpleCompilation.cs index 365a2675f..eca2b96ed 100644 --- a/ICSharpCode.Decompiler/TypeSystem/Implementation/SimpleCompilation.cs +++ b/ICSharpCode.Decompiler/TypeSystem/Implementation/SimpleCompilation.cs @@ -27,26 +27,35 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation /// public class SimpleCompilation : ICompilation { - readonly ITypeResolveContext context; readonly CacheManager cacheManager = new CacheManager(); - readonly KnownTypeCache knownTypeCache; - readonly IModule mainModule; - readonly IList assemblies; - readonly IList referencedAssemblies; + IModule mainModule; + KnownTypeCache knownTypeCache; + IReadOnlyList assemblies; + IReadOnlyList referencedAssemblies; + bool initialized; INamespace rootNamespace; public SimpleCompilation(IModuleReference mainAssembly, params IModuleReference[] assemblyReferences) - : this(mainAssembly, (IEnumerable)assemblyReferences) { + Init(mainAssembly, assemblyReferences); } - + public SimpleCompilation(IModuleReference mainAssembly, IEnumerable assemblyReferences) + { + Init(mainAssembly, assemblyReferences); + } + + protected SimpleCompilation() + { + } + + protected void Init(IModuleReference mainAssembly, IEnumerable assemblyReferences) { if (mainAssembly == null) throw new ArgumentNullException("mainAssembly"); if (assemblyReferences == null) throw new ArgumentNullException("assemblyReferences"); - this.context = new SimpleTypeResolveContext(this); + var context = new SimpleTypeResolveContext(this); this.mainModule = mainAssembly.Resolve(context); List assemblies = new List(); assemblies.Add(this.mainModule); @@ -66,43 +75,40 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation this.assemblies = assemblies.AsReadOnly(); this.referencedAssemblies = referencedAssemblies.AsReadOnly(); this.knownTypeCache = new KnownTypeCache(this); + this.initialized = true; } - + public IModule MainModule { get { - if (mainModule == null) + if (!initialized) throw new InvalidOperationException("Compilation isn't initialized yet"); return mainModule; } } - public IList Modules { + public IReadOnlyList Modules { get { - if (assemblies == null) + if (!initialized) throw new InvalidOperationException("Compilation isn't initialized yet"); return assemblies; } } - public IList ReferencedModules { + public IReadOnlyList ReferencedModules { get { - if (referencedAssemblies == null) + if (!initialized) throw new InvalidOperationException("Compilation isn't initialized yet"); return referencedAssemblies; } } - public ITypeResolveContext TypeResolveContext { - get { return context; } - } - public INamespace RootNamespace { get { INamespace ns = LazyInit.VolatileRead(ref this.rootNamespace); if (ns != null) { return ns; } else { - if (referencedAssemblies == null) + if (!initialized) throw new InvalidOperationException("Compilation isn't initialized yet"); return LazyInit.GetOrSet(ref this.rootNamespace, CreateRootNamespace()); } @@ -144,7 +150,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation public override string ToString() { - return "[SimpleCompilation " + mainModule.AssemblyName + "]"; + return "[" + GetType().Name + " " + mainModule.AssemblyName + "]"; } } } diff --git a/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs b/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs index 16dbaa154..1a46c177a 100644 --- a/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs +++ b/ICSharpCode.Decompiler/TypeSystem/ReflectionHelper.cs @@ -53,7 +53,7 @@ namespace ICSharpCode.Decompiler.TypeSystem /// public static IType FindType(this ICompilation compilation, Type type) { - return type.ToTypeReference().Resolve(compilation.TypeResolveContext); + return type.ToTypeReference().Resolve(new SimpleTypeResolveContext(compilation)); } #endregion diff --git a/ILSpy.BamlDecompiler/CecilTypeResolver.cs b/ILSpy.BamlDecompiler/CecilTypeResolver.cs index 19b04a3ab..6622bc12d 100644 --- a/ILSpy.BamlDecompiler/CecilTypeResolver.cs +++ b/ILSpy.BamlDecompiler/CecilTypeResolver.cs @@ -16,18 +16,16 @@ namespace ILSpy.BamlDecompiler { readonly PEFile module; readonly DecompilerTypeSystem typeSystem; - readonly ICompilation compilation; public NRTypeResolver(PEFile module, IAssemblyResolver resolver) { this.module = module ?? throw new ArgumentNullException(nameof(module)); this.typeSystem = new DecompilerTypeSystem(module, resolver); - this.compilation = typeSystem.Compilation; } public bool IsLocalAssembly(string name) { - return MakeShort(name) == compilation.MainModule.AssemblyName; + return MakeShort(name) == typeSystem.MainModule.AssemblyName; } string MakeShort(string name) @@ -50,7 +48,7 @@ namespace ILSpy.BamlDecompiler string fullName = bracket > -1 ? name.Substring(0, name.IndexOf('[')) : name.Substring(0, comma); string assemblyName = name.Substring(comma + 1).Trim(); - var type = compilation.FindType(new FullTypeName(fullName)).GetDefinition(); + var type = typeSystem.FindType(new FullTypeName(fullName)).GetDefinition(); if (type == null) return new UnresolvableType(name); diff --git a/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs b/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs index 8377bfb88..5bca43bee 100644 --- a/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs +++ b/ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs @@ -37,7 +37,7 @@ namespace ILSpy.BamlDecompiler var result = new List<(LongSet, EventRegistration[])>(); var typeSystem = new DecompilerTypeSystem(module, assemblyResolver); - var typeDefinition = typeSystem.Compilation.FindType(new FullTypeName(fullTypeName)).GetDefinition(); + var typeDefinition = typeSystem.FindType(new FullTypeName(fullTypeName)).GetDefinition(); if (typeDefinition == null) return result;