Browse Source

Merge pull request #3635 from icsharpcode/ilambience

Refactoring of EntityToString API
pull/3644/head
Siegfried Pammer 2 weeks ago committed by GitHub
parent
commit
5a6ef92b7c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 403
      ICSharpCode.Decompiler.Tests/Output/ILAmbienceTests.cs
  3. 15
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs
  4. 58
      ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
  5. 1
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  6. 520
      ICSharpCode.Decompiler/IL/ILAmbience.cs
  7. 8
      ICSharpCode.ILSpyX/Abstractions/ILanguage.cs
  8. 3
      ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs
  9. 3
      ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs
  10. 3
      ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs
  11. 3
      ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs
  12. 2
      ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs
  13. 70
      ILSpy/Languages/CSharpLanguage.cs
  14. 372
      ILSpy/Languages/Language.cs
  15. 14
      ILSpy/Search/SearchResultFactory.cs
  16. 3
      ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs
  17. 7
      ILSpy/TreeNodes/AssemblyTreeNode.cs
  18. 4
      ILSpy/TreeNodes/BaseTypesEntryNode.cs
  19. 2
      ILSpy/TreeNodes/BaseTypesTreeNode.cs
  20. 4
      ILSpy/TreeNodes/DerivedTypesEntryNode.cs
  21. 2
      ILSpy/TreeNodes/DerivedTypesTreeNode.cs
  22. 3
      ILSpy/TreeNodes/EventTreeNode.cs
  23. 4
      ILSpy/TreeNodes/ExportedTypeTreeNode.cs
  24. 3
      ILSpy/TreeNodes/FieldTreeNode.cs
  25. 3
      ILSpy/TreeNodes/MemberReferenceTreeNode.cs
  26. 5
      ILSpy/TreeNodes/MethodTreeNode.cs
  27. 3
      ILSpy/TreeNodes/ModuleReferenceTreeNode.cs
  28. 5
      ILSpy/TreeNodes/PropertyTreeNode.cs
  29. 3
      ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs
  30. 3
      ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs
  31. 5
      ILSpy/TreeNodes/TypeReferenceTreeNode.cs
  32. 5
      ILSpy/TreeNodes/TypeTreeNode.cs
  33. 17
      ILSpy/ViewModels/CompareViewModel.cs

1
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -143,6 +143,7 @@ @@ -143,6 +143,7 @@
<Compile Include="DisassemblerPrettyTestRunner.cs" />
<Compile Include="Helpers\RoslynToolset.cs" />
<Compile Include="Helpers\TestsAssemblyOutput.cs" />
<Compile Include="Output\ILAmbienceTests.cs" />
<Compile Include="Output\InsertParenthesesVisitorTests.cs" />
<Compile Include="ProjectDecompiler\TargetFrameworkTests.cs" />
<Compile Include="ProjectDecompiler\WholeProjectDecompilerTests.cs" />

403
ICSharpCode.Decompiler.Tests/Output/ILAmbienceTests.cs

@ -0,0 +1,403 @@ @@ -0,0 +1,403 @@
// 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 System.Linq;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.Tests.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using NUnit.Framework;
using static ICSharpCode.Decompiler.Output.ConversionFlags;
namespace ICSharpCode.Decompiler.Tests.Output
{
[TestFixture]
public class ILAmbienceTests
{
ICompilation compilation;
ILAmbience ambience;
[OneTimeSetUp]
public void FixtureSetUp()
{
ambience = new ILAmbience();
compilation = new SimpleCompilation(TypeSystemLoaderTests.TestAssembly,
TypeSystemLoaderTests.Mscorlib.WithOptions(TypeSystemOptions.Default));
}
ITypeDefinition GetDefinition(Type type)
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
var foundType = compilation.FindType(type).GetDefinition();
Assert.That(foundType, Is.Not.Null);
return foundType;
}
const ConversionFlags ILSpyMainTreeViewTypeFlags = ShowTypeParameterList | PlaceReturnTypeAfterParameterList;
const ConversionFlags ILSpyMainTreeViewMemberFlags = ILSpyMainTreeViewTypeFlags | ShowParameterList | ShowReturnType | ShowParameterModifiers;
#region ITypeDefinition tests
[TestCase(None, "Dictionary`2")]
[TestCase(ShowDefinitionKeyword, ".class Dictionary`2")]
[TestCase(ShowAccessibility, "public Dictionary`2")]
[TestCase(ShowDefinitionKeyword | ShowAccessibility, ".class public Dictionary`2")]
[TestCase(ShowTypeParameterList, "Dictionary`2<TKey,TValue>")]
[TestCase(ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, ".class public Dictionary`2<TKey,TValue>")]
[TestCase(UseFullyQualifiedEntityNames | ShowTypeParameterList, "System.Collections.Generic.Dictionary`2<TKey,TValue>")]
[TestCase(UseFullyQualifiedEntityNames | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, ".class public System.Collections.Generic.Dictionary`2<TKey,TValue>")]
[TestCase(ILSpyMainTreeViewTypeFlags, "Dictionary`2<TKey,TValue>")]
public void GenericType(ConversionFlags flags, string expectedOutput)
{
var typeDef = GetDefinition(typeof(Dictionary<,>));
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput));
}
[TestCase(None, "Object")]
[TestCase(ShowDefinitionKeyword, ".class Object")]
[TestCase(ShowAccessibility, "public Object")]
[TestCase(ShowDefinitionKeyword | ShowAccessibility, ".class public Object")]
[TestCase(ShowTypeParameterList, "Object")]
[TestCase(ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, ".class public Object")]
[TestCase(UseFullyQualifiedEntityNames | ShowTypeParameterList, "System.Object")]
[TestCase(All, ".class public serializable beforefieldinit System.Object")]
[TestCase(ILSpyMainTreeViewTypeFlags, "Object")]
public void SimpleType(ConversionFlags flags, string expectedOutput)
{
var typeDef = GetDefinition(typeof(object));
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput));
}
[TestCase(None, "IEnumerable`1")]
[TestCase(ShowTypeParameterList, "IEnumerable`1<T>")]
[TestCase(ShowTypeParameterList | ShowTypeParameterVarianceModifier, "IEnumerable`1<+T>")]
[TestCase(All, ".class interface public abstract System.Collections.Generic.IEnumerable`1<+T>")]
[TestCase(ILSpyMainTreeViewTypeFlags, "IEnumerable`1<T>")]
public void GenericInterface(ConversionFlags flags, string expectedOutput)
{
var typeDef = GetDefinition(typeof(IEnumerable<>));
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput));
}
[TestCase(None, "Enumerator")]
[TestCase(ShowDefinitionKeyword, ".class Enumerator")]
[TestCase(ShowAccessibility, "nested public Enumerator")]
[TestCase(ShowDefinitionKeyword | ShowAccessibility, ".class nested public Enumerator")]
[TestCase(ShowTypeParameterList, "Enumerator<T>")]
[TestCase(ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, ".class nested public Enumerator<T>")]
[TestCase(UseFullyQualifiedEntityNames | ShowTypeParameterList, "System.Collections.Generic.List`1<T>.Enumerator<T>")]
[TestCase(ShowDeclaringType | ShowTypeParameterList, "List`1<T>.Enumerator<T>")]
[TestCase(All, ".class nested public sealed serializable beforefieldinit System.Collections.Generic.List`1<T>.Enumerator<T>")]
[TestCase(ILSpyMainTreeViewTypeFlags, "Enumerator<T>")]
public void GenericTypeWithNested(ConversionFlags flags, string expectedOutput)
{
var typeDef = GetDefinition(typeof(List<>.Enumerator));
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput));
}
[TestCase(None, "StaticClass")]
[TestCase(ShowDefinitionKeyword, ".class StaticClass")]
[TestCase(ShowModifiers | ShowDefinitionKeyword, ".class abstract sealed beforefieldinit StaticClass")]
[TestCase(ShowModifiers | ShowAccessibility, "private abstract sealed beforefieldinit StaticClass")]
[TestCase(ShowModifiers | ShowDefinitionKeyword | ShowAccessibility, ".class private abstract sealed beforefieldinit StaticClass")]
[TestCase(ShowModifiers | ShowTypeParameterList, "abstract sealed beforefieldinit StaticClass")]
[TestCase(ShowModifiers | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, ".class private abstract sealed beforefieldinit StaticClass")]
[TestCase(All, ".class private abstract sealed beforefieldinit ICSharpCode.Decompiler.Tests.Output.StaticClass")]
[TestCase(ILSpyMainTreeViewTypeFlags, "StaticClass")]
public void StaticClassTest(ConversionFlags flags, string expectedOutput)
{
var typeDef = GetDefinition(typeof(StaticClass));
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput));
}
[TestCase(None, "SealedClass")]
[TestCase(ShowDefinitionKeyword, ".class SealedClass")]
[TestCase(ShowModifiers | ShowDefinitionKeyword, ".class sealed beforefieldinit SealedClass")]
[TestCase(ShowModifiers | ShowAccessibility, "private sealed beforefieldinit SealedClass")]
[TestCase(ShowModifiers | ShowDefinitionKeyword | ShowAccessibility, ".class private sealed beforefieldinit SealedClass")]
[TestCase(ShowModifiers | ShowTypeParameterList, "sealed beforefieldinit SealedClass")]
[TestCase(ShowModifiers | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, ".class private sealed beforefieldinit SealedClass")]
[TestCase(All, ".class private sealed beforefieldinit ICSharpCode.Decompiler.Tests.Output.SealedClass")]
[TestCase(ILSpyMainTreeViewTypeFlags, "SealedClass")]
public void SealedClassTest(ConversionFlags flags, string expectedOutput)
{
var typeDef = GetDefinition(typeof(SealedClass));
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput));
}
[TestCase(None, "RefStruct")]
[TestCase(ShowDefinitionKeyword, ".class RefStruct")]
[TestCase(ShowModifiers | ShowDefinitionKeyword, ".class sealed beforefieldinit RefStruct")]
[TestCase(ShowModifiers | ShowAccessibility, "private sealed beforefieldinit RefStruct")]
[TestCase(ShowModifiers | ShowDefinitionKeyword | ShowAccessibility, ".class private sealed beforefieldinit RefStruct")]
[TestCase(ShowModifiers | ShowTypeParameterList, "sealed beforefieldinit RefStruct")]
[TestCase(ShowModifiers | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, ".class private sealed beforefieldinit RefStruct")]
[TestCase(All, ".class private sealed beforefieldinit ICSharpCode.Decompiler.Tests.Output.RefStruct")]
[TestCase(ILSpyMainTreeViewTypeFlags, "RefStruct")]
public void RefStructTest(ConversionFlags flags, string expectedOutput)
{
var typeDef = GetDefinition(typeof(RefStruct));
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput));
}
[TestCase(None, "ReadonlyStruct")]
[TestCase(ShowDefinitionKeyword, ".class ReadonlyStruct")]
[TestCase(ShowModifiers | ShowDefinitionKeyword, ".class sealed beforefieldinit ReadonlyStruct")]
[TestCase(ShowModifiers | ShowAccessibility, "private sealed beforefieldinit ReadonlyStruct")]
[TestCase(ShowModifiers | ShowDefinitionKeyword | ShowAccessibility, ".class private sealed beforefieldinit ReadonlyStruct")]
[TestCase(ShowModifiers | ShowTypeParameterList, "sealed beforefieldinit ReadonlyStruct")]
[TestCase(ShowModifiers | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, ".class private sealed beforefieldinit ReadonlyStruct")]
[TestCase(All, ".class private sealed beforefieldinit ICSharpCode.Decompiler.Tests.Output.ReadonlyStruct")]
[TestCase(ILSpyMainTreeViewTypeFlags, "ReadonlyStruct")]
public void ReadonlyStructTest(ConversionFlags flags, string expectedOutput)
{
var typeDef = GetDefinition(typeof(ReadonlyStruct));
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput));
}
[TestCase(None, "ReadonlyRefStruct")]
[TestCase(ShowDefinitionKeyword, ".class ReadonlyRefStruct")]
[TestCase(ShowModifiers | ShowDefinitionKeyword, ".class sealed beforefieldinit ReadonlyRefStruct")]
[TestCase(ShowModifiers | ShowAccessibility, "private sealed beforefieldinit ReadonlyRefStruct")]
[TestCase(ShowModifiers | ShowDefinitionKeyword | ShowAccessibility, ".class private sealed beforefieldinit ReadonlyRefStruct")]
[TestCase(ShowModifiers | ShowTypeParameterList, "sealed beforefieldinit ReadonlyRefStruct")]
[TestCase(ShowModifiers | ShowTypeParameterList | ShowDefinitionKeyword | ShowAccessibility, ".class private sealed beforefieldinit ReadonlyRefStruct")]
[TestCase(All, ".class private sealed beforefieldinit ICSharpCode.Decompiler.Tests.Output.ReadonlyRefStruct")]
[TestCase(ILSpyMainTreeViewTypeFlags, "ReadonlyRefStruct")]
public void ReadonlyRefStructTest(ConversionFlags flags, string expectedOutput)
{
var typeDef = GetDefinition(typeof(ReadonlyRefStruct));
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(typeDef), Is.EqualTo(expectedOutput));
}
#endregion
#region Delegate tests
[TestCase(None, "Func`2")]
[TestCase(ShowTypeParameterList, "Func`2<T,TResult>")]
[TestCase(ShowTypeParameterList | ShowTypeParameterVarianceModifier, "Func`2<-T,+TResult>")]
[TestCase(All, ".class public sealed System.Func`2<-T,+TResult>")]
[TestCase(ILSpyMainTreeViewTypeFlags, "Func`2<T,TResult>")]
public void FuncDelegate(ConversionFlags flags, string expectedOutput)
{
var func = GetDefinition(typeof(Func<,>));
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(func), Is.EqualTo(expectedOutput));
}
#endregion
#region IField tests
[TestCase(All & ~PlaceReturnTypeAfterParameterList, ".field private instance int32 ICSharpCode.Decompiler.Tests.Output.Program::test")]
[TestCase(ILSpyMainTreeViewMemberFlags, "test : int32")]
[TestCase(All & ~(ShowDeclaringType | ShowModifiers | ShowAccessibility | PlaceReturnTypeAfterParameterList), ".field int32 ICSharpCode.Decompiler.Tests.Output.Program::test")]
public void SimpleField(ConversionFlags flags, string expectedOutput)
{
var field = GetDefinition(typeof(Program)).GetFields(f => f.Name == "test").Single();
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(field), Is.EqualTo(expectedOutput));
}
[TestCase(All & ~PlaceReturnTypeAfterParameterList, ".field private static literal int32 ICSharpCode.Decompiler.Tests.Output.Program::TEST2")]
[TestCase(ILSpyMainTreeViewMemberFlags, "TEST2 : int32")]
public void SimpleConstField(ConversionFlags flags, string expectedOutput)
{
var field = compilation.FindType(typeof(Program)).GetFields(f => f.Name == "TEST2").Single();
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(field), Is.EqualTo(expectedOutput));
}
#endregion
#region IEvent tests
[Test]
public void EventWithDeclaringType()
{
var ev = compilation.FindType(typeof(Program)).GetEvents(f => f.Name == "ProgramChanged").Single();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags | ConversionFlags.ShowDeclaringType;
string result = ambience.ConvertSymbol(ev);
Assert.That(result, Is.EqualTo(".event instance EventHandler Program::ProgramChanged"));
}
[Test]
public void CustomEvent()
{
var ev = compilation.FindType(typeof(Program)).GetEvents(f => f.Name == "SomeEvent").Single();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags;
string result = ambience.ConvertSymbol(ev);
Assert.That(result, Is.EqualTo(".event instance EventHandler SomeEvent"));
}
#endregion
#region Property tests
[TestCase(StandardConversionFlags, ".property instance int32 Test")]
[TestCase(ILSpyMainTreeViewMemberFlags, "Test : int32")]
public void AutomaticProperty(ConversionFlags flags, string expectedOutput)
{
var prop = compilation.FindType(typeof(Program)).GetProperties(p => p.Name == "Test").Single();
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(prop), Is.EqualTo(expectedOutput));
}
[TestCase(StandardConversionFlags, ".property instance int32 Item(int32 index)")]
[TestCase(ILSpyMainTreeViewMemberFlags, "Item(int32) : int32")]
public void Indexer(ConversionFlags flags, string expectedOutput)
{
var prop = compilation.FindType(typeof(Program)).GetProperties(p => p.IsIndexer && !p.IsExplicitInterfaceImplementation).Single();
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(prop), Is.EqualTo(expectedOutput));
}
[TestCase(StandardConversionFlags, ".property instance int32 ICSharpCode.Decompiler.Tests.Output.Interface.Item(int32 index)")]
[TestCase(ILSpyMainTreeViewMemberFlags, "ICSharpCode.Decompiler.Tests.Output.Interface.Item(int32) : int32")]
public void ExplicitIndexer(ConversionFlags flags, string expectedOutput)
{
var prop = compilation.FindType(typeof(Program)).GetProperties(p => p.IsIndexer && p.IsExplicitInterfaceImplementation).Single();
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(prop), Is.EqualTo(expectedOutput));
}
#endregion
#region IMethod tests
[TestCase(StandardConversionFlags, ".method public hidebysig specialname rtspecialname instance .ctor(int32 x)")]
[TestCase(ILSpyMainTreeViewMemberFlags, ".ctor(int32)")]
public void ConstructorTests(ConversionFlags flags, string expectedOutput)
{
var prop = compilation.FindType(typeof(Program)).GetConstructors().Single();
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(prop), Is.EqualTo(expectedOutput));
}
[TestCase(StandardConversionFlags, ".method family hidebysig virtual instance void Finalize()")]
[TestCase(ILSpyMainTreeViewMemberFlags, "Finalize() : void")]
public void DestructorTests(ConversionFlags flags, string expectedOutput)
{
var dtor = compilation.FindType(typeof(Program))
.GetMembers(m => m.SymbolKind == SymbolKind.Destructor, GetMemberOptions.IgnoreInheritedMembers).Single();
ambience.ConversionFlags = flags;
Assert.That(ambience.ConvertSymbol(dtor), Is.EqualTo(expectedOutput));
}
#endregion
}
#region Test types
#pragma warning disable 169, 67
class Test { }
static class StaticClass { }
sealed class SealedClass { }
ref struct RefStruct { }
readonly struct ReadonlyStruct { }
readonly ref struct ReadonlyRefStruct { }
interface Interface
{
int this[int x] { get; }
}
class Program : Interface
{
int test;
const int TEST2 = 2;
public int Test { get; set; }
public int this[int index] {
get {
return index;
}
}
int Interface.this[int index] {
get {
return index;
}
}
public event EventHandler ProgramChanged;
public event EventHandler SomeEvent {
add { }
remove { }
}
public static bool operator +(Program lhs, Program rhs)
{
throw new NotImplementedException();
}
public static implicit operator Test(Program lhs)
{
throw new NotImplementedException();
}
public static explicit operator int(Program lhs)
{
throw new NotImplementedException();
}
public Program(int x)
{
}
~Program()
{
}
public static void Main(string[] args)
{
Console.WriteLine("Hello World!");
Console.Write("Press any key to continue . . . ");
Console.ReadKey(true);
}
public static void InParameter(in int a)
{
}
}
#endregion
}

15
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs

@ -16,6 +16,8 @@ @@ -16,6 +16,8 @@
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
#nullable enable
using System;
using System.Collections.Generic;
using System.IO;
@ -58,8 +60,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -58,8 +60,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
AstNode node = astBuilder.ConvertSymbol(symbol);
writer.StartNode(node);
EntityDeclaration entityDecl = node as EntityDeclaration;
if (entityDecl != null)
if (node is EntityDeclaration entityDecl)
PrintModifiers(entityDecl.Modifiers, writer);
if ((ConversionFlags & ConversionFlags.ShowDefinitionKeyword) == ConversionFlags.ShowDefinitionKeyword)
@ -280,7 +281,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -280,7 +281,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
ConvertType(member.DeclaringType, writer, formattingPolicy);
writer.WriteToken(Roles.Dot, ".");
}
IType explicitInterfaceType = GetExplicitInterfaceType(member);
IType? explicitInterfaceType = GetExplicitInterfaceType(member);
string name = member.Name;
if (explicitInterfaceType != null)
{
@ -297,11 +298,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -297,11 +298,11 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
writer.WriteKeyword(Roles.Identifier, "this");
break;
case SymbolKind.Constructor:
WriteQualifiedName(member.DeclaringType.Name, writer, formattingPolicy);
WriteQualifiedName(member.DeclaringType!.Name, writer, formattingPolicy);
break;
case SymbolKind.Destructor:
writer.WriteToken(DestructorDeclaration.TildeRole, "~");
WriteQualifiedName(member.DeclaringType.Name, writer, formattingPolicy);
WriteQualifiedName(member.DeclaringType!.Name, writer, formattingPolicy);
break;
case SymbolKind.Operator:
switch (name)
@ -431,7 +432,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -431,7 +432,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
return astType.ToString();
}
public void ConvertType(IType type, TokenWriter writer, CSharpFormattingOptions formattingPolicy)
void ConvertType(IType type, TokenWriter writer, CSharpFormattingOptions formattingPolicy)
{
TypeSystemAstBuilder astBuilder = CreateAstBuilder();
astBuilder.AlwaysUseShortTypeNames = (ConversionFlags & ConversionFlags.UseFullyQualifiedEntityNames) != ConversionFlags.UseFullyQualifiedEntityNames;
@ -439,7 +440,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -439,7 +440,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
astType.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
}
IType GetExplicitInterfaceType(IMember member)
IType? GetExplicitInterfaceType(IMember member)
{
if (member.IsExplicitInterfaceImplementation)
{

58
ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs

@ -99,7 +99,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -99,7 +99,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
#region Disassemble Method
EnumNameCollection<MethodAttributes> methodAttributeFlags = new EnumNameCollection<MethodAttributes>() {
internal static readonly EnumNameCollection<MethodAttributes> methodAttributeFlags = new EnumNameCollection<MethodAttributes>() {
{ MethodAttributes.Final, "final" },
{ MethodAttributes.HideBySig, "hidebysig" },
{ MethodAttributes.SpecialName, "specialname" },
@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -115,7 +115,7 @@ namespace ICSharpCode.Decompiler.Disassembler
{ MethodAttributes.HasSecurity, null }, // ?? also invisible in ILDasm
};
EnumNameCollection<MethodAttributes> methodVisibility = new EnumNameCollection<MethodAttributes>() {
internal static readonly EnumNameCollection<MethodAttributes> methodVisibility = new EnumNameCollection<MethodAttributes>() {
{ MethodAttributes.Private, "private" },
{ MethodAttributes.FamANDAssem, "famandassem" },
{ MethodAttributes.Assembly, "assembly" },
@ -124,7 +124,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -124,7 +124,7 @@ namespace ICSharpCode.Decompiler.Disassembler
{ MethodAttributes.Public, "public" },
};
EnumNameCollection<SignatureCallingConvention> callingConvention = new EnumNameCollection<SignatureCallingConvention>() {
internal static readonly EnumNameCollection<SignatureCallingConvention> callingConvention = new EnumNameCollection<SignatureCallingConvention>() {
{ SignatureCallingConvention.CDecl, "unmanaged cdecl" },
{ SignatureCallingConvention.StdCall, "unmanaged stdcall" },
{ SignatureCallingConvention.ThisCall, "unmanaged thiscall" },
@ -133,14 +133,14 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -133,14 +133,14 @@ namespace ICSharpCode.Decompiler.Disassembler
{ SignatureCallingConvention.Default, null },
};
EnumNameCollection<MethodImplAttributes> methodCodeType = new EnumNameCollection<MethodImplAttributes>() {
internal static readonly EnumNameCollection<MethodImplAttributes> methodCodeType = new EnumNameCollection<MethodImplAttributes>() {
{ MethodImplAttributes.IL, "cil" },
{ MethodImplAttributes.Native, "native" },
{ MethodImplAttributes.OPTIL, "optil" },
{ MethodImplAttributes.Runtime, "runtime" },
};
EnumNameCollection<MethodImplAttributes> methodImpl = new EnumNameCollection<MethodImplAttributes>() {
internal static readonly EnumNameCollection<MethodImplAttributes> methodImpl = new EnumNameCollection<MethodImplAttributes>() {
{ MethodImplAttributes.Synchronized, "synchronized" },
{ MethodImplAttributes.NoInlining, "noinlining" },
{ MethodImplAttributes.NoOptimization, "nooptimization" },
@ -180,8 +180,8 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -180,8 +180,8 @@ namespace ICSharpCode.Decompiler.Disassembler
// instance default class [mscorlib]System.IO.TextWriter get_BaseWriter () cil managed
//
//emit flags
WriteEnum(methodDefinition.Attributes & MethodAttributes.MemberAccessMask, methodVisibility);
WriteFlags(methodDefinition.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags);
WriteEnum(methodDefinition.Attributes & MethodAttributes.MemberAccessMask, methodVisibility, output);
WriteFlags(methodDefinition.Attributes & ~MethodAttributes.MemberAccessMask, methodAttributeFlags, output);
bool isCompilerControlled = (methodDefinition.Attributes & MethodAttributes.MemberAccessMask) == MethodAttributes.PrivateScope;
if (isCompilerControlled)
output.Write("privatescope ");
@ -259,7 +259,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -259,7 +259,7 @@ namespace ICSharpCode.Decompiler.Disassembler
}
//call convention
WriteEnum(signature.Value.Header.CallingConvention, callingConvention);
WriteEnum(signature.Value.Header.CallingConvention, callingConvention, output);
//return type
signature.Value.ReturnType(ILNameSyntax.Signature);
@ -307,12 +307,12 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -307,12 +307,12 @@ namespace ICSharpCode.Decompiler.Disassembler
}
output.Write(") ");
//cil managed
WriteEnum(methodDefinition.ImplAttributes & MethodImplAttributes.CodeTypeMask, methodCodeType);
WriteEnum(methodDefinition.ImplAttributes & MethodImplAttributes.CodeTypeMask, methodCodeType, output);
if ((methodDefinition.ImplAttributes & MethodImplAttributes.ManagedMask) == MethodImplAttributes.Managed)
output.Write("managed ");
else
output.Write("unmanaged ");
WriteFlags(methodDefinition.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl);
WriteFlags(methodDefinition.ImplAttributes & ~(MethodImplAttributes.CodeTypeMask | MethodImplAttributes.ManagedMask), methodImpl, output);
output.Unindent();
}
@ -1267,7 +1267,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1267,7 +1267,7 @@ namespace ICSharpCode.Decompiler.Disassembler
#endregion
#region Disassemble Field
EnumNameCollection<FieldAttributes> fieldVisibility = new EnumNameCollection<FieldAttributes>() {
internal static readonly EnumNameCollection<FieldAttributes> fieldVisibility = new EnumNameCollection<FieldAttributes>() {
{ FieldAttributes.Private, "private" },
{ FieldAttributes.FamANDAssem, "famandassem" },
{ FieldAttributes.Assembly, "assembly" },
@ -1276,7 +1276,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1276,7 +1276,7 @@ namespace ICSharpCode.Decompiler.Disassembler
{ FieldAttributes.Public, "public" },
};
EnumNameCollection<FieldAttributes> fieldAttributes = new EnumNameCollection<FieldAttributes>() {
internal static readonly EnumNameCollection<FieldAttributes> fieldAttributes = new EnumNameCollection<FieldAttributes>() {
{ FieldAttributes.Static, "static" },
{ FieldAttributes.Literal, "literal" },
{ FieldAttributes.InitOnly, "initonly" },
@ -1360,9 +1360,9 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1360,9 +1360,9 @@ namespace ICSharpCode.Decompiler.Disassembler
{
output.Write("[" + offset + "] ");
}
WriteEnum(fieldDefinition.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility);
WriteEnum(fieldDefinition.Attributes & FieldAttributes.FieldAccessMask, fieldVisibility, output);
const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA;
WriteFlags(fieldDefinition.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), fieldAttributes);
WriteFlags(fieldDefinition.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), fieldAttributes, output);
var signature = fieldDefinition.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new MetadataGenericContext(fieldDefinition.GetDeclaringType(), module));
@ -1415,7 +1415,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1415,7 +1415,7 @@ namespace ICSharpCode.Decompiler.Disassembler
#endregion
#region Disassemble Property
EnumNameCollection<PropertyAttributes> propertyAttributes = new EnumNameCollection<PropertyAttributes>() {
internal static readonly EnumNameCollection<PropertyAttributes> propertyAttributes = new EnumNameCollection<PropertyAttributes>() {
{ PropertyAttributes.SpecialName, "specialname" },
{ PropertyAttributes.RTSpecialName, "rtspecialname" },
{ PropertyAttributes.HasDefault, "hasdefault" },
@ -1450,7 +1450,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1450,7 +1450,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteReference(module, handle, ".property", isDefinition: true);
WriteMetadataToken(output, module, handle, MetadataTokens.GetToken(handle),
spaceAfter: true, spaceBefore: true, ShowMetadataTokens, ShowMetadataTokensInBase10);
WriteFlags(propertyDefinition.Attributes, propertyAttributes);
WriteFlags(propertyDefinition.Attributes, propertyAttributes, output);
var accessors = propertyDefinition.GetAccessors();
var declaringType = metadata.GetMethodDefinition(accessors.GetAny()).GetDeclaringType();
var signature = propertyDefinition.DecodeSignature(new DisassemblerSignatureTypeProvider(module, output), new MetadataGenericContext(declaringType, module));
@ -1489,7 +1489,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1489,7 +1489,7 @@ namespace ICSharpCode.Decompiler.Disassembler
#endregion
#region Disassemble Event
EnumNameCollection<EventAttributes> eventAttributes = new EnumNameCollection<EventAttributes>() {
internal static readonly EnumNameCollection<EventAttributes> eventAttributes = new EnumNameCollection<EventAttributes>() {
{ EventAttributes.SpecialName, "specialname" },
{ EventAttributes.RTSpecialName, "rtspecialname" },
};
@ -1536,7 +1536,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1536,7 +1536,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteReference(module, handle, ".event", isDefinition: true);
WriteMetadataToken(output, module, handle, MetadataTokens.GetToken(handle),
spaceAfter: true, spaceBefore: true, ShowMetadataTokens, ShowMetadataTokensInBase10);
WriteFlags(eventDefinition.Attributes, eventAttributes);
WriteFlags(eventDefinition.Attributes, eventAttributes, output);
var provider = new DisassemblerSignatureTypeProvider(module, output);
Action<ILNameSyntax> signature;
switch (eventDefinition.Type.Kind)
@ -1561,7 +1561,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1561,7 +1561,7 @@ namespace ICSharpCode.Decompiler.Disassembler
#endregion
#region Disassemble Type
EnumNameCollection<TypeAttributes> typeVisibility = new EnumNameCollection<TypeAttributes>() {
internal static readonly EnumNameCollection<TypeAttributes> typeVisibility = new EnumNameCollection<TypeAttributes>() {
{ TypeAttributes.Public, "public" },
{ TypeAttributes.NotPublic, "private" },
{ TypeAttributes.NestedPublic, "nested public" },
@ -1584,7 +1584,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1584,7 +1584,7 @@ namespace ICSharpCode.Decompiler.Disassembler
{ TypeAttributes.UnicodeClass, "unicode" },
};
EnumNameCollection<TypeAttributes> typeAttributes = new EnumNameCollection<TypeAttributes>() {
internal static readonly EnumNameCollection<TypeAttributes> typeAttributes = new EnumNameCollection<TypeAttributes>() {
{ TypeAttributes.Abstract, "abstract" },
{ TypeAttributes.Sealed, "sealed" },
{ TypeAttributes.SpecialName, "specialname" },
@ -1730,11 +1730,11 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1730,11 +1730,11 @@ namespace ICSharpCode.Decompiler.Disassembler
spaceAfter: true, spaceBefore: true, ShowMetadataTokens, ShowMetadataTokensInBase10);
if ((typeDefinition.Attributes & TypeAttributes.ClassSemanticsMask) == TypeAttributes.Interface)
output.Write("interface ");
WriteEnum(typeDefinition.Attributes & TypeAttributes.VisibilityMask, typeVisibility);
WriteEnum(typeDefinition.Attributes & TypeAttributes.LayoutMask, typeLayout);
WriteEnum(typeDefinition.Attributes & TypeAttributes.StringFormatMask, typeStringFormat);
WriteEnum(typeDefinition.Attributes & TypeAttributes.VisibilityMask, typeVisibility, output);
WriteEnum(typeDefinition.Attributes & TypeAttributes.LayoutMask, typeLayout, output);
WriteEnum(typeDefinition.Attributes & TypeAttributes.StringFormatMask, typeStringFormat, output);
const TypeAttributes masks = TypeAttributes.ClassSemanticsMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask;
WriteFlags(typeDefinition.Attributes & ~masks, typeAttributes);
WriteFlags(typeDefinition.Attributes & ~masks, typeAttributes, output);
output.Write(typeDefinition.GetDeclaringType().IsNil ? typeDefinition.GetFullTypeName(module.Metadata).ToILNameString() : DisassemblerHelpers.Escape(module.Metadata.GetString(typeDefinition.Name)));
WriteTypeParameters(output, module, genericContext, typeDefinition.GetGenericParameters());
@ -1967,7 +1967,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1967,7 +1967,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.WriteLine();
}
void WriteFlags<T>(T flags, EnumNameCollection<T> flagNames) where T : struct
internal static void WriteFlags<T>(T flags, EnumNameCollection<T> flagNames, ITextOutput output) where T : struct
{
long val = Convert.ToInt64(flags);
long tested = 0;
@ -1984,7 +1984,7 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -1984,7 +1984,7 @@ namespace ICSharpCode.Decompiler.Disassembler
output.Write("flags({0:x4}) ", val & ~tested);
}
void WriteEnum<T>(T enumValue, EnumNameCollection<T> enumNames) where T : struct
internal static void WriteEnum<T>(T enumValue, EnumNameCollection<T> enumNames, ITextOutput output) where T : struct
{
long val = Convert.ToInt64(enumValue);
foreach (var pair in enumNames)
@ -2006,10 +2006,14 @@ namespace ICSharpCode.Decompiler.Disassembler @@ -2006,10 +2006,14 @@ namespace ICSharpCode.Decompiler.Disassembler
}
sealed class EnumNameCollection<T> : IEnumerable<KeyValuePair<long, string>> where T : struct
internal struct EnumNameCollection<T> : IEnumerable<KeyValuePair<long, string>> where T : struct
{
List<KeyValuePair<long, string>> names = new List<KeyValuePair<long, string>>();
public EnumNameCollection()
{
}
public void Add(T flag, string name)
{
this.names.Add(new KeyValuePair<long, string>(Convert.ToInt64(flag), name));

1
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -109,6 +109,7 @@ @@ -109,6 +109,7 @@
<Compile Include="Disassembler\IEntityProcessor.cs" />
<Compile Include="Disassembler\SortByNameProcessor.cs" />
<Compile Include="Humanizer\StringHumanizeExtensions.cs" />
<Compile Include="IL\ILAmbience.cs" />
<Compile Include="IL\Transforms\InlineArrayTransform.cs" />
<Compile Include="IL\Transforms\RemoveUnconstrainedGenericReferenceTypeCheck.cs" />
<Compile Include="Metadata\MetadataFile.cs" />

520
ICSharpCode.Decompiler/IL/ILAmbience.cs

@ -0,0 +1,520 @@ @@ -0,0 +1,520 @@
// Copyright (c) Siegfried Pammer
//
// 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 System.Diagnostics;
using System.IO;
using System.Reflection;
using System.Reflection.Metadata;
using System.Text;
using ICSharpCode.Decompiler.Disassembler;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
#nullable enable
namespace ICSharpCode.Decompiler.IL
{
public class ILAmbience : IAmbience
{
public ConversionFlags ConversionFlags { get; set; }
public string ConvertConstantValue(object constantValue)
{
throw new NotImplementedException();
}
public string ConvertSymbol(ISymbol symbol)
{
StringWriter sw = new StringWriter();
ConvertSymbol(sw, symbol);
return sw.ToString();
}
void ConvertSymbol(StringWriter writer, ISymbol symbol)
{
var metadata = (symbol as IEntity)?.ParentModule!.MetadataFile?.Metadata;
var token = (symbol as IEntity)?.MetadataToken ?? default;
var output = new PlainTextOutput(writer);
switch (symbol)
{
case IField f:
Debug.Assert(metadata != null);
if (ConversionFlags.HasFlag(ConversionFlags.ShowDefinitionKeyword))
writer.Write(".field ");
var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)token);
if (ConversionFlags.HasFlag(ConversionFlags.ShowAccessibility))
ReflectionDisassembler.WriteEnum(fd.Attributes & FieldAttributes.FieldAccessMask, ReflectionDisassembler.fieldVisibility, output);
if (ConversionFlags.HasFlag(ConversionFlags.ShowModifiers))
{
const FieldAttributes hasXAttributes = FieldAttributes.HasDefault | FieldAttributes.HasFieldMarshal | FieldAttributes.HasFieldRVA;
ReflectionDisassembler.WriteFlags(fd.Attributes & ~(FieldAttributes.FieldAccessMask | hasXAttributes), ReflectionDisassembler.fieldAttributes, output);
if (!f.IsStatic)
{
writer.Write("instance ");
}
}
break;
case IMethod m:
Debug.Assert(metadata != null);
if (ConversionFlags.HasFlag(ConversionFlags.ShowDefinitionKeyword))
writer.Write(".method ");
var md = metadata.GetMethodDefinition((MethodDefinitionHandle)token);
if (ConversionFlags.HasFlag(ConversionFlags.ShowAccessibility))
ReflectionDisassembler.WriteEnum(md.Attributes & MethodAttributes.MemberAccessMask, ReflectionDisassembler.methodVisibility, output);
if (ConversionFlags.HasFlag(ConversionFlags.ShowModifiers))
{
ReflectionDisassembler.WriteFlags(md.Attributes & ~MethodAttributes.MemberAccessMask, ReflectionDisassembler.methodAttributeFlags, output);
if (!m.IsStatic)
{
writer.Write("instance ");
}
}
break;
case IProperty p:
Debug.Assert(metadata != null);
if (ConversionFlags.HasFlag(ConversionFlags.ShowDefinitionKeyword))
writer.Write(".property ");
var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)token);
if (ConversionFlags.HasFlag(ConversionFlags.ShowModifiers))
{
ReflectionDisassembler.WriteFlags(pd.Attributes, ReflectionDisassembler.propertyAttributes, output);
if (!p.IsStatic)
{
writer.Write("instance ");
}
}
break;
case IEvent e:
Debug.Assert(metadata != null);
if (ConversionFlags.HasFlag(ConversionFlags.ShowDefinitionKeyword))
writer.Write(".event ");
var ed = metadata.GetEventDefinition((EventDefinitionHandle)token);
if (ConversionFlags.HasFlag(ConversionFlags.ShowModifiers))
{
ReflectionDisassembler.WriteFlags(ed.Attributes, ReflectionDisassembler.eventAttributes, output);
if (!e.IsStatic)
{
writer.Write("instance ");
}
}
break;
case ITypeDefinition:
Debug.Assert(metadata != null);
var td = metadata.GetTypeDefinition((TypeDefinitionHandle)token);
if (ConversionFlags.HasFlag(ConversionFlags.ShowDefinitionKeyword))
{
writer.Write(".class ");
if (td.Attributes.HasFlag(TypeAttributes.Interface))
writer.Write("interface ");
}
if (ConversionFlags.HasFlag(ConversionFlags.ShowAccessibility))
ReflectionDisassembler.WriteEnum(td.Attributes & TypeAttributes.VisibilityMask, ReflectionDisassembler.typeVisibility, output);
const TypeAttributes masks = TypeAttributes.ClassSemanticsMask | TypeAttributes.VisibilityMask | TypeAttributes.LayoutMask | TypeAttributes.StringFormatMask;
if (ConversionFlags.HasFlag(ConversionFlags.ShowModifiers))
ReflectionDisassembler.WriteFlags(td.Attributes & ~masks, ReflectionDisassembler.typeAttributes, output);
break;
}
bool showReturnTypeBefore = ConversionFlags.HasFlag(ConversionFlags.ShowReturnType)
&& !ConversionFlags.HasFlag(ConversionFlags.PlaceReturnTypeAfterParameterList);
bool showReturnTypeAfter = ConversionFlags.HasFlag(ConversionFlags.ShowReturnType)
&& ConversionFlags.HasFlag(ConversionFlags.PlaceReturnTypeAfterParameterList);
if (showReturnTypeBefore && symbol is IMember { SymbolKind: not SymbolKind.Constructor })
{
switch (symbol)
{
case IField f:
writer.Write(ConvertType(f.ReturnType));
break;
case IMethod m:
writer.Write(ConvertType(m.ReturnType));
break;
case IProperty p:
writer.Write(ConvertType(p.ReturnType));
break;
case IEvent e:
writer.Write(ConvertType(e.ReturnType));
break;
}
writer.Write(' ');
}
void WriteTypeDefinition(ITypeDefinition typeDef)
{
if ((ConversionFlags.HasFlag(ConversionFlags.UseFullyQualifiedEntityNames)
|| ConversionFlags.HasFlag(ConversionFlags.ShowDeclaringType))
&& typeDef.DeclaringTypeDefinition != null)
{
WriteTypeDefinition(typeDef.DeclaringTypeDefinition);
writer.Write('.');
}
else if (ConversionFlags.HasFlag(ConversionFlags.UseFullyQualifiedEntityNames)
&& !string.IsNullOrEmpty(typeDef.Namespace))
{
writer.Write(typeDef.Namespace);
writer.Write('.');
}
writer.Write(typeDef.Name);
WriteTypeParameters(typeDef.TypeParameters, typeDef);
}
void WriteTypeParameters(IReadOnlyList<ITypeParameter> typeParameters, IEntity owner)
{
if (typeParameters.Count > 0)
{
int typeParameterCount = typeParameters.Count - (owner.DeclaringTypeDefinition?.TypeParameterCount ?? 0);
if (typeParameterCount > 0)
{
switch (owner)
{
case IType:
writer.Write("`");
break;
case IMethod _:
writer.Write("``");
break;
}
writer.Write(typeParameterCount);
}
if (ConversionFlags.HasFlag(ConversionFlags.ShowTypeParameterList))
{
int i = 0;
writer.Write('<');
foreach (var tp in typeParameters)
{
if (i > 0)
writer.Write(",");
if (ConversionFlags.HasFlag(ConversionFlags.ShowTypeParameterVarianceModifier))
{
switch (tp.Variance)
{
case VarianceModifier.Covariant:
writer.Write('+');
break;
case VarianceModifier.Contravariant:
writer.Write('-');
break;
}
}
writer.Write(tp.Name);
i++;
}
writer.Write('>');
}
}
}
switch (symbol)
{
case ITypeDefinition definition:
WriteTypeDefinition(definition);
break;
case IMember member:
if ((ConversionFlags.HasFlag(ConversionFlags.UseFullyQualifiedTypeNames)
|| ConversionFlags.HasFlag(ConversionFlags.ShowDeclaringType)) && member.DeclaringTypeDefinition != null)
{
WriteTypeDefinition(member.DeclaringTypeDefinition);
writer.Write("::");
}
writer.Write(member.Name);
if (member is IMethod method)
{
WriteTypeParameters(method.TypeParameters, member);
}
break;
}
if (ConversionFlags.HasFlag(ConversionFlags.ShowParameterList) && symbol is IParameterizedMember { SymbolKind: not SymbolKind.Property } pm)
{
writer.Write('(');
int i = 0;
foreach (var parameter in pm.Parameters)
{
if (i > 0)
writer.Write(", ");
writer.Write(ConvertType(parameter.Type));
if (ConversionFlags.HasFlag(ConversionFlags.ShowParameterNames))
writer.Write(" " + parameter.Name);
i++;
}
writer.Write(')');
}
if (showReturnTypeAfter && symbol is IMember { SymbolKind: not SymbolKind.Constructor })
{
writer.Write(" : ");
switch (symbol)
{
case IField f:
writer.Write(ConvertType(f.ReturnType));
break;
case IMethod m:
writer.Write(ConvertType(m.ReturnType));
break;
case IProperty p:
writer.Write(ConvertType(p.ReturnType));
break;
case IEvent e:
writer.Write(ConvertType(e.ReturnType));
break;
}
}
}
public string ConvertType(IType type)
{
var visitor = new TypeToStringVisitor(ConversionFlags);
type.AcceptVisitor(visitor);
return visitor.ToString();
}
class TypeToStringVisitor : TypeVisitor
{
readonly ConversionFlags flags;
readonly StringBuilder builder;
public override string ToString()
{
return builder.ToString();
}
public TypeToStringVisitor(ConversionFlags flags)
{
this.flags = flags;
this.builder = new StringBuilder();
}
public override IType VisitArrayType(ArrayType type)
{
base.VisitArrayType(type);
builder.Append('[');
builder.Append(',', type.Dimensions - 1);
builder.Append(']');
return type;
}
public override IType VisitByReferenceType(ByReferenceType type)
{
base.VisitByReferenceType(type);
builder.Append('&');
return type;
}
public override IType VisitModOpt(ModifiedType type)
{
type.ElementType.AcceptVisitor(this);
builder.Append(" modopt(");
type.Modifier.AcceptVisitor(this);
builder.Append(")");
return type;
}
public override IType VisitModReq(ModifiedType type)
{
type.ElementType.AcceptVisitor(this);
builder.Append(" modreq(");
type.Modifier.AcceptVisitor(this);
builder.Append(")");
return type;
}
public override IType VisitPointerType(PointerType type)
{
base.VisitPointerType(type);
builder.Append('*');
return type;
}
public override IType VisitTypeParameter(ITypeParameter type)
{
base.VisitTypeParameter(type);
EscapeName(builder, type.Name);
return type;
}
public override IType VisitParameterizedType(ParameterizedType type)
{
type.GenericType.AcceptVisitor(this);
builder.Append('<');
for (int i = 0; i < type.TypeArguments.Count; i++)
{
if (i > 0)
builder.Append(',');
type.TypeArguments[i].AcceptVisitor(this);
}
builder.Append('>');
return type;
}
public override IType VisitTupleType(TupleType type)
{
type.UnderlyingType.AcceptVisitor(this);
return type;
}
public override IType VisitFunctionPointerType(FunctionPointerType type)
{
builder.Append("method ");
if (type.CallingConvention != SignatureCallingConvention.Default)
{
builder.Append(type.CallingConvention.ToILSyntax());
builder.Append(' ');
}
type.ReturnType.AcceptVisitor(this);
builder.Append(" *(");
bool first = true;
foreach (var p in type.ParameterTypes)
{
if (first)
first = false;
else
builder.Append(", ");
p.AcceptVisitor(this);
}
builder.Append(')');
return type;
}
public override IType VisitOtherType(IType type)
{
WriteType(type);
return type;
}
private void WriteType(IType type)
{
if (flags.HasFlag(ConversionFlags.UseFullyQualifiedTypeNames))
EscapeName(builder, type.FullName);
else
EscapeName(builder, type.Name);
if (type.TypeParameterCount > 0)
{
builder.Append('`');
builder.Append(type.TypeParameterCount);
}
}
public override IType VisitTypeDefinition(ITypeDefinition type)
{
switch (type.KnownTypeCode)
{
case KnownTypeCode.Object:
builder.Append("object");
break;
case KnownTypeCode.Boolean:
builder.Append("bool");
break;
case KnownTypeCode.Char:
builder.Append("char");
break;
case KnownTypeCode.SByte:
builder.Append("int8");
break;
case KnownTypeCode.Byte:
builder.Append("uint8");
break;
case KnownTypeCode.Int16:
builder.Append("int16");
break;
case KnownTypeCode.UInt16:
builder.Append("uint16");
break;
case KnownTypeCode.Int32:
builder.Append("int32");
break;
case KnownTypeCode.UInt32:
builder.Append("uint32");
break;
case KnownTypeCode.Int64:
builder.Append("int64");
break;
case KnownTypeCode.UInt64:
builder.Append("uint64");
break;
case KnownTypeCode.Single:
builder.Append("float32");
break;
case KnownTypeCode.Double:
builder.Append("float64");
break;
case KnownTypeCode.String:
builder.Append("string");
break;
case KnownTypeCode.Void:
builder.Append("void");
break;
case KnownTypeCode.IntPtr:
builder.Append("native int");
break;
case KnownTypeCode.UIntPtr:
builder.Append("native uint");
break;
case KnownTypeCode.TypedReference:
builder.Append("typedref");
break;
default:
WriteType(type);
break;
}
return type;
}
}
public string WrapComment(string comment)
{
return "// " + comment;
}
/// <summary>
/// Escape characters that cannot be displayed in the UI.
/// </summary>
public static StringBuilder EscapeName(StringBuilder sb, string name)
{
foreach (char ch in name)
{
if (char.IsWhiteSpace(ch) || char.IsControl(ch) || char.IsSurrogate(ch))
sb.AppendFormat("\\u{0:x4}", (int)ch);
else
sb.Append(ch);
}
return sb;
}
/// <summary>
/// Escape characters that cannot be displayed in the UI.
/// </summary>
public static string EscapeName(string name)
{
return EscapeName(new StringBuilder(name.Length), name).ToString();
}
}
}

8
ICSharpCode.ILSpyX/Abstractions/ILanguage.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpyX.Abstractions
@ -30,10 +31,7 @@ namespace ICSharpCode.ILSpyX.Abstractions @@ -30,10 +31,7 @@ namespace ICSharpCode.ILSpyX.Abstractions
string GetEntityName(MetadataFile module, System.Reflection.Metadata.EntityHandle handle, bool fullName, bool omitGenerics);
string GetTooltip(IEntity entity);
string TypeToString(IType type, bool includeNamespace);
string MethodToString(IMethod method, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName);
string FieldToString(IField field, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName);
string PropertyToString(IProperty property, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName);
string EventToString(IEvent @event, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName);
string TypeToString(IType type, ConversionFlags conversionFlags = ConversionFlags.UseFullyQualifiedEntityNames | ConversionFlags.UseFullyQualifiedTypeNames);
string EntityToString(IEntity entity, ConversionFlags conversionFlags);
}
}

3
ILSpy/Analyzers/TreeNodes/AnalyzedEventTreeNode.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@ -45,7 +46,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes @@ -45,7 +46,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
public override object Icon => EventTreeNode.GetIcon(analyzedEvent);
// TODO: This way of formatting is not suitable for events which explicitly implement interfaces.
public override object Text => prefix + Language.EventToString(analyzedEvent, includeDeclaringTypeName: true, includeNamespace: false, includeNamespaceOfDeclaringTypeName: true);
public override object Text => prefix + Language.EntityToString(analyzedEvent, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
protected override void LoadChildren()
{

3
ILSpy/Analyzers/TreeNodes/AnalyzedFieldTreeNode.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Diagnostics;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@ -39,7 +40,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes @@ -39,7 +40,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
public override object Icon => FieldTreeNode.GetIcon(analyzedField);
public override object Text => Language.FieldToString(analyzedField, true, false, true);
public override object Text => Language.EntityToString(analyzedField, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
protected override void LoadChildren()
{

3
ILSpy/Analyzers/TreeNodes/AnalyzedMethodTreeNode.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Diagnostics;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@ -41,7 +42,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes @@ -41,7 +42,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
public override object Icon => MethodTreeNode.GetIcon(analyzedMethod);
public override object Text => prefix + Language.MethodToString(analyzedMethod, true, false, true);
public override object Text => prefix + Language.EntityToString(analyzedMethod, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
protected override void LoadChildren()
{

3
ILSpy/Analyzers/TreeNodes/AnalyzedPropertyTreeNode.cs

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.Diagnostics;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
@ -42,7 +43,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes @@ -42,7 +43,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
public override object Icon => PropertyTreeNode.GetIcon(analyzedProperty);
// TODO: This way of formatting is not suitable for properties which explicitly implement interfaces.
public override object Text => prefix + Language.PropertyToString(analyzedProperty, includeNamespace: false, includeDeclaringTypeName: true, includeNamespaceOfDeclaringTypeName: true);
public override object Text => prefix + Language.EntityToString(analyzedProperty, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames);
protected override void LoadChildren()
{

2
ILSpy/Analyzers/TreeNodes/AnalyzedTypeTreeNode.cs

@ -39,7 +39,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes @@ -39,7 +39,7 @@ namespace ICSharpCode.ILSpy.Analyzers.TreeNodes
public override object Icon => TypeTreeNode.GetIcon(analyzedType);
public override object Text => Language.TypeToString(analyzedType, includeNamespace: true);
public override object Text => Language.TypeToString(analyzedType);
protected override void LoadChildren()
{

70
ILSpy/Languages/CSharpLanguage.cs

@ -34,6 +34,7 @@ using ICSharpCode.Decompiler.CSharp.OutputVisitor; @@ -34,6 +34,7 @@ using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.Solution;
@ -157,7 +158,7 @@ namespace ICSharpCode.ILSpy @@ -157,7 +158,7 @@ namespace ICSharpCode.ILSpy
AddReferenceAssemblyWarningMessage(assembly, output);
AddReferenceWarningMessage(assembly, output);
WriteCommentLine(output, assembly.FullName);
WriteCommentLine(output, TypeToString(method.DeclaringType, includeNamespace: true));
WriteCommentLine(output, TypeToString(method.DeclaringType));
var methodDefinition = decompiler.TypeSystem.MainModule.ResolveEntity(method.MetadataToken) as IMethod;
if (methodDefinition.IsConstructor && methodDefinition.DeclaringType.IsReferenceType != false)
{
@ -258,7 +259,7 @@ namespace ICSharpCode.ILSpy @@ -258,7 +259,7 @@ namespace ICSharpCode.ILSpy
AddReferenceAssemblyWarningMessage(assembly, output);
AddReferenceWarningMessage(assembly, output);
WriteCommentLine(output, assembly.FullName);
WriteCommentLine(output, TypeToString(property.DeclaringType, includeNamespace: true));
WriteCommentLine(output, TypeToString(property.DeclaringType));
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(property.MetadataToken), decompiler.TypeSystem);
}
@ -269,7 +270,7 @@ namespace ICSharpCode.ILSpy @@ -269,7 +270,7 @@ namespace ICSharpCode.ILSpy
AddReferenceAssemblyWarningMessage(assembly, output);
AddReferenceWarningMessage(assembly, output);
WriteCommentLine(output, assembly.FullName);
WriteCommentLine(output, TypeToString(field.DeclaringType, includeNamespace: true));
WriteCommentLine(output, TypeToString(field.DeclaringType));
if (field.IsConst)
{
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(field.MetadataToken), decompiler.TypeSystem);
@ -348,7 +349,7 @@ namespace ICSharpCode.ILSpy @@ -348,7 +349,7 @@ namespace ICSharpCode.ILSpy
AddReferenceAssemblyWarningMessage(assembly, output);
AddReferenceWarningMessage(assembly, output);
WriteCommentLine(output, assembly.FullName);
WriteCommentLine(output, TypeToString(@event.DeclaringType, includeNamespace: true));
WriteCommentLine(output, TypeToString(@event.DeclaringType));
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(@event.MetadataToken), decompiler.TypeSystem);
}
@ -359,7 +360,7 @@ namespace ICSharpCode.ILSpy @@ -359,7 +360,7 @@ namespace ICSharpCode.ILSpy
AddReferenceAssemblyWarningMessage(assembly, output);
AddReferenceWarningMessage(assembly, output);
WriteCommentLine(output, assembly.FullName);
WriteCommentLine(output, TypeToString(type, includeNamespace: true));
WriteCommentLine(output, TypeToString(type, ConversionFlags.UseFullyQualifiedTypeNames | ConversionFlags.UseFullyQualifiedEntityNames));
WriteCode(output, options.DecompilerSettings, decompiler.Decompile(type.MetadataToken), decompiler.TypeSystem);
}
@ -456,7 +457,7 @@ namespace ICSharpCode.ILSpy @@ -456,7 +457,7 @@ namespace ICSharpCode.ILSpy
if (globalType != null)
{
output.Write("// Global type: ");
output.WriteReference(globalType, EscapeName(globalType.FullName));
output.WriteReference(globalType, ILAmbience.EscapeName(globalType.FullName));
output.WriteLine();
}
var metadata = module.Metadata;
@ -470,7 +471,7 @@ namespace ICSharpCode.ILSpy @@ -470,7 +471,7 @@ namespace ICSharpCode.ILSpy
if (entrypoint != null)
{
output.Write("// Entry point: ");
output.WriteReference(entrypoint, EscapeName(entrypoint.DeclaringType.FullName + "." + entrypoint.Name));
output.WriteReference(entrypoint, ILAmbience.EscapeName(entrypoint.DeclaringType.FullName + "." + entrypoint.Name));
output.WriteLine();
}
}
@ -595,40 +596,27 @@ namespace ICSharpCode.ILSpy @@ -595,40 +596,27 @@ namespace ICSharpCode.ILSpy
return ambience;
}
string EntityToString(IEntity entity, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
public override string EntityToString(IEntity entity, ConversionFlags conversionFlags)
{
// Do not forget to update CSharpAmbienceTests, if this ever changes.
var ambience = CreateAmbience();
ambience.ConversionFlags |= ConversionFlags.ShowReturnType | ConversionFlags.ShowParameterList | ConversionFlags.ShowParameterModifiers;
if (includeDeclaringTypeName)
ambience.ConversionFlags |= ConversionFlags.ShowDeclaringType;
if (includeNamespace)
ambience.ConversionFlags |= ConversionFlags.UseFullyQualifiedTypeNames;
if (includeNamespaceOfDeclaringTypeName)
ambience.ConversionFlags |= ConversionFlags.UseFullyQualifiedEntityNames;
ambience.ConversionFlags |= conversionFlags
| ConversionFlags.ShowReturnType
| ConversionFlags.ShowParameterList
| ConversionFlags.ShowParameterModifiers;
return ambience.ConvertSymbol(entity);
}
public override string TypeToString(IType type, bool includeNamespace)
public override string TypeToString(IType type, ConversionFlags conversionFlags = ConversionFlags.UseFullyQualifiedEntityNames | ConversionFlags.UseFullyQualifiedTypeNames)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
var ambience = CreateAmbience();
// Do not forget to update CSharpAmbienceTests.ILSpyMainTreeViewFlags, if this ever changes.
if (includeNamespace)
{
ambience.ConversionFlags |= ConversionFlags.UseFullyQualifiedTypeNames;
ambience.ConversionFlags |= ConversionFlags.UseFullyQualifiedEntityNames;
}
ambience.ConversionFlags |= conversionFlags;
if (type is ITypeDefinition definition)
{
return ambience.ConvertSymbol(definition);
// HACK : UnknownType is not supported by CSharpAmbience.
}
else if (type.Kind == TypeKind.Unknown)
{
return (includeNamespace ? type.FullName : type.Name)
+ (type.TypeParameterCount > 0 ? "<" + string.Join(", ", type.TypeArguments.Select(t => t.Name)) + ">" : "");
}
else
{
@ -636,34 +624,6 @@ namespace ICSharpCode.ILSpy @@ -636,34 +624,6 @@ namespace ICSharpCode.ILSpy
}
}
public override string FieldToString(IField field, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
{
if (field == null)
throw new ArgumentNullException(nameof(field));
return EntityToString(field, includeDeclaringTypeName, includeNamespace, includeNamespaceOfDeclaringTypeName);
}
public override string PropertyToString(IProperty property, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
{
if (property == null)
throw new ArgumentNullException(nameof(property));
return EntityToString(property, includeDeclaringTypeName, includeNamespace, includeNamespaceOfDeclaringTypeName);
}
public override string MethodToString(IMethod method, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
{
if (method == null)
throw new ArgumentNullException(nameof(method));
return EntityToString(method, includeDeclaringTypeName, includeNamespace, includeNamespaceOfDeclaringTypeName);
}
public override string EventToString(IEvent @event, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
{
if (@event == null)
throw new ArgumentNullException(nameof(@event));
return EntityToString(@event, includeDeclaringTypeName, includeNamespace, includeNamespaceOfDeclaringTypeName);
}
static string ToCSharpString(MetadataReader metadata, TypeDefinitionHandle handle, bool fullName, bool omitGenerics)
{
var currentTypeDefHandle = handle;

372
ILSpy/Languages/Language.cs

@ -21,14 +21,14 @@ using System.Collections.Generic; @@ -21,14 +21,14 @@ using System.Collections.Generic;
using System.Linq;
using System.Reflection.Metadata;
using System.Reflection.PortableExecutable;
using System.Text;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.Solution;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.Decompiler.Util;
using ICSharpCode.ILSpy.AssemblyTree;
using ICSharpCode.ILSpyX;
@ -87,27 +87,27 @@ namespace ICSharpCode.ILSpy @@ -87,27 +87,27 @@ namespace ICSharpCode.ILSpy
public virtual void DecompileMethod(IMethod method, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(method.DeclaringTypeDefinition, includeNamespace: true) + "." + method.Name);
WriteCommentLine(output, TypeToString(method.DeclaringTypeDefinition) + "." + method.Name);
}
public virtual void DecompileProperty(IProperty property, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(property.DeclaringTypeDefinition, includeNamespace: true) + "." + property.Name);
WriteCommentLine(output, TypeToString(property.DeclaringTypeDefinition) + "." + property.Name);
}
public virtual void DecompileField(IField field, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(field.DeclaringTypeDefinition, includeNamespace: true) + "." + field.Name);
WriteCommentLine(output, TypeToString(field.DeclaringTypeDefinition) + "." + field.Name);
}
public virtual void DecompileEvent(IEvent @event, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(@event.DeclaringTypeDefinition, includeNamespace: true) + "." + @event.Name);
WriteCommentLine(output, TypeToString(@event.DeclaringTypeDefinition) + "." + @event.Name);
}
public virtual void DecompileType(ITypeDefinition type, ITextOutput output, DecompilationOptions options)
{
WriteCommentLine(output, TypeToString(type, includeNamespace: true));
WriteCommentLine(output, TypeToString(type));
}
public virtual void DecompileNamespace(string nameSpace, IEnumerable<ITypeDefinition> types, ITextOutput output, DecompilationOptions options)
@ -158,204 +158,9 @@ namespace ICSharpCode.ILSpy @@ -158,204 +158,9 @@ namespace ICSharpCode.ILSpy
/// <summary>
/// Converts a type definition, reference or specification into a string. This method is used by tree nodes and search results.
/// </summary>
public virtual string TypeToString(IType type, bool includeNamespace)
public virtual string TypeToString(IType type, ConversionFlags conversionFlags = ConversionFlags.UseFullyQualifiedTypeNames | ConversionFlags.UseFullyQualifiedEntityNames)
{
var visitor = new TypeToStringVisitor(includeNamespace);
type.AcceptVisitor(visitor);
return visitor.ToString();
}
class TypeToStringVisitor : TypeVisitor
{
readonly bool includeNamespace;
readonly StringBuilder builder;
public override string ToString()
{
return builder.ToString();
}
public TypeToStringVisitor(bool includeNamespace)
{
this.includeNamespace = includeNamespace;
this.builder = new StringBuilder();
}
public override IType VisitArrayType(ArrayType type)
{
base.VisitArrayType(type);
builder.Append('[');
builder.Append(',', type.Dimensions - 1);
builder.Append(']');
return type;
}
public override IType VisitByReferenceType(ByReferenceType type)
{
base.VisitByReferenceType(type);
builder.Append('&');
return type;
}
public override IType VisitModOpt(ModifiedType type)
{
type.ElementType.AcceptVisitor(this);
builder.Append(" modopt(");
type.Modifier.AcceptVisitor(this);
builder.Append(")");
return type;
}
public override IType VisitModReq(ModifiedType type)
{
type.ElementType.AcceptVisitor(this);
builder.Append(" modreq(");
type.Modifier.AcceptVisitor(this);
builder.Append(")");
return type;
}
public override IType VisitPointerType(PointerType type)
{
base.VisitPointerType(type);
builder.Append('*');
return type;
}
public override IType VisitTypeParameter(ITypeParameter type)
{
base.VisitTypeParameter(type);
EscapeName(builder, type.Name);
return type;
}
public override IType VisitParameterizedType(ParameterizedType type)
{
type.GenericType.AcceptVisitor(this);
builder.Append('<');
for (int i = 0; i < type.TypeArguments.Count; i++)
{
if (i > 0)
builder.Append(',');
type.TypeArguments[i].AcceptVisitor(this);
}
builder.Append('>');
return type;
}
public override IType VisitTupleType(TupleType type)
{
type.UnderlyingType.AcceptVisitor(this);
return type;
}
public override IType VisitFunctionPointerType(FunctionPointerType type)
{
builder.Append("method ");
if (type.CallingConvention != SignatureCallingConvention.Default)
{
builder.Append(type.CallingConvention.ToILSyntax());
builder.Append(' ');
}
type.ReturnType.AcceptVisitor(this);
builder.Append(" *(");
bool first = true;
foreach (var p in type.ParameterTypes)
{
if (first)
first = false;
else
builder.Append(", ");
p.AcceptVisitor(this);
}
builder.Append(')');
return type;
}
public override IType VisitOtherType(IType type)
{
WriteType(type);
return type;
}
private void WriteType(IType type)
{
if (includeNamespace)
EscapeName(builder, type.FullName);
else
EscapeName(builder, type.Name);
if (type.TypeParameterCount > 0)
{
builder.Append('`');
builder.Append(type.TypeParameterCount);
}
}
public override IType VisitTypeDefinition(ITypeDefinition type)
{
switch (type.KnownTypeCode)
{
case KnownTypeCode.Object:
builder.Append("object");
break;
case KnownTypeCode.Boolean:
builder.Append("bool");
break;
case KnownTypeCode.Char:
builder.Append("char");
break;
case KnownTypeCode.SByte:
builder.Append("int8");
break;
case KnownTypeCode.Byte:
builder.Append("uint8");
break;
case KnownTypeCode.Int16:
builder.Append("int16");
break;
case KnownTypeCode.UInt16:
builder.Append("uint16");
break;
case KnownTypeCode.Int32:
builder.Append("int32");
break;
case KnownTypeCode.UInt32:
builder.Append("uint32");
break;
case KnownTypeCode.Int64:
builder.Append("int64");
break;
case KnownTypeCode.UInt64:
builder.Append("uint64");
break;
case KnownTypeCode.Single:
builder.Append("float32");
break;
case KnownTypeCode.Double:
builder.Append("float64");
break;
case KnownTypeCode.String:
builder.Append("string");
break;
case KnownTypeCode.Void:
builder.Append("void");
break;
case KnownTypeCode.IntPtr:
builder.Append("native int");
break;
case KnownTypeCode.UIntPtr:
builder.Append("native uint");
break;
case KnownTypeCode.TypedReference:
builder.Append("typedref");
break;
default:
WriteType(type);
break;
}
return type;
}
return new ILAmbience() { ConversionFlags = conversionFlags }.ConvertType(type);
}
#endregion
@ -377,72 +182,92 @@ namespace ICSharpCode.ILSpy @@ -377,72 +182,92 @@ namespace ICSharpCode.ILSpy
return GetTooltip(entity);
}
[Obsolete("Use EntityToString instead")]
public virtual string FieldToString(IField field, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
{
if (field == null)
throw new ArgumentNullException(nameof(field));
return GetDisplayName(field, includeDeclaringTypeName, includeNamespace, includeNamespaceOfDeclaringTypeName) + " : " + TypeToString(field.ReturnType, includeNamespace);
var flags = ConversionFlags.ShowTypeParameterList
| ConversionFlags.PlaceReturnTypeAfterParameterList
| ConversionFlags.ShowReturnType
| ConversionFlags.ShowParameterList
| ConversionFlags.ShowParameterModifiers;
if (includeDeclaringTypeName)
flags |= ConversionFlags.ShowDeclaringType;
if (includeNamespace)
flags |= ConversionFlags.UseFullyQualifiedTypeNames;
if (includeNamespaceOfDeclaringTypeName)
flags |= ConversionFlags.UseFullyQualifiedEntityNames;
return EntityToString(field, flags);
}
[Obsolete("Use EntityToString instead")]
public virtual string PropertyToString(IProperty property, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
{
if (property == null)
throw new ArgumentNullException(nameof(property));
return GetDisplayName(property, includeDeclaringTypeName, includeNamespace, includeNamespaceOfDeclaringTypeName) + " : " + TypeToString(property.ReturnType, includeNamespace);
var flags = ConversionFlags.ShowTypeParameterList
| ConversionFlags.PlaceReturnTypeAfterParameterList
| ConversionFlags.ShowReturnType
| ConversionFlags.ShowParameterList
| ConversionFlags.ShowParameterModifiers;
if (includeDeclaringTypeName)
flags |= ConversionFlags.ShowDeclaringType;
if (includeNamespace)
flags |= ConversionFlags.UseFullyQualifiedTypeNames;
if (includeNamespaceOfDeclaringTypeName)
flags |= ConversionFlags.UseFullyQualifiedEntityNames;
return EntityToString(property, flags);
}
[Obsolete("Use EntityToString instead")]
public virtual string MethodToString(IMethod method, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
{
if (method == null)
throw new ArgumentNullException(nameof(method));
int i = 0;
var buffer = new StringBuilder();
buffer.Append(GetDisplayName(method, includeDeclaringTypeName, includeNamespace, includeNamespaceOfDeclaringTypeName));
var typeParameters = method.TypeParameters;
if (typeParameters.Count > 0)
{
buffer.Append("``");
buffer.Append(typeParameters.Count);
buffer.Append('<');
foreach (var tp in typeParameters)
{
if (i > 0)
buffer.Append(", ");
buffer.Append(tp.Name);
i++;
}
buffer.Append('>');
}
buffer.Append('(');
i = 0;
var parameters = method.Parameters;
foreach (var param in parameters)
{
if (i > 0)
buffer.Append(", ");
buffer.Append(TypeToString(param.Type, includeNamespace));
i++;
}
buffer.Append(')');
if (!method.IsConstructor)
{
buffer.Append(" : ");
buffer.Append(TypeToString(method.ReturnType, includeNamespace));
}
return buffer.ToString();
var flags = ConversionFlags.ShowTypeParameterList
| ConversionFlags.PlaceReturnTypeAfterParameterList
| ConversionFlags.ShowReturnType
| ConversionFlags.ShowParameterList
| ConversionFlags.ShowParameterModifiers;
if (includeDeclaringTypeName)
flags |= ConversionFlags.ShowDeclaringType;
if (includeNamespace)
flags |= ConversionFlags.UseFullyQualifiedTypeNames;
if (includeNamespaceOfDeclaringTypeName)
flags |= ConversionFlags.UseFullyQualifiedEntityNames;
return EntityToString(method, flags);
}
[Obsolete("Use EntityToString instead")]
public virtual string EventToString(IEvent @event, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
{
if (@event == null)
throw new ArgumentNullException(nameof(@event));
var buffer = new StringBuilder();
buffer.Append(GetDisplayName(@event, includeDeclaringTypeName, includeNamespace, includeNamespaceOfDeclaringTypeName));
buffer.Append(" : ");
buffer.Append(TypeToString(@event.ReturnType, includeNamespace));
return buffer.ToString();
var flags = ConversionFlags.ShowTypeParameterList
| ConversionFlags.PlaceReturnTypeAfterParameterList
| ConversionFlags.ShowReturnType
| ConversionFlags.ShowParameterList
| ConversionFlags.ShowParameterModifiers;
if (includeDeclaringTypeName)
flags |= ConversionFlags.ShowDeclaringType;
if (includeNamespace)
flags |= ConversionFlags.UseFullyQualifiedTypeNames;
if (includeNamespaceOfDeclaringTypeName)
flags |= ConversionFlags.UseFullyQualifiedEntityNames;
return EntityToString(@event, flags);
}
public virtual string EntityToString(IEntity entity, ConversionFlags conversionFlags)
{
var ambience = new ILAmbience();
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList
| ConversionFlags.PlaceReturnTypeAfterParameterList
| ConversionFlags.ShowReturnType
| ConversionFlags.ShowParameterList
| ConversionFlags.ShowParameterModifiers
| conversionFlags;
return ambience.ConvertSymbol(entity);
}
protected string GetDisplayName(IEntity entity, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
@ -452,17 +277,17 @@ namespace ICSharpCode.ILSpy @@ -452,17 +277,17 @@ namespace ICSharpCode.ILSpy
{
MetadataReader metadata = t.ParentModule.MetadataFile.Metadata;
var typeDef = metadata.GetTypeDefinition((TypeDefinitionHandle)t.MetadataToken);
entityName = EscapeName(metadata.GetString(typeDef.Name));
entityName = ILAmbience.EscapeName(metadata.GetString(typeDef.Name));
}
else
{
entityName = EscapeName(entity.Name);
entityName = ILAmbience.EscapeName(entity.Name);
}
if (includeNamespace || includeDeclaringTypeName)
{
if (entity.DeclaringTypeDefinition != null)
return TypeToString(entity.DeclaringTypeDefinition, includeNamespaceOfDeclaringTypeName) + "." + entityName;
return EscapeName(entity.Namespace) + "." + entityName;
return TypeToString(entity.DeclaringTypeDefinition, ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames) + "." + entityName;
return ILAmbience.EscapeName(entity.Namespace) + "." + entityName;
}
else
{
@ -493,14 +318,14 @@ namespace ICSharpCode.ILSpy @@ -493,14 +318,14 @@ namespace ICSharpCode.ILSpy
{
case HandleKind.TypeDefinition:
if (fullName)
return EscapeName(((TypeDefinitionHandle)handle).GetFullTypeName(metadata).ToILNameString(omitGenerics));
return ILAmbience.EscapeName(((TypeDefinitionHandle)handle).GetFullTypeName(metadata).ToILNameString(omitGenerics));
var td = metadata.GetTypeDefinition((TypeDefinitionHandle)handle);
return EscapeName(metadata.GetString(td.Name));
return ILAmbience.EscapeName(metadata.GetString(td.Name));
case HandleKind.FieldDefinition:
var fd = metadata.GetFieldDefinition((FieldDefinitionHandle)handle);
if (fullName)
return EscapeName(fd.GetDeclaringType().GetFullTypeName(metadata).ToILNameString(omitGenerics) + "." + metadata.GetString(fd.Name));
return EscapeName(metadata.GetString(fd.Name));
return ILAmbience.EscapeName(fd.GetDeclaringType().GetFullTypeName(metadata).ToILNameString(omitGenerics) + "." + metadata.GetString(fd.Name));
return ILAmbience.EscapeName(metadata.GetString(fd.Name));
case HandleKind.MethodDefinition:
var md = metadata.GetMethodDefinition((MethodDefinitionHandle)handle);
string methodName = metadata.GetString(md.Name);
@ -511,20 +336,20 @@ namespace ICSharpCode.ILSpy @@ -511,20 +336,20 @@ namespace ICSharpCode.ILSpy
methodName += "``" + genericParamCount;
}
if (fullName)
return EscapeName(md.GetDeclaringType().GetFullTypeName(metadata).ToILNameString(omitGenerics) + "." + methodName);
return EscapeName(methodName);
return ILAmbience.EscapeName(md.GetDeclaringType().GetFullTypeName(metadata).ToILNameString(omitGenerics) + "." + methodName);
return ILAmbience.EscapeName(methodName);
case HandleKind.EventDefinition:
var ed = metadata.GetEventDefinition((EventDefinitionHandle)handle);
var declaringType = metadata.GetMethodDefinition(ed.GetAccessors().GetAny()).GetDeclaringType();
if (fullName)
return EscapeName(declaringType.GetFullTypeName(metadata).ToILNameString(omitGenerics) + "." + metadata.GetString(ed.Name));
return EscapeName(metadata.GetString(ed.Name));
return ILAmbience.EscapeName(declaringType.GetFullTypeName(metadata).ToILNameString(omitGenerics) + "." + metadata.GetString(ed.Name));
return ILAmbience.EscapeName(metadata.GetString(ed.Name));
case HandleKind.PropertyDefinition:
var pd = metadata.GetPropertyDefinition((PropertyDefinitionHandle)handle);
declaringType = metadata.GetMethodDefinition(pd.GetAccessors().GetAny()).GetDeclaringType();
if (fullName)
return EscapeName(declaringType.GetFullTypeName(metadata).ToILNameString(omitGenerics) + "." + metadata.GetString(pd.Name));
return EscapeName(metadata.GetString(pd.Name));
return ILAmbience.EscapeName(declaringType.GetFullTypeName(metadata).ToILNameString(omitGenerics) + "." + metadata.GetString(pd.Name));
return ILAmbience.EscapeName(metadata.GetString(pd.Name));
default:
return null;
}
@ -573,28 +398,5 @@ namespace ICSharpCode.ILSpy @@ -573,28 +398,5 @@ namespace ICSharpCode.ILSpy
{
return module.Metadata.MetadataVersion;
}
/// <summary>
/// Escape characters that cannot be displayed in the UI.
/// </summary>
public static StringBuilder EscapeName(StringBuilder sb, string name)
{
foreach (char ch in name)
{
if (char.IsWhiteSpace(ch) || char.IsControl(ch) || char.IsSurrogate(ch))
sb.AppendFormat("\\u{0:x4}", (int)ch);
else
sb.Append(ch);
}
return sb;
}
/// <summary>
/// Escape characters that cannot be displayed in the UI.
/// </summary>
public static string EscapeName(string name)
{
return EscapeName(new StringBuilder(name.Length), name).ToString();
}
}
}

14
ILSpy/Search/SearchResultFactory.cs

@ -16,11 +16,11 @@ @@ -16,11 +16,11 @@
// 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 System.Composition;
using System.Windows.Media;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.ILSpyX.Abstractions;
@ -65,15 +65,15 @@ namespace ICSharpCode.ILSpy.Search @@ -65,15 +65,15 @@ namespace ICSharpCode.ILSpy.Search
switch (member)
{
case ITypeDefinition t:
return language.TypeToString(t, false);
return language.TypeToString(t, ConversionFlags.None);
case IField f:
return language.FieldToString(f, true, false, false);
return language.EntityToString(f, ConversionFlags.ShowDeclaringType);
case IProperty p:
return language.PropertyToString(p, true, false, false);
return language.EntityToString(p, ConversionFlags.ShowDeclaringType);
case IMethod m:
return language.MethodToString(m, true, false, false);
return language.EntityToString(m, ConversionFlags.ShowDeclaringType);
case IEvent e:
return language.EventToString(e, true, false, false);
return language.EntityToString(e, ConversionFlags.ShowDeclaringType);
default:
throw new NotSupportedException(member?.GetType() + " not supported!");
}
@ -105,7 +105,7 @@ namespace ICSharpCode.ILSpy.Search @@ -105,7 +105,7 @@ namespace ICSharpCode.ILSpy.Search
Member = entity,
Fitness = CalculateFitness(entity),
Name = GetLanguageSpecificName(entity),
Location = declaringType != null ? language.TypeToString(declaringType, includeNamespace: true) : entity.Namespace,
Location = declaringType != null ? language.TypeToString(declaringType, ConversionFlags.UseFullyQualifiedEntityNames | ConversionFlags.UseFullyQualifiedTypeNames) : entity.Namespace,
Assembly = entity.ParentModule.FullAssemblyName,
ToolTip = entity.ParentModule.MetadataFile?.FileName,
Image = GetIcon(entity),

3
ILSpy/TreeNodes/AssemblyReferenceTreeNode.cs

@ -23,6 +23,7 @@ using System.Windows.Threading; @@ -23,6 +23,7 @@ using System.Windows.Threading;
using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.Themes;
@ -60,7 +61,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -60,7 +61,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public AssemblyReference AssemblyReference => r;
public override object Text {
get { return Language.EscapeName(r.Name) + GetSuffixString(r.Handle); }
get { return ILAmbience.EscapeName(r.Name) + GetSuffixString(r.Handle); }
}
public override object NavigationText => $"{Text} ({Properties.Resources.References})";

7
ILSpy/TreeNodes/AssemblyTreeNode.cs

@ -28,6 +28,7 @@ using System.Windows.Documents; @@ -28,6 +28,7 @@ using System.Windows.Documents;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.AssemblyTree;
@ -286,20 +287,20 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -286,20 +287,20 @@ namespace ICSharpCode.ILSpy.TreeNodes
int decimalIndex = @namespace.LastIndexOf('.');
if (decimalIndex < 0)
{
var escapedNamespace = Language.EscapeName(@namespace);
var escapedNamespace = ILAmbience.EscapeName(@namespace);
ns = new NamespaceTreeNode(escapedNamespace);
}
else
{
var parentNamespaceTreeNode = GetOrCreateNamespaceTreeNode(@namespace.Substring(0, decimalIndex));
var escapedInnerNamespace = Language.EscapeName(@namespace.Substring(decimalIndex + 1));
var escapedInnerNamespace = ILAmbience.EscapeName(@namespace.Substring(decimalIndex + 1));
ns = new NamespaceTreeNode(escapedInnerNamespace);
parentNamespaceTreeNode.Children.Add(ns);
}
}
else
{
var escapedNamespace = Language.EscapeName(@namespace);
var escapedNamespace = ILAmbience.EscapeName(@namespace);
ns = new NamespaceTreeNode(escapedNamespace);
}
namespaces.Add(@namespace, ns);

4
ILSpy/TreeNodes/BaseTypesEntryNode.cs

@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -34,7 +34,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.type = type;
}
public override object Text => this.Language.TypeToString(type, includeNamespace: true);
public override object Text => this.Language.TypeToString(type);
public override object NavigationText => $"{Text} ({Properties.Resources.BaseTypes})";
@ -61,7 +61,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -61,7 +61,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, language.TypeToString(type, includeNamespace: true));
language.WriteCommentLine(output, language.TypeToString(type));
}
IEntity IMemberTreeNode.Member => type;

2
ILSpy/TreeNodes/BaseTypesTreeNode.cs

@ -46,7 +46,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -46,7 +46,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override object Text => Properties.Resources.BaseTypes;
public override object NavigationText => $"{Text} ({this.Language.TypeToString(type, includeNamespace: true)})";
public override object NavigationText => $"{Text} ({this.Language.TypeToString(type)})";
public override object Icon => Images.SuperTypes;

4
ILSpy/TreeNodes/DerivedTypesEntryNode.cs

@ -44,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -44,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override bool ShowExpander => !type.IsSealed && base.ShowExpander;
public override object Text {
get { return Language.TypeToString(type, includeNamespace: true) + GetSuffixString(type.MetadataToken); }
get { return Language.TypeToString(type) + GetSuffixString(type.MetadataToken); }
}
public override object NavigationText => $"{Text} ({Properties.Resources.DerivedTypes})";
@ -98,7 +98,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -98,7 +98,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, language.TypeToString(type, includeNamespace: true));
language.WriteCommentLine(output, language.TypeToString(type));
}
IEntity IMemberTreeNode.Member => type;

2
ILSpy/TreeNodes/DerivedTypesTreeNode.cs

@ -46,7 +46,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -46,7 +46,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override object Text => Resources.DerivedTypes;
public override object NavigationText => $"{Text} ({this.Language.TypeToString(type, includeNamespace: true)})";
public override object NavigationText => $"{Text} ({this.Language.TypeToString(type)})";
public override object Icon => Images.SubTypes;

3
ILSpy/TreeNodes/EventTreeNode.cs

@ -24,6 +24,7 @@ using ICSharpCode.Decompiler; @@ -24,6 +24,7 @@ using ICSharpCode.Decompiler;
namespace ICSharpCode.ILSpy.TreeNodes
{
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpyX;
@ -60,7 +61,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -60,7 +61,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static object GetText(IEvent ev, Language language, bool includeDeclaringTypeName = false)
{
return language.EventToString(ev, includeDeclaringTypeName, false, false);
return language.EntityToString(ev, includeDeclaringTypeName ? ConversionFlags.ShowDeclaringType : ConversionFlags.None);
}
public override object Icon => GetIcon(GetEventDefinition());

4
ILSpy/TreeNodes/ExportedTypeTreeNode.cs

@ -43,7 +43,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -43,7 +43,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
public override object Text
=> Language.TypeToString(resolvedType, includeNamespace: true) + GetSuffixString(r.Handle);
=> Language.TypeToString(resolvedType) + GetSuffixString(r.Handle);
public override object Icon => Images.ExportedType;
@ -57,7 +57,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -57,7 +57,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, $"{Language.TypeToString(resolvedType, includeNamespace: true)} (Exported, IsForwarder: {r.IsForwarder}, Attributes: {(int)r.Attributes:X8})");
language.WriteCommentLine(output, $"{Language.TypeToString(resolvedType)} (Exported, IsForwarder: {r.IsForwarder}, Attributes: {(int)r.Attributes:X8})");
}
}
}

3
ILSpy/TreeNodes/FieldTreeNode.cs

@ -24,6 +24,7 @@ using ICSharpCode.Decompiler; @@ -24,6 +24,7 @@ using ICSharpCode.Decompiler;
namespace ICSharpCode.ILSpy.TreeNodes
{
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpyX;
@ -52,7 +53,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -52,7 +53,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static object GetText(IField field, Language language, bool includeDeclaringTypeName = false)
{
return language.FieldToString(field, includeDeclaringTypeName, includeNamespace: false, includeNamespaceOfDeclaringTypeName: false);
return language.EntityToString(field, includeDeclaringTypeName ? ConversionFlags.ShowDeclaringType : ConversionFlags.None);
}
public override object Icon => GetIcon(GetFieldDefinition());

3
ILSpy/TreeNodes/MemberReferenceTreeNode.cs

@ -23,6 +23,7 @@ using System.Reflection.Metadata; @@ -23,6 +23,7 @@ using System.Reflection.Metadata;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.TreeNodes
@ -57,7 +58,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -57,7 +58,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
_ => throw new NotSupportedException(),
};
public string Signature => resolvedMember is IMethod m ? Language.MethodToString(m, false, false, false) : Language.FieldToString((IField)resolvedMember, false, false, false);
public string Signature => Language.EntityToString(resolvedMember, ConversionFlags.None);
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{

5
ILSpy/TreeNodes/MethodTreeNode.cs

@ -24,6 +24,7 @@ using ICSharpCode.Decompiler; @@ -24,6 +24,7 @@ using ICSharpCode.Decompiler;
namespace ICSharpCode.ILSpy.TreeNodes
{
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpyX;
@ -52,7 +53,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -52,7 +53,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static object GetText(IMethod method, Language language, bool includeDeclaringTypeName = false)
{
return language.MethodToString(method, includeDeclaringTypeName, false, false);
return language.EntityToString(method, includeDeclaringTypeName ? ConversionFlags.ShowDeclaringType : ConversionFlags.None);
}
public override object Icon => GetIcon(GetMethodDefinition());
@ -108,7 +109,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -108,7 +109,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override string ToString()
{
return LanguageService.ILLanguage.MethodToString(MethodDefinition, false, false, false);
return LanguageService.ILLanguage.EntityToString(MethodDefinition, ConversionFlags.None);
}
}
}

3
ILSpy/TreeNodes/ModuleReferenceTreeNode.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions;
@ -49,7 +50,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -49,7 +50,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.module = module ?? throw new ArgumentNullException(nameof(module));
this.metadata = module.Metadata;
this.reference = module.Metadata.GetModuleReference(r);
this.moduleName = Language.EscapeName(metadata.GetString(reference.Name));
this.moduleName = ILAmbience.EscapeName(metadata.GetString(reference.Name));
foreach (var h in metadata.AssemblyFiles)
{

5
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -24,6 +24,7 @@ using ICSharpCode.Decompiler; @@ -24,6 +24,7 @@ using ICSharpCode.Decompiler;
namespace ICSharpCode.ILSpy.TreeNodes
{
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpyX;
@ -62,7 +63,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -62,7 +63,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static object GetText(IProperty property, Language language, bool includeDeclaringTypeName = false)
{
return language.PropertyToString(property, includeDeclaringTypeName, false, false);
return language.EntityToString(property, includeDeclaringTypeName ? ConversionFlags.ShowDeclaringType : ConversionFlags.None);
}
public override object Icon => GetIcon(GetPropertyDefinition());
@ -106,7 +107,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -106,7 +107,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override string ToString()
{
return LanguageService.ILLanguage.PropertyToString(PropertyDefinition, false, false, false);
return LanguageService.ILLanguage.EntityToString(PropertyDefinition, ConversionFlags.None);
}
}
}

3
ILSpy/TreeNodes/ResourceNodes/ResourceEntryNode.cs

@ -21,6 +21,7 @@ using System.IO; @@ -21,6 +21,7 @@ using System.IO;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using Microsoft.Win32;
@ -35,7 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -35,7 +36,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
private readonly string key;
private readonly Func<Stream> openStream;
public override object Text => Language.EscapeName(key);
public override object Text => ILAmbience.EscapeName(key);
public override object Icon => Images.Resource;

3
ILSpy/TreeNodes/ResourceNodes/ResourceTreeNode.cs

@ -25,6 +25,7 @@ using ICSharpCode.AvalonEdit.Highlighting; @@ -25,6 +25,7 @@ using ICSharpCode.AvalonEdit.Highlighting;
using ICSharpCode.AvalonEdit.Utils;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp.ProjectDecompiler;
using ICSharpCode.Decompiler.IL;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.ILSpy.Properties;
using ICSharpCode.ILSpy.TextView;
@ -51,7 +52,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -51,7 +52,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public Resource Resource { get; }
public override object Text => Language.EscapeName(Resource.Name);
public override object Text => ILAmbience.EscapeName(Resource.Name);
public override object Icon => Images.Resource;

5
ILSpy/TreeNodes/TypeReferenceTreeNode.cs

@ -20,6 +20,7 @@ using System; @@ -20,6 +20,7 @@ using System;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.ILSpy.TreeNodes
@ -43,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -43,7 +44,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
public override object Text
=> Language.TypeToString(resolvedType, includeNamespace: false) + GetSuffixString(r.Handle);
=> Language.TypeToString(resolvedType, ConversionFlags.None) + GetSuffixString(r.Handle);
public override object NavigationText => $"{Text} ({Properties.Resources.ReferencedTypes})";
@ -62,7 +63,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -62,7 +63,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public override void Decompile(Language language, ITextOutput output, DecompilationOptions options)
{
language.WriteCommentLine(output, Language.TypeToString(resolvedType, includeNamespace: true));
language.WriteCommentLine(output, Language.TypeToString(resolvedType));
EnsureLazyChildren();
foreach (ILSpyTreeNode child in Children)
{

5
ILSpy/TreeNodes/TypeTreeNode.cs

@ -26,6 +26,7 @@ using SRM = System.Reflection.Metadata; @@ -26,6 +26,7 @@ using SRM = System.Reflection.Metadata;
namespace ICSharpCode.ILSpy.TreeNodes
{
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpyX;
@ -42,10 +43,10 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -42,10 +43,10 @@ namespace ICSharpCode.ILSpy.TreeNodes
public AssemblyTreeNode ParentAssemblyNode { get; }
public override object Text => this.Language.TypeToString(GetTypeDefinition(), includeNamespace: false)
public override object Text => this.Language.TypeToString(GetTypeDefinition(), ConversionFlags.None)
+ GetSuffixString(TypeDefinition.MetadataToken);
public override object NavigationText => this.Language.TypeToString(GetTypeDefinition(), includeNamespace: true)
public override object NavigationText => this.Language.TypeToString(GetTypeDefinition())
+ GetSuffixString(TypeDefinition.MetadataToken);
private ITypeDefinition GetTypeDefinition()

17
ILSpy/ViewModels/CompareViewModel.cs

@ -41,6 +41,7 @@ using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions; @@ -41,6 +41,7 @@ using ICSharpCode.ILSpyX.TreeView.PlatformAbstractions;
namespace ICSharpCode.ILSpy.ViewModels
{
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using TomsToolbox.Wpf;
@ -217,11 +218,8 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -217,11 +218,8 @@ namespace ICSharpCode.ILSpy.ViewModels
return result;
string? GetEntityText(ISymbol? symbol) => symbol switch {
ITypeDefinition t => this.assemblyTreeModel.CurrentLanguage.TypeToString(t, includeNamespace: true),
IMethod m => this.assemblyTreeModel.CurrentLanguage.MethodToString(m, false, false, false),
IField f => this.assemblyTreeModel.CurrentLanguage.FieldToString(f, false, false, false),
IProperty p => this.assemblyTreeModel.CurrentLanguage.PropertyToString(p, false, false, false),
IEvent e => this.assemblyTreeModel.CurrentLanguage.EventToString(e, false, false, false),
ITypeDefinition t => this.assemblyTreeModel.CurrentLanguage.TypeToString(t),
IEntity m => this.assemblyTreeModel.CurrentLanguage.EntityToString(m, ConversionFlags.None),
INamespace n => n.FullName,
IModule m => m.FullAssemblyName,
_ => null,
@ -301,7 +299,7 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -301,7 +299,7 @@ namespace ICSharpCode.ILSpy.ViewModels
var module = (MetadataModule)typeSystem.MainModule!;
var metadata = module.MetadataFile.Metadata;
var ambience = new CSharpAmbience();
ambience.ConversionFlags = ICSharpCode.Decompiler.Output.ConversionFlags.All & ~ICSharpCode.Decompiler.Output.ConversionFlags.ShowDeclaringType;
ambience.ConversionFlags = ConversionFlags.All & ~ConversionFlags.ShowDeclaringType;
List<Entry> results = new();
Dictionary<TypeDefinitionHandle, Entry> typeEntries = new();
@ -651,11 +649,8 @@ namespace ICSharpCode.ILSpy.ViewModels @@ -651,11 +649,8 @@ namespace ICSharpCode.ILSpy.ViewModels
return entityText + (otherText != null && entityText != otherText ? " -> " + otherText : "");
string? GetEntityText(ISymbol? symbol) => symbol switch {
ITypeDefinition t => this.Language.TypeToString(t, includeNamespace: false) + GetSuffixString(t.MetadataToken),
IMethod m => this.Language.MethodToString(m, false, false, false) + GetSuffixString(m.MetadataToken),
IField f => this.Language.FieldToString(f, false, false, false) + GetSuffixString(f.MetadataToken),
IProperty p => this.Language.PropertyToString(p, false, false, false) + GetSuffixString(p.MetadataToken),
IEvent e => this.Language.EventToString(e, false, false, false) + GetSuffixString(e.MetadataToken),
ITypeDefinition t => this.Language.TypeToString(t, ConversionFlags.None) + GetSuffixString(t.MetadataToken),
IEntity e => this.Language.EntityToString(e, ConversionFlags.All & ~(ConversionFlags.ShowDeclaringType | ConversionFlags.UseFullyQualifiedEntityNames | ConversionFlags.UseFullyQualifiedTypeNames)) + GetSuffixString(e.MetadataToken),
INamespace n => n.FullName,
IModule m => m.FullAssemblyName,
_ => null,

Loading…
Cancel
Save