33
44namespace StyleCop . Analyzers . ReadabilityRules
55{
6+ using System ;
67 using System . Collections . Immutable ;
78 using System . Composition ;
89 using System . Linq ;
@@ -49,22 +50,22 @@ public override Task RegisterCodeFixesAsync(CodeFixContext context)
4950 private static async Task < Document > GetTransformedDocumentAsync ( Document document , Diagnostic diagnostic , CancellationToken cancellationToken )
5051 {
5152 var syntaxRoot = await document . GetSyntaxRootAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
53+ var semanticModel = await document . GetSemanticModelAsync ( cancellationToken ) . ConfigureAwait ( false ) ;
5254
5355 var newExpression = syntaxRoot . FindNode ( diagnostic . Location . SourceSpan , getInnermostNodeForTie : true ) ;
54- var newSyntaxRoot = syntaxRoot . ReplaceNode ( newExpression , GetReplacementNode ( newExpression ) ) ;
56+ var newSyntaxRoot = syntaxRoot . ReplaceNode ( newExpression , GetReplacementNode ( newExpression , semanticModel , cancellationToken ) ) ;
57+
5558 return document . WithSyntaxRoot ( newSyntaxRoot ) ;
5659 }
5760
58- private static SyntaxNode GetReplacementNode ( SyntaxNode node )
61+ private static SyntaxNode GetReplacementNode ( SyntaxNode node , SemanticModel semanticModel , CancellationToken cancellationToken )
5962 {
6063 var newExpression = ( ObjectCreationExpressionSyntax ) node ;
61- var nameSyntax = newExpression . Type as NameSyntax ;
62- var identifierName = NameSyntaxHelpers . ToNormalizedString ( nameSyntax ) ;
6364
6465 SyntaxNode replacement = null ;
65- if ( identifierName . EndsWith ( nameof ( CancellationToken ) , System . StringComparison . OrdinalIgnoreCase ) )
66+ if ( IsType < CancellationToken > ( newExpression . Type , semanticModel , cancellationToken ) )
6667 {
67- replacement = GetCancellationTokenNoneSyntax ( nameSyntax ) ;
68+ replacement = GetCancellationTokenNoneSyntax ( newExpression . Type ) ;
6869 }
6970 else
7071 {
@@ -76,11 +77,40 @@ private static SyntaxNode GetReplacementNode(SyntaxNode node)
7677 . WithTrailingTrivia ( newExpression . GetTrailingTrivia ( ) ) ;
7778 }
7879
79- private static SyntaxNode GetCancellationTokenNoneSyntax ( NameSyntax nameSyntax )
80+ private static bool IsType < T > ( TypeSyntax typeSyntax , SemanticModel semanticModel , CancellationToken cancellationToken )
81+ {
82+ var expectedType = typeof ( T ) ;
83+ var symbolInfo = semanticModel . GetSymbolInfo ( typeSyntax , cancellationToken ) ;
84+ var namedTypeSymbol = symbolInfo . Symbol as INamedTypeSymbol ;
85+
86+ if ( namedTypeSymbol == null )
87+ {
88+ return false ;
89+ }
90+
91+ if ( ! string . Equals ( expectedType . Name , namedTypeSymbol . Name , StringComparison . Ordinal ) )
92+ {
93+ return false ;
94+ }
95+
96+ if ( ! string . Equals ( expectedType . Namespace , namedTypeSymbol . ContainingNamespace ? . ToDisplayString ( SymbolDisplayFormat . FullyQualifiedFormat . WithGlobalNamespaceStyle ( SymbolDisplayGlobalNamespaceStyle . Omitted ) ) , StringComparison . Ordinal ) )
97+ {
98+ return false ;
99+ }
100+
101+ return true ;
102+ }
103+
104+ /// <summary>
105+ /// Gets a qualified member access expression for <c>CancellationToken.None</c>.
106+ /// </summary>
107+ /// <param name="typeSyntax">The type syntax from the original constructor.</param>
108+ /// <returns>A new member access expression.</returns>
109+ private static SyntaxNode GetCancellationTokenNoneSyntax ( TypeSyntax typeSyntax )
80110 {
81111 return SyntaxFactory . MemberAccessExpression (
82112 SyntaxKind . SimpleMemberAccessExpression ,
83- nameSyntax ,
113+ typeSyntax ,
84114 SyntaxFactory . IdentifierName ( nameof ( CancellationToken . None ) ) ) ;
85115 }
86116
@@ -101,10 +131,11 @@ protected override async Task<SyntaxNode> FixAllInDocumentAsync(FixAllContext fi
101131 }
102132
103133 var syntaxRoot = await document . GetSyntaxRootAsync ( fixAllContext . CancellationToken ) . ConfigureAwait ( false ) ;
134+ var semanticModel = await document . GetSemanticModelAsync ( ) . ConfigureAwait ( false ) ;
104135
105136 var nodes = diagnostics . Select ( diagnostic => syntaxRoot . FindNode ( diagnostic . Location . SourceSpan , getInnermostNodeForTie : true ) ) ;
106137
107- return syntaxRoot . ReplaceNodes ( nodes , ( originalNode , rewrittenNode ) => GetReplacementNode ( rewrittenNode ) ) ;
138+ return syntaxRoot . ReplaceNodes ( nodes , ( originalNode , rewrittenNode ) => GetReplacementNode ( rewrittenNode , semanticModel , CancellationToken . None ) ) ;
108139 }
109140 }
110141 }
0 commit comments