Browse Source

Don't show compiler-generated code for automatic properties. Closes #69.

pull/100/head
Daniel Grunwald 15 years ago
parent
commit
41d6c3f6eb
  1. 6
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 77
      ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs
  3. 2
      ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs
  4. 45
      ICSharpCode.Decompiler/DecompilerSettings.cs

6
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -50,8 +50,10 @@ namespace ICSharpCode.Decompiler.Ast @@ -50,8 +50,10 @@ namespace ICSharpCode.Decompiler.Ast
return true;
}
FieldDefinition field = member as FieldDefinition;
if (field != null) {
if (settings.AnonymousMethods && field.Name.StartsWith("CS$<>", StringComparison.Ordinal) && field.IsCompilerGenerated())
if (field != null && field.IsCompilerGenerated()) {
if (settings.AnonymousMethods && field.Name.StartsWith("CS$<>", StringComparison.Ordinal))
return true;
if (settings.AutomaticProperties && field.Name.StartsWith("<", StringComparison.Ordinal) && field.Name.EndsWith("BackingField", StringComparison.Ordinal))
return true;
}
return false;

77
ICSharpCode.Decompiler/Ast/Transforms/PatternStatementTransform.cs

@ -14,11 +14,24 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -14,11 +14,24 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
/// </summary>
public class PatternStatementTransform : IAstTransform
{
DecompilerContext context;
public PatternStatementTransform(DecompilerContext context)
{
if (context == null)
throw new ArgumentNullException("context");
this.context = context;
}
public void Run(AstNode compilationUnit)
{
if (context.Settings.UsingStatement)
TransformUsings(compilationUnit);
if (context.Settings.ForEachStatement)
TransformForeach(compilationUnit);
TransformFor(compilationUnit);
if (context.Settings.AutomaticProperties)
TransformAutomaticProperties(compilationUnit);
}
/// <summary>
@ -99,7 +112,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -99,7 +112,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
#endregion
#region foreach
UsingStatement foreachPattern = new UsingStatement {
static readonly UsingStatement foreachPattern = new UsingStatement {
ResourceAcquisition = new VariableDeclarationStatement {
Type = new AnyNode("enumeratorType"),
Variables = {
@ -188,7 +201,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -188,7 +201,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
#endregion
#region for
WhileStatement forPattern = new WhileStatement {
static readonly WhileStatement forPattern = new WhileStatement {
Condition = new BinaryOperatorExpression {
Left = new NamedNode("ident", new IdentifierExpression()),
Operator = BinaryOperatorType.Any,
@ -237,5 +250,65 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -237,5 +250,65 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
}
}
#endregion
#region Automatic Properties
static readonly PropertyDeclaration automaticPropertyPattern = new PropertyDeclaration {
Attributes = { new Repeat(new AnyNode()) },
Modifiers = Modifiers.Any,
ReturnType = new AnyNode(),
Getter = new Accessor {
Attributes = { new Repeat(new AnyNode()) },
Modifiers = Modifiers.Any,
Body = new BlockStatement {
new ReturnStatement {
Expression = new NamedNode("fieldReference", new MemberReferenceExpression { Target = new ThisReferenceExpression() })
}
}
},
Setter = new Accessor {
Attributes = { new Repeat(new AnyNode()) },
Modifiers = Modifiers.Any,
Body = new BlockStatement {
new AssignmentExpression {
Left = new Backreference("fieldReference"),
Right = new IdentifierExpression("value")
}
}}};
void TransformAutomaticProperties(AstNode compilationUnit)
{
foreach (var property in compilationUnit.Descendants.OfType<PropertyDeclaration>()) {
PropertyDefinition cecilProperty = property.Annotation<PropertyDefinition>();
if (cecilProperty == null || cecilProperty.GetMethod == null || cecilProperty.SetMethod == null)
continue;
if (!(cecilProperty.GetMethod.IsCompilerGenerated() && cecilProperty.SetMethod.IsCompilerGenerated()))
continue;
Match m = automaticPropertyPattern.Match(property);
if (m != null) {
FieldDefinition field = m.Get("fieldReference").Single().Annotation<FieldDefinition>();
if (field.IsCompilerGenerated()) {
RemoveCompilerGeneratedAttribute(property.Getter.Attributes);
RemoveCompilerGeneratedAttribute(property.Setter.Attributes);
property.Getter.Body = null;
property.Setter.Body = null;
}
}
}
}
void RemoveCompilerGeneratedAttribute(AstNodeCollection<AttributeSection> attributeSections)
{
foreach (AttributeSection section in attributeSections) {
foreach (var attr in section.Attributes) {
TypeReference tr = attr.Type.Annotation<TypeReference>();
if (tr != null && tr.Namespace == "System.Runtime.CompilerServices" && tr.Name == "CompilerGeneratedAttribute") {
attr.Remove();
}
}
if (section.Attributes.Count == 0)
section.Remove();
}
}
#endregion
}
}

2
ICSharpCode.Decompiler/Ast/Transforms/TransformationPipeline.cs

@ -19,7 +19,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms @@ -19,7 +19,7 @@ namespace ICSharpCode.Decompiler.Ast.Transforms
return new IAstTransform[] {
new PushNegation(),
new DelegateConstruction(context),
new PatternStatementTransform(),
new PatternStatementTransform(context),
new ConvertConstructorCallIntoInitializer(),
new ReplaceMethodCallsWithOperators(),
};

45
ICSharpCode.Decompiler/DecompilerSettings.cs

@ -41,6 +41,51 @@ namespace ICSharpCode.Decompiler @@ -41,6 +41,51 @@ namespace ICSharpCode.Decompiler
}
}
bool automaticProperties = true;
/// <summary>
/// Decompile automatic properties
/// </summary>
public bool AutomaticProperties {
get { return automaticProperties; }
set {
if (automaticProperties != value) {
automaticProperties = value;
OnPropertyChanged("AutomaticProperties");
}
}
}
bool usingStatement = true;
/// <summary>
/// Decompile using statements.
/// </summary>
public bool UsingStatement {
get { return usingStatement; }
set {
if (usingStatement != value) {
usingStatement = value;
OnPropertyChanged("UsingStatement");
}
}
}
bool forEachStatement = true;
/// <summary>
/// Decompile foreach statements.
/// </summary>
public bool ForEachStatement {
get { return forEachStatement; }
set {
if (forEachStatement != value) {
forEachStatement = value;
OnPropertyChanged("ForEachStatement");
}
}
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged(string propertyName)

Loading…
Cancel
Save