Browse Source

Implement support for explicit interface implementation of operators and operator uses.

pull/3050/head
Siegfried Pammer 2 years ago
parent
commit
591ab6b75d
  1. 105
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/StaticAbstractInterfaceMembers.cs
  2. 2
      ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs
  4. 13
      ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/OperatorDeclaration.cs
  5. 9
      ICSharpCode.Decompiler/CSharp/Syntax/TypeSystemAstBuilder.cs
  6. 6
      ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs

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

@ -2,11 +2,59 @@ @@ -2,11 +2,59 @@
namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.StaticAbstractInterfaceMembers
{
internal class C : I<C>
{
private string _s;
static C I<C>.P { get; set; }
static event Action I<C>.E {
add {
}
remove {
}
}
public C(string s)
{
_s = s;
}
static void I<C>.M(object x)
{
Console.WriteLine("Implementation");
}
static C I<C>.operator +(C l, C r)
{
return new C(l._s + " " + r._s);
}
static bool I<C>.operator ==(C l, C r)
{
return l._s == r._s;
}
static bool I<C>.operator !=(C l, C r)
{
return l._s != r._s;
}
static implicit I<C>.operator C(string s)
{
return new C(s);
}
static explicit I<C>.operator string(C c)
{
return c._s;
}
}
internal interface I<T> where T : I<T>
{
static abstract T P { get; set; }
static abstract event Action E;
static abstract void M();
static abstract void M(object x);
static abstract T operator +(T l, T r);
static abstract bool operator ==(T l, T r);
static abstract bool operator !=(T l, T r);
@ -25,28 +73,77 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.StaticAbstractInterfaceM @@ -25,28 +73,77 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty.StaticAbstractInterfaceM
internal interface IAmStatic<T> where T : IAmStatic<T>
{
static int f;
static T P { get; set; }
static event Action E;
static void M()
static void M(object x)
{
}
static T operator +(IAmStatic<T> l, T r)
static IAmStatic<T> operator +(IAmStatic<T> l, IAmStatic<T> r)
{
throw new NotImplementedException();
}
static IAmStatic()
{
f = 42;
}
}
internal interface IAmVirtual<T> where T : IAmVirtual<T>
{
static virtual T P { get; set; }
static virtual event Action E;
static virtual void M()
static virtual void M(object x)
{
}
static virtual T operator +(T l, T r)
{
throw new NotImplementedException();
}
static virtual implicit operator T(string s)
{
return default(T);
}
static virtual explicit operator string(T t)
{
return null;
}
}
internal class Uses
{
public static T TestVirtualStaticUse<T>(T a, T b) where T : IAmVirtual<T>
{
T.P = a;
a = "World";
T.E += null;
T.E -= null;
T.M("Hello");
UseString((string)b);
return a + b;
}
public static IAmStatic<T> TestStaticUse<T>(T a, T b) where T : IAmStatic<T>
{
IAmStatic<T>.f = 11;
IAmStatic<T>.P = a;
IAmStatic<T>.E += null;
IAmStatic<T>.E -= null;
IAmStatic<T>.M("Hello");
return a + b;
}
public static I<T> TestAbstractStaticUse<T>(T a, T b) where T : I<T>
{
T.P = a;
a = "World";
T.E += null;
T.E -= null;
T.M("Hello");
UseString((string)b);
return a + b;
}
private static void UseString(string a)
{
}
}
public class X : IAmSimple

2
ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs

@ -1585,7 +1585,7 @@ namespace ICSharpCode.Decompiler.CSharp @@ -1585,7 +1585,7 @@ namespace ICSharpCode.Decompiler.CSharp
var typeSystemAstBuilder = CreateAstBuilder(decompileRun.Settings);
var methodDecl = typeSystemAstBuilder.ConvertEntity(method);
int lastDot = method.Name.LastIndexOf('.');
if (method.IsExplicitInterfaceImplementation && lastDot >= 0)
if (methodDecl is not OperatorDeclaration && method.IsExplicitInterfaceImplementation && lastDot >= 0)
{
methodDecl.Name = method.Name.Substring(lastDot + 1);
}

2
ICSharpCode.Decompiler/CSharp/OutputVisitor/CSharpOutputVisitor.cs

@ -2574,6 +2574,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor @@ -2574,6 +2574,8 @@ namespace ICSharpCode.Decompiler.CSharp.OutputVisitor
{
operatorDeclaration.ReturnType.AcceptVisitor(this);
}
Space();
WritePrivateImplementationType(operatorDeclaration.PrivateImplementationType);
WriteKeyword(OperatorDeclaration.OperatorKeywordRole);
Space();
if (OperatorDeclaration.IsChecked(operatorDeclaration.OperatorType))

13
ICSharpCode.Decompiler/CSharp/Syntax/TypeMembers/OperatorDeclaration.cs

@ -159,6 +159,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -159,6 +159,15 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
get { return SymbolKind.Operator; }
}
/// <summary>
/// Gets/Sets the type reference of the interface that is explicitly implemented.
/// Null node if this member is not an explicit interface implementation.
/// </summary>
public AstType PrivateImplementationType {
get { return GetChildByRole(PrivateImplementationTypeRole); }
set { SetChildByRole(PrivateImplementationTypeRole, value); }
}
OperatorType operatorType;
public OperatorType OperatorType {
@ -347,7 +356,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -347,7 +356,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
protected internal override bool DoMatch(AstNode other, PatternMatching.Match match)
{
OperatorDeclaration o = other as OperatorDeclaration;
return o != null && this.MatchAttributesAndModifiers(o, match) && this.OperatorType == o.OperatorType
return o != null && this.MatchAttributesAndModifiers(o, match)
&& this.PrivateImplementationType.DoMatch(o.PrivateImplementationType, match)
&& this.OperatorType == o.OperatorType
&& this.ReturnType.DoMatch(o.ReturnType, match)
&& this.Parameters.DoMatch(o.Parameters, match) && this.Body.DoMatch(o.Body, match);
}

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

@ -1740,6 +1740,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -1740,6 +1740,10 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
case SymbolKind.Event:
return ConvertEvent((IEvent)entity);
case SymbolKind.Method:
if (entity.Name.Contains(".op_"))
{
goto case SymbolKind.Operator;
}
return ConvertMethod((IMethod)entity);
case SymbolKind.Operator:
return ConvertOperator((IMethod)entity);
@ -2225,7 +2229,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2225,7 +2229,9 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
EntityDeclaration ConvertOperator(IMethod op)
{
OperatorType? opType = OperatorDeclaration.GetOperatorType(op.Name);
int dot = op.Name.LastIndexOf('.');
string name = op.Name.Substring(dot + 1);
OperatorType? opType = OperatorDeclaration.GetOperatorType(name);
if (opType == null)
return ConvertMethod(op);
if (opType == OperatorType.UnsignedRightShift && !SupportUnsignedRightShift)
@ -2255,6 +2261,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax @@ -2255,6 +2261,7 @@ namespace ICSharpCode.Decompiler.CSharp.Syntax
decl.AddAnnotation(new MemberResolveResult(null, op));
}
decl.Body = GenerateBodyBlock();
decl.PrivateImplementationType = GetExplicitInterfaceType(op);
return decl;
}

6
ICSharpCode.Decompiler/TypeSystem/Implementation/AbstractTypeParameter.cs

@ -378,10 +378,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation @@ -378,10 +378,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
static Predicate<T> FilterNonStatic<T>(Predicate<T> filter) where T : class, IMember
{
if (filter == null)
return member => !member.IsStatic;
else
return member => !member.IsStatic && filter(member);
return member => (!member.IsStatic || member.SymbolKind == SymbolKind.Operator || member.IsVirtual)
&& (filter == null || filter(member));
}
public sealed override bool Equals(object obj)

Loading…
Cancel
Save