Skip to content

Commit

Permalink
#894: Transform IsByRefLikeAttribute and IsReadOnlyAttribute on struc…
Browse files Browse the repository at this point in the history
…ts to ref and readonly modifiers, respectively. Remove ObsoleteAttribute.
  • Loading branch information
siegfriedpammer committed Mar 4, 2018
1 parent 6362244 commit 3dcc388
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 9 deletions.
50 changes: 42 additions & 8 deletions ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util;
using System.IO;
using ICSharpCode.Decompiler.CSharp.Syntax.PatternMatching;

namespace ICSharpCode.Decompiler.CSharp
{
Expand Down Expand Up @@ -667,20 +668,35 @@ EntityDeclaration DoDecompile(ITypeDefinition typeDef, ITypeResolveContext decom
}
if (typeDecl.Members.OfType<IndexerDeclaration>().Any(idx => idx.PrivateImplementationType.IsNull)) {
// Remove the [DefaultMember] attribute if the class contains indexers
foreach (AttributeSection section in typeDecl.Attributes) {
foreach (var attr in section.Attributes) {
var tr = attr.Type.GetResolveResult().Type;
if (tr.Name == "DefaultMemberAttribute" && tr.Namespace == "System.Reflection") {
RemoveAttribute(typeDecl, new TopLevelTypeName("System.Reflection", "DefaultMemberAttribute"));
}
if (settings.IntroduceRefAndReadonlyModifiersOnStructs && typeDecl.ClassType == ClassType.Struct) {
if (RemoveAttribute(typeDecl, new TopLevelTypeName("System.Runtime.CompilerServices", "IsByRefLikeAttribute"))) {
typeDecl.Modifiers |= Modifiers.Ref;
}
if (RemoveAttribute(typeDecl, new TopLevelTypeName("System.Runtime.CompilerServices", "IsReadOnlyAttribute"))) {
typeDecl.Modifiers |= Modifiers.Readonly;
}
if (FindAttribute(typeDecl, new TopLevelTypeName("System", "ObsoleteAttribute"), out var attr)) {
if (obsoleteAttributePattern.IsMatch(attr)) {
if (attr.Parent is Syntax.AttributeSection section && section.Attributes.Count == 1)
section.Remove();
else
attr.Remove();
}
}
if (section.Attributes.Count == 0)
section.Remove();
}
}
return typeDecl;
}

static readonly Syntax.Attribute obsoleteAttributePattern = new Syntax.Attribute() {
Type = new TypePattern(typeof(ObsoleteAttribute)),
Arguments = {
new PrimitiveExpression("Types with embedded references are not supported in this version of your compiler."),
new Choice() { new PrimitiveExpression(true), new PrimitiveExpression(false) }
}
};

MethodDeclaration GenerateConvHelper(string name, KnownTypeCode source, KnownTypeCode target, TypeSystemAstBuilder typeSystemAstBuilder,
Expression intermediate32, Expression intermediate64)
{
Expand Down Expand Up @@ -806,19 +822,37 @@ void DecompileBody(MethodDefinition methodDefinition, IMethod method, EntityDecl
}
}

void RemoveAttribute(EntityDeclaration entityDecl, FullTypeName attrName)
bool RemoveAttribute(EntityDeclaration entityDecl, FullTypeName attrName)
{
bool found = false;
foreach (var section in entityDecl.Attributes) {
foreach (var attr in section.Attributes) {
var symbol = attr.Type.GetSymbol();
if (symbol is ITypeDefinition td && td.FullTypeName == attrName) {
attr.Remove();
found = true;
}
}
if (section.Attributes.Count == 0) {
section.Remove();
}
}
return found;
}

bool FindAttribute(EntityDeclaration entityDecl, FullTypeName attrName, out Syntax.Attribute attribute)
{
attribute = null;
foreach (var section in entityDecl.Attributes) {
foreach (var attr in section.Attributes) {
var symbol = attr.Type.GetSymbol();
if (symbol is ITypeDefinition td && td.FullTypeName == attrName) {
attribute = attr;
return true;
}
}
}
return false;
}

HashSet<string> definedSymbols;
Expand Down
20 changes: 19 additions & 1 deletion ICSharpCode.Decompiler/DecompilerSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ public DecompilerSettings(CSharp.LanguageVersion languageVersion)
if (languageVersion < CSharp.LanguageVersion.CSharp7) {
outVariables = false;
}
if (languageVersion < CSharp.LanguageVersion.CSharp7_2) {
introduceRefAndReadonlyModifiersOnStructs = false;
}
}

bool anonymousMethods = true;
Expand Down Expand Up @@ -520,7 +523,7 @@ public bool UseExpressionBodyForCalculatedGetterOnlyProperties {
bool outVariables = true;

/// <summary>
/// Gets/Sets whether simple calculated getter-only property declarations should use expression body syntax.
/// Gets/Sets whether out variable declarations should be used when possible.
/// </summary>
public bool OutVariables {
get { return outVariables; }
Expand All @@ -532,6 +535,21 @@ public bool OutVariables {
}
}

bool introduceRefAndReadonlyModifiersOnStructs = true;

/// <summary>
/// Gets/Sets whether IsByRefLikeAttribute and IsReadOnlyAttribute should be replaced with 'ref' and 'readonly' modifiers on structs.
/// </summary>
public bool IntroduceRefAndReadonlyModifiersOnStructs {
get { return introduceRefAndReadonlyModifiersOnStructs; }
set {
if (introduceRefAndReadonlyModifiersOnStructs != value) {
introduceRefAndReadonlyModifiersOnStructs = value;
OnPropertyChanged();
}
}
}

#region Options to aid VB decompilation
bool introduceIncrementAndDecrement = true;

Expand Down

0 comments on commit 3dcc388

Please sign in to comment.