Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Remove SymbolAndProjectId #43483

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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ private partial class SymbolInlineRenameInfo : IInlineRenameInfoWithFileRename
public bool CanRename { get; }
public string LocalizedErrorMessage { get; }
public TextSpan TriggerSpan { get; }
public SymbolAndProjectId RenameSymbolAndProjectId { get; }
public bool HasOverloads { get; }
public bool ForceRenameOverloads { get; }

Expand All @@ -55,13 +54,13 @@ private partial class SymbolInlineRenameInfo : IInlineRenameInfoWithFileRename
/// </summary>
public ImmutableArray<DocumentSpan> DefinitionLocations { get; }

public ISymbol RenameSymbol => RenameSymbolAndProjectId.Symbol;
public ISymbol RenameSymbol { get; }

public SymbolInlineRenameInfo(
IEnumerable<IRefactorNotifyService> refactorNotifyServices,
Document document,
TextSpan triggerSpan,
SymbolAndProjectId renameSymbolAndProjectId,
ISymbol renameSymbol,
bool forceRenameOverloads,
ImmutableArray<DocumentSpan> definitionLocations,
CancellationToken cancellationToken)
Expand All @@ -70,9 +69,9 @@ public SymbolInlineRenameInfo(

_refactorNotifyServices = refactorNotifyServices;
_document = document;
this.RenameSymbolAndProjectId = renameSymbolAndProjectId;
this.RenameSymbol = renameSymbol;

this.HasOverloads = RenameLocations.GetOverloadedSymbols(this.RenameSymbolAndProjectId).Any();
this.HasOverloads = RenameLocations.GetOverloadedSymbols(this.RenameSymbol).Any();
this.ForceRenameOverloads = forceRenameOverloads;

_isRenamingAttributePrefix = CanRenameAttributePrefix(document, triggerSpan, cancellationToken);
Expand Down Expand Up @@ -209,7 +208,7 @@ public Task<IInlineRenameLocationSet> FindRenameLocationsAsync(OptionSet optionS
// If this is the first call, then just start finding the initial set of rename
// locations.
_underlyingFindRenameLocationsTask = RenameLocations.FindAsync(
this.RenameSymbolAndProjectId, _document.Project.Solution, optionSet, cancellationToken);
this.RenameSymbol, _document.Project.Solution, optionSet, cancellationToken);
renameTask = _underlyingFindRenameLocationsTask;

// null out the option set. We don't need it anymore, and this will ensure
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -91,8 +91,7 @@ internal static async Task<IInlineRenameInfo> GetRenameInfoAsync(
}
}

var symbolAndProjectId = await RenameLocations.ReferenceProcessing.GetRenamableSymbolAsync(document, triggerToken.SpanStart, cancellationToken: cancellationToken).ConfigureAwait(false);
var symbol = symbolAndProjectId.Symbol;
var symbol = await RenameLocations.ReferenceProcessing.GetRenamableSymbolAsync(document, triggerToken.SpanStart, cancellationToken: cancellationToken).ConfigureAwait(false);
if (symbol == null)
{
return new FailureInlineRenameInfo(EditorFeaturesResources.You_cannot_rename_this_element);
Expand Down Expand Up @@ -200,7 +199,7 @@ internal static async Task<IInlineRenameInfo> GetRenameInfoAsync(

return new SymbolInlineRenameInfo(
refactorNotifyServices, document, triggerToken.Span,
symbolAndProjectId, forceRenameOverloads, documentSpans.ToImmutableAndFree(), cancellationToken);
symbol, forceRenameOverloads, documentSpans.ToImmutableAndFree(), cancellationToken);
}

private async Task<SyntaxToken> GetTriggerTokenAsync(Document document, int position, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,30 +94,30 @@ public FindReferencesProgressAdapter(
// used by the FAR engine to the INavigableItems used by the streaming FAR
// feature.

private async Task<DefinitionItem> GetDefinitionItemAsync(SymbolAndProjectId definition)
private async Task<DefinitionItem> GetDefinitionItemAsync(ISymbol definition)
{
using (await _gate.DisposableWaitAsync(_context.CancellationToken).ConfigureAwait(false))
var cancellationToken = _context.CancellationToken;
using (await _gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false))
{
if (!_definitionToItem.TryGetValue(definition.Symbol, out var definitionItem))
if (!_definitionToItem.TryGetValue(definition, out var definitionItem))
{
definitionItem = await definition.Symbol.ToClassifiedDefinitionItemAsync(
_solution.GetProject(definition.ProjectId), includeHiddenLocations: false,
_options, _context.CancellationToken).ConfigureAwait(false);
definitionItem = await definition.ToClassifiedDefinitionItemAsync(
_solution, includeHiddenLocations: false, _options, _context.CancellationToken).ConfigureAwait(false);

_definitionToItem[definition.Symbol] = definitionItem;
_definitionToItem[definition] = definitionItem;
}

return definitionItem;
}
}

public async Task OnDefinitionFoundAsync(SymbolAndProjectId definition)
public async Task OnDefinitionFoundAsync(ISymbol definition)
{
var definitionItem = await GetDefinitionItemAsync(definition).ConfigureAwait(false);
await _context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false);
}

public async Task OnReferenceFoundAsync(SymbolAndProjectId definition, ReferenceLocation location)
public async Task OnReferenceFoundAsync(ISymbol definition, ReferenceLocation location)
{
var definitionItem = await GetDefinitionItemAsync(definition).ConfigureAwait(false);
var referenceItem = await location.TryCreateSourceReferenceItemAsync(
Expand Down
35 changes: 14 additions & 21 deletions src/EditorFeatures/Core/FindUsages/AbstractFindUsagesService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ await context.ReportMessageAsync(
return;
}

var (solution, symbolAndProjectId, implementations, message) = tupleOpt.Value;
var (solution, symbol, implementations, message) = tupleOpt.Value;
if (message != null)
{
await context.ReportMessageAsync(message).ConfigureAwait(false);
Expand All @@ -47,13 +47,13 @@ await context.ReportMessageAsync(

await context.SetSearchTitleAsync(
string.Format(EditorFeaturesResources._0_implementations,
FindUsagesHelpers.GetDisplayName(symbolAndProjectId.Symbol))).ConfigureAwait(false);
FindUsagesHelpers.GetDisplayName(symbol))).ConfigureAwait(false);

foreach (var implementation in implementations)
{
var definitionItem = await implementation.Symbol.ToClassifiedDefinitionItemAsync(
solution.GetProject(implementation.ProjectId), includeHiddenLocations: false,
FindReferencesSearchOptions.Default, cancellationToken: cancellationToken).ConfigureAwait(false);
var definitionItem = await implementation.ToClassifiedDefinitionItemAsync(
solution, includeHiddenLocations: false, FindReferencesSearchOptions.Default, cancellationToken).ConfigureAwait(false);

await context.OnDefinitionFoundAsync(definitionItem).ConfigureAwait(false);
}
}
Expand Down Expand Up @@ -121,16 +121,16 @@ private async Task FindSymbolReferencesAsync(
cancellationToken.ThrowIfCancellationRequested();

// Find the symbol we want to search and the solution we want to search in.
var symbolAndProjectOpt = await FindUsagesHelpers.GetRelevantSymbolAndProjectAtPositionAsync(
var symbolAndSolutionOpt = await FindUsagesHelpers.GetRelevantSymbolAndSolutionAtPositionAsync(
document, position, cancellationToken).ConfigureAwait(false);
if (symbolAndProjectOpt == null)
if (symbolAndSolutionOpt == null)
return;

var (symbol, project) = symbolAndProjectOpt.Value;
var (symbol, solution) = symbolAndSolutionOpt.Value;

await FindSymbolReferencesAsync(
_threadingContext, context,
symbol, project,
symbol, solution,
cancellationToken).ConfigureAwait(false);
}

Expand All @@ -140,9 +140,9 @@ await FindSymbolReferencesAsync(
/// </summary>
public static async Task FindSymbolReferencesAsync(
IThreadingContext threadingContext, IFindUsagesContext context,
ISymbol symbol, Project project, CancellationToken cancellationToken)
ISymbol symbol, Solution solution, CancellationToken cancellationToken)
{
var monikerUsagesService = project.Solution.Workspace.Services.GetRequiredService<IFindSymbolMonikerUsagesService>();
var monikerUsagesService = solution.Workspace.Services.GetRequiredService<IFindSymbolMonikerUsagesService>();

await context.SetSearchTitleAsync(string.Format(EditorFeaturesResources._0_references,
FindUsagesHelpers.GetDisplayName(symbol))).ConfigureAwait(false);
Expand All @@ -153,20 +153,13 @@ await context.SetSearchTitleAsync(string.Format(EditorFeaturesResources._0_refer
// engine will push results into the 'progress' instance passed into it.
// We'll take those results, massage them, and forward them along to the
// FindReferencesContext instance we were given.
var progress = new FindReferencesProgressAdapter(threadingContext, solution, context, options);
var normalFindReferencesTask = SymbolFinder.FindReferencesAsync(
SymbolAndProjectId.Create(symbol, project.Id),
project.Solution,
new FindReferencesProgressAdapter(threadingContext, project.Solution, context, options),
documents: null,
options,
cancellationToken);
symbol, solution, progress, documents: null, options, cancellationToken);

// Kick off work to search the online code index system in parallel
var codeIndexReferencesTask = FindSymbolMonikerReferencesAsync(
monikerUsagesService,
symbol,
context,
cancellationToken);
monikerUsagesService, symbol, context, cancellationToken);

await Task.WhenAll(normalFindReferencesTask, codeIndexReferencesTask).ConfigureAwait(false);
}
Expand Down
66 changes: 32 additions & 34 deletions src/EditorFeatures/Core/FindUsages/FindUsagesHelpers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public static string GetDisplayName(ISymbol symbol)
/// there may be symbol mapping involved (for example in Metadata-As-Source
/// scenarios).
/// </summary>
public static async Task<(ISymbol symbol, Project project)?> GetRelevantSymbolAndProjectAtPositionAsync(
public static async Task<(ISymbol symbol, Solution solution)?> GetRelevantSymbolAndSolutionAtPositionAsync(
Document document, int position, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
Expand All @@ -49,31 +49,30 @@ public static string GetDisplayName(ISymbol symbol)
if (mapping == null)
return null;

return (mapping.Symbol, mapping.Project);
return (mapping.Symbol, mapping.Project.Solution);
}

public static async Task<(Solution solution, SymbolAndProjectId symboAndProjectId, ImmutableArray<SymbolAndProjectId> implementations, string message)?> FindSourceImplementationsAsync(Document document, int position, CancellationToken cancellationToken)
public static async Task<(Solution solution, ISymbol symbol, ImmutableArray<ISymbol> implementations, string message)?> FindSourceImplementationsAsync(Document document, int position, CancellationToken cancellationToken)
{
var symbolAndProjectOpt = await GetRelevantSymbolAndProjectAtPositionAsync(
var symbolAndSolutionOpt = await GetRelevantSymbolAndSolutionAtPositionAsync(
document, position, cancellationToken).ConfigureAwait(false);
if (symbolAndProjectOpt == null)
if (symbolAndSolutionOpt == null)
return null;

var (symbol, project) = symbolAndProjectOpt.Value;
var symbolAndProjectId = new SymbolAndProjectId(symbol, project.Id);
var (symbol, solution) = symbolAndSolutionOpt.Value;
return await FindSourceImplementationsAsync(
project.Solution, symbolAndProjectId, cancellationToken).ConfigureAwait(false);
solution, symbol, cancellationToken).ConfigureAwait(false);
}

private static async Task<(Solution solution, SymbolAndProjectId symbolAndProjectId, ImmutableArray<SymbolAndProjectId> implementations, string message)?> FindSourceImplementationsAsync(
Solution solution, SymbolAndProjectId symbolAndProjectId, CancellationToken cancellationToken)
private static async Task<(Solution solution, ISymbol symbol, ImmutableArray<ISymbol> implementations, string message)?> FindSourceImplementationsAsync(
Solution solution, ISymbol symbol, CancellationToken cancellationToken)
{
var builder = new HashSet<SymbolAndProjectId>(SymbolAndProjectIdComparer.SymbolEquivalenceInstance);
var builder = new HashSet<ISymbol>(SymbolEquivalenceComparer.Instance);

// If we're in a linked file, try to find all the symbols this links to, and find all the implementations of
// each of those linked symbols. De-dupe the results so the user only gets unique results.
var linkedSymbols = await SymbolFinder.FindLinkedSymbolsAsync(
solution, symbolAndProjectId, cancellationToken).ConfigureAwait(false);
symbol, solution, cancellationToken).ConfigureAwait(false);

foreach (var linkedSymbol in linkedSymbols)
{
Expand All @@ -84,69 +83,68 @@ public static string GetDisplayName(ISymbol symbol)
var result = builder.ToImmutableArray();
var message = result.IsEmpty ? EditorFeaturesResources.The_symbol_has_no_implementations : null;

return (solution, symbolAndProjectId, result, message);
return (solution, symbol, result, message);
}

private static async Task<ImmutableArray<SymbolAndProjectId>> FindSourceImplementationsWorkerAsync(
Solution solution, SymbolAndProjectId symbolAndProjectId, CancellationToken cancellationToken)
private static async Task<ImmutableArray<ISymbol>> FindSourceImplementationsWorkerAsync(
Solution solution, ISymbol symbol, CancellationToken cancellationToken)
{
var implementations = await FindSourceAndMetadataImplementationsAsync(solution, symbolAndProjectId, cancellationToken).ConfigureAwait(false);
return implementations.WhereAsArray(s => s.Symbol.Locations.Any(l => l.IsInSource));
var implementations = await FindSourceAndMetadataImplementationsAsync(solution, symbol, cancellationToken).ConfigureAwait(false);
return implementations.WhereAsArray(s => s.Locations.Any(l => l.IsInSource));
}

private static async Task<ImmutableArray<SymbolAndProjectId>> FindSourceAndMetadataImplementationsAsync(
Solution solution, SymbolAndProjectId symbolAndProjectId, CancellationToken cancellationToken)
private static async Task<ImmutableArray<ISymbol>> FindSourceAndMetadataImplementationsAsync(
Solution solution, ISymbol symbol, CancellationToken cancellationToken)
{
if (symbolAndProjectId.Symbol.IsInterfaceType() || symbolAndProjectId.Symbol.IsImplementableMember())
if (symbol.IsInterfaceType() || symbol.IsImplementableMember())
{
var implementations = await SymbolFinder.FindImplementationsAsync(
symbolAndProjectId, solution, cancellationToken: cancellationToken).ConfigureAwait(false);
symbol, solution, cancellationToken: cancellationToken).ConfigureAwait(false);

// It's important we use a HashSet here -- we may have cases in an inheritance hierarchy where more than one method
// in an overrides chain implements the same interface method, and we want to duplicate those. The easiest way to do it
// is to just use a HashSet.
var implementationsAndOverrides = new HashSet<SymbolAndProjectId>();
var implementationsAndOverrides = new HashSet<ISymbol>();

foreach (var implementation in implementations)
{
implementationsAndOverrides.Add(implementation);

// FindImplementationsAsync will only return the base virtual/abstract method, not that method and the overrides
// of the method. We should also include those.
if (implementation.Symbol.IsOverridable())
if (implementation.IsOverridable())
{
var overrides = await SymbolFinder.FindOverridesAsync(
implementation, solution, cancellationToken: cancellationToken).ConfigureAwait(false);
implementationsAndOverrides.AddRange(overrides);
}
}

if (!symbolAndProjectId.Symbol.IsInterfaceType() &&
!symbolAndProjectId.Symbol.IsAbstract)
if (!symbol.IsInterfaceType() &&
!symbol.IsAbstract)
{
implementationsAndOverrides.Add(symbolAndProjectId);
implementationsAndOverrides.Add(symbol);
}

return implementationsAndOverrides.ToImmutableArray();
}
else if (symbolAndProjectId.Symbol is INamedTypeSymbol { TypeKind: TypeKind.Class } namedType)
else if (symbol is INamedTypeSymbol { TypeKind: TypeKind.Class } namedType)
{
var derivedClasses = await SymbolFinder.FindDerivedClassesAsync(
symbolAndProjectId.WithSymbol(namedType),
solution, cancellationToken: cancellationToken).ConfigureAwait(false);
namedType, solution, cancellationToken: cancellationToken).ConfigureAwait(false);

return derivedClasses.SelectAsArray(s => (SymbolAndProjectId)s).Concat(symbolAndProjectId);
return derivedClasses.Concat(symbol).ToImmutableArray();
}
else if (symbolAndProjectId.Symbol.IsOverridable())
else if (symbol.IsOverridable())
{
var overrides = await SymbolFinder.FindOverridesAsync(
symbolAndProjectId, solution, cancellationToken: cancellationToken).ConfigureAwait(false);
return overrides.Concat(symbolAndProjectId);
symbol, solution, cancellationToken: cancellationToken).ConfigureAwait(false);
return overrides.Concat(symbol).ToImmutableArray();
}
else
{
// This is something boring like a regular method or type, so we'll just go there directly
return ImmutableArray.Create(symbolAndProjectId);
return ImmutableArray.Create(symbol);
}
}

Expand Down
Loading