From 08a5e815177404487e22481fb4961bb68f698964 Mon Sep 17 00:00:00 2001 From: Daniel Grunwald Date: Sun, 16 Nov 2014 15:41:35 +0100 Subject: [PATCH] Re-enable IntroduceUsingDeclarations --- .../CSharp/CSharpDecompiler.cs | 82 +++++++++++-------- .../CSharp/ExpressionBuilder.cs | 13 +-- .../CSharp/StatementBuilder.cs | 8 +- .../CSharp/Transforms/AddCheckedBlocks.cs | 4 +- .../ConvertConstructorCallIntoInitializer.cs | 47 ++++++----- .../CSharp/Transforms/IAstTransform.cs | 2 +- .../Transforms/IntroduceUnsafeModifier.cs | 2 +- .../Transforms/IntroduceUsingDeclarations.cs | 69 +++++++--------- .../ReplaceMethodCallsWithOperators.cs | 2 +- .../CSharp/Transforms/TransformContext.cs | 53 ++++++++++++ .../CSharp/TranslatedExpression.cs | 2 +- .../DecompilerTypeSystem.cs | 30 +++---- .../ICSharpCode.Decompiler.csproj | 2 + ICSharpCode.Decompiler/IL/BlockBuilder.cs | 2 +- ICSharpCode.Decompiler/IL/ILReader.cs | 10 +-- .../OutputVisitor/CSharpAmbience.cs | 2 +- .../Refactoring/TypeSystemAstBuilder.cs | 34 ++++++-- 17 files changed, 227 insertions(+), 137 deletions(-) create mode 100644 ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs index a30a75ecd..212ad6392 100644 --- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs +++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using System.Text; using System.Threading; @@ -36,8 +37,22 @@ namespace ICSharpCode.Decompiler.CSharp public class CSharpDecompiler { readonly DecompilerTypeSystem typeSystem; - TypeSystemAstBuilder typeSystemAstBuilder; - List astTransforms; + List astTransforms = new List { + //new PushNegation(), + //new DelegateConstruction(context), + //new PatternStatementTransform(context), + new ReplaceMethodCallsWithOperators(), + new IntroduceUnsafeModifier(), + new AddCheckedBlocks(), + //new DeclareVariables(context), // should run after most transforms that modify statements + new ConvertConstructorCallIntoInitializer(), // must run after DeclareVariables + //new DecimalConstantTransform(), + new IntroduceUsingDeclarations(), + //new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations + //new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods + //new CombineQueryExpressions(context), + //new FlattenSwitchBlocks(), + }; public CancellationToken CancellationToken { get; set; } @@ -58,38 +73,27 @@ namespace ICSharpCode.Decompiler.CSharp if (typeSystem == null) throw new ArgumentNullException("typeSystem"); this.typeSystem = typeSystem; - - astTransforms = new List { - //new PushNegation(), - //new DelegateConstruction(context), - //new PatternStatementTransform(context), - new ReplaceMethodCallsWithOperators(), - new IntroduceUnsafeModifier(), - new AddCheckedBlocks(), - //new DeclareVariables(context), // should run after most transforms that modify statements - new ConvertConstructorCallIntoInitializer(typeSystem), // must run after DeclareVariables - //new DecimalConstantTransform(), - //new IntroduceUsingDeclarations(context), - //new IntroduceExtensionMethods(context), // must run after IntroduceUsingDeclarations - //new IntroduceQueryExpressions(context), // must run after IntroduceExtensionMethods - //new CombineQueryExpressions(context), - //new FlattenSwitchBlocks(), - }; - - typeSystemAstBuilder = new TypeSystemAstBuilder(); + } + + TypeSystemAstBuilder CreateAstBuilder(ITypeResolveContext decompilationContext) + { + var typeSystemAstBuilder = new TypeSystemAstBuilder(); typeSystemAstBuilder.AlwaysUseShortTypeNames = true; - typeSystemAstBuilder.AddAnnotations = true; + typeSystemAstBuilder.AddResolveResultAnnotations = true; + return typeSystemAstBuilder; } - void RunTransforms(AstNode rootNode) + void RunTransforms(AstNode rootNode, ITypeResolveContext decompilationContext) { + var context = new TransformContext(typeSystem, decompilationContext); foreach (var transform in astTransforms) - transform.Run(rootNode); + transform.Run(rootNode, context); rootNode.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true }); } public SyntaxTree DecompileWholeModuleAsSingleFile() { + var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly); SyntaxTree syntaxTree = new SyntaxTree(); foreach (var g in typeSystem.Compilation.MainAssembly.TopLevelTypeDefinitions.GroupBy(t => t.Namespace)) { AstNode groupNode; @@ -104,11 +108,11 @@ namespace ICSharpCode.Decompiler.CSharp foreach (var typeDef in g) { if (typeDef.Name == "" && typeDef.Members.Count == 0) continue; - var typeDecl = DoDecompile(typeDef); + var typeDecl = DoDecompile(typeDef, decompilationContext.WithCurrentTypeDefinition(typeDef)); groupNode.AddChild(typeDecl, SyntaxTree.MemberRole); } } - RunTransforms(syntaxTree); + RunTransforms(syntaxTree, decompilationContext); return syntaxTree; } @@ -116,16 +120,19 @@ namespace ICSharpCode.Decompiler.CSharp { if (typeDefinition == null) throw new ArgumentNullException("typeDefinition"); - ITypeDefinition typeDef = typeSystem.GetType(typeDefinition).GetDefinition(); + ITypeDefinition typeDef = typeSystem.Resolve(typeDefinition).GetDefinition(); if (typeDef == null) throw new InvalidOperationException("Could not find type definition in NR type system"); - var decl = DoDecompile(typeDef); - RunTransforms(decl); + var decompilationContext = new SimpleTypeResolveContext(typeDef); + var decl = DoDecompile(typeDef, decompilationContext); + RunTransforms(decl, decompilationContext); return decl; } - EntityDeclaration DoDecompile(ITypeDefinition typeDef) + EntityDeclaration DoDecompile(ITypeDefinition typeDef, ITypeResolveContext decompilationContext) { + Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef); + var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var entityDecl = typeSystemAstBuilder.ConvertEntity(typeDef); var typeDecl = entityDecl as TypeDeclaration; if (typeDecl == null) { @@ -135,7 +142,7 @@ namespace ICSharpCode.Decompiler.CSharp foreach (var method in typeDef.Methods) { var methodDef = typeSystem.GetCecil(method) as MethodDefinition; if (methodDef != null) { - var memberDecl = DoDecompile(methodDef, method); + var memberDecl = DoDecompile(methodDef, method, decompilationContext.WithCurrentMember(method)); typeDecl.Members.Add(memberDecl); } } @@ -146,16 +153,19 @@ namespace ICSharpCode.Decompiler.CSharp { if (methodDefinition == null) throw new ArgumentNullException("methodDefinition"); - var method = typeSystem.GetMethod(methodDefinition); + var method = typeSystem.Resolve(methodDefinition); if (method == null) throw new InvalidOperationException("Could not find method in NR type system"); - var decl = DoDecompile(methodDefinition, method); - RunTransforms(decl); + var decompilationContext = new SimpleTypeResolveContext(method); + var decl = DoDecompile(methodDefinition, method, decompilationContext); + RunTransforms(decl, decompilationContext); return decl; } - EntityDeclaration DoDecompile(MethodDefinition methodDefinition, IMethod method) + EntityDeclaration DoDecompile(MethodDefinition methodDefinition, IMethod method, ITypeResolveContext decompilationContext) { + Debug.Assert(decompilationContext.CurrentMember == method); + var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var entityDecl = typeSystemAstBuilder.ConvertEntity(method); if (methodDefinition.HasBody) { var ilReader = new ILReader(typeSystem); @@ -163,7 +173,7 @@ namespace ICSharpCode.Decompiler.CSharp function.CheckInvariant(); function.Body = function.Body.AcceptVisitor(new TransformingVisitor()); function.CheckInvariant(); - var statementBuilder = new StatementBuilder(method); + var statementBuilder = new StatementBuilder(decompilationContext); var body = statementBuilder.ConvertAsBlock(function.Body); // insert variables at start of body diff --git a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs index 435a6ddb5..7a0b43c6a 100644 --- a/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs @@ -17,6 +17,7 @@ // DEALINGS IN THE SOFTWARE. using System.Diagnostics; +using ICSharpCode.NRefactory.CSharp.TypeSystem; using ExpressionType = System.Linq.Expressions.ExpressionType; using ICSharpCode.NRefactory.CSharp.Refactoring; using ICSharpCode.NRefactory.CSharp.Resolver; @@ -41,12 +42,14 @@ namespace ICSharpCode.Decompiler.CSharp internal readonly CSharpResolver resolver; internal readonly TypeSystemAstBuilder astBuilder; - public ExpressionBuilder(ICompilation compilation) + public ExpressionBuilder(ITypeResolveContext decompilationContext) { - Debug.Assert(compilation != null); - this.compilation = compilation; - this.resolver = new CSharpResolver(compilation); + Debug.Assert(decompilationContext != null); + this.compilation = decompilationContext.Compilation; + this.resolver = new CSharpResolver(new CSharpTypeResolveContext(compilation.MainAssembly, null, decompilationContext.CurrentTypeDefinition, decompilationContext.CurrentMember)); this.astBuilder = new TypeSystemAstBuilder(resolver); + this.astBuilder.AlwaysUseShortTypeNames = true; + this.astBuilder.AddResolveResultAnnotations = true; } public AstType ConvertType(IType type) @@ -145,7 +148,7 @@ namespace ICSharpCode.Decompiler.CSharp { return new NullReferenceExpression() .WithILInstruction(inst) - .WithRR(new ConstantResolveResult(SpecialType.UnknownType, null)); + .WithRR(new ConstantResolveResult(SpecialType.NullType, null)); } protected internal override TranslatedExpression VisitLogicNot(LogicNot inst) diff --git a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs index 6003da946..03f9a918e 100644 --- a/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs +++ b/ICSharpCode.Decompiler/CSharp/StatementBuilder.cs @@ -16,6 +16,7 @@ // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER // DEALINGS IN THE SOFTWARE. +using System.Diagnostics; using ICSharpCode.Decompiler.IL; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.TypeSystem; @@ -32,10 +33,11 @@ namespace ICSharpCode.Decompiler.CSharp readonly ExpressionBuilder exprBuilder; readonly IMethod currentMethod; - public StatementBuilder(IMethod method) + public StatementBuilder(ITypeResolveContext decompilationContext) { - this.exprBuilder = new ExpressionBuilder(method.Compilation); - this.currentMethod = method; + Debug.Assert(decompilationContext != null && decompilationContext.CurrentMember is IMethod); + this.exprBuilder = new ExpressionBuilder(decompilationContext); + this.currentMethod = (IMethod)decompilationContext.CurrentMember; } public Statement Convert(ILInstruction inst) diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs b/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs index 51b0db29d..edd7fdf94 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/AddCheckedBlocks.cs @@ -234,12 +234,12 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } #endregion - public void Run(AstNode node) + public void Run(AstNode node, TransformContext context) { BlockStatement block = node as BlockStatement; if (block == null) { for (AstNode child = node.FirstChild; child != null; child = child.NextSibling) { - Run(child); + Run(child, context); } } else { Result r = GetResultFromBlock(block); diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs b/ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs index a1067de70..a87c2b86a 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs @@ -18,6 +18,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using ICSharpCode.NRefactory.CSharp; using ICSharpCode.NRefactory.PatternMatching; @@ -30,17 +31,31 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms /// /// If the first element of a constructor is a chained constructor call, convert it into a constructor initializer. /// - public class ConvertConstructorCallIntoInitializer : DepthFirstAstVisitor, IAstTransform + public class ConvertConstructorCallIntoInitializer : IAstTransform { - readonly DecompilerTypeSystem typeSystem; - - public ConvertConstructorCallIntoInitializer(DecompilerTypeSystem typeSystem) + public void Run(AstNode node, TransformContext context) { - if (typeSystem == null) - throw new ArgumentNullException("typeSystem"); - this.typeSystem = typeSystem; + var visitor = new ConvertConstructorCallIntoInitializerVisitor(context); + + // If we're viewing some set of members (fields are direct children of SyntaxTree), + // we also need to handle those: + visitor.HandleInstanceFieldInitializers(node.Children); + visitor.HandleStaticFieldInitializers(node.Children); + + node.AcceptVisitor(visitor); } - + } + + sealed class ConvertConstructorCallIntoInitializerVisitor : DepthFirstAstVisitor + { + readonly TransformContext context; + + public ConvertConstructorCallIntoInitializerVisitor(TransformContext context) + { + Debug.Assert(context != null); + this.context = context; + } + public override void VisitConstructorDeclaration(ConstructorDeclaration constructorDeclaration) { ExpressionStatement stmt = constructorDeclaration.Body.Statements.FirstOrDefault() as ExpressionStatement; @@ -96,7 +111,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms HandleStaticFieldInitializers(typeDeclaration.Members); } - void HandleInstanceFieldInitializers(IEnumerable members) + internal void HandleInstanceFieldInitializers(IEnumerable members) { var instanceCtors = members.OfType().Where(c => (c.Modifiers & Modifiers.Static) == 0).ToArray(); var instanceCtorsNotChainingWithThis = instanceCtors.Where(ctor => !thisCallPattern.IsMatch(ctor.Body.Statements.FirstOrDefault())).ToArray(); @@ -150,13 +165,13 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } - void HandleStaticFieldInitializers(IEnumerable members) + internal void HandleStaticFieldInitializers(IEnumerable members) { // Translate static constructor into field initializers if the class is BeforeFieldInit var staticCtor = members.OfType().FirstOrDefault(c => (c.Modifiers & Modifiers.Static) == Modifiers.Static); if (staticCtor != null) { IMethod ctorMethod = staticCtor.GetSymbol() as IMethod; - MethodDefinition ctorMethodDef = typeSystem.GetCecil(ctorMethod) as MethodDefinition; + MethodDefinition ctorMethodDef = context.TypeSystem.GetCecil(ctorMethod) as MethodDefinition; if (ctorMethodDef != null && ctorMethodDef.DeclaringType.IsBeforeFieldInit) { while (true) { ExpressionStatement es = staticCtor.Body.Statements.FirstOrDefault() as ExpressionStatement; @@ -179,15 +194,5 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } } - - public void Run(AstNode node) - { - // If we're viewing some set of members (fields are direct children of CompilationUnit), - // we also need to handle those: - HandleInstanceFieldInitializers(node.Children); - HandleStaticFieldInitializers(node.Children); - - node.AcceptVisitor(this); - } } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IAstTransform.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IAstTransform.cs index 426251cb2..4e106ed88 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IAstTransform.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IAstTransform.cs @@ -25,6 +25,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms { public interface IAstTransform { - void Run(AstNode rootNode); + void Run(AstNode rootNode, TransformContext context); } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs index 37f817e5c..2fc818d93 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUnsafeModifier.cs @@ -27,7 +27,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms sealed class PointerArithmetic {} - public void Run(AstNode compilationUnit) + public void Run(AstNode compilationUnit, TransformContext context) { compilationUnit.AcceptVisitor(this); } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs index a8936086d..702c9c19b 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs @@ -20,7 +20,7 @@ using System; using System.Collections.Generic; using System.Linq; using ICSharpCode.NRefactory.CSharp; -using Mono.Cecil; +using ICSharpCode.NRefactory.Semantics; namespace ICSharpCode.Decompiler.CSharp.Transforms { @@ -29,25 +29,18 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms /// public class IntroduceUsingDeclarations : IAstTransform { - DecompilerContext context; + public bool FullyQualifyAmbiguousTypeNames = true; - public IntroduceUsingDeclarations(DecompilerContext context) + public void Run(AstNode compilationUnit, TransformContext context) { - this.context = context; - } - - public void Run(AstNode compilationUnit) - { - if (!context.Settings.UsingDeclarations) - return; - // First determine all the namespaces that need to be imported: - compilationUnit.AcceptVisitor(new FindRequiredImports(this), null); + var requiredImports = new FindRequiredImports(context); + compilationUnit.AcceptVisitor(requiredImports); - importedNamespaces.Add("System"); // always import System, even when not necessary + requiredImports.ImportedNamespaces.Add("System"); // always import System, even when not necessary // Now add using declarations for those namespaces: - foreach (string ns in importedNamespaces.OrderByDescending(n => n)) { + foreach (string ns in requiredImports.ImportedNamespaces.OrderByDescending(n => n)) { // we go backwards (OrderByDescending) through the list of namespaces because we insert them backwards // (always inserting at the start of the list) string[] parts = ns.Split('.'); @@ -58,9 +51,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms compilationUnit.InsertChildAfter(null, new UsingDeclaration { Import = nsType }, SyntaxTree.MemberRole); } - if (!context.Settings.FullyQualifyAmbiguousTypeNames) + if (!FullyQualifyAmbiguousTypeNames) return; - + + /* FindAmbiguousTypeNames(context.CurrentModule, internalsVisible: true); foreach (AssemblyNameReference r in context.CurrentModule.AssemblyReferences) { AssemblyDefinition d = context.CurrentModule.AssemblyResolver.Resolve(r); @@ -69,25 +63,24 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } // verify that the SimpleTypes refer to the correct type (no ambiguities) - compilationUnit.AcceptVisitor(new FullyQualifyAmbiguousTypeNamesVisitor(this), null); + compilationUnit.AcceptVisitor(new FullyQualifyAmbiguousTypeNamesVisitor(this), null);*/ } - readonly HashSet declaredNamespaces = new HashSet() { string.Empty }; - readonly HashSet importedNamespaces = new HashSet(); // Note that we store type names with `n suffix, so we automatically disambiguate based on number of type parameters. - readonly HashSet availableTypeNames = new HashSet(); - readonly HashSet ambiguousTypeNames = new HashSet(); + //readonly HashSet availableTypeNames = new HashSet(); + //readonly HashSet ambiguousTypeNames = new HashSet(); - sealed class FindRequiredImports : DepthFirstAstVisitor + sealed class FindRequiredImports : DepthFirstAstVisitor { - readonly IntroduceUsingDeclarations transform; string currentNamespace; + + public readonly HashSet DeclaredNamespaces = new HashSet() { string.Empty }; + public readonly HashSet ImportedNamespaces = new HashSet(); - public FindRequiredImports(IntroduceUsingDeclarations transform) + public FindRequiredImports(TransformContext context) { - this.transform = transform; - this.currentNamespace = transform.context.CurrentType != null ? transform.context.CurrentType.Namespace : string.Empty; + this.currentNamespace = context.DecompiledTypeDefinition != null ? context.DecompiledTypeDefinition.Namespace : string.Empty; } bool IsParentOfCurrentNamespace(string ns) @@ -103,28 +96,28 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return false; } - public override object VisitSimpleType(SimpleType simpleType, object data) + public override void VisitSimpleType(SimpleType simpleType) { - TypeReference tr = simpleType.Annotation(); - if (tr != null && !IsParentOfCurrentNamespace(tr.Namespace)) { - transform.importedNamespaces.Add(tr.Namespace); + var trr = simpleType.Annotation(); + if (trr != null && !IsParentOfCurrentNamespace(trr.Type.Namespace)) { + ImportedNamespaces.Add(trr.Type.Namespace); } - return base.VisitSimpleType(simpleType, data); // also visit type arguments + base.VisitSimpleType(simpleType); // also visit type arguments } - public override object VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration, object data) + public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) { string oldNamespace = currentNamespace; - foreach (Identifier ident in namespaceDeclaration.Identifiers) { - currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident.Name); - transform.declaredNamespaces.Add(currentNamespace); + foreach (string ident in namespaceDeclaration.Identifiers) { + currentNamespace = NamespaceDeclaration.BuildQualifiedName(currentNamespace, ident); + DeclaredNamespaces.Add(currentNamespace); } - base.VisitNamespaceDeclaration(namespaceDeclaration, data); + base.VisitNamespaceDeclaration(namespaceDeclaration); currentNamespace = oldNamespace; - return null; } } + /* void FindAmbiguousTypeNames(ModuleDefinition module, bool internalsVisible) { foreach (TypeDefinition type in module.Types) { @@ -355,6 +348,6 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms return false; return transform.ambiguousTypeNames.Contains(name); } - } + }*/ } } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs b/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs index e766a2409..ee53dfd3a 100644 --- a/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs +++ b/ICSharpCode.Decompiler/CSharp/Transforms/ReplaceMethodCallsWithOperators.cs @@ -345,7 +345,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms } } - void IAstTransform.Run(AstNode node) + void IAstTransform.Run(AstNode node, TransformContext context) { node.AcceptVisitor(this); } diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs b/ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs new file mode 100644 index 000000000..261be4c5b --- /dev/null +++ b/ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs @@ -0,0 +1,53 @@ +// Copyright (c) 2014 Daniel Grunwald +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using ICSharpCode.NRefactory.CSharp.Resolver; +using ICSharpCode.NRefactory.TypeSystem; + +namespace ICSharpCode.Decompiler.CSharp.Transforms +{ + /// + /// Parameters for IAstTransform. + /// + public class TransformContext + { + public readonly DecompilerTypeSystem TypeSystem; + readonly ITypeResolveContext decompilationContext; + + /// + /// Returns the member that is being decompiled; or null if a whole type or assembly is being decompiled. + /// + public IMember DecompiledMember { + get { return decompilationContext.CurrentMember; } + } + + /// + /// Returns the type definition that is being decompiled; or null if an assembly is being decompiled. + /// + public ITypeDefinition DecompiledTypeDefinition { + get { return decompilationContext.CurrentTypeDefinition; } + } + + internal TransformContext(DecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext) + { + this.TypeSystem = typeSystem; + this.decompilationContext = decompilationContext; + } + } +} diff --git a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs index 9522d3c6d..af5f2a406 100644 --- a/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs +++ b/ICSharpCode.Decompiler/CSharp/TranslatedExpression.cs @@ -194,7 +194,7 @@ namespace ICSharpCode.Decompiler.CSharp } else if (Type.Kind == TypeKind.Pointer) { var nullRef = new NullReferenceExpression() .WithoutILInstruction() - .WithRR(new ConstantResolveResult(this.Type, null)); + .WithRR(new ConstantResolveResult(SpecialType.NullType, null)); return new BinaryOperatorExpression(Expression, BinaryOperatorType.InEquality, nullRef.Expression) .WithoutILInstruction() .WithRR(new OperatorResolveResult(boolType, System.Linq.Expressions.ExpressionType.NotEqual, diff --git a/ICSharpCode.Decompiler/DecompilerTypeSystem.cs b/ICSharpCode.Decompiler/DecompilerTypeSystem.cs index 57f24e339..2799f55ab 100644 --- a/ICSharpCode.Decompiler/DecompilerTypeSystem.cs +++ b/ICSharpCode.Decompiler/DecompilerTypeSystem.cs @@ -56,13 +56,15 @@ namespace ICSharpCode.Decompiler context = new SimpleTypeResolveContext(compilation.MainAssembly); } - public ICompilation Compilation - { + public ICompilation Compilation { get { return compilation; } } + + public IAssembly MainAssembly { + get { return compilation.MainAssembly; } + } - public ModuleDefinition ModuleDefinition - { + public ModuleDefinition ModuleDefinition { get { return moduleDefinition; } } @@ -113,7 +115,7 @@ namespace ICSharpCode.Decompiler /// /// Retrieves a type definition for a type defined in the compilation's main assembly. /// - public IType GetType(TypeReference typeReference) + public IType Resolve(TypeReference typeReference) { if (typeReference == null) return SpecialType.UnknownType; @@ -125,7 +127,7 @@ namespace ICSharpCode.Decompiler #endregion #region Resolve Field - public IField GetField(FieldReference fieldReference) + public IField Resolve(FieldReference fieldReference) { if (fieldReference == null) throw new ArgumentNullException("fieldReference"); @@ -135,7 +137,7 @@ namespace ICSharpCode.Decompiler field = FindNonGenericField(fieldReference); if (fieldReference.DeclaringType.IsGenericInstance) { var git = (GenericInstanceType)fieldReference.DeclaringType; - var typeArguments = git.GenericArguments.SelectArray(GetType); + var typeArguments = git.GenericArguments.SelectArray(Resolve); field = (IField)field.Specialize(new TypeParameterSubstitution(typeArguments, null)); } fieldLookupCache.Add(fieldReference, field); @@ -146,7 +148,7 @@ namespace ICSharpCode.Decompiler IField FindNonGenericField(FieldReference fieldReference) { - ITypeDefinition typeDef = GetType(fieldReference.DeclaringType).GetDefinition(); + ITypeDefinition typeDef = Resolve(fieldReference.DeclaringType).GetDefinition(); if (typeDef == null) return CreateFakeField(fieldReference); foreach (IField field in typeDef.Fields) @@ -157,7 +159,7 @@ namespace ICSharpCode.Decompiler IField CreateFakeField(FieldReference fieldReference) { - var declaringType = GetType(fieldReference.DeclaringType); + var declaringType = Resolve(fieldReference.DeclaringType); var f = new DefaultUnresolvedField(); f.Name = fieldReference.Name; f.ReturnType = typeReferenceCecilLoader.ReadTypeReference(fieldReference.FieldType); @@ -182,7 +184,7 @@ namespace ICSharpCode.Decompiler #endregion #region Resolve Method - public IMethod GetMethod(MethodReference methodReference) + public IMethod Resolve(MethodReference methodReference) { if (methodReference == null) throw new ArgumentNullException("methodReference"); @@ -195,11 +197,11 @@ namespace ICSharpCode.Decompiler IList methodTypeArguments = null; if (methodReference.IsGenericInstance) { var gim = ((GenericInstanceMethod)methodReference); - methodTypeArguments = gim.GenericArguments.SelectArray(GetType); + methodTypeArguments = gim.GenericArguments.SelectArray(Resolve); } if (methodReference.DeclaringType.IsGenericInstance) { var git = (GenericInstanceType)methodReference.DeclaringType; - classTypeArguments = git.GenericArguments.SelectArray(GetType); + classTypeArguments = git.GenericArguments.SelectArray(Resolve); } method = method.Specialize(new TypeParameterSubstitution(classTypeArguments, methodTypeArguments)); } @@ -211,7 +213,7 @@ namespace ICSharpCode.Decompiler IMethod FindNonGenericMethod(MethodReference methodReference) { - ITypeDefinition typeDef = GetType(methodReference.DeclaringType).GetDefinition(); + ITypeDefinition typeDef = Resolve(methodReference.DeclaringType).GetDefinition(); if (typeDef == null) return CreateFakeMethod(methodReference); IEnumerable methods; @@ -227,7 +229,7 @@ namespace ICSharpCode.Decompiler if (GetCecil(method) == methodReference) return method; } - var parameterTypes = methodReference.Parameters.SelectArray(p => GetType(p.ParameterType)); + var parameterTypes = methodReference.Parameters.SelectArray(p => Resolve(p.ParameterType)); foreach (var method in methods) { if (CompareSignatures(method.Parameters, parameterTypes)) return method; diff --git a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj index 10d599e99..d4cdf3749 100644 --- a/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj +++ b/ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj @@ -63,6 +63,8 @@ + + diff --git a/ICSharpCode.Decompiler/IL/BlockBuilder.cs b/ICSharpCode.Decompiler/IL/BlockBuilder.cs index 4019be2b2..60427483a 100644 --- a/ICSharpCode.Decompiler/IL/BlockBuilder.cs +++ b/ICSharpCode.Decompiler/IL/BlockBuilder.cs @@ -72,7 +72,7 @@ namespace ICSharpCode.Decompiler.IL tryInstructionList.Add(tryCatch); } - var variable = new ILVariable(VariableKind.Exception, typeSystem.GetType(eh.CatchType), handlerBlock.ILRange.Start); + var variable = new ILVariable(VariableKind.Exception, typeSystem.Resolve(eh.CatchType), handlerBlock.ILRange.Start); variable.Name = "ex"; handlerBlock.EntryPoint.Instructions.Add(new LdLoc(variable)); diff --git a/ICSharpCode.Decompiler/IL/ILReader.cs b/ICSharpCode.Decompiler/IL/ILReader.cs index f83919bf2..1d7d904d7 100644 --- a/ICSharpCode.Decompiler/IL/ILReader.cs +++ b/ICSharpCode.Decompiler/IL/ILReader.cs @@ -93,21 +93,21 @@ namespace ICSharpCode.Decompiler.IL { var token = ReadMetadataToken(ref reader); var typeReference = body.LookupToken(token) as TypeReference; - return typeSystem.GetType(typeReference); + return typeSystem.Resolve(typeReference); } IMethod ReadAndDecodeMethodReference() { var token = ReadMetadataToken(ref reader); var methodReference = body.LookupToken(token) as MethodReference; - return typeSystem.GetMethod(methodReference); + return typeSystem.Resolve(methodReference); } IField ReadAndDecodeFieldReference() { var token = ReadMetadataToken(ref reader); var fieldReference = body.LookupToken(token) as FieldReference; - return typeSystem.GetField(fieldReference); + return typeSystem.Resolve(fieldReference); } void InitParameterVariables() @@ -123,7 +123,7 @@ namespace ICSharpCode.Decompiler.IL ILVariable CreateILVariable(Cil.VariableDefinition v) { - var ilVar = new ILVariable(VariableKind.Local, typeSystem.GetType(v.VariableType), v.Index); + var ilVar = new ILVariable(VariableKind.Local, typeSystem.Resolve(v.VariableType), v.Index); if (string.IsNullOrEmpty(v.Name)) ilVar.Name = "V_" + v.Index; else @@ -134,7 +134,7 @@ namespace ICSharpCode.Decompiler.IL ILVariable CreateILVariable(ParameterDefinition p) { var variableKind = p.Index == -1 ? VariableKind.This : VariableKind.Parameter; - var ilVar = new ILVariable(variableKind, typeSystem.GetType(p.ParameterType), p.Index); + var ilVar = new ILVariable(variableKind, typeSystem.Resolve(p.ParameterType), p.Index); ilVar.StoreCount = 1; // count the initial store when the method is called with an argument if (variableKind == VariableKind.This) ilVar.Name = "this"; diff --git a/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs b/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs index f6c153b1a..93c73052b 100644 --- a/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs +++ b/NRefactory/ICSharpCode.NRefactory.CSharp/OutputVisitor/CSharpAmbience.cs @@ -171,7 +171,7 @@ namespace ICSharpCode.NRefactory.CSharp TypeSystemAstBuilder CreateAstBuilder() { TypeSystemAstBuilder astBuilder = new TypeSystemAstBuilder(); - astBuilder.AddAnnotations = true; + astBuilder.AddTypeReferenceAnnotations = true; astBuilder.ShowModifiers = (ConversionFlags & ConversionFlags.ShowModifiers) == ConversionFlags.ShowModifiers; astBuilder.ShowAccessibility = (ConversionFlags & ConversionFlags.ShowAccessibility) == ConversionFlags.ShowAccessibility; astBuilder.AlwaysUseShortTypeNames = (ConversionFlags & ConversionFlags.UseFullyQualifiedTypeNames) != ConversionFlags.UseFullyQualifiedTypeNames; diff --git a/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs b/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs index 6793680e5..09725b2d8 100644 --- a/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs +++ b/NRefactory/ICSharpCode.NRefactory.CSharp/Refactoring/TypeSystemAstBuilder.cs @@ -77,7 +77,13 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring /// Specifies whether the ast builder should add annotations to type references. /// The default value is false. /// - public bool AddAnnotations { get; set; } + public bool AddTypeReferenceAnnotations { get; set; } + + /// + /// Specifies whether the ast builder should add ResolveResult annotations to AST nodes. + /// The default value is false. + /// + public bool AddResolveResultAnnotations { get; set; } /// /// Controls the accessibility modifiers are shown. @@ -159,8 +165,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (type == null) throw new ArgumentNullException("type"); AstType astType = ConvertTypeHelper(type); - if (AddAnnotations) + if (AddTypeReferenceAnnotations) astType.AddAnnotation(type); + if (AddResolveResultAnnotations) + astType.AddAnnotation(new TypeResolveResult(type)); return astType; } @@ -417,7 +425,10 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring } if (rr is TypeOfResolveResult) { - return new TypeOfExpression(ConvertType(rr.Type)); + var expr = new TypeOfExpression(ConvertType(rr.Type)); + if (AddResolveResultAnnotations) + expr.AddAnnotation(rr); + return expr; } else if (rr is ArrayCreateResolveResult) { ArrayCreateResolveResult acrr = (ArrayCreateResolveResult)rr; ArrayCreateExpression ace = new ArrayCreateExpression(); @@ -438,6 +449,8 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring initializer.Elements.AddRange(acrr.InitializerElements.Select(ConvertConstantValue)); ace.Initializer = initializer; } + if (AddResolveResultAnnotations) + ace.AddAnnotation(rr); return ace; } else if (rr.IsCompileTimeConstant) { return ConvertConstantValue(rr.Type, rr.ConstantValue); @@ -451,10 +464,17 @@ namespace ICSharpCode.NRefactory.CSharp.Refactoring if (type == null) throw new ArgumentNullException("type"); if (constantValue == null) { - if (type.IsReferenceType == true) - return new NullReferenceExpression(); - else - return new DefaultValueExpression(ConvertType(type)); + if (type.IsReferenceType == true) { + var expr = new NullReferenceExpression(); + if (AddResolveResultAnnotations) + expr.AddAnnotation(new ConstantResolveResult(SpecialType.NullType, null)); + return expr; + } else { + var expr = new DefaultValueExpression(ConvertType(type)); + if (AddResolveResultAnnotations) + expr.AddAnnotation(new ConstantResolveResult(type, null)); + return expr; + } } else if (type.Kind == TypeKind.Enum) { return ConvertEnumValue(type, (long)CSharpPrimitiveCast.Cast(TypeCode.Int64, constantValue, false)); } else {