@@ -5,6 +5,7 @@ namespace StyleCop.Analyzers.Helpers
55{
66 using System . Text ;
77 using Microsoft . CodeAnalysis ;
8+ using Microsoft . CodeAnalysis . CSharp ;
89 using Microsoft . CodeAnalysis . CSharp . Syntax ;
910 using StyleCop . Analyzers . Lightup ;
1011
@@ -17,83 +18,138 @@ internal static class SymbolNameHelpers
1718 private const string GenericTypeParametersClose = ">" ;
1819 private const string GenericSeparator = ", " ;
1920
21+ private const string TupleTypeOpen = "(" ;
22+ private const string TupleTypeClose = ")" ;
23+ private const string TupleElementSeparator = ", " ;
24+
2025 /// <summary>
2126 /// Generates the qualified name for the given symbol.
2227 /// </summary>
2328 /// <param name="symbol">The symbol to use.</param>
29+ /// <param name="name">The syntax node which resolves to the symbol.</param>
2430 /// <returns>The generated qualified name.</returns>
25- public static string ToQualifiedString ( this ISymbol symbol )
31+ public static string ToQualifiedString ( this ISymbol symbol , NameSyntax name )
2632 {
2733 var builder = ObjectPools . StringBuilderPool . Allocate ( ) ;
34+ AppendQualifiedSymbolName ( builder , symbol , name ) ;
35+ return ObjectPools . StringBuilderPool . ReturnAndFree ( builder ) ;
36+ }
2837
29- if ( symbol is INamedTypeSymbol namedTypeSymbol )
38+ private static bool AppendQualifiedSymbolName ( StringBuilder builder , ISymbol symbol , TypeSyntax type )
39+ {
40+ switch ( symbol . Kind )
3041 {
31- if ( SpecialTypeHelper . TryGetPredefinedType ( namedTypeSymbol . SpecialType , out PredefinedTypeSyntax specialTypeSyntax ) )
42+ case SymbolKind . ArrayType :
43+ var arraySymbol = ( IArrayTypeSymbol ) symbol ;
44+ AppendQualifiedSymbolName ( builder , arraySymbol . ElementType , ( type as ArrayTypeSyntax ) ? . ElementType ) ;
45+ builder
46+ . Append ( "[" )
47+ . Append ( ',' , arraySymbol . Rank - 1 )
48+ . Append ( "]" ) ;
49+ return true ;
50+
51+ case SymbolKind . Namespace :
52+ var namespaceSymbol = ( INamespaceSymbol ) symbol ;
53+ if ( namespaceSymbol . IsGlobalNamespace )
3254 {
33- return specialTypeSyntax . ToFullString ( ) ;
55+ return false ;
3456 }
3557
36- if ( namedTypeSymbol . IsTupleType ( ) )
58+ builder . Append ( namespaceSymbol . ToDisplayString ( ) ) ;
59+ return true ;
60+
61+ case SymbolKind . NamedType :
62+ var namedTypeSymbol = ( INamedTypeSymbol ) symbol ;
63+ if ( SpecialTypeHelper . TryGetPredefinedType ( namedTypeSymbol . SpecialType , out var specialTypeSyntax ) )
3764 {
38- namedTypeSymbol = namedTypeSymbol . TupleUnderlyingType ( ) ;
65+ builder . Append ( specialTypeSyntax . ToFullString ( ) ) ;
66+ return true ;
3967 }
68+ else if ( namedTypeSymbol . IsTupleType ( ) )
69+ {
70+ if ( TupleTypeSyntaxWrapper . IsInstance ( type ) )
71+ {
72+ var tupleType = ( TupleTypeSyntaxWrapper ) type ;
73+
74+ builder . Append ( TupleTypeOpen ) ;
75+ var elements = namedTypeSymbol . TupleElements ( ) ;
76+ for ( int i = 0 ; i < elements . Length ; i ++ )
77+ {
78+ var field = elements [ i ] ;
79+ var fieldType = tupleType . Elements . Count > i ? tupleType . Elements [ i ] : default ;
4080
41- AppendQualifiedSymbolName ( builder , namedTypeSymbol ) ;
81+ if ( i > 0 )
82+ {
83+ builder . Append ( TupleElementSeparator ) ;
84+ }
85+
86+ AppendQualifiedSymbolName ( builder , field . Type , fieldType . Type ) ;
87+ if ( field != field . CorrespondingTupleField ( ) )
88+ {
89+ builder . Append ( " " ) . Append ( field . Name ) ;
90+ }
91+ }
4292
43- if ( namedTypeSymbol . IsGenericType )
93+ builder . Append ( TupleTypeClose ) ;
94+ return true ;
95+ }
96+ else
97+ {
98+ return AppendQualifiedSymbolName ( builder , namedTypeSymbol . TupleUnderlyingType ( ) , type ) ;
99+ }
100+ }
101+ else if ( namedTypeSymbol . OriginalDefinition . SpecialType == SpecialType . System_Nullable_T )
102+ {
103+ AppendQualifiedSymbolName ( builder , namedTypeSymbol . TypeArguments [ 0 ] , ( type as NullableTypeSyntax ) ? . ElementType ) ;
104+ builder . Append ( "?" ) ;
105+ return true ;
106+ }
107+ else
44108 {
45- builder . Append ( GenericTypeParametersOpen ) ;
109+ if ( AppendQualifiedSymbolName ( builder , symbol . ContainingSymbol , ( type as QualifiedNameSyntax ) ? . Left ) )
110+ {
111+ builder . Append ( "." ) ;
112+ }
46113
47- foreach ( var typeArgument in namedTypeSymbol . TypeArguments )
114+ builder . Append ( symbol . Name ) ;
115+ if ( namedTypeSymbol . IsGenericType && ! namedTypeSymbol . TypeArguments . IsEmpty )
48116 {
49- if ( typeArgument is INamedTypeSymbol namedTypeArgument && typeArgument . IsTupleType ( ) )
50- {
51- builder . Append ( namedTypeArgument . TupleUnderlyingType ( ) . ToQualifiedString ( ) ) ;
52- }
53- else
117+ builder . Append ( GenericTypeParametersOpen ) ;
118+ var arguments = namedTypeSymbol . TypeArguments ;
119+ var argumentTypes = type is QualifiedNameSyntax qualifiedName
120+ ? ( qualifiedName . Right as GenericNameSyntax ) ? . TypeArgumentList
121+ : ( type as GenericNameSyntax ) ? . TypeArgumentList ;
122+
123+ for ( int i = 0 ; i < arguments . Length ; i ++ )
54124 {
55- builder . Append ( typeArgument . ToQualifiedString ( ) ) ;
125+ var argument = arguments [ i ] ;
126+ var argumentType = argumentTypes != null && argumentTypes . Arguments . Count > i ? argumentTypes . Arguments [ i ] : null ;
127+
128+ if ( i > 0 )
129+ {
130+ builder . Append ( GenericSeparator ) ;
131+ }
132+
133+ if ( ! argumentType . IsKind ( SyntaxKind . OmittedTypeArgument ) )
134+ {
135+ AppendQualifiedSymbolName ( builder , argument , argumentType ) ;
136+ }
56137 }
57138
58- builder . Append ( GenericSeparator ) ;
139+ builder . Append ( GenericTypeParametersClose ) ;
59140 }
60141
61- builder . Remove ( builder . Length - GenericSeparator . Length , GenericSeparator . Length ) ;
62- builder . Append ( GenericTypeParametersClose ) ;
142+ return true ;
63143 }
64- }
65- else
66- {
67- AppendQualifiedSymbolName ( builder , symbol ) ;
68- }
69-
70- return ObjectPools . StringBuilderPool . ReturnAndFree ( builder ) ;
71- }
72-
73- private static void AppendQualifiedSymbolName ( StringBuilder builder , ISymbol symbol )
74- {
75- switch ( symbol )
76- {
77- case IArrayTypeSymbol arraySymbol :
78- builder
79- . Append ( arraySymbol . ElementType . ContainingNamespace . ToDisplayString ( ) )
80- . Append ( "." )
81- . Append ( arraySymbol . ElementType . Name )
82- . Append ( "[" )
83- . Append ( ',' , arraySymbol . Rank - 1 )
84- . Append ( "]" ) ;
85- break ;
86144
87145 default :
88- if ( ! symbol . ContainingNamespace . IsGlobalNamespace )
146+ if ( symbol != null )
89147 {
90- builder
91- . Append ( symbol . ContainingNamespace . ToDisplayString ( ) )
92- . Append ( "." ) ;
148+ builder . Append ( symbol . Name ) ;
149+ return true ;
93150 }
94151
95- builder . Append ( symbol . Name ) ;
96- break ;
152+ return false ;
97153 }
98154 }
99155 }
0 commit comments