diff --git a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
index 074902fe0..27a8e277a 100644
--- a/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
+++ b/ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
@@ -110,6 +110,8 @@
+
+
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBAutomaticEvents.cs b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBAutomaticEvents.cs
new file mode 100644
index 000000000..29bfd5557
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBAutomaticEvents.cs
@@ -0,0 +1,14 @@
+public class VBAutomaticEvents
+{
+ public delegate void EventWithParameterEventHandler(int EventNumber);
+ public delegate void EventWithoutParameterEventHandler();
+
+ public event EventWithParameterEventHandler EventWithParameter;
+ public event EventWithoutParameterEventHandler EventWithoutParameter;
+
+ public void RaiseEvents()
+ {
+ EventWithParameter?.Invoke(1);
+ EventWithoutParameter?.Invoke();
+ }
+}
diff --git a/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBAutomaticEvents.vb b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBAutomaticEvents.vb
new file mode 100644
index 000000000..361cb6b17
--- /dev/null
+++ b/ICSharpCode.Decompiler.Tests/TestCases/VBPretty/VBAutomaticEvents.vb
@@ -0,0 +1,9 @@
+Public Class VBAutomaticEvents
+ Event EventWithParameter(ByVal EventNumber As Integer)
+ Event EventWithoutParameter()
+
+ Sub RaiseEvents()
+ RaiseEvent EventWithParameter(1)
+ RaiseEvent EventWithoutParameter()
+ End Sub
+End Class
diff --git a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs
index b5db5269b..b9a609cda 100644
--- a/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs
+++ b/ICSharpCode.Decompiler.Tests/VBPrettyTestRunner.cs
@@ -1,4 +1,4 @@
-// Copyright (c) AlphaSierraPapa for the SharpDevelop Team
+// Copyright (c) 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
@@ -125,6 +125,12 @@ namespace ICSharpCode.Decompiler.Tests
await Run(options: options | CompilerOptions.Library);
}
+ [Test]
+ public async Task VBAutomaticEvents([ValueSource(nameof(defaultOptions))] CompilerOptions options)
+ {
+ await Run(options: options | CompilerOptions.Library);
+ }
+
async Task Run([CallerMemberName] string testName = null, CompilerOptions options = CompilerOptions.UseDebug, DecompilerSettings settings = null)
{
var vbFile = Path.Combine(TestCasePath, testName + ".vb");
diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
index 087b509c0..13d9c067b 100644
--- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
@@ -1,4 +1,4 @@
-// Copyright (c) 2014 Daniel Grunwald
+// Copyright (c) 2014 Daniel Grunwald
//
// 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
@@ -367,8 +367,16 @@ namespace ICSharpCode.Decompiler.CSharp
return true;
}
// event-fields are not [CompilerGenerated]
- if (settings.AutomaticEvents && metadata.GetTypeDefinition(field.GetDeclaringType()).GetEvents().Any(ev => metadata.GetEventDefinition(ev).Name == field.Name))
- return true;
+ if (settings.AutomaticEvents)
+ {
+ foreach (var ev in metadata.GetTypeDefinition(field.GetDeclaringType()).GetEvents())
+ {
+ var eventName = metadata.GetString(metadata.GetEventDefinition(ev).Name);
+ var fieldName = metadata.GetString(field.Name);
+ if (IsEventBackingFieldName(fieldName, eventName, out _))
+ return true;
+ }
+ }
if (settings.ArrayInitializers && metadata.GetString(metadata.GetTypeDefinition(field.GetDeclaringType()).Name).StartsWith("", StringComparison.Ordinal))
{
// only hide fields starting with '__StaticArrayInit'
@@ -412,6 +420,20 @@ namespace ICSharpCode.Decompiler.CSharp
return false;
}
+ internal static bool IsEventBackingFieldName(string fieldName, string eventName, out int suffixLength)
+ {
+ suffixLength = 0;
+ if (fieldName == eventName)
+ return true;
+ var vbSuffixLength = "Event".Length;
+ if (fieldName.Length == eventName.Length + vbSuffixLength && fieldName.StartsWith(eventName, StringComparison.Ordinal) && fieldName.EndsWith("Event", StringComparison.Ordinal))
+ {
+ suffixLength = vbSuffixLength;
+ return true;
+ }
+ return false;
+ }
+
static bool IsAnonymousMethodCacheField(SRM.FieldDefinition field, MetadataReader metadata)
{
var name = metadata.GetString(field.Name);
diff --git a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
index ca35ea946..f9a605012 100644
--- a/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
+++ b/ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs
@@ -1,4 +1,4 @@
-// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
+// Copyright (c) 2011 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
@@ -763,12 +763,17 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
var field = mrr?.Member as IField;
if (field == null)
return null;
- var @event = field.DeclaringType.GetEvents(ev => ev.Name == field.Name, GetMemberOptions.IgnoreInheritedMembers).SingleOrDefault();
- if (@event != null && currentMethod.AccessorOwner != @event)
+ foreach (var ev in field.DeclaringType.GetEvents(null, GetMemberOptions.IgnoreInheritedMembers))
{
- parent.RemoveAnnotations();
- parent.AddAnnotation(new MemberResolveResult(mrr.TargetResult, @event));
- return identifier;
+ if (CSharpDecompiler.IsEventBackingFieldName(field.Name, ev.Name, out int suffixLength) &&
+ currentMethod.AccessorOwner != ev)
+ {
+ parent.RemoveAnnotations();
+ parent.AddAnnotation(new MemberResolveResult(mrr.TargetResult, ev));
+ if (suffixLength != 0)
+ identifier.Name = identifier.Name.Substring(0, identifier.Name.Length - suffixLength);
+ return identifier;
+ }
}
return null;
}
@@ -911,11 +916,11 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
switch (fieldExpression)
{
case IdentifierExpression identifier:
- if (identifier.Identifier != ev.Name)
+ if (!CSharpDecompiler.IsEventBackingFieldName(identifier.Identifier, ev.Name, out _))
return false;
break;
case MemberReferenceExpression memberRef:
- if (memberRef.MemberName != ev.Name)
+ if (!CSharpDecompiler.IsEventBackingFieldName(memberRef.MemberName, ev.Name, out _))
return false;
break;
default:
@@ -1013,7 +1018,7 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
ed.CopyAnnotationsFrom(ev);
var fieldDecl = ev.Parent?.Children.OfType()
- .FirstOrDefault(fd => fd.Variables.Single().Name == ev.Name);
+ .FirstOrDefault(fd => CSharpDecompiler.IsEventBackingFieldName(fd.Variables.Single().Name, ev.Name, out _));
if (fieldDecl != null)
{
fieldDecl.Remove();