Browse Source

Use IAmbience API in CSharpLanguage.

pull/1253/head
Siegfried Pammer 7 years ago
parent
commit
23907c8d7d
  1. 1
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 303
      ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs
  3. 21
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs
  4. 2
      ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
  5. 9
      ICSharpCode.Decompiler/Output/IAmbience.cs
  6. 7
      ILSpy.Tests/ILSpy.Tests.csproj
  7. 129
      ILSpy.Tests/Languages/CSharpLanguageTests.cs
  8. 2
      ILSpy.Tests/Stub.cs
  9. 176
      ILSpy/Languages/CSharpLanguage.cs

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

@ -63,6 +63,7 @@ @@ -63,6 +63,7 @@
<ItemGroup>
<Compile Include="DisassemblerPrettyTestRunner.cs" />
<Compile Include="Output\CSharpAmbienceTests.cs" />
<Compile Include="Semantics\ConversionTests.cs" />
<Compile Include="Semantics\ExplicitConversionTest.cs" />
<Compile Include="Semantics\OverloadResolutionTests.cs" />

303
ICSharpCode.Decompiler.Tests/Output/CSharpAmbienceTests.cs

@ -0,0 +1,303 @@ @@ -0,0 +1,303 @@
// 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.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.Tests.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using NUnit.Framework;
namespace ICSharpCode.Decompiler.Tests.Output
{
[TestFixture]
public class CSharpAmbienceTests
{
ICompilation compilation;
CSharpAmbience ambience;
[OneTimeSetUp]
public void FixtureSetUp()
{
ambience = new CSharpAmbience();
compilation = new SimpleCompilation(TypeSystemLoaderTests.TestAssembly,
TypeSystemLoaderTests.Mscorlib.WithOptions(TypeSystemOptions.Default | TypeSystemOptions.OnlyPublicAPI));
}
#region ITypeDefinition tests
[Test]
public void GenericType()
{
var typeDef = compilation.FindType(typeof(Dictionary<,>)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedEntityNames | ConversionFlags.ShowTypeParameterList;
string result = ambience.ConvertSymbol(typeDef);
Assert.AreEqual("System.Collections.Generic.Dictionary<TKey,TValue>", result);
}
[Test]
public void GenericTypeShortName()
{
var typeDef = compilation.FindType(typeof(Dictionary<,>)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList;
string result = ambience.ConvertSymbol(typeDef);
Assert.AreEqual("Dictionary<TKey,TValue>", result);
}
[Test]
public void SimpleType()
{
var typeDef = compilation.FindType(typeof(Object)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedEntityNames | ConversionFlags.ShowTypeParameterList;
string result = ambience.ConvertSymbol(typeDef);
Assert.AreEqual("System.Object", result);
}
[Test]
public void SimpleTypeDefinition()
{
var typeDef = compilation.FindType(typeof(Object)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.All & ~(ConversionFlags.UseFullyQualifiedEntityNames);
string result = ambience.ConvertSymbol(typeDef);
Assert.AreEqual("public class Object", result);
}
[Test]
public void SimpleTypeDefinitionWithoutModifiers()
{
var typeDef = compilation.FindType(typeof(Object)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.All & ~(ConversionFlags.UseFullyQualifiedEntityNames | ConversionFlags.ShowModifiers | ConversionFlags.ShowAccessibility);
string result = ambience.ConvertSymbol(typeDef);
Assert.AreEqual("class Object", result);
}
[Test]
public void GenericTypeDefinitionFull()
{
var typeDef = compilation.FindType(typeof(List<>)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.All;
string result = ambience.ConvertSymbol(typeDef);
Assert.AreEqual("public class System.Collections.Generic.List<T>", result);
}
[Test]
public void GenericInterfaceFull()
{
var typeDef = compilation.FindType(typeof(IEnumerable<>)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.All;
string result = ambience.ConvertSymbol(typeDef);
Assert.AreEqual("public interface System.Collections.Generic.IEnumerable<out T>", result);
}
[Test]
public void SimpleTypeShortName()
{
var typeDef = compilation.FindType(typeof(Object)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList;
string result = ambience.ConvertSymbol(typeDef);
Assert.AreEqual("Object", result);
}
[Test]
public void GenericTypeWithNested()
{
var typeDef = compilation.FindType(typeof(List<>.Enumerator)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.UseFullyQualifiedEntityNames | ConversionFlags.ShowTypeParameterList;
string result = ambience.ConvertSymbol(typeDef);
Assert.AreEqual("System.Collections.Generic.List<T>.Enumerator", result);
}
[Test]
public void GenericTypeWithNestedShortName()
{
var typeDef = compilation.FindType(typeof(List<>.Enumerator)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.ShowDeclaringType | ConversionFlags.ShowTypeParameterList;
string result = ambience.ConvertSymbol(typeDef);
Assert.AreEqual("List<T>.Enumerator", result);
}
#endregion
#region Delegate tests
[Test]
public void DelegateName()
{
var func = compilation.FindType(typeof(Func<,>)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.ShowTypeParameterList;
Assert.AreEqual("Func<in T,out TResult>", ambience.ConvertSymbol(func));
}
[Test]
public void FullDelegate()
{
var func = compilation.FindType(typeof(Func<,>)).GetDefinition();
ambience.ConversionFlags = ConversionFlags.All;
Assert.AreEqual("public delegate TResult System.Func<in T,out TResult>(T arg);", ambience.ConvertSymbol(func));
}
#endregion
#region IField tests
[Test]
public void SimpleField()
{
var field = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetFields(f => f.Name == "test").Single();
ambience.ConversionFlags = ConversionFlags.All;
string result = ambience.ConvertSymbol(field);
Assert.AreEqual("private int ICSharpCode.Decompiler.Tests.Output.CSharpAmbienceTests.Program.test;", result);
}
[Test]
public void SimpleConstField()
{
var field = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetFields(f => f.Name == "TEST2").Single();
ambience.ConversionFlags = ConversionFlags.All;
string result = ambience.ConvertSymbol(field);
Assert.AreEqual("private const int ICSharpCode.Decompiler.Tests.Output.CSharpAmbienceTests.Program.TEST2;", result);
}
[Test]
public void SimpleFieldWithoutModifiers()
{
var field = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetFields(f => f.Name == "test").Single();
ambience.ConversionFlags = ConversionFlags.All & ~(ConversionFlags.ShowDeclaringType | ConversionFlags.ShowModifiers | ConversionFlags.ShowAccessibility);
string result = ambience.ConvertSymbol(field);
Assert.AreEqual("int test;", result);
}
#endregion
#region IEvent tests
[Test]
public void EventWithDeclaringType()
{
var ev = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetEvents(f => f.Name == "ProgramChanged").Single();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags | ConversionFlags.ShowDeclaringType;
string result = ambience.ConvertSymbol(ev);
Assert.AreEqual("public event EventHandler Program.ProgramChanged;", result);
}
[Test]
public void CustomEvent()
{
var ev = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetEvents(f => f.Name == "SomeEvent").Single();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags;
string result = ambience.ConvertSymbol(ev);
Assert.AreEqual("public event EventHandler SomeEvent;", result);
}
#endregion
#region Property tests
[Test]
public void AutomaticProperty()
{
var prop = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetProperties(p => p.Name == "Test").Single();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags;
string result = ambience.ConvertSymbol(prop);
Assert.AreEqual("public int Test { get; set; }", result);
}
[Test]
public void Indexer()
{
var prop = compilation.FindType(typeof(CSharpAmbienceTests.Program)).GetProperties(p => p.IsIndexer).Single();
ambience.ConversionFlags = ConversionFlags.StandardConversionFlags;
string result = ambience.ConvertSymbol(prop);
Assert.AreEqual("public int this[int index] { get; }", result);
}
#endregion
#region Test types
#pragma warning disable 169, 67
class Test { }
class Program
{
int test;
const int TEST2 = 2;
public int Test { get; set; }
public int 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);
}
}
#endregion
}
}

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

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
using System;
using System.IO;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
@ -37,7 +38,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -37,7 +38,7 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
throw new ArgumentNullException("symbol");
StringWriter writer = new StringWriter();
ConvertSymbol(symbol, new TextWriterTokenWriter(writer), FormattingOptionsFactory.CreateMono ());
ConvertSymbol(symbol, new TextWriterTokenWriter(writer), FormattingOptionsFactory.CreateEmpty());
return writer.ToString();
}
@ -87,7 +88,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -87,7 +88,9 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
}
if ((ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType) {
if ((ConversionFlags & ConversionFlags.PlaceReturnTypeAfterParameterList) != ConversionFlags.PlaceReturnTypeAfterParameterList
&& (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType)
{
var rt = node.GetChildByRole(Roles.Type);
if (!rt.IsNull) {
rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
@ -116,7 +119,19 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -116,7 +119,19 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
}
writer.WriteToken(symbol.SymbolKind == SymbolKind.Indexer ? Roles.RBracket : Roles.RPar, symbol.SymbolKind == SymbolKind.Indexer ? "]" : ")");
}
if ((ConversionFlags & ConversionFlags.PlaceReturnTypeAfterParameterList) == ConversionFlags.PlaceReturnTypeAfterParameterList
&& (ConversionFlags & ConversionFlags.ShowReturnType) == ConversionFlags.ShowReturnType)
{
var rt = node.GetChildByRole(Roles.Type);
if (!rt.IsNull) {
writer.Space();
writer.WriteToken(Roles.Colon, ":");
writer.Space();
rt.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
}
}
if ((ConversionFlags & ConversionFlags.ShowBody) == ConversionFlags.ShowBody && !(node is TypeDeclaration)) {
IProperty property = symbol as IProperty;
if (property != null) {

2
ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj

@ -487,7 +487,7 @@ @@ -487,7 +487,7 @@
<Compile Include="TypeSystem\ComHelper.cs" />
<Compile Include="TypeSystem\DecompilerTypeSystem.cs" />
<Compile Include="TypeSystem\FullTypeName.cs" />
<Compile Include="TypeSystem\IAmbience.cs" />
<Compile Include="Output\IAmbience.cs" />
<Compile Include="TypeSystem\IAssembly.cs" />
<Compile Include="TypeSystem\IAttribute.cs" />
<Compile Include="TypeSystem\ICodeContext.cs" />

9
ICSharpCode.Decompiler/TypeSystem/IAmbience.cs → ICSharpCode.Decompiler/Output/IAmbience.cs

@ -17,8 +17,9 @@ @@ -17,8 +17,9 @@
// DEALINGS IN THE SOFTWARE.
using System;
using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.TypeSystem
namespace ICSharpCode.Decompiler.Output
{
[Flags]
public enum ConversionFlags
@ -69,11 +70,15 @@ namespace ICSharpCode.Decompiler.TypeSystem @@ -69,11 +70,15 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// For properties: shows "{ get; }" or similar.
/// </summary>
ShowBody = 0x200,
/// <summary>
/// Use fully qualified names for members.
/// </summary>
UseFullyQualifiedEntityNames = 0x400,
/// <summary>
/// Instead of placing the return type before the entity name,
/// append it after the parameter list, preceeded by a colon.
/// </summary>
PlaceReturnTypeAfterParameterList = 0x800,
StandardConversionFlags = ShowParameterNames |
ShowAccessibility |

7
ILSpy.Tests/ILSpy.Tests.csproj

@ -19,6 +19,7 @@ @@ -19,6 +19,7 @@
<SignAssembly>True</SignAssembly>
<AssemblyOriginatorKeyFile>..\ICSharpCode.Decompiler\ICSharpCode.Decompiler.snk</AssemblyOriginatorKeyFile>
<RootNamespace>ICSharpCode.ILSpy.Tests</RootNamespace>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug'">
@ -36,8 +37,6 @@ @@ -36,8 +37,6 @@
</PropertyGroup>
<ItemGroup>
<Compile Include="..\ICSharpCode.Decompiler.Tests\TypeSystem\TypeSystemTestCase.cs" Link="TestCases\TypeSystemTestCase.cs" />
<Compile Include="Languages\CSharpLanguageTests.cs" />
<Compile Include="Stub.cs" />
</ItemGroup>
@ -63,8 +62,4 @@ @@ -63,8 +62,4 @@
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<ItemGroup>
<Folder Include="TestCases\" />
</ItemGroup>
</Project>

129
ILSpy.Tests/Languages/CSharpLanguageTests.cs

@ -1,129 +0,0 @@ @@ -1,129 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using ICSharpCode.Decompiler.Metadata;
using ICSharpCode.Decompiler.Tests.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.TypeSystem.Implementation;
using ICSharpCode.ILSpy;
using NUnit.Framework;
namespace ILSpy.Tests.Languages
{
[TestFixture, Parallelizable(ParallelScope.All)]
public class CSharpLanguageTests
{
const string ns = "ICSharpCode.Decompiler.Tests.TypeSystem";
static PEFile LoadAssembly(string filename)
{
return new PEFile(filename, new FileStream(filename, FileMode.Open, FileAccess.Read));
}
static readonly Lazy<PEFile> mscorlib = new Lazy<PEFile>(
delegate {
return LoadAssembly(typeof(object).Assembly.Location);
});
static readonly Lazy<PEFile> systemCore = new Lazy<PEFile>(
delegate {
return LoadAssembly(typeof(System.Linq.Enumerable).Assembly.Location);
});
static readonly Lazy<PEFile> testAssembly = new Lazy<PEFile>(
delegate {
return LoadAssembly(typeof(CSharpLanguageTests).Assembly.Location);
});
public static PEFile Mscorlib { get { return mscorlib.Value; } }
public static PEFile SystemCore { get { return systemCore.Value; } }
public static PEFile TestAssembly { get { return testAssembly.Value; } }
[OneTimeSetUp]
public void FixtureSetUp()
{
compilation = new SimpleCompilation(TestAssembly,
Mscorlib.WithOptions(TypeSystemOptions.Default));
language = new CSharpLanguage();
}
ICompilation compilation;
CSharpLanguage language;
ITypeDefinition GetTypeDefinition(Type type)
{
return compilation.FindType(type).GetDefinition();
}
void TestType(Type t, string ns, string name)
{
var type = GetTypeDefinition(t);
Assert.AreEqual(name, language.TypeToString(type, includeNamespace: false));
Assert.AreEqual(ns + "." + name, language.TypeToString(type, includeNamespace: true));
}
void TestMethod(Type t, Predicate<IMember> filter, string ns, string typeName, string name, string paramListReturnType, string longParamListReturnType = null)
{
var type = GetTypeDefinition(t);
var method = type.GetMembers(filter, GetMemberOptions.IgnoreInheritedMembers).Single() as IMethod;
if (method == null)
throw new ArgumentNullException();
if (longParamListReturnType == null)
longParamListReturnType = paramListReturnType;
Assert.AreEqual(name + paramListReturnType, language.MethodToString(method, includeDeclaringTypeName: false, includeNamespace: false, includeNamespaceOfDeclaringTypeName: false));
Assert.AreEqual(typeName + "." + name + paramListReturnType, language.MethodToString(method, includeDeclaringTypeName: true, includeNamespace: false, includeNamespaceOfDeclaringTypeName: false));
Assert.AreEqual(name + longParamListReturnType, language.MethodToString(method, includeDeclaringTypeName: false, includeNamespace: true, includeNamespaceOfDeclaringTypeName: false));
Assert.AreEqual(typeName + "." + name + longParamListReturnType, language.MethodToString(method, includeDeclaringTypeName: true, includeNamespace: true, includeNamespaceOfDeclaringTypeName: false));
Assert.AreEqual(name + paramListReturnType, language.MethodToString(method, includeDeclaringTypeName: false, includeNamespace: false, includeNamespaceOfDeclaringTypeName: true));
Assert.AreEqual(ns + "." + typeName + "." + name + paramListReturnType, language.MethodToString(method, includeDeclaringTypeName: true, includeNamespace: false, includeNamespaceOfDeclaringTypeName: true));
Assert.AreEqual(name + longParamListReturnType, language.MethodToString(method, includeDeclaringTypeName: false, includeNamespace: true, includeNamespaceOfDeclaringTypeName: true));
Assert.AreEqual(ns + "." + typeName + "." + name + longParamListReturnType, language.MethodToString(method, includeDeclaringTypeName: true, includeNamespace: true, includeNamespaceOfDeclaringTypeName: true));
}
[Test]
public void PrimitiveTypes()
{
TestType(typeof(object), "System", "Object");
TestType(typeof(string), "System", "String");
TestType(typeof(int), "System", "Int32");
}
[Test]
public void ClassTests()
{
TestType(typeof(SimplePublicClass), ns, "SimplePublicClass");
TestType(typeof(GenericClass<,>), ns, "GenericClass<A,B>");
TestType(typeof(OuterGeneric<>), ns, "OuterGeneric<X>");
TestType(typeof(OuterGeneric<>.Inner), ns + ".OuterGeneric<X>", "Inner");
}
[Test]
public void InterfaceTests()
{
TestType(typeof(IBase1), ns, "IBase1");
TestType(typeof(IGenericInterface<>), ns, "IGenericInterface<T>");
}
[Test]
public void EnumTests()
{
TestType(typeof(MyEnum), ns, "MyEnum");
TestType(typeof(GenericClass<,>.NestedEnum), ns + ".GenericClass<A,B>", "NestedEnum");
}
[Test]
public void DelegateTests()
{
TestType(typeof(GenericDelegate<,>), ns, "GenericDelegate<T,S>");
}
[Test]
public void MethodTests()
{
TestMethod(typeof(IMarshalAsTests), x => x.Name == "QueryApplicationFile", ns, "IMarshalAsTests", "QueryApplicationFile", "(string, out string, out string, out bool, out bool, out object[]) : void");
TestMethod(typeof(MyClassWithCtor), x => x is IMethod m && m.IsConstructor, ns, "MyClassWithCtor", "MyClassWithCtor", "(int)");
TestMethod(typeof(OuterGeneric<>), x => x is IMethod m && m.IsConstructor, ns, "OuterGeneric<X>", "OuterGeneric<X>", "()");
}
}
}

2
ILSpy.Tests/Stub.cs

@ -1,6 +1,6 @@ @@ -1,6 +1,6 @@
using System;
namespace ILSpy.Tests
namespace ICSharpCode.ILSpy.Tests
{
class Stub
{

176
ILSpy/Languages/CSharpLanguage.cs

@ -21,19 +21,21 @@ using System.Collections.Generic; @@ -21,19 +21,21 @@ using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.IO;
using System.Linq;
using System.Reflection.Metadata;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using ICSharpCode.Decompiler;
using ICSharpCode.Decompiler.CSharp;
using ICSharpCode.Decompiler.CSharp.OutputVisitor;
using ICSharpCode.Decompiler.CSharp.Syntax;
using ICSharpCode.Decompiler.CSharp.Transforms;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.ILSpy.TreeNodes;
using ICSharpCode.Decompiler.Metadata;
using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Output;
using ICSharpCode.Decompiler.TypeSystem;
using ICSharpCode.Decompiler.Util;
using System.Text;
using ICSharpCode.ILSpy.TreeNodes;
namespace ICSharpCode.ILSpy
{
@ -113,7 +115,7 @@ namespace ICSharpCode.ILSpy @@ -113,7 +115,7 @@ namespace ICSharpCode.ILSpy
return decompiler;
}
void WriteCode(ITextOutput output, Decompiler.DecompilerSettings settings, SyntaxTree syntaxTree, IDecompilerTypeSystem typeSystem)
void WriteCode(ITextOutput output, DecompilerSettings settings, SyntaxTree syntaxTree, IDecompilerTypeSystem typeSystem)
{
syntaxTree.AcceptVisitor(new InsertParenthesesVisitor { InsertParenthesesForReadability = true });
TokenWriter tokenWriter = new TextTokenWriter(output, settings, typeSystem) { FoldBraces = settings.FoldBraces, ExpandMemberDefinitions = settings.ExpandMemberDefinitions };
@ -424,170 +426,68 @@ namespace ICSharpCode.ILSpy @@ -424,170 +426,68 @@ namespace ICSharpCode.ILSpy
}
}
static readonly CSharpFormattingOptions TypeToStringFormattingOptions = FormattingOptionsFactory.CreateEmpty();
public override string TypeToString(IType type, bool includeNamespace)
static CSharpAmbience CreateAmbience()
{
if (type == null)
throw new ArgumentNullException(nameof(type));
if (type is ITypeDefinition definition && definition.TypeParameterCount > 0) {
return TypeToStringInternal(new ParameterizedType(definition, definition.TypeParameters), includeNamespace, false);
}
return TypeToStringInternal(type, includeNamespace, false);
CSharpAmbience ambience = new CSharpAmbience();
ambience.ConversionFlags = ConversionFlags.ShowParameterList
| ConversionFlags.ShowReturnType
| ConversionFlags.ShowTypeParameterList
| ConversionFlags.PlaceReturnTypeAfterParameterList;
return ambience;
}
string TypeToStringInternal(IType t, bool includeNamespace, bool useBuiltinTypeNames = true, ParameterModifier parameterModifier = ParameterModifier.None)
static string EntityToString(IEntity entity, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
{
TypeSystemAstBuilder builder = new TypeSystemAstBuilder();
builder.AlwaysUseShortTypeNames = !includeNamespace;
builder.AlwaysUseBuiltinTypeNames = useBuiltinTypeNames;
const ParameterModifier refInOutModifier = ParameterModifier.Ref | ParameterModifier.Out | ParameterModifier.In;
AstType astType = builder.ConvertType(t);
if ((parameterModifier & refInOutModifier) != 0 && astType is ComposedType ct && ct.HasRefSpecifier) {
ct.HasRefSpecifier = false;
}
StringWriter w = new StringWriter();
astType.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions));
string output = w.ToString();
switch (parameterModifier) {
case ParameterModifier.Ref:
output = "ref " + output;
break;
case ParameterModifier.Out:
output = "out " + output;
break;
case ParameterModifier.In:
output = "in " + output;
break;
}
return output;
var ambience = CreateAmbience();
if (includeDeclaringTypeName)
ambience.ConversionFlags |= ConversionFlags.ShowDeclaringType;
if (includeNamespace)
ambience.ConversionFlags |= ConversionFlags.UseFullyQualifiedTypeNames;
if (includeNamespaceOfDeclaringTypeName)
ambience.ConversionFlags |= ConversionFlags.UseFullyQualifiedEntityNames;
return ambience.ConvertSymbol(entity);
}
static ParameterModifier GetModifier(IParameter p)
public override string TypeToString(IType type, bool includeNamespace)
{
if (p.IsRef)
return ParameterModifier.Ref;
if (p.IsOut)
return ParameterModifier.Out;
if (p.IsIn)
return ParameterModifier.In;
return ParameterModifier.None;
if (type == null)
throw new ArgumentNullException(nameof(type));
var ambience = CreateAmbience();
if (includeNamespace)
ambience.ConversionFlags |= ConversionFlags.UseFullyQualifiedTypeNames;
if (type is ITypeDefinition definition) {
return ambience.ConvertSymbol(definition);
} else {
return ambience.ConvertType(type);
}
}
public override string FieldToString(IField field, bool includeDeclaringTypeName, bool includeNamespace, bool includeNamespaceOfDeclaringTypeName)
{
if (field == null)
throw new ArgumentNullException(nameof(field));
string simple = field.Name + " : " + TypeToString(field.Type, includeNamespace);
if (!includeDeclaringTypeName)
return simple;
return TypeToStringInternal(field.DeclaringType, includeNamespaceOfDeclaringTypeName) + "." + simple;
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));
var buffer = new System.Text.StringBuilder();
if (includeDeclaringTypeName) {
buffer.Append(TypeToString(property.DeclaringType, includeNamespaceOfDeclaringTypeName));
buffer.Append('.');
}
if (property.IsIndexer) {
if (property.IsExplicitInterfaceImplementation) {
string name = property.Name;
int index = name.LastIndexOf('.');
if (index > 0) {
buffer.Append(name.Substring(0, index));
buffer.Append('.');
}
}
buffer.Append(@"this[");
int i = 0;
var parameters = property.Parameters;
foreach (var param in parameters) {
if (i > 0)
buffer.Append(", ");
buffer.Append(TypeToStringInternal(param.Type, includeNamespace, parameterModifier: GetModifier(param)));
i++;
}
buffer.Append(@"]");
} else {
buffer.Append(property.Name);
}
buffer.Append(" : ");
buffer.Append(TypeToStringInternal(property.ReturnType, includeNamespace));
return buffer.ToString();
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));
string name;
if (includeDeclaringTypeName) {
name = TypeToString(method.DeclaringType, includeNamespace: includeNamespaceOfDeclaringTypeName) + ".";
} else {
name = "";
}
if (method.IsConstructor) {
name += TypeToString(method.DeclaringType, false);
} else {
name += method.Name;
}
int i = 0;
var buffer = new StringBuilder(name);
if (method.TypeParameters.Count > 0) {
buffer.Append('<');
foreach (var tp in method.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(TypeToStringInternal(param.Type, includeNamespace, parameterModifier: GetModifier(param)));
i++;
}
buffer.Append(')');
if (!method.IsConstructor) {
buffer.Append(" : ");
buffer.Append(TypeToStringInternal(method.ReturnType, includeNamespace));
}
return buffer.ToString();
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));
var buffer = new System.Text.StringBuilder();
if (includeDeclaringTypeName) {
buffer.Append(TypeToString(@event.DeclaringType, includeNamespaceOfDeclaringTypeName) + ".");
}
buffer.Append(@event.Name);
buffer.Append(" : ");
buffer.Append(TypeToStringInternal(@event.ReturnType, includeNamespace));
return buffer.ToString();
return EntityToString(@event, includeDeclaringTypeName, includeNamespace, includeNamespaceOfDeclaringTypeName);
}
string ToCSharpString(MetadataReader metadata, TypeDefinitionHandle handle, bool fullName)

Loading…
Cancel
Save