From 75bc074bf02bdfaa8f50eb228f346a59b07266d2 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Tue, 2 Mar 2021 14:43:56 -0800 Subject: [PATCH 01/12] Experiment --- .../FindReferencesCascadeDirection.cs | 27 +++++++++++++++++++ .../FindReferencesSearchEngine.cs | 6 ++++- .../FindReferencesSearchEngine_MapCreation.cs | 16 +++++------ .../FindReferencesSearchOptions.cs | 10 +++++++ .../ILanguageServiceReferenceFinder.cs | 2 +- .../Finders/IReferenceFinder.cs | 5 ++-- 6 files changed, 54 insertions(+), 12 deletions(-) create mode 100644 src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs new file mode 100644 index 0000000000000..2a164032d2b81 --- /dev/null +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs @@ -0,0 +1,27 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +namespace Microsoft.CodeAnalysis.FindSymbols +{ + internal enum FindReferencesCascadeDirection + { + /// + /// Cascade to all symbols no matter what. is not the same as Up | Down. implies that cascading should go in both directions for every symbol hit. Up | Down + /// means going both up and down from the initial symbol, but then any cascaded symbols should stick with or depending on the initial cascading direction. + /// + All = 0, + + /// + /// Cascade up the inheritance hierarchy only. + /// + Up = 1, + + /// + /// Cascade down the inheritance hierarchy only. + /// + Down = 2, + } +} diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs index d914bc68fd48a..01e29649963cb 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs @@ -67,7 +67,11 @@ public async Task FindReferencesAsync(ISymbol symbol) { await using var _ = await _progressTracker.AddSingleItemAsync().ConfigureAwait(false); - var symbols = await DetermineAllSymbolsAsync(symbol).ConfigureAwait(false); + var cascadeDirection = _options.UnidirectionalHierarchyCascade + ? FindReferencesCascadeDirection.Up | FindReferencesCascadeDirection.Down + : FindReferencesCascadeDirection.All; + + var symbols = await DetermineAllSymbolsAsync(symbol, cascadeDirection).ConfigureAwait(false); var projectMap = await CreateProjectMapAsync(symbols).ConfigureAwait(false); var projectToDocumentMap = await CreateProjectToDocumentMapAsync(projectMap).ConfigureAwait(false); diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_MapCreation.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_MapCreation.cs index 81c18d64475d3..60ff29ad34731 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_MapCreation.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_MapCreation.cs @@ -102,18 +102,18 @@ private async Task CreateProjectMapAsync(ConcurrentSet symb } private async Task> DetermineAllSymbolsAsync( - ISymbol symbol) + ISymbol symbol, FindReferencesCascadeDirection cascadeDirection) { using (Logger.LogBlock(FunctionId.FindReference_DetermineAllSymbolsAsync, _cancellationToken)) { var result = new ConcurrentSet(MetadataUnifyingEquivalenceComparer.Instance); - await DetermineAllSymbolsCoreAsync(symbol, result).ConfigureAwait(false); + await DetermineAllSymbolsCoreAsync(symbol, cascadeDirection, result).ConfigureAwait(false); return result; } } private async Task DetermineAllSymbolsCoreAsync( - ISymbol symbol, ConcurrentSet result) + ISymbol symbol, FindReferencesCascadeDirection cascadeDirection, ConcurrentSet result) { _cancellationToken.ThrowIfCancellationRequested(); @@ -144,7 +144,7 @@ private async Task DetermineAllSymbolsCoreAsync( using var _ = ArrayBuilder.GetInstance(out var symbolTasks); var symbols = await f.DetermineCascadedSymbolsAsync( - searchSymbol, _solution, projects, _options, _cancellationToken).ConfigureAwait(false); + searchSymbol, _solution, projects, _options, cascadeDirection, _cancellationToken).ConfigureAwait(false); AddSymbolTasks(result, symbols, symbolTasks); // Defer to the language to see if it wants to cascade here in some special way. @@ -168,17 +168,17 @@ private async Task DetermineAllSymbolsCoreAsync( private void AddSymbolTasks( ConcurrentSet result, - ImmutableArray symbols, + ImmutableArray<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)> symbols, ArrayBuilder symbolTasks) { if (!symbols.IsDefault) { - foreach (var child in symbols) + foreach (var (symbol, cascadeDirection) in symbols) { - Contract.ThrowIfNull(child); + Contract.ThrowIfNull(symbol); _cancellationToken.ThrowIfCancellationRequested(); symbolTasks.Add(Task.Factory.StartNew( - () => DetermineAllSymbolsCoreAsync(child, result), _cancellationToken, TaskCreationOptions.None, _scheduler).Unwrap()); + () => DetermineAllSymbolsCoreAsync(symbol, cascadeDirection, result), _cancellationToken, TaskCreationOptions.None, _scheduler).Unwrap()); } } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs index 0581091aa9f4d..d1983bb65c612 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs @@ -49,6 +49,16 @@ internal sealed class FindReferencesSearchOptions [DataMember(Order = 2)] public bool Explicit { get; } + /// + /// When cascading if we should only travel in a consistent direction away from the starting symbol. For + /// example, starting on a virtual method, this would cascade upwards to implemented interface methods, and + /// downwards to overridden methods. However, it would not then travel back down to other implementations of + /// those interface methods. This is useful for cases where the client only wants references that could lead to + /// this symbol actually being called into at runtime. + /// + [DataMember(Order = 3)] + public bool UnidirectionalHierarchyCascade { get; } + public FindReferencesSearchOptions( bool associatePropertyReferencesWithSpecificAccessor, bool cascade, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ILanguageServiceReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ILanguageServiceReferenceFinder.cs index 737e35400968d..27ea0a26c7a9a 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ILanguageServiceReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ILanguageServiceReferenceFinder.cs @@ -16,7 +16,7 @@ namespace Microsoft.CodeAnalysis.FindSymbols.Finders /// internal interface ILanguageServiceReferenceFinder : ILanguageService { - Task> DetermineCascadedSymbolsAsync( + Task> DetermineCascadedSymbolsAsync( ISymbol symbol, Project project, CancellationToken cancellationToken); } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/IReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/IReferenceFinder.cs index dcc05a19cd02c..d6219a3c8f7ab 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/IReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/IReferenceFinder.cs @@ -24,9 +24,10 @@ internal interface IReferenceFinder /// /// Implementations of this method must be thread-safe. /// - Task> DetermineCascadedSymbolsAsync( + Task> DetermineCascadedSymbolsAsync( ISymbol symbol, Solution solution, IImmutableSet? projects, - FindReferencesSearchOptions options, CancellationToken cancellationToken); + FindReferencesSearchOptions options, FindReferencesCascadeDirection cascadeDirection, + CancellationToken cancellationToken); /// /// Called by the find references search engine to determine which projects should be From b22d624df9c51897ce8286f258993eb680cc20e8 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 3 Mar 2021 10:16:45 -0800 Subject: [PATCH 02/12] Add directions --- ...bstractFindUsagesService_FindReferences.cs | 2 +- .../DelegateInvokeMethodReferenceFinder.cs | 15 ++--- .../FindReferencesCascadeDirection.cs | 24 ++++--- .../FindReferencesSearchEngine.cs | 7 +-- .../FindReferencesSearchEngine_MapCreation.cs | 11 +++- .../FindReferencesSearchOptions.cs | 27 +++++--- ...dOrPropertyOrEventSymbolReferenceFinder.cs | 63 +++++++++++-------- .../Finders/AbstractReferenceFinder.cs | 22 ++++--- .../DestructorSymbolReferenceFinder.cs | 10 --- .../Finders/EventSymbolReferenceFinder.cs | 9 +-- .../ExplicitInterfaceMethodReferenceFinder.cs | 11 +++- .../Finders/FieldSymbolReferenceFinder.cs | 14 ++--- .../ILanguageServiceReferenceFinder.cs | 2 +- .../Finders/LinkedFileReferenceFinder.cs | 14 +++-- ...ethodTypeParameterSymbolReferenceFinder.cs | 13 ++-- .../Finders/NamedTypeSymbolReferenceFinder.cs | 9 ++- .../Finders/OrdinaryMethodReferenceFinder.cs | 13 ++-- .../Finders/ParameterSymbolReferenceFinder.cs | 23 ++++--- .../PropertyAccessorSymbolReferenceFinder.cs | 14 ++--- .../Finders/PropertySymbolReferenceFinder.cs | 16 +++-- .../FindSymbols/VisualBasicReferenceFinder.vb | 50 +++++++-------- 21 files changed, 198 insertions(+), 171 deletions(-) diff --git a/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService_FindReferences.cs b/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService_FindReferences.cs index 0d3bde98e06e3..21683c9a1427f 100644 --- a/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService_FindReferences.cs +++ b/src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService_FindReferences.cs @@ -112,7 +112,7 @@ public static async Task FindSymbolReferencesAsync( await context.SetSearchTitleAsync(string.Format(EditorFeaturesResources._0_references, FindUsagesHelpers.GetDisplayName(symbol))).ConfigureAwait(false); - var options = FindSymbols.FindReferencesSearchOptions.GetFeatureOptionsForStartingSymbol(symbol); + var options = FindReferencesSearchOptions.GetFeatureOptionsForStartingSymbol(symbol); // Now call into the underlying FAR engine to find reference. The FAR // engine will push results into the 'progress' instance passed into it. diff --git a/src/Features/Core/Portable/ChangeSignature/DelegateInvokeMethodReferenceFinder.cs b/src/Features/Core/Portable/ChangeSignature/DelegateInvokeMethodReferenceFinder.cs index 8ad3929ab6a06..b5db419837dab 100644 --- a/src/Features/Core/Portable/ChangeSignature/DelegateInvokeMethodReferenceFinder.cs +++ b/src/Features/Core/Portable/ChangeSignature/DelegateInvokeMethodReferenceFinder.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis.FindSymbols; using Microsoft.CodeAnalysis.FindSymbols.Finders; using Microsoft.CodeAnalysis.LanguageServices; +using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Extensions; using Roslyn.Utilities; @@ -32,20 +33,19 @@ internal class DelegateInvokeMethodReferenceFinder : AbstractReferenceFinder symbol.MethodKind == MethodKind.DelegateInvoke; - protected override async Task> DetermineCascadedSymbolsAsync( + protected override async Task> DetermineCascadedSymbolsAsync( IMethodSymbol symbol, Solution solution, IImmutableSet projects, FindReferencesSearchOptions options, + FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { - var result = ImmutableArray.CreateBuilder(); + using var _ = ArrayBuilder<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>.GetInstance(out var result); var beginInvoke = symbol.ContainingType.GetMembers(WellKnownMemberNames.DelegateBeginInvokeName).FirstOrDefault(); if (beginInvoke != null) - { - result.Add(beginInvoke); - } + result.Add((beginInvoke, cascadeDirection)); // All method group references foreach (var project in solution.Projects) @@ -53,8 +53,9 @@ protected override async Task> DetermineCascadedSymbolsA foreach (var document in project.Documents) { var changeSignatureService = document.GetLanguageService(); - result.AddRange(await changeSignatureService.DetermineCascadedSymbolsFromDelegateInvokeAsync( - symbol, document, cancellationToken).ConfigureAwait(false)); + var cascaded = await changeSignatureService.DetermineCascadedSymbolsFromDelegateInvokeAsync( + symbol, document, cancellationToken).ConfigureAwait(false); + result.AddRange(cascaded.SelectAsArray(s => (s, cascadeDirection))); } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs index 2a164032d2b81..6c1065d7672c5 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs @@ -2,26 +2,32 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System; + namespace Microsoft.CodeAnalysis.FindSymbols { + [Flags] internal enum FindReferencesCascadeDirection { /// - /// Cascade to all symbols no matter what. is not the same as Up | Down. implies that cascading should go in both directions for every symbol hit. Up | Down - /// means going both up and down from the initial symbol, but then any cascaded symbols should stick with or depending on the initial cascading direction. + /// Cascade up the inheritance hierarchy. /// - All = 0, + Up = 1, /// - /// Cascade up the inheritance hierarchy only. + /// Cascade down the inheritance hierarchy. /// - Up = 1, + Down = 2, /// - /// Cascade down the inheritance hierarchy only. + /// Cascade in both directions. /// - Down = 2, + UpAndDown = Up | Down, + } + + internal static class FindReferencesCascadeDirectionExtensions + { + public static bool HasFlag(this FindReferencesCascadeDirection value, FindReferencesCascadeDirection flag) + => (value & flag) != flag; } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs index 01e29649963cb..17a89c1b595d0 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine.cs @@ -67,11 +67,8 @@ public async Task FindReferencesAsync(ISymbol symbol) { await using var _ = await _progressTracker.AddSingleItemAsync().ConfigureAwait(false); - var cascadeDirection = _options.UnidirectionalHierarchyCascade - ? FindReferencesCascadeDirection.Up | FindReferencesCascadeDirection.Down - : FindReferencesCascadeDirection.All; - - var symbols = await DetermineAllSymbolsAsync(symbol, cascadeDirection).ConfigureAwait(false); + // For the starting symbol, always cascade up and down the inheritance hierarchy. + var symbols = await DetermineAllSymbolsAsync(symbol, FindReferencesCascadeDirection.UpAndDown).ConfigureAwait(false); var projectMap = await CreateProjectMapAsync(symbols).ConfigureAwait(false); var projectToDocumentMap = await CreateProjectToDocumentMapAsync(projectMap).ConfigureAwait(false); diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_MapCreation.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_MapCreation.cs index 60ff29ad34731..1525056574707 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_MapCreation.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchEngine_MapCreation.cs @@ -152,7 +152,7 @@ private async Task DetermineAllSymbolsCoreAsync( if (symbolProject?.LanguageServices.GetService() is { } service) { symbols = await service.DetermineCascadedSymbolsAsync( - searchSymbol, symbolProject, _cancellationToken).ConfigureAwait(false); + searchSymbol, symbolProject, cascadeDirection, _cancellationToken).ConfigureAwait(false); AddSymbolTasks(result, symbols, symbolTasks); } @@ -177,8 +177,15 @@ private void AddSymbolTasks( { Contract.ThrowIfNull(symbol); _cancellationToken.ThrowIfCancellationRequested(); + + // If we're cascading unidirectionally, then keep going in the direction this symbol was found in. + // Otherwise, if we're not unidirectional, then continue to cascade in both directions with this + // symbol. + var finalDirection = _options.UnidirectionalHierarchyCascade + ? cascadeDirection + : FindReferencesCascadeDirection.UpAndDown; symbolTasks.Add(Task.Factory.StartNew( - () => DetermineAllSymbolsCoreAsync(symbol, cascadeDirection, result), _cancellationToken, TaskCreationOptions.None, _scheduler).Unwrap()); + () => DetermineAllSymbolsCoreAsync(symbol, finalDirection, result), _cancellationToken, TaskCreationOptions.None, _scheduler).Unwrap()); } } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs index d1983bb65c612..bccaf8d5312bf 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs @@ -62,38 +62,49 @@ internal sealed class FindReferencesSearchOptions public FindReferencesSearchOptions( bool associatePropertyReferencesWithSpecificAccessor, bool cascade, - bool @explicit) + bool @explicit, + bool unidirectionalHierarchyCascade) { AssociatePropertyReferencesWithSpecificAccessor = associatePropertyReferencesWithSpecificAccessor; Cascade = cascade; Explicit = @explicit; + UnidirectionalHierarchyCascade = unidirectionalHierarchyCascade; } public FindReferencesSearchOptions With( Optional associatePropertyReferencesWithSpecificAccessor = default, Optional cascade = default, - Optional @explicit = default) + Optional @explicit = default, + Optional unidirectionalHierarchyCascade = default) { var newAssociatePropertyReferencesWithSpecificAccessor = associatePropertyReferencesWithSpecificAccessor.HasValue ? associatePropertyReferencesWithSpecificAccessor.Value : AssociatePropertyReferencesWithSpecificAccessor; var newCascade = cascade.HasValue ? cascade.Value : Cascade; var newExplicit = @explicit.HasValue ? @explicit.Value : Explicit; + var newUnidirectionalHierarchyCascade = unidirectionalHierarchyCascade.HasValue ? unidirectionalHierarchyCascade.Value : Explicit; if (newAssociatePropertyReferencesWithSpecificAccessor == AssociatePropertyReferencesWithSpecificAccessor && newCascade == Cascade && - newExplicit == Explicit) + newExplicit == Explicit && + newUnidirectionalHierarchyCascade == UnidirectionalHierarchyCascade) { return this; } - return new FindReferencesSearchOptions(newAssociatePropertyReferencesWithSpecificAccessor, newCascade, newExplicit); + return new FindReferencesSearchOptions( + newAssociatePropertyReferencesWithSpecificAccessor, + newCascade, + newExplicit, + newUnidirectionalHierarchyCascade); } /// - /// For IDE features, if the user starts searching on an accessor, then we want to give - /// results associated with the specific accessor. Otherwise, if they search on a property, - /// then associate everything with the property. + /// For IDE features, if the user starts searching on an accessor, then we want to give results associated with + /// the specific accessor. Otherwise, if they search on a property, then associate everything with the + /// property. We also only want to travel an inheritance hierarchy unidirectionally so that we only see potential + /// references that could actually reach this particular member. /// public static FindReferencesSearchOptions GetFeatureOptionsForStartingSymbol(ISymbol symbol) - => Default.With(associatePropertyReferencesWithSpecificAccessor: symbol.IsPropertyAccessor()); + => Default.With(associatePropertyReferencesWithSpecificAccessor: symbol.IsPropertyAccessor(), + unidirectionalHierarchyCascade: true); } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs index c220523a2be38..7fafd1390ea58 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs @@ -18,43 +18,54 @@ protected AbstractMethodOrPropertyOrEventSymbolReferenceFinder() { } - protected override async Task> DetermineCascadedSymbolsAsync( + protected override async Task> DetermineCascadedSymbolsAsync( TSymbol symbol, Solution solution, IImmutableSet? projects, FindReferencesSearchOptions options, + FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { // Static methods can't cascade. - if (!symbol.IsStatic) + if (symbol.IsStatic) + return ImmutableArray<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>.Empty; + + if (symbol.IsImplementableMember()) + { + // We have an interface method. Walk down the inheritance hierarchy and find all implementations of + // that method and cascade to them. + var result = cascadeDirection.HasFlag(FindReferencesCascadeDirection.Down) + ? await SymbolFinder.FindMemberImplementationsArrayAsync(symbol, solution, projects, cancellationToken).ConfigureAwait(false) + : ImmutableArray.Empty; + return result.SelectAsArray(s => (s, FindReferencesCascadeDirection.Down)); + } + else { - if (symbol.IsImplementableMember()) - { - // We have an interface method. Find all implementations of that method and - // cascade to them. - return await SymbolFinder.FindMemberImplementationsArrayAsync(symbol, solution, projects, cancellationToken).ConfigureAwait(false); - } - else - { - // We have a normal method. Find any interface methods that it implicitly or - // explicitly implements and cascade down to those. - var interfaceMembersImplemented = await SymbolFinder.FindImplementedInterfaceMembersArrayAsync( - symbol, solution, projects, cancellationToken).ConfigureAwait(false); + // We have a normal method. Find any interface methods up the inheritance hierarchy that it implicitly + // or explicitly implements and cascade to those. + var interfaceMembersImplemented = cascadeDirection.HasFlag(FindReferencesCascadeDirection.Up) + ? await SymbolFinder.FindImplementedInterfaceMembersArrayAsync(symbol, solution, projects, cancellationToken).ConfigureAwait(false) + : ImmutableArray.Empty; - // Finally, methods can cascade through virtual/override inheritance. NOTE(cyrusn): - // We only need to go up or down one level. Then, when we're finding references on - // those members, we'll end up traversing the entire hierarchy. - var overrides = await SymbolFinder.FindOverridesArrayAsync( - symbol, solution, projects, cancellationToken).ConfigureAwait(false); + // Finally, methods can cascade through virtual/override inheritance. NOTE(cyrusn): + // We only need to go up or down one level. Then, when we're finding references on + // those members, we'll end up traversing the entire hierarchy. + var overrides = cascadeDirection.HasFlag(FindReferencesCascadeDirection.Up) + ? await SymbolFinder.FindOverridesArrayAsync(symbol, solution, projects, cancellationToken).ConfigureAwait(false) + : ImmutableArray.Empty; - var overriddenMember = symbol.GetOverriddenMember(); - return overriddenMember == null - ? interfaceMembersImplemented.Concat(overrides) - : interfaceMembersImplemented.Concat(overrides).Concat(overriddenMember); - } - } + var overriddenMember = cascadeDirection.HasFlag(FindReferencesCascadeDirection.Up) + ? symbol.GetOverriddenMember() + : null; + + var interfaceMembersImplementedWithDirection = interfaceMembersImplemented.SelectAsArray(s => (s, FindReferencesCascadeDirection.Up)); + var overridesWithDirection = overrides.SelectAsArray(s => (s, FindReferencesCascadeDirection.Down)); + var overriddenMemberWithDirection = (overriddenMember!, FindReferencesCascadeDirection.Up); - return ImmutableArray.Empty; + return overriddenMember == null + ? interfaceMembersImplementedWithDirection.Concat(overridesWithDirection) + : interfaceMembersImplementedWithDirection.Concat(overridesWithDirection).Concat(overriddenMemberWithDirection); + } } protected static ImmutableArray GetReferencedAccessorSymbols( diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs index d8ee036faf9bd..ba890f19328fb 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractReferenceFinder.cs @@ -26,9 +26,10 @@ internal abstract partial class AbstractReferenceFinder : IReferenceFinder public const string ContainingTypeInfoPropertyName = "ContainingTypeInfo"; public const string ContainingMemberInfoPropertyName = "ContainingMemberInfo"; - public abstract Task> DetermineCascadedSymbolsAsync( + public abstract Task> DetermineCascadedSymbolsAsync( ISymbol symbol, Solution solution, IImmutableSet? projects, - FindReferencesSearchOptions options, CancellationToken cancellationToken); + FindReferencesSearchOptions options, FindReferencesCascadeDirection cascadeDirection, + CancellationToken cancellationToken); public abstract Task> DetermineProjectsToSearchAsync(ISymbol symbol, Solution solution, IImmutableSet? projects, CancellationToken cancellationToken); @@ -932,20 +933,20 @@ public override ValueTask> FindReferencesInDocume : new ValueTask>(ImmutableArray.Empty); } - public override Task> DetermineCascadedSymbolsAsync( + public override Task> DetermineCascadedSymbolsAsync( ISymbol symbol, Solution solution, IImmutableSet? projects, - FindReferencesSearchOptions options, CancellationToken cancellationToken) + FindReferencesSearchOptions options, FindReferencesCascadeDirection cascadeDirection, + CancellationToken cancellationToken) { if (options.Cascade && symbol is TSymbol typedSymbol && CanFind(typedSymbol)) { return DetermineCascadedSymbolsAsync( - typedSymbol, - solution, projects, options, cancellationToken); + typedSymbol, solution, projects, options, cascadeDirection, cancellationToken); } - return SpecializedTasks.EmptyImmutableArray(); + return SpecializedTasks.EmptyImmutableArray<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>(); } protected virtual Task> DetermineProjectsToSearchAsync( @@ -955,11 +956,12 @@ protected virtual Task> DetermineProjectsToSearchAsync( solution, symbol, projects, cancellationToken); } - protected virtual Task> DetermineCascadedSymbolsAsync( + protected virtual Task> DetermineCascadedSymbolsAsync( TSymbol symbol, Solution solution, IImmutableSet? projects, - FindReferencesSearchOptions options, CancellationToken cancellationToken) + FindReferencesSearchOptions options, FindReferencesCascadeDirection cascadeDirection, + CancellationToken cancellationToken) { - return SpecializedTasks.EmptyImmutableArray(); + return SpecializedTasks.EmptyImmutableArray<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>(); } protected static ValueTask> FindReferencesInDocumentUsingSymbolNameAsync( diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/DestructorSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/DestructorSymbolReferenceFinder.cs index 2c7b642f205fc..0ac3ddebb3cee 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/DestructorSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/DestructorSymbolReferenceFinder.cs @@ -14,16 +14,6 @@ internal class DestructorSymbolReferenceFinder : AbstractReferenceFinder symbol.MethodKind == MethodKind.Destructor; - protected override Task> DetermineCascadedSymbolsAsync( - IMethodSymbol symbol, - Solution solution, - IImmutableSet? projects, - FindReferencesSearchOptions options, - CancellationToken cancellationToken) - { - return SpecializedTasks.EmptyImmutableArray(); - } - protected override Task> DetermineDocumentsToSearchAsync( IMethodSymbol symbol, Project project, diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/EventSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/EventSymbolReferenceFinder.cs index efb31e040f2e4..059f739c5c777 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/EventSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/EventSymbolReferenceFinder.cs @@ -14,15 +14,16 @@ internal class EventSymbolReferenceFinder : AbstractMethodOrPropertyOrEventSymbo protected override bool CanFind(IEventSymbol symbol) => true; - protected override async Task> DetermineCascadedSymbolsAsync( + protected override async Task> DetermineCascadedSymbolsAsync( IEventSymbol symbol, Solution solution, IImmutableSet? projects, FindReferencesSearchOptions options, + FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { var baseSymbols = await base.DetermineCascadedSymbolsAsync( - symbol, solution, projects, options, cancellationToken).ConfigureAwait(false); + symbol, solution, projects, options, cascadeDirection, cancellationToken).ConfigureAwait(false); var backingFields = symbol.ContainingType.GetMembers() .OfType() @@ -32,8 +33,8 @@ protected override async Task> DetermineCascadedSymbolsA var associatedNamedTypes = symbol.ContainingType.GetTypeMembers() .WhereAsArray(n => symbol.Equals(n.AssociatedSymbol)); - return baseSymbols.Concat(ImmutableArray.CastUp(backingFields)) - .Concat(ImmutableArray.CastUp(associatedNamedTypes)); + return baseSymbols.Concat(backingFields.SelectAsArray(f => ((ISymbol)f, cascadeDirection))) + .Concat(associatedNamedTypes.SelectAsArray(n => ((ISymbol)n, cascadeDirection))); } protected override Task> DetermineDocumentsToSearchAsync( diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ExplicitInterfaceMethodReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ExplicitInterfaceMethodReferenceFinder.cs index b4c1382e95970..533c4227ff5a3 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ExplicitInterfaceMethodReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ExplicitInterfaceMethodReferenceFinder.cs @@ -14,15 +14,20 @@ internal class ExplicitInterfaceMethodReferenceFinder : AbstractReferenceFinder< protected override bool CanFind(IMethodSymbol symbol) => symbol.MethodKind == MethodKind.ExplicitInterfaceImplementation; - protected override Task> DetermineCascadedSymbolsAsync( + protected override Task> DetermineCascadedSymbolsAsync( IMethodSymbol symbol, Solution solution, IImmutableSet? projects, FindReferencesSearchOptions options, + FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { - // An explicit interface method will cascade to all the methods that it implements. - return Task.FromResult(ImmutableArray.CastUp(symbol.ExplicitInterfaceImplementations)); + if (!cascadeDirection.HasFlag(FindReferencesCascadeDirection.Up)) + return SpecializedTasks.EmptyImmutableArray<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>(); + + // An explicit interface method will cascade to all the methods that it implements in the up direction. + return Task.FromResult( + symbol.ExplicitInterfaceImplementations.SelectAsArray(m => ((ISymbol)m, FindReferencesCascadeDirection.Up))); } protected override Task> DetermineDocumentsToSearchAsync( diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/FieldSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/FieldSymbolReferenceFinder.cs index 47076afcf406e..829999659d2f6 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/FieldSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/FieldSymbolReferenceFinder.cs @@ -14,21 +14,17 @@ internal class FieldSymbolReferenceFinder : AbstractReferenceFinder true; - protected override Task> DetermineCascadedSymbolsAsync( + protected override Task> DetermineCascadedSymbolsAsync( IFieldSymbol symbol, Solution solution, IImmutableSet? projects, FindReferencesSearchOptions options, + FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { - if (symbol.AssociatedSymbol != null) - { - return Task.FromResult(ImmutableArray.Create(symbol.AssociatedSymbol)); - } - else - { - return SpecializedTasks.EmptyImmutableArray(); - } + return symbol.AssociatedSymbol != null + ? Task.FromResult(ImmutableArray.Create((symbol.AssociatedSymbol, cascadeDirection))) + : SpecializedTasks.EmptyImmutableArray<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>(); } protected override Task> DetermineDocumentsToSearchAsync( diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ILanguageServiceReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ILanguageServiceReferenceFinder.cs index 27ea0a26c7a9a..aec22cca0ea43 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ILanguageServiceReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ILanguageServiceReferenceFinder.cs @@ -17,6 +17,6 @@ namespace Microsoft.CodeAnalysis.FindSymbols.Finders internal interface ILanguageServiceReferenceFinder : ILanguageService { Task> DetermineCascadedSymbolsAsync( - ISymbol symbol, Project project, CancellationToken cancellationToken); + ISymbol symbol, Project project, FindReferencesCascadeDirection cascadeDirection, 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 ac9e7b32fde03..c1514949a5b05 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/LinkedFileReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/LinkedFileReferenceFinder.cs @@ -11,13 +11,17 @@ namespace Microsoft.CodeAnalysis.FindSymbols.Finders { internal class LinkedFileReferenceFinder : IReferenceFinder { - public Task> DetermineCascadedSymbolsAsync( + public async Task> DetermineCascadedSymbolsAsync( ISymbol symbol, Solution solution, IImmutableSet? projects, - FindReferencesSearchOptions options, CancellationToken cancellationToken) + FindReferencesSearchOptions options, FindReferencesCascadeDirection cascadeDirection, + CancellationToken cancellationToken) { - return options.Cascade - ? SymbolFinder.FindLinkedSymbolsAsync(symbol, solution, cancellationToken) - : SpecializedTasks.EmptyImmutableArray(); + if (!options.Cascade) + return ImmutableArray<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>.Empty; + + var linkedSymbols = await SymbolFinder.FindLinkedSymbolsAsync(symbol, solution, cancellationToken).ConfigureAwait(false); + return linkedSymbols.SelectAsArray(s => (s, cascadeDirection)); + } public Task> DetermineDocumentsToSearchAsync( diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/MethodTypeParameterSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/MethodTypeParameterSymbolReferenceFinder.cs index 86cf5bd2d89a3..a2b57b754e0ee 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/MethodTypeParameterSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/MethodTypeParameterSymbolReferenceFinder.cs @@ -14,11 +14,12 @@ internal class MethodTypeParameterSymbolReferenceFinder : AbstractReferenceFinde protected override bool CanFind(ITypeParameterSymbol symbol) => symbol.TypeParameterKind == TypeParameterKind.Method; - protected override Task> DetermineCascadedSymbolsAsync( + protected override Task> DetermineCascadedSymbolsAsync( ITypeParameterSymbol symbol, Solution solution, IImmutableSet? projects, FindReferencesSearchOptions options, + FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { var method = (IMethodSymbol)symbol.ContainingSymbol; @@ -28,18 +29,18 @@ protected override Task> DetermineCascadedSymbolsAsync( { if (method.PartialDefinitionPart != null && ordinal < method.PartialDefinitionPart.TypeParameters.Length) { - return Task.FromResult(ImmutableArray.Create( - method.PartialDefinitionPart.TypeParameters[ordinal])); + return Task.FromResult(ImmutableArray.Create( + ((ISymbol)method.PartialDefinitionPart.TypeParameters[ordinal], cascadeDirection))); } if (method.PartialImplementationPart != null && ordinal < method.PartialImplementationPart.TypeParameters.Length) { - return Task.FromResult(ImmutableArray.Create( - method.PartialImplementationPart.TypeParameters[ordinal])); + return Task.FromResult(ImmutableArray.Create( + ((ISymbol)method.PartialImplementationPart.TypeParameters[ordinal], cascadeDirection))); } } - return SpecializedTasks.EmptyImmutableArray(); + return SpecializedTasks.EmptyImmutableArray<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>(); } protected override Task> DetermineDocumentsToSearchAsync( diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamedTypeSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamedTypeSymbolReferenceFinder.cs index b56114f09d41b..7ff58d482f381 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamedTypeSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/NamedTypeSymbolReferenceFinder.cs @@ -18,19 +18,18 @@ internal class NamedTypeSymbolReferenceFinder : AbstractReferenceFinder symbol.TypeKind != TypeKind.Error; - protected override Task> DetermineCascadedSymbolsAsync( + protected override Task> DetermineCascadedSymbolsAsync( INamedTypeSymbol symbol, Solution solution, IImmutableSet? projects, FindReferencesSearchOptions options, + FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { - var result = ArrayBuilder.GetInstance(); + using var _ = ArrayBuilder.GetInstance(out var result); if (symbol.AssociatedSymbol != null) - { Add(result, ImmutableArray.Create(symbol.AssociatedSymbol)); - } // cascade to constructors Add(result, symbol.Constructors); @@ -38,7 +37,7 @@ protected override Task> DetermineCascadedSymbolsAsync( // cascade to destructor Add(result, symbol.GetMembers(WellKnownMemberNames.DestructorName)); - return Task.FromResult(result.ToImmutableAndFree()); + return Task.FromResult(result.SelectAsArray(s => (s, cascadeDirection))); } private static void Add(ArrayBuilder result, ImmutableArray enumerable) where TSymbol : ISymbol diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OrdinaryMethodReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OrdinaryMethodReferenceFinder.cs index 2122e4ffa18c5..c147242d317eb 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OrdinaryMethodReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/OrdinaryMethodReferenceFinder.cs @@ -20,31 +20,30 @@ protected override bool CanFind(IMethodSymbol symbol) symbol.MethodKind == MethodKind.LocalFunction; } - protected override async Task> DetermineCascadedSymbolsAsync( + protected override async Task> DetermineCascadedSymbolsAsync( IMethodSymbol symbol, Solution solution, IImmutableSet? projects, FindReferencesSearchOptions options, + FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { // If it's a delegate method, then cascade to the type as well. These guys are // practically equivalent for users. if (symbol.ContainingType.TypeKind == TypeKind.Delegate) { - return ImmutableArray.Create(symbol.ContainingType); + return ImmutableArray.Create(((ISymbol)symbol.ContainingType, cascadeDirection)); } else { var otherPartsOfPartial = GetOtherPartsOfPartial(symbol); var baseCascadedSymbols = await base.DetermineCascadedSymbolsAsync( - symbol, solution, projects, options, cancellationToken).ConfigureAwait(false); + symbol, solution, projects, options, cascadeDirection, cancellationToken).ConfigureAwait(false); if (otherPartsOfPartial == null && baseCascadedSymbols == null) - { - return ImmutableArray.Empty; - } + return ImmutableArray<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>.Empty; - return otherPartsOfPartial.Concat(baseCascadedSymbols); + return otherPartsOfPartial.SelectAsArray(m => (m, cascadeDirection)).Concat(baseCascadedSymbols); } } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ParameterSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ParameterSymbolReferenceFinder.cs index ff20f519990f5..70abcb6e42298 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ParameterSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/ParameterSymbolReferenceFinder.cs @@ -95,26 +95,31 @@ protected override ValueTask> FindReferencesInDoc }; } - protected override async Task> DetermineCascadedSymbolsAsync( + protected override async Task> DetermineCascadedSymbolsAsync( IParameterSymbol parameter, Solution solution, IImmutableSet? projects, FindReferencesSearchOptions options, + FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { if (parameter.IsThis) { - return ImmutableArray.Empty; + return ImmutableArray<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>.Empty; } - var result = ArrayBuilder.GetInstance(); + using var _1 = ArrayBuilder.GetInstance(out var symbols); - await CascadeBetweenAnonymousFunctionParametersAsync(solution, parameter, result, cancellationToken).ConfigureAwait(false); - CascadeBetweenPropertyAndAccessorParameters(parameter, result); - CascadeBetweenDelegateMethodParameters(parameter, result); - CascadeBetweenPartialMethodParameters(parameter, result); + await CascadeBetweenAnonymousFunctionParametersAsync(solution, parameter, symbols, cancellationToken).ConfigureAwait(false); + CascadeBetweenPropertyAndAccessorParameters(parameter, symbols); + CascadeBetweenDelegateMethodParameters(parameter, symbols); + CascadeBetweenPartialMethodParameters(parameter, symbols); - return result.ToImmutableAndFree(); + using var _2 = ArrayBuilder<(ISymbol symbol, FindReferencesCascadeDirection cascadeDirection)>.GetInstance(symbols.Count, out var result); + foreach (var symbol in symbols) + result.Add((symbol, cascadeDirection)); + + return result.ToImmutable(); } private static async Task CascadeBetweenAnonymousFunctionParametersAsync( @@ -250,7 +255,7 @@ private static void CascadeBetweenDelegateMethodParameters( var ordinal = parameter.Ordinal; if (parameter.ContainingSymbol is IMethodSymbol containingMethod) { - var containingType = containingMethod.ContainingType as INamedTypeSymbol; + var containingType = containingMethod.ContainingType; if (containingType.IsDelegateType()) { if (containingMethod.MethodKind == MethodKind.DelegateInvoke) diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertyAccessorSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertyAccessorSymbolReferenceFinder.cs index a88717d9f8c3e..f138a610f5a93 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertyAccessorSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertyAccessorSymbolReferenceFinder.cs @@ -15,25 +15,21 @@ internal class PropertyAccessorSymbolReferenceFinder : AbstractMethodOrPropertyO protected override bool CanFind(IMethodSymbol symbol) => symbol.MethodKind.IsPropertyAccessor(); - protected override async Task> DetermineCascadedSymbolsAsync( + protected override async Task> DetermineCascadedSymbolsAsync( IMethodSymbol symbol, Solution solution, IImmutableSet? projects, FindReferencesSearchOptions options, + FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { var result = await base.DetermineCascadedSymbolsAsync( - symbol, solution, projects, options, cancellationToken).ConfigureAwait(false); + symbol, solution, projects, options, cascadeDirection, cancellationToken).ConfigureAwait(false); // If we've been asked to search for specific accessors, then do not cascade. // We don't want to produce results for the associated property. - if (!options.AssociatePropertyReferencesWithSpecificAccessor) - { - if (symbol.AssociatedSymbol != null) - { - result = result.Add(symbol.AssociatedSymbol); - } - } + if (!options.AssociatePropertyReferencesWithSpecificAccessor && symbol.AssociatedSymbol != null) + result = result.Add((symbol.AssociatedSymbol, cascadeDirection)); return result; } diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertySymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertySymbolReferenceFinder.cs index 13c8efb0eb5e9..f91b23d9ebc7c 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertySymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/PropertySymbolReferenceFinder.cs @@ -22,32 +22,30 @@ internal class PropertySymbolReferenceFinder : AbstractMethodOrPropertyOrEventSy protected override bool CanFind(IPropertySymbol symbol) => true; - protected override async Task> DetermineCascadedSymbolsAsync( + protected override async Task> DetermineCascadedSymbolsAsync( IPropertySymbol symbol, Solution solution, IImmutableSet? projects, FindReferencesSearchOptions options, + FindReferencesCascadeDirection cascadeDirection, CancellationToken cancellationToken) { var baseSymbols = await base.DetermineCascadedSymbolsAsync( - symbol, solution, projects, options, cancellationToken).ConfigureAwait(false); + symbol, solution, projects, options, cascadeDirection, cancellationToken).ConfigureAwait(false); var backingFields = symbol.ContainingType.GetMembers() .OfType() .Where(f => symbol.Equals(f.AssociatedSymbol)) - .ToImmutableArray(); + .Select(f => ((ISymbol)f, cascadeDirection)) + .ToImmutableArray(); var result = baseSymbols.Concat(backingFields); if (symbol.GetMethod != null) - { - result = result.Add(symbol.GetMethod); - } + result = result.Add((symbol.GetMethod, cascadeDirection)); if (symbol.SetMethod != null) - { - result = result.Add(symbol.SetMethod); - } + result = result.Add((symbol.SetMethod, cascadeDirection)); return result; } diff --git a/src/Workspaces/VisualBasic/Portable/FindSymbols/VisualBasicReferenceFinder.vb b/src/Workspaces/VisualBasic/Portable/FindSymbols/VisualBasicReferenceFinder.vb index 04b53a4c0a4e4..eaf724e56be67 100644 --- a/src/Workspaces/VisualBasic/Portable/FindSymbols/VisualBasicReferenceFinder.vb +++ b/src/Workspaces/VisualBasic/Portable/FindSymbols/VisualBasicReferenceFinder.vb @@ -19,58 +19,56 @@ Namespace Microsoft.CodeAnalysis.FindSymbols Public Sub New() End Sub - Public Function DetermineCascadedSymbolsAsync(symbol As ISymbol, - project As Project, - cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of ISymbol)) Implements ILanguageServiceReferenceFinder.DetermineCascadedSymbolsAsync + Public Function DetermineCascadedSymbolsAsync( + symbol As ISymbol, + project As Project, + cascadeDirection As FindReferencesCascadeDirection, + cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of (symbol As ISymbol, cascadeDirection As FindReferencesCascadeDirection))) Implements ILanguageServiceReferenceFinder.DetermineCascadedSymbolsAsync If symbol.Kind = SymbolKind.Property Then - Return DetermineCascadedSymbolsAsync( - DirectCast(symbol, IPropertySymbol), project, cancellationToken) + Return DetermineCascadedSymbolsAsync(DirectCast(symbol, IPropertySymbol), project, cascadeDirection, cancellationToken) ElseIf symbol.Kind = SymbolKind.NamedType Then - Return DetermineCascadedSymbolsAsync( - DirectCast(symbol, INamedTypeSymbol), project, cancellationToken) + Return DetermineCascadedSymbolsAsync(DirectCast(symbol, INamedTypeSymbol), project, cascadeDirection, cancellationToken) Else - Return SpecializedTasks.EmptyImmutableArray(Of ISymbol)() + Return SpecializedTasks.EmptyImmutableArray(Of (symbol As ISymbol, cascadeDirection As FindReferencesCascadeDirection))() End If End Function Private Shared Async Function DetermineCascadedSymbolsAsync( [property] As IPropertySymbol, project As Project, - cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of ISymbol)) + cascadeDirection As FindReferencesCascadeDirection, + cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of (symbol As ISymbol, cascadeDirection As FindReferencesCascadeDirection))) Dim compilation = Await project.GetCompilationAsync(cancellationToken).ConfigureAwait(False) Dim relatedSymbol = [property].FindRelatedExplicitlyDeclaredSymbol(compilation) Return If([property].Equals(relatedSymbol), - ImmutableArray(Of ISymbol).Empty, - ImmutableArray.Create(relatedSymbol)) + ImmutableArray(Of (symbol As ISymbol, cascadeDirection As FindReferencesCascadeDirection)).Empty, + ImmutableArray.Create((relatedSymbol, cascadeDirection))) End Function Private Shared Async Function DetermineCascadedSymbolsAsync( namedType As INamedTypeSymbol, project As Project, - cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of ISymbol)) + cascadeDirection As FindReferencesCascadeDirection, + cancellationToken As CancellationToken) As Task(Of ImmutableArray(Of (symbol As ISymbol, cascadeDirection As FindReferencesCascadeDirection))) Dim compilation = Await project.GetCompilationAsync(cancellationToken).ConfigureAwait(False) ' If this is a WinForms project, then the VB 'my' feature may have synthesized ' a property that would return an instance of the main Form type for the project. ' Search for such properties and cascade to them as well. - Return GetMatchingMyPropertySymbols(namedType, compilation, cancellationToken). - Distinct().ToImmutableArray() - End Function - Private Shared Function GetMatchingMyPropertySymbols( - namedType As INamedTypeSymbol, - compilation As Compilation, - cancellationToken As CancellationToken) As IEnumerable(Of ISymbol) - Return From childNamespace In compilation.RootNamespace.GetNamespaceMembers() - Where childNamespace.IsMyNamespace(compilation) - From type In childNamespace.GetAllTypes(cancellationToken) - Where type.Name = "MyForms" - From childProperty In type.GetMembers().OfType(Of IPropertySymbol) - Where childProperty.IsImplicitlyDeclared AndAlso childProperty.Type.Equals(namedType) - Select DirectCast(childProperty, ISymbol) + Dim matchingMyPropertySymbols = + From childNamespace In compilation.RootNamespace.GetNamespaceMembers() + Where childNamespace.IsMyNamespace(compilation) + From type In childNamespace.GetAllTypes(cancellationToken) + Where type.Name = "MyForms" + From childProperty In type.GetMembers().OfType(Of IPropertySymbol) + Where childProperty.IsImplicitlyDeclared AndAlso childProperty.Type.Equals(namedType) + Select (DirectCast(childProperty, ISymbol), cascadeDirection) + + Return matchingMyPropertySymbols.Distinct().ToImmutableArray() End Function End Class End Namespace From ed37f82290f81c18cfcbec32c871be8604548112 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 3 Mar 2021 11:00:36 -0800 Subject: [PATCH 03/12] Options --- .../FindReferences/FindReferencesSearchOptions.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs index bccaf8d5312bf..cc6368c6e651e 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs @@ -11,10 +11,10 @@ namespace Microsoft.CodeAnalysis.FindSymbols internal sealed class FindReferencesSearchOptions { public static readonly FindReferencesSearchOptions Default = - new( - associatePropertyReferencesWithSpecificAccessor: false, + new(associatePropertyReferencesWithSpecificAccessor: false, cascade: true, - @explicit: true); + @explicit: true, + unidirectionalHierarchyCascade: false); /// /// When searching for property, associate specific references we find to the relevant From 3c56b7bc47d3c81f2a47f38373c7e9b3f4680d87 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 3 Mar 2021 11:17:32 -0800 Subject: [PATCH 04/12] Break out tests --- .../FindReferencesTests.NamedTypeSymbols.vb | 56 ++++- ...ndReferencesTests.OrdinaryMethodSymbols.vb | 198 +++++++++++++++++- .../FindReferencesTests.PropertySymbols.vb | 82 +++++++- .../FindReferencesSearchOptions.cs | 2 +- 4 files changed, 319 insertions(+), 19 deletions(-) diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb index aa5ff63354ab3..41d8aa7e87edc 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb @@ -545,7 +545,7 @@ class C : I, I - Public Async Function TestCascadedMembersFromConstructedInterfaces5(kind As TestKind, host As TestHost) As Task + Public Async Function TestCascadedMembersFromConstructedInterfaces5_Api(host As TestHost) As Task Dim input = @@ -564,12 +564,36 @@ class C : I, I - Await TestAPIAndFeature(input, kind, host) + Await TestAPI(input, host) + End Function + + + + Public Async Function TestCascadedMembersFromConstructedInterfaces5_FEature(host As TestHost) As Task + Dim input = + + + +{ + void {|Definition:Goo|}(X x); +} + +class C : I, I +{ + public void {|Definition:$$Goo|}(int x) { } + public void {|Definition:Goo|}(string x) { } +} +]]> + + + + Await TestStreamingFeature(input, host) End Function - Public Async Function TestCascadedMembersFromConstructedInterfaces6(kind As TestKind, host As TestHost) As Task + Public Async Function TestCascadedMembersFromConstructedInterfaces6_Api(host As TestHost) As Task Dim input = @@ -588,7 +612,31 @@ class C : I, I - Await TestAPIAndFeature(input, kind, host) + Await TestAPI(input, host) + End Function + + + + Public Async Function TestCascadedMembersFromConstructedInterfaces6_Feature(host As TestHost) As Task + Dim input = + + + +{ + void {|Definition:Goo|}(X x); +} + +class C : I, I +{ + public void {|Definition:Goo|}(int x) { } + public void {|Definition:$$Goo|}(string x) { } +} +]]> + + + + Await TestStreamingFeature(input, host) End Function diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb index 71841563ba2f3..47a684df7ded6 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb @@ -443,7 +443,7 @@ class C End Function - Public Async Function TestOrdinaryMethodInterfaceInheritance_FromReference(kind As TestKind, host As TestHost) As Task + Public Async Function TestOrdinaryMethodInterfaceInheritance_FromReference_Api(host As TestHost) As Task Dim input = @@ -480,11 +480,52 @@ class C - Await TestAPIAndFeature(input, kind, host) + Await TestAPI(input, host) + End Function + + + Public Async Function TestOrdinaryMethodInterfaceInheritance_FromReference_Feature(kind As TestKind, host As TestHost) As Task + Dim input = + + + + interface I1 + { + void {|Definition:Goo|}(); + } + + class C1 : I1 + { + public void {|Definition:Goo|}() + { + } + } + + interface I2 : I1 + { + void {|Definition:Goo|}(); + void Bar(); + } + + class C2 : I2 + { + public void Bar() + { + [|Goo$$|](); + } + + public void {|Definition:Goo|}(); + { + } + } + + + + Await TestStreamingFeature(input, host) End Function - Public Async Function TestOrdinaryMethodInterfaceInheritance_FromDefinition(kind As TestKind, host As TestHost) As Task + Public Async Function TestOrdinaryMethodInterfaceInheritance_FromDefinition_Api(host As TestHost) As Task Dim input = @@ -521,7 +562,48 @@ class C - Await TestAPIAndFeature(input, kind, host) + Await TestAPI(input, host) + End Function + + + Public Async Function TestOrdinaryMethodInterfaceInheritance_FromDefinition_Feature(host As TestHost) As Task + Dim input = + + + + interface I1 + { + void {|Definition:Go$$o|}(); + } + + class C1 : I1 + { + public void {|Definition:Goo|}() + { + } + } + + interface I2 : I1 + { + void {|Definition:Goo|}(); + void Bar(); + } + + class C2 : I2 + { + public void Bar() + { + [|Goo|](); + } + + public void {|Definition:Goo|}(); + { + } + } + + + + Await TestStreamingFeature(input, host) End Function @@ -1398,7 +1480,7 @@ End Interface - Public Async Function TestCascadeOrdinaryMethodFromGenericInterface2(kind As TestKind, host As TestHost) As Task + Public Async Function TestCascadeOrdinaryMethodFromGenericInterface2_Api(host As TestHost) As Task Dim input = @@ -1425,12 +1507,44 @@ End Interface - Await TestAPIAndFeature(input, kind, host) + Await TestAPI(input, host) End Function - Public Async Function TestCascadeOrdinaryMethodFromGenericInterface3(kind As TestKind, host As TestHost) As Task + Public Async Function TestCascadeOrdinaryMethodFromGenericInterface2_Feature(host As TestHost) As Task + Dim input = + + + + + { + void {|Definition:F|}(); + } + + class Base : I + { + void I.{|Definition:$$F|}() { } + } + + class Derived : Base, I + { + public void {|Definition:F|}() + { + [|F|](); + } + } +]]> + + + + Await TestStreamingFeature(input, host) + End Function + + + + Public Async Function TestCascadeOrdinaryMethodFromGenericInterface3_Api(host As TestHost) As Task Dim input = @@ -1457,12 +1571,44 @@ End Interface - Await TestAPIAndFeature(input, kind, host) + Await TestAPI(input, host) + End Function + + + + Public Async Function TestCascadeOrdinaryMethodFromGenericInterface3_Feature(host As TestHost) As Task + Dim input = + + + + + { + void {|Definition:F|}(); + } + + class Base : I + { + void I.{|Definition:F|}() { } + } + + class Derived : Base, I + { + public void {|Definition:$$F|}() + { + [|F|](); + } + } +]]> + + + + Await TestStreamingFeature(input, host) End Function - Public Async Function TestCascadeOrdinaryMethodFromGenericInterface4(kind As TestKind, host As TestHost) As Task + Public Async Function TestCascadeOrdinaryMethodFromGenericInterface4_Api(host As TestHost) As Task Dim input = @@ -1489,7 +1635,39 @@ End Interface - Await TestAPIAndFeature(input, kind, host) + Await TestAPI(input, host) + End Function + + + + Public Async Function TestCascadeOrdinaryMethodFromGenericInterface4_Feature(host As TestHost) As Task + Dim input = + + + + + { + void {|Definition:F|}(); + } + + class Base : I + { + void I.{|Definition:F|}() { } + } + + class Derived : Base, I + { + public void {|Definition:F|}() + { + [|$$F|](); + } + } +]]> + + + + Await TestStreamingFeature(input, host) End Function diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb index 48dc7f4eaa9ea..499d0b229e08b 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb @@ -297,7 +297,7 @@ public class A : DD - Public Async Function TestCSharp_PropertyFromGenericInterface1(kind As TestKind, host As TestHost) As Task + Public Async Function TestCSharp_PropertyFromGenericInterface1_Api(host As TestHost) As Task Dim input = @@ -329,7 +329,44 @@ public class M : I1, I3 - Await TestAPIAndFeature(input, kind, host) + Await TestAPI(input, host) + End Function + + + + Public Async Function TestCSharp_PropertyFromGenericInterface1_Streaming(host As TestHost) As Task + Dim input = + + + + +{ + T {|Definition:$$Name|} { get; set; } +} + +interface I2 +{ + int Name { get; set; } +} + +interface I3 : I2 +{ + new T {|Definition:Name|} { get; set; } +} + +public class M : I1, I3 +{ + public T {|Definition:Name|} { get; set; } + int I2.Name { get; set; } +} +]]> + + + + Await TestStreamingFeature(input, host) End Function @@ -371,7 +408,7 @@ public class M : I1, I3 - Public Async Function TestCSharp_PropertyFromGenericInterface3(kind As TestKind, host As TestHost) As Task + Public Async Function TestCSharp_PropertyFromGenericInterface3_Api(host As TestHost) As Task Dim input = @@ -403,7 +440,44 @@ public class M : I1, I3 - Await TestAPIAndFeature(input, kind, host) + Await TestAPI(input, host) + End Function + + + + Public Async Function TestCSharp_PropertyFromGenericInterface3_Streaming(host As TestHost) As Task + Dim input = + + + + +{ + T {|Definition:Name|} { get; set; } +} + +interface I2 +{ + int Name { get; set; } +} + +interface I3 : I2 +{ + new T {|Definition:$$Name|} { get; set; } +} + +public class M : I1, I3 +{ + public T {|Definition:Name|} { get; set; } + int I2.Name { get; set; } +} +]]> + + + + Await TestStreamingFeature(input, host) End Function diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs index cc6368c6e651e..d8bc7d3d04ad6 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs @@ -80,7 +80,7 @@ public FindReferencesSearchOptions With( var newAssociatePropertyReferencesWithSpecificAccessor = associatePropertyReferencesWithSpecificAccessor.HasValue ? associatePropertyReferencesWithSpecificAccessor.Value : AssociatePropertyReferencesWithSpecificAccessor; var newCascade = cascade.HasValue ? cascade.Value : Cascade; var newExplicit = @explicit.HasValue ? @explicit.Value : Explicit; - var newUnidirectionalHierarchyCascade = unidirectionalHierarchyCascade.HasValue ? unidirectionalHierarchyCascade.Value : Explicit; + var newUnidirectionalHierarchyCascade = unidirectionalHierarchyCascade.HasValue ? unidirectionalHierarchyCascade.Value : UnidirectionalHierarchyCascade; if (newAssociatePropertyReferencesWithSpecificAccessor == AssociatePropertyReferencesWithSpecificAccessor && newCascade == Cascade && From 90b5d77cf28c67a140065b62819cee5c304c86ca Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 3 Mar 2021 12:08:02 -0800 Subject: [PATCH 05/12] Split tests --- .../FindReferencesTests.AccessorSymbols.vb | 52 +++++- .../FindReferencesTests.NamedTypeSymbols.vb | 4 +- ...ndReferencesTests.OrdinaryMethodSymbols.vb | 39 +++- .../FindReferencesTests.PropertySymbols.vb | 8 +- .../FindReferencesTests.WinmdSymbols.vb | 168 +++++++++++++++++- ...dOrPropertyOrEventSymbolReferenceFinder.cs | 2 +- 6 files changed, 254 insertions(+), 19 deletions(-) diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.AccessorSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.AccessorSymbols.vb index 53964ab4503db..5471237eed52e 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.AccessorSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.AccessorSymbols.vb @@ -495,7 +495,57 @@ class Usages End Function - Public Async Function TestCSharpAccessor_FromNameOf_Feature1(host As TestHost) As Task + Public Async Function TestCSharpAccessor_FromNameOf1_Api(host As TestHost) As Task + Dim input = + + + +interface IC +{ + int {|Definition:Prop|} { get; set; } +} + +class C : IC +{ + public virtual int {|Definition:Prop|} { get; set; } +} + +class D : C +{ + public override int {|Definition:Prop|} { get => base.[|Prop|]; set => base.[|Prop|] = value; } +} + +class Usages +{ + void M() + { + IC ic; + var n1 = nameof(ic.[|$$Prop|]); + var v1 = ic.[|Prop|]; + ic.[|Prop|] = 1; + ic.[|Prop|]++; + + C c; + var n2 = nameof(c.[|Prop|]); + var v2 = c.[|Prop|]; + c.[|Prop|] = 1; + c.[|Prop|]++; + + D d; + var n3 = nameof(d.[|Prop|]); + var v3 = d.[|Prop|]; + d.[|Prop|] = 1; + d.[|Prop|]++; + } +} + + + + Await TestAPI(input, host) + End Function + + + Public Async Function TestCSharpAccessor_FromNameOf1_Feature(host As TestHost) As Task Dim input = diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb index 41d8aa7e87edc..03d2f45e0ffd7 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.NamedTypeSymbols.vb @@ -582,7 +582,7 @@ interface I class C : I, I { public void {|Definition:$$Goo|}(int x) { } - public void {|Definition:Goo|}(string x) { } + public void Goo(string x) { } } ]]> @@ -629,7 +629,7 @@ interface I class C : I, I { - public void {|Definition:Goo|}(int x) { } + public void Goo(int x) { } public void {|Definition:$$Goo|}(string x) { } } ]]> diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb index 47a684df7ded6..d03f562f23df0 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb @@ -394,7 +394,7 @@ class C End Function - Public Async Function TestOrdinaryMethodOverride_InMetadata(kind As TestKind, host As TestHost) As Task + Public Async Function TestOrdinaryMethodOverride_InMetadata_Api(host As TestHost) As Task Dim input = @@ -411,7 +411,28 @@ class C - Await TestAPIAndFeature(input, kind, host) + Await TestAPI(input, host) + End Function + + + Public Async Function TestOrdinaryMethodOverride_InMetadata_Feature(host As TestHost) As Task + Dim input = + + + + class C + { + // Will walk up to Object.ToString + public override string {|Definition:To$$String|}() { } + } + class O + { + public override string ToString() { } + } + + + + Await TestStreamingFeature(input, host) End Function @@ -484,7 +505,7 @@ class C End Function - Public Async Function TestOrdinaryMethodInterfaceInheritance_FromReference_Feature(kind As TestKind, host As TestHost) As Task + Public Async Function TestOrdinaryMethodInterfaceInheritance_FromReference_Feature(host As TestHost) As Task Dim input = @@ -496,7 +517,7 @@ class C class C1 : I1 { - public void {|Definition:Goo|}() + public void Goo() { } } @@ -585,7 +606,7 @@ class C interface I2 : I1 { - void {|Definition:Goo|}(); + void Goo(); void Bar(); } @@ -1530,9 +1551,9 @@ End Interface class Derived : Base, I { - public void {|Definition:F|}() + public void F() { - [|F|](); + F(); } } ]]> @@ -1589,7 +1610,7 @@ End Interface class Base : I { - void I.{|Definition:F|}() { } + void I.F() { } } class Derived : Base, I @@ -1653,7 +1674,7 @@ End Interface class Base : I { - void I.{|Definition:F|}() { } + void I.F() { } } class Derived : Base, I diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb index 499d0b229e08b..cc09e74a29f19 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.PropertySymbols.vb @@ -334,7 +334,7 @@ public class M : I1, I3 - Public Async Function TestCSharp_PropertyFromGenericInterface1_Streaming(host As TestHost) As Task + Public Async Function TestCSharp_PropertyFromGenericInterface1_Feature(host As TestHost) As Task Dim input = @@ -354,7 +354,7 @@ interface I2 interface I3 : I2 { - new T {|Definition:Name|} { get; set; } + new T Name { get; set; } } public class M : I1, I3 @@ -445,7 +445,7 @@ public class M : I1, I3 - Public Async Function TestCSharp_PropertyFromGenericInterface3_Streaming(host As TestHost) As Task + Public Async Function TestCSharp_PropertyFromGenericInterface3_FEature(host As TestHost) As Task Dim input = @@ -455,7 +455,7 @@ using System; interface I1 { - T {|Definition:Name|} { get; set; } + T Name { get; set; } } interface I2 diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.WinmdSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.WinmdSymbols.vb index 4906d091aa1ea..b61cf03b0bf7f 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.WinmdSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.WinmdSymbols.vb @@ -473,7 +473,7 @@ namespace SampleComponent End Function - Public Async Function TestWinmdVBAllIsWellTest(kind As TestKind, host As TestHost) As Task + Public Async Function TestWinmdVBAllIsWellTest_Api(host As TestHost) As Task Dim input = @@ -633,7 +633,171 @@ End Class - Await TestAPIAndFeature(input, kind, host) + Await TestAPI(input, host) + End Function + + + Public Async Function TestWinmdVBAllIsWellTest_Feature(host As TestHost) As Task + Dim input = + + + + +Imports System +Imports System.Collections +Imports System.Collections.Generic +Public Interface I + Sub Add(ByVal item As Integer) +End Interface + +Public NotInheritable Class Class1 + Implements I, IList(Of Integer) + + Public ReadOnly Property Count As Integer Implements ICollection(Of Integer).Count + Get + Throw New NotImplementedException() + End Get + End Property + + Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of Integer).IsReadOnly + Get + Throw New NotImplementedException() + End Get + End Property + + Default Public Property Item(index As Integer) As Integer Implements IList(Of Integer).Item + Get + Throw New NotImplementedException() + End Get + Set(value As Integer) + Throw New NotImplementedException() + End Set + End Property + + Public Sub Add(item As Integer) Implements I.Add + Throw New NotImplementedException() + End Sub + + Public Sub Clear() Implements ICollection(Of Integer).Clear + Throw New NotImplementedException() + End Sub + + Public Sub CopyTo(array() As Integer, arrayIndex As Integer) Implements ICollection(Of Integer).CopyTo + Throw New NotImplementedException() + End Sub + + Public Sub Insert(index As Integer, item As Integer) Implements IList(Of Integer).Insert + Throw New NotImplementedException() + End Sub + + Public Sub RemoveAt(index As Integer) Implements IList(Of Integer).RemoveAt + Throw New NotImplementedException() + End Sub + + Private Sub ICollection_Add(item As Integer) Implements ICollection(Of Integer).[|Add|] + Throw New NotImplementedException() + End Sub + + Public Function Contains(item As Integer) As Boolean Implements ICollection(Of Integer).Contains + Throw New NotImplementedException() + End Function + + Public Function GetEnumerator() As IEnumerator(Of Integer) Implements IEnumerable(Of Integer).GetEnumerator + Throw New NotImplementedException() + End Function + + Public Function IndexOf(item As Integer) As Integer Implements IList(Of Integer).IndexOf + Throw New NotImplementedException() + End Function + + Public Function Remove(item As Integer) As Boolean Implements ICollection(Of Integer).Remove + Throw New NotImplementedException() + End Function + + Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator + Throw New NotImplementedException() + End Function +End Class + +Public NotInheritable Class Class2 + Implements IList(Of Integer) + + Public ReadOnly Property Count As Integer Implements ICollection(Of Integer).Count + Get + Throw New NotImplementedException() + End Get + End Property + + Public ReadOnly Property IsReadOnly As Boolean Implements ICollection(Of Integer).IsReadOnly + Get + Throw New NotImplementedException() + End Get + End Property + + Default Public Property Item(index As Integer) As Integer Implements IList(Of Integer).Item + Get + Throw New NotImplementedException() + End Get + Set(value As Integer) + Throw New NotImplementedException() + End Set + End Property + + Public Sub {|Definition:Add|}(item As Integer) Implements ICollection(Of Integer).[|Add|] + Throw New NotImplementedException() + End Sub + + Public Sub Clear() Implements ICollection(Of Integer).Clear + Throw New NotImplementedException() + End Sub + + Public Sub CopyTo(array() As Integer, arrayIndex As Integer) Implements ICollection(Of Integer).CopyTo + Throw New NotImplementedException() + End Sub + + Public Sub Insert(index As Integer, item As Integer) Implements IList(Of Integer).Insert + Throw New NotImplementedException() + End Sub + + Public Sub RemoveAt(index As Integer) Implements IList(Of Integer).RemoveAt + Throw New NotImplementedException() + End Sub + + Public Function Contains(item As Integer) As Boolean Implements ICollection(Of Integer).Contains + Throw New NotImplementedException() + End Function + + Public Function GetEnumerator() As IEnumerator(Of Integer) Implements IEnumerable(Of Integer).GetEnumerator + Throw New NotImplementedException() + End Function + + Public Function IndexOf(item As Integer) As Integer Implements IList(Of Integer).IndexOf + Throw New NotImplementedException() + End Function + + Public Function Remove(item As Integer) As Boolean Implements ICollection(Of Integer).Remove + Throw New NotImplementedException() + End Function + + Private Function IEnumerable_GetEnumerator() As IEnumerator Implements IEnumerable.GetEnumerator + Throw New NotImplementedException() + End Function +End Class + +Public NotInheritable Class Test + Public Sub Goo() + Dim c1 = DirectCast(New Class1(), IList(Of Integer)) + Dim c2 As New Class1 + Dim c3 As New Class2 + c2.Add(3) + c1.[|Add|](3) + c3.[|$$Add|](3) + End Sub +End Class + + + + Await TestStreamingFeature(input, host) End Function End Class End Namespace diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs index 7fafd1390ea58..4b2948900236d 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/AbstractMethodOrPropertyOrEventSymbolReferenceFinder.cs @@ -50,7 +50,7 @@ protected AbstractMethodOrPropertyOrEventSymbolReferenceFinder() // Finally, methods can cascade through virtual/override inheritance. NOTE(cyrusn): // We only need to go up or down one level. Then, when we're finding references on // those members, we'll end up traversing the entire hierarchy. - var overrides = cascadeDirection.HasFlag(FindReferencesCascadeDirection.Up) + var overrides = cascadeDirection.HasFlag(FindReferencesCascadeDirection.Down) ? await SymbolFinder.FindOverridesArrayAsync(symbol, solution, projects, cancellationToken).ConfigureAwait(false) : ImmutableArray.Empty; From ca9783cfc2c6161fb8cffeec1c39cc85457c26dc Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 3 Mar 2021 12:13:14 -0800 Subject: [PATCH 06/12] Add tests --- ...ndReferencesTests.OrdinaryMethodSymbols.vb | 179 ++++++++++++++++++ 1 file changed, 179 insertions(+) diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb index d03f562f23df0..e4950a2ee212f 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb @@ -3607,5 +3607,184 @@ End Class Await TestAPIAndFeature(input, kind, TestHost.InProcess) ' TODO: support out of proc in tests: https://github.com/dotnet/roslyn/issues/50494 End Function + + Public Async Function TestFeatureHierarchyCascade1(host As TestHost) As Task + Dim input = + + + + interface I1 + { + void {|Definition:$$Goo|}(); + } + + interface I2 + { + void Goo(); + } + + class B : I1 + { + public virtual void {|Definition:Goo|}() {} + } + + class D1 : I1, I2 + { + public override void {|Definition:Goo|}() {} + } + + class D2 : I1 + { + public override void {|Definition:Goo|}() {} + } + + + + Await TestStreamingFeature(input, host) + End Function + + + Public Async Function TestFeatureHierarchyCascade2(host As TestHost) As Task + Dim input = + + + + interface I1 + { + void Goo(); + } + + interface I2 + { + void {|Definition:$$Goo|}(); + } + + class B : I1 + { + public virtual void Goo() {} + } + + class D1 : I1, I2 + { + public override void {|Definition:Goo|}() {} + } + + class D2 : I1 + { + public override void {|Definition:Goo|}() {} + } + + + + Await TestStreamingFeature(input, host) + End Function + + + Public Async Function TestFeatureHierarchyCascade3(host As TestHost) As Task + Dim input = + + + + interface I1 + { + void {|Definition:Goo|}(); + } + + interface I2 + { + void Goo(); + } + + class B : I1 + { + public virtual void {|Definition:$$Goo|}() {} + } + + class D1 : I1, I2 + { + public override void {|Definition:Goo|}() {} + } + + class D2 : I1 + { + public override void {|Definition:Goo|}() {} + } + + + + Await TestStreamingFeature(input, host) + End Function + + + Public Async Function TestFeatureHierarchyCascade4(host As TestHost) As Task + Dim input = + + + + interface I1 + { + void {|Definition:Goo|}(); + } + + interface I2 + { + void {|Definition:Goo|}(); + } + + class B : I1 + { + public virtual void {|Definition:Goo|}() {} + } + + class D1 : I1, I2 + { + public override void {|Definition:$$Goo|}() {} + } + + class D2 : I1 + { + public override void Goo() {} + } + + + + Await TestStreamingFeature(input, host) + End Function + + + Public Async Function TestFeatureHierarchyCascade5(host As TestHost) As Task + Dim input = + + + + interface I1 + { + void {|Definition:Goo|}(); + } + + interface I2 + { + void Goo(); + } + + class B : I1 + { + public virtual void {|Definition:Goo|}() {} + } + + class D1 : I1, I2 + { + public override void Goo() {} + } + + class D2 : I1 + { + public override void {|Definition:$$Goo|}() {} + } + + + + Await TestStreamingFeature(input, host) + End Function End Class End Namespace From 97bf4e685b18328012898d8963297093fdb8360b Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 3 Mar 2021 12:18:27 -0800 Subject: [PATCH 07/12] Add tests --- ...ndReferencesTests.OrdinaryMethodSymbols.vb | 22 +++++++++---------- .../CodeLens/CodeLensReferencesService.cs | 17 +++++++++----- 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb index e4950a2ee212f..9af2045e94161 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.OrdinaryMethodSymbols.vb @@ -3628,12 +3628,12 @@ End Class public virtual void {|Definition:Goo|}() {} } - class D1 : I1, I2 + class D1 : B, I1, I2 { public override void {|Definition:Goo|}() {} } - class D2 : I1 + class D2 : B, I1 { public override void {|Definition:Goo|}() {} } @@ -3664,14 +3664,14 @@ End Class public virtual void Goo() {} } - class D1 : I1, I2 + class D1 : B, I1, I2 { public override void {|Definition:Goo|}() {} } - class D2 : I1 + class D2 : B, I1 { - public override void {|Definition:Goo|}() {} + public override void Goo() {} } @@ -3700,12 +3700,12 @@ End Class public virtual void {|Definition:$$Goo|}() {} } - class D1 : I1, I2 + class D1 : B, I1, I2 { public override void {|Definition:Goo|}() {} } - class D2 : I1 + class D2 : B, I1 { public override void {|Definition:Goo|}() {} } @@ -3736,12 +3736,12 @@ End Class public virtual void {|Definition:Goo|}() {} } - class D1 : I1, I2 + class D1 : B, I1, I2 { public override void {|Definition:$$Goo|}() {} } - class D2 : I1 + class D2 : B, I1 { public override void Goo() {} } @@ -3772,12 +3772,12 @@ End Class public virtual void {|Definition:Goo|}() {} } - class D1 : I1, I2 + class D1 : B, I1, I2 { public override void Goo() {} } - class D2 : I1 + class D2 : B, I1 { public override void {|Definition:$$Goo|}() {} } diff --git a/src/Features/Core/Portable/CodeLens/CodeLensReferencesService.cs b/src/Features/Core/Portable/CodeLens/CodeLensReferencesService.cs index f25391ebe9b17..7ea7b73e82ff4 100644 --- a/src/Features/Core/Portable/CodeLens/CodeLensReferencesService.cs +++ b/src/Features/Core/Portable/CodeLens/CodeLensReferencesService.cs @@ -22,15 +22,20 @@ namespace Microsoft.CodeAnalysis.CodeLens internal sealed class CodeLensReferencesService : ICodeLensReferencesService { private static readonly SymbolDisplayFormat MethodDisplayFormat = - new( - typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, + new(typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces, memberOptions: SymbolDisplayMemberOptions.IncludeContainingType); - // Set ourselves as an implicit invocation of FindReferences. This will cause the finding operation to operate - // in serial, not parallel. We're running ephemerally in the BG and do not want to saturate the system with - // work that then slows the user down. + /// + /// Set ourselves as an implicit invocation of FindReferences. This will cause the finding operation to operate + /// in serial, not parallel. We're running ephemerally in the BG and do not want to saturate the system with + /// work that then slows the user down. Also, only process the inheritance hierarchy unidirectionally. We want + /// to find references that could actually call into a particular, not references to other members that could + /// never actually call into this member. + /// private static readonly FindReferencesSearchOptions s_nonParallelSearch = - FindReferencesSearchOptions.Default.With(@explicit: false); + FindReferencesSearchOptions.Default.With( + @explicit: false, + unidirectionalHierarchyCascade: true); private static async Task FindAsync(Solution solution, DocumentId documentId, SyntaxNode syntaxNode, Func> onResults, Func> onCapped, From 752e1b89c26e200571c690b7687640ba075e10ca Mon Sep 17 00:00:00 2001 From: CyrusNajmabadi Date: Wed, 3 Mar 2021 12:37:37 -0800 Subject: [PATCH 08/12] Update src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/LinkedFileReferenceFinder.cs --- .../FindReferences/Finders/LinkedFileReferenceFinder.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/LinkedFileReferenceFinder.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/LinkedFileReferenceFinder.cs index c1514949a5b05..90ac75ed84fa8 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/LinkedFileReferenceFinder.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/Finders/LinkedFileReferenceFinder.cs @@ -21,7 +21,6 @@ internal class LinkedFileReferenceFinder : IReferenceFinder var linkedSymbols = await SymbolFinder.FindLinkedSymbolsAsync(symbol, solution, cancellationToken).ConfigureAwait(false); return linkedSymbols.SelectAsArray(s => (s, cascadeDirection)); - } public Task> DetermineDocumentsToSearchAsync( From 51e960bb50986317ea1163876c259678cfa92579 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 3 Mar 2021 13:22:18 -0800 Subject: [PATCH 09/12] Fix flag --- .../FindReferences/FindReferencesCascadeDirection.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs index 6c1065d7672c5..3cc61554b7206 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesCascadeDirection.cs @@ -28,6 +28,6 @@ internal enum FindReferencesCascadeDirection internal static class FindReferencesCascadeDirectionExtensions { public static bool HasFlag(this FindReferencesCascadeDirection value, FindReferencesCascadeDirection flag) - => (value & flag) != flag; + => (value & flag) == flag; } } From e86ba0ce6e3bef34e7fb95c846a6e4bc0fcd1dd6 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Wed, 3 Mar 2021 13:30:40 -0800 Subject: [PATCH 10/12] UPdate comment --- .../FindReferences/FindReferencesSearchOptions.cs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs index d8bc7d3d04ad6..8b7d0e82f1c51 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs @@ -56,6 +56,21 @@ internal sealed class FindReferencesSearchOptions /// those interface methods. This is useful for cases where the client only wants references that could lead to /// this symbol actually being called into at runtime. /// + /// + /// There are cases where a client will not want this behavior. An example of that is 'Rename'. In rename, + /// there is a implicit link between members in a hierarchy with the same name (and appropriate signature). For example, in: + /// + /// + /// interface I { void Goo(); } + /// class C1 : I { public void Goo() { } } + /// class C2 : I { public void Goo() { } } + /// + /// + /// If C1.Goo is renamed, this will need to rename C2.Goo as well to keep the code properly + /// compiling. So, by default 'Rename' will cascade to all of these so it can appropriately update them. This + /// option is the more relevant with knowing if a particular reference would actually result in a call to the + /// original member, not if it has a relation to the original member. + /// [DataMember(Order = 3)] public bool UnidirectionalHierarchyCascade { get; } From 89f50dad0bc593719a6f8a39bd27a0d4e95f5dad Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 5 Mar 2021 11:29:53 -0800 Subject: [PATCH 11/12] Improve doc comment --- .../FindReferences/FindReferencesSearchOptions.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs index 8b7d0e82f1c51..54db82fde92c2 100644 --- a/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs +++ b/src/Workspaces/Core/Portable/FindSymbols/FindReferences/FindReferencesSearchOptions.cs @@ -113,10 +113,12 @@ public FindReferencesSearchOptions With( } /// - /// For IDE features, if the user starts searching on an accessor, then we want to give results associated with - /// the specific accessor. Otherwise, if they search on a property, then associate everything with the - /// property. We also only want to travel an inheritance hierarchy unidirectionally so that we only see potential - /// references that could actually reach this particular member. + /// Returns the appropriate options for a given symbol for the specific 'Find References' feature. This should + /// not be used for other features (like 'Rename'). For the 'Find References' feature, if the user starts + /// searching on an accessor, then we want to give results associated with the specific accessor. Otherwise, if + /// they search on a property, then associate everything with the property. We also only want to travel an + /// inheritance hierarchy unidirectionally so that we only see potential references that could actually reach + /// this particular member. /// public static FindReferencesSearchOptions GetFeatureOptionsForStartingSymbol(ISymbol symbol) => Default.With(associatePropertyReferencesWithSpecificAccessor: symbol.IsPropertyAccessor(), From ac03831072e3cf036112ea86e42aba038b2b0905 Mon Sep 17 00:00:00 2001 From: Cyrus Najmabadi Date: Fri, 5 Mar 2021 11:49:40 -0800 Subject: [PATCH 12/12] Simplify --- .../FindReferencesTests.WinmdSymbols.vb | 96 ++----------------- 1 file changed, 6 insertions(+), 90 deletions(-) diff --git a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.WinmdSymbols.vb b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.WinmdSymbols.vb index b61cf03b0bf7f..7d475e360faa9 100644 --- a/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.WinmdSymbols.vb +++ b/src/EditorFeatures/Test2/FindReferences/FindReferencesTests.WinmdSymbols.vb @@ -487,7 +487,7 @@ Public Interface I End Interface Public NotInheritable Class Class1 - Implements I, IList(Of Integer) + Implements I, ICollection(Of Integer) Public ReadOnly Property Count As Integer Implements ICollection(Of Integer).Count Get @@ -501,15 +501,6 @@ Public NotInheritable Class Class1 End Get End Property - Default Public Property Item(index As Integer) As Integer Implements IList(Of Integer).Item - Get - Throw New NotImplementedException() - End Get - Set(value As Integer) - Throw New NotImplementedException() - End Set - End Property - Public Sub Add(item As Integer) Implements I.Add Throw New NotImplementedException() End Sub @@ -522,14 +513,6 @@ Public NotInheritable Class Class1 Throw New NotImplementedException() End Sub - Public Sub Insert(index As Integer, item As Integer) Implements IList(Of Integer).Insert - Throw New NotImplementedException() - End Sub - - Public Sub RemoveAt(index As Integer) Implements IList(Of Integer).RemoveAt - Throw New NotImplementedException() - End Sub - Private Sub {|Definition:ICollection_Add|}(item As Integer) Implements ICollection(Of Integer).[|Add|] Throw New NotImplementedException() End Sub @@ -542,10 +525,6 @@ Public NotInheritable Class Class1 Throw New NotImplementedException() End Function - Public Function IndexOf(item As Integer) As Integer Implements IList(Of Integer).IndexOf - Throw New NotImplementedException() - End Function - Public Function Remove(item As Integer) As Boolean Implements ICollection(Of Integer).Remove Throw New NotImplementedException() End Function @@ -556,7 +535,7 @@ Public NotInheritable Class Class1 End Class Public NotInheritable Class Class2 - Implements IList(Of Integer) + Implements ICollection(Of Integer) Public ReadOnly Property Count As Integer Implements ICollection(Of Integer).Count Get @@ -570,15 +549,6 @@ Public NotInheritable Class Class2 End Get End Property - Default Public Property Item(index As Integer) As Integer Implements IList(Of Integer).Item - Get - Throw New NotImplementedException() - End Get - Set(value As Integer) - Throw New NotImplementedException() - End Set - End Property - Public Sub {|Definition:Add|}(item As Integer) Implements ICollection(Of Integer).[|Add|] Throw New NotImplementedException() End Sub @@ -591,14 +561,6 @@ Public NotInheritable Class Class2 Throw New NotImplementedException() End Sub - Public Sub Insert(index As Integer, item As Integer) Implements IList(Of Integer).Insert - Throw New NotImplementedException() - End Sub - - Public Sub RemoveAt(index As Integer) Implements IList(Of Integer).RemoveAt - Throw New NotImplementedException() - End Sub - Public Function Contains(item As Integer) As Boolean Implements ICollection(Of Integer).Contains Throw New NotImplementedException() End Function @@ -607,10 +569,6 @@ Public NotInheritable Class Class2 Throw New NotImplementedException() End Function - Public Function IndexOf(item As Integer) As Integer Implements IList(Of Integer).IndexOf - Throw New NotImplementedException() - End Function - Public Function Remove(item As Integer) As Boolean Implements ICollection(Of Integer).Remove Throw New NotImplementedException() End Function @@ -622,7 +580,7 @@ End Class Public NotInheritable Class Test Public Sub Goo() - Dim c1 = DirectCast(New Class1(), IList(Of Integer)) + Dim c1 = DirectCast(New Class1(), ICollection(Of Integer)) Dim c2 As New Class1 Dim c3 As New Class2 c2.Add(3) @@ -651,7 +609,7 @@ Public Interface I End Interface Public NotInheritable Class Class1 - Implements I, IList(Of Integer) + Implements I, ICollection(Of Integer) Public ReadOnly Property Count As Integer Implements ICollection(Of Integer).Count Get @@ -665,15 +623,6 @@ Public NotInheritable Class Class1 End Get End Property - Default Public Property Item(index As Integer) As Integer Implements IList(Of Integer).Item - Get - Throw New NotImplementedException() - End Get - Set(value As Integer) - Throw New NotImplementedException() - End Set - End Property - Public Sub Add(item As Integer) Implements I.Add Throw New NotImplementedException() End Sub @@ -686,14 +635,6 @@ Public NotInheritable Class Class1 Throw New NotImplementedException() End Sub - Public Sub Insert(index As Integer, item As Integer) Implements IList(Of Integer).Insert - Throw New NotImplementedException() - End Sub - - Public Sub RemoveAt(index As Integer) Implements IList(Of Integer).RemoveAt - Throw New NotImplementedException() - End Sub - Private Sub ICollection_Add(item As Integer) Implements ICollection(Of Integer).[|Add|] Throw New NotImplementedException() End Sub @@ -706,10 +647,6 @@ Public NotInheritable Class Class1 Throw New NotImplementedException() End Function - Public Function IndexOf(item As Integer) As Integer Implements IList(Of Integer).IndexOf - Throw New NotImplementedException() - End Function - Public Function Remove(item As Integer) As Boolean Implements ICollection(Of Integer).Remove Throw New NotImplementedException() End Function @@ -720,7 +657,7 @@ Public NotInheritable Class Class1 End Class Public NotInheritable Class Class2 - Implements IList(Of Integer) + Implements ICollection(Of Integer) Public ReadOnly Property Count As Integer Implements ICollection(Of Integer).Count Get @@ -734,15 +671,6 @@ Public NotInheritable Class Class2 End Get End Property - Default Public Property Item(index As Integer) As Integer Implements IList(Of Integer).Item - Get - Throw New NotImplementedException() - End Get - Set(value As Integer) - Throw New NotImplementedException() - End Set - End Property - Public Sub {|Definition:Add|}(item As Integer) Implements ICollection(Of Integer).[|Add|] Throw New NotImplementedException() End Sub @@ -755,14 +683,6 @@ Public NotInheritable Class Class2 Throw New NotImplementedException() End Sub - Public Sub Insert(index As Integer, item As Integer) Implements IList(Of Integer).Insert - Throw New NotImplementedException() - End Sub - - Public Sub RemoveAt(index As Integer) Implements IList(Of Integer).RemoveAt - Throw New NotImplementedException() - End Sub - Public Function Contains(item As Integer) As Boolean Implements ICollection(Of Integer).Contains Throw New NotImplementedException() End Function @@ -771,10 +691,6 @@ Public NotInheritable Class Class2 Throw New NotImplementedException() End Function - Public Function IndexOf(item As Integer) As Integer Implements IList(Of Integer).IndexOf - Throw New NotImplementedException() - End Function - Public Function Remove(item As Integer) As Boolean Implements ICollection(Of Integer).Remove Throw New NotImplementedException() End Function @@ -786,7 +702,7 @@ End Class Public NotInheritable Class Test Public Sub Goo() - Dim c1 = DirectCast(New Class1(), IList(Of Integer)) + Dim c1 = DirectCast(New Class1(), ICollection(Of Integer)) Dim c2 As New Class1 Dim c3 As New Class2 c2.Add(3)