Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down
403 changes: 403 additions & 0 deletions ICSharpCode.Decompiler.Tests/Output/ILAmbienceTests.cs

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpAmbience.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -58,8 +60,7 @@ public void ConvertSymbol(ISymbol symbol, TokenWriter writer, CSharpFormattingOp
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)
Expand Down Expand Up @@ -280,7 +281,7 @@ void WriteMemberDeclarationName(IMember member, TokenWriter writer, CSharpFormat
ConvertType(member.DeclaringType, writer, formattingPolicy);
writer.WriteToken(Roles.Dot, ".");
}
IType explicitInterfaceType = GetExplicitInterfaceType(member);
IType? explicitInterfaceType = GetExplicitInterfaceType(member);
string name = member.Name;
if (explicitInterfaceType != null)
{
Expand All @@ -297,11 +298,11 @@ void WriteMemberDeclarationName(IMember member, TokenWriter writer, CSharpFormat
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)
Expand Down Expand Up @@ -431,15 +432,15 @@ public string ConvertType(IType type)
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;
AstType astType = astBuilder.ConvertType(type);
astType.AcceptVisitor(new CSharpOutputVisitor(writer, formattingPolicy));
}

IType GetExplicitInterfaceType(IMember member)
IType? GetExplicitInterfaceType(IMember member)
{
if (member.IsExplicitInterfaceImplementation)
{
Expand Down
58 changes: 31 additions & 27 deletions ICSharpCode.Decompiler/Disassembler/ReflectionDisassembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ public ReflectionDisassembler(ITextOutput output, MethodBodyDisassembler methodB
}

#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" },
Expand All @@ -115,7 +115,7 @@ public ReflectionDisassembler(ITextOutput output, MethodBodyDisassembler methodB
{ 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" },
Expand All @@ -124,7 +124,7 @@ public ReflectionDisassembler(ITextOutput output, MethodBodyDisassembler methodB
{ 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" },
Expand All @@ -133,14 +133,14 @@ public ReflectionDisassembler(ITextOutput output, MethodBodyDisassembler methodB
{ 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" },
Expand Down Expand Up @@ -180,8 +180,8 @@ void DisassembleMethodHeaderInternal(MetadataFile module, MethodDefinitionHandle
// 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 ");
Expand Down Expand Up @@ -259,7 +259,7 @@ void DisassembleMethodHeaderInternal(MetadataFile module, MethodDefinitionHandle
}

//call convention
WriteEnum(signature.Value.Header.CallingConvention, callingConvention);
WriteEnum(signature.Value.Header.CallingConvention, callingConvention, output);

//return type
signature.Value.ReturnType(ILNameSyntax.Signature);
Expand Down Expand Up @@ -307,12 +307,12 @@ void DisassembleMethodHeaderInternal(MetadataFile module, MethodDefinitionHandle
}
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();
}
Expand Down Expand Up @@ -1267,7 +1267,7 @@ void WriteConstant(MetadataReader metadata, Constant constant)
#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" },
Expand All @@ -1276,7 +1276,7 @@ void WriteConstant(MetadataReader metadata, Constant constant)
{ 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" },
Expand Down Expand Up @@ -1360,9 +1360,9 @@ private char DisassembleFieldHeaderInternal(MetadataFile module, FieldDefinition
{
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));

Expand Down Expand Up @@ -1415,7 +1415,7 @@ char GetRVASectionPrefix(MetadataFile module, int rva)
#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" },
Expand Down Expand Up @@ -1450,7 +1450,7 @@ private PropertyAccessors DisassemblePropertyHeaderInternal(MetadataFile module,
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));
Expand Down Expand Up @@ -1489,7 +1489,7 @@ void WriteNestedMethod(string keyword, MetadataFile module, MethodDefinitionHand
#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" },
};
Expand Down Expand Up @@ -1536,7 +1536,7 @@ private void DisassembleEventHeaderInternal(MetadataFile module, EventDefinition
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)
Expand All @@ -1561,7 +1561,7 @@ private void DisassembleEventHeaderInternal(MetadataFile module, EventDefinition
#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" },
Expand All @@ -1584,7 +1584,7 @@ private void DisassembleEventHeaderInternal(MetadataFile module, EventDefinition
{ 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" },
Expand Down Expand Up @@ -1730,11 +1730,11 @@ private void DisassembleTypeHeaderInternal(MetadataFile module, TypeDefinitionHa
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());
Expand Down Expand Up @@ -1967,7 +1967,7 @@ void CloseBlock(string comment = null)
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;
Expand All @@ -1984,7 +1984,7 @@ void WriteFlags<T>(T flags, EnumNameCollection<T> flagNames) where T : struct
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)
Expand All @@ -2006,10 +2006,14 @@ void WriteEnum<T>(T enumValue, EnumNameCollection<T> enumNames) where T : struct

}

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>>();
Comment thread
siegfriedpammer marked this conversation as resolved.

public EnumNameCollection()
{
Comment thread
siegfriedpammer marked this conversation as resolved.
}

public void Add(T flag, string name)
{
this.names.Add(new KeyValuePair<long, string>(Convert.ToInt64(flag), name));
Expand Down
1 change: 1 addition & 0 deletions ICSharpCode.Decompiler/ICSharpCode.Decompiler.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -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" />
Expand Down
Loading
Loading