Browse Source

Reimplement transform for auto events

pull/832/head
Siegfried Pammer 8 years ago
parent
commit
4b6e0cc462
  1. 4
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  2. 6
      ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs
  3. 74
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
  4. 1
      ICSharpCode.Decompiler/Tests/ICSharpCode.Decompiler.Tests.csproj
  5. 6
      ICSharpCode.Decompiler/Tests/PrettyTestRunner.cs

4
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -202,8 +202,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -202,8 +202,8 @@ namespace ICSharpCode.Decompiler.CSharp
// return true;
}
// event-fields are not [CompilerGenerated]
// if (settings.AutomaticEvents && field.DeclaringType.Events.Any(ev => ev.Name == field.Name))
// return true;
if (settings.AutomaticEvents && field.DeclaringType.Events.Any(ev => ev.Name == field.Name))
return true;
// HACK : only hide fields starting with '__StaticArrayInit'
if (field.DeclaringType.Name.StartsWith("<PrivateImplementationDetails>", StringComparison.Ordinal)) {
if (field.Name.StartsWith("__StaticArrayInit", StringComparison.Ordinal))

6
ICSharpCode.Decompiler/CSharp/Transforms/ConvertConstructorCallIntoInitializer.cs

@ -126,10 +126,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -126,10 +126,10 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (!m.Success)
break;
IMember fieldOrProperty = (m.Get<AstNode>("fieldAccess").Single().GetSymbol() as IMember)?.MemberDefinition;
if (!(fieldOrProperty is IField) && !(fieldOrProperty is IProperty))
IMember fieldOrPropertyOrEvent = (m.Get<AstNode>("fieldAccess").Single().GetSymbol() as IMember)?.MemberDefinition;
if (!(fieldOrPropertyOrEvent is IField) && !(fieldOrPropertyOrEvent is IProperty) && !(fieldOrPropertyOrEvent is IEvent))
break;
AstNode fieldOrPropertyOrEventDecl = members.FirstOrDefault(f => f.GetSymbol() == fieldOrProperty);
AstNode fieldOrPropertyOrEventDecl = members.FirstOrDefault(f => f.GetSymbol() == fieldOrPropertyOrEvent);
if (fieldOrPropertyOrEventDecl == null)
break;
Expression initializer = m.Get<Expression>("initializer").Single();

74
ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

@ -86,6 +86,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -86,6 +86,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
if (result != null)
return result;
}
if (context.Settings.AutomaticEvents) {
result = ReplaceEventFieldAnnotation(expressionStatement);
if (result != null)
return result;
}
return base.VisitExpressionStatement(expressionStatement);
}
@ -1057,15 +1062,28 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -1057,15 +1062,28 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
}
return null;
}
ExpressionStatement ReplaceEventFieldAnnotation(ExpressionStatement expressionStatement)
{
foreach (var identifier in expressionStatement.Descendants.OfType<Identifier>()) {
var parent = identifier.Parent;
var mrr = parent.Annotation<MemberResolveResult>();
var field = mrr?.Member as IField;
if (field == null) continue;
var @event = field.DeclaringType.GetEvents(ev => ev.Name == field.Name, GetMemberOptions.IgnoreInheritedMembers).SingleOrDefault();
if (@event != null) {
parent.RemoveAnnotations<MemberResolveResult>();
parent.AddAnnotation(new MemberResolveResult(mrr.TargetResult, @event));
}
}
return null;
}
#endregion
#region Automatic Events
static readonly Accessor automaticEventPatternV4 = new Accessor {
Attributes = { new Repeat(new AnyNode()) },
Body = new BlockStatement {
new VariableDeclarationStatement { Type = new AnyNode("type"), Variables = { new AnyNode() } },
new VariableDeclarationStatement { Type = new Backreference("type"), Variables = { new AnyNode() } },
new VariableDeclarationStatement { Type = new Backreference("type"), Variables = { new AnyNode() } },
new AssignmentExpression {
Left = new NamedNode("var1", new IdentifierExpression(Pattern.AnyString)),
Operator = AssignmentOperatorType.Assign,
@ -1076,14 +1094,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -1076,14 +1094,15 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
MemberName = Pattern.AnyString
})
},
new DoWhileStatement {
new WhileStatement {
Condition = new PrimitiveExpression(true),
EmbeddedStatement = new BlockStatement {
new AssignmentExpression(new NamedNode("var2", new IdentifierExpression(Pattern.AnyString)), new IdentifierExpressionBackreference("var1")),
new AssignmentExpression {
Left = new NamedNode("var3", new IdentifierExpression(Pattern.AnyString)),
Operator = AssignmentOperatorType.Assign,
Right = new CastExpression(new Backreference("type"), new InvocationExpression(new AnyNode("delegateCombine").ToExpression(), new IdentifierExpressionBackreference("var2"),
new IdentifierExpression("value")
Right = new CastExpression(new AnyNode("type"), new InvocationExpression(new AnyNode("delegateCombine").ToExpression(), new CastExpression(new TypePattern(typeof(System.Delegate)), new IdentifierExpressionBackreference("var2")),
new CastExpression(new TypePattern(typeof(System.Delegate)), new IdentifierExpression("value"))
))
},
new AssignmentExpression {
@ -1096,13 +1115,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -1096,13 +1115,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
new IdentifierExpressionBackreference("var3"),
new IdentifierExpressionBackreference("var2")
}
)}
},
Condition = new BinaryOperatorExpression {
Left = new IdentifierExpressionBackreference("var1"),
Operator = BinaryOperatorType.InEquality,
Right = new IdentifierExpressionBackreference("var2")
}}
)},
new IfElseStatement {
Condition = new BinaryOperatorExpression {
Left = new CastExpression(new TypePattern(typeof(object)), new IdentifierExpressionBackreference("var1")),
Operator = BinaryOperatorType.Equality,
Right = new IdentifierExpressionBackreference("var2")
},
TrueStatement = new BreakStatement()
}
}
}
}};
bool CheckAutomaticEventV4Match(Match m, CustomEventDeclaration ev, bool isAddAccessor)
@ -1113,11 +1136,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -1113,11 +1136,16 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
return false; // field name must match event name
if (!ev.ReturnType.IsMatch(m.Get("type").Single()))
return false; // variable types must match event type
var combineMethod = m.Get<AstNode>("delegateCombine").Single().Parent.Annotation<MethodReference>();
var combineMethod = m.Get<AstNode>("delegateCombine").Single().Parent.GetSymbol() as IMethod;
if (combineMethod == null || combineMethod.Name != (isAddAccessor ? "Combine" : "Remove"))
return false;
return combineMethod.DeclaringType.FullName == "System.Delegate";
}
static readonly string[] attributeTypesToRemoveFromAutoEvents = new[] {
"System.Runtime.CompilerServices.CompilerGeneratedAttribute",
"System.Diagnostics.DebuggerBrowsableAttribute"
};
EventDeclaration TransformAutomaticEvents(CustomEventDeclaration ev)
{
@ -1127,6 +1155,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -1127,6 +1155,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
Match m2 = automaticEventPatternV4.Match(ev.RemoveAccessor);
if (!CheckAutomaticEventV4Match(m2, ev, false))
return null;
RemoveCompilerGeneratedAttribute(ev.AddAccessor.Attributes);
EventDeclaration ed = new EventDeclaration();
ev.Attributes.MoveTo(ed.Attributes);
foreach (var attr in ev.AddAccessor.Attributes) {
@ -1138,12 +1167,21 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms @@ -1138,12 +1167,21 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
ed.Variables.Add(new VariableInitializer(ev.Name));
ed.CopyAnnotationsFrom(ev);
EventDefinition eventDef = ev.Annotation<EventDefinition>();
IEvent eventDef = ev.GetSymbol() as IEvent;
if (eventDef != null) {
FieldDefinition field = eventDef.DeclaringType.Fields.FirstOrDefault(f => f.Name == ev.Name);
IField field = eventDef.DeclaringType.GetFields(f => f.Name == ev.Name, GetMemberOptions.IgnoreInheritedMembers).SingleOrDefault();
if (field != null) {
ed.AddAnnotation(field);
// TODO AstBuilder.ConvertAttributes(ed, field, "field");
var attributes = field.Attributes
.Where(a => !attributeTypesToRemoveFromAutoEvents.Any(t => t == a.AttributeType.FullName))
.Select(context.TypeSystemAstBuilder.ConvertAttribute).ToArray();
if (attributes.Length > 0) {
var section = new AttributeSection {
AttributeTarget = "field"
};
section.Attributes.AddRange(attributes);
ed.Attributes.Add(section);
}
}
}

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

@ -153,6 +153,7 @@ @@ -153,6 +153,7 @@
<Compile Include="TestCases\Pretty\ExceptionHandling.cs" />
<Compile Include="TestCases\Pretty\HelloWorld.cs" />
<Compile Include="TestCases\Pretty\InlineAssignmentTest.cs" />
<Compile Include="TestCases\Pretty\PropertiesAndEvents.cs" />
<Compile Include="TestCases\Pretty\ShortCircuit.cs" />
<Compile Include="TestTraceListener.cs" />
<Compile Include="Util\IntervalTests.cs" />

6
ICSharpCode.Decompiler/Tests/PrettyTestRunner.cs

@ -115,6 +115,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -115,6 +115,12 @@ namespace ICSharpCode.Decompiler.Tests
Run(cscOptions: cscOptions);
}
[Test]
public void PropertiesAndEvents([ValueSource("defaultOptions")] CompilerOptions cscOptions)
{
Run(cscOptions: cscOptions);
}
[Test]
public void AutoProperties([ValueSource("roslynOnlyOptions")] CompilerOptions cscOptions)
{

Loading…
Cancel
Save