Browse Source

Merge "Improved names of indexers in the tree view and analyzers bug fix"

pull/124/head
Daniel Grunwald 14 years ago
parent
commit
4912bef543
  1. 47
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 55
      ICSharpCode.Decompiler/CecilExtensions.cs
  3. 31
      ILSpy/CSharpLanguage.cs
  4. 7
      ILSpy/Language.cs
  5. 3
      ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs
  6. 3
      ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs
  7. 3
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs
  8. 9
      ILSpy/TreeNodes/Analyzer/AnalyzedPropertyTreeNode.cs
  9. 3
      ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs
  10. 10
      ILSpy/TreeNodes/PropertyTreeNode.cs
  11. 10
      ILSpy/TreeNodes/TypeTreeNode.cs

47
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -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) {
@ -775,39 +774,12 @@ namespace ICSharpCode.Decompiler.Ast @@ -775,39 +774,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) {
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();
@ -1313,18 +1285,5 @@ namespace ICSharpCode.Decompiler.Ast @@ -1313,18 +1285,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;
@ -234,5 +235,59 @@ namespace ICSharpCode.Decompiler @@ -234,5 +235,59 @@ namespace ICSharpCode.Decompiler
else
return false;
}
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;
}
}
}

31
ILSpy/CSharpLanguage.cs

@ -419,6 +419,37 @@ namespace ICSharpCode.ILSpy @@ -419,6 +419,37 @@ namespace ICSharpCode.ILSpy
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

@ -106,6 +106,13 @@ namespace ICSharpCode.ILSpy @@ -106,6 +106,13 @@ namespace ICSharpCode.ILSpy
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.
/// </summary>

3
ILSpy/TreeNodes/Analyzer/AnalyzedFieldAccessNode.cs

@ -57,8 +57,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -57,8 +57,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return FindReferences(MainWindow.Instance.AssemblyList.GetAssemblies(), ct);
}
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly[] assemblies, CancellationToken ct)
IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
}

3
ILSpy/TreeNodes/Analyzer/AnalyzedMethodUsedByTreeNode.cs

@ -70,8 +70,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -70,8 +70,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return FindReferences(MainWindow.Instance.AssemblyList.GetAssemblies(), ct);
}
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly[] assemblies, CancellationToken ct)
IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
}

3
ILSpy/TreeNodes/Analyzer/AnalyzedPropertyOverridesTreeNode.cs

@ -54,8 +54,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -54,8 +54,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return FindReferences(MainWindow.Instance.AssemblyList.GetAssemblies(), ct);
}
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly[] assemblies, CancellationToken ct)
IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
}

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)

3
ILSpy/TreeNodes/Analyzer/AnalyzerMethodOverridesTreeNode.cs

@ -58,8 +58,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer @@ -58,8 +58,9 @@ namespace ICSharpCode.ILSpy.TreeNodes.Analyzer
return FindReferences(MainWindow.Instance.AssemblyList.GetAssemblies(), ct);
}
IEnumerable<SharpTreeNode> FindReferences(LoadedAssembly[] assemblies, CancellationToken ct)
IEnumerable<SharpTreeNode> FindReferences(IEnumerable<LoadedAssembly> assemblies, CancellationToken ct)
{
assemblies = assemblies.Where(asm => asm.AssemblyDefinition != null);
// use parallelism only on the assembly level (avoid locks within Cecil)
return assemblies.AsParallel().WithCancellation(ct).SelectMany((LoadedAssembly asm) => FindReferences(asm, ct));
}

10
ILSpy/TreeNodes/PropertyTreeNode.cs

@ -31,12 +31,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -31,12 +31,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));
@ -55,12 +55,12 @@ namespace ICSharpCode.ILSpy.TreeNodes @@ -55,12 +55,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

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));

Loading…
Cancel
Save