Browse Source

Remove UnresolvedUsingScope

pull/3532/head
Siegfried Pammer 5 months ago
parent
commit
c9e3790adc
  1. 56
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 1
      ICSharpCode.Decompiler/CSharp/CallBuilder.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs
  4. 34
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs
  5. 86
      ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs
  6. 143
      ICSharpCode.Decompiler/CSharp/TypeSystem/ResolvedUsingScope.cs
  7. 167
      ICSharpCode.Decompiler/CSharp/TypeSystem/UsingScope.cs
  8. 30
      ICSharpCode.Decompiler/DecompileRun.cs
  9. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  10. 2
      ICSharpCode.Decompiler/IL/Transforms/IILTransform.cs
  11. 3
      ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

56
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -18,6 +18,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
@ -30,6 +31,7 @@ using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Resolver; using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Transforms; using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.CSharp.TypeSystem;
using ICSharpCode.Decompiler.DebugInfo; using ICSharpCode.Decompiler.DebugInfo;
using ICSharpCode.Decompiler.Disassembler; using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.Documentation;
@ -518,11 +520,28 @@ namespace ICSharpCode.Decompiler.CSharp
} }
} }
DecompileRun CreateDecompileRun() DecompileRun CreateDecompileRun(HashSet<string> namespaces)
{ {
return new DecompileRun(settings) { List<INamespace> resolvedNamespaces = new List<INamespace>();
foreach (var ns in namespaces)
{
var resolvedNamespace = typeSystem.GetNamespaceByFullName(ns);
if (resolvedNamespace != null)
{
resolvedNamespaces.Add(resolvedNamespace);
}
}
ResolvedUsingScope usingScope = new ResolvedUsingScope(
new CSharpTypeResolveContext(typeSystem.MainModule),
typeSystem.RootNamespace,
resolvedNamespaces.ToImmutableArray()
);
return new DecompileRun(settings, usingScope) {
DocumentationProvider = DocumentationProvider ?? CreateDefaultDocumentationProvider(), DocumentationProvider = DocumentationProvider ?? CreateDefaultDocumentationProvider(),
CancellationToken = CancellationToken CancellationToken = CancellationToken,
Namespaces = namespaces
}; };
} }
@ -554,9 +573,10 @@ namespace ICSharpCode.Decompiler.CSharp
public SyntaxTree DecompileModuleAndAssemblyAttributes() public SyntaxTree DecompileModuleAndAssemblyAttributes()
{ {
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule); var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
DecompileRun decompileRun = CreateDecompileRun(); var namespaces = new HashSet<string>();
syntaxTree = new SyntaxTree(); syntaxTree = new SyntaxTree();
RequiredNamespaceCollector.CollectAttributeNamespaces(module, decompileRun.Namespaces); RequiredNamespaceCollector.CollectAttributeNamespaces(module, namespaces);
DecompileRun decompileRun = CreateDecompileRun(namespaces);
DoDecompileModuleAndAssemblyAttributes(decompileRun, decompilationContext, syntaxTree); DoDecompileModuleAndAssemblyAttributes(decompileRun, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompileRun, decompilationContext); RunTransforms(syntaxTree, decompileRun, decompilationContext);
return syntaxTree; return syntaxTree;
@ -640,9 +660,10 @@ namespace ICSharpCode.Decompiler.CSharp
public SyntaxTree DecompileWholeModuleAsSingleFile(bool sortTypes) public SyntaxTree DecompileWholeModuleAsSingleFile(bool sortTypes)
{ {
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule); var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
var decompileRun = CreateDecompileRun();
syntaxTree = new SyntaxTree(); syntaxTree = new SyntaxTree();
RequiredNamespaceCollector.CollectNamespaces(module, decompileRun.Namespaces); var namespaces = new HashSet<string>();
RequiredNamespaceCollector.CollectNamespaces(module, namespaces);
var decompileRun = CreateDecompileRun(namespaces);
DoDecompileModuleAndAssemblyAttributes(decompileRun, decompilationContext, syntaxTree); DoDecompileModuleAndAssemblyAttributes(decompileRun, decompilationContext, syntaxTree);
var typeDefs = metadata.GetTopLevelTypeDefinitions(); var typeDefs = metadata.GetTopLevelTypeDefinitions();
if (sortTypes) if (sortTypes)
@ -662,8 +683,9 @@ namespace ICSharpCode.Decompiler.CSharp
/// </summary> /// </summary>
public ILTransformContext CreateILTransformContext(ILFunction function) public ILTransformContext CreateILTransformContext(ILFunction function)
{ {
var decompileRun = CreateDecompileRun(); var namespaces = new HashSet<string>();
RequiredNamespaceCollector.CollectNamespaces(function.Method, module, decompileRun.Namespaces); RequiredNamespaceCollector.CollectNamespaces(function.Method, module, namespaces);
var decompileRun = CreateDecompileRun(namespaces);
return new ILTransformContext(function, typeSystem, DebugInfoProvider, settings) { return new ILTransformContext(function, typeSystem, DebugInfoProvider, settings) {
CancellationToken = CancellationToken, CancellationToken = CancellationToken,
DecompileRun = decompileRun DecompileRun = decompileRun
@ -907,17 +929,17 @@ 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.MainModule); var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
var decompileRun = CreateDecompileRun();
syntaxTree = new SyntaxTree(); syntaxTree = new SyntaxTree();
var namespaces = new HashSet<string>();
foreach (var type in types) foreach (var type in types)
{ {
CancellationToken.ThrowIfCancellationRequested(); CancellationToken.ThrowIfCancellationRequested();
if (type.IsNil) if (type.IsNil)
throw new ArgumentException("types contains null element"); throw new ArgumentException("types contains null element");
RequiredNamespaceCollector.CollectNamespaces(type, module, decompileRun.Namespaces); RequiredNamespaceCollector.CollectNamespaces(type, module, namespaces);
} }
var decompileRun = CreateDecompileRun(namespaces);
DoDecompileTypes(types, decompileRun, decompilationContext, syntaxTree); DoDecompileTypes(types, decompileRun, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompileRun, decompilationContext); RunTransforms(syntaxTree, decompileRun, decompilationContext);
return syntaxTree; return syntaxTree;
@ -949,9 +971,10 @@ namespace ICSharpCode.Decompiler.CSharp
if (type.ParentModule != typeSystem.MainModule) if (type.ParentModule != typeSystem.MainModule)
throw new NotSupportedException($"Type {fullTypeName} was not found in the module being decompiled, but only in {type.ParentModule.Name}"); throw new NotSupportedException($"Type {fullTypeName} was not found in the module being decompiled, but only in {type.ParentModule.Name}");
var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule); var decompilationContext = new SimpleTypeResolveContext(typeSystem.MainModule);
var decompileRun = CreateDecompileRun(); var namespaces = new HashSet<string>();
syntaxTree = new SyntaxTree(); syntaxTree = new SyntaxTree();
RequiredNamespaceCollector.CollectNamespaces(type.MetadataToken, module, decompileRun.Namespaces); RequiredNamespaceCollector.CollectNamespaces(type.MetadataToken, module, namespaces);
var decompileRun = CreateDecompileRun(namespaces);
DoDecompileTypes(new[] { (TypeDefinitionHandle)type.MetadataToken }, decompileRun, decompilationContext, syntaxTree); DoDecompileTypes(new[] { (TypeDefinitionHandle)type.MetadataToken }, decompileRun, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompileRun, decompilationContext); RunTransforms(syntaxTree, decompileRun, decompilationContext);
return syntaxTree; return syntaxTree;
@ -984,13 +1007,14 @@ namespace ICSharpCode.Decompiler.CSharp
if (definitions == null) if (definitions == null)
throw new ArgumentNullException(nameof(definitions)); throw new ArgumentNullException(nameof(definitions));
syntaxTree = new SyntaxTree(); syntaxTree = new SyntaxTree();
var decompileRun = CreateDecompileRun(); var namespaces = new HashSet<string>();
foreach (var entity in definitions) foreach (var entity in definitions)
{ {
if (entity.IsNil) if (entity.IsNil)
throw new ArgumentException("definitions contains null element"); throw new ArgumentException("definitions contains null element");
RequiredNamespaceCollector.CollectNamespaces(entity, module, decompileRun.Namespaces); RequiredNamespaceCollector.CollectNamespaces(entity, module, namespaces);
} }
var decompileRun = CreateDecompileRun(namespaces);
bool first = true; bool first = true;
ITypeDefinition parentTypeDef = null; ITypeDefinition parentTypeDef = null;

1
ICSharpCode.Decompiler/CSharp/CallBuilder.cs

@ -2051,7 +2051,6 @@ namespace ICSharpCode.Decompiler.CSharp
if (isExtensionMethodReference) if (isExtensionMethodReference)
{ {
var resolver = this.resolver.WithCurrentUsingScope(this.expressionBuilder.statementBuilder.decompileRun.UsingScope.Resolve(this.resolver.Compilation));
result = resolver.ResolveMemberAccess(target, method.Name, typeArguments, NameLookupMode.InvocationTarget) as MethodGroupResolveResult; result = resolver.ResolveMemberAccess(target, method.Name, typeArguments, NameLookupMode.InvocationTarget) as MethodGroupResolveResult;
if (result == null) if (result == null)
return false; return false;

2
ICSharpCode.Decompiler/CSharp/ExpressionBuilder.cs

@ -97,7 +97,7 @@ namespace ICSharpCode.Decompiler.CSharp
this.compilation = decompilationContext.Compilation; this.compilation = decompilationContext.Compilation;
this.resolver = new CSharpResolver(new CSharpTypeResolveContext( this.resolver = new CSharpResolver(new CSharpTypeResolveContext(
compilation.MainModule, compilation.MainModule,
decompileRun.UsingScope.Resolve(compilation), decompileRun.UsingScope,
decompilationContext.CurrentTypeDefinition, decompilationContext.CurrentTypeDefinition,
decompilationContext.CurrentMember decompilationContext.CurrentMember
)); ));

34
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceExtensionMethods.cs

@ -42,63 +42,53 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {
this.context = context; this.context = context;
this.conversions = CSharpConversions.Get(context.TypeSystem); this.conversions = CSharpConversions.Get(context.TypeSystem);
InitializeContext(rootNode.Annotation<UsingScope>()); InitializeContext(rootNode.Annotation<ResolvedUsingScope>());
rootNode.AcceptVisitor(this); rootNode.AcceptVisitor(this);
} }
Stack<CSharpTypeResolveContext> resolveContextStack = new Stack<CSharpTypeResolveContext>(); void InitializeContext(ResolvedUsingScope usingScope)
void InitializeContext(UsingScope usingScope)
{ {
this.resolveContextStack = new Stack<CSharpTypeResolveContext>();
if (!string.IsNullOrEmpty(context.CurrentTypeDefinition?.Namespace)) if (!string.IsNullOrEmpty(context.CurrentTypeDefinition?.Namespace))
{ {
foreach (string ns in context.CurrentTypeDefinition.Namespace.Split('.')) foreach (string ns in context.CurrentTypeDefinition.Namespace.Split('.'))
{ {
usingScope = new UsingScope(usingScope, ns); usingScope = usingScope.WithNestedNamespace(ns);
} }
} }
var currentContext = new CSharpTypeResolveContext(context.TypeSystem.MainModule, usingScope.Resolve(context.TypeSystem), context.CurrentTypeDefinition); var currentContext = new CSharpTypeResolveContext(context.TypeSystem.MainModule, usingScope, context.CurrentTypeDefinition);
this.resolveContextStack.Push(currentContext);
this.resolver = new CSharpResolver(currentContext); this.resolver = new CSharpResolver(currentContext);
} }
public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration) public override void VisitNamespaceDeclaration(NamespaceDeclaration namespaceDeclaration)
{ {
var previousContext = resolveContextStack.Peek(); var usingScope = resolver.CurrentUsingScope;
var usingScope = previousContext.CurrentUsingScope.UnresolvedUsingScope;
foreach (string ident in namespaceDeclaration.Identifiers) foreach (string ident in namespaceDeclaration.Identifiers)
{ {
usingScope = new UsingScope(usingScope, ident); usingScope = usingScope.WithNestedNamespace(ident);
} }
var currentContext = new CSharpTypeResolveContext(previousContext.CurrentModule, usingScope.Resolve(previousContext.Compilation)); var previousResolver = this.resolver;
resolveContextStack.Push(currentContext);
try try
{ {
this.resolver = new CSharpResolver(currentContext); this.resolver = this.resolver.WithCurrentUsingScope(usingScope);
base.VisitNamespaceDeclaration(namespaceDeclaration); base.VisitNamespaceDeclaration(namespaceDeclaration);
} }
finally finally
{ {
this.resolver = new CSharpResolver(previousContext); this.resolver = previousResolver;
resolveContextStack.Pop();
} }
} }
public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration) public override void VisitTypeDeclaration(TypeDeclaration typeDeclaration)
{ {
var previousContext = resolveContextStack.Peek(); var previousResolver = this.resolver;
var currentContext = previousContext.WithCurrentTypeDefinition(typeDeclaration.GetSymbol() as ITypeDefinition); this.resolver = resolver.WithCurrentTypeDefinition(typeDeclaration.GetSymbol() as ITypeDefinition);
resolveContextStack.Push(currentContext);
try try
{ {
this.resolver = new CSharpResolver(currentContext);
base.VisitTypeDeclaration(typeDeclaration); base.VisitTypeDeclaration(typeDeclaration);
} }
finally finally
{ {
this.resolver = new CSharpResolver(previousContext); this.resolver = previousResolver;
resolveContextStack.Pop();
} }
} }

86
ICSharpCode.Decompiler/CSharp/Transforms/IntroduceUsingDeclarations.cs

@ -18,6 +18,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
@ -42,8 +43,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
var requiredImports = new FindRequiredImports(context); var requiredImports = new FindRequiredImports(context);
rootNode.AcceptVisitor(requiredImports); rootNode.AcceptVisitor(requiredImports);
var usingScope = new UsingScope(); List<INamespace> resolvedNamespaces = new List<INamespace>();
rootNode.AddAnnotation(usingScope);
if (context.Settings.UsingDeclarations) if (context.Settings.UsingDeclarations)
{ {
@ -64,12 +64,22 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {
nsType = new MemberType { Target = nsType, MemberName = parts[i] }; nsType = new MemberType { Target = nsType, MemberName = parts[i] };
} }
if (nsType.ToTypeReference(NameLookupMode.TypeInUsingDeclaration) is TypeOrNamespaceReference reference) var resolvedNamespace = context.TypeSystem.GetNamespaceByFullName(ns);
usingScope.Usings.Add(reference); if (resolvedNamespace != null)
{
resolvedNamespaces.Add(resolvedNamespace);
}
rootNode.InsertChildAfter(insertionPoint, new UsingDeclaration { Import = nsType }, SyntaxTree.MemberRole); rootNode.InsertChildAfter(insertionPoint, new UsingDeclaration { Import = nsType }, SyntaxTree.MemberRole);
} }
} }
var usingScope = new ResolvedUsingScope(
new CSharpTypeResolveContext(context.TypeSystem.MainModule),
context.TypeSystem.RootNamespace,
resolvedNamespaces.ToImmutableArray()
);
rootNode.AddAnnotation(usingScope);
// verify that the SimpleTypes refer to the correct type (no ambiguities) // verify that the SimpleTypes refer to the correct type (no ambiguities)
rootNode.AcceptVisitor(new FullyQualifyAmbiguousTypeNamesVisitor(context, usingScope)); rootNode.AcceptVisitor(new FullyQualifyAmbiguousTypeNamesVisitor(context, usingScope));
} }
@ -173,41 +183,35 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
sealed class FullyQualifyAmbiguousTypeNamesVisitor : DepthFirstAstVisitor sealed class FullyQualifyAmbiguousTypeNamesVisitor : DepthFirstAstVisitor
{ {
readonly Stack<CSharpTypeResolveContext> context;
readonly bool ignoreUsingScope; readonly bool ignoreUsingScope;
readonly DecompilerSettings settings; readonly DecompilerSettings settings;
CSharpResolver resolver;
TypeSystemAstBuilder astBuilder; TypeSystemAstBuilder astBuilder;
public FullyQualifyAmbiguousTypeNamesVisitor(TransformContext context, UsingScope usingScope) public FullyQualifyAmbiguousTypeNamesVisitor(TransformContext context, ResolvedUsingScope usingScope)
{ {
this.ignoreUsingScope = !context.Settings.UsingDeclarations; this.ignoreUsingScope = !context.Settings.UsingDeclarations;
this.settings = context.Settings; this.settings = context.Settings;
this.resolver = new CSharpResolver(new CSharpTypeResolveContext(context.TypeSystem.MainModule));
CSharpTypeResolveContext currentContext; if (!ignoreUsingScope)
if (ignoreUsingScope)
{
currentContext = new CSharpTypeResolveContext(context.TypeSystem.MainModule);
}
else
{ {
this.context = new Stack<CSharpTypeResolveContext>();
if (!string.IsNullOrEmpty(context.CurrentTypeDefinition?.Namespace)) if (!string.IsNullOrEmpty(context.CurrentTypeDefinition?.Namespace))
{ {
foreach (string ns in context.CurrentTypeDefinition.Namespace.Split('.')) foreach (string ns in context.CurrentTypeDefinition.Namespace.Split('.'))
{ {
usingScope = new UsingScope(usingScope, ns); usingScope = usingScope.WithNestedNamespace(ns);
} }
} }
currentContext = new CSharpTypeResolveContext(context.TypeSystem.MainModule, usingScope.Resolve(context.TypeSystem), context.CurrentTypeDefinition); this.resolver = this.resolver.WithCurrentUsingScope(usingScope)
this.context.Push(currentContext); .WithCurrentTypeDefinition(context.CurrentTypeDefinition);
} }
this.astBuilder = CreateAstBuilder(currentContext); this.astBuilder = CreateAstBuilder(resolver);
} }
TypeSystemAstBuilder CreateAstBuilder(CSharpTypeResolveContext context, IL.ILFunction function = null) TypeSystemAstBuilder CreateAstBuilder(CSharpResolver resolver, IL.ILFunction function = null)
{ {
CSharpResolver resolver = new CSharpResolver(context);
if (function != null) if (function != null)
{ {
var variables = new Dictionary<string, IVariable>(); var variables = new Dictionary<string, IVariable>();
@ -234,23 +238,23 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
base.VisitNamespaceDeclaration(namespaceDeclaration); base.VisitNamespaceDeclaration(namespaceDeclaration);
return; return;
} }
var previousContext = context.Peek(); var previousResolver = resolver;
var usingScope = previousContext.CurrentUsingScope.UnresolvedUsingScope; var previousAstBuilder = astBuilder;
var usingScope = resolver.CurrentUsingScope;
foreach (string ident in namespaceDeclaration.Identifiers) foreach (string ident in namespaceDeclaration.Identifiers)
{ {
usingScope = new UsingScope(usingScope, ident); usingScope = usingScope.WithNestedNamespace(ident);
} }
var currentContext = new CSharpTypeResolveContext(previousContext.CurrentModule, usingScope.Resolve(previousContext.Compilation)); resolver = resolver.WithCurrentUsingScope(usingScope);
context.Push(currentContext);
try try
{ {
astBuilder = CreateAstBuilder(currentContext); astBuilder = CreateAstBuilder(resolver);
base.VisitNamespaceDeclaration(namespaceDeclaration); base.VisitNamespaceDeclaration(namespaceDeclaration);
} }
finally finally
{ {
astBuilder = CreateAstBuilder(previousContext); astBuilder = previousAstBuilder;
context.Pop(); resolver = previousResolver;
} }
} }
@ -261,18 +265,18 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
base.VisitTypeDeclaration(typeDeclaration); base.VisitTypeDeclaration(typeDeclaration);
return; return;
} }
var previousContext = context.Peek(); var previousResolver = resolver;
var currentContext = previousContext.WithCurrentTypeDefinition(typeDeclaration.GetSymbol() as ITypeDefinition); var previousAstBuilder = astBuilder;
context.Push(currentContext); resolver = resolver.WithCurrentTypeDefinition(typeDeclaration.GetSymbol() as ITypeDefinition);
try try
{ {
astBuilder = CreateAstBuilder(currentContext); astBuilder = CreateAstBuilder(resolver);
base.VisitTypeDeclaration(typeDeclaration); base.VisitTypeDeclaration(typeDeclaration);
} }
finally finally
{ {
astBuilder = CreateAstBuilder(previousContext); astBuilder = previousAstBuilder;
context.Pop(); resolver = previousResolver;
} }
} }
@ -310,27 +314,27 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
} }
if (entityDeclaration.GetSymbol() is IMethod method) if (entityDeclaration.GetSymbol() is IMethod method)
{ {
var previousContext = context.Peek(); var previousResolver = resolver;
CSharpTypeResolveContext currentContext; var previousAstBuilder = astBuilder;
if (CSharpDecompiler.IsWindowsFormsInitializeComponentMethod(method)) if (CSharpDecompiler.IsWindowsFormsInitializeComponentMethod(method))
{ {
currentContext = new CSharpTypeResolveContext(previousContext.CurrentModule); var currentContext = new CSharpTypeResolveContext(previousResolver.Compilation.MainModule);
resolver = new CSharpResolver(currentContext);
} }
else else
{ {
currentContext = previousContext.WithCurrentMember(method); resolver = resolver.WithCurrentMember(method);
} }
context.Push(currentContext);
try try
{ {
var function = entityDeclaration.Annotation<IL.ILFunction>(); var function = entityDeclaration.Annotation<IL.ILFunction>();
astBuilder = CreateAstBuilder(currentContext, function); astBuilder = CreateAstBuilder(resolver, function);
baseCall(entityDeclaration); baseCall(entityDeclaration);
} }
finally finally
{ {
astBuilder = CreateAstBuilder(previousContext); resolver = previousResolver;
context.Pop(); astBuilder = previousAstBuilder;
} }
} }
else else

143
ICSharpCode.Decompiler/CSharp/TypeSystem/ResolvedUsingScope.cs

@ -19,153 +19,60 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.Immutable;
using System.Diagnostics;
using ICSharpCode.Decompiler.CSharp.Resolver;
using ICSharpCode.Decompiler.CSharp.Syntax; using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Semantics; using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
#nullable enable
namespace ICSharpCode.Decompiler.CSharp.TypeSystem namespace ICSharpCode.Decompiler.CSharp.TypeSystem
{ {
/// <summary> /// <summary>
/// Resolved version of using scope. /// Represents a scope that contains "using" statements.
/// This is either the mo itself, or a namespace declaration.
/// </summary> /// </summary>
public class ResolvedUsingScope public class ResolvedUsingScope
{ {
readonly CSharpTypeResolveContext parentContext; readonly CSharpTypeResolveContext parentContext;
readonly UsingScope usingScope;
internal readonly ConcurrentDictionary<string, ResolveResult> ResolveCache = new ConcurrentDictionary<string, ResolveResult>(); internal readonly ConcurrentDictionary<string, ResolveResult> ResolveCache = new ConcurrentDictionary<string, ResolveResult>();
internal List<List<IMethod>> AllExtensionMethods; internal List<List<IMethod>>? AllExtensionMethods;
public ResolvedUsingScope(CSharpTypeResolveContext context, UsingScope usingScope) public ResolvedUsingScope(CSharpTypeResolveContext context, INamespace @namespace, ImmutableArray<INamespace> usings)
{ {
if (context == null) this.parentContext = context ?? throw new ArgumentNullException(nameof(context));
throw new ArgumentNullException(nameof(context)); this.Usings = usings;
if (usingScope == null) this.Namespace = @namespace ?? throw new ArgumentNullException(nameof(@namespace));
throw new ArgumentNullException(nameof(usingScope));
this.parentContext = context;
this.usingScope = usingScope;
if (usingScope.Parent != null)
{
if (context.CurrentUsingScope == null)
throw new InvalidOperationException();
}
else
{
if (context.CurrentUsingScope != null)
throw new InvalidOperationException();
}
} }
public UsingScope UnresolvedUsingScope { public INamespace Namespace { get; }
get { return usingScope; }
}
INamespace @namespace;
public INamespace Namespace {
get {
INamespace result = LazyInit.VolatileRead(ref this.@namespace);
if (result != null)
{
return result;
}
else
{
if (parentContext.CurrentUsingScope != null)
{
result = parentContext.CurrentUsingScope.Namespace.GetChildNamespace(usingScope.ShortNamespaceName);
if (result == null)
result = new DummyNamespace(parentContext.CurrentUsingScope.Namespace, usingScope.ShortNamespaceName);
}
else
{
result = parentContext.Compilation.RootNamespace;
}
Debug.Assert(result != null);
return LazyInit.GetOrSet(ref this.@namespace, result);
}
}
}
public ResolvedUsingScope Parent { public ResolvedUsingScope Parent {
get { return parentContext.CurrentUsingScope; } get { return parentContext.CurrentUsingScope; }
} }
IList<INamespace> usings; public ImmutableArray<INamespace> Usings { get; }
public IList<INamespace> Usings {
get {
var result = LazyInit.VolatileRead(ref this.usings);
if (result != null)
{
return result;
}
else
{
result = new List<INamespace>();
CSharpResolver resolver = new CSharpResolver(parentContext.WithUsingScope(this));
foreach (var u in usingScope.Usings)
{
INamespace ns = u.ResolveNamespace(resolver);
if (ns != null && !result.Contains(ns))
result.Add(ns);
}
return LazyInit.GetOrSet(ref this.usings, new ReadOnlyCollection<INamespace>(result));
}
}
}
IList<KeyValuePair<string, ResolveResult>> usingAliases; public IReadOnlyList<KeyValuePair<string, ResolveResult>> UsingAliases => [];
public IList<KeyValuePair<string, ResolveResult>> UsingAliases {
get {
var result = LazyInit.VolatileRead(ref this.usingAliases);
if (result != null)
{
return result;
}
else
{
CSharpResolver resolver = new CSharpResolver(parentContext.WithUsingScope(this));
result = new KeyValuePair<string, ResolveResult>[usingScope.UsingAliases.Count];
for (int i = 0; i < result.Count; i++)
{
var rr = usingScope.UsingAliases[i].Value.Resolve(resolver);
if (rr is TypeResolveResult)
{
rr = new AliasTypeResolveResult(usingScope.UsingAliases[i].Key, (TypeResolveResult)rr);
}
else if (rr is NamespaceResolveResult)
{
rr = new AliasNamespaceResolveResult(usingScope.UsingAliases[i].Key, (NamespaceResolveResult)rr);
}
result[i] = new KeyValuePair<string, ResolveResult>(
usingScope.UsingAliases[i].Key,
rr
);
}
return LazyInit.GetOrSet(ref this.usingAliases, result);
}
}
}
public IList<string> ExternAliases { public IReadOnlyList<string> ExternAliases => [];
get { return usingScope.ExternAliases; }
}
/// <summary> /// <summary>
/// Gets whether this using scope has an alias (either using or extern) /// Gets whether this using scope has an alias (either using or extern)
/// with the specified name. /// with the specified name.
/// </summary> /// </summary>
public bool HasAlias(string identifier) public bool HasAlias(string identifier) => false;
internal ResolvedUsingScope WithNestedNamespace(string simpleName)
{ {
return usingScope.HasAlias(identifier); var ns = Namespace.GetChildNamespace(simpleName) ?? new DummyNamespace(Namespace, simpleName);
return new ResolvedUsingScope(
parentContext.WithUsingScope(this),
ns,
[]);
} }
sealed class DummyNamespace : INamespace sealed class DummyNamespace : INamespace
@ -179,7 +86,7 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem
this.name = name; this.name = name;
} }
public string ExternAlias { get; set; } string INamespace.ExternAlias => "";
string INamespace.FullName { string INamespace.FullName {
get { return NamespaceDeclaration.BuildQualifiedName(parentNamespace.FullName, name); } get { return NamespaceDeclaration.BuildQualifiedName(parentNamespace.FullName, name); }
@ -213,12 +120,12 @@ namespace ICSharpCode.Decompiler.CSharp.TypeSystem
get { return parentNamespace.Compilation; } get { return parentNamespace.Compilation; }
} }
INamespace INamespace.GetChildNamespace(string name) INamespace? INamespace.GetChildNamespace(string name)
{ {
return null; return null;
} }
ITypeDefinition INamespace.GetTypeDefinition(string name, int typeParameterCount) ITypeDefinition? INamespace.GetTypeDefinition(string name, int typeParameterCount)
{ {
return null; return null;
} }

167
ICSharpCode.Decompiler/CSharp/TypeSystem/UsingScope.cs

@ -1,167 +0,0 @@
// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team
//
// 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 System.Collections.Generic;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.CSharp.TypeSystem
{
/// <summary>
/// Represents a scope that contains "using" statements.
/// This is either the file itself, or a namespace declaration.
/// </summary>
[Serializable]
public class UsingScope : AbstractFreezable
{
readonly UsingScope parent;
string shortName = "";
IList<TypeOrNamespaceReference> usings;
IList<KeyValuePair<string, TypeOrNamespaceReference>> usingAliases;
IList<string> externAliases;
protected override void FreezeInternal()
{
usings = FreezableHelper.FreezeList(usings);
usingAliases = FreezableHelper.FreezeList(usingAliases);
externAliases = FreezableHelper.FreezeList(externAliases);
// In current model (no child scopes), it makes sense to freeze the parent as well
// to ensure the whole lookup chain is immutable.
if (parent != null)
parent.Freeze();
base.FreezeInternal();
}
/// <summary>
/// Creates a new root using scope.
/// </summary>
public UsingScope()
{
}
/// <summary>
/// Creates a new nested using scope.
/// </summary>
/// <param name="parent">The parent using scope.</param>
/// <param name="shortName">The short namespace name.</param>
public UsingScope(UsingScope parent, string shortName)
{
if (parent == null)
throw new ArgumentNullException(nameof(parent));
if (shortName == null)
throw new ArgumentNullException(nameof(shortName));
this.parent = parent;
this.shortName = shortName;
}
public UsingScope Parent {
get { return parent; }
}
public string ShortNamespaceName {
get {
return shortName;
}
}
public string NamespaceName {
get {
if (parent != null)
return NamespaceDeclaration.BuildQualifiedName(parent.NamespaceName, shortName);
else
return shortName;
}
// set {
// if (value == null)
// throw new ArgumentNullException("NamespaceName");
// FreezableHelper.ThrowIfFrozen(this);
// namespaceName = value;
// }
}
public IList<TypeOrNamespaceReference> Usings {
get {
if (usings == null)
usings = new List<TypeOrNamespaceReference>();
return usings;
}
}
public IList<KeyValuePair<string, TypeOrNamespaceReference>> UsingAliases {
get {
if (usingAliases == null)
usingAliases = new List<KeyValuePair<string, TypeOrNamespaceReference>>();
return usingAliases;
}
}
public IList<string> ExternAliases {
get {
if (externAliases == null)
externAliases = new List<string>();
return externAliases;
}
}
// public IList<UsingScope> ChildScopes {
// get {
// if (childScopes == null)
// childScopes = new List<UsingScope>();
// return childScopes;
// }
// }
/// <summary>
/// Gets whether this using scope has an alias (either using or extern)
/// with the specified name.
/// </summary>
public bool HasAlias(string identifier)
{
if (usingAliases != null)
{
foreach (var pair in usingAliases)
{
if (pair.Key == identifier)
return true;
}
}
return externAliases != null && externAliases.Contains(identifier);
}
/// <summary>
/// Resolves the namespace represented by this using scope.
/// </summary>
public ResolvedUsingScope Resolve(ICompilation compilation)
{
CacheManager cache = compilation.CacheManager;
ResolvedUsingScope resolved = cache.GetShared(this) as ResolvedUsingScope;
if (resolved == null)
{
var csContext = new CSharpTypeResolveContext(compilation.MainModule, parent != null ? parent.Resolve(compilation) : null);
resolved = (ResolvedUsingScope)cache.GetOrAddShared(this, new ResolvedUsingScope(csContext, this));
}
return resolved;
}
}
}

30
ICSharpCode.Decompiler/DecompileRun.cs

@ -21,7 +21,6 @@ using System.Collections.Generic;
using System.Threading; using System.Threading;
using ICSharpCode.Decompiler.CSharp; using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Documentation; using ICSharpCode.Decompiler.Documentation;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
@ -30,7 +29,7 @@ namespace ICSharpCode.Decompiler
internal class DecompileRun internal class DecompileRun
{ {
public HashSet<string> DefinedSymbols { get; } = new HashSet<string>(); public HashSet<string> DefinedSymbols { get; } = new HashSet<string>();
public HashSet<string> Namespaces { get; } = new HashSet<string>(); public HashSet<string> Namespaces { get; set; }
public CancellationToken CancellationToken { get; set; } public CancellationToken CancellationToken { get; set; }
public DecompilerSettings Settings { get; } public DecompilerSettings Settings { get; }
public IDocumentationProvider DocumentationProvider { get; set; } public IDocumentationProvider DocumentationProvider { get; set; }
@ -38,33 +37,12 @@ namespace ICSharpCode.Decompiler
public Dictionary<ITypeDefinition, bool> TypeHierarchyIsKnown { get; } = new(); public Dictionary<ITypeDefinition, bool> TypeHierarchyIsKnown { get; } = new();
Lazy<CSharp.TypeSystem.UsingScope> usingScope => public CSharp.TypeSystem.ResolvedUsingScope UsingScope { get; }
new Lazy<CSharp.TypeSystem.UsingScope>(() => CreateUsingScope(Namespaces));
public CSharp.TypeSystem.UsingScope UsingScope => usingScope.Value; public DecompileRun(DecompilerSettings settings, CSharp.TypeSystem.ResolvedUsingScope usingScope)
public DecompileRun(DecompilerSettings settings)
{ {
this.Settings = settings ?? throw new ArgumentNullException(nameof(settings)); this.Settings = settings ?? throw new ArgumentNullException(nameof(settings));
} this.UsingScope = usingScope ?? throw new ArgumentNullException(nameof(usingScope));
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

@ -341,7 +341,6 @@
<Compile Include="CSharp\TypeSystem\ResolvedUsingScope.cs" /> <Compile Include="CSharp\TypeSystem\ResolvedUsingScope.cs" />
<Compile Include="CSharp\TypeSystem\SimpleTypeOrNamespaceReference.cs" /> <Compile Include="CSharp\TypeSystem\SimpleTypeOrNamespaceReference.cs" />
<Compile Include="CSharp\TypeSystem\TypeOrNamespaceReference.cs" /> <Compile Include="CSharp\TypeSystem\TypeOrNamespaceReference.cs" />
<Compile Include="CSharp\TypeSystem\UsingScope.cs" />
<Compile Include="DebugInfo\AsyncDebugInfo.cs" /> <Compile Include="DebugInfo\AsyncDebugInfo.cs" />
<Compile Include="DebugInfo\ImportScopeInfo.cs" /> <Compile Include="DebugInfo\ImportScopeInfo.cs" />
<Compile Include="DebugInfo\DebugInfoGenerator.cs" /> <Compile Include="DebugInfo\DebugInfoGenerator.cs" />

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

@ -52,7 +52,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
public Metadata.MetadataFile PEFile => TypeSystem.MainModule.MetadataFile; public Metadata.MetadataFile PEFile => TypeSystem.MainModule.MetadataFile;
internal DecompileRun? DecompileRun { get; set; } internal DecompileRun? DecompileRun { get; set; }
internal ResolvedUsingScope? UsingScope => DecompileRun?.UsingScope.Resolve(TypeSystem); internal ResolvedUsingScope? UsingScope => DecompileRun?.UsingScope;
CSharpResolver? csharpResolver; CSharpResolver? csharpResolver;

3
ICSharpCode.Decompiler/TypeSystem/TypeSystemExtensions.cs

@ -831,7 +831,8 @@ namespace ICSharpCode.Decompiler.TypeSystem
} }
} }
public static INamespace GetNamespaceByFullName(this ICompilation compilation, string name) #nullable enable
public static INamespace? GetNamespaceByFullName(this ICompilation compilation, string? name)
{ {
if (string.IsNullOrEmpty(name)) if (string.IsNullOrEmpty(name))
return compilation.RootNamespace; return compilation.RootNamespace;

Loading…
Cancel
Save