Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ private CSharpSyntaxHelper()
public override bool IsCaseSensitive
=> true;

public override int AttributeListKind
=> (int)SyntaxKind.AttributeList;

public override bool IsValidIdentifier(string name)
=> SyntaxFacts.IsValidIdentifier(name);

Expand Down Expand Up @@ -60,38 +63,50 @@ public override bool IsLambdaExpression(SyntaxNode node)
public override SyntaxToken GetUnqualifiedIdentifierOfName(SyntaxNode node)
=> ((NameSyntax)node).GetUnqualifiedName().Identifier;

public override void AddAliases(SyntaxNode node, ArrayBuilder<(string aliasName, string symbolName)> aliases, bool global)
public override void AddAliases(GreenNode node, ArrayBuilder<(string aliasName, string symbolName)> aliases, bool global)
{
if (node is CompilationUnitSyntax compilationUnit)
if (node is Syntax.InternalSyntax.CompilationUnitSyntax compilationUnit)
{
AddAliases(compilationUnit.Usings, aliases, global);
}
else if (node is BaseNamespaceDeclarationSyntax namespaceDeclaration)
else if (node is Syntax.InternalSyntax.BaseNamespaceDeclarationSyntax namespaceDeclaration)
{
AddAliases(namespaceDeclaration.Usings, aliases, global);
}
else
{
throw ExceptionUtilities.UnexpectedValue(node.Kind());
throw ExceptionUtilities.UnexpectedValue(node.KindText);
}
}

private static void AddAliases(SyntaxList<UsingDirectiveSyntax> usings, ArrayBuilder<(string aliasName, string symbolName)> aliases, bool global)
private static void AddAliases(
CodeAnalysis.Syntax.InternalSyntax.SyntaxList<Syntax.InternalSyntax.UsingDirectiveSyntax> usings,
ArrayBuilder<(string aliasName, string symbolName)> aliases,
bool global)
{
foreach (var usingDirective in usings)
{
if (usingDirective.Alias is null)
continue;

if (global != usingDirective.GlobalKeyword.Kind() is SyntaxKind.GlobalKeyword)
if (global != (usingDirective.GlobalKeyword != null))
continue;

var aliasName = usingDirective.Alias.Name.Identifier.ValueText;
var symbolName = usingDirective.Name.GetUnqualifiedName().Identifier.ValueText;
var symbolName = GetUnqualifiedName(usingDirective.Name).Identifier.ValueText;
aliases.Add((aliasName, symbolName));
}
}

private static Syntax.InternalSyntax.SimpleNameSyntax GetUnqualifiedName(Syntax.InternalSyntax.NameSyntax name)
=> name switch
{
Syntax.InternalSyntax.AliasQualifiedNameSyntax alias => alias.Name,
Syntax.InternalSyntax.QualifiedNameSyntax qualified => qualified.Right,
Syntax.InternalSyntax.SimpleNameSyntax simple => simple,
_ => throw ExceptionUtilities.UnexpectedValue(name.KindText),
};

public override void AddAliases(CompilationOptions compilation, ArrayBuilder<(string aliasName, string symbolName)> aliases)
{
// C# doesn't have global aliases at the compilation level.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ namespace Microsoft.CodeAnalysis.SourceGeneration
internal interface ISyntaxHelper
{
bool IsCaseSensitive { get; }
int AttributeListKind { get; }

bool IsValidIdentifier(string name);

Expand All @@ -33,13 +34,14 @@ internal interface ISyntaxHelper
/// <summary>
/// <paramref name="node"/> must be a compilation unit or namespace block.
/// </summary>
void AddAliases(SyntaxNode node, ArrayBuilder<(string aliasName, string symbolName)> aliases, bool global);
void AddAliases(GreenNode node, ArrayBuilder<(string aliasName, string symbolName)> aliases, bool global);
void AddAliases(CompilationOptions options, ArrayBuilder<(string aliasName, string symbolName)> aliases);
}

internal abstract class AbstractSyntaxHelper : ISyntaxHelper
{
public abstract bool IsCaseSensitive { get; }
public abstract int AttributeListKind { get; }

public abstract bool IsValidIdentifier(string name);

Expand All @@ -56,7 +58,7 @@ internal abstract class AbstractSyntaxHelper : ISyntaxHelper

public abstract bool IsLambdaExpression(SyntaxNode node);

public abstract void AddAliases(SyntaxNode node, ArrayBuilder<(string aliasName, string symbolName)> aliases, bool global);
public abstract void AddAliases(GreenNode node, ArrayBuilder<(string aliasName, string symbolName)> aliases, bool global);
public abstract void AddAliases(CompilationOptions options, ArrayBuilder<(string aliasName, string symbolName)> aliases);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ static GlobalAliases getGlobalAliasesInCompilationUnit(
Debug.Assert(compilationUnit is ICompilationUnitSyntax);
var globalAliases = Aliases.GetInstance();

syntaxHelper.AddAliases(compilationUnit, globalAliases, global: true);
syntaxHelper.AddAliases(compilationUnit.Green, globalAliases, global: true);

return GlobalAliases.Create(globalAliases.ToImmutableAndFree());
}
Expand All @@ -119,9 +119,12 @@ private static ImmutableArray<SyntaxNode> GetMatchingNodes(
CancellationToken cancellationToken)
{
var compilationUnit = syntaxTree.GetRoot(cancellationToken);

Debug.Assert(compilationUnit is ICompilationUnitSyntax);

// Walk the green node tree first to avoid allocating the entire red tree for files that have no attributes.
if (!ContainsAttributeList(compilationUnit.Green, syntaxHelper.AttributeListKind))
return ImmutableArray<SyntaxNode>.Empty;

var isCaseSensitive = syntaxHelper.IsCaseSensitive;
var comparison = isCaseSensitive ? StringComparison.Ordinal : StringComparison.OrdinalIgnoreCase;

Expand Down Expand Up @@ -158,14 +161,14 @@ void recurse(SyntaxNode node)

if (node is ICompilationUnitSyntax)
{
syntaxHelper.AddAliases(node, localAliases, global: false);
syntaxHelper.AddAliases(node.Green, localAliases, global: false);

recurseChildren(node);
}
else if (syntaxHelper.IsAnyNamespaceBlock(node))
{
var localAliasCount = localAliases.Count;
syntaxHelper.AddAliases(node, localAliases, global: false);
syntaxHelper.AddAliases(node.Green, localAliases, global: false);

recurseChildren(node);

Expand Down Expand Up @@ -285,4 +288,21 @@ bool matchesAttributeName(string currentAttributeName, bool withAttributeSuffix)
return false;
}
}

private static bool ContainsAttributeList(GreenNode node, int attributeListKind)
{
if (node.RawKind == attributeListKind)
return true;

foreach (var child in node.ChildNodesAndTokens())
{
if (node.IsToken)
return false;

if (ContainsAttributeList(child, attributeListKind))
return true;
}

return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic

Public Overrides ReadOnly Property IsCaseSensitive As Boolean = False

Public Overrides ReadOnly Property AttributeListKind As Integer = SyntaxKind.AttributeList

Public Overrides Function IsValidIdentifier(name As String) As Boolean
Return SyntaxFacts.IsValidIdentifier(name)
End Function
Expand Down Expand Up @@ -83,20 +85,34 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Throw ExceptionUtilities.UnexpectedValue(node.Kind())
End Function

Public Overrides Sub AddAliases(node As SyntaxNode, aliases As ArrayBuilder(Of (aliasName As String, symbolName As String)), [global] As Boolean)
Public Overloads Function GetUnqualifiedIdentifierOfName(name As InternalSyntax.NameSyntax) As InternalSyntax.IdentifierTokenSyntax
Dim qualifiedName = TryCast(name, InternalSyntax.QualifiedNameSyntax)
If qualifiedName IsNot Nothing Then
Return qualifiedName.Right.Identifier
End If

Dim simpleName = TryCast(name, InternalSyntax.SimpleNameSyntax)
If simpleName IsNot Nothing Then
Return simpleName.Identifier
End If

Throw ExceptionUtilities.UnexpectedValue(name.KindText)
End Function

Public Overrides Sub AddAliases(node As GreenNode, aliases As ArrayBuilder(Of (aliasName As String, symbolName As String)), [global] As Boolean)
' VB does not have global aliases at the syntax level.
If [global] Then
Return
End If

Dim compilationUnit = TryCast(node, CompilationUnitSyntax)
Dim compilationUnit = TryCast(node, InternalSyntax.CompilationUnitSyntax)
If compilationUnit Is Nothing Then
Return
End If

For Each importsStatement In compilationUnit.Imports
For Each importsClause In importsStatement.ImportsClauses
ProcessImportsClause(aliases, importsClause)
For i = 0 To importsStatement.ImportsClauses.Count - 1
ProcessImportsClause(aliases, importsStatement.ImportsClauses(i))
Next
Next
End Sub
Expand All @@ -106,12 +122,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic

For Each globalImport In vbOptions.GlobalImports
Dim clause = globalImport.Clause
ProcessImportsClause(aliases, clause)
ProcessImportsClause(aliases, DirectCast(clause.Green, InternalSyntax.ImportsClauseSyntax))
Next
End Sub

Private Sub ProcessImportsClause(aliases As ArrayBuilder(Of (aliasName As String, symbolName As String)), clause As ImportsClauseSyntax)
Dim importsClause = TryCast(clause, SimpleImportsClauseSyntax)
Private Sub ProcessImportsClause(aliases As ArrayBuilder(Of (aliasName As String, symbolName As String)), clause As InternalSyntax.ImportsClauseSyntax)
Dim importsClause = TryCast(clause, InternalSyntax.SimpleImportsClauseSyntax)
If importsClause?.Alias IsNot Nothing Then
aliases.Add((importsClause.Alias.Identifier.ValueText, GetUnqualifiedIdentifierOfName(importsClause.Name).ValueText))
End If
Expand Down