Browse Source

Fix #2389: missing extern keyword for properties and events.

pull/2408/head
Siegfried Pammer 4 years ago
parent
commit
aa147870a2
  1. 2
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 10
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.cs
  3. 21
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  4. 3
      ICSharpCode.Decompiler/CSharp/Transforms/PatternStatementTransform.cs

2
ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj

@ -191,7 +191,7 @@
<Compile Include="TestCases\Pretty\CustomAttributeConflicts.cs" /> <Compile Include="TestCases\Pretty\CustomAttributeConflicts.cs" />
<Compile Include="TestCases\Pretty\DynamicTests.cs" /> <Compile Include="TestCases\Pretty\DynamicTests.cs" />
<Compile Include="TestCases\Pretty\Issue1080.cs" /> <Compile Include="TestCases\Pretty\Issue1080.cs" />
<Compile Include="TestCases\Pretty\MemberTests.cs" /> <None Include="TestCases\Pretty\MemberTests.cs" />
<Compile Include="TestCases\Pretty\NamedArguments.cs" /> <Compile Include="TestCases\Pretty\NamedArguments.cs" />
<Compile Include="TestCases\Pretty\QualifierTests.cs" /> <Compile Include="TestCases\Pretty\QualifierTests.cs" />
<Compile Include="TestCases\Pretty\RefLocalsAndReturns.cs" /> <Compile Include="TestCases\Pretty\RefLocalsAndReturns.cs" />

10
ICSharpCode.Decompiler.Tests/TestCases/Pretty/MemberTests.cs

@ -30,11 +30,13 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
#if ROSLYN #if ROSLYN
public int this[int index] => 0; public int this[int index] => 0;
#else #else
#pragma warning disable format
public int this[int index] { public int this[int index] {
get { get {
return 0; return 0;
} }
} }
#pragma warning restore format
#endif #endif
} }
@ -49,11 +51,19 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
private volatile int volatileField = 3; private volatile int volatileField = 3;
private static volatile int staticVolatileField = 4; private static volatile int staticVolatileField = 4;
public extern int ExternGetOnly { get; }
public extern int ExternSetOnly { set; }
public extern int ExternProperty { get; set; }
public extern event EventHandler Event;
public void UseVolatileFields() public void UseVolatileFields()
{ {
Console.WriteLine(volatileField + staticVolatileField); Console.WriteLine(volatileField + staticVolatileField);
volatileField++; volatileField++;
staticVolatileField++; staticVolatileField++;
} }
public extern void ExternMethod();
} }
} }

21
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1735,14 +1735,21 @@ namespace ICSharpCode.Decompiler.CSharp
getter = ((IndexerDeclaration)propertyDecl).Getter; getter = ((IndexerDeclaration)propertyDecl).Getter;
setter = ((IndexerDeclaration)propertyDecl).Setter; setter = ((IndexerDeclaration)propertyDecl).Setter;
} }
if (property.CanGet && property.Getter.HasBody)
bool getterHasBody = property.CanGet && property.Getter.HasBody;
bool setterHasBody = property.CanSet && property.Setter.HasBody;
if (getterHasBody)
{ {
DecompileBody(property.Getter, getter, decompileRun, decompilationContext); DecompileBody(property.Getter, getter, decompileRun, decompilationContext);
} }
if (property.CanSet && property.Setter.HasBody) if (setterHasBody)
{ {
DecompileBody(property.Setter, setter, decompileRun, decompilationContext); DecompileBody(property.Setter, setter, decompileRun, decompilationContext);
} }
if (!getterHasBody && !setterHasBody && !property.IsAbstract && property.DeclaringType.Kind != TypeKind.Interface)
{
propertyDecl.Modifiers |= Modifiers.Extern;
}
var accessorHandle = (MethodDefinitionHandle)(property.Getter ?? property.Setter).MetadataToken; var accessorHandle = (MethodDefinitionHandle)(property.Getter ?? property.Setter).MetadataToken;
var accessor = metadata.GetMethodDefinition(accessorHandle); var accessor = metadata.GetMethodDefinition(accessorHandle);
if (!accessorHandle.GetMethodImplementations(metadata).Any() && accessor.HasFlag(System.Reflection.MethodAttributes.Virtual) == accessor.HasFlag(System.Reflection.MethodAttributes.NewSlot)) if (!accessorHandle.GetMethodImplementations(metadata).Any() && accessor.HasFlag(System.Reflection.MethodAttributes.Virtual) == accessor.HasFlag(System.Reflection.MethodAttributes.NewSlot))
@ -1768,14 +1775,20 @@ namespace ICSharpCode.Decompiler.CSharp
{ {
eventDecl.Name = ev.Name.Substring(lastDot + 1); eventDecl.Name = ev.Name.Substring(lastDot + 1);
} }
if (ev.CanAdd && ev.AddAccessor.HasBody) bool adderHasBody = ev.CanAdd && ev.AddAccessor.HasBody;
bool removerHasBody = ev.CanRemove && ev.RemoveAccessor.HasBody;
if (adderHasBody)
{ {
DecompileBody(ev.AddAccessor, ((CustomEventDeclaration)eventDecl).AddAccessor, decompileRun, decompilationContext); DecompileBody(ev.AddAccessor, ((CustomEventDeclaration)eventDecl).AddAccessor, decompileRun, decompilationContext);
} }
if (ev.CanRemove && ev.RemoveAccessor.HasBody) if (removerHasBody)
{ {
DecompileBody(ev.RemoveAccessor, ((CustomEventDeclaration)eventDecl).RemoveAccessor, decompileRun, decompilationContext); DecompileBody(ev.RemoveAccessor, ((CustomEventDeclaration)eventDecl).RemoveAccessor, decompileRun, decompilationContext);
} }
if (!adderHasBody && !removerHasBody && !ev.IsAbstract && ev.DeclaringType.Kind != TypeKind.Interface)
{
eventDecl.Modifiers |= Modifiers.Extern;
}
var accessor = metadata.GetMethodDefinition((MethodDefinitionHandle)(ev.AddAccessor ?? ev.RemoveAccessor).MetadataToken); var accessor = metadata.GetMethodDefinition((MethodDefinitionHandle)(ev.AddAccessor ?? ev.RemoveAccessor).MetadataToken);
if (accessor.HasFlag(System.Reflection.MethodAttributes.Virtual) == accessor.HasFlag(System.Reflection.MethodAttributes.NewSlot)) if (accessor.HasFlag(System.Reflection.MethodAttributes.Virtual) == accessor.HasFlag(System.Reflection.MethodAttributes.NewSlot))
{ {

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

@ -986,7 +986,8 @@ namespace ICSharpCode.Decompiler.CSharp.Transforms
{ {
if (!ev.PrivateImplementationType.IsNull) if (!ev.PrivateImplementationType.IsNull)
return null; return null;
if (!ev.Modifiers.HasFlag(Modifiers.Abstract)) const Modifiers withoutBody = Modifiers.Abstract | Modifiers.Extern;
if ((ev.Modifiers & withoutBody) == 0 && ev.GetSymbol() is IEvent symbol && symbol.DeclaringType.Kind != TypeKind.Interface)
{ {
if (!CheckAutomaticEventV4AggressivelyInlined(ev) && !CheckAutomaticEventV4(ev) && !CheckAutomaticEventV2(ev) && !CheckAutomaticEventV4MCS(ev)) if (!CheckAutomaticEventV4AggressivelyInlined(ev) && !CheckAutomaticEventV4(ev) && !CheckAutomaticEventV2(ev) && !CheckAutomaticEventV4MCS(ev))
return null; return null;

Loading…
Cancel
Save