提交 8ce70292 编写于 作者: S Sam Harwell

Calculate aliases at the start of analysis

上级 32881a23
......@@ -15,6 +15,8 @@ namespace Microsoft.CodeAnalysis.CSharp.Diagnostics.SimplifyTypeNames
{
internal class TypeSyntaxSimplifierWalker : CSharpSyntaxWalker
{
private static readonly ImmutableHashSet<string> s_emptyAliasedNames = ImmutableHashSet.Create<string>(StringComparer.Ordinal);
/// <summary>
/// This set contains the full names of types that have equivalent predefined names in the language.
/// </summary>
......@@ -48,7 +50,7 @@ internal class TypeSyntaxSimplifierWalker : CSharpSyntaxWalker
/// This is used so we can easily tell if we should try to simplify some identifier to an
/// alias when we encounter it.
/// </summary>
private ImmutableHashSet<string> _aliasedNames = ImmutableHashSet.Create<string>(StringComparer.Ordinal);
private readonly ImmutableHashSet<string> _aliasedNames;
public List<Diagnostic> Diagnostics { get; } = new List<Diagnostic>();
......@@ -59,23 +61,58 @@ public TypeSyntaxSimplifierWalker(CSharpSimplifyTypeNamesDiagnosticAnalyzer anal
_semanticModel = semanticModel;
_optionSet = optionSet;
_cancellationToken = cancellationToken;
var root = semanticModel.SyntaxTree.GetRoot(cancellationToken);
_aliasedNames = GetAliasedNames(root as CompilationUnitSyntax);
}
public override void VisitUsingDirective(UsingDirectiveSyntax node)
private static ImmutableHashSet<string> GetAliasedNames(CompilationUnitSyntax? compilationUnit)
{
if (node.Alias is object)
var aliasedNames = s_emptyAliasedNames;
if (compilationUnit is null)
return aliasedNames;
foreach (var usingDirective in compilationUnit.Usings)
{
if (node.Name.GetRightmostName() is IdentifierNameSyntax identifierName)
AddAliasedName(usingDirective);
}
foreach (var member in compilationUnit.Members)
{
if (member is NamespaceDeclarationSyntax namespaceDeclaration)
AddAliasedNames(namespaceDeclaration);
}
return aliasedNames;
void AddAliasedName(UsingDirectiveSyntax usingDirective)
{
if (usingDirective.Alias is object)
{
var identifierAlias = identifierName.Identifier.ValueText;
if (!RoslynString.IsNullOrEmpty(identifierAlias))
if (usingDirective.Name.GetRightmostName() is IdentifierNameSyntax identifierName)
{
ImmutableInterlocked.Update(ref _aliasedNames, (set, alias) => set.Add(alias), identifierAlias);
var identifierAlias = identifierName.Identifier.ValueText;
if (!RoslynString.IsNullOrEmpty(identifierAlias))
{
aliasedNames = aliasedNames.Add(identifierAlias);
}
}
}
}
base.VisitUsingDirective(node);
void AddAliasedNames(NamespaceDeclarationSyntax namespaceDeclaration)
{
foreach (var usingDirective in namespaceDeclaration.Usings)
{
AddAliasedName(usingDirective);
}
foreach (var member in namespaceDeclaration.Members)
{
if (member is NamespaceDeclarationSyntax memberNamespace)
AddAliasedNames(memberNamespace);
}
}
}
public override void VisitQualifiedName(QualifiedNameSyntax node)
......
......@@ -9,6 +9,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames
Friend Class TypeSyntaxSimplifierWalker
Inherits VisualBasicSyntaxWalker
Private Shared ReadOnly s_emptyAliasedNames As ImmutableHashSet(Of String) = ImmutableHashSet.Create(Of String)(CaseInsensitiveComparison.Comparer)
Private Shared ReadOnly s_predefinedTypeMetadataNames As ImmutableHashSet(Of String) = ImmutableHashSet.Create(
CaseInsensitiveComparison.Comparer,
NameOf([Boolean]),
......@@ -39,7 +41,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames
''' This is used so we can easily tell if we should try to simplify some identifier to an
''' alias when we encounter it.
''' </summary>
Private _aliasedNames As ImmutableHashSet(Of String) = ImmutableHashSet.Create(Of String)(CaseInsensitiveComparison.Comparer)
Private ReadOnly _aliasedNames As ImmutableHashSet(Of String)
Public ReadOnly Property Diagnostics As List(Of Diagnostic) = New List(Of Diagnostic)()
......@@ -51,22 +53,43 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CodeFixes.SimplifyTypeNames
_optionSet = optionSet
_cancellationToken = cancellationToken
Dim root = semanticModel.SyntaxTree.GetRoot(cancellationToken)
_aliasedNames = GetAliasedNames(TryCast(root, CompilationUnitSyntax))
For Each aliasSymbol In semanticModel.Compilation.AliasImports()
_aliasedNames = _aliasedNames.Add(aliasSymbol.Target.Name)
Next
End Sub
Public Overrides Sub VisitSimpleImportsClause(node As SimpleImportsClauseSyntax)
If node.Alias IsNot Nothing Then
Dim identifierName = TryCast(node.Name.GetRightmostName(), IdentifierNameSyntax)
Private Shared Function GetAliasedNames(compilationUnit As CompilationUnitSyntax) As ImmutableHashSet(Of String)
Dim aliasedNames = s_emptyAliasedNames
If compilationUnit Is Nothing Then
Return aliasedNames
End If
For Each importsStatement In compilationUnit.Imports
For Each importsClause In importsStatement.ImportsClauses
Dim simpleImportsClause = TryCast(importsClause, SimpleImportsClauseSyntax)
If simpleImportsClause Is Nothing Then
Continue For
End If
AddAliasedName(aliasedNames, simpleImportsClause)
Next
Next
Return aliasedNames
End Function
Private Shared Sub AddAliasedName(ByRef aliasedNames As ImmutableHashSet(Of String), simpleImportsClause As SimpleImportsClauseSyntax)
If simpleImportsClause.Alias IsNot Nothing Then
Dim identifierName = TryCast(simpleImportsClause.Name.GetRightmostName(), IdentifierNameSyntax)
If identifierName IsNot Nothing Then
If Not String.IsNullOrEmpty(identifierName.Identifier.ValueText) Then
ImmutableInterlocked.Update(_aliasedNames, Function(names, identifier) names.Add(identifier), identifierName.Identifier.ValueText)
aliasedNames = aliasedNames.Add(identifierName.Identifier.ValueText)
End If
End If
End If
MyBase.VisitSimpleImportsClause(node)
End Sub
Public Overrides Sub VisitQualifiedName(node As QualifiedNameSyntax)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册