Browse Source

Added support for new modifier (methods and properties only).

pull/112/head
Artur Zgodziski 15 years ago
parent
commit
368cac6c7f
  1. 247
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 243
      ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs

247
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -1,5 +1,6 @@ @@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
@ -626,9 +627,13 @@ namespace ICSharpCode.Decompiler.Ast @@ -626,9 +627,13 @@ namespace ICSharpCode.Decompiler.Ast
astMethod.Parameters.AddRange(MakeParameters(methodDef.Parameters));
astMethod.Constraints.AddRange(MakeConstraints(methodDef.GenericParameters));
if (!methodDef.DeclaringType.IsInterface) {
if (!methodDef.HasOverrides)
if (!methodDef.HasOverrides) {
astMethod.Modifiers = ConvertModifiers(methodDef);
else
if (methodDef.IsVirtual ^ !methodDef.IsNewSlot) {
if (TypeMap.FindBaseMethods(methodDef).Any())
astMethod.Modifiers |= Modifiers.New;
}
} else
astMethod.PrivateImplementationType = ConvertType(methodDef.Overrides.First().DeclaringType);
astMethod.Body = AstMethodBodyBuilder.CreateMethodBody(methodDef, context, astMethod.Parameters);
}
@ -658,7 +663,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -658,7 +663,7 @@ namespace ICSharpCode.Decompiler.Ast
}
return astMethod;
}
IEnumerable<TypeParameterDeclaration> MakeTypeParameters(IEnumerable<GenericParameter> genericParameters)
{
foreach (var gp in genericParameters) {
@ -739,19 +744,17 @@ namespace ICSharpCode.Decompiler.Ast @@ -739,19 +744,17 @@ namespace ICSharpCode.Decompiler.Ast
getterModifiers = ConvertModifiers(propDef.GetMethod);
setterModifiers = ConvertModifiers(propDef.SetMethod);
astProp.Modifiers = FixUpVisibility(getterModifiers | setterModifiers);
if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null)) {
var baseType = propDef.DeclaringType.BaseType.Resolve();
while (baseType != null && baseType.BaseType != null) {
var basePropDef = baseType.Properties.FirstOrDefault(pd => CouldOverride(pd, propDef));
if (basePropDef != null)
if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) {
var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod);
astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask));
break;
} else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot)
break;
baseType = baseType.BaseType.Resolve();
}
if (accessor.IsVirtual && !accessor.IsNewSlot && (propDef.GetMethod == null || propDef.SetMethod == null))
foreach (var basePropDef in TypeMap.FindBaseProperties(propDef))
if (basePropDef.GetMethod != null && basePropDef.SetMethod != null) {
var propVisibilityModifiers = ConvertModifiers(basePropDef.GetMethod) | ConvertModifiers(basePropDef.SetMethod);
astProp.Modifiers = FixUpVisibility((astProp.Modifiers & ~Modifiers.VisibilityMask) | (propVisibilityModifiers & Modifiers.VisibilityMask));
break;
} else if ((basePropDef.GetMethod ?? basePropDef.SetMethod).IsNewSlot)
break;
if (accessor.IsVirtual ^ !accessor.IsNewSlot) {
if (TypeMap.FindBaseProperties(propDef).Any())
astProp.Modifiers |= Modifiers.New;
}
}
astProp.Name = CleanName(propDef.Name);
@ -805,30 +808,6 @@ namespace ICSharpCode.Decompiler.Ast @@ -805,30 +808,6 @@ namespace ICSharpCode.Decompiler.Ast
return astProp;
}
bool CouldOverride(PropertyDefinition baseProperty, PropertyDefinition property)
{
if (baseProperty.Name != property.Name || baseProperty.PropertyType.Resolve() != property.PropertyType.Resolve())
return false;
if (baseProperty.HasParameters) {
if (!property.HasParameters) {
return false;
}
var parameters1 = baseProperty.Parameters;
var parameters2 = property.Parameters;
if (parameters1.Count != parameters2.Count)
return false;
for (int index = 0; index < parameters1.Count; index++) {
if (parameters1[index].ParameterType.Resolve() != parameters2[index].ParameterType.Resolve())
return false;
}
}
return true;
}
bool IsDefaultMemberAttribute(CustomAttribute ca)
{
return ca.AttributeType.Name == "DefaultMemberAttribute" && ca.AttributeType.Namespace == "System.Reflection";
@ -1322,5 +1301,193 @@ namespace ICSharpCode.Decompiler.Ast @@ -1322,5 +1301,193 @@ namespace ICSharpCode.Decompiler.Ast
return new Tuple<string,CustomAttribute>(null, null);
}
class TypeMap
{
public static IEnumerable<MethodDefinition> FindBaseMethods(MethodDefinition method)
{
var typeContext = CreateGenericContext(method.DeclaringType);
var gMethod = typeContext.ApplyTo(method);
foreach (var baseType in BaseTypes(method.DeclaringType))
foreach (var baseMethod in baseType.Item.Methods)
if (MatchMethod(baseType.ApplyTo(baseMethod), gMethod) && IsVisbleFrom(baseMethod, method)) {
yield return baseMethod;
if (!(baseMethod.IsNewSlot ^ baseMethod.IsVirtual))
yield break;
}
}
public static IEnumerable<PropertyDefinition> FindBaseProperties(PropertyDefinition property)
{
var typeContext = CreateGenericContext(property.DeclaringType);
var gProperty = typeContext.ApplyTo(property);
foreach (var baseType in BaseTypes(property.DeclaringType))
foreach (var baseProperty in baseType.Item.Properties)
if (MatchProperty(baseType.ApplyTo(baseProperty), gProperty) && IsVisbleFrom(baseProperty, property)) {
yield return baseProperty;
var anyPropertyAccessor = baseProperty.GetMethod ?? baseProperty.SetMethod;
if (!(anyPropertyAccessor.IsNewSlot ^ anyPropertyAccessor.IsVirtual))
yield break;
}
}
private static bool IsVisbleFrom(MethodDefinition baseCandidate, MethodDefinition method)
{
if (baseCandidate.IsPrivate)
return false;
if ((baseCandidate.IsAssembly || baseCandidate.IsFamilyAndAssembly) && baseCandidate.Module != method.Module)
return false;
return true;
}
private static bool IsVisbleFrom(PropertyDefinition baseCandidate, PropertyDefinition property)
{
if (baseCandidate.GetMethod != null && property.GetMethod != null && IsVisbleFrom(baseCandidate.GetMethod, property.GetMethod))
return true;
if (baseCandidate.SetMethod != null && property.SetMethod != null && IsVisbleFrom(baseCandidate.SetMethod, property.SetMethod))
return true;
return false;
}
private static bool MatchMethod(GenericContext<MethodDefinition> candidate, GenericContext<MethodDefinition> method)
{
var mCandidate = candidate.Item;
var mMethod = method.Item;
if (mCandidate.Name != mMethod.Name)
return false;
if (mCandidate.HasOverrides)
return false;
if (candidate.Resolve(mCandidate.ReturnType) != method.Resolve(mMethod.ReturnType))
return false;
if (mCandidate.HasGenericParameters || mMethod.HasGenericParameters) {
if (!mCandidate.HasGenericParameters || !mMethod.HasGenericParameters || mCandidate.GenericParameters.Count != mMethod.GenericParameters.Count)
return false;
}
if (mCandidate.HasParameters || mMethod.HasParameters) {
if (!mCandidate.HasParameters || !mMethod.HasParameters || mCandidate.Parameters.Count != mMethod.Parameters.Count)
return false;
for (int index = 0; index < mCandidate.Parameters.Count; index++) {
if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), method.ApplyTo(mMethod.Parameters[index])))
return false;
}
}
return true;
}
private static bool MatchProperty(GenericContext<PropertyDefinition> candidate, GenericContext<PropertyDefinition> property)
{
var mCandidate = candidate.Item;
var mProperty = property.Item;
if (mCandidate.Name != mProperty.Name)
return false;
if ((mCandidate.GetMethod ?? mCandidate.SetMethod).HasOverrides)
return false;
if (candidate.Resolve(mCandidate.PropertyType) != property.Resolve(mProperty.PropertyType))
return false;
if (mCandidate.HasParameters || mProperty.HasParameters) {
if (!mCandidate.HasParameters || !mProperty.HasParameters || mCandidate.Parameters.Count != mProperty.Parameters.Count)
return false;
for (int index = 0; index < mCandidate.Parameters.Count; index++) {
if (!MatchParameters(candidate.ApplyTo(mCandidate.Parameters[index]), property.ApplyTo(mProperty.Parameters[index])))
return false;
}
}
return true;
}
private static bool MatchParameters(GenericContext<ParameterDefinition> baseParameterType, GenericContext<ParameterDefinition> parameterType)
{
var baseParam = baseParameterType.Resolve(baseParameterType.Item.ParameterType);
var param = parameterType.Resolve(parameterType.Item.ParameterType);
return baseParam == param;
}
private static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(TypeDefinition type)
{
return BaseTypes(CreateGenericContext(type));
}
private static IEnumerable<GenericContext<TypeDefinition>> BaseTypes(GenericContext<TypeDefinition> type)
{
while (type.Item.BaseType != null) {
var baseType = type.Item.BaseType;
var genericBaseType = baseType as GenericInstanceType;
if (genericBaseType != null) {
type = new GenericContext<TypeDefinition>(genericBaseType.Resolve(),
genericBaseType.GenericArguments.Select(t => type.Resolve(t)));
} else
type = new GenericContext<TypeDefinition>(baseType.Resolve());
yield return type;
}
}
private static GenericContext<TypeDefinition> CreateGenericContext(TypeDefinition type)
{
return new GenericContext<TypeDefinition>(type, type.GenericParameters);
}
struct GenericContext<T>
{
private static readonly ReadOnlyCollection<TypeReference> Empty = new ReadOnlyCollection<TypeReference>(new List<TypeReference>());
public readonly T Item;
public readonly ReadOnlyCollection<TypeReference> TypeArguments;
public GenericContext(T item)
{
Item = item;
TypeArguments = Empty;
}
public GenericContext(T item, IEnumerable<TypeReference> typeArguments)
{
Item = item;
var list = new List<TypeReference>();
foreach (var arg in typeArguments) {
if (arg == null)
throw new ArgumentNullException("typeArguments");
if (!arg.IsGenericParameter)
list.Add(arg.Resolve());
else
list.Add(arg);
}
TypeArguments = new ReadOnlyCollection<TypeReference>(list);
}
private GenericContext(T item, ReadOnlyCollection<TypeReference> typeArguments)
{
Item = item;
TypeArguments = typeArguments;
}
public TypeReference Resolve(TypeReference type)
{
var genericParameter = type as GenericParameter;
if (genericParameter != null && genericParameter.Owner.GenericParameterType == GenericParameterType.Type) {
return this.TypeArguments[genericParameter.Position];
}
return type.Resolve();
}
public GenericContext<T2> ApplyTo<T2>(T2 item)
{
return new GenericContext<T2>(item, this.TypeArguments);
}
}
}
}
}

243
ICSharpCode.Decompiler/Tests/Types/S_TypeMemberDeclarations.cs

@ -374,7 +374,7 @@ namespace PropertyOverrideOneAccessor @@ -374,7 +374,7 @@ namespace PropertyOverrideOneAccessor
}
public class DerivedNew : MyClass
{
public virtual int MyProperty
public new virtual int MyProperty
{
set
{
@ -428,3 +428,244 @@ namespace IndexerOverrideRestrictedAccessorOnly @@ -428,3 +428,244 @@ namespace IndexerOverrideRestrictedAccessorOnly
}
}
}
//$$ PropertyHiding
namespace PropertyHiding
{
public class A
{
public virtual int P
{
get
{
return 0;
}
set
{
}
}
}
public class B : A
{
private new int P
{
get
{
return 0;
}
set
{
}
}
}
public class C : B
{
public override int P
{
set
{
}
}
}
}
//$$ IndexerHidingGeneric
namespace IndexerHidingGeneric
{
public class A<T>
{
public virtual int this[T r]
{
get
{
return 0;
}
set
{
}
}
}
public class B : A<int>
{
private new int this[int k]
{
get
{
return 0;
}
set
{
}
}
}
public class C<T> : A<T>
{
public override int this[T s]
{
set
{
}
}
}
public class D<T> : C<T>
{
public new virtual int this[T s]
{
set
{
}
}
}
}
//$$ MethodHiding
namespace MethodHiding
{
public class A
{
public virtual void F()
{
}
}
public class B : A
{
private new void F()
{
base.F();
}
}
public class C : B
{
public override void F()
{
base.F();
}
}
}
//$$ MethodHideGeneric
namespace MethodHideGeneric
{
public class A<T>
{
public virtual void F(T s)
{
}
public new static bool Equals(object o1, object o2)
{
return true;
}
}
public class B : A<string>
{
private new void F(string k)
{
}
public void F(int i)
{
}
}
public class C<T> : A<T>
{
public override void F(T r)
{
}
public void G(T t)
{
}
}
public class D<T1> : C<T1>
{
public new virtual void F(T1 k)
{
}
public virtual void F<T2>(T2 k)
{
}
public virtual void G<T2>(T2 t)
{
}
}
}
//$$ MethodHideGenericSkipPrivate
namespace MethodHideGenericSkipPrivate
{
public class A<T>
{
public virtual void F(T t)
{
}
}
public class B<T> : A<T>
{
private new void F(T t)
{
}
private void K()
{
}
}
public class C<T> : B<T>
{
public override void F(T tt)
{
}
public void K()
{
}
}
public class D : B<int>
{
public override void F(int t)
{
}
}
}
//$$ MethodHideGeneric2
namespace MethodHideGeneric2
{
public class A
{
public virtual void F(int i)
{
}
public void K()
{
}
}
public class B<T> : A
{
protected virtual void F(T t)
{
}
public void K<T2>()
{
}
}
public class C : B<int>
{
protected override void F(int k)
{
}
public new void K<T3>()
{
}
}
public class D : B<string>
{
public override void F(int k)
{
}
public void L<T4>()
{
}
}
public class E<T>
{
public void M<T2>(T t, T2 t2)
{
}
}
public class F<T> : E<T>
{
public void M(T t1, T t2)
{
}
}
}

Loading…
Cancel
Save