Browse Source

Cache UsingScope during decompiler run.

pull/1096/merge
Siegfried Pammer 8 years ago
parent
commit
1a0052a345
  1. 204
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 15
      ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs
  3. 41
      ICSharpCode.Decompiler/DecompileRun.cs
  4. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  5. 5
      ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs
  6. 5
      ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs
  7. 12
      ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs
  8. 19
      ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs
  9. 5
      ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs
  10. 2
      ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs
  11. 6
      ILSpy/Languages/ILAstLanguage.cs

204
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -51,7 +51,6 @@ namespace ICSharpCode.Decompiler.CSharp
readonly DecompilerTypeSystem typeSystem; readonly DecompilerTypeSystem typeSystem;
readonly DecompilerSettings settings; readonly DecompilerSettings settings;
SyntaxTree syntaxTree; SyntaxTree syntaxTree;
HashSet<string> namespaces;
List<IILTransform> ilTransforms = GetILTransforms(); List<IILTransform> ilTransforms = GetILTransforms();
@ -291,10 +290,10 @@ namespace ICSharpCode.Decompiler.CSharp
return typeSystemAstBuilder; return typeSystemAstBuilder;
} }
void RunTransforms(AstNode rootNode, ITypeResolveContext decompilationContext) void RunTransforms(AstNode rootNode, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{ {
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
var context = new TransformContext(typeSystem, decompilationContext, namespaces.ToImmutableHashSet(), typeSystemAstBuilder, settings, CancellationToken); var context = new TransformContext(typeSystem, decompileRun, decompilationContext, typeSystemAstBuilder);
foreach (var transform in astTransforms) { foreach (var transform in astTransforms) {
CancellationToken.ThrowIfCancellationRequested(); CancellationToken.ThrowIfCancellationRequested();
transform.Run(rootNode, context); transform.Run(rootNode, context);
@ -315,11 +314,12 @@ namespace ICSharpCode.Decompiler.CSharp
public SyntaxTree DecompileModuleAndAssemblyAttributes() public SyntaxTree DecompileModuleAndAssemblyAttributes()
{ {
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly); var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly);
var decompileRun = new DecompileRun(settings) {
CancellationToken = CancellationToken
};
syntaxTree = new SyntaxTree(); syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>(); DoDecompileModuleAndAssemblyAttributes(decompileRun, decompilationContext, syntaxTree);
namespaces = new HashSet<string>(); RunTransforms(syntaxTree, decompileRun, decompilationContext);
DoDecompileModuleAndAssemblyAttributes(decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompilationContext);
return syntaxTree; return syntaxTree;
} }
@ -331,12 +331,12 @@ namespace ICSharpCode.Decompiler.CSharp
return SyntaxTreeToString(DecompileModuleAndAssemblyAttributes()); return SyntaxTreeToString(DecompileModuleAndAssemblyAttributes());
} }
void DoDecompileModuleAndAssemblyAttributes(ITypeResolveContext decompilationContext, SyntaxTree syntaxTree) void DoDecompileModuleAndAssemblyAttributes(DecompileRun decompileRun, ITypeResolveContext decompilationContext, SyntaxTree syntaxTree)
{ {
foreach (var a in typeSystem.Compilation.MainAssembly.AssemblyAttributes) { foreach (var a in typeSystem.Compilation.MainAssembly.AssemblyAttributes) {
namespaces.Add(a.AttributeType.Namespace); decompileRun.Namespaces.Add(a.AttributeType.Namespace);
namespaces.AddRange(a.PositionalArguments.Select(pa => pa.Type.Namespace)); decompileRun.Namespaces.AddRange(a.PositionalArguments.Select(pa => pa.Type.Namespace));
namespaces.AddRange(a.NamedArguments.Select(na => na.Value.Type.Namespace)); decompileRun.Namespaces.AddRange(a.NamedArguments.Select(na => na.Value.Type.Namespace));
var astBuilder = CreateAstBuilder(decompilationContext); var astBuilder = CreateAstBuilder(decompilationContext);
var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a)); var attrSection = new AttributeSection(astBuilder.ConvertAttribute(a));
attrSection.AttributeTarget = "assembly"; attrSection.AttributeTarget = "assembly";
@ -344,7 +344,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
void DoDecompileTypes(IEnumerable<TypeDefinition> types, ITypeResolveContext decompilationContext, SyntaxTree syntaxTree) void DoDecompileTypes(IEnumerable<TypeDefinition> types, DecompileRun decompileRun, ITypeResolveContext decompilationContext, SyntaxTree syntaxTree)
{ {
string currentNamespace = null; string currentNamespace = null;
AstNode groupNode = null; AstNode groupNode = null;
@ -363,7 +363,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
currentNamespace = cecilType.Namespace; currentNamespace = cecilType.Namespace;
var typeDecl = DoDecompile(typeDef, decompilationContext.WithCurrentTypeDefinition(typeDef)); var typeDecl = DoDecompile(typeDef, decompileRun, decompilationContext.WithCurrentTypeDefinition(typeDef));
groupNode.AddChild(typeDecl, SyntaxTree.MemberRole); groupNode.AddChild(typeDecl, SyntaxTree.MemberRole);
} }
} }
@ -374,19 +374,19 @@ namespace ICSharpCode.Decompiler.CSharp
public SyntaxTree DecompileWholeModuleAsSingleFile() public SyntaxTree DecompileWholeModuleAsSingleFile()
{ {
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly); var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly);
var decompileRun = new DecompileRun(settings) {
CancellationToken = CancellationToken
};
syntaxTree = new SyntaxTree(); syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>(); CollectNamespacesForAllTypes(decompileRun.Namespaces);
namespaces = CollectNamespacesForAllTypes(); DoDecompileModuleAndAssemblyAttributes(decompileRun, decompilationContext, syntaxTree);
DoDecompileModuleAndAssemblyAttributes(decompilationContext, syntaxTree); DoDecompileTypes(typeSystem.ModuleDefinition.Types, decompileRun, decompilationContext, syntaxTree);
DoDecompileTypes(typeSystem.ModuleDefinition.Types, decompilationContext, syntaxTree); RunTransforms(syntaxTree, decompileRun, decompilationContext);
RunTransforms(syntaxTree, decompilationContext);
return syntaxTree; return syntaxTree;
} }
HashSet<string> CollectNamespacesForAllTypes() void CollectNamespacesForAllTypes(HashSet<string> namespaces)
{ {
var namespaces = new HashSet<string>();
foreach (var type in typeSystem.ModuleDefinition.Types) { foreach (var type in typeSystem.ModuleDefinition.Types) {
CollectNamespacesForDecompilation(new[] { type }, namespaces); CollectNamespacesForDecompilation(new[] { type }, namespaces);
} }
@ -394,8 +394,6 @@ namespace ICSharpCode.Decompiler.CSharp
foreach (var typeRef in typeSystem.ModuleDefinition.GetTypeReferences()) { foreach (var typeRef in typeSystem.ModuleDefinition.GetTypeReferences()) {
namespaces.Add(typeRef.Namespace); namespaces.Add(typeRef.Namespace);
} }
return namespaces;
} }
static void CollectNamespacesForDecompilation(MemberReference memberReference, HashSet<string> namespaces, bool decodeDetails = false) static void CollectNamespacesForDecompilation(MemberReference memberReference, HashSet<string> namespaces, bool decodeDetails = false)
@ -659,6 +657,16 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
public ILTransformContext CreateILTransformContext(ILFunction function)
{
var decompileRun = new DecompileRun(settings) { CancellationToken = CancellationToken };
CollectNamespacesForDecompilation(new[] { function.CecilMethod }, decompileRun.Namespaces);
return new ILTransformContext(function, typeSystem, settings) {
CancellationToken = CancellationToken,
DecompileRun = decompileRun
};
}
/// <summary> /// <summary>
/// Decompiles the whole module into a single string. /// Decompiles the whole module into a single string.
/// </summary> /// </summary>
@ -678,12 +686,14 @@ namespace ICSharpCode.Decompiler.CSharp
if (types == null) if (types == null)
throw new ArgumentNullException(nameof(types)); throw new ArgumentNullException(nameof(types));
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly); var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly);
var decompileRun = new DecompileRun(settings) {
CancellationToken = CancellationToken
};
syntaxTree = new SyntaxTree(); syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>();
namespaces = new HashSet<string>(); CollectNamespacesForDecompilation(types, decompileRun.Namespaces);
CollectNamespacesForDecompilation(types, namespaces); DoDecompileTypes(types, decompileRun, decompilationContext, syntaxTree);
DoDecompileTypes(types, decompilationContext, syntaxTree); RunTransforms(syntaxTree, decompileRun, decompilationContext);
RunTransforms(syntaxTree, decompilationContext);
return syntaxTree; return syntaxTree;
} }
@ -710,13 +720,14 @@ namespace ICSharpCode.Decompiler.CSharp
if (type == null) if (type == null)
throw new InvalidOperationException($"Could not find type definition {fullTypeName} in type system."); throw new InvalidOperationException($"Could not find type definition {fullTypeName} in type system.");
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly); var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainAssembly);
var decompileRun = new DecompileRun(settings) {
CancellationToken = CancellationToken
};
syntaxTree = new SyntaxTree(); syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>();
namespaces = new HashSet<string>();
var cecilType = typeSystem.GetCecil(type); var cecilType = typeSystem.GetCecil(type);
CollectNamespacesForDecompilation(cecilType, namespaces, true); CollectNamespacesForDecompilation(cecilType, decompileRun.Namespaces, true);
DoDecompileTypes(new[] { cecilType }, decompilationContext, syntaxTree); DoDecompileTypes(new[] { cecilType }, decompileRun, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompilationContext); RunTransforms(syntaxTree, decompileRun, decompilationContext);
return syntaxTree; return syntaxTree;
} }
@ -748,52 +759,52 @@ namespace ICSharpCode.Decompiler.CSharp
throw new ArgumentNullException(nameof(definitions)); throw new ArgumentNullException(nameof(definitions));
ITypeDefinition parentTypeDef = null; ITypeDefinition parentTypeDef = null;
syntaxTree = new SyntaxTree(); syntaxTree = new SyntaxTree();
definedSymbols = new HashSet<string>(); var decompileRun = new DecompileRun(settings) { CancellationToken = CancellationToken };
namespaces = new HashSet<string>(); CollectNamespacesForDecompilation(definitions, decompileRun.Namespaces);
CollectNamespacesForDecompilation(definitions, namespaces);
foreach (var def in definitions) { foreach (var def in definitions) {
if (def == null) if (def == null)
throw new ArgumentException("definitions contains null element"); throw new ArgumentException("definitions contains null element");
var typeDefinition = def as TypeDefinition; switch (def) {
var methodDefinition = def as MethodDefinition; case TypeDefinition typeDefinition:
var fieldDefinition = def as FieldDefinition; ITypeDefinition typeDef = typeSystem.Resolve(typeDefinition).GetDefinition();
var propertyDefinition = def as PropertyDefinition; if (typeDef == null)
var eventDefinition = def as EventDefinition; throw new InvalidOperationException("Could not find type definition in NR type system");
if (typeDefinition != null) { syntaxTree.Members.Add(DoDecompile(typeDef, decompileRun, new SimpleTypeResolveContext(typeDef)));
ITypeDefinition typeDef = typeSystem.Resolve(typeDefinition).GetDefinition(); parentTypeDef = typeDef.DeclaringTypeDefinition;
if (typeDef == null) break;
throw new InvalidOperationException("Could not find type definition in NR type system"); case MethodDefinition methodDefinition:
syntaxTree.Members.Add(DoDecompile(typeDef, new SimpleTypeResolveContext(typeDef))); IMethod method = typeSystem.Resolve(methodDefinition);
parentTypeDef = typeDef.DeclaringTypeDefinition; if (method == null)
} else if (methodDefinition != null) { throw new InvalidOperationException("Could not find method definition in NR type system");
IMethod method = typeSystem.Resolve(methodDefinition); syntaxTree.Members.Add(DoDecompile(methodDefinition, method, decompileRun, new SimpleTypeResolveContext(method)));
if (method == null) parentTypeDef = method.DeclaringTypeDefinition;
throw new InvalidOperationException("Could not find method definition in NR type system"); break;
syntaxTree.Members.Add(DoDecompile(methodDefinition, method, new SimpleTypeResolveContext(method))); case FieldDefinition fieldDefinition:
parentTypeDef = method.DeclaringTypeDefinition; IField field = typeSystem.Resolve(fieldDefinition);
} else if (fieldDefinition != null) { if (field == null)
IField field = typeSystem.Resolve(fieldDefinition); throw new InvalidOperationException("Could not find field definition in NR type system");
if (field == null) syntaxTree.Members.Add(DoDecompile(fieldDefinition, field, decompileRun, new SimpleTypeResolveContext(field)));
throw new InvalidOperationException("Could not find field definition in NR type system"); parentTypeDef = field.DeclaringTypeDefinition;
syntaxTree.Members.Add(DoDecompile(fieldDefinition, field, new SimpleTypeResolveContext(field))); break;
parentTypeDef = field.DeclaringTypeDefinition; case PropertyDefinition propertyDefinition:
} else if (propertyDefinition != null) { IProperty property = typeSystem.Resolve(propertyDefinition);
IProperty property = typeSystem.Resolve(propertyDefinition); if (property == null)
if (property == null) throw new InvalidOperationException("Could not find property definition in NR type system");
throw new InvalidOperationException("Could not find field definition in NR type system"); syntaxTree.Members.Add(DoDecompile(propertyDefinition, property, decompileRun, new SimpleTypeResolveContext(property)));
syntaxTree.Members.Add(DoDecompile(propertyDefinition, property, new SimpleTypeResolveContext(property))); parentTypeDef = property.DeclaringTypeDefinition;
parentTypeDef = property.DeclaringTypeDefinition; break;
} else if (eventDefinition != null) { case EventDefinition eventDefinition:
IEvent ev = typeSystem.Resolve(eventDefinition); IEvent ev = typeSystem.Resolve(eventDefinition);
if (ev == null) if (ev == null)
throw new InvalidOperationException("Could not find field definition in NR type system"); throw new InvalidOperationException("Could not find event definition in NR type system");
syntaxTree.Members.Add(DoDecompile(eventDefinition, ev, new SimpleTypeResolveContext(ev))); syntaxTree.Members.Add(DoDecompile(eventDefinition, ev, decompileRun, new SimpleTypeResolveContext(ev)));
parentTypeDef = ev.DeclaringTypeDefinition; parentTypeDef = ev.DeclaringTypeDefinition;
} else { break;
throw new NotSupportedException(def.GetType().Name); default:
throw new NotSupportedException(def.GetType().Name);
} }
} }
RunTransforms(syntaxTree, parentTypeDef != null ? new SimpleTypeResolveContext(parentTypeDef) : new SimpleTypeResolveContext(typeSystem.MainAssembly)); RunTransforms(syntaxTree, decompileRun, parentTypeDef != null ? new SimpleTypeResolveContext(parentTypeDef) : new SimpleTypeResolveContext(typeSystem.MainAssembly));
return syntaxTree; return syntaxTree;
} }
@ -910,7 +921,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
EntityDeclaration DoDecompile(ITypeDefinition typeDef, ITypeResolveContext decompilationContext) EntityDeclaration DoDecompile(ITypeDefinition typeDef, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{ {
Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef); Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
@ -923,7 +934,7 @@ namespace ICSharpCode.Decompiler.CSharp
foreach (var type in typeDef.NestedTypes) { foreach (var type in typeDef.NestedTypes) {
var cecilType = typeSystem.GetCecil(type); var cecilType = typeSystem.GetCecil(type);
if (cecilType != null && !MemberIsHidden(cecilType, settings)) { if (cecilType != null && !MemberIsHidden(cecilType, settings)) {
var nestedType = DoDecompile(type, decompilationContext.WithCurrentTypeDefinition(type)); var nestedType = DoDecompile(type, decompileRun, decompilationContext.WithCurrentTypeDefinition(type));
SetNewModifier(nestedType); SetNewModifier(nestedType);
typeDecl.Members.Add(nestedType); typeDecl.Members.Add(nestedType);
} }
@ -931,28 +942,28 @@ namespace ICSharpCode.Decompiler.CSharp
foreach (var field in typeDef.Fields) { foreach (var field in typeDef.Fields) {
var fieldDef = typeSystem.GetCecil(field) as FieldDefinition; var fieldDef = typeSystem.GetCecil(field) as FieldDefinition;
if (fieldDef != null && !MemberIsHidden(fieldDef, settings)) { if (fieldDef != null && !MemberIsHidden(fieldDef, settings)) {
var memberDecl = DoDecompile(fieldDef, field, decompilationContext.WithCurrentMember(field)); var memberDecl = DoDecompile(fieldDef, field, decompileRun, decompilationContext.WithCurrentMember(field));
typeDecl.Members.Add(memberDecl); typeDecl.Members.Add(memberDecl);
} }
} }
foreach (var property in typeDef.Properties) { foreach (var property in typeDef.Properties) {
var propDef = typeSystem.GetCecil(property) as PropertyDefinition; var propDef = typeSystem.GetCecil(property) as PropertyDefinition;
if (propDef != null && !MemberIsHidden(propDef, settings)) { if (propDef != null && !MemberIsHidden(propDef, settings)) {
var propDecl = DoDecompile(propDef, property, decompilationContext.WithCurrentMember(property)); var propDecl = DoDecompile(propDef, property, decompileRun, decompilationContext.WithCurrentMember(property));
typeDecl.Members.Add(propDecl); typeDecl.Members.Add(propDecl);
} }
} }
foreach (var @event in typeDef.Events) { foreach (var @event in typeDef.Events) {
var eventDef = typeSystem.GetCecil(@event) as EventDefinition; var eventDef = typeSystem.GetCecil(@event) as EventDefinition;
if (eventDef != null && !MemberIsHidden(eventDef, settings)) { if (eventDef != null && !MemberIsHidden(eventDef, settings)) {
var eventDecl = DoDecompile(eventDef, @event, decompilationContext.WithCurrentMember(@event)); var eventDecl = DoDecompile(eventDef, @event, decompileRun, decompilationContext.WithCurrentMember(@event));
typeDecl.Members.Add(eventDecl); typeDecl.Members.Add(eventDecl);
} }
} }
foreach (var method in typeDef.Methods) { foreach (var method in typeDef.Methods) {
var methodDef = typeSystem.GetCecil(method) as MethodDefinition; var methodDef = typeSystem.GetCecil(method) as MethodDefinition;
if (methodDef != null && !MemberIsHidden(methodDef, settings)) { if (methodDef != null && !MemberIsHidden(methodDef, settings)) {
var memberDecl = DoDecompile(methodDef, method, decompilationContext.WithCurrentMember(method)); var memberDecl = DoDecompile(methodDef, method, decompileRun, decompilationContext.WithCurrentMember(method));
typeDecl.Members.Add(memberDecl); typeDecl.Members.Add(memberDecl);
typeDecl.Members.AddRange(AddInterfaceImplHelpers(memberDecl, methodDef, typeSystemAstBuilder)); typeDecl.Members.AddRange(AddInterfaceImplHelpers(memberDecl, methodDef, typeSystemAstBuilder));
} }
@ -1024,7 +1035,7 @@ namespace ICSharpCode.Decompiler.CSharp
return method; return method;
} }
EntityDeclaration DoDecompile(MethodDefinition methodDefinition, IMethod method, ITypeResolveContext decompilationContext) EntityDeclaration DoDecompile(MethodDefinition methodDefinition, IMethod method, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{ {
Debug.Assert(decompilationContext.CurrentMember == method); Debug.Assert(decompilationContext.CurrentMember == method);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
@ -1035,7 +1046,7 @@ namespace ICSharpCode.Decompiler.CSharp
} }
FixParameterNames(methodDecl); FixParameterNames(methodDecl);
if (methodDefinition.HasBody) { if (methodDefinition.HasBody) {
DecompileBody(methodDefinition, method, methodDecl, decompilationContext); DecompileBody(methodDefinition, method, methodDecl, decompileRun, decompilationContext);
} else if (!method.IsAbstract && method.DeclaringType.Kind != TypeKind.Interface) { } else if (!method.IsAbstract && method.DeclaringType.Kind != TypeKind.Interface) {
methodDecl.Modifiers |= Modifiers.Extern; methodDecl.Modifiers |= Modifiers.Extern;
} }
@ -1045,7 +1056,7 @@ namespace ICSharpCode.Decompiler.CSharp
return methodDecl; return methodDecl;
} }
void DecompileBody(MethodDefinition methodDefinition, IMethod method, EntityDeclaration entityDecl, ITypeResolveContext decompilationContext) void DecompileBody(MethodDefinition methodDefinition, IMethod method, EntityDeclaration entityDecl, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{ {
try { try {
var specializingTypeSystem = typeSystem.GetSpecializingTypeSystem(decompilationContext); var specializingTypeSystem = typeSystem.GetSpecializingTypeSystem(decompilationContext);
@ -1064,8 +1075,9 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
var context = new ILTransformContext(function, specializingTypeSystem, namespaces.ToImmutableHashSet(), settings) { var context = new ILTransformContext(function, specializingTypeSystem, settings) {
CancellationToken = CancellationToken CancellationToken = CancellationToken,
DecompileRun = decompileRun
}; };
foreach (var transform in ilTransforms) { foreach (var transform in ilTransforms) {
CancellationToken.ThrowIfCancellationRequested(); CancellationToken.ThrowIfCancellationRequested();
@ -1081,7 +1093,7 @@ namespace ICSharpCode.Decompiler.CSharp
var body = BlockStatement.Null; var body = BlockStatement.Null;
// Generate C# AST only if bodies should be displayed. // Generate C# AST only if bodies should be displayed.
if (settings.DecompileMemberBodies) { if (settings.DecompileMemberBodies) {
AddDefinesForConditionalAttributes(function); AddDefinesForConditionalAttributes(function, decompileRun, decompilationContext);
var statementBuilder = new StatementBuilder(specializingTypeSystem, decompilationContext, function, settings, CancellationToken); var statementBuilder = new StatementBuilder(specializingTypeSystem, decompilationContext, function, settings, CancellationToken);
body = statementBuilder.ConvertAsBlock(function.Body); body = statementBuilder.ConvertAsBlock(function.Body);
@ -1146,20 +1158,18 @@ namespace ICSharpCode.Decompiler.CSharp
return false; return false;
} }
HashSet<string> definedSymbols; void AddDefinesForConditionalAttributes(ILFunction function, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
void AddDefinesForConditionalAttributes(ILFunction function)
{ {
foreach (var call in function.Descendants.OfType<CallInstruction>()) { foreach (var call in function.Descendants.OfType<CallInstruction>()) {
var attr = call.Method.GetAttribute(new TopLevelTypeName("System.Diagnostics", nameof(ConditionalAttribute))); var attr = call.Method.GetAttribute(new TopLevelTypeName("System.Diagnostics", nameof(ConditionalAttribute)));
var symbolName = attr?.PositionalArguments.FirstOrDefault()?.ConstantValue as string; var symbolName = attr?.PositionalArguments.FirstOrDefault()?.ConstantValue as string;
if (symbolName == null || !definedSymbols.Add(symbolName)) if (symbolName == null || !decompileRun.DefinedSymbols.Add(symbolName))
continue; continue;
syntaxTree.InsertChildAfter(null, new PreProcessorDirective(PreProcessorDirectiveType.Define, symbolName), Roles.PreProcessorDirective); syntaxTree.InsertChildAfter(null, new PreProcessorDirective(PreProcessorDirectiveType.Define, symbolName), Roles.PreProcessorDirective);
} }
} }
EntityDeclaration DoDecompile(FieldDefinition fieldDefinition, IField field, ITypeResolveContext decompilationContext) EntityDeclaration DoDecompile(FieldDefinition fieldDefinition, IField field, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{ {
Debug.Assert(decompilationContext.CurrentMember == field); Debug.Assert(decompilationContext.CurrentMember == field);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
@ -1227,7 +1237,7 @@ namespace ICSharpCode.Decompiler.CSharp
return false; return false;
} }
EntityDeclaration DoDecompile(PropertyDefinition propertyDefinition, IProperty property, ITypeResolveContext decompilationContext) EntityDeclaration DoDecompile(PropertyDefinition propertyDefinition, IProperty property, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{ {
Debug.Assert(decompilationContext.CurrentMember == property); Debug.Assert(decompilationContext.CurrentMember == property);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
@ -1246,10 +1256,10 @@ namespace ICSharpCode.Decompiler.CSharp
setter = ((IndexerDeclaration)propertyDecl).Setter; setter = ((IndexerDeclaration)propertyDecl).Setter;
} }
if (property.CanGet && property.Getter.HasBody) { if (property.CanGet && property.Getter.HasBody) {
DecompileBody(propertyDefinition.GetMethod, property.Getter, getter, decompilationContext); DecompileBody(propertyDefinition.GetMethod, property.Getter, getter, decompileRun, decompilationContext);
} }
if (property.CanSet && property.Setter.HasBody) { if (property.CanSet && property.Setter.HasBody) {
DecompileBody(propertyDefinition.SetMethod, property.Setter, setter, decompilationContext); DecompileBody(propertyDefinition.SetMethod, property.Setter, setter, decompileRun, decompilationContext);
} }
var accessor = propertyDefinition.GetMethod ?? propertyDefinition.SetMethod; var accessor = propertyDefinition.GetMethod ?? propertyDefinition.SetMethod;
if (!accessor.HasOverrides && accessor.IsVirtual == accessor.IsNewSlot) if (!accessor.HasOverrides && accessor.IsVirtual == accessor.IsNewSlot)
@ -1257,7 +1267,7 @@ namespace ICSharpCode.Decompiler.CSharp
return propertyDecl; return propertyDecl;
} }
EntityDeclaration DoDecompile(EventDefinition eventDefinition, IEvent ev, ITypeResolveContext decompilationContext) EntityDeclaration DoDecompile(EventDefinition eventDefinition, IEvent ev, DecompileRun decompileRun, ITypeResolveContext decompilationContext)
{ {
Debug.Assert(decompilationContext.CurrentMember == ev); Debug.Assert(decompilationContext.CurrentMember == ev);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext); var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
@ -1268,10 +1278,10 @@ namespace ICSharpCode.Decompiler.CSharp
eventDecl.Name = ev.Name.Substring(lastDot + 1); eventDecl.Name = ev.Name.Substring(lastDot + 1);
} }
if (eventDefinition.AddMethod != null && eventDefinition.AddMethod.HasBody) { if (eventDefinition.AddMethod != null && eventDefinition.AddMethod.HasBody) {
DecompileBody(eventDefinition.AddMethod, ev.AddAccessor, ((CustomEventDeclaration)eventDecl).AddAccessor, decompilationContext); DecompileBody(eventDefinition.AddMethod, ev.AddAccessor, ((CustomEventDeclaration)eventDecl).AddAccessor, decompileRun, decompilationContext);
} }
if (eventDefinition.RemoveMethod != null && eventDefinition.RemoveMethod.HasBody) { if (eventDefinition.RemoveMethod != null && eventDefinition.RemoveMethod.HasBody) {
DecompileBody(eventDefinition.RemoveMethod, ev.RemoveAccessor, ((CustomEventDeclaration)eventDecl).RemoveAccessor, decompilationContext); DecompileBody(eventDefinition.RemoveMethod, ev.RemoveAccessor, ((CustomEventDeclaration)eventDecl).RemoveAccessor, decompileRun, decompilationContext);
} }
var accessor = eventDefinition.AddMethod ?? eventDefinition.RemoveMethod; var accessor = eventDefinition.AddMethod ?? eventDefinition.RemoveMethod;
if (accessor.IsVirtual == accessor.IsNewSlot) { if (accessor.IsVirtual == accessor.IsNewSlot) {

15
ICSharpCode.Decompiler/CSharp/Transforms/TransformContext.cs

@ -32,9 +32,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
public readonly CancellationToken CancellationToken; public readonly CancellationToken CancellationToken;
public readonly TypeSystemAstBuilder TypeSystemAstBuilder; public readonly TypeSystemAstBuilder TypeSystemAstBuilder;
public readonly DecompilerSettings Settings; public readonly DecompilerSettings Settings;
internal readonly DecompileRun DecompileRun;
readonly ITypeResolveContext decompilationContext; readonly ITypeResolveContext decompilationContext;
/// <summary> /// <summary>
/// Returns the member that is being decompiled; or null if a whole type or assembly is being decompiled. /// Returns the member that is being decompiled; or null if a whole type or assembly is being decompiled.
/// </summary> /// </summary>
@ -59,16 +60,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
/// <summary> /// <summary>
/// Returns the max possible set of namespaces that will be used during decompilation. /// Returns the max possible set of namespaces that will be used during decompilation.
/// </summary> /// </summary>
public IImmutableSet<string> RequiredNamespacesSuperset { get; } public IImmutableSet<string> RequiredNamespacesSuperset => DecompileRun.Namespaces.ToImmutableHashSet();
internal TransformContext(DecompilerTypeSystem typeSystem, ITypeResolveContext decompilationContext, IImmutableSet<string> namespaces, TypeSystemAstBuilder typeSystemAstBuilder, DecompilerSettings settings, CancellationToken cancellationToken) internal TransformContext(DecompilerTypeSystem typeSystem, DecompileRun decompileRun, ITypeResolveContext decompilationContext, TypeSystemAstBuilder typeSystemAstBuilder)
{ {
this.TypeSystem = typeSystem; this.TypeSystem = typeSystem;
this.DecompileRun = decompileRun;
this.decompilationContext = decompilationContext; this.decompilationContext = decompilationContext;
this.RequiredNamespacesSuperset = namespaces;
this.TypeSystemAstBuilder = typeSystemAstBuilder; this.TypeSystemAstBuilder = typeSystemAstBuilder;
this.Settings = settings; this.CancellationToken = decompileRun.CancellationToken;
this.CancellationToken = cancellationToken; this.Settings = decompileRun.Settings;
} }
} }
} }

41
ICSharpCode.Decompiler/DecompileRun.cs

@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler
{
internal class DecompileRun
{
public HashSet<string> DefinedSymbols { get; private set; } = new HashSet<string>();
public HashSet<string> Namespaces { get; private set; } = new HashSet<string>();
public CancellationToken CancellationToken { get; set; }
public DecompilerSettings Settings { get; }
Lazy<CSharp.TypeSystem.UsingScope> usingScope => new Lazy<CSharp.TypeSystem.UsingScope>(() => CreateUsingScope(Namespaces));
public CSharp.TypeSystem.UsingScope UsingScope => usingScope.Value;
public DecompileRun(DecompilerSettings settings)
{
this.Settings = settings ?? throw new ArgumentNullException(nameof(settings));
}
CSharp.TypeSystem.UsingScope CreateUsingScope(HashSet<string> requiredNamespacesSuperset)
{
var usingScope = new CSharp.TypeSystem.UsingScope();
foreach (var ns in requiredNamespacesSuperset) {
string[] parts = ns.Split('.');
AstType nsType = new SimpleType(parts[0]);
for (int i = 1; i < parts.Length; i++) {
nsType = new MemberType { Target = nsType, MemberName = parts[i] };
}
var reference = nsType.ToTypeReference(CSharp.Resolver.NameLookupMode.TypeInUsingDeclaration) as CSharp.TypeSystem.TypeOrNamespaceReference;
if (reference != null)
usingScope.Usings.Add(reference);
}
return usingScope;
}
}
}

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -265,6 +265,7 @@
<Compile Include="CSharp\Transforms\ReplaceMethodCallsWithOperators.cs" /> <Compile Include="CSharp\Transforms\ReplaceMethodCallsWithOperators.cs" />
<Compile Include="CSharp\WholeProjectDecompiler.cs" /> <Compile Include="CSharp\WholeProjectDecompiler.cs" />
<Compile Include="CSharp\Transforms\AddXmlDocumentationTransform.cs" /> <Compile Include="CSharp\Transforms\AddXmlDocumentationTransform.cs" />
<Compile Include="DecompileRun.cs" />
<Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" /> <Compile Include="Documentation\GetPotentiallyNestedClassTypeReference.cs" />
<Compile Include="Documentation\IdStringMemberReference.cs" /> <Compile Include="Documentation\IdStringMemberReference.cs" />
<Compile Include="Documentation\IdStringProvider.cs" /> <Compile Include="Documentation\IdStringProvider.cs" />

5
ICSharpCode.Decompiler/IL/ControlFlow/YieldReturnDecompiler.cs

@ -378,8 +378,9 @@ namespace ICSharpCode.Decompiler.IL.ControlFlow
} }
var il = new ILReader(typeSystem).ReadIL(method.Body, context.CancellationToken); var il = new ILReader(typeSystem).ReadIL(method.Body, context.CancellationToken);
il.RunTransforms(CSharpDecompiler.EarlyILTransforms(true), il.RunTransforms(CSharpDecompiler.EarlyILTransforms(true),
new ILTransformContext(il, typeSystem, context.RequiredNamespacesSuperset, context.Settings) { new ILTransformContext(il, typeSystem, context.Settings) {
CancellationToken = context.CancellationToken CancellationToken = context.CancellationToken,
DecompileRun = context.DecompileRun
}); });
return il; return il;
} }

5
ICSharpCode.Decompiler/IL/Transforms/DelegateConstruction.cs

@ -149,8 +149,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
v.Name = contextPrefix + v.Name; v.Name = contextPrefix + v.Name;
} }
var nestedContext = new ILTransformContext(function, localTypeSystem, context.RequiredNamespacesSuperset, context.Settings) { var nestedContext = new ILTransformContext(function, localTypeSystem, context.Settings) {
CancellationToken = context.CancellationToken CancellationToken = context.CancellationToken,
DecompileRun = context.DecompileRun
}; };
function.RunTransforms(CSharpDecompiler.GetILTransforms().TakeWhile(t => !(t is DelegateConstruction)), nestedContext); function.RunTransforms(CSharpDecompiler.GetILTransforms().TakeWhile(t => !(t is DelegateConstruction)), nestedContext);
function.AcceptVisitor(new ReplaceDelegateTargetVisitor(target, function.Variables.SingleOrDefault(v => v.Index == -1 && v.Kind == VariableKind.Parameter))); function.AcceptVisitor(new ReplaceDelegateTargetVisitor(target, function.Variables.SingleOrDefault(v => v.Index == -1 && v.Kind == VariableKind.Parameter)));

12
ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs

@ -17,10 +17,13 @@
// DEALINGS IN THE SOFTWARE. // DEALINGS IN THE SOFTWARE.
using System; using System;
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler.CSharp.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.IL.Transforms namespace ICSharpCode.Decompiler.IL.Transforms
{ {
@ -40,15 +43,16 @@ namespace ICSharpCode.Decompiler.IL.Transforms
public ILFunction Function { get; } public ILFunction Function { get; }
public IDecompilerTypeSystem TypeSystem { get; } public IDecompilerTypeSystem TypeSystem { get; }
public DecompilerSettings Settings { get; } public DecompilerSettings Settings { get; }
public IImmutableSet<string> RequiredNamespacesSuperset { get; }
public CancellationToken CancellationToken { get; set; } public CancellationToken CancellationToken { get; set; }
public Stepper Stepper { get; set; } public Stepper Stepper { get; set; }
public ILTransformContext(ILFunction function, IDecompilerTypeSystem typeSystem, IImmutableSet<string> requiredNamespaces, DecompilerSettings settings = null) internal DecompileRun DecompileRun { get; set; }
internal ResolvedUsingScope UsingScope => DecompileRun.UsingScope.Resolve(TypeSystem.Compilation);
public ILTransformContext(ILFunction function, IDecompilerTypeSystem typeSystem, DecompilerSettings settings = null)
{ {
this.Function = function ?? throw new ArgumentNullException(nameof(function)); this.Function = function ?? throw new ArgumentNullException(nameof(function));
this.TypeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem)); this.TypeSystem = typeSystem ?? throw new ArgumentNullException(nameof(typeSystem));
this.RequiredNamespacesSuperset = requiredNamespaces ?? throw new ArgumentNullException(nameof(requiredNamespaces));
this.Settings = settings ?? new DecompilerSettings(); this.Settings = settings ?? new DecompilerSettings();
Stepper = new Stepper(); Stepper = new Stepper();
} }
@ -58,7 +62,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
this.Function = context.Function; this.Function = context.Function;
this.TypeSystem = context.TypeSystem; this.TypeSystem = context.TypeSystem;
this.Settings = context.Settings; this.Settings = context.Settings;
this.RequiredNamespacesSuperset = context.RequiredNamespacesSuperset; this.DecompileRun = context.DecompileRun;
this.CancellationToken = context.CancellationToken; this.CancellationToken = context.CancellationToken;
this.Stepper = context.Stepper; this.Stepper = context.Stepper;
} }

19
ICSharpCode.Decompiler/IL/Transforms/NullPropagationTransform.cs

@ -246,28 +246,11 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var paramTypes = call.Method.Parameters.Skip(1).Select(p => new ResolveResult(p.Type)).ToArray(); var paramTypes = call.Method.Parameters.Skip(1).Select(p => new ResolveResult(p.Type)).ToArray();
var paramNames = call.Method.Parameters.SelectArray(p => p.Name); var paramNames = call.Method.Parameters.SelectArray(p => p.Name);
var typeArgs = call.Method.TypeArguments.ToArray(); var typeArgs = call.Method.TypeArguments.ToArray();
var usingScope = CreateUsingScope(context.RequiredNamespacesSuperset).Resolve(context.TypeSystem.Compilation); var resolveContext = new CSharp.TypeSystem.CSharpTypeResolveContext(context.TypeSystem.Compilation.MainAssembly, context.UsingScope);
var resolveContext = new CSharp.TypeSystem.CSharpTypeResolveContext(context.TypeSystem.Compilation.MainAssembly, usingScope);
var resolver = new CSharp.Resolver.CSharpResolver(resolveContext); var resolver = new CSharp.Resolver.CSharpResolver(resolveContext);
return CSharp.Transforms.IntroduceExtensionMethods.CanTransformToExtensionMethodCall(resolver, call.Method, typeArgs, targetType, paramTypes); return CSharp.Transforms.IntroduceExtensionMethods.CanTransformToExtensionMethodCall(resolver, call.Method, typeArgs, targetType, paramTypes);
} }
CSharp.TypeSystem.UsingScope CreateUsingScope(IImmutableSet<string> requiredNamespacesSuperset)
{
var usingScope = new CSharp.TypeSystem.UsingScope();
foreach (var ns in requiredNamespacesSuperset) {
string[] parts = ns.Split('.');
AstType nsType = new SimpleType(parts[0]);
for (int i = 1; i < parts.Length; i++) {
nsType = new MemberType { Target = nsType, MemberName = parts[i] };
}
var reference = nsType.ToTypeReference(CSharp.Resolver.NameLookupMode.TypeInUsingDeclaration) as CSharp.TypeSystem.TypeOrNamespaceReference;
if (reference != null)
usingScope.Usings.Add(reference);
}
return usingScope;
}
static bool IsGetter(IMethod method) static bool IsGetter(IMethod method)
{ {
return method.AccessorOwner is IProperty p && p.Getter == method; return method.AccessorOwner is IProperty p && p.Getter == method;

5
ICSharpCode.Decompiler/IL/Transforms/ProxyCallReplacer.cs

@ -21,8 +21,9 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var ilReader = new ILReader(specializingTypeSystem); var ilReader = new ILReader(specializingTypeSystem);
System.Threading.CancellationToken cancellationToken = new System.Threading.CancellationToken(); System.Threading.CancellationToken cancellationToken = new System.Threading.CancellationToken();
var proxyFunction = ilReader.ReadIL(methodDef.Body, cancellationToken); var proxyFunction = ilReader.ReadIL(methodDef.Body, cancellationToken);
var transformContext = new ILTransformContext(proxyFunction, specializingTypeSystem, context.RequiredNamespacesSuperset, this.context.Settings) { var transformContext = new ILTransformContext(proxyFunction, specializingTypeSystem, this.context.Settings) {
CancellationToken = cancellationToken CancellationToken = cancellationToken,
DecompileRun = context.DecompileRun
}; };
foreach (var transform in CSharp.CSharpDecompiler.GetILTransforms()) { foreach (var transform in CSharp.CSharpDecompiler.GetILTransforms()) {
if (transform.GetType() != typeof(ProxyCallReplacer)) { // don't call itself on itself if (transform.GetType() != typeof(ProxyCallReplacer)) { // don't call itself on itself

2
ILSpy.BamlDecompiler/ConnectMethodDecompiler.cs

@ -61,7 +61,7 @@ namespace ILSpy.BamlDecompiler
var ilReader = new ILReader(typeSystem); var ilReader = new ILReader(typeSystem);
var function = ilReader.ReadIL(method.Body, cancellationToken); var function = ilReader.ReadIL(method.Body, cancellationToken);
var context = new ILTransformContext(function, typeSystem, ImmutableHashSet<string>.Empty) { var context = new ILTransformContext(function, typeSystem) {
CancellationToken = cancellationToken CancellationToken = cancellationToken
}; };
function.RunTransforms(CSharpDecompiler.GetILTransforms(), context); function.RunTransforms(CSharpDecompiler.GetILTransforms(), context);

6
ILSpy/Languages/ILAstLanguage.cs

@ -118,10 +118,8 @@ namespace ICSharpCode.ILSpy
reader.UseDebugSymbols = options.DecompilerSettings.UseDebugSymbols; reader.UseDebugSymbols = options.DecompilerSettings.UseDebugSymbols;
ILFunction il = reader.ReadIL(method.Body, options.CancellationToken); ILFunction il = reader.ReadIL(method.Body, options.CancellationToken);
var namespaces = new HashSet<string>(); var namespaces = new HashSet<string>();
CSharpDecompiler.CollectNamespacesForDecompilation(new[] { method }, namespaces); var decompiler = new CSharpDecompiler(typeSystem, options.DecompilerSettings) { CancellationToken = options.CancellationToken };
ILTransformContext context = new ILTransformContext(il, typeSystem, namespaces.ToImmutableHashSet(), options.DecompilerSettings) { ILTransformContext context = decompiler.CreateILTransformContext(il);
CancellationToken = options.CancellationToken
};
context.Stepper.StepLimit = options.StepLimit; context.Stepper.StepLimit = options.StepLimit;
context.Stepper.IsDebug = options.IsDebug; context.Stepper.IsDebug = options.IsDebug;
try { try {

Loading…
Cancel
Save