Browse Source

Fix ToString methods of CSharpLanguage

pull/1198/head
Siegfried Pammer 7 years ago
parent
commit
a4962e17cd
  1. 221
      ILSpy/Languages/CSharpLanguage.cs
  2. 13
      ILSpy/Languages/Language.cs
  3. 3
      ILSpy/TreeNodes/TypeTreeNode.cs

221
ILSpy/Languages/CSharpLanguage.cs

@ -403,19 +403,46 @@ namespace ICSharpCode.ILSpy
return base.WriteResourceToFile(fileName, resourceName, entryStream); return base.WriteResourceToFile(fileName, resourceName, entryStream);
} }
} }
static readonly CSharpFormattingOptions TypeToStringFormattingOptions = FormattingOptionsFactory.CreateEmpty();
public override string TypeToString(IType type, bool includeNamespace) public override string TypeToString(IType type, bool includeNamespace)
{ {
if (type == null) if (type == null)
throw new ArgumentNullException(nameof(type)); throw new ArgumentNullException(nameof(type));
TypeSystemAstBuilder builder = new TypeSystemAstBuilder(); TypeSystemAstBuilder builder = new TypeSystemAstBuilder();
builder.AlwaysUseShortTypeNames = !includeNamespace;
AstType astType = builder.ConvertType(type); AstType astType = builder.ConvertType(type);
StringWriter w = new StringWriter(); StringWriter w = new StringWriter();
astType.AcceptVisitor(new CSharpOutputVisitor(w, FormattingOptionsFactory.CreateAllman())); astType.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions));
return w.ToString(); return w.ToString();
} }
public override string TypeDefinitionToString(ITypeDefinition type, bool includeNamespace)
{
if (type == null)
throw new ArgumentNullException(nameof(type));
var buffer = new System.Text.StringBuilder();
if (includeNamespace) {
buffer.Append(type.FullName);
} else {
buffer.Append(type.Name);
}
if (type.TypeParameterCount > 0) {
buffer.Append('<');
int i = 0;
foreach (var tp in type.TypeParameters) {
if (i > 0)
buffer.Append(", ");
buffer.Append(tp.Name);
i++;
}
buffer.Append('>');
}
return buffer.ToString();
}
public override string FieldToString(IField field, bool includeTypeName, bool includeNamespace) public override string FieldToString(IField field, bool includeTypeName, bool includeNamespace)
{ {
if (field == null) if (field == null)
@ -429,7 +456,7 @@ namespace ICSharpCode.ILSpy
return typeName.Name + "." + simple; return typeName.Name + "." + simple;
return typeName + "." + simple; return typeName + "." + simple;
} }
/*
public override string PropertyToString(IProperty property, bool includeTypeName, bool includeNamespace, bool? isIndexer = null) public override string PropertyToString(IProperty property, bool includeTypeName, bool includeNamespace, bool? isIndexer = null)
{ {
if (property == null) if (property == null)
@ -439,147 +466,66 @@ namespace ICSharpCode.ILSpy
convertTypeOptions |= ConvertTypeOptions.IncludeNamespace; convertTypeOptions |= ConvertTypeOptions.IncludeNamespace;
if (includeTypeName) if (includeTypeName)
convertTypeOptions |= ConvertTypeOptions.IncludeOuterTypeName; convertTypeOptions |= ConvertTypeOptions.IncludeOuterTypeName;
var metadata = property.Module.Metadata;
var pd = metadata.GetPropertyDefinition(property.Handle);
var accessors = pd.GetAccessors();
var accessorHandle = accessors.GetAny();
var accessor = metadata.GetMethodDefinition(accessorHandle);
var declaringType = metadata.GetTypeDefinition(accessor.GetDeclaringType());
if (!isIndexer.HasValue) {
isIndexer = accessor.GetDeclaringType().GetDefaultMemberName(metadata) != null;
}
var buffer = new System.Text.StringBuilder(); var buffer = new System.Text.StringBuilder();
if (isIndexer.Value) { if (isIndexer.Value) {
var overrides = accessorHandle.GetMethodImplementations(metadata); if (property.IsExplicitInterfaceImplementation) {
if (overrides.Any()) { string name = property.Name;
string name = metadata.GetString(pd.Name);
int index = name.LastIndexOf('.'); int index = name.LastIndexOf('.');
if (index > 0) { if (index > 0) {
buffer.Append(name.Substring(0, index)); buffer.Append(name.Substring(0, index));
buffer.Append(@"."); buffer.Append('.');
} }
} }
buffer.Append(@"this["); buffer.Append(@"this[");
var signature = pd.DecodeSignature(new AstTypeBuilder(convertTypeOptions), new GenericContext(accessorHandle, property.Module));
var parameterHandles = accessor.GetParameters();
int i = 0; int i = 0;
CustomAttributeHandleCollection? returnTypeAttributes = null; var parameters = property.Parameters;
if (signature.RequiredParameterCount > parameterHandles.Count) { foreach (var param in parameters) {
foreach (var type in signature.ParameterTypes) { if (i > 0)
if (i > 0)
buffer.Append(", ");
buffer.Append(TypeToString(signature.ParameterTypes[i], metadata, null));
i++;
}
} else {
foreach (var h in parameterHandles) {
var p = metadata.GetParameter(h);
if (p.SequenceNumber > 0 && i < signature.ParameterTypes.Length) {
if (i > 0)
buffer.Append(", ");
buffer.Append(TypeToString(signature.ParameterTypes[i], metadata, p.GetCustomAttributes(), h));
i++;
}
if (p.SequenceNumber == 0) {
returnTypeAttributes = p.GetCustomAttributes();
}
}
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
if (signature.ParameterTypes.Length > 0)
buffer.Append(", "); buffer.Append(", ");
buffer.Append("..."); buffer.Append(TypeToString(param.Type, includeNamespace));
i++;
} }
buffer.Append(@"]"); buffer.Append(@"]");
buffer.Append(" : ");
buffer.Append(TypeToString(signature.ReturnType, metadata, returnTypeAttributes));
} else { } else {
var signature = pd.DecodeSignature(new AstTypeBuilder(convertTypeOptions), new GenericContext(accessorHandle, property.Module)); buffer.Append(property.Name);
var parameterHandles = accessor.GetParameters();
CustomAttributeHandleCollection? returnTypeAttributes = null;
if (parameterHandles.Count > 0) {
var p = metadata.GetParameter(parameterHandles.First());
if (p.SequenceNumber == 0) {
returnTypeAttributes = p.GetCustomAttributes();
}
}
buffer.Append(metadata.GetString(pd.Name));
buffer.Append(" : ");
buffer.Append(TypeToString(signature.ReturnType, metadata, returnTypeAttributes));
} }
buffer.Append(" : ");
buffer.Append(TypeToString(property.ReturnType, includeNamespace));
return buffer.ToString(); return buffer.ToString();
} }
static readonly CSharpFormattingOptions TypeToStringFormattingOptions = FormattingOptionsFactory.CreateEmpty();
string TypeToString(AstType astType, MetadataReader metadata, CustomAttributeHandleCollection? customAttributes, ParameterHandle paramHandle = default) public override string MethodToString(IMethod method, bool includeTypeName, bool includeNamespace)
{ {
StringWriter w = new StringWriter(); if (method == null)
throw new ArgumentNullException(nameof(method));
if (astType is ComposedType ct && ct.HasRefSpecifier) {
if (!paramHandle.IsNil) {
var p = metadata.GetParameter(paramHandle);
if ((p.Attributes & ParameterAttributes.In) == 0 && (p.Attributes & ParameterAttributes.Out) != 0) {
w.Write("out ");
} else {
w.Write("ref ");
}
} else {
w.Write("ref ");
}
astType = ct.BaseType;
astType.Remove();
}
var st = new SyntaxTree();
st.AddChild(astType, Roles.Type);
//st.AcceptVisitor(new InsertDynamicTypeVisitor(metadata, customAttributes));
// TODO: we should probably remove AstTypeBuilder and use TypeBuilder(with dummy compilation)+TSAstBuilder instead.
// Otherwise we'd need to duplicate a whole bunch of logic...
st.FirstChild.AcceptVisitor(new CSharpOutputVisitor(w, TypeToStringFormattingOptions));
return w.ToString();
}
public override string MethodToString(Decompiler.Metadata.MethodDefinition method, bool includeTypeName, bool includeNamespace)
{
if (method.IsNil)
throw new ArgumentNullException("method");
ConvertTypeOptions convertTypeOptions = ConvertTypeOptions.IncludeTypeParameterDefinitions; ConvertTypeOptions convertTypeOptions = ConvertTypeOptions.IncludeTypeParameterDefinitions;
if (includeNamespace) if (includeNamespace)
convertTypeOptions |= ConvertTypeOptions.IncludeNamespace; convertTypeOptions |= ConvertTypeOptions.IncludeNamespace;
if (includeTypeName) if (includeTypeName)
convertTypeOptions |= ConvertTypeOptions.IncludeOuterTypeName; convertTypeOptions |= ConvertTypeOptions.IncludeOuterTypeName;
var metadata = method.Module.Metadata;
var md = metadata.GetMethodDefinition(method.Handle);
string name; string name;
if (md.IsConstructor(metadata)) { if (method.IsConstructor) {
name = TypeToString(new Decompiler.Metadata.TypeDefinition(method.Module, md.GetDeclaringType()), includeNamespace: includeNamespace); name = TypeDefinitionToString(method.DeclaringTypeDefinition, includeNamespace: includeNamespace);
} else { } else {
if (includeTypeName) { if (includeTypeName) {
name = TypeToString(new Decompiler.Metadata.TypeDefinition(method.Module, md.GetDeclaringType()), includeNamespace: includeNamespace) + "."; name = TypeDefinitionToString(method.DeclaringTypeDefinition, includeNamespace: includeNamespace) + ".";
} else { } else {
name = ""; name = "";
} }
name += metadata.GetString(md.Name); name += method.Name;
} }
var signature = md.DecodeSignature(new AstTypeBuilder(convertTypeOptions), new GenericContext(method));
int i = 0; int i = 0;
var buffer = new System.Text.StringBuilder(name); var buffer = new System.Text.StringBuilder(name);
var genericParams = md.GetGenericParameters();
if (genericParams.Count > 0) { if (method.TypeParameters.Count > 0) {
buffer.Append('<'); buffer.Append('<');
foreach (var h in genericParams) { foreach (var tp in method.TypeParameters) {
var gp = metadata.GetGenericParameter(h);
if (i > 0) if (i > 0)
buffer.Append(", "); buffer.Append(", ");
buffer.Append(metadata.GetString(gp.Name)); buffer.Append(tp.Name);
i++; i++;
} }
buffer.Append('>'); buffer.Append('>');
@ -587,71 +533,30 @@ namespace ICSharpCode.ILSpy
buffer.Append('('); buffer.Append('(');
i = 0; i = 0;
var parameterHandles = md.GetParameters(); var parameters = method.Parameters;
CustomAttributeHandleCollection? returnTypeAttributes = null; foreach (var param in parameters) {
if (signature.RequiredParameterCount > parameterHandles.Count) { if (i > 0)
foreach (var type in signature.ParameterTypes) {
if (i > 0)
buffer.Append(", ");
buffer.Append(TypeToString(signature.ParameterTypes[i], metadata, null));
i++;
}
} else {
foreach (var h in parameterHandles) {
var p = metadata.GetParameter(h);
if (p.SequenceNumber > 0 && i < signature.ParameterTypes.Length) {
if (i > 0)
buffer.Append(", ");
buffer.Append(TypeToString(signature.ParameterTypes[i], metadata, p.GetCustomAttributes(), h));
i++;
}
if (p.SequenceNumber == 0) {
returnTypeAttributes = p.GetCustomAttributes();
}
}
}
if (signature.Header.CallingConvention == SignatureCallingConvention.VarArgs) {
if (signature.ParameterTypes.Length > 0)
buffer.Append(", "); buffer.Append(", ");
buffer.Append("..."); buffer.Append(TypeToString(param.Type, includeNamespace));
i++;
} }
buffer.Append(')'); buffer.Append(')');
buffer.Append(" : "); buffer.Append(" : ");
buffer.Append(TypeToString(signature.ReturnType, metadata, returnTypeAttributes)); buffer.Append(TypeToString(method.ReturnType, includeNamespace));
return buffer.ToString(); return buffer.ToString();
} }
public override string EventToString(Decompiler.Metadata.EventDefinition @event, bool includeTypeName, bool includeNamespace) public override string EventToString(IEvent @event, bool includeTypeName, bool includeNamespace)
{ {
if (@event.IsNil) if (@event == null)
throw new ArgumentNullException(nameof(@event)); throw new ArgumentNullException(nameof(@event));
ConvertTypeOptions convertTypeOptions = ConvertTypeOptions.IncludeTypeParameterDefinitions;
if (includeNamespace)
convertTypeOptions |= ConvertTypeOptions.IncludeNamespace;
if (includeTypeName)
convertTypeOptions |= ConvertTypeOptions.IncludeOuterTypeName;
var metadata = @event.Module.Metadata;
var ed = metadata.GetEventDefinition(@event.Handle);
var accessors = ed.GetAccessors();
var accessorHandle = accessors.GetAny();
var accessor = metadata.GetMethodDefinition(accessorHandle);
var declaringType = metadata.GetTypeDefinition(accessor.GetDeclaringType());
var signature = ed.DecodeSignature(metadata, new AstTypeBuilder(convertTypeOptions), new GenericContext(accessorHandle, @event.Module));
var parameterHandles = accessor.GetParameters();
CustomAttributeHandleCollection? returnTypeAttributes = null;
if (parameterHandles.Count > 0) {
var p = metadata.GetParameter(parameterHandles.First());
if (p.SequenceNumber == 0) {
returnTypeAttributes = p.GetCustomAttributes();
}
}
var buffer = new System.Text.StringBuilder(); var buffer = new System.Text.StringBuilder();
buffer.Append(metadata.GetString(ed.Name)); buffer.Append(GetDisplayName(@event, includeTypeName, includeNamespace));
buffer.Append(" : "); buffer.Append(" : ");
buffer.Append(TypeToString(signature, metadata, returnTypeAttributes)); buffer.Append(TypeToString(@event.ReturnType, includeNamespace));
return buffer.ToString(); return buffer.ToString();
}*/ }
public override bool ShowMember(IEntity member) public override bool ShowMember(IEntity member)
{ {

13
ILSpy/Languages/Language.cs

@ -149,7 +149,7 @@ namespace ICSharpCode.ILSpy
} }
/// <summary> /// <summary>
/// Converts a type definition, reference or specification into a string. This method is used by the type tree nodes and search results. /// Converts a type definition, reference or specification into a string. This method is used by tree nodes and search results.
/// </summary> /// </summary>
public virtual string TypeToString(IType type, bool includeNamespace) public virtual string TypeToString(IType type, bool includeNamespace)
{ {
@ -159,6 +159,17 @@ namespace ICSharpCode.ILSpy
return type.Name; return type.Name;
} }
/// <summary>
/// Converts a type definition into a string. This method is used by tree nodes and search results.
/// </summary>
public virtual string TypeDefinitionToString(ITypeDefinition type, bool includeNamespace)
{
if (includeNamespace)
return type.FullName;
else
return type.Name;
}
/// <summary> /// <summary>
/// Converts a member signature to a string. /// Converts a member signature to a string.
/// This is used for displaying the tooltip on a member reference. /// This is used for displaying the tooltip on a member reference.

3
ILSpy/TreeNodes/TypeTreeNode.cs

@ -40,7 +40,8 @@ namespace ICSharpCode.ILSpy.TreeNodes
public AssemblyTreeNode ParentAssemblyNode { get; } public AssemblyTreeNode ParentAssemblyNode { get; }
public override object Text => this.Language.TypeToString(TypeDefinition, includeNamespace: false) + TypeDefinition.MetadataToken.ToSuffixString(); public override object Text => this.Language.TypeDefinitionToString(TypeDefinition, includeNamespace: false)
+ TypeDefinition.MetadataToken.ToSuffixString();
public override bool IsPublicAPI { public override bool IsPublicAPI {
get { get {

Loading…
Cancel
Save