提交 34a820cd 编写于 作者: C Cyrus Najmabadi

Limit cascading when finding the set of members to update when switching member to be explicit.

上级 f94a0963
...@@ -4,7 +4,6 @@ ...@@ -4,7 +4,6 @@
#nullable enable #nullable enable
using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Composition; using System.Composition;
using System.Linq; using System.Linq;
...@@ -49,11 +48,18 @@ protected override bool CheckMemberCanBeConverted(ISymbol member) ...@@ -49,11 +48,18 @@ protected override bool CheckMemberCanBeConverted(ISymbol member)
{ {
var solution = project.Solution; var solution = project.Solution;
// We don't need to cascade in this search, we're only explicitly looking for direct
// calls to our instance member (and not anyone else already calling through the
// interface already).
//
// This can save a lot of extra time spent finding callers, especially for methods with
// high fan-out (like IDisposable.Dispose()).
var findRefsOptions = FindReferencesSearchOptions.Default.WithCascade(false);
var references = await SymbolFinder.FindReferencesAsync( var references = await SymbolFinder.FindReferencesAsync(
new SymbolAndProjectId(implMember, project.Id), new SymbolAndProjectId(implMember, project.Id),
solution, cancellationToken).ConfigureAwait(false); solution, findRefsOptions, cancellationToken).ConfigureAwait(false);
var implReferences = references.FirstOrDefault(r => implMember.Equals(r.Definition)); var implReferences = references.FirstOrDefault();
if (implReferences == null) if (implReferences == null)
return; return;
......
// 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 class FindReferencesOptions
{
public static readonly FindReferencesOptions Default = new FindReferencesOptions(
cascade: true);
/// <summary>
/// Whether or not we should automatically cascade to members when doing a find-references
/// search. Default to <see langword="true"/>.
/// </summary>
public readonly bool Cascade;
public FindReferencesOptions(bool cascade)
{
Cascade = cascade;
}
}
}
...@@ -2,17 +2,16 @@ ...@@ -2,17 +2,16 @@
// The .NET Foundation licenses this file to you under the MIT license. // The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System.Collections.Generic;
using Microsoft.CodeAnalysis.FindSymbols.Finders;
using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.FindSymbols namespace Microsoft.CodeAnalysis.FindSymbols
{ {
internal class FindReferencesSearchOptions internal class FindReferencesSearchOptions
{ {
public static readonly FindReferencesSearchOptions Default = public static readonly FindReferencesSearchOptions Default =
new FindReferencesSearchOptions(associatePropertyReferencesWithSpecificAccessor: false); new FindReferencesSearchOptions(
associatePropertyReferencesWithSpecificAccessor: false,
cascade: true);
/// <summary> /// <summary>
/// When searching for property, associate specific references we find to the relevant /// When searching for property, associate specific references we find to the relevant
...@@ -28,17 +27,25 @@ internal class FindReferencesSearchOptions ...@@ -28,17 +27,25 @@ internal class FindReferencesSearchOptions
/// </summary> /// </summary>
public bool AssociatePropertyReferencesWithSpecificAccessor { get; } public bool AssociatePropertyReferencesWithSpecificAccessor { get; }
/// <summary>
/// Whether or not we should cascade from the original search symbol to new symbols as we're
/// doing the find-references search.
/// </summary>
public bool Cascade { get; }
public FindReferencesSearchOptions( public FindReferencesSearchOptions(
bool associatePropertyReferencesWithSpecificAccessor) bool associatePropertyReferencesWithSpecificAccessor,
bool cascade)
{ {
AssociatePropertyReferencesWithSpecificAccessor = associatePropertyReferencesWithSpecificAccessor; AssociatePropertyReferencesWithSpecificAccessor = associatePropertyReferencesWithSpecificAccessor;
Cascade = cascade;
} }
public FindReferencesSearchOptions WithAssociatePropertyReferencesWithSpecificAccessor( public FindReferencesSearchOptions WithAssociatePropertyReferencesWithSpecificAccessor(bool associatePropertyReferencesWithSpecificAccessor)
bool associatePropertyReferencesWithSpecificAccessor) => new FindReferencesSearchOptions(associatePropertyReferencesWithSpecificAccessor, Cascade);
{
return new FindReferencesSearchOptions(associatePropertyReferencesWithSpecificAccessor); public FindReferencesSearchOptions WithCascade(bool cascade)
} => new FindReferencesSearchOptions(AssociatePropertyReferencesWithSpecificAccessor, cascade);
/// <summary> /// <summary>
/// For IDE features, if the user starts searching on an accessor, then we want to give /// For IDE features, if the user starts searching on an accessor, then we want to give
...@@ -46,8 +53,6 @@ internal class FindReferencesSearchOptions ...@@ -46,8 +53,6 @@ internal class FindReferencesSearchOptions
/// then associate everything with the property. /// then associate everything with the property.
/// </summary> /// </summary>
public static FindReferencesSearchOptions GetFeatureOptionsForStartingSymbol(ISymbol symbol) public static FindReferencesSearchOptions GetFeatureOptionsForStartingSymbol(ISymbol symbol)
=> symbol.IsPropertyAccessor() => Default.WithAssociatePropertyReferencesWithSpecificAccessor(symbol.IsPropertyAccessor());
? new FindReferencesSearchOptions(associatePropertyReferencesWithSpecificAccessor: true)
: FindReferencesSearchOptions.Default;
} }
} }
...@@ -825,12 +825,15 @@ public override Task<ImmutableArray<Project>> DetermineProjectsToSearchAsync(ISy ...@@ -825,12 +825,15 @@ public override Task<ImmutableArray<Project>> DetermineProjectsToSearchAsync(ISy
SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet<Project> projects, SymbolAndProjectId symbolAndProjectId, Solution solution, IImmutableSet<Project> projects,
FindReferencesSearchOptions options, CancellationToken cancellationToken) FindReferencesSearchOptions options, CancellationToken cancellationToken)
{ {
var symbol = symbolAndProjectId.Symbol; if (options.Cascade)
if (symbol is TSymbol typedSymbol && CanFind(typedSymbol))
{ {
return DetermineCascadedSymbolsAsync( var symbol = symbolAndProjectId.Symbol;
symbolAndProjectId.WithSymbol(typedSymbol), if (symbol is TSymbol typedSymbol && CanFind(typedSymbol))
solution, projects, options, cancellationToken); {
return DetermineCascadedSymbolsAsync(
symbolAndProjectId.WithSymbol(typedSymbol),
solution, projects, options, cancellationToken);
}
} }
return SpecializedTasks.EmptyImmutableArray<SymbolAndProjectId>(); return SpecializedTasks.EmptyImmutableArray<SymbolAndProjectId>();
......
...@@ -30,17 +30,19 @@ public static partial class SymbolFinder ...@@ -30,17 +30,19 @@ public static partial class SymbolFinder
return FindReferencesAsync(new SymbolAndProjectId(symbol, projectId: null), solution, cancellationToken); return FindReferencesAsync(new SymbolAndProjectId(symbol, projectId: null), solution, cancellationToken);
} }
internal static Task<IEnumerable<ReferencedSymbol>> FindReferencesAsync(SymbolAndProjectId symbolAndProjectId, Solution solution, CancellationToken cancellationToken)
=> FindReferencesAsync(symbolAndProjectId, solution, FindReferencesSearchOptions.Default, cancellationToken);
internal static async Task<IEnumerable<ReferencedSymbol>> FindReferencesAsync( internal static async Task<IEnumerable<ReferencedSymbol>> FindReferencesAsync(
SymbolAndProjectId symbolAndProjectId, SymbolAndProjectId symbolAndProjectId,
Solution solution, Solution solution,
CancellationToken cancellationToken = default) FindReferencesSearchOptions options,
CancellationToken cancellationToken)
{ {
var progressCollector = new StreamingProgressCollector(StreamingFindReferencesProgress.Instance); var progressCollector = new StreamingProgressCollector(StreamingFindReferencesProgress.Instance);
await FindReferencesAsync( await FindReferencesAsync(
symbolAndProjectId, symbolAndProjectId, solution, progressCollector,
solution, progress: progressCollector, documents: null, documents: null, options, cancellationToken).ConfigureAwait(false);
options: FindReferencesSearchOptions.Default,
cancellationToken: cancellationToken).ConfigureAwait(false);
return progressCollector.GetReferencedSymbols(); return progressCollector.GetReferencedSymbols();
} }
......
...@@ -19,18 +19,22 @@ namespace Microsoft.CodeAnalysis.Remote ...@@ -19,18 +19,22 @@ namespace Microsoft.CodeAnalysis.Remote
internal class SerializableFindReferencesSearchOptions internal class SerializableFindReferencesSearchOptions
{ {
public bool AssociatePropertyReferencesWithSpecificAccessor; public bool AssociatePropertyReferencesWithSpecificAccessor;
public bool Cascade;
public static SerializableFindReferencesSearchOptions Dehydrate(FindReferencesSearchOptions options) public static SerializableFindReferencesSearchOptions Dehydrate(FindReferencesSearchOptions options)
{ {
return new SerializableFindReferencesSearchOptions return new SerializableFindReferencesSearchOptions
{ {
AssociatePropertyReferencesWithSpecificAccessor = options.AssociatePropertyReferencesWithSpecificAccessor AssociatePropertyReferencesWithSpecificAccessor = options.AssociatePropertyReferencesWithSpecificAccessor,
Cascade = options.Cascade,
}; };
} }
public FindReferencesSearchOptions Rehydrate() public FindReferencesSearchOptions Rehydrate()
{ {
return new FindReferencesSearchOptions(AssociatePropertyReferencesWithSpecificAccessor); return new FindReferencesSearchOptions(
associatePropertyReferencesWithSpecificAccessor: AssociatePropertyReferencesWithSpecificAccessor,
cascade: Cascade);
} }
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册