diff --git a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
index 3c64dd46e..76b690df3 100644
--- a/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
+++ b/ICSharpCode.Decompiler/CSharp/CSharpDecompiler.cs
@@ -21,8 +21,10 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
+using ICSharpCode.Decompiler.Ast;
using ICSharpCode.NRefactory.CSharp;
using ICSharpCode.NRefactory.CSharp.Refactoring;
+using ICSharpCode.NRefactory.Semantics;
using ICSharpCode.NRefactory.TypeSystem;
using Mono.Cecil;
using ICSharpCode.Decompiler.CSharp.Transforms;
@@ -374,6 +376,89 @@ namespace ICSharpCode.Decompiler.CSharp
}
}
+ #region SetNewModifier
+ ///
+ /// Sets new modifier if the member hides some other member from a base type.
+ ///
+ /// The node of the member which new modifier state should be determined.
+ void SetNewModifier(EntityDeclaration member)
+ {
+ bool addNewModifier = false;
+ if (member is IndexerDeclaration) {
+ var propertyDef = GetDefinitionFromAnnotation(member) as PropertyDefinition;
+ if (propertyDef != null)
+ addNewModifier = TypesHierarchyHelpers.FindBaseProperties(propertyDef).Any();
+ } else
+ addNewModifier = HidesBaseMember(member) == true;
+
+ if (addNewModifier)
+ member.Modifiers |= Modifiers.New;
+ }
+
+ IMemberDefinition GetDefinitionFromAnnotation(EntityDeclaration member)
+ {
+ if (member is TypeDeclaration) {
+ return (IMemberDefinition)typeSystem.GetCecil(member.Annotation().Type.GetDefinition());
+ } else {
+ return (IMemberDefinition)typeSystem.GetCecil(member.Annotation().Member.MemberDefinition);
+ }
+ }
+
+ bool? HidesBaseMember(EntityDeclaration member)
+ {
+ var memberDefinition = GetDefinitionFromAnnotation(member);
+ if (memberDefinition == null)
+ return null;
+ var methodDefinition = memberDefinition as MethodDefinition;
+ if (methodDefinition != null) {
+ bool? hidesByName = HidesByName(memberDefinition, includeBaseMethods: false);
+ return hidesByName != true && TypesHierarchyHelpers.FindBaseMethods(methodDefinition).Any();
+ } else
+ return HidesByName(memberDefinition, includeBaseMethods: true);
+ }
+
+ ///
+ /// Determines whether any base class member has the same name as the given member.
+ ///
+ /// The derived type's member.
+ /// true if names of methods declared in base types should also be checked.
+ /// true if any base member has the same name as given member, otherwise false. Returns null on error.
+ static bool? HidesByName(IMemberDefinition member, bool includeBaseMethods)
+ {
+ Debug.Assert(!(member is PropertyDefinition) || !((PropertyDefinition)member).IsIndexer());
+
+ if (member.DeclaringType.BaseType != null) {
+ var baseTypeRef = member.DeclaringType.BaseType;
+ while (baseTypeRef != null) {
+ var baseType = baseTypeRef.Resolve();
+ if (baseType == null)
+ return null;
+ if (baseType.HasProperties && AnyIsHiddenBy(baseType.Properties, member, m => !m.IsIndexer()))
+ return true;
+ if (baseType.HasEvents && AnyIsHiddenBy(baseType.Events, member))
+ return true;
+ if (baseType.HasFields && AnyIsHiddenBy(baseType.Fields, member))
+ return true;
+ if (includeBaseMethods && baseType.HasMethods
+ && AnyIsHiddenBy(baseType.Methods, member, m => !m.IsSpecialName))
+ return true;
+ if (baseType.HasNestedTypes && AnyIsHiddenBy(baseType.NestedTypes, member))
+ return true;
+ baseTypeRef = baseType.BaseType;
+ }
+ }
+ return false;
+ }
+
+ static bool AnyIsHiddenBy(IEnumerable members, IMemberDefinition derived, Predicate condition = null)
+ where T : IMemberDefinition
+ {
+ return members.Any(m => m.Name == derived.Name
+ && (condition == null || condition(m))
+ && TypesHierarchyHelpers.IsVisibleFromDerived(m, derived.DeclaringType));
+ }
+ #endregion
+
EntityDeclaration DoDecompile(ITypeDefinition typeDef, ITypeResolveContext decompilationContext)
{
Debug.Assert(decompilationContext.CurrentTypeDefinition == typeDef);
@@ -385,7 +470,9 @@ namespace ICSharpCode.Decompiler.CSharp
return entityDecl;
}
foreach (var type in typeDef.NestedTypes) {
- typeDecl.Members.Add(DoDecompile(type, decompilationContext.WithCurrentTypeDefinition(type)));
+ var nestedType = DoDecompile(type, decompilationContext.WithCurrentTypeDefinition(type));
+ SetNewModifier(nestedType);
+ typeDecl.Members.Add(nestedType);
}
foreach (var field in typeDef.Fields) {
var fieldDef = typeSystem.GetCecil(field) as FieldDefinition;
@@ -437,11 +524,15 @@ namespace ICSharpCode.Decompiler.CSharp
{
Debug.Assert(decompilationContext.CurrentMember == method);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
- var entityDecl = typeSystemAstBuilder.ConvertEntity(method);
+ var methodDecl = typeSystemAstBuilder.ConvertEntity(method);
if (methodDefinition.HasBody) {
- DecompileBody(methodDefinition, method, entityDecl, decompilationContext, typeSystemAstBuilder);
+ DecompileBody(methodDefinition, method, methodDecl, decompilationContext, typeSystemAstBuilder);
}
- return entityDecl;
+ if (decompilationContext.CurrentTypeDefinition.Kind != TypeKind.Interface
+ && method.SymbolKind == SymbolKind.Method
+ && methodDefinition.IsVirtual == methodDefinition.IsNewSlot)
+ SetNewModifier(methodDecl);
+ return methodDecl;
}
IDecompilerTypeSystem GetSpecializingTypeSystem(ITypeResolveContext decompilationContext)
@@ -504,21 +595,23 @@ namespace ICSharpCode.Decompiler.CSharp
enumDec.Attributes.AddRange(field.Attributes.Select(a => new AttributeSection(typeSystemAstBuilder.ConvertAttribute(a))));
return enumDec;
}
- return typeSystemAstBuilder.ConvertEntity(field);
+ var fieldDecl = typeSystemAstBuilder.ConvertEntity(field);
+ SetNewModifier(fieldDecl);
+ return fieldDecl;
}
EntityDeclaration DoDecompile(PropertyDefinition propertyDefinition, IProperty property, ITypeResolveContext decompilationContext)
{
Debug.Assert(decompilationContext.CurrentMember == property);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
- EntityDeclaration entityDecl = typeSystemAstBuilder.ConvertEntity(property);
+ EntityDeclaration propertyDecl = typeSystemAstBuilder.ConvertEntity(property);
Accessor getter, setter;
- if (entityDecl is PropertyDeclaration) {
- getter = ((PropertyDeclaration)entityDecl).Getter;
- setter = ((PropertyDeclaration)entityDecl).Setter;
+ if (propertyDecl is PropertyDeclaration) {
+ getter = ((PropertyDeclaration)propertyDecl).Getter;
+ setter = ((PropertyDeclaration)propertyDecl).Setter;
} else {
- getter = ((IndexerDeclaration)entityDecl).Getter;
- setter = ((IndexerDeclaration)entityDecl).Setter;
+ getter = ((IndexerDeclaration)propertyDecl).Getter;
+ setter = ((IndexerDeclaration)propertyDecl).Setter;
}
if (property.CanGet && property.Getter.HasBody) {
DecompileBody(propertyDefinition.GetMethod, property.Getter, getter, decompilationContext, typeSystemAstBuilder);
@@ -526,20 +619,27 @@ namespace ICSharpCode.Decompiler.CSharp
if (property.CanSet && property.Setter.HasBody) {
DecompileBody(propertyDefinition.SetMethod, property.Setter, setter, decompilationContext, typeSystemAstBuilder);
}
- return entityDecl;
+ var accessor = propertyDefinition.GetMethod ?? propertyDefinition.SetMethod;
+ if (!accessor.HasOverrides && !accessor.DeclaringType.IsInterface && accessor.IsVirtual == accessor.IsNewSlot)
+ SetNewModifier(propertyDecl);
+ return propertyDecl;
}
- EntityDeclaration DoDecompile(EventDefinition propertyDefinition, IEvent ev, ITypeResolveContext decompilationContext)
+ EntityDeclaration DoDecompile(EventDefinition eventDefinition, IEvent ev, ITypeResolveContext decompilationContext)
{
Debug.Assert(decompilationContext.CurrentMember == ev);
var typeSystemAstBuilder = CreateAstBuilder(decompilationContext);
typeSystemAstBuilder.UseCustomEvents = true;
var eventDecl = (CustomEventDeclaration)typeSystemAstBuilder.ConvertEntity(ev);
- if (propertyDefinition.AddMethod != null && propertyDefinition.AddMethod.HasBody) {
- DecompileBody(propertyDefinition.AddMethod, ev.AddAccessor, eventDecl.AddAccessor, decompilationContext, typeSystemAstBuilder);
+ if (eventDefinition.AddMethod != null && eventDefinition.AddMethod.HasBody) {
+ DecompileBody(eventDefinition.AddMethod, ev.AddAccessor, eventDecl.AddAccessor, decompilationContext, typeSystemAstBuilder);
+ }
+ if (eventDefinition.RemoveMethod != null && eventDefinition.RemoveMethod.HasBody) {
+ DecompileBody(eventDefinition.RemoveMethod, ev.RemoveAccessor, eventDecl.RemoveAccessor, decompilationContext, typeSystemAstBuilder);
}
- if (propertyDefinition.RemoveMethod != null && propertyDefinition.RemoveMethod.HasBody) {
- DecompileBody(propertyDefinition.RemoveMethod, ev.RemoveAccessor, eventDecl.RemoveAccessor, decompilationContext, typeSystemAstBuilder);
+ var accessor = eventDefinition.AddMethod ?? eventDefinition.RemoveMethod;
+ if (accessor.IsVirtual == accessor.IsNewSlot) {
+ SetNewModifier(eventDecl);
}
return eventDecl;
}