Browse Source

Use C# syntax for generic types in the tree view.

pull/100/head
Daniel Grunwald 15 years ago
parent
commit
99f5c45a16
  1. 74
      ICSharpCode.Decompiler/Ast/AstBuilder.cs
  2. 33
      ILSpy/CSharpLanguage.cs
  3. 2
      ILSpy/TreeNodes/TypeTreeNode.cs

74
ICSharpCode.Decompiler/Ast/AstBuilder.cs

@ -19,7 +19,15 @@ namespace ICSharpCode.Decompiler.Ast
using Ast = ICSharpCode.NRefactory.CSharp; using Ast = ICSharpCode.NRefactory.CSharp;
using ClassType = ICSharpCode.NRefactory.TypeSystem.ClassType; using ClassType = ICSharpCode.NRefactory.TypeSystem.ClassType;
using VarianceModifier = ICSharpCode.NRefactory.TypeSystem.VarianceModifier; using VarianceModifier = ICSharpCode.NRefactory.TypeSystem.VarianceModifier;
[Flags]
public enum ConvertTypeOptions
{
None = 0,
IncludeNamespace = 1,
IncludeTypeParameterDefinitions = 2
}
public class AstBuilder public class AstBuilder
{ {
DecompilerContext context = new DecompilerContext(); DecompilerContext context = new DecompilerContext();
@ -270,13 +278,13 @@ namespace ICSharpCode.Decompiler.Ast
/// a type system type reference.</param> /// a type system type reference.</param>
/// <param name="typeAttributes">Attributes associated with the Cecil type reference. /// <param name="typeAttributes">Attributes associated with the Cecil type reference.
/// This is used to support the 'dynamic' type.</param> /// This is used to support the 'dynamic' type.</param>
public static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes = null) public static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes = null, ConvertTypeOptions options = ConvertTypeOptions.None)
{ {
int typeIndex = 0; int typeIndex = 0;
return ConvertType(type, typeAttributes, ref typeIndex); return ConvertType(type, typeAttributes, ref typeIndex, options);
} }
static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex) static AstType ConvertType(TypeReference type, ICustomAttributeProvider typeAttributes, ref int typeIndex, ConvertTypeOptions options)
{ {
while (type is OptionalModifierType || type is RequiredModifierType) { while (type is OptionalModifierType || type is RequiredModifierType) {
type = ((TypeSpecification)type).ElementType; type = ((TypeSpecification)type).ElementType;
@ -288,39 +296,44 @@ namespace ICSharpCode.Decompiler.Ast
if (type is Mono.Cecil.ByReferenceType) { if (type is Mono.Cecil.ByReferenceType) {
typeIndex++; typeIndex++;
// by reference type cannot be represented in C#; so we'll represent it as a pointer instead // by reference type cannot be represented in C#; so we'll represent it as a pointer instead
return ConvertType((type as Mono.Cecil.ByReferenceType).ElementType, typeAttributes, ref typeIndex) return ConvertType((type as Mono.Cecil.ByReferenceType).ElementType, typeAttributes, ref typeIndex, options)
.MakePointerType(); .MakePointerType();
} else if (type is Mono.Cecil.PointerType) { } else if (type is Mono.Cecil.PointerType) {
typeIndex++; typeIndex++;
return ConvertType((type as Mono.Cecil.PointerType).ElementType, typeAttributes, ref typeIndex) return ConvertType((type as Mono.Cecil.PointerType).ElementType, typeAttributes, ref typeIndex, options)
.MakePointerType(); .MakePointerType();
} else if (type is Mono.Cecil.ArrayType) { } else if (type is Mono.Cecil.ArrayType) {
typeIndex++; typeIndex++;
return ConvertType((type as Mono.Cecil.ArrayType).ElementType, typeAttributes, ref typeIndex) return ConvertType((type as Mono.Cecil.ArrayType).ElementType, typeAttributes, ref typeIndex, options)
.MakeArrayType((type as Mono.Cecil.ArrayType).Rank); .MakeArrayType((type as Mono.Cecil.ArrayType).Rank);
} else if (type is GenericInstanceType) { } else if (type is GenericInstanceType) {
GenericInstanceType gType = (GenericInstanceType)type; GenericInstanceType gType = (GenericInstanceType)type;
if (gType.ElementType.Namespace == "System" && gType.ElementType.Name == "Nullable`1" && gType.GenericArguments.Count == 1) { if (gType.ElementType.Namespace == "System" && gType.ElementType.Name == "Nullable`1" && gType.GenericArguments.Count == 1) {
typeIndex++; typeIndex++;
return new ComposedType { return new ComposedType {
BaseType = ConvertType(gType.GenericArguments[0], typeAttributes, ref typeIndex), BaseType = ConvertType(gType.GenericArguments[0], typeAttributes, ref typeIndex, options),
HasNullableSpecifier = true HasNullableSpecifier = true
}; };
} }
AstType baseType = ConvertType(gType.ElementType, typeAttributes, ref typeIndex); AstType baseType = ConvertType(gType.ElementType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
List<AstType> typeArguments = new List<AstType>(); List<AstType> typeArguments = new List<AstType>();
foreach (var typeArgument in gType.GenericArguments) { foreach (var typeArgument in gType.GenericArguments) {
typeIndex++; typeIndex++;
typeArguments.Add(ConvertType(typeArgument, typeAttributes, ref typeIndex)); typeArguments.Add(ConvertType(typeArgument, typeAttributes, ref typeIndex, options));
} }
ApplyTypeArgumentsTo(baseType, typeArguments); ApplyTypeArgumentsTo(baseType, typeArguments);
return baseType; return baseType;
} else if (type is GenericParameter) { } else if (type is GenericParameter) {
return new SimpleType(type.Name); return new SimpleType(type.Name);
} else if (type.IsNested) { } else if (type.IsNested) {
AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex); AstType typeRef = ConvertType(type.DeclaringType, typeAttributes, ref typeIndex, options & ~ConvertTypeOptions.IncludeTypeParameterDefinitions);
string namepart = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name); string namepart = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(type.Name);
return new MemberType { Target = typeRef, MemberName = namepart }.WithAnnotation(type); MemberType memberType = new MemberType { Target = typeRef, MemberName = namepart };
memberType.AddAnnotation(type);
if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
AddTypeParameterDefininitionsTo(type, memberType);
}
return memberType;
} else { } else {
string ns = type.Namespace ?? string.Empty; string ns = type.Namespace ?? string.Empty;
string name = type.Name; string name = type.Name;
@ -369,18 +382,35 @@ namespace ICSharpCode.Decompiler.Ast
name = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(name); name = ICSharpCode.NRefactory.TypeSystem.ReflectionHelper.SplitTypeParameterCountFromReflectionName(name);
// TODO: Until we can simplify type with 'using', use just the name without namesapce AstType astType;
return new SimpleType(name).WithAnnotation(type); if ((options & ConvertTypeOptions.IncludeNamespace) == ConvertTypeOptions.IncludeNamespace && ns.Length > 0) {
string[] parts = ns.Split('.');
AstType nsType = new SimpleType(parts[0]);
for (int i = 1; i < parts.Length; i++) {
nsType = new MemberType { Target = nsType, MemberName = parts[i] };
}
astType = new MemberType { Target = nsType, MemberName = name };
} else {
astType = new SimpleType(name);
}
astType.AddAnnotation(type);
// if (ns.Length == 0) if ((options & ConvertTypeOptions.IncludeTypeParameterDefinitions) == ConvertTypeOptions.IncludeTypeParameterDefinitions) {
// return new SimpleType(name).WithAnnotation(type); AddTypeParameterDefininitionsTo(type, astType);
// string[] parts = ns.Split('.'); }
// AstType nsType = new SimpleType(parts[0]); return astType;
// for (int i = 1; i < parts.Length; i++) { }
// nsType = new MemberType { Target = nsType, MemberName = parts[i] }; }
// } }
// return new MemberType { Target = nsType, MemberName = name }.WithAnnotation(type);
static void AddTypeParameterDefininitionsTo(TypeReference type, AstType astType)
{
if (type.HasGenericParameters) {
List<AstType> typeArguments = new List<AstType>();
foreach (GenericParameter gp in type.GenericParameters) {
typeArguments.Add(new SimpleType(gp.Name));
} }
ApplyTypeArgumentsTo(astType, typeArguments);
} }
} }

33
ILSpy/CSharpLanguage.cs

@ -387,13 +387,10 @@ namespace ICSharpCode.ILSpy
public override string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes = null) public override string TypeToString(TypeReference type, bool includeNamespace, ICustomAttributeProvider typeAttributes = null)
{ {
AstType astType = AstBuilder.ConvertType(type, typeAttributes); ConvertTypeOptions options = ConvertTypeOptions.IncludeTypeParameterDefinitions;
if (includeNamespace) { if (includeNamespace)
// embed the type in TypeReferenceExpression so that the whole type can get replaced options |= ConvertTypeOptions.IncludeNamespace;
var tre = new TypeReferenceExpression { Type = astType }; AstType astType = AstBuilder.ConvertType(type, typeAttributes, options);
tre.AcceptVisitor(new AddNamespaceToType(), null);
astType = tre.Type;
}
StringWriter w = new StringWriter(); StringWriter w = new StringWriter();
if (type.IsByReference) { if (type.IsByReference) {
@ -411,28 +408,6 @@ namespace ICSharpCode.ILSpy
return w.ToString(); return w.ToString();
} }
sealed class AddNamespaceToType : DepthFirstAstVisitor<object, object>
{
public override object VisitSimpleType(SimpleType simpleType, object data)
{
base.VisitSimpleType(simpleType, data); // handle type arguments
TypeReference tr = simpleType.Annotation<TypeReference>();
if (tr != null && !string.IsNullOrEmpty(tr.Namespace)) {
string[] parts = tr.Namespace.Split('.');
AstType nsType = new SimpleType(parts[0]);
for (int i = 1; i < parts.Length; i++) {
nsType = new MemberType { Target = nsType, MemberName = parts[i] };
}
MemberType memberType = new MemberType();
memberType.Target = nsType;
memberType.MemberName = simpleType.Identifier;
simpleType.TypeArguments.MoveTo(memberType.TypeArguments);
simpleType.ReplaceWith(memberType);
}
return null;
}
}
public override bool ShowMember(MemberReference member) public override bool ShowMember(MemberReference member)
{ {
return showAllMembers || !AstBuilder.MemberIsHidden(member, new DecompilationOptions().DecompilerSettings); return showAllMembers || !AstBuilder.MemberIsHidden(member, new DecompilationOptions().DecompilerSettings);

2
ILSpy/TreeNodes/TypeTreeNode.cs

@ -59,7 +59,7 @@ namespace ICSharpCode.ILSpy.TreeNodes
} }
public override object Text { public override object Text {
get { return HighlightSearchMatch(type.Name); } get { return HighlightSearchMatch(this.Language.TypeToString(type, includeNamespace: false)); }
} }
public bool IsPublicAPI { public bool IsPublicAPI {

Loading…
Cancel
Save