Browse Source

Improved names of indexers in the tree view.

pull/115/head
Artur Zgodziski 15 years ago
parent
commit
8462984233
  1. 55
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 55
      ICSharpCode.Decompiler/CecilExtensions.cs
  3. 33
      ILSpy/CSharpLanguage.cs
  4. 7
      ILSpy/Language.cs
  5. 9
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs
  6. 12
      ILSpy/TreeNodes/PropertyTreeNode.cs
  7. 10
      ILSpy/TreeNodes/TypeTreeNode.cs
  8. 4
      Mono.Cecil/Mono.Cecil/PropertyDefinition.cs

55
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -168,7 +168,7 @@ namespace ICSharpCode.Decompiler.Ast @@ -168,7 +168,7 @@ namespace ICSharpCode.Decompiler.Ast
AstNode node = method.IsConstructor ? (AstNode)CreateConstructor(method) : CreateMethod(method);
astCompileUnit.AddChild(node, CompilationUnit.MemberRole);
}
public void AddProperty(PropertyDefinition property)
{
astCompileUnit.AddChild(CreateProperty(property), CompilationUnit.MemberRole);
@ -269,10 +269,9 @@ namespace ICSharpCode.Decompiler.Ast @@ -269,10 +269,9 @@ namespace ICSharpCode.Decompiler.Ast
foreach (var i in typeDef.Interfaces)
astType.AddChild(ConvertType(i), TypeDeclaration.BaseTypeRole);
AddTypeMembers(astType, typeDef);
if (astType.Members.Any(m => m is IndexerDeclaration)) {
if (astType.Members.OfType<IndexerDeclaration>().Any(idx => idx.PrivateImplementationType.IsNull)) {
// Remove the [DefaultMember] attribute if the class contains indexers
foreach (AttributeSection section in astType.Attributes) {
foreach (Ast.Attribute attr in section.Attributes) {
@ -780,39 +779,12 @@ namespace ICSharpCode.Decompiler.Ast @@ -780,39 +779,12 @@ namespace ICSharpCode.Decompiler.Ast
}
ConvertCustomAttributes(astProp, propDef);
// Check whether the property is an indexer:
if (propDef.HasParameters) {
PropertyDefinition basePropDef = propDef;
if (accessor.HasOverrides) {
// if the property is explicitly implementing an interface, look up the property in the interface:
MethodDefinition baseAccessor = accessor.Overrides.First().Resolve();
if (baseAccessor != null) {
foreach (PropertyDefinition baseProp in baseAccessor.DeclaringType.Properties) {
if (baseProp.GetMethod == baseAccessor || baseProp.SetMethod == baseAccessor) {
basePropDef = baseProp;
break;
}
}
}
}
// figure out the name of the indexer:
string defaultMemberName = null;
var defaultMemberAttribute = basePropDef.DeclaringType.CustomAttributes.FirstOrDefault(IsDefaultMemberAttribute);
if (defaultMemberAttribute != null && defaultMemberAttribute.ConstructorArguments.Count == 1) {
defaultMemberName = defaultMemberAttribute.ConstructorArguments[0].Value as string;
}
if (basePropDef.Name == defaultMemberName) {
return ConvertPropertyToIndexer(astProp, propDef);
}
}
return astProp;
if(propDef.IsIndexer())
return ConvertPropertyToIndexer(astProp, propDef);
else
return astProp;
}
bool IsDefaultMemberAttribute(CustomAttribute ca)
{
return ca.AttributeType.Name == "DefaultMemberAttribute" && ca.AttributeType.Namespace == "System.Reflection";
}
IndexerDeclaration ConvertPropertyToIndexer(PropertyDeclaration astProp, PropertyDefinition propDef)
{
var astIndexer = new IndexerDeclaration();
@ -1287,18 +1259,5 @@ namespace ICSharpCode.Decompiler.Ast @@ -1287,18 +1259,5 @@ namespace ICSharpCode.Decompiler.Ast
return type.CustomAttributes.Any(attr => attr.AttributeType.FullName == "System.FlagsAttribute");
}
/// <summary>
/// Gets the name of the default member of the type pointed by the <see cref="System.Reflection.DefaultMemberAttribute"/> attribute.
/// </summary>
/// <param name="type">The type definition.</param>
/// <returns>The name of the default member or null if no <see cref="System.Reflection.DefaultMemberAttribute"/> attribute has been found.</returns>
private static Tuple<string, CustomAttribute> GetDefaultMember(TypeDefinition type)
{
foreach (CustomAttribute ca in type.CustomAttributes)
if (ca.Constructor.FullName == "System.Void System.Reflection.DefaultMemberAttribute::.ctor(System.String)")
return Tuple.Create(ca.ConstructorArguments.Single().Value as string, ca);
return new Tuple<string,CustomAttribute>(null, null);
}
}
}

55
ICSharpCode.Decompiler/CecilExtensions.cs

@ -18,6 +18,7 @@ @@ -18,6 +18,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Mono.Cecil;
using Mono.Cecil.Cil;
@ -202,5 +203,59 @@ namespace ICSharpCode.Decompiler @@ -202,5 +203,59 @@ namespace ICSharpCode.Decompiler
return true;
return IsCompilerGeneratedOrIsInCompilerGeneratedClass(member.DeclaringType);
}
public static string GetDefaultMemberName(this TypeDefinition type)
{
CustomAttribute attr;
return type.GetDefaultMemberName(out attr);
}
public static string GetDefaultMemberName(this TypeDefinition type, out CustomAttribute defaultMemberAttribute)
{
if (type.HasCustomAttributes)
foreach (CustomAttribute ca in type.CustomAttributes)
if (ca.Constructor.DeclaringType.Name == "DefaultMemberAttribute" && ca.Constructor.DeclaringType.Namespace == "System.Reflection"
&& ca.Constructor.FullName == @"System.Void System.Reflection.DefaultMemberAttribute::.ctor(System.String)") {
defaultMemberAttribute = ca;
return ca.ConstructorArguments[0].Value as string;
}
defaultMemberAttribute = null;
return null;
}
public static bool IsIndexer(this PropertyDefinition property)
{
CustomAttribute attr;
return property.IsIndexer(out attr);
}
public static bool IsIndexer(this PropertyDefinition property, out CustomAttribute defaultMemberAttribute)
{
defaultMemberAttribute = null;
if (property.HasParameters) {
var accessor = property.GetMethod ?? property.SetMethod;
PropertyDefinition basePropDef = property;
if (accessor.HasOverrides) {
// if the property is explicitly implementing an interface, look up the property in the interface:
MethodDefinition baseAccessor = accessor.Overrides.First().Resolve();
if (baseAccessor != null) {
foreach (PropertyDefinition baseProp in baseAccessor.DeclaringType.Properties) {
if (baseProp.GetMethod == baseAccessor || baseProp.SetMethod == baseAccessor) {
basePropDef = baseProp;
break;
}
}
} else
return false;
}
CustomAttribute attr;
var defaultMemberName = basePropDef.DeclaringType.GetDefaultMemberName(out attr);
if (defaultMemberName == basePropDef.Name) {
defaultMemberAttribute = attr;
return true;
}
}
return false;
}
}
}

33
ILSpy/CSharpLanguage.cs

@ -415,7 +415,38 @@ namespace ICSharpCode.ILSpy @@ -415,7 +415,38 @@ namespace ICSharpCode.ILSpy
astType.AcceptVisitor(new OutputVisitor(w, new CSharpFormattingPolicy()), null);
return w.ToString();
}
public override string FormatPropertyName(PropertyDefinition property, bool? isIndexer)
{
if (property == null)
throw new ArgumentNullException("property");
if (!isIndexer.HasValue) {
isIndexer = property.IsIndexer();
}
if (isIndexer.Value) {
var buffer = new System.Text.StringBuilder();
var accessor = property.GetMethod ?? property.SetMethod;
if (accessor.HasOverrides) {
var declaringType = accessor.Overrides.First().DeclaringType;
buffer.Append(TypeToString(declaringType, includeNamespace: true));
buffer.Append(@".");
}
buffer.Append(@"this[");
bool addSeparator = false;
foreach (var p in property.Parameters) {
if (addSeparator)
buffer.Append(@", ");
else
addSeparator = true;
buffer.Append(TypeToString(p.ParameterType, includeNamespace: true));
}
buffer.Append(@"]");
return buffer.ToString();
} else
return property.Name;
}
public override bool ShowMember(MemberReference member)
{
return showAllMembers || !AstBuilder.MemberIsHidden(member, new DecompilationOptions().DecompilerSettings);

7
ILSpy/Language.cs

@ -105,6 +105,13 @@ namespace ICSharpCode.ILSpy @@ -105,6 +105,13 @@ namespace ICSharpCode.ILSpy
else
return type.Name;
}
public virtual string FormatPropertyName(PropertyDefinition property, bool? isIndexer = null)
{
if (property == null)
throw new ArgumentNullException("property");
return property.Name;
}
/// <summary>
/// Used for WPF keyboard navigation.

9
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs

@ -18,31 +18,34 @@ @@ -18,31 +18,34 @@
using System;
using Mono.Cecil;
using ICSharpCode.Decompiler;
namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
{
class AnalyzedPropertyTreeNode : AnalyzerTreeNode
{
PropertyDefinition analyzedProperty;
bool isIndexer;
string prefix;
public AnalyzedPropertyTreeNode(PropertyDefinition analyzedProperty, string prefix = "")
{
if (analyzedProperty == null)
throw new ArgumentNullException("analyzedMethod");
this.isIndexer = analyzedProperty.IsIndexer();
this.analyzedProperty = analyzedProperty;
this.prefix = prefix;
this.LazyLoading = true;
}
public override object Icon {
get { return PropertyTreeNode.GetIcon(analyzedProperty); }
get { return PropertyTreeNode.GetIcon(analyzedProperty, isIndexer); }
}
public override object Text {
get {
return prefix + Language.TypeToString(analyzedProperty.DeclaringType, true) + "." + PropertyTreeNode.GetText(analyzedProperty, Language); }
// TODO: This way of formatting is not suitable for properties which explicitly implement interfaces.
return prefix + Language.TypeToString(analyzedProperty.DeclaringType, true) + "." + PropertyTreeNode.GetText(analyzedProperty, Language, isIndexer); }
}
public override void ActivateItem(System.Windows.RoutedEventArgs e)

12
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -32,12 +32,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -32,12 +32,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
readonly PropertyDefinition property;
readonly bool isIndexer;
public PropertyTreeNode(PropertyDefinition property, bool isIndexer)
public PropertyTreeNode(PropertyDefinition property)
{
if (property == null)
throw new ArgumentNullException("property");
this.property = property;
this.isIndexer = isIndexer;
this.isIndexer = property.IsIndexer();
if (property.GetMethod != null)
this.Children.Add(new MethodTreeNode(property.GetMethod));
if (property.SetMethod != null)
@ -54,12 +54,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -54,12 +54,12 @@ namespace ICSharpCode.ILSpy.TreeNodes
}
public override object Text {
get { return GetText(property, Language); }
get { return GetText(property, Language, isIndexer); }
}
public static object GetText(PropertyDefinition property, Language language)
public static object GetText(PropertyDefinition property, Language language, bool? isIndexer = null)
{
return HighlightSearchMatch(property.Name, " : " + language.TypeToString(property.PropertyType, false, property));
return HighlightSearchMatch(language.FormatPropertyName(property, isIndexer), " : " + language.TypeToString(property.PropertyType, false, property));
}
public override object Icon {
@ -70,7 +70,7 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -70,7 +70,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
public static BitmapImage GetIcon(PropertyDefinition property, bool? isIndexer = null)
{
return (isIndexer ?? false) ? Images.Indexer : Images.Property;
return (isIndexer ?? property.IsIndexer()) ? Images.Indexer : Images.Property;
}
public override FilterResult Filter(FilterSettings settings)

10
ILSpy/TreeNodes/TypeTreeNode.cs

@ -103,16 +103,8 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -103,16 +103,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
this.Children.Add(new FieldTreeNode(field));
}
// figure out the name of the indexer:
string defaultMemberName = null;
var defaultMemberAttribute = type.CustomAttributes.FirstOrDefault(
a => a.AttributeType.FullName == typeof(System.Reflection.DefaultMemberAttribute).FullName);
if (defaultMemberAttribute != null && defaultMemberAttribute.ConstructorArguments.Count == 1) {
defaultMemberName = defaultMemberAttribute.ConstructorArguments[0].Value as string;
}
foreach (PropertyDefinition property in type.Properties.OrderBy(m => m.Name)) {
this.Children.Add(new PropertyTreeNode(property, property.Name == defaultMemberName));
this.Children.Add(new PropertyTreeNode(property));
}
foreach (EventDefinition ev in type.Events.OrderBy(m => m.Name)) {
this.Children.Add(new EventTreeNode(ev));

4
Mono.Cecil/Mono.Cecil/PropertyDefinition.cs

@ -127,10 +127,10 @@ namespace Mono.Cecil { @@ -127,10 +127,10 @@ namespace Mono.Cecil {
public bool HasParameters {
get {
if (get_method != null)
if (GetMethod != null)
return get_method.HasParameters;
if (set_method != null)
if (SetMethod != null)
return set_method.HasParameters && set_method.Parameters.Count > 1;
return false;

Loading…
Cancel
Save