Browse Source

Partially rewrite RequiredNamespaceCollector

pull/1198/head
Siegfried Pammer 7 years ago
parent
commit
6b195b870b
  1. 22
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 279
      ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs
  3. 4
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  4. 12
      ILSpy/Languages/CSharpLanguage.cs

22
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -37,6 +37,7 @@ using System.Collections.Immutable; @@ -37,6 +37,7 @@ using System.Collections.Immutable;
using System.Runtime.InteropServices;
using System.Reflection.Metadata;
using SRM = System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
namespace ICSharpCode.Decompiler.CSharp
{
@ -272,24 +273,24 @@ namespace ICSharpCode.Decompiler.CSharp @@ -272,24 +273,24 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
}
static bool IsSwitchOnStringCache(FieldDefinition field, MetadataReader metadata)
static bool IsSwitchOnStringCache(SRM.FieldDefinition field, MetadataReader metadata)
{
return metadata.GetString(field.Name).StartsWith("<>f__switch", StringComparison.Ordinal);
}
static bool IsAutomaticPropertyBackingField(FieldDefinition field, MetadataReader metadata)
static bool IsAutomaticPropertyBackingField(SRM.FieldDefinition field, MetadataReader metadata)
{
var name = metadata.GetString(field.Name);
return name.StartsWith("<", StringComparison.Ordinal) && name.EndsWith("BackingField", StringComparison.Ordinal);
}
static bool IsAnonymousMethodCacheField(FieldDefinition field, MetadataReader metadata)
static bool IsAnonymousMethodCacheField(SRM.FieldDefinition field, MetadataReader metadata)
{
var name = metadata.GetString(field.Name);
return name.StartsWith("CS$<>", StringComparison.Ordinal) || name.StartsWith("<>f__am", StringComparison.Ordinal);
}
static bool IsClosureType(TypeDefinition type, MetadataReader metadata)
static bool IsClosureType(SRM.TypeDefinition type, MetadataReader metadata)
{
var name = metadata.GetString(type.Name);
if (!type.Name.IsGeneratedName(metadata) || !type.IsCompilerGenerated(metadata))
@ -307,6 +308,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -307,6 +308,7 @@ namespace ICSharpCode.Decompiler.CSharp
using (var fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read)) {
stream = new MemoryStream();
fileStream.CopyTo(stream);
stream.Position = 0;
}
} else {
stream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
@ -416,9 +418,9 @@ namespace ICSharpCode.Decompiler.CSharp @@ -416,9 +418,9 @@ namespace ICSharpCode.Decompiler.CSharp
};
syntaxTree = new SyntaxTree();
MetadataReader metadata = typeSystem.ModuleDefinition.GetMetadataReader();
RequiredNamespaceCollector.CollectNamespaces(metadata, decompileRun.Namespaces);
RequiredNamespaceCollector.CollectNamespaces(typeSystem, decompileRun.Namespaces);
DoDecompileModuleAndAssemblyAttributes(decompileRun, decompilationContext, syntaxTree);
DoDecompileTypes(metadata.TypeDefinitions, decompileRun, decompilationContext, syntaxTree);
DoDecompileTypes(metadata.GetTopLevelTypeDefinitions(), decompileRun, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompileRun, decompilationContext);
return syntaxTree;
}
@ -426,7 +428,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -426,7 +428,7 @@ namespace ICSharpCode.Decompiler.CSharp
public ILTransformContext CreateILTransformContext(ILFunction function)
{
var decompileRun = new DecompileRun(settings) { CancellationToken = CancellationToken };
RequiredNamespaceCollector.CollectNamespaces((MethodDefinitionHandle)function.Method.MetadataToken, typeSystem.ModuleDefinition.Reader, decompileRun.Namespaces);
RequiredNamespaceCollector.CollectNamespaces(function.Method, typeSystem, decompileRun.Namespaces);
return new ILTransformContext(function, typeSystem, settings) {
CancellationToken = CancellationToken,
DecompileRun = decompileRun
@ -458,7 +460,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -458,7 +460,7 @@ namespace ICSharpCode.Decompiler.CSharp
syntaxTree = new SyntaxTree();
foreach (var type in types)
RequiredNamespaceCollector.CollectNamespaces(type, typeSystem.ModuleDefinition.Reader, decompileRun.Namespaces);
RequiredNamespaceCollector.CollectNamespaces(type, typeSystem, decompileRun.Namespaces);
DoDecompileTypes(types, decompileRun, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompileRun, decompilationContext);
return syntaxTree;
@ -491,7 +493,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -491,7 +493,7 @@ namespace ICSharpCode.Decompiler.CSharp
CancellationToken = CancellationToken
};
syntaxTree = new SyntaxTree();
RequiredNamespaceCollector.CollectNamespaces((TypeDefinitionHandle)type.MetadataToken, typeSystem.ModuleDefinition.Reader, decompileRun.Namespaces);
RequiredNamespaceCollector.CollectNamespaces(type.MetadataToken, typeSystem, decompileRun.Namespaces);
DoDecompileTypes(new[] { (TypeDefinitionHandle)type.MetadataToken }, decompileRun, decompilationContext, syntaxTree);
RunTransforms(syntaxTree, decompileRun, decompilationContext);
return syntaxTree;
@ -527,7 +529,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -527,7 +529,7 @@ namespace ICSharpCode.Decompiler.CSharp
syntaxTree = new SyntaxTree();
var decompileRun = new DecompileRun(settings) { CancellationToken = CancellationToken };
foreach (var entity in definitions)
RequiredNamespaceCollector.CollectNamespaces(entity, typeSystem.ModuleDefinition.Reader, decompileRun.Namespaces);
RequiredNamespaceCollector.CollectNamespaces(entity, typeSystem, decompileRun.Namespaces);
foreach (var entity in definitions) {
if (entity.IsNil)
throw new ArgumentException("definitions contains null element");

279
ICSharpCode.Decompiler/CSharp/RequiredNamespaceCollector.cs

@ -8,277 +8,68 @@ using System.Reflection.PortableExecutable; @@ -8,277 +8,68 @@ using System.Reflection.PortableExecutable;
using System.Text;
using System.Threading.Tasks;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using static ICSharpCode.Decompiler.Metadata.ILOpCodeExtensions;
namespace ICSharpCode.Decompiler.CSharp
{
class RequiredNamespaceCollector : ISignatureTypeProvider<Unit, Unit>
class RequiredNamespaceCollector
{
public HashSet<string> Namespaces { get; }
HashSet<EntityHandle> visited = new HashSet<EntityHandle>();
DecompilerTypeSystem typeSystem;
Unit IConstructedTypeProvider<Unit>.GetArrayType(Unit elementType, ArrayShape shape) => default;
Unit IConstructedTypeProvider<Unit>.GetByReferenceType(Unit elementType) => default;
Unit ISignatureTypeProvider<Unit, Unit>.GetFunctionPointerType(MethodSignature<Unit> signature) => default;
Unit IConstructedTypeProvider<Unit>.GetGenericInstantiation(Unit genericType, ImmutableArray<Unit> typeArguments) => default;
Unit ISignatureTypeProvider<Unit, Unit>.GetGenericMethodParameter(Unit genericContext, int index) => default;
Unit ISignatureTypeProvider<Unit, Unit>.GetGenericTypeParameter(Unit genericContext, int index) => default;
Unit ISignatureTypeProvider<Unit, Unit>.GetModifiedType(Unit modifier, Unit unmodifiedType, bool isRequired) => default;
Unit ISignatureTypeProvider<Unit, Unit>.GetPinnedType(Unit elementType) => default;
Unit IConstructedTypeProvider<Unit>.GetPointerType(Unit elementType) => default;
Unit ISimpleTypeProvider<Unit>.GetPrimitiveType(PrimitiveTypeCode typeCode) => default;
Unit ISZArrayTypeProvider<Unit>.GetSZArrayType(Unit elementType) => default;
Unit ISimpleTypeProvider<Unit>.GetTypeFromDefinition(MetadataReader reader, TypeDefinitionHandle handle, byte rawTypeKind)
{
var typeDef = reader.GetTypeDefinition(handle);
GetNamespaceFrom(typeDef, reader);
return default;
}
Unit ISimpleTypeProvider<Unit>.GetTypeFromReference(MetadataReader reader, TypeReferenceHandle handle, byte rawTypeKind)
public static void CollectNamespaces(DecompilerTypeSystem typeSystem, HashSet<string> namespaces)
{
var typeRef = reader.GetTypeReference(handle);
foreach (var type in typeSystem.MainAssembly.GetAllTypeDefinitions()) {
namespaces.Add(type.Namespace);
HandleAttributes(type.Attributes, namespaces);
if (!typeRef.Namespace.IsNil)
Namespaces.Add(reader.GetString(typeRef.Namespace));
return default;
}
Unit ISignatureTypeProvider<Unit, Unit>.GetTypeFromSpecification(MetadataReader reader, Unit genericContext, TypeSpecificationHandle handle, byte rawTypeKind)
{
reader.GetTypeSpecification(handle).DecodeSignature(this, default);
return default;
}
void GetNamespaceFrom(TypeDefinition typeDef, MetadataReader reader)
{
TypeDefinitionHandle handle;
while (!(handle = typeDef.GetDeclaringType()).IsNil) {
typeDef = reader.GetTypeDefinition(handle);
}
if (!typeDef.Namespace.IsNil)
Namespaces.Add(reader.GetString(typeDef.Namespace));
}
foreach (var field in type.Fields) {
HandleAttributes(field.Attributes, namespaces);
}
void GetNamespaceFrom(TypeReference typeRef, MetadataReader reader)
{
if (!typeRef.Namespace.IsNil) {
Namespaces.Add(reader.GetString(typeRef.Namespace));
} else {
switch (typeRef.ResolutionScope.Kind) {
case HandleKind.TypeReference:
typeRef = reader.GetTypeReference((TypeReferenceHandle)typeRef.ResolutionScope);
GetNamespaceFrom(typeRef, reader);
break;
case HandleKind.ModuleReference:
break;
foreach (var property in type.Properties) {
HandleAttributes(property.Attributes, namespaces);
}
}
}
protected RequiredNamespaceCollector(HashSet<string> namespaces)
{
this.Namespaces = namespaces;
}
foreach (var @event in type.Events) {
HandleAttributes(@event.Attributes, namespaces);
}
public static void CollectNamespaces(EntityHandle handle, PEReader reader, HashSet<string> namespaces)
{
switch (handle.Kind) {
case HandleKind.TypeDefinition:
CollectNamespaces((TypeDefinitionHandle)handle, reader, namespaces);
break;
case HandleKind.MethodDefinition:
CollectNamespaces((MethodDefinitionHandle)handle, reader, namespaces);
break;
case HandleKind.PropertyDefinition:
CollectNamespaces((PropertyDefinitionHandle)handle, reader, namespaces);
break;
case HandleKind.EventDefinition:
CollectNamespaces((EventDefinitionHandle)handle, reader, namespaces);
break;
case HandleKind.FieldDefinition:
CollectNamespaces((FieldDefinitionHandle)handle, reader, namespaces);
break;
default:
throw new NotSupportedException();
foreach (var method in type.Methods) {
HandleAttributes(method.Attributes, namespaces);
}
}
}
public static void CollectNamespaces(TypeDefinitionHandle handle, PEReader reader, HashSet<string> namespaces)
public static void CollectNamespaces(IEntity entity, DecompilerTypeSystem typeSystem, HashSet<string> namespaces)
{
var inst = new RequiredNamespaceCollector(namespaces);
inst.CollectNamespacesForDefinition(handle, reader);
}
public static void CollectNamespaces(MethodDefinitionHandle handle, PEReader reader, HashSet<string> namespaces)
public static void CollectNamespaces(EntityHandle entity, DecompilerTypeSystem typeSystem, HashSet<string> namespaces)
{
var inst = new RequiredNamespaceCollector(namespaces);
inst.CollectNamespacesForDefinition(handle, reader);
}
public static void CollectNamespaces(FieldDefinitionHandle handle, PEReader reader, HashSet<string> namespaces)
{
var inst = new RequiredNamespaceCollector(namespaces);
inst.CollectNamespacesForDefinition(handle, reader);
}
public static void CollectNamespaces(PropertyDefinitionHandle handle, PEReader reader, HashSet<string> namespaces)
static void HandleAttributes(IEnumerable<IAttribute> attributes, HashSet<string> namespaces)
{
var inst = new RequiredNamespaceCollector(namespaces);
inst.CollectNamespacesForDefinition(handle, reader);
}
public static void CollectNamespaces(EventDefinitionHandle handle, PEReader reader, HashSet<string> namespaces)
{
var inst = new RequiredNamespaceCollector(namespaces);
inst.CollectNamespacesForDefinition(handle, reader);
}
public static void CollectNamespaces(MetadataReader metadata, HashSet<string> namespaces)
{
foreach (var h in metadata.TypeDefinitions) {
var td = metadata.GetTypeDefinition(h);
if (!td.Namespace.IsNil)
namespaces.Add(metadata.GetString(td.Namespace));
}
foreach (var h in metadata.TypeReferences) {
var tr = metadata.GetTypeReference(h);
if (!tr.Namespace.IsNil)
namespaces.Add(metadata.GetString(tr.Namespace));
}
}
void CollectNamespacesFromAttributes(CustomAttributeHandleCollection attributes, MetadataReader metadata)
{
foreach (var handle in attributes) {
var ca = metadata.GetCustomAttribute(handle);
CollectNamespacesFromReference(ca.Constructor, metadata);
}
}
void CollectNamespacesFromReference(EntityHandle handle, MetadataReader metadata)
{
TypeDefinition declaringType;
switch (handle.Kind) {
case HandleKind.TypeDefinition:
var td = metadata.GetTypeDefinition((TypeDefinitionHandle)handle);
GetNamespaceFrom(td, metadata);
break;
case HandleKind.FieldDefinition:
var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)handle);
declaringType = metadata.GetTypeDefinition(fd.GetDeclaringType());
GetNamespaceFrom(declaringType, metadata);
break;
case HandleKind.MethodDefinition:
var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle);
declaringType = metadata.GetTypeDefinition(md.GetDeclaringType());
GetNamespaceFrom(declaringType, metadata);
break;
case HandleKind.TypeReference:
var tr = metadata.GetTypeReference((TypeReferenceHandle)handle);
GetNamespaceFrom(tr, metadata);
break;
case HandleKind.MemberReference:
var mr = metadata.GetMemberReference((MemberReferenceHandle)handle);
CollectNamespacesFromReference(mr.Parent, metadata);
switch (mr.GetKind()) {
case MemberReferenceKind.Field:
mr.DecodeFieldSignature(this, default);
break;
case MemberReferenceKind.Method:
mr.DecodeMethodSignature(this, default);
break;
}
break;
case HandleKind.MethodSpecification:
var ms = metadata.GetMethodSpecification((MethodSpecificationHandle)handle);
CollectNamespacesFromReference(ms.Method, metadata);
ms.DecodeSignature(this, default);
break;
case HandleKind.TypeSpecification:
var ts = metadata.GetTypeSpecification((TypeSpecificationHandle)handle);
ts.DecodeSignature(this, default);
break;
default:
throw new NotImplementedException();
}
}
void CollectNamespacesForDefinition(EntityHandle handle, PEReader reader)
{
if (!visited.Add(handle))
return;
var metadata = reader.GetMetadataReader();
TypeDefinition declaringType;
switch (handle.Kind) {
case HandleKind.TypeDefinition:
var td = metadata.GetTypeDefinition((TypeDefinitionHandle)handle);
GetNamespaceFrom(td, metadata);
CollectNamespacesFromAttributes(td.GetCustomAttributes(), metadata);
CollectNamespacesFromReference(td.BaseType, metadata);
foreach (var h in td.GetInterfaceImplementations()) {
var intf = metadata.GetInterfaceImplementation(h);
CollectNamespacesFromReference(intf.Interface, metadata);
}
foreach (var nestedType in td.GetNestedTypes())
CollectNamespacesForDefinition(nestedType, reader);
foreach (var field in td.GetFields())
CollectNamespacesForDefinition(field, reader);
foreach (var property in td.GetProperties())
CollectNamespacesForDefinition(property, reader);
foreach (var @event in td.GetEvents())
CollectNamespacesForDefinition(@event, reader);
foreach (var method in td.GetMethods())
CollectNamespacesForDefinition(method, reader);
break;
case HandleKind.FieldDefinition:
var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)handle);
declaringType = metadata.GetTypeDefinition(fd.GetDeclaringType());
GetNamespaceFrom(declaringType, metadata);
CollectNamespacesFromAttributes(fd.GetCustomAttributes(), metadata);
fd.DecodeSignature(this, default);
if (!fd.GetMarshallingDescriptor().IsNil)
Namespaces.Add("System.Runtime.InteropServices");
break;
case HandleKind.MethodDefinition:
var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle);
declaringType = metadata.GetTypeDefinition(md.GetDeclaringType());
GetNamespaceFrom(declaringType, metadata);
CollectNamespacesFromAttributes(md.GetCustomAttributes(), metadata);
md.DecodeSignature(this, default);
if (md.RelativeVirtualAddress > 0)
CollectNamespacesFromMethodBody(reader.GetMethodBody(md.RelativeVirtualAddress), reader);
break;
case HandleKind.EventDefinition:
var ed = metadata.GetEventDefinition((EventDefinitionHandle)handle);
CollectNamespacesFromAttributes(ed.GetCustomAttributes(), metadata);
CollectNamespacesFromReference(ed.Type, metadata);
var edacc = ed.GetAccessors();
if (!edacc.Adder.IsNil)
CollectNamespacesForDefinition(edacc.Adder, reader);
if (!edacc.Remover.IsNil)
CollectNamespacesForDefinition(edacc.Remover, reader);
if (!edacc.Raiser.IsNil)
CollectNamespacesForDefinition(edacc.Raiser, reader);
break;
case HandleKind.PropertyDefinition:
var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)handle);
CollectNamespacesFromAttributes(pd.GetCustomAttributes(), metadata);
pd.DecodeSignature(this, default);
var pdacc = pd.GetAccessors();
if (!pdacc.Getter.IsNil)
CollectNamespacesForDefinition(pdacc.Getter, reader);
if (!pdacc.Setter.IsNil)
CollectNamespacesForDefinition(pdacc.Setter, reader);
break;
default:
break;
foreach (var attr in attributes) {
namespaces.Add(attr.AttributeType.Namespace);
foreach (var arg in attr.PositionalArguments) {
namespaces.Add(arg.Type.Namespace);
if (arg is TypeOfResolveResult torr)
namespaces.Add(torr.ReferencedType.Namespace);
}
foreach (var arg in attr.NamedArguments) {
namespaces.Add(arg.Value.Type.Namespace);
if (arg.Value is TypeOfResolveResult torr)
namespaces.Add(torr.ReferencedType.Namespace);
}
}
}
@ -295,7 +86,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -295,7 +86,7 @@ namespace ICSharpCode.Decompiler.CSharp
case Metadata.OperandType.Tok:
case Metadata.OperandType.Type:
var handle = MetadataTokens.EntityHandle(instructions.ReadInt32());
CollectNamespacesFromReference(handle, metadata);
//CollectNamespaces(handle, metadata);
break;
default:
instructions.SkipOperand(opCode);

4
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -3,8 +3,12 @@ @@ -3,8 +3,12 @@
<Import Sdk="Microsoft.NET.Sdk" Project="Sdk.props" />
<PropertyGroup>
<!--
<TargetFramework Condition=" '$(OS)' != 'Windows_NT' ">netstandard2.0</TargetFramework>
<TargetFrameworks Condition=" '$(OS)' == 'Windows_NT' ">netstandard2.0;net46;net45</TargetFrameworks>
-->
<TargetFrameworks>net46</TargetFrameworks>
<Description>IL decompiler engine</Description>
<Company>ic#code</Company>

12
ILSpy/Languages/CSharpLanguage.cs

@ -400,11 +400,6 @@ namespace ICSharpCode.ILSpy @@ -400,11 +400,6 @@ namespace ICSharpCode.ILSpy
}
}
public override ISignatureTypeProvider<string, GenericContext> CreateSignatureTypeProvider(bool includeNamespace)
{
return base.CreateSignatureTypeProvider(includeNamespace);
}
public override string TypeToString(Entity type, bool includeNamespace, CustomAttributeHandleCollection typeAttributes = default)
{
ConvertTypeOptions options = ConvertTypeOptions.IncludeTypeParameterDefinitions;
@ -434,7 +429,12 @@ namespace ICSharpCode.ILSpy @@ -434,7 +429,12 @@ namespace ICSharpCode.ILSpy
astType.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions));
return w.ToString();
}
public override ISignatureTypeProvider<string, GenericContext> CreateSignatureTypeProvider(bool includeNamespace)
{
return base.CreateSignatureTypeProvider(includeNamespace);
}
static readonly CSharpFormattingOptions TypeToStringFormattingOptions = FormattingOptionsFactory.CreateEmpty();
public override string FormatPropertyName(Decompiler.Metadata.PropertyDefinition property, bool? isIndexer)

Loading…
Cancel
Save