Skip to content

Fix FAR on an alias to a predefined type #76101

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Nov 26, 2024
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 @@ -483,6 +483,23 @@ namespace N
}
</Document>
</Project>
</Workspace>
Await TestAPIAndFeature(input, kind, host)
End Function

<WpfTheory, CombinatorialData>
<WorkItem("https://github.com/dotnet/roslyn/issues/74384")>
Public Async Function TestAliasToPrimitive1(kind As TestKind, host As TestHost) As Task
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
using $$TBitMap = [|ulong|];

var size = sizeof([|TBitMap|]);
var array = new [|TBitMap|][10];
</Document>
</Project>
</Workspace>
Await TestAPIAndFeature(input, kind, host)
End Function
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,25 +112,26 @@ protected override void FindReferencesInDocument<TData>(
FindReferencesSearchOptions options,
CancellationToken cancellationToken)
{
using var _ = ArrayBuilder<FinderLocation>.GetInstance(out var initialReferences);
using var _ = ArrayBuilder<FinderLocation>.GetInstance(out var tempReferences);

// First find all references to this type, either with it's actual name, or through potential
// global alises to it.
// First find all references to this type, using it's actual .Net name.
AddReferencesToTypeOrGlobalAliasToIt(
namedType, state, StandardCallbacks<FinderLocation>.AddToArrayBuilder, initialReferences, cancellationToken);
namedType, state, StandardCallbacks<FinderLocation>.AddToArrayBuilder, tempReferences, cancellationToken);

// The items in initialReferences need to be both reported and used later to calculate additional results.
foreach (var location in initialReferences)
// Next, if this named type is a predefined type (like int/long), also search for it with the C# name,
// not the .Net one.
AddPredefinedTypeReferences(namedType, state, tempReferences, cancellationToken);

// The items in tempReferences need to be both reported and used later to calculate additional results.
foreach (var location in tempReferences)
processResult(location, processResultData);

// This named type may end up being locally aliased as well. If so, now find all the references
// to the local alias.
// This named type may end up being locally aliased as well. If so, now find all the references to the local
// alias. Note: the local alias may be like `using X = System.Int32` or it could be `using X = int`. Because
// we searched for both forms above, we'll find all references to the local aliases to either form here.

FindLocalAliasReferences(
initialReferences, state, processResult, processResultData, cancellationToken);

FindPredefinedTypeReferences(
namedType, state, processResult, processResultData, cancellationToken);
tempReferences, state, processResult, processResultData, cancellationToken);

FindReferencesInDocumentInsideGlobalSuppressions(
namedType, state, processResult, processResultData, cancellationToken);
Expand Down Expand Up @@ -203,11 +204,10 @@ private static void FindOrdinaryReferences<TData>(
namedType, name, state, processResult, processResultData, cancellationToken);
}

private static void FindPredefinedTypeReferences<TData>(
private static void AddPredefinedTypeReferences(
INamedTypeSymbol symbol,
FindReferencesDocumentState state,
Action<FinderLocation, TData> processResult,
TData processResultData,
ArrayBuilder<FinderLocation> tempReferences,
CancellationToken cancellationToken)
{
var predefinedType = symbol.SpecialType.ToPredefinedType();
Expand All @@ -220,7 +220,8 @@ private static void FindPredefinedTypeReferences<TData>(
static (token, tuple) => IsPotentialReference(tuple.predefinedType, tuple.state.SyntaxFacts, token),
(state, predefinedType));

FindReferencesInTokens(symbol, state, tokens, processResult, processResultData, cancellationToken);
FindReferencesInTokens(
symbol, state, tokens, StandardCallbacks<FinderLocation>.AddToArrayBuilder, tempReferences, cancellationToken);
}

private static void FindAttributeReferences<TData>(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,23 +59,27 @@ protected sealed override SymbolKeyResolution Resolve(
SemanticModel semanticModel, SyntaxNode syntaxNode, string name, ISymbol target,
CancellationToken cancellationToken)
{
var symbol = semanticModel.GetDeclaredSymbol(syntaxNode, cancellationToken);
if (symbol != null)
// Don't call on the root compilation unit itself. For top level programs this will be the synthesized
// '<main>' entrypoint.
if (syntaxNode is not ICompilationUnitSyntax)
{
if (symbol.Kind == SymbolKind.Alias)
var symbol = semanticModel.GetDeclaredSymbol(syntaxNode, cancellationToken);
if (symbol != null)
{
var aliasSymbol = (IAliasSymbol)symbol;
if (aliasSymbol.Name == name &&
SymbolEquivalenceComparer.Instance.Equals(aliasSymbol.Target, target))
if (symbol is IAliasSymbol aliasSymbol)
{
return new SymbolKeyResolution(aliasSymbol);
if (aliasSymbol.Name == name &&
SymbolEquivalenceComparer.Instance.Equals(aliasSymbol.Target, target))
{
return new SymbolKeyResolution(aliasSymbol);
}
}
else if (symbol.Kind != SymbolKind.Namespace)
{
// Don't recurse into anything except namespaces. We can't find aliases
// any deeper than that.
return null;
}
}
else if (symbol.Kind != SymbolKind.Namespace)
{
// Don't recurse into anything except namespaces. We can't find aliases
// any deeper than that.
return null;
}
}

Expand All @@ -85,9 +89,7 @@ protected sealed override SymbolKeyResolution Resolve(
{
var result = Resolve(semanticModel, childNode, name, target, cancellationToken);
if (result.HasValue)
{
return result;
}
}
}

Expand Down
Loading