public static ImmutableArray <SymbolDisplayPart> GetDisplayParts( ISymbol symbol, SymbolDisplayFormat format, SymbolDisplayTypeDeclarationOptions typeDeclarationOptions = SymbolDisplayTypeDeclarationOptions.None, SymbolDisplayAdditionalOptions additionalOptions = SymbolDisplayAdditionalOptions.None, Func <ISymbol, AttributeData, bool> shouldDisplayAttribute = null) { ImmutableArray <SymbolDisplayPart> parts; if (symbol is INamedTypeSymbol typeSymbol) { parts = typeSymbol.ToDisplayParts(format, typeDeclarationOptions); } else { parts = symbol.ToDisplayParts(format); typeSymbol = null; } IEnumerable <AttributeData> attributes = (additionalOptions.HasOption(SymbolDisplayAdditionalOptions.IncludeAttributes)) ? GetAttributes(symbol, shouldDisplayAttribute) : ImmutableArray <AttributeData> .Empty; ImmutableArray <SymbolDisplayPart> .Builder builder = default; INamedTypeSymbol baseType = null; ImmutableArray <INamedTypeSymbol> interfaces = ImmutableArray <INamedTypeSymbol> .Empty; if (typeSymbol != null && (typeDeclarationOptions & SymbolDisplayTypeDeclarationOptions.BaseList) != 0) { if ((typeDeclarationOptions & SymbolDisplayTypeDeclarationOptions.BaseType) != 0 && typeSymbol.TypeKind.Is(TypeKind.Class, TypeKind.Interface)) { baseType = typeSymbol.BaseType; if (baseType?.SpecialType == SpecialType.System_Object) { baseType = null; } } if ((typeDeclarationOptions & SymbolDisplayTypeDeclarationOptions.Interfaces) != 0) { interfaces = typeSymbol.Interfaces; if (additionalOptions.HasOption(SymbolDisplayAdditionalOptions.OmitIEnumerable) && interfaces.Any(f => f.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T)) { interfaces = interfaces.RemoveAll(f => f.SpecialType == SpecialType.System_Collections_IEnumerable); } } } int baseListCount = interfaces.Length; if (baseType != null) { baseListCount++; } int constraintCount = 0; int whereIndex = -1; for (int i = 0; i < parts.Length; i++) { if (parts[i].IsKeyword("where")) { if (whereIndex == -1) { whereIndex = i; } constraintCount++; } } if (baseListCount > 0) { InitializeBuilder(); if (whereIndex != -1) { builder.AddRange(parts, whereIndex); } else { builder.AddRange(parts); builder.AddSpace(); } builder.AddPunctuation(":"); builder.AddSpace(); if (baseType != null) { builder.AddDisplayParts(baseType, format, additionalOptions); if (interfaces.Any()) { builder.AddPunctuation(","); if (additionalOptions.HasOption(SymbolDisplayAdditionalOptions.FormatBaseList)) { builder.AddLineBreak(); builder.AddIndentation(); } else { builder.AddSpace(); } } } IComparer <INamedTypeSymbol> comparer = (additionalOptions.HasOption(SymbolDisplayAdditionalOptions.OmitContainingNamespace)) ? SymbolDefinitionComparer.SystemFirstOmitContainingNamespace.TypeComparer : SymbolDefinitionComparer.SystemFirst.TypeComparer; interfaces = interfaces.Sort(comparer); ImmutableArray <INamedTypeSymbol> .Enumerator en = interfaces.GetEnumerator(); if (en.MoveNext()) { while (true) { builder.AddDisplayParts(en.Current, format, additionalOptions); if (en.MoveNext()) { builder.AddPunctuation(","); if (additionalOptions.HasOption(SymbolDisplayAdditionalOptions.FormatBaseList)) { builder.AddLineBreak(); builder.AddIndentation(); } else { builder.AddSpace(); } } else { break; } } } if (whereIndex != -1) { if (!additionalOptions.HasOption(SymbolDisplayAdditionalOptions.FormatConstraints) || (baseListCount == 1 && constraintCount == 1)) { builder.AddSpace(); } } } if (whereIndex != -1) { InitializeBuilder(); if (baseListCount == 0) { builder.AddRange(parts, whereIndex); } for (int i = whereIndex; i < parts.Length; i++) { if (parts[i].IsKeyword("where") && additionalOptions.HasOption(SymbolDisplayAdditionalOptions.FormatConstraints) && (baseListCount > 1 || constraintCount > 1)) { builder.AddLineBreak(); builder.AddIndentation(); } builder.Add(parts[i]); } } if (builder == null && attributes.Any()) { builder = ImmutableArray.CreateBuilder <SymbolDisplayPart>(parts.Length); AddAttributes(builder, attributes, format, additionalOptions, includeTrailingNewLine: true); builder.AddRange(parts); } bool hasEventAccessorList = false; if (additionalOptions.HasOption(SymbolDisplayAdditionalOptions.IncludeAccessorAttributes)) { if (symbol.Kind == SymbolKind.Property) { var propertySymbol = (IPropertySymbol)symbol; IMethodSymbol getMethod = propertySymbol.GetMethod; if (getMethod != null) { builder = builder ?? parts.ToBuilder(); AddAccessorAttributes(builder, getMethod, format, additionalOptions, shouldDisplayAttribute: shouldDisplayAttribute); } IMethodSymbol setMethod = propertySymbol.SetMethod; if (setMethod != null) { builder = builder ?? parts.ToBuilder(); AddAccessorAttributes(builder, setMethod, format, additionalOptions, shouldDisplayAttribute: shouldDisplayAttribute); } } else if (symbol.Kind == SymbolKind.Event) { var eventSymbol = (IEventSymbol)symbol; IEnumerable <AttributeData> addAttributes = GetAttributes(eventSymbol.AddMethod, shouldDisplayAttribute); IEnumerable <AttributeData> removeAttributes = GetAttributes(eventSymbol.RemoveMethod, shouldDisplayAttribute); if (addAttributes.Any() || removeAttributes.Any()) { hasEventAccessorList = true; builder = builder ?? parts.ToBuilder(); AddEventAccessorAttributes(builder, addAttributes, removeAttributes, format, additionalOptions); } } } ImmutableArray <IParameterSymbol> parameters = symbol.GetParameters(); if (additionalOptions.HasOption(SymbolDisplayAdditionalOptions.IncludeParameterAttributes) && parameters.Any(f => GetAttributes(f, shouldDisplayAttribute).Any())) { builder = builder ?? parts.ToBuilder(); AddParameterAttributes(builder, symbol, parameters, format, additionalOptions, shouldDisplayAttribute); } if (additionalOptions.HasOption(SymbolDisplayAdditionalOptions.FormatParameters) && parameters.Length > 1) { builder = builder ?? parts.ToBuilder(); FormatParameters(symbol, builder, DefinitionListFormat.Default.IndentChars); } if (ShouldAddTrailingSemicolon()) { if (builder == null) { parts = parts.Add(new SymbolDisplayPart(SymbolDisplayPartKind.Punctuation, null, ";")); } else { builder.AddPunctuation(";"); } } return(builder?.ToImmutableArray() ?? parts); void InitializeBuilder() { if (builder == null) { builder = ImmutableArray.CreateBuilder <SymbolDisplayPart>(parts.Length); if (attributes.Any()) { AddAttributes(builder, attributes, format, additionalOptions, includeTrailingNewLine: true); } } } bool ShouldAddTrailingSemicolon() { if (additionalOptions.HasOption(SymbolDisplayAdditionalOptions.IncludeTrailingSemicolon)) { if (typeSymbol?.TypeKind == TypeKind.Delegate) { return(true); } switch (symbol.Kind) { case SymbolKind.Event: return(!hasEventAccessorList); case SymbolKind.Field: return(symbol.ContainingType?.TypeKind != TypeKind.Enum); case SymbolKind.Method: return(true); } } return(false); } }
public static ImmutableArray <SymbolDisplayPart> GetDisplayParts( ISymbol symbol, SymbolDisplayFormat format, SymbolDisplayTypeDeclarationOptions typeDeclarationOptions = SymbolDisplayTypeDeclarationOptions.None, Func <INamedTypeSymbol, bool> isVisibleAttribute = null, bool formatBaseList = false, bool formatConstraints = false, bool formatParameters = false, bool splitAttributes = true, bool includeAttributeArguments = false, bool omitIEnumerable = false, bool useNameOnlyIfPossible = false) { ImmutableArray <SymbolDisplayPart> parts; if (symbol is INamedTypeSymbol typeSymbol) { parts = typeSymbol.ToDisplayParts(format, typeDeclarationOptions); } else { parts = symbol.ToDisplayParts(format); typeSymbol = null; } ImmutableArray <AttributeData> attributes = ImmutableArray <AttributeData> .Empty; bool hasAttributes = false; if (isVisibleAttribute != null) { attributes = symbol.GetAttributes(); hasAttributes = attributes.Any(f => isVisibleAttribute(f.AttributeClass)); } int baseListCount = 0; INamedTypeSymbol baseType = null; ImmutableArray <INamedTypeSymbol> interfaces = default; if (typeSymbol != null) { if (typeSymbol.TypeKind.Is(TypeKind.Class, TypeKind.Interface)) { baseType = typeSymbol.BaseType; if (baseType?.SpecialType == SpecialType.System_Object) { baseType = null; } } interfaces = typeSymbol.Interfaces; if (omitIEnumerable && interfaces.Any(f => f.OriginalDefinition.SpecialType == SpecialType.System_Collections_Generic_IEnumerable_T)) { interfaces = interfaces.RemoveAll(f => f.SpecialType == SpecialType.System_Collections_IEnumerable); } baseListCount = interfaces.Length; if (baseType != null) { baseListCount++; } } int constraintCount = 0; int whereIndex = -1; for (int i = 0; i < parts.Length; i++) { if (parts[i].IsKeyword("where")) { if (whereIndex == -1) { whereIndex = i; } constraintCount++; } } if (!hasAttributes && baseListCount == 0 && constraintCount == 0 && (!formatParameters || symbol.GetParameters().Length <= 1)) { return(parts); } INamespaceSymbol containingNamespace = (useNameOnlyIfPossible) ? symbol.ContainingNamespace : null; ImmutableArray <SymbolDisplayPart> .Builder builder = ImmutableArray.CreateBuilder <SymbolDisplayPart>(parts.Length); AddAttributes(builder, attributes, isVisibleAttribute, containingNamespace, splitAttributes: splitAttributes, includeAttributeArguments: includeAttributeArguments); if (baseListCount > 0) { if (whereIndex != -1) { builder.AddRange(parts, whereIndex); } else { builder.AddRange(parts); builder.AddSpace(); } builder.AddPunctuation(":"); builder.AddSpace(); if (baseType != null) { builder.AddDisplayParts(baseType, containingNamespace); if (interfaces.Any()) { builder.AddPunctuation(","); if (formatBaseList) { builder.AddLineBreak(); builder.AddIndentation(); } else { builder.AddSpace(); } } } interfaces = interfaces.Sort((x, y) => { INamespaceSymbol n1 = x.ContainingNamespace; INamespaceSymbol n2 = y.ContainingNamespace; if (!MetadataNameEqualityComparer <INamespaceSymbol> .Instance.Equals(n1, n2)) { return(string.CompareOrdinal( n1.ToDisplayString(SymbolDisplayFormats.TypeNameAndContainingTypesAndNamespaces), n2.ToDisplayString(SymbolDisplayFormats.TypeNameAndContainingTypesAndNamespaces))); } return(string.CompareOrdinal( ToDisplayString(x, containingNamespace), ToDisplayString(y, containingNamespace))); }); ImmutableArray <INamedTypeSymbol> .Enumerator en = interfaces.GetEnumerator(); if (en.MoveNext()) { while (true) { builder.AddDisplayParts(en.Current, containingNamespace); if (en.MoveNext()) { builder.AddPunctuation(","); if (formatBaseList) { builder.AddLineBreak(); builder.AddIndentation(); } else { builder.AddSpace(); } } else { break; } } } if (whereIndex != -1) { if (!formatConstraints || (baseListCount == 1 && constraintCount == 1)) { builder.AddSpace(); } } } else if (whereIndex != -1) { builder.AddRange(parts, whereIndex); } else { builder.AddRange(parts); } if (whereIndex != -1) { for (int i = whereIndex; i < parts.Length; i++) { if (parts[i].IsKeyword("where")) { if (formatConstraints && (baseListCount > 1 || constraintCount > 1)) { builder.AddLineBreak(); builder.AddIndentation(); } builder.Add(parts[i]); } else if (parts[i].IsTypeName() && parts[i].Symbol is INamedTypeSymbol namedTypeSymbol) { builder.AddDisplayParts(namedTypeSymbol, containingNamespace); } else { builder.Add(parts[i]); } } } if (formatParameters) { ImmutableArray <IParameterSymbol> parameters = symbol.GetParameters(); if (parameters.Length > 1) { FormatParameters(symbol, builder, DeclarationListOptions.DefaultValues.IndentChars); } } return(builder.ToImmutableArray()); }
internal static string ToDisplayString(this INamedTypeSymbol typeSymbol, SymbolDisplayFormat format, SymbolDisplayTypeDeclarationOptions typeDeclarationOptions) { return(typeSymbol.ToDisplayParts(format, typeDeclarationOptions).ToDisplayString()); }
internal static ImmutableArray <SymbolDisplayPart> ToDisplayParts(this INamedTypeSymbol typeSymbol, SymbolDisplayFormat format, SymbolDisplayTypeDeclarationOptions typeDeclarationOptions) { if (typeDeclarationOptions == SymbolDisplayTypeDeclarationOptions.None) { return(typeSymbol.ToDisplayParts(format)); } ImmutableArray <SymbolDisplayPart> parts = typeSymbol.ToDisplayParts(format); ImmutableArray <SymbolDisplayPart> .Builder builder = ImmutableArray.CreateBuilder <SymbolDisplayPart>(parts.Length); if ((typeDeclarationOptions & SymbolDisplayTypeDeclarationOptions.IncludeAccessibility) != 0) { switch (typeSymbol.DeclaredAccessibility) { case Accessibility.Public: { AddKeyword(SyntaxKind.PublicKeyword); break; } case Accessibility.ProtectedOrInternal: { AddKeyword(SyntaxKind.ProtectedKeyword); AddKeyword(SyntaxKind.InternalKeyword); break; } case Accessibility.Internal: { AddKeyword(SyntaxKind.InternalKeyword); break; } case Accessibility.Protected: { AddKeyword(SyntaxKind.ProtectedKeyword); break; } case Accessibility.ProtectedAndInternal: { AddKeyword(SyntaxKind.PrivateKeyword); AddKeyword(SyntaxKind.ProtectedKeyword); break; } case Accessibility.Private: { AddKeyword(SyntaxKind.PrivateKeyword); break; } default: { throw new InvalidOperationException(); } } } if ((typeDeclarationOptions & SymbolDisplayTypeDeclarationOptions.IncludeModifiers) != 0) { if (typeSymbol.IsStatic) { AddKeyword(SyntaxKind.StaticKeyword); } if (typeSymbol.IsSealed && !typeSymbol.TypeKind.Is(TypeKind.Struct, TypeKind.Enum, TypeKind.Delegate)) { AddKeyword(SyntaxKind.SealedKeyword); } if (typeSymbol.IsAbstract && typeSymbol.TypeKind != TypeKind.Interface) { AddKeyword(SyntaxKind.AbstractKeyword); } } builder.AddRange(parts); return(builder.ToImmutableArray()); void AddKeyword(SyntaxKind kind) { builder.Add(SymbolDisplayPartFactory.Keyword(SyntaxFacts.GetText(kind))); AddSpace(); } void AddSpace() { builder.Add(SymbolDisplayPartFactory.Space()); } }
public void Append(INamedTypeSymbol symbol, SymbolDisplayFormat format, SymbolDisplayTypeDeclarationOptions typeDeclarationOptions = SymbolDisplayTypeDeclarationOptions.None) { Append(symbol.ToDisplayParts(format, typeDeclarationOptions)); }