Browse Source

Add basic support for abstract static members in interfaces.

pull/2568/head
Siegfried Pammer 4 years ago
parent
commit
15f49c0079
  1. 1
      ICSharpCode.Decompiler.Tests/ICSharpCode.Decompiler.Tests.csproj
  2. 6
      ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs
  3. 3
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/InterfaceTests.cs
  4. 69
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/StaticAbstractInterfaceMembers.cs
  5. 7
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  6. 14
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

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

@ -108,6 +108,7 @@ @@ -108,6 +108,7 @@
<Compile Include="TestCases\Correctness\DeconstructionTests.cs" />
<Compile Include="TestCases\Correctness\DynamicTests.cs" />
<Compile Include="TestCases\Correctness\StringConcat.cs" />
<None Include="TestCases\Pretty\StaticAbstractInterfaceMembers.cs" />
<Compile Include="TestCases\Pretty\Structs.cs" />
<None Include="TestCases\Pretty\FileScopedNamespaces.cs" />
<Compile Include="TestCases\Pretty\PatternMatching.cs" />

6
ICSharpCode.Decompiler.Tests/PrettyTestRunner.cs

@ -627,6 +627,12 @@ namespace ICSharpCode.Decompiler.Tests @@ -627,6 +627,12 @@ namespace ICSharpCode.Decompiler.Tests
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview);
}
[Test]
public void StaticAbstractInterfaceMembers([ValueSource(nameof(roslynLatestOnlyOptions))] CompilerOptions cscOptions)
{
RunForLibrary(cscOptions: cscOptions | CompilerOptions.Preview | CompilerOptions.ReferenceCore);
}
void RunForLibrary([CallerMemberName] string testName = null, AssemblerOptions asmOptions = AssemblerOptions.None, CompilerOptions cscOptions = CompilerOptions.None, DecompilerSettings decompilerSettings = null)
{
Run(testName, asmOptions | AssemblerOptions.Library, cscOptions | CompilerOptions.Library, decompilerSettings);

3
ICSharpCode.Decompiler.Tests/TestCases/Pretty/InterfaceTests.cs

@ -24,6 +24,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty @@ -24,6 +24,9 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{
public interface IA
{
#if CS80
static int Field;
#endif
int Property1 { get; }
int Property2 { set; }
int Property3 { get; set; }

69
ICSharpCode.Decompiler.Tests/TestCases/Pretty/StaticAbstractInterfaceMembers.cs

@ -0,0 +1,69 @@ @@ -0,0 +1,69 @@
using System;
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.StaticAbstractInterfaceMembers
{
public interface I
{
abstract static int Capacity { get; }
abstract static int Count { get; set; }
abstract static int SetterOnly { set; }
abstract static event EventHandler E;
abstract static I CreateI();
}
public class X : I
{
public static int Capacity { get; }
public static int Count { get; set; }
public static int SetterOnly {
set {
}
}
public static event EventHandler E;
public static I CreateI()
{
return new X();
}
}
public class X2 : I
{
public static int Capacity {
get {
throw new NotImplementedException();
}
}
public static int Count {
get {
throw new NotImplementedException();
}
set {
throw new NotImplementedException();
}
}
public static int SetterOnly {
set {
throw new NotImplementedException();
}
}
public static event EventHandler E {
add {
throw new NotImplementedException();
}
remove {
throw new NotImplementedException();
}
}
public static I CreateI()
{
throw new NotImplementedException();
}
}
}

7
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1073,6 +1073,10 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1073,6 +1073,10 @@ namespace ICSharpCode.Decompiler.CSharp
{
yield break; // cannot create forwarder for existing explicit interface impl
}
if (method.IsStatic)
{
yield break; // cannot create forwarder for static interface impl
}
var genericContext = new Decompiler.TypeSystem.GenericContext(method);
var methodHandle = (MethodDefinitionHandle)method.MetadataToken;
foreach (var h in methodHandle.GetMethodImplementations(metadata))
@ -1464,7 +1468,8 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1464,7 +1468,8 @@ namespace ICSharpCode.Decompiler.CSharp
{
methodDecl.Modifiers |= Modifiers.Extern;
}
if (method.SymbolKind == SymbolKind.Method && !method.IsExplicitInterfaceImplementation && methodDefinition.HasFlag(System.Reflection.MethodAttributes.Virtual) == methodDefinition.HasFlag(System.Reflection.MethodAttributes.NewSlot))
if (method.SymbolKind == SymbolKind.Method && !method.IsExplicitInterfaceImplementation
&& methodDefinition.HasFlag(System.Reflection.MethodAttributes.Virtual) == methodDefinition.HasFlag(System.Reflection.MethodAttributes.NewSlot))
{
SetNewModifier(methodDecl);
}

14
ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs

@ -2312,17 +2312,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2312,17 +2312,19 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
m |= Modifiers.Static;
}
}
else if (member.IsStatic)
{
m |= Modifiers.Static;
}
else
{
if (member.IsStatic)
{
m |= Modifiers.Static;
}
var declaringType = member.DeclaringType;
if (declaringType.Kind == TypeKind.Interface)
{
if (!member.IsVirtual && !member.IsAbstract && !member.IsOverride && member.Accessibility != Accessibility.Private && member is IMethod method2 && method2.HasBody)
m |= Modifiers.Sealed;
if (member.IsAbstract && member.IsStatic)
m |= Modifiers.Abstract;
}
else
{
@ -2330,11 +2332,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2330,11 +2332,11 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
m |= Modifiers.Abstract;
else if (member.IsVirtual && !member.IsOverride)
m |= Modifiers.Virtual;
if (member.IsSealed && !member.IsExplicitInterfaceImplementation)
m |= Modifiers.Sealed;
}
if (member.IsOverride && !member.IsExplicitInterfaceImplementation)
m |= Modifiers.Override;
if (member.IsSealed && !member.IsExplicitInterfaceImplementation)
m |= Modifiers.Sealed;
if (member is IMethod method && method.ThisIsRefReadOnly && method.DeclaringTypeDefinition?.IsReadOnly == false)
m |= Modifiers.Readonly;
}

Loading…
Cancel
Save