Browse Source

Expose IMethod.AccessorKind. This makes it easier to determine if a method is a setter, particular in generic classes where "m.AccessorOwner?.Setter == m" ended up being wrong.

pull/1464/head
Daniel Grunwald 7 years ago
parent
commit
a5505ab00d
  1. 20
      ICSharpCode.Decompiler.Tests/TestCases/Pretty/ValueTypes.cs
  2. 15
      ICSharpCode.Decompiler/CSharp/Resolver/ReducedExtensionMethod.cs
  3. 2
      ICSharpCode.Decompiler/CSharp/StatementBuilder.cs
  4. 18
      ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs
  5. 6
      ICSharpCode.Decompiler/TypeSystem/IMethod.cs
  6. 2
      ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs
  7. 3
      ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs
  8. 3
      ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs
  9. 15
      ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs

20
ICSharpCode.Decompiler.Tests/TestCases/Pretty/ValueTypes.cs

@ -25,6 +25,15 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
{ {
public int Field; public int Field;
public int Property {
get {
return Field;
}
set {
Field = value;
}
}
public S(int field) public S(int field)
{ {
Field = field; Field = field;
@ -184,5 +193,16 @@ namespace ICSharpCode.Decompiler.Tests.TestCases.Pretty
Console.WriteLine("true"); Console.WriteLine("true");
} }
} }
public static void CallOnTemporary()
{
// Method can be called directly on temporaries
//InitObj2().MethodCalls();
// Setting a property requires a temporary to avoid
// CS1612 Cannot modify the return value of 'InitObj2()' because it is not a variable
S s = InitObj2();
s.Property = 1;
}
} }
} }

15
ICSharpCode.Decompiler/CSharp/Resolver/ReducedExtensionMethod.cs

@ -27,6 +27,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using ICSharpCode.Decompiler.TypeSystem; using ICSharpCode.Decompiler.TypeSystem;
namespace ICSharpCode.Decompiler.CSharp.Resolver namespace ICSharpCode.Decompiler.CSharp.Resolver
@ -172,17 +173,9 @@ namespace ICSharpCode.Decompiler.CSharp.Resolver
} }
} }
public bool IsAccessor { public bool IsAccessor => baseMethod.IsAccessor;
get { public IMember AccessorOwner => baseMethod.AccessorOwner;
return baseMethod.IsAccessor; public MethodSemanticsAttributes AccessorKind => baseMethod.AccessorKind;
}
}
public IMember AccessorOwner {
get {
return baseMethod.AccessorOwner;
}
}
public IMethod ReducedFrom { public IMethod ReducedFrom {
get { get {

2
ICSharpCode.Decompiler/CSharp/StatementBuilder.cs

@ -763,7 +763,7 @@ namespace ICSharpCode.Decompiler.CSharp
return false; return false;
switch (targetMethod.AccessorOwner) { switch (targetMethod.AccessorOwner) {
case IProperty p: case IProperty p:
return p.Setter == targetMethod; return targetMethod.AccessorKind == System.Reflection.MethodSemanticsAttributes.Setter;
default: default:
return true; return true;
} }

18
ICSharpCode.Decompiler/IL/Transforms/AssignVariableNames.cs

@ -19,6 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Humanizer; using Humanizer;
@ -71,7 +72,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
var lastParameter = f.Method.Parameters.Last(); var lastParameter = f.Method.Parameters.Last();
switch (f.Method.AccessorOwner) { switch (f.Method.AccessorOwner) {
case IProperty prop: case IProperty prop:
if (prop.Setter == f.Method) { if (f.Method.AccessorKind == MethodSemanticsAttributes.Setter) {
if (prop.Parameters.Any(p => p.Name == "value")) { if (prop.Parameters.Any(p => p.Name == "value")) {
f.Warnings.Add("Parameter named \"value\" already present in property signature!"); f.Warnings.Add("Parameter named \"value\" already present in property signature!");
break; break;
@ -90,7 +91,7 @@ namespace ICSharpCode.Decompiler.IL.Transforms
} }
break; break;
case IEvent ev: case IEvent ev:
if (f.Method != ev.InvokeAccessor) { if (f.Method.AccessorKind != MethodSemanticsAttributes.Raiser) {
var variableForLastParameter = f.Variables.FirstOrDefault(v => v.Function == f var variableForLastParameter = f.Variables.FirstOrDefault(v => v.Function == f
&& v.Kind == VariableKind.Parameter && v.Kind == VariableKind.Parameter
&& v.Index == f.Method.Parameters.Count - 1); && v.Index == f.Method.Parameters.Count - 1);
@ -124,11 +125,14 @@ namespace ICSharpCode.Decompiler.IL.Transforms
bool IsSetOrEventAccessor(IMethod method) bool IsSetOrEventAccessor(IMethod method)
{ {
if (method.AccessorOwner is IProperty p) switch (method.AccessorKind) {
return p.Setter == method; case MethodSemanticsAttributes.Setter:
if (method.AccessorOwner is IEvent e) case MethodSemanticsAttributes.Adder:
return e.InvokeAccessor != method; case MethodSemanticsAttributes.Remover:
return false; return true;
default:
return false;
}
} }
void PerformAssignment(ILFunction function) void PerformAssignment(ILFunction function)

6
ICSharpCode.Decompiler/TypeSystem/IMethod.cs

@ -18,6 +18,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
namespace ICSharpCode.Decompiler.TypeSystem namespace ICSharpCode.Decompiler.TypeSystem
{ {
@ -69,6 +70,11 @@ namespace ICSharpCode.Decompiler.TypeSystem
/// </summary> /// </summary>
IMember AccessorOwner { get; } IMember AccessorOwner { get; }
/// <summary>
/// Gets the kind of accessor this is.
/// </summary>
MethodSemanticsAttributes AccessorKind { get; }
/// <summary> /// <summary>
/// If this method is reduced from an extension method return the original method, <c>null</c> otherwise. /// If this method is reduced from an extension method return the original method, <c>null</c> otherwise.
/// A reduced method doesn't contain the extension method parameter. That means that has one parameter less than it's definition. /// A reduced method doesn't contain the extension method parameter. That means that has one parameter less than it's definition.

2
ICSharpCode.Decompiler/TypeSystem/Implementation/FakeMember.cs

@ -18,6 +18,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Metadata; using System.Reflection.Metadata;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
@ -144,6 +145,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
bool IMethod.HasBody => false; bool IMethod.HasBody => false;
bool IMethod.IsAccessor => false; bool IMethod.IsAccessor => false;
IMember IMethod.AccessorOwner => null; IMember IMethod.AccessorOwner => null;
MethodSemanticsAttributes IMethod.AccessorKind => 0;
IMethod IMethod.ReducedFrom => null; IMethod IMethod.ReducedFrom => null;

3
ICSharpCode.Decompiler/TypeSystem/Implementation/MetadataMethod.cs

@ -25,7 +25,6 @@ using System.Reflection.Metadata;
using System.Reflection.Metadata.Ecma335; using System.Reflection.Metadata.Ecma335;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using ICSharpCode.Decompiler.Semantics;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
namespace ICSharpCode.Decompiler.TypeSystem.Implementation namespace ICSharpCode.Decompiler.TypeSystem.Implementation
@ -40,6 +39,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
readonly SymbolKind symbolKind; readonly SymbolKind symbolKind;
readonly ITypeParameter[] typeParameters; readonly ITypeParameter[] typeParameters;
readonly EntityHandle accessorOwner; readonly EntityHandle accessorOwner;
public MethodSemanticsAttributes AccessorKind { get; }
public bool IsExtensionMethod { get; } public bool IsExtensionMethod { get; }
// lazy-loaded fields: // lazy-loaded fields:
@ -64,6 +64,7 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
if (semanticsAttribute != 0) { if (semanticsAttribute != 0) {
this.symbolKind = SymbolKind.Accessor; this.symbolKind = SymbolKind.Accessor;
this.accessorOwner = accessorOwner; this.accessorOwner = accessorOwner;
this.AccessorKind = semanticsAttribute;
} else if ((attributes & (MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)) != 0) { } else if ((attributes & (MethodAttributes.SpecialName | MethodAttributes.RTSpecialName)) != 0) {
string name = this.Name; string name = this.Name;
if (name == ".cctor" || name == ".ctor") if (name == ".cctor" || name == ".ctor")

3
ICSharpCode.Decompiler/TypeSystem/Implementation/SpecializedMethod.cs

@ -19,6 +19,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using ICSharpCode.Decompiler.Util; using ICSharpCode.Decompiler.Util;
@ -125,6 +126,8 @@ namespace ICSharpCode.Decompiler.TypeSystem.Implementation
get { return methodDefinition.IsAccessor; } get { return methodDefinition.IsAccessor; }
} }
public MethodSemanticsAttributes AccessorKind => methodDefinition.AccessorKind;
public IMethod ReducedFrom { public IMethod ReducedFrom {
get { return null; } get { return null; }
} }

15
ICSharpCode.Decompiler/TypeSystem/VarArgInstanceMethod.cs

@ -20,6 +20,7 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.Linq; using System.Linq;
using System.Reflection;
using System.Text; using System.Text;
using ICSharpCode.Decompiler.TypeSystem.Implementation; using ICSharpCode.Decompiler.TypeSystem.Implementation;
@ -142,14 +143,10 @@ namespace ICSharpCode.Decompiler.TypeSystem
public bool HasBody { public bool HasBody {
get { return baseMethod.HasBody; } get { return baseMethod.HasBody; }
} }
public bool IsAccessor { public bool IsAccessor => baseMethod.IsAccessor;
get { return baseMethod.IsAccessor; } public IMember AccessorOwner => baseMethod.AccessorOwner;
} public MethodSemanticsAttributes AccessorKind => baseMethod.AccessorKind;
public IMember AccessorOwner {
get { return baseMethod.AccessorOwner; }
}
public IMethod ReducedFrom { public IMethod ReducedFrom {
get { return baseMethod.ReducedFrom; } get { return baseMethod.ReducedFrom; }
@ -158,7 +155,7 @@ namespace ICSharpCode.Decompiler.TypeSystem
#endregion #endregion
#region IMember implementation #region IMember implementation
IMember IMember.Specialize(TypeParameterSubstitution substitution) IMember IMember.Specialize(TypeParameterSubstitution substitution)
{ {
return Specialize(substitution); return Specialize(substitution);

Loading…
Cancel
Save