Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 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 @@ -23,39 +23,39 @@ internal sealed class WrappedAddImportFixData

public ImmutableArray<TextChange> TextChanges => Underlying.TextChanges;

public string Title => Underlying.Title;
public string? Title => Underlying.Title;

public ImmutableArray<string> Tags => Underlying.Tags;

#region When adding P2P references.

public ProjectId ProjectReferenceToAdd => Underlying.ProjectReferenceToAdd;
public ProjectId? ProjectReferenceToAdd => Underlying.ProjectReferenceToAdd;

#endregion

#region When adding a metadata reference

public ProjectId PortableExecutableReferenceProjectId => Underlying.PortableExecutableReferenceProjectId;
public ProjectId? PortableExecutableReferenceProjectId => Underlying.PortableExecutableReferenceProjectId;

public string PortableExecutableReferenceFilePathToAdd => Underlying.PortableExecutableReferenceFilePathToAdd;
public string? PortableExecutableReferenceFilePathToAdd => Underlying.PortableExecutableReferenceFilePathToAdd;

#endregion

#region When adding an assembly reference

public string AssemblyReferenceAssemblyName => Underlying.AssemblyReferenceAssemblyName;
public string? AssemblyReferenceAssemblyName => Underlying.AssemblyReferenceAssemblyName;

public string AssemblyReferenceFullyQualifiedTypeName => Underlying.AssemblyReferenceFullyQualifiedTypeName;
public string? AssemblyReferenceFullyQualifiedTypeName => Underlying.AssemblyReferenceFullyQualifiedTypeName;

#endregion

#region When adding a package reference

public string PackageSource => Underlying.PackageSource;
public string? PackageSource => Underlying.PackageSource;

public string PackageName => Underlying.PackageName;
public string? PackageName => Underlying.PackageName;

public string PackageVersionOpt => Underlying.PackageVersionOpt;
public string? PackageVersionOpt => Underlying.PackageVersionOpt;

#endregion

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -177,27 +177,27 @@ private async Task<ImmutableArray<Reference>> FindResultsAsync(
{
var allReferences = new ConcurrentQueue<Reference>();

// First search the current project to see if any symbols (source or metadata) match the
// search string.
await FindResultsInAllSymbolsInStartingProjectAsync(
allReferences, finder, exact, cancellationToken).ConfigureAwait(false);

// Only bother doing this for host workspaces. We don't want this for
// things like the Interactive workspace as we can't even add project
// references to the interactive window. We could consider adding metadata
// references with #r in the future.
// First search the current project to see if any symbols (source or metadata) match the search string.
var searchOptions = finder.Options.SearchOptions;
if (searchOptions.SearchReferencedProjectSymbols)
await FindResultsInAllSymbolsInStartingProjectAsync(allReferences, finder, exact, cancellationToken).ConfigureAwait(false);

// Only bother doing this for host workspaces. We don't want this for things like the Interactive workspace as
// we can't even add project references to the interactive window. We could consider adding metadata references
// with #r in the future.
if (IsHostOrRemoteWorkspace(project))
{
// Now search unreferenced projects, and see if they have any source symbols that match
// the search string.
await FindResultsInUnreferencedProjectSourceSymbolsAsync(projectToAssembly, project, allReferences, maxResults, finder, exact, cancellationToken).ConfigureAwait(false);
// Now search unreferenced projects, and see if they have any source symbols that match the search string.
if (searchOptions.SearchUnreferencedProjectSourceSymbols)
await FindResultsInUnreferencedProjectSourceSymbolsAsync(projectToAssembly, project, allReferences, maxResults, finder, exact, cancellationToken).ConfigureAwait(false);

// Finally, check and see if we have any metadata symbols that match the search string.
await FindResultsInUnreferencedMetadataSymbolsAsync(referenceToCompilation, project, allReferences, maxResults, finder, exact, cancellationToken).ConfigureAwait(false);
// Next, check and see if we have any metadata symbols that match the search string.
if (searchOptions.SearchUnreferencedMetadataSymbols)
await FindResultsInUnreferencedMetadataSymbolsAsync(referenceToCompilation, project, allReferences, maxResults, finder, exact, cancellationToken).ConfigureAwait(false);

// We only support searching NuGet in an exact manner currently.
if (exact)
await finder.FindNugetOrReferenceAssemblyReferencesAsync(allReferences, cancellationToken).ConfigureAwait(false);
// Finally, search for nuget or reference assembly symbols that match the search string.
if (searchOptions.SearchNuGetPackages || searchOptions.SearchReferenceAssemblies)
await finder.FindNugetOrReferenceAssemblyReferencesAsync(allReferences, exact, cancellationToken).ConfigureAwait(false);
}

return [.. allReferences];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,9 @@
namespace Microsoft.CodeAnalysis.AddImport;

/// <summary>
/// Code action we use when just adding a using, possibly with a project or
/// metadata reference. We don't use the standard code action types because
/// we want to do things like show a glyph if this will do more than just add
/// an import.
/// Code action we use when just adding a using, possibly with a project or metadata reference. We don't use the
/// standard code action types because we want to do things like show a glyph if this will do more than just add an
/// import.
/// </summary>
internal abstract class AddImportCodeAction : CodeAction
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,35 +16,36 @@ namespace Microsoft.CodeAnalysis.AddImport;
internal interface IAddImportFeatureService : ILanguageService
{
/// <summary>
/// Gets data for how to fix a particular <see cref="Diagnostic" /> id within the specified Document.
/// Useful when you do not have an instance of the diagnostic, such as when invoked as a remote service.
/// Gets data for how to fix a particular <see cref="Diagnostic" /> id within the specified Document. Useful when
/// you do not have an instance of the diagnostic, such as when invoked as a remote service.
/// </summary>
Task<ImmutableArray<AddImportFixData>> GetFixesAsync(
Document document, TextSpan span, string diagnosticId, int maxResults,
ISymbolSearchService symbolSearchService, AddImportOptions options,
ImmutableArray<PackageSource> packageSources, CancellationToken cancellationToken);

/// <summary>
/// Gets data for how to fix a set of <see cref="Diagnostic" />s within the specified Document.
/// The fix data can be used to create code actions that apply the fixes.
/// Gets data for how to fix a set of <see cref="Diagnostic" />s within the specified Document. The fix data can be
/// used to create code actions that apply the fixes.
/// </summary>
Task<ImmutableArray<(Diagnostic Diagnostic, ImmutableArray<AddImportFixData> Fixes)>> GetFixesForDiagnosticsAsync(
Document document, TextSpan span, ImmutableArray<Diagnostic> diagnostics, int maxResultsPerDiagnostic,
ISymbolSearchService symbolSearchService, AddImportOptions options,
ImmutableArray<PackageSource> packageSources, CancellationToken cancellationToken);

/// <summary>
/// Gets code actions that, when applied, will fix the missing imports for the document using
/// the information from the provided fixes.
/// Gets code actions that, when applied, will fix the missing imports for the document using the information from
/// the provided fixes.
/// </summary>
ImmutableArray<CodeAction> GetCodeActionsForFixes(
Document document, ImmutableArray<AddImportFixData> fixes,
IPackageInstallerService? installerService, int maxResults);

/// <summary>
/// Gets data for how to fix a particular <see cref="Diagnostic" /> id within the specified Document.
/// Similar to <see cref="GetFixesAsync(Document, TextSpan, string, int, ISymbolSearchService, AddImportOptions, ImmutableArray{PackageSource}, CancellationToken)"/>
/// except it only returns fix data when there is a single using fix for a given span
/// Gets data for how to fix a particular <see cref="Diagnostic" /> id within the specified Document. Similar to
/// <see cref="GetFixesAsync(Document, TextSpan, string, int, ISymbolSearchService, AddImportOptions,
/// ImmutableArray{PackageSource}, CancellationToken)"/> except it only returns fix data when there is a single
/// using fix for a given span
/// </summary>
Task<ImmutableArray<AddImportFixData>> GetUniqueFixesAsync(
Document document, TextSpan span, ImmutableArray<string> diagnosticIds,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,15 @@ private sealed partial class SymbolReferenceFinder

private readonly SyntaxNode _node;
private readonly ISymbolSearchService _symbolSearchService;
private readonly AddImportOptions _options;
private readonly ImmutableArray<PackageSource> _packageSources;

/// <summary>
/// If the search is being conducted inside of a `using/import` directive.
/// </summary>
private readonly bool _isWithinImport;

public readonly AddImportOptions Options;

public SymbolReferenceFinder(
AbstractAddImportFeatureService<TSimpleNameSyntax> owner,
Document document,
Expand All @@ -64,7 +65,7 @@ public SymbolReferenceFinder(
_node = node;

_symbolSearchService = symbolSearchService;
_options = options;
Options = options;
_packageSources = packageSources;
_syntaxFacts = document.GetLanguageService<ISyntaxFactsService>();

Expand Down Expand Up @@ -211,7 +212,7 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingType
// editor browsable rules.
var accessibleTypeSymbols = typeSymbols.WhereAsArray(
s => ArityAccessibilityAndAttributeContextAreCorrect(s.Symbol, arity, inAttributeContext, hasIncompleteParentMember, looksGeneric) &&
s.Symbol.IsEditorBrowsable(_options.MemberDisplayOptions.HideAdvancedMembers, _semanticModel.Compilation, editorBrowserInfo));
s.Symbol.IsEditorBrowsable(Options.MemberDisplayOptions.HideAdvancedMembers, _semanticModel.Compilation, editorBrowserInfo));

// These types may be contained within namespaces, or they may be nested
// inside generic types. Record these namespaces/types if it would be
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,15 @@ internal abstract partial class AbstractAddImportFeatureService<TSimpleNameSynta
private sealed partial class SymbolReferenceFinder
{
internal async Task FindNugetOrReferenceAssemblyReferencesAsync(
ConcurrentQueue<Reference> allReferences, CancellationToken cancellationToken)
ConcurrentQueue<Reference> allReferences, bool exact, CancellationToken cancellationToken)
{
var options = this.Options.SearchOptions;
Contract.ThrowIfFalse(options.SearchNuGetPackages || options.SearchReferenceAssemblies);

// We only support searching NuGet in an exact manner currently.
if (!exact)
return;

// Only do this if none of the project or metadata searches produced any results. We always consider source
// and local metadata to be better than any NuGet/assembly-reference results.
if (!allReferences.IsEmpty)
Expand Down Expand Up @@ -48,12 +55,9 @@ async Task FindWorkerAsync(
NamespaceQuery namespaceQuery,
bool isAttributeSearch)
{
if (_options.SearchOptions.SearchReferenceAssemblies)
{
cancellationToken.ThrowIfCancellationRequested();
await FindReferenceAssemblyReferencesAsync(
allReferences, nameNode, typeQuery, namespaceQuery, isAttributeSearch, cancellationToken).ConfigureAwait(false);
}
cancellationToken.ThrowIfCancellationRequested();
await FindReferenceAssemblyReferencesAsync(
allReferences, nameNode, typeQuery, namespaceQuery, isAttributeSearch, cancellationToken).ConfigureAwait(false);

var packageSources = PackageSourceHelper.GetPackageSources(_packageSources);
foreach (var (sourceName, sourceUrl) in packageSources)
Expand Down Expand Up @@ -125,6 +129,9 @@ private async Task FindReferenceAssemblyReferencesAsync(
bool isAttributeSearch,
CancellationToken cancellationToken)
{
if (!this.Options.SearchOptions.SearchReferenceAssemblies)
return;

cancellationToken.ThrowIfCancellationRequested();
var results = await _symbolSearchService.FindReferenceAssembliesAsync(
typeQuery, namespaceQuery, cancellationToken).ConfigureAwait(false);
Expand All @@ -151,6 +158,9 @@ private async Task FindNugetReferencesAsync(
bool isAttributeSearch,
CancellationToken cancellationToken)
{
if (!this.Options.SearchOptions.SearchNuGetPackages)
return;

cancellationToken.ThrowIfCancellationRequested();
var results = await _symbolSearchService.FindPackagesAsync(
sourceName, typeQuery, namespaceQuery, cancellationToken).ConfigureAwait(false);
Expand Down
Loading