diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.AccessorSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.AccessorSymbols.vb index 2c83f93f0bbf804c00b3eaaa4264d4b56491421a..b7dd6204231bf7abc1dffc7f1de21239afcdb218 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.AccessorSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.AccessorSymbols.vb @@ -585,6 +585,50 @@ class Usages Await TestStreamingFeature(input) End Function + + Public Async Function TestCSharpAccessor_Indexer1() As Task + Dim input = + + + +interface IC +{ + int this[int i] { {|Definition:$$get|} => 0; set { } } +} + +class C : IC +{ + public virtual int this[int i] { {|Definition:get|} => 0; set { } } +} + +class D : C +{ + public override int this[int i] { {|Definition:get|} => base[||][i]; set { base[i] = value; } } +} + +class Usages +{ + void M() + { + IC ic; + var v1 = ic[||][0] + ic[0] = 1 + + C c; + var v1 = c[||][0] + c[0] = 1 + + D d; + var v1 = d[||][0] + d[0] = 1 + } +} + + + + Await TestStreamingFeature(input) + End Function + Public Async Function TestVBAccessor_Get_Feature1() As Task Dim input = diff --git a/src/Features/Core/Portable/ChangeSignature/DelegateInvokeMethodReferenceFinder.cs b/src/Features/Core/Portable/ChangeSignature/DelegateInvokeMethodReferenceFinder.cs index fd77350ba4717f3f116c3526fb6b8de4f5ebe6f7..643f2ec32a7c50213415b01bab30d536064ce541 100644 --- a/src/Features/Core/Portable/ChangeSignature/DelegateInvokeMethodReferenceFinder.cs +++ b/src/Features/Core/Portable/ChangeSignature/DelegateInvokeMethodReferenceFinder.cs @@ -71,7 +71,7 @@ protected override bool CanFind(IMethodSymbol symbol) return Task.FromResult(project.Documents.ToImmutableArray()); } - protected override async Task> FindReferencesInDocumentAsync( + protected override async Task> FindReferencesInDocumentAsync( IMethodSymbol methodSymbol, Document document, SemanticModel semanticModel, @@ -104,7 +104,7 @@ protected override bool CanFind(IMethodSymbol symbol) .Where(e => semanticModel.GetSymbolInfo(e, cancellationToken).Symbol.OriginalDefinition == methodSymbol); var result = invocations.Concat(convertedAnonymousFunctions).Select( - e => new ReferenceLocation(document, null, e.GetLocation(), isImplicit: false, isWrittenTo: false, candidateReason: CandidateReason.None)); + n => (n, new ReferenceLocation(document, null, n.GetLocation(), isImplicit: false, isWrittenTo: false, candidateReason: CandidateReason.None))); return result.ToImmutableArray(); } diff --git a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs index 9b76071defc506a9df8904f11c17ecf92ac915c6..337ac67f650038ac3a283698f2fa2b8fa91160c6 100644 --- a/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs +++ b/src/Workspaces/CSharp/Portable/LanguageServices/CSharpSyntaxFactsService.cs @@ -657,11 +657,12 @@ public SyntaxNode GetExpressionOfMemberAccessExpression(SyntaxNode node, bool al public SyntaxNode GetExpressionOfConditionalAccessExpression(SyntaxNode node) => (node as ConditionalAccessExpressionSyntax)?.Expression; - public SyntaxNode GetExpressionOfElementAccessExpression(SyntaxNode node) - => (node as ElementAccessExpressionSyntax)?.Expression; - - public SyntaxNode GetArgumentListOfElementAccessExpression(SyntaxNode node) - => (node as ElementAccessExpressionSyntax)?.ArgumentList; + public void GetPartsOfElementAccessExpression(SyntaxNode node, out SyntaxNode expression, out SyntaxNode argumentList) + { + var elementAccess = node as ElementAccessExpressionSyntax; + expression = elementAccess?.Expression; + argumentList = elementAccess?.ArgumentList; + } public SyntaxNode GetExpressionOfInterpolation(SyntaxNode node) => (node as InterpolationSyntax)?.Expression; diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_DocumentProcessing.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_DocumentProcessing.cs index ea137e9a551399ccd39a98b99bdc4957ab483863..3ca2357dbf69786350dfc6e48cec3aefdfdb9480 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_DocumentProcessing.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_DocumentProcessing.cs @@ -61,7 +61,7 @@ internal partial class FindReferencesSearchEngine symbolAndProjectId, document, semanticModel, _options, _cancellationToken).ConfigureAwait(false); foreach (var location in references) { - await HandleLocationAsync(symbolAndProjectId, location).ConfigureAwait(false); + await HandleLocationAsync(symbolAndProjectId, location.location).ConfigureAwait(false); } } finally diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMemberScopedReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMemberScopedReferenceFinder.cs index fc99e3cd03806a76b4a5f28e220f63372f43bc42..bdbf18d685a1ae0028736922cd308b737d0e2e5f 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMemberScopedReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMemberScopedReferenceFinder.cs @@ -47,7 +47,7 @@ protected sealed override bool CanFind(TSymbol symbol) return Task.FromResult(ImmutableArray.Create(document)); } - protected override async Task> FindReferencesInDocumentAsync( + protected override async Task> FindReferencesInDocumentAsync( TSymbol symbol, Document document, SemanticModel semanticModel, @@ -71,7 +71,7 @@ protected sealed override bool CanFind(TSymbol symbol) symbol, document, semanticModel, tokens, cancellationToken).ConfigureAwait(false); } - return ImmutableArray.Empty; + return ImmutableArray<(SyntaxNode node, ReferenceLocation location)>.Empty; } private static ISymbol GetContainer(ISymbol symbol) @@ -109,7 +109,7 @@ private static ISymbol GetContainer(ISymbol symbol) return null; } - protected Task> FindReferencesInTokensWithSymbolNameAsync( + protected Task> FindReferencesInTokensWithSymbolNameAsync( TSymbol symbol, Document document, SemanticModel semanticModel, @@ -121,7 +121,7 @@ private static ISymbol GetContainer(ISymbol symbol) findParentNode: null, cancellationToken: cancellationToken); } - protected Task> FindReferencesInTokensWithSymbolNameAsync( + protected Task> FindReferencesInTokensWithSymbolNameAsync( TSymbol symbol, Document document, SemanticModel semanticModel, @@ -142,7 +142,7 @@ private static ISymbol GetContainer(ISymbol symbol) cancellationToken); } - private Task> FindReferencesInContainerAsync( + private Task> FindReferencesInContainerAsync( TSymbol symbol, ISymbol container, Document document, @@ -154,7 +154,7 @@ private static ISymbol GetContainer(ISymbol symbol) findParentNode: null, cancellationToken: cancellationToken); } - private Task> FindReferencesInContainerAsync( + private Task> FindReferencesInContainerAsync( TSymbol symbol, ISymbol container, Document document, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs index 214d92bfd81fbe7b49545980e039331f3317a6e0..4e05153b5b79c0214b36fce6b913d63fd67836e2 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs @@ -59,9 +59,18 @@ protected AbstractMethodOrPropertyOrEventSymbolReferenceFinder() } protected ImmutableArray GetReferencedAccessorSymbols( - ISemanticFactsService semanticFacts, SemanticModel model, - IPropertySymbol property, SyntaxNode node, CancellationToken cancellationToken) + ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, + SemanticModel model, IPropertySymbol property, SyntaxNode node, CancellationToken cancellationToken) { + if (syntaxFacts.IsForEachStatement(node)) + { + var symbols = semanticFacts.GetForEachSymbols(model, node); + + // the only accessor method referenced in a foreach-statement is the .Current's + // get-accessor + return ImmutableArray.Create(symbols.CurrentProperty.GetMethod); + } + if (semanticFacts.IsWrittenTo(model, node, cancellationToken)) { // if it was only written to, then only the setter was referenced. diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs index 811876dc9730be67b17c71022984c7448e723c1e..011960617e04deaa648f8d38a6aeb077def252fa 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs @@ -26,7 +26,7 @@ internal abstract partial class AbstractReferenceFinder : IReferenceFinder public abstract Task> DetermineDocumentsToSearchAsync( ISymbol symbol, Project project, IImmutableSet documents, FindReferencesSearchOptions options, CancellationToken cancellationToken); - public abstract Task> FindReferencesInDocumentAsync( + public abstract Task> FindReferencesInDocumentAsync( SymbolAndProjectId symbolAndProjectId, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken); protected static bool TryGetNameWithoutAttributeSuffix( @@ -130,7 +130,7 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n return syntaxFacts.IsIdentifier(token) && syntaxFacts.TextMatch(token.ValueText, name); } - protected static Task> FindReferencesInDocumentUsingIdentifierAsync( + protected static Task> FindReferencesInDocumentUsingIdentifierAsync( ISymbol symbol, string identifier, Document document, @@ -142,7 +142,7 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n cancellationToken: cancellationToken); } - protected static Task> FindReferencesInDocumentUsingIdentifierAsync( + protected static Task> FindReferencesInDocumentUsingIdentifierAsync( ISymbol symbol, string identifier, Document document, @@ -156,7 +156,7 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n identifier, document, semanticModel, symbolsMatch, cancellationToken); } - protected static async Task> FindReferencesInDocumentUsingIdentifierAsync( + protected static async Task> FindReferencesInDocumentUsingIdentifierAsync( string identifier, Document document, SemanticModel semanticModel, @@ -215,7 +215,7 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n return symbolsMatch; } - protected static async Task> FindReferencesInTokensAsync( + protected static async Task> FindReferencesInTokensAsync( Document document, SemanticModel semanticModel, IEnumerable tokens, @@ -227,7 +227,7 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false); - var locations = ArrayBuilder.GetInstance(); + var locations = ArrayBuilder<(SyntaxNode node, ReferenceLocation location)>.GetInstance(); foreach (var token in tokens) { cancellationToken.ThrowIfCancellationRequested(); @@ -241,9 +241,9 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n var location = token.GetLocation(); var isWrittenTo = semanticFacts.IsWrittenTo(semanticModel, token.Parent, cancellationToken); - locations.Add(new ReferenceLocation( + locations.Add((token.Parent, new ReferenceLocation( document, alias, location, isImplicit: false, - isWrittenTo: isWrittenTo, candidateReason: match.reason)); + isWrittenTo: isWrittenTo, candidateReason: match.reason))); } } } @@ -251,40 +251,32 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n return locations.ToImmutableAndFree(); } - private static async Task GetAliasSymbolAsync( + private static IAliasSymbol GetAliasSymbol( Document document, SemanticModel semanticModel, - ReferenceLocation location, + SyntaxNode node, CancellationToken cancellationToken) { - if (location.Location.IsInSource) + var syntaxFacts = document.GetLanguageService(); + if (syntaxFacts.IsRightSideOfQualifiedName(node)) { - var tree = location.Location.SourceTree; - var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false); - var token = root.FindToken(location.Location.SourceSpan.Start); - var node = token.Parent; - - var syntaxFacts = document.GetLanguageService(); - if (syntaxFacts.IsRightSideOfQualifiedName(node)) - { - node = node.Parent; - } + node = node.Parent; + } - if (syntaxFacts.IsUsingDirectiveName(node)) + if (syntaxFacts.IsUsingDirectiveName(node)) + { + var directive = node.Parent; + if (semanticModel.GetDeclaredSymbol(directive, cancellationToken) is IAliasSymbol aliasSymbol) { - var directive = node.Parent; - if (semanticModel.GetDeclaredSymbol(directive, cancellationToken) is IAliasSymbol aliasSymbol) - { - return aliasSymbol; - } + return aliasSymbol; } } return null; } - protected static Task> FindAliasReferencesAsync( - ImmutableArray nonAliasReferences, + protected static Task> FindAliasReferencesAsync( + ImmutableArray<(SyntaxNode node, ReferenceLocation location)> nonAliasReferences, ISymbol symbol, Document document, SemanticModel semanticModel, @@ -295,50 +287,50 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n findParentNode: null, cancellationToken: cancellationToken); } - protected static async Task> FindAliasReferencesAsync( - ImmutableArray nonAliasReferences, + protected static async Task> FindAliasReferencesAsync( + ImmutableArray<(SyntaxNode node, ReferenceLocation location)> nonAliasReferences, ISymbol symbol, Document document, SemanticModel semanticModel, Func findParentNode, CancellationToken cancellationToken) { - var aliasSymbols = await GetAliasSymbolsAsync(document, semanticModel, nonAliasReferences, cancellationToken).ConfigureAwait(false); + var aliasSymbols = GetAliasSymbols(document, semanticModel, nonAliasReferences, cancellationToken); if (aliasSymbols == null) { - return ImmutableArray.Empty; + return ImmutableArray<(SyntaxNode node, ReferenceLocation location)>.Empty; } return await FindReferencesThroughAliasSymbolsAsync(symbol, document, semanticModel, aliasSymbols, findParentNode, cancellationToken).ConfigureAwait(false); } - protected static async Task> FindAliasReferencesAsync( - ImmutableArray nonAliasReferences, + protected static async Task> FindAliasReferencesAsync( + ImmutableArray<(SyntaxNode node, ReferenceLocation location)> nonAliasReferences, ISymbol symbol, Document document, SemanticModel semanticModel, Func symbolsMatch, CancellationToken cancellationToken) { - var aliasSymbols = await GetAliasSymbolsAsync(document, semanticModel, nonAliasReferences, cancellationToken).ConfigureAwait(false); + var aliasSymbols = GetAliasSymbols(document, semanticModel, nonAliasReferences, cancellationToken); if (aliasSymbols == null) { - return ImmutableArray.Empty; + return ImmutableArray<(SyntaxNode node, ReferenceLocation location)>.Empty; } return await FindReferencesThroughAliasSymbolsAsync(symbol, document, semanticModel, aliasSymbols, symbolsMatch, cancellationToken).ConfigureAwait(false); } - private static async Task> GetAliasSymbolsAsync( + private static ImmutableArray GetAliasSymbols( Document document, SemanticModel semanticModel, - ImmutableArray nonAliasReferences, + ImmutableArray<(SyntaxNode node, ReferenceLocation location)> nonAliasReferences, CancellationToken cancellationToken) { var aliasSymbols = ArrayBuilder.GetInstance(); foreach (var r in nonAliasReferences) { - var symbol = await GetAliasSymbolAsync(document, semanticModel, r, cancellationToken).ConfigureAwait(false); + var symbol = GetAliasSymbol(document, semanticModel, r.node, cancellationToken); if (symbol != null) { aliasSymbols.Add(symbol); @@ -348,7 +340,7 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n return aliasSymbols.ToImmutableAndFree(); } - private static async Task> FindReferencesThroughAliasSymbolsAsync( + private static async Task> FindReferencesThroughAliasSymbolsAsync( ISymbol symbol, Document document, SemanticModel semanticModel, @@ -357,7 +349,7 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n CancellationToken cancellationToken) { var syntaxFactsService = document.GetLanguageService(); - var allAliasReferences = ArrayBuilder.GetInstance(); + var allAliasReferences = ArrayBuilder<(SyntaxNode node, ReferenceLocation location)>.GetInstance(); foreach (var aliasSymbol in aliasSymbols) { var aliasReferences = await FindReferencesInDocumentUsingIdentifierAsync( @@ -376,7 +368,7 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n return allAliasReferences.ToImmutableAndFree(); } - private static async Task> FindReferencesThroughAliasSymbolsAsync( + private static async Task> FindReferencesThroughAliasSymbolsAsync( ISymbol symbol, Document document, SemanticModel semanticModel, @@ -385,7 +377,7 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n CancellationToken cancellationToken) { var syntaxFactsService = document.GetLanguageService(); - var allAliasReferences = ArrayBuilder.GetInstance(); + var allAliasReferences = ArrayBuilder<(SyntaxNode node, ReferenceLocation location)>.GetInstance(); foreach (var aliasSymbol in aliasSymbols) { var aliasReferences = await FindReferencesInDocumentUsingIdentifierAsync(aliasSymbol.Name, document, semanticModel, symbolsMatch, cancellationToken).ConfigureAwait(false); @@ -402,7 +394,7 @@ protected static bool IdentifiersMatch(ISyntaxFactsService syntaxFacts, string n return allAliasReferences.ToImmutableAndFree(); } - private Task> FindDocumentsWithPredicateAsync(Project project, IImmutableSet documents, Func predicate, CancellationToken cancellationToken) + protected Task> FindDocumentsWithPredicateAsync(Project project, IImmutableSet documents, Func predicate, CancellationToken cancellationToken) { return FindDocumentsAsync(project, documents, async (d, c) => { @@ -424,9 +416,9 @@ protected Task> FindDocumentsWithAwaitExpressionAsync(P /// If the `node` implicitly matches the `symbol`, then it will be added to `locations`. /// private delegate void CollectMatchingReferences(ISymbol symbol, SyntaxNode node, - ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, ArrayBuilder locations); + ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, ArrayBuilder<(SyntaxNode node, ReferenceLocation location)> locations); - private async Task> FindReferencesInDocumentAsync( + private async Task> FindReferencesInDocumentAsync( ISymbol symbol, Document document, SemanticModel semanticModel, @@ -441,7 +433,7 @@ protected Task> FindDocumentsWithAwaitExpressionAsync(P var semanticFacts = document.GetLanguageService(); var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); - var locations = ArrayBuilder.GetInstance(); + var locations = ArrayBuilder<(SyntaxNode node, ReferenceLocation location)>.GetInstance(); var originalUnreducedSymbolDefinition = symbol.GetOriginalUnreducedDefinition(); @@ -454,10 +446,10 @@ protected Task> FindDocumentsWithAwaitExpressionAsync(P return locations.ToImmutableAndFree(); } - return ImmutableArray.Empty; + return ImmutableArray<(SyntaxNode node, ReferenceLocation location)>.Empty; } - protected Task> FindReferencesInForEachStatementsAsync( + protected Task> FindReferencesInForEachStatementsAsync( ISymbol symbol, Document document, SemanticModel semanticModel, @@ -469,7 +461,7 @@ bool isRelevantDocument(SyntaxTreeIndex syntaxTreeInfo) => syntaxTreeInfo.ContainsForEachStatement; void collectMatchingReferences(ISymbol originalUnreducedSymbolDefinition, SyntaxNode node, - ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, ArrayBuilder locations) + ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, ArrayBuilder<(SyntaxNode node, ReferenceLocation location)> locations) { var info = semanticFacts.GetForEachSymbols(semanticModel, node); @@ -479,13 +471,13 @@ bool isRelevantDocument(SyntaxTreeIndex syntaxTreeInfo) Matches(info.DisposeMethod, originalUnreducedSymbolDefinition)) { var location = node.GetFirstToken().GetLocation(); - locations.Add(new ReferenceLocation( - document, alias: null, location: location, isImplicit: true, isWrittenTo: false, candidateReason: CandidateReason.None)); + locations.Add((node, new ReferenceLocation( + document, alias: null, location: location, isImplicit: true, isWrittenTo: false, candidateReason: CandidateReason.None))); } } } - protected Task> FindReferencesInDeconstructionAsync( + protected Task> FindReferencesInDeconstructionAsync( ISymbol symbol, Document document, SemanticModel semanticModel, @@ -497,7 +489,7 @@ bool isRelevantDocument(SyntaxTreeIndex syntaxTreeInfo) => syntaxTreeInfo.ContainsDeconstruction; void collectMatchingReferences(ISymbol originalUnreducedSymbolDefinition, SyntaxNode node, - ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, ArrayBuilder locations) + ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, ArrayBuilder<(SyntaxNode node, ReferenceLocation location)> locations) { var deconstructMethods = semanticFacts.GetDeconstructionAssignmentMethods(semanticModel, node); if (deconstructMethods.IsEmpty) @@ -509,13 +501,13 @@ bool isRelevantDocument(SyntaxTreeIndex syntaxTreeInfo) if (deconstructMethods.Any(m => Matches(m, originalUnreducedSymbolDefinition))) { var location = syntaxFacts.GetDeconstructionReferenceLocation(node); - locations.Add(new ReferenceLocation( - document, alias: null, location, isImplicit: true, isWrittenTo: false, CandidateReason.None)); + locations.Add((node, new ReferenceLocation( + document, alias: null, location, isImplicit: true, isWrittenTo: false, CandidateReason.None))); } } } - protected Task> FindReferencesInAwaitExpressionAsync( + protected Task> FindReferencesInAwaitExpressionAsync( ISymbol symbol, Document document, SemanticModel semanticModel, @@ -527,15 +519,15 @@ bool isRelevantDocument(SyntaxTreeIndex syntaxTreeInfo) => syntaxTreeInfo.ContainsAwait; void collectMatchingReferences(ISymbol originalUnreducedSymbolDefinition, SyntaxNode node, - ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, ArrayBuilder locations) + ISyntaxFactsService syntaxFacts, ISemanticFactsService semanticFacts, ArrayBuilder<(SyntaxNode node, ReferenceLocation location)> locations) { var awaitExpressionMethod = semanticFacts.GetGetAwaiterMethod(semanticModel, node); if (Matches(awaitExpressionMethod, originalUnreducedSymbolDefinition)) { var location = node.GetFirstToken().GetLocation(); - locations.Add(new ReferenceLocation( - document, alias: null, location, isImplicit: true, isWrittenTo: false, CandidateReason.None)); + locations.Add((node, new ReferenceLocation( + document, alias: null, location, isImplicit: true, isWrittenTo: false, CandidateReason.None))); } } } @@ -557,7 +549,7 @@ internal abstract partial class AbstractReferenceFinder : AbstractRefer TSymbol symbol, Project project, IImmutableSet documents, FindReferencesSearchOptions options, CancellationToken cancellationToken); - protected abstract Task> FindReferencesInDocumentAsync( + protected abstract Task> FindReferencesInDocumentAsync( TSymbol symbol, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken); @@ -577,14 +569,14 @@ public override Task> DetermineProjectsToSearchAsync(ISy : SpecializedTasks.EmptyImmutableArray(); } - public override Task> FindReferencesInDocumentAsync( + public override Task> FindReferencesInDocumentAsync( SymbolAndProjectId symbolAndProjectId, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken) { var symbol = symbolAndProjectId.Symbol; return symbol is TSymbol && CanFind((TSymbol)symbol) ? FindReferencesInDocumentAsync((TSymbol)symbol, document, semanticModel, options, cancellationToken) - : SpecializedTasks.EmptyImmutableArray(); + : SpecializedTasks.EmptyImmutableArray<(SyntaxNode node, ReferenceLocation location)>(); } public override Task> DetermineCascadedSymbolsAsync( @@ -616,7 +608,7 @@ public override Task> DetermineProjectsToSearchAsync(ISy return SpecializedTasks.EmptyImmutableArray(); } - protected static Task> FindReferencesInDocumentUsingSymbolNameAsync( + protected static Task> FindReferencesInDocumentUsingSymbolNameAsync( TSymbol symbol, Document document, SemanticModel semanticModel, @@ -626,7 +618,7 @@ public override Task> DetermineProjectsToSearchAsync(ISy symbol, symbol.Name, document, semanticModel, cancellationToken: cancellationToken); } - protected Task> FindReferencesInTokensAsync( + protected Task> FindReferencesInTokensAsync( TSymbol symbol, Document document, SemanticModel semanticModel, @@ -639,7 +631,7 @@ public override Task> DetermineProjectsToSearchAsync(ISy findParentNode: null, cancellationToken: cancellationToken); } - protected Task> FindReferencesInTokensAsync( + protected Task> FindReferencesInTokensAsync( TSymbol symbol, Document document, SemanticModel semanticModel, @@ -659,7 +651,7 @@ public override Task> DetermineProjectsToSearchAsync(ISy cancellationToken); } - protected static Task> FindReferencesInDocumentAsync( + protected static Task> FindReferencesInDocumentAsync( TSymbol symbol, Document document, SemanticModel semanticModel, @@ -671,7 +663,7 @@ public override Task> DetermineProjectsToSearchAsync(ISy findParentNode: null, cancellationToken: cancellationToken); } - protected static Task> FindReferencesInDocumentAsync( + protected static Task> FindReferencesInDocumentAsync( TSymbol symbol, Document document, SemanticModel semanticModel, @@ -683,7 +675,7 @@ public override Task> DetermineProjectsToSearchAsync(ISy return FindReferencesInDocumentAsync(symbol, document, semanticModel, tokensMatch, symbolsMatch, cancellationToken); } - protected static async Task> FindReferencesInDocumentAsync( + protected static async Task> FindReferencesInDocumentAsync( TSymbol symbol, Document document, SemanticModel semanticModel, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ConstructorInitializerSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ConstructorInitializerSymbolReferenceFinder.cs index cad205ad77edc52c43071b246e69f6498187dc76..6f8e307128ce4ae352bc2b2ed67a0c4d318783a1 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ConstructorInitializerSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ConstructorInitializerSymbolReferenceFinder.cs @@ -49,7 +49,7 @@ protected override bool CanFind(IMethodSymbol symbol) }, cancellationToken); } - protected override async Task> FindReferencesInDocumentAsync( + protected override async Task> FindReferencesInDocumentAsync( IMethodSymbol methodSymbol, Document document, SemanticModel semanticModel, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ConstructorSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ConstructorSymbolReferenceFinder.cs index d9c620790d6f0a8bd9f3353b902b3ad4a791b395..f39f80680d0425b12295b69d4727fdf319875dcb 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ConstructorSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ConstructorSymbolReferenceFinder.cs @@ -55,7 +55,7 @@ protected override bool CanFind(IMethodSymbol symbol) predefinedType == actualType; } - protected override Task> FindReferencesInDocumentAsync( + protected override Task> FindReferencesInDocumentAsync( IMethodSymbol methodSymbol, Document document, SemanticModel semanticModel, @@ -65,7 +65,7 @@ protected override bool CanFind(IMethodSymbol symbol) return FindAllReferencesInDocumentAsync(methodSymbol, document, semanticModel, cancellationToken); } - internal async Task> FindAllReferencesInDocumentAsync( + internal async Task> FindAllReferencesInDocumentAsync( IMethodSymbol methodSymbol, Document document, SemanticModel semanticModel, @@ -87,7 +87,7 @@ protected override bool CanFind(IMethodSymbol symbol) return t => syntaxFacts.GetBindableParent(t); } - private async Task> FindReferencesInDocumentWorkerAsync( + private async Task> FindReferencesInDocumentWorkerAsync( IMethodSymbol symbol, Document document, SemanticModel semanticModel, @@ -101,7 +101,7 @@ protected override bool CanFind(IMethodSymbol symbol) return ordinaryRefs.Concat(attributeRefs).Concat(predefinedTypeRefs); } - private Task> FindOrdinaryReferencesAsync( + private Task> FindOrdinaryReferencesAsync( IMethodSymbol symbol, Document document, SemanticModel semanticModel, @@ -113,7 +113,7 @@ protected override bool CanFind(IMethodSymbol symbol) symbol, name, document, semanticModel, findParentNode, cancellationToken); } - private Task> FindPredefinedTypeReferencesAsync( + private Task> FindPredefinedTypeReferencesAsync( IMethodSymbol symbol, Document document, SemanticModel semanticModel, @@ -122,7 +122,7 @@ protected override bool CanFind(IMethodSymbol symbol) var predefinedType = symbol.ContainingType.SpecialType.ToPredefinedType(); if (predefinedType == PredefinedType.None) { - return SpecializedTasks.EmptyImmutableArray(); + return SpecializedTasks.EmptyImmutableArray<(SyntaxNode node, ReferenceLocation location)>(); } var syntaxFacts = document.GetLanguageService(); @@ -132,7 +132,7 @@ protected override bool CanFind(IMethodSymbol symbol) cancellationToken); } - private Task> FindAttributeReferencesAsync( + private Task> FindAttributeReferencesAsync( IMethodSymbol symbol, Document document, SemanticModel semanticModel, @@ -141,7 +141,7 @@ protected override bool CanFind(IMethodSymbol symbol) var syntaxFacts = document.GetLanguageService(); return TryGetNameWithoutAttributeSuffix(symbol.ContainingType.Name, syntaxFacts, out var simpleName) ? FindReferencesInDocumentUsingIdentifierAsync(symbol, simpleName, document, semanticModel, cancellationToken) - : SpecializedTasks.EmptyImmutableArray(); + : SpecializedTasks.EmptyImmutableArray<(SyntaxNode node, ReferenceLocation location)>(); } } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/DestructorSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/DestructorSymbolReferenceFinder.cs index 4bc092e018fcccbcdb43d82daf48148c7097f2e2..6c128a066abcf0d276eb6fdc3f19aee03d24bac6 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/DestructorSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/DestructorSymbolReferenceFinder.cs @@ -34,14 +34,14 @@ protected override bool CanFind(IMethodSymbol symbol) return SpecializedTasks.EmptyImmutableArray(); } - protected override Task> FindReferencesInDocumentAsync( + protected override Task> FindReferencesInDocumentAsync( IMethodSymbol methodSymbol, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken) { - return SpecializedTasks.EmptyImmutableArray(); + return SpecializedTasks.EmptyImmutableArray<(SyntaxNode node, ReferenceLocation location)>(); } } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/EventSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/EventSymbolReferenceFinder.cs index eeda3c191eb3e40c4f1e984e1748bddc3bb2dd91..93c409991a1325579d7e9facc2019338afe624ce 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/EventSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/EventSymbolReferenceFinder.cs @@ -53,7 +53,7 @@ protected override bool CanFind(IEventSymbol symbol) return FindDocumentsAsync(project, documents, cancellationToken, symbol.Name); } - protected override Task> FindReferencesInDocumentAsync( + protected override Task> FindReferencesInDocumentAsync( IEventSymbol symbol, Document document, SemanticModel semanticModel, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ExplicitInterfaceMethodReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ExplicitInterfaceMethodReferenceFinder.cs index 7c2569f8306c2f672e223763939978a74a133d68..e92427a17c461d6b7add6212fcb6e86bed1df902 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ExplicitInterfaceMethodReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ExplicitInterfaceMethodReferenceFinder.cs @@ -40,7 +40,7 @@ protected override bool CanFind(IMethodSymbol symbol) return SpecializedTasks.EmptyImmutableArray(); } - protected override Task> FindReferencesInDocumentAsync( + protected override Task> FindReferencesInDocumentAsync( IMethodSymbol symbol, Document document, SemanticModel semanticModel, @@ -48,7 +48,7 @@ protected override bool CanFind(IMethodSymbol symbol) CancellationToken cancellationToken) { // An explicit method can't be referenced anywhere. - return SpecializedTasks.EmptyImmutableArray(); + return SpecializedTasks.EmptyImmutableArray<(SyntaxNode node, ReferenceLocation location)>(); } } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/FieldSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/FieldSymbolReferenceFinder.cs index 9fed377ad2ee9dce5b0df409dd2d3dfc6ddbb224..17cd76b81477828c84c2097ebce7c767486226a1 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/FieldSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/FieldSymbolReferenceFinder.cs @@ -43,7 +43,7 @@ protected override bool CanFind(IFieldSymbol symbol) return FindDocumentsAsync(project, documents, cancellationToken, symbol.Name); } - protected override Task> FindReferencesInDocumentAsync( + protected override Task> FindReferencesInDocumentAsync( IFieldSymbol symbol, Document document, SemanticModel semanticModel, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/IReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/IReferenceFinder.cs index fea9dfda9285b8783e32c1041ceeaf75d1eedc29..16ed72b7b04ce9a234ca5e8a55fed66a6174862e 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/IReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/IReferenceFinder.cs @@ -66,7 +66,7 @@ internal interface IReferenceFinder /// /// Implementations of this method must be thread-safe. /// - Task> FindReferencesInDocumentAsync( + Task> FindReferencesInDocumentAsync( SymbolAndProjectId symbolAndProjectId, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken); } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/LinkedFileReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/LinkedFileReferenceFinder.cs index ce8cc9ec19e9ea5c8a1fc955a2c9cc6f85ff1e17..dc3b7e3852e7900a24b5245110f3ed89c20b18fa 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/LinkedFileReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/LinkedFileReferenceFinder.cs @@ -75,11 +75,11 @@ public Task> DetermineProjectsToSearchAsync(ISymbol symb return SpecializedTasks.EmptyImmutableArray(); } - public Task> FindReferencesInDocumentAsync( + public Task> FindReferencesInDocumentAsync( SymbolAndProjectId symbolAndProjectId, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken) { - return SpecializedTasks.EmptyImmutableArray(); + return SpecializedTasks.EmptyImmutableArray<(SyntaxNode node, ReferenceLocation location)>(); } } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/MethodTypeParameterSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/MethodTypeParameterSymbolReferenceFinder.cs index 22b68f320b0bffb709fcd8af79dd669805766c23..ac26b35e27e1166ef7f2bc3c88c6693c4d5aa8d4 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/MethodTypeParameterSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/MethodTypeParameterSymbolReferenceFinder.cs @@ -74,7 +74,7 @@ private static string GetMemberNameWithoutInterfaceName(string fullName) : fullName; } - protected override Task> FindReferencesInDocumentAsync( + protected override Task> FindReferencesInDocumentAsync( ITypeParameterSymbol symbol, Document document, SemanticModel semanticModel, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamedTypeSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamedTypeSymbolReferenceFinder.cs index 09e87c18307f91830227f7615e28ba5ab7205322..2a2f407fd22936e20d6ee8f2fb53f98b4703f7f6 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamedTypeSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamedTypeSymbolReferenceFinder.cs @@ -79,29 +79,29 @@ protected override bool CanFind(INamedTypeSymbol symbol) predefinedType == actualType; } - protected override async Task> FindReferencesInDocumentAsync( + protected override async Task> FindReferencesInDocumentAsync( INamedTypeSymbol namedType, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken) { - var namedTypereferences = await FindReferencesInDocumentWorker( + var namedTypeReferences = await FindReferencesInDocumentWorker( namedType, document, semanticModel, cancellationToken).ConfigureAwait(false); // Mark any references that are also Constructor references. Some callers // will want to know about these so they won't display duplicates. return await MarkConstructorReferences( - namedType, document, semanticModel, namedTypereferences, cancellationToken).ConfigureAwait(false); + namedType, document, semanticModel, namedTypeReferences, cancellationToken).ConfigureAwait(false); } - private async Task> MarkConstructorReferences( + private async Task> MarkConstructorReferences( INamedTypeSymbol namedType, Document document, SemanticModel semanticModel, - ImmutableArray namedTypereferences, + ImmutableArray<(SyntaxNode node, ReferenceLocation location)> namedTypeReferences, CancellationToken cancellationToken) { - var constructorReferences = ArrayBuilder.GetInstance(); + var constructorReferences = ArrayBuilder<(SyntaxNode node, ReferenceLocation location)>.GetInstance(); foreach (var constructor in namedType.Constructors) { var references = await ConstructorSymbolReferenceFinder.Instance.FindAllReferencesInDocumentAsync( @@ -109,13 +109,13 @@ protected override bool CanFind(INamedTypeSymbol symbol) constructorReferences.AddRange(references); } - var result = ArrayBuilder.GetInstance(); - foreach (var reference in namedTypereferences) + var result = ArrayBuilder<(SyntaxNode node, ReferenceLocation location)>.GetInstance(); + foreach (var reference in namedTypeReferences) { if (Contains(constructorReferences, reference)) { var localReference = reference; - localReference.IsDuplicateReferenceLocation = true; + localReference.location.IsDuplicateReferenceLocation = true; result.Add(localReference); } else @@ -128,12 +128,12 @@ protected override bool CanFind(INamedTypeSymbol symbol) } private bool Contains( - ArrayBuilder constructorReferences, - ReferenceLocation reference) + ArrayBuilder<(SyntaxNode node, ReferenceLocation location)> constructorReferences, + (SyntaxNode node, ReferenceLocation location) reference) { foreach (var constructorRef in constructorReferences) { - if (reference.Location == constructorRef.Location) + if (reference.location.Location == constructorRef.location.Location) { return true; } @@ -142,7 +142,7 @@ protected override bool CanFind(INamedTypeSymbol symbol) return false; } - private static async Task> FindReferencesInDocumentWorker( + private static async Task> FindReferencesInDocumentWorker( INamedTypeSymbol namedType, Document document, SemanticModel semanticModel, @@ -154,7 +154,7 @@ protected override bool CanFind(INamedTypeSymbol symbol) return nonAliasReferences.Concat(aliasReferences); } - internal static async Task> FindNonAliasReferencesAsync( + internal static async Task> FindNonAliasReferencesAsync( INamedTypeSymbol symbol, Document document, SemanticModel semanticModel, @@ -166,7 +166,7 @@ protected override bool CanFind(INamedTypeSymbol symbol) return ordinaryRefs.Concat(attributeRefs).Concat(predefinedTypeRefs); } - private static Task> FindOrdinaryReferencesAsync( + private static Task> FindOrdinaryReferencesAsync( INamedTypeSymbol namedType, Document document, SemanticModel semanticModel, @@ -178,7 +178,7 @@ protected override bool CanFind(INamedTypeSymbol symbol) namedType.Name, document, semanticModel, symbolsMatch, cancellationToken); } - private static Task> FindPredefinedTypeReferencesAsync( + private static Task> FindPredefinedTypeReferencesAsync( INamedTypeSymbol symbol, Document document, SemanticModel semanticModel, @@ -187,7 +187,7 @@ protected override bool CanFind(INamedTypeSymbol symbol) var predefinedType = symbol.SpecialType.ToPredefinedType(); if (predefinedType == PredefinedType.None) { - return SpecializedTasks.EmptyImmutableArray(); + return SpecializedTasks.EmptyImmutableArray<(SyntaxNode node, ReferenceLocation location)>(); } var syntaxFacts = document.GetLanguageService(); @@ -197,7 +197,7 @@ protected override bool CanFind(INamedTypeSymbol symbol) cancellationToken); } - private static Task> FindAttributeReferencesAsync( + private static Task> FindAttributeReferencesAsync( INamedTypeSymbol namedType, Document document, SemanticModel semanticModel, @@ -207,7 +207,7 @@ protected override bool CanFind(INamedTypeSymbol symbol) var syntaxFacts = document.GetLanguageService(); return TryGetNameWithoutAttributeSuffix(namedType.Name, syntaxFacts, out var simpleName) ? FindReferencesInDocumentUsingIdentifierAsync(simpleName, document, semanticModel, symbolsMatch, cancellationToken) - : SpecializedTasks.EmptyImmutableArray(); + : SpecializedTasks.EmptyImmutableArray<(SyntaxNode node, ReferenceLocation location)>(); } } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamespaceSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamespaceSymbolReferenceFinder.cs index bba734009296f83529aca50e04cc7aa9e0107a6a..cb4c5204f1d824628896e5d092f1ba915b7e69cf 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamespaceSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamespaceSymbolReferenceFinder.cs @@ -37,7 +37,7 @@ private static string GetNamespaceIdentifierName(INamespaceSymbol symbol, Projec : symbol.Name; } - protected override async Task> FindReferencesInDocumentAsync( + protected override async Task> FindReferencesInDocumentAsync( INamespaceSymbol symbol, Document document, SemanticModel semanticModel, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OperatorSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OperatorSymbolReferenceFinder.cs index 2b6bb51baec4304b0eb630262bf78d7ec87e50ce..4fa3782f94227fcf14717dfd4faca853e93d53d2 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OperatorSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OperatorSymbolReferenceFinder.cs @@ -27,7 +27,7 @@ protected override bool CanFind(IMethodSymbol symbol) return FindDocumentsAsync(project, documents, op, cancellationToken); } - protected override Task> FindReferencesInDocumentAsync( + protected override Task> FindReferencesInDocumentAsync( IMethodSymbol symbol, Document document, SemanticModel semanticModel, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OrdinaryMethodReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OrdinaryMethodReferenceFinder.cs index b1fcb6184aea7ae8030952e6882d8d1aa50ee4b3..79579f4ad9f53d6674142e544c348b6ad51d62e6 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OrdinaryMethodReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OrdinaryMethodReferenceFinder.cs @@ -120,7 +120,7 @@ private bool IsDeconstructMethod(IMethodSymbol methodSymbol) private bool IsGetAwaiterMethod(IMethodSymbol methodSymbol) => methodSymbol.Name == WellKnownMemberNames.GetAwaiter; - protected override async Task> FindReferencesInDocumentAsync( + protected override async Task> FindReferencesInDocumentAsync( IMethodSymbol symbol, Document document, SemanticModel semanticModel, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ParameterSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ParameterSymbolReferenceFinder.cs index 33044987bed9cea64647a99b1126af32344d1fbb..d2ca81fda24b752c380acc522bd271258b2d34f4 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ParameterSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ParameterSymbolReferenceFinder.cs @@ -35,7 +35,7 @@ protected override bool CanFind(IParameterSymbol symbol) return FindDocumentsAsync(project, documents, cancellationToken, symbol.Name); } - protected override Task> FindReferencesInDocumentAsync( + protected override Task> FindReferencesInDocumentAsync( IParameterSymbol symbol, Document document, SemanticModel semanticModel, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertyAccessorSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertyAccessorSymbolReferenceFinder.cs index 327cbc23dbb83d26021e683e81a2778a741f4482..2fbb334dba3fd492a11e908fbdab8ff739a2f54f 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertyAccessorSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertyAccessorSymbolReferenceFinder.cs @@ -44,20 +44,28 @@ protected override bool CanFind(IMethodSymbol symbol) var result = await FindDocumentsAsync( project, documents, cancellationToken, symbol.Name).ConfigureAwait(false); - if (options.AssociatePropertyReferencesWithSpecificAccessor) + if (symbol.AssociatedSymbol is IPropertySymbol property && + options.AssociatePropertyReferencesWithSpecificAccessor) { // we want to associate normal property references with the specific // accessor being referenced. So we also need to include documents // with our property's name. - var propDocuments = await FindDocumentsAsync( - project, documents, cancellationToken, symbol.AssociatedSymbol.Name).ConfigureAwait(false); - result = result.AddRange(propDocuments); + result = await ReferenceFinders.Property.DetermineDocumentsToSearchAsync( + property, project, documents, + options.WithAssociatePropertyReferencesWithSpecificAccessor(false), + cancellationToken).ConfigureAwait(false); } return result; } - protected override async Task> FindReferencesInDocumentAsync( + private Task> FindDocumentWithElementAccessExpressionsAsync( + Project project, IImmutableSet documents, CancellationToken cancellationToken) + { + return FindDocumentsWithPredicateAsync(project, documents, info => info.ContainsElementAccessExpression, cancellationToken); + } + + protected override async Task> FindReferencesInDocumentAsync( IMethodSymbol symbol, Document document, SemanticModel semanticModel, FindReferencesSearchOptions options, CancellationToken cancellationToken) { @@ -67,19 +75,19 @@ protected override bool CanFind(IMethodSymbol symbol) if (symbol.AssociatedSymbol is IPropertySymbol property && options.AssociatePropertyReferencesWithSpecificAccessor) { - var propertyReferences = await ReferenceFinders.Property.FindReferencesInDocumentAsync( - SymbolAndProjectId.Create(property, document.Project.Id), - document, semanticModel, options.WithAssociatePropertyReferencesWithSpecificAccessor(false), + var propertyReferences = await PropertySymbolReferenceFinder.Instance.FindAllReferencesInDocumentAsync( + property, document, semanticModel, + options.WithAssociatePropertyReferencesWithSpecificAccessor(false), cancellationToken).ConfigureAwait(false); + var syntaxFacts = document.GetLanguageService(); var semanticFacts = document.GetLanguageService(); + var accessorReferences = propertyReferences.WhereAsArray( loc => { var accessors = GetReferencedAccessorSymbols( - semanticFacts, semanticModel, property, - loc.Location.FindNode(getInnermostNodeForTie: true, cancellationToken), - cancellationToken); + syntaxFacts, semanticFacts, semanticModel, property, loc.node, cancellationToken); return accessors.Contains(symbol); }); diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertySymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertySymbolReferenceFinder.cs index a93df3a59551adfc4196a4b141bedc603127a639..684a31024654cb9168c9dcb54bcdd7d556a8b2cc 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertySymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertySymbolReferenceFinder.cs @@ -15,6 +15,12 @@ namespace Microsoft.CodeAnalysis.FindSymbols.Finders { internal class PropertySymbolReferenceFinder : AbstractMethodOrPropertyOrEventSymbolReferenceFinder { + public static readonly PropertySymbolReferenceFinder Instance = new PropertySymbolReferenceFinder(); + + private PropertySymbolReferenceFinder() + { + } + protected override bool CanFind(IPropertySymbol symbol) { return true; @@ -83,12 +89,16 @@ private static bool IsForEachProperty(IPropertySymbol symbol) return symbol.Name == WellKnownMemberNames.CurrentPropertyName; } - protected override async Task> FindReferencesInDocumentAsync( - IPropertySymbol symbol, - Document document, - SemanticModel semanticModel, - FindReferencesSearchOptions options, - CancellationToken cancellationToken) + protected override Task> FindReferencesInDocumentAsync( + IPropertySymbol symbol, Document document, SemanticModel semanticModel, + FindReferencesSearchOptions options, CancellationToken cancellationToken) + { + return FindAllReferencesInDocumentAsync(symbol, document, semanticModel, options, cancellationToken); + } + + internal async Task> FindAllReferencesInDocumentAsync( + IPropertySymbol symbol, Document document, SemanticModel semanticModel, + FindReferencesSearchOptions options, CancellationToken cancellationToken) { var nameReferences = await FindReferencesInDocumentUsingSymbolNameAsync( symbol, document, semanticModel, cancellationToken).ConfigureAwait(false); @@ -98,101 +108,121 @@ private static bool IsForEachProperty(IPropertySymbol symbol) // We want to associate property references to a specific accessor (if an accessor // is being referenced). Check if this reference would match an accessor. If so, do // not add it. It will be added by PropertyAccessorSymbolReferenceFinder. + var syntaxFacts = document.GetLanguageService(); var semanticFacts = document.GetLanguageService(); nameReferences = nameReferences.WhereAsArray(loc => { var accessors = GetReferencedAccessorSymbols( - semanticFacts, semanticModel, symbol, - loc.Location.FindNode(getInnermostNodeForTie: true, cancellationToken), - cancellationToken); + syntaxFacts, semanticFacts, semanticModel, symbol, loc.node, cancellationToken); return accessors.Length == 0; }); } var forEachReferences = IsForEachProperty(symbol) ? await FindReferencesInForEachStatementsAsync(symbol, document, semanticModel, cancellationToken).ConfigureAwait(false) - : ImmutableArray.Empty; + : ImmutableArray<(SyntaxNode, ReferenceLocation)>.Empty; var elementAccessReferences = symbol.IsIndexer - ? await FindElementAccessReferencesAndIndexerMemberCrefReferencesAsync(symbol, document, semanticModel, cancellationToken).ConfigureAwait(false) - : ImmutableArray.Empty; + ? await FindElementAccessReferencesAsync(symbol, document, semanticModel, options, cancellationToken).ConfigureAwait(false) + : ImmutableArray<(SyntaxNode, ReferenceLocation)>.Empty; + + var indexerCrefReferences = symbol.IsIndexer + ? await FindIndexerCrefReferencesAsync(symbol, document, semanticModel, options, cancellationToken) + : ImmutableArray<(SyntaxNode, ReferenceLocation)>.Empty; return nameReferences.Concat(forEachReferences) - .Concat(elementAccessReferences); + .Concat(elementAccessReferences) + .Concat(indexerCrefReferences); } private Task> FindDocumentWithElementAccessExpressionsAsync( Project project, IImmutableSet documents, CancellationToken cancellationToken) { - return FindDocumentsAsync(project, documents, async (d, c) => - { - var info = await SyntaxTreeIndex.GetIndexAsync(d, c).ConfigureAwait(false); - return info.ContainsElementAccessExpression; - }, cancellationToken); + return FindDocumentsWithPredicateAsync(project, documents, info => info.ContainsElementAccessExpression, cancellationToken); } private Task> FindDocumentWithIndexerMemberCrefAsync( Project project, IImmutableSet documents, CancellationToken cancellationToken) { - return FindDocumentsAsync(project, documents, async (d, c) => - { - var info = await SyntaxTreeIndex.GetIndexAsync(d, c).ConfigureAwait(false); - return info.ContainsIndexerMemberCref; - }, cancellationToken); + return FindDocumentsWithPredicateAsync(project, documents, info => info.ContainsIndexerMemberCref, cancellationToken); } - private async Task> FindElementAccessReferencesAndIndexerMemberCrefReferencesAsync( - IPropertySymbol symbol, - Document document, - SemanticModel semanticModel, - CancellationToken cancellationToken) + private async Task> FindElementAccessReferencesAsync( + IPropertySymbol symbol, Document document, SemanticModel semanticModel, + FindReferencesSearchOptions options, CancellationToken cancellationToken) { + if (options.AssociatePropertyReferencesWithSpecificAccessor) + { + // Looking for individual get/set references. Don't find anything here. + // these results will be provided by the PropertyAccessorSymbolReferenceFinder + return ImmutableArray<(SyntaxNode, ReferenceLocation)>.Empty; + } + var symbolsMatch = GetStandardSymbolsNodeMatchFunction(symbol, document.Project.Solution, cancellationToken); var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var syntaxFacts = document.GetLanguageService(); - // Now that we have Doc Comments in place, We are searching for References in the Trivia as well by setting descendIntoTrivia: true var elementAccessExpressions = syntaxRoot.DescendantNodes().Where(syntaxFacts.IsElementAccessExpression); - var indexerMemberCref = syntaxRoot.DescendantNodes(descendIntoTrivia: true).Where(syntaxFacts.IsIndexerMemberCRef); - - var elementAccessExpressionsAndIndexerMemberCref = elementAccessExpressions.Concat(indexerMemberCref); + var locations = ArrayBuilder<(SyntaxNode, ReferenceLocation)>.GetInstance(); - var locations = ArrayBuilder.GetInstance(); - - foreach (var node in elementAccessExpressionsAndIndexerMemberCref) + foreach (var node in elementAccessExpressions) { cancellationToken.ThrowIfCancellationRequested(); - var match = symbolsMatch(node, semanticModel); - if (match.matched) + var (matched, reason) = symbolsMatch(node, semanticModel); + if (matched) { - SyntaxNode nodeToBeReferenced = null; + syntaxFacts.GetPartsOfElementAccessExpression(node, out var expression, out var argumentList); - if (syntaxFacts.IsIndexerMemberCRef(node)) + if (symbolsMatch(expression, semanticModel).matched) { - nodeToBeReferenced = node; - } - else - { - var childNodes = node.ChildNodes(); - var leftOfInvocation = childNodes.First(); - if (symbolsMatch(leftOfInvocation, semanticModel).matched) - { - // Element access with explicit member name (allowed in VB). - // We have already added a reference location for the member name identifier, so skip this one. - continue; - } - - nodeToBeReferenced = childNodes.Skip(1).FirstOrDefault(); + // Element access with explicit member name (allowed in VB). + // We have already added a reference location for the member name identifier, so skip this one. + continue; } - if (nodeToBeReferenced != null) - { - var location = nodeToBeReferenced.SyntaxTree.GetLocation(new TextSpan(nodeToBeReferenced.SpanStart, 0)); - locations.Add(new ReferenceLocation(document, null, location, isImplicit: false, isWrittenTo: false, candidateReason: match.reason)); - } + var location = argumentList.SyntaxTree.GetLocation(new TextSpan(argumentList.SpanStart, 0)); + locations.Add( + (node, new ReferenceLocation(document, null, location, isImplicit: false, isWrittenTo: false, candidateReason: reason))); + } + } + + return locations.ToImmutableAndFree(); + } + + private async Task> FindIndexerCrefReferencesAsync( + IPropertySymbol symbol, Document document, SemanticModel semanticModel, + FindReferencesSearchOptions options, CancellationToken cancellationToken) + { + if (options.AssociatePropertyReferencesWithSpecificAccessor) + { + // can't find indexer get/set accessors in a cref. + return ImmutableArray<(SyntaxNode, ReferenceLocation)>.Empty; + } + + var symbolsMatch = GetStandardSymbolsNodeMatchFunction(symbol, document.Project.Solution, cancellationToken); + + var syntaxRoot = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); + var syntaxFacts = document.GetLanguageService(); + + // Now that we have Doc Comments in place, We are searching for References in the Trivia as well by setting descendIntoTrivia: true + var indexerMemberCrefs = syntaxRoot.DescendantNodes(descendIntoTrivia: true) + .Where(syntaxFacts.IsIndexerMemberCRef); + + var locations = ArrayBuilder<(SyntaxNode, ReferenceLocation)>.GetInstance(); + + foreach (var node in indexerMemberCrefs) + { + cancellationToken.ThrowIfCancellationRequested(); + + var match = symbolsMatch(node, semanticModel); + if (match.matched) + { + var location = node.SyntaxTree.GetLocation(new TextSpan(node.SpanStart, 0)); + locations.Add( + (node, new ReferenceLocation(document, null, location, isImplicit: false, isWrittenTo: false, candidateReason: match.reason))); } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ReferenceFinders.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ReferenceFinders.cs index 2e33b57b7ed4303a002d1cf21be09fc5fdd08165..eaf2560f8ec2838375d8aabc843519f3f7839b03 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ReferenceFinders.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ReferenceFinders.cs @@ -21,7 +21,7 @@ internal static class ReferenceFinders public static readonly IReferenceFinder Operator = new OperatorSymbolReferenceFinder(); public static readonly IReferenceFinder OrdinaryMethod = new OrdinaryMethodReferenceFinder(); public static readonly IReferenceFinder Parameter = new ParameterSymbolReferenceFinder(); - public static readonly IReferenceFinder Property = new PropertySymbolReferenceFinder(); + public static readonly IReferenceFinder Property = PropertySymbolReferenceFinder.Instance; public static readonly IReferenceFinder PropertyAccessor = new PropertyAccessorSymbolReferenceFinder(); public static readonly IReferenceFinder RangeVariable = new RangeVariableSymbolReferenceFinder(); public static readonly IReferenceFinder TypeParameter = new TypeParameterSymbolReferenceFinder(); diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/TypeParameterSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/TypeParameterSymbolReferenceFinder.cs index 9c04256a30d19d1888bd5430df8828f4db3e5f10..2432dffe4c00e2f43171f705f8add1929e9e8444 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/TypeParameterSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/TypeParameterSymbolReferenceFinder.cs @@ -31,7 +31,7 @@ protected override bool CanFind(ITypeParameterSymbol symbol) return FindDocumentsAsync(project, documents, cancellationToken, symbol.Name, symbol.ContainingType.Name); } - protected override Task> FindReferencesInDocumentAsync( + protected override Task> FindReferencesInDocumentAsync( ITypeParameterSymbol symbol, Document document, SemanticModel semanticModel, diff --git a/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs b/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs index 4c896fddd72b69d056f5184cc51de9de1b6ba131..2587c89cb3b94ec9763ca1b7abb2f73c5e52d310 100644 --- a/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs +++ b/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsService.cs @@ -165,8 +165,7 @@ internal interface ISyntaxFactsService : ILanguageService SyntaxNode GetExpressionOfConditionalAccessExpression(SyntaxNode node); - SyntaxNode GetExpressionOfElementAccessExpression(SyntaxNode node); - SyntaxNode GetArgumentListOfElementAccessExpression(SyntaxNode node); + void GetPartsOfElementAccessExpression(SyntaxNode node, out SyntaxNode expression, out SyntaxNode argumentList); SyntaxNode GetExpressionOfArgument(SyntaxNode node); SyntaxNode GetExpressionOfInterpolation(SyntaxNode node); diff --git a/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsServiceExtensions.cs b/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsServiceExtensions.cs index dba54d7c684ecc8656b6af54d94551361f38345c..b8312edc5ca03b6554072f5de99f71c240e9ebbe 100644 --- a/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsServiceExtensions.cs +++ b/src/Workspaces/Core/Portable/LanguageServices/SyntaxFactsService/ISyntaxFactsServiceExtensions.cs @@ -139,5 +139,16 @@ public static bool IsAnonymousOrLocalFunctionStatement(this ISyntaxFactsService => syntaxFacts.IsAnonymousFunction(node) || syntaxFacts.IsLocalFunctionStatement(node); + public static SyntaxNode GetExpressionOfElementAccessExpression(this ISyntaxFactsService syntaxFacts, SyntaxNode node) + { + syntaxFacts.GetPartsOfElementAccessExpression(node, out var expression, out _); + return expression; + } + + public static SyntaxNode GetArgumentListOfElementAccessExpression(this ISyntaxFactsService syntaxFacts, SyntaxNode node) + { + syntaxFacts.GetPartsOfElementAccessExpression(node, out _, out var argumentList); + return argumentList; + } } } diff --git a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb index 1ed9d73d4298fa2b4fd6820e0b17f8f082ae407f..34afe619ae09c9c60612569d4b7e52016c914bed 100644 --- a/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb +++ b/src/Workspaces/VisualBasic/Portable/LanguageServices/VisualBasicSyntaxFactsService.vb @@ -601,13 +601,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Return TryCast(node, ConditionalAccessExpressionSyntax)?.Expression End Function - Public Function GetExpressionOfElementAccessExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfElementAccessExpression - Return TryCast(node, InvocationExpressionSyntax)?.Expression - End Function - - Public Function GetArgumentListOfElementAccessExpression(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetArgumentListOfElementAccessExpression - Return TryCast(node, InvocationExpressionSyntax)?.ArgumentList - End Function + Public Sub GetPartsOfElementAccessExpression(node As SyntaxNode, ByRef expression As SyntaxNode, ByRef argumentList As SyntaxNode) Implements ISyntaxFactsService.GetPartsOfElementAccessExpression + Dim invocation = TryCast(node, InvocationExpressionSyntax) + expression = invocation?.Expression + argumentList = invocation?.ArgumentList + End Sub Public Function GetExpressionOfInterpolation(node As SyntaxNode) As SyntaxNode Implements ISyntaxFactsService.GetExpressionOfInterpolation Return TryCast(node, InterpolationSyntax)?.Expression