Skip to content

Commit

Permalink
Simplified generation of CodeAction title.
Browse files Browse the repository at this point in the history
  • Loading branch information
MaStr11 committed Jan 8, 2018
1 parent ae7bdbf commit b752f84
Show file tree
Hide file tree
Showing 3 changed files with 9 additions and 78 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,9 @@

using System.Collections.Immutable;
using System.Composition;
using System.Diagnostics;
using Microsoft.CodeAnalysis.AliasAmbiguousType;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Shared.Extensions;

namespace Microsoft.CodeAnalysis.CSharp.AliasAmbiguousType
{
Expand All @@ -21,42 +20,7 @@ internal class CSharpAliasAmbiguousTypeCodeFixProvider : AbstractAliasAmbiguousT
public override ImmutableArray<string> FixableDiagnosticIds
=> ImmutableArray.Create(CS0104);

protected override string GetTextPreviewOfChange(SyntaxNode aliasNode)
{
Debug.Assert(aliasNode is UsingDirectiveSyntax);
// A poor man's name simplifier. For the preview of the context menu text the likely change is predicted by
// removing the global:: namespace alias if present. For the majority of cases this should be the same result
// as what the real Simplifier produces in the preview pane and when the fix is applied.
aliasNode = RemoveGlobalNamespaceAliasIfPresent(aliasNode);
return aliasNode.NormalizeWhitespace().ToFullString();
}

NameSyntax GetLeftmostQualifiedName(NameSyntax nameSyntax)
{
while (nameSyntax is QualifiedNameSyntax qualifiedNameSyntax)
{
nameSyntax = qualifiedNameSyntax.Left;
}

return nameSyntax;
}

private SyntaxNode RemoveGlobalNamespaceAliasIfPresent(SyntaxNode aliasNode)
{
var usingDirective = (UsingDirectiveSyntax)aliasNode;
var nameSyntax = usingDirective.Name;
var leftmostName = GetLeftmostQualifiedName(nameSyntax);
if (leftmostName is AliasQualifiedNameSyntax aliasQualifiedName &&
aliasQualifiedName.Alias.Identifier.IsKind(SyntaxKind.GlobalKeyword))
{
if (aliasQualifiedName.Parent is QualifiedNameSyntax parentOfGlobalAlias)
{
var replacement = parentOfGlobalAlias.WithLeft(SyntaxFactory.IdentifierName(aliasQualifiedName.Name.Identifier));
usingDirective = usingDirective.ReplaceNode(parentOfGlobalAlias, replacement);
}
}

return usingDirective;
}
protected override string GetTextPreviewOfChange(string alias, ITypeSymbol typeSymbol)
=> $"using { alias } = { typeSymbol.ToNameDisplayString() };";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace Microsoft.CodeAnalysis.AliasAmbiguousType
internal abstract class AbstractAliasAmbiguousTypeCodeFixProvider : CodeFixProvider
{

protected abstract string GetTextPreviewOfChange(SyntaxNode aliasNode);
protected abstract string GetTextPreviewOfChange(string aliasName, ITypeSymbol typeSymbol);

public override FixAllProvider GetFixAllProvider() => null;

Expand All @@ -42,18 +42,17 @@ public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var addImportService = document.GetLanguageService<IAddImportsService>();
var syntaxGenerator = document.GetLanguageService<SyntaxGenerator>();
var diagnostic = context.Diagnostics.First();
var compilation = semanticModel.Compilation;
var optionSet = await document.GetOptionsAsync(cancellationToken).ConfigureAwait(false);
var placeSystemNamespaceFirst = optionSet.GetOption(GenerationOptions.PlaceSystemNamespaceFirst, document.Project.Language);
var codeActionsBuilder = ImmutableArray.CreateBuilder<CodeAction>(symbolInfo.CandidateSymbols.Length);
foreach (var symbol in symbolInfo.CandidateSymbols)
foreach (var symbol in symbolInfo.CandidateSymbols.Cast<ITypeSymbol>())
{
var typeName = symbol.Name;
var aliasDirective = syntaxGenerator.AliasImportDeclaration(typeName, (ITypeSymbol)symbol);
var codeActionPreviewText = GetTextPreviewOfChange(aliasDirective);
var codeActionPreviewText = GetTextPreviewOfChange(typeName, symbol);
Task<Document> CreateChangedDocument(CancellationToken c)
{
var aliasDirective = syntaxGenerator.AliasImportDeclaration(typeName, symbol);
var newRoot = addImportService.AddImport(compilation, root, diagnosticNode, aliasDirective, placeSystemNamespaceFirst);
return Task.FromResult(document.WithSyntaxRoot(newRoot));
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ Imports System.Collections.Immutable
Imports System.Composition
Imports Microsoft.CodeAnalysis.AliasAmbiguousType
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax

Namespace Microsoft.CodeAnalysis.VisualBasic.AliasAmbiguousType

Expand All @@ -18,40 +17,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AliasAmbiguousType

Public Overrides ReadOnly Property FixableDiagnosticIds As ImmutableArray(Of String) = ImmutableArray.Create(BC30561)

Protected Overrides Function GetTextPreviewOfChange(aliasNode As SyntaxNode) As String
Debug.Assert(TypeOf aliasNode Is ImportsStatementSyntax)
' A poor man's name simplifier. For the preview of the context menu text the likely change is predicted by
' removing the global. namespace alias if present. For the majority Of cases this should be the same result
' as what the real Simplifier produces in the preview pane And when the fix is applied.
' The real Simplifier also removes Module names from the import which is not supported here.
aliasNode = RemoveGlobalNamespaceAliasIfPresent(aliasNode)
Return aliasNode.NormalizeWhitespace().ToFullString()
Protected Overrides Function GetTextPreviewOfChange(aliasName As String, typeSymbol As ITypeSymbol) As String
Return $"Imports { aliasName } = { typeSymbol.ToNameDisplayString() }"
End Function

Private Function RemoveGlobalNamespaceAliasIfPresent(aliasNode As SyntaxNode) As SyntaxNode
Dim importsStatement = CType(aliasNode, ImportsStatementSyntax)
If importsStatement.ImportsClauses.Count = 1 AndAlso
TypeOf importsStatement.ImportsClauses(0) Is SimpleImportsClauseSyntax Then
Dim importsName = CType(importsStatement.ImportsClauses(0), SimpleImportsClauseSyntax).Name
Dim leftMostNameSyntax = GetLeftmostName(importsName)
If TypeOf leftMostNameSyntax Is GlobalNameSyntax Then
If TypeOf leftMostNameSyntax.Parent Is QualifiedNameSyntax Then
Dim parentOfGlobal = CType(leftMostNameSyntax.Parent, QualifiedNameSyntax)
Dim replacement = SyntaxFactory.IdentifierName(parentOfGlobal.Right.Identifier)
importsStatement = importsStatement.ReplaceNode(parentOfGlobal, replacement)
End If
End If
End If

Return importsStatement
End Function

Private Function GetLeftmostName(name As NameSyntax) As NameSyntax
While TypeOf name Is QualifiedNameSyntax
name = CType(name, QualifiedNameSyntax).Left
End While

Return name
End Function
End Class
End Namespace

0 comments on commit b752f84

Please sign in to comment.