提交 cdde5bd4 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #19957 from CyrusNajmabadi/addUsingOOP4

Switch to using a string instead of a full diagnostic.
...@@ -174,11 +174,11 @@ protected override bool CanAddImport(SyntaxNode node, CancellationToken cancella ...@@ -174,11 +174,11 @@ protected override bool CanAddImport(SyntaxNode node, CancellationToken cancella
} }
protected override bool CanAddImportForMethod( protected override bool CanAddImportForMethod(
Diagnostic diagnostic, ISyntaxFactsService syntaxFacts, SyntaxNode node, out SimpleNameSyntax nameNode) string diagnosticId, ISyntaxFactsService syntaxFacts, SyntaxNode node, out SimpleNameSyntax nameNode)
{ {
nameNode = null; nameNode = null;
switch (diagnostic.Id) switch (diagnosticId)
{ {
case CS7036: case CS7036:
case CS0428: case CS0428:
...@@ -264,18 +264,18 @@ protected override bool CanAddImport(SyntaxNode node, CancellationToken cancella ...@@ -264,18 +264,18 @@ protected override bool CanAddImport(SyntaxNode node, CancellationToken cancella
return true; return true;
} }
protected override bool CanAddImportForDeconstruct(Diagnostic diagnostic, SyntaxNode node) protected override bool CanAddImportForDeconstruct(string diagnosticId, SyntaxNode node)
=> diagnostic.Id == CS8129; => diagnosticId == CS8129;
protected override bool CanAddImportForNamespace(Diagnostic diagnostic, SyntaxNode node, out SimpleNameSyntax nameNode) protected override bool CanAddImportForNamespace(string diagnosticId, SyntaxNode node, out SimpleNameSyntax nameNode)
{ {
nameNode = null; nameNode = null;
return false; return false;
} }
protected override bool CanAddImportForQuery(Diagnostic diagnostic, SyntaxNode node) protected override bool CanAddImportForQuery(string diagnosticId, SyntaxNode node)
{ {
if (diagnostic.Id != CS1935) if (diagnosticId != CS1935)
{ {
return false; return false;
} }
...@@ -283,10 +283,10 @@ protected override bool CanAddImportForQuery(Diagnostic diagnostic, SyntaxNode n ...@@ -283,10 +283,10 @@ protected override bool CanAddImportForQuery(Diagnostic diagnostic, SyntaxNode n
return node.AncestorsAndSelf().Any(n => n is QueryExpressionSyntax && !(n.Parent is QueryContinuationSyntax)); return node.AncestorsAndSelf().Any(n => n is QueryExpressionSyntax && !(n.Parent is QueryContinuationSyntax));
} }
protected override bool CanAddImportForType(Diagnostic diagnostic, SyntaxNode node, out SimpleNameSyntax nameNode) protected override bool CanAddImportForType(string diagnosticId, SyntaxNode node, out SimpleNameSyntax nameNode)
{ {
nameNode = null; nameNode = null;
switch (diagnostic.Id) switch (diagnosticId)
{ {
case CS0103: case CS0103:
case CS0246: case CS0246:
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Editing; using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host;
...@@ -40,11 +41,11 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt ...@@ -40,11 +41,11 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
} }
protected abstract bool CanAddImport(SyntaxNode node, CancellationToken cancellationToken); protected abstract bool CanAddImport(SyntaxNode node, CancellationToken cancellationToken);
protected abstract bool CanAddImportForMethod(Diagnostic diagnostic, ISyntaxFactsService syntaxFacts, SyntaxNode node, out TSimpleNameSyntax nameNode); protected abstract bool CanAddImportForMethod(string diagnosticId, ISyntaxFactsService syntaxFacts, SyntaxNode node, out TSimpleNameSyntax nameNode);
protected abstract bool CanAddImportForNamespace(Diagnostic diagnostic, SyntaxNode node, out TSimpleNameSyntax nameNode); protected abstract bool CanAddImportForNamespace(string diagnosticId, SyntaxNode node, out TSimpleNameSyntax nameNode);
protected abstract bool CanAddImportForDeconstruct(Diagnostic diagnostic, SyntaxNode node); protected abstract bool CanAddImportForDeconstruct(string diagnosticId, SyntaxNode node);
protected abstract bool CanAddImportForQuery(Diagnostic diagnostic, SyntaxNode node); protected abstract bool CanAddImportForQuery(string diagnosticId, SyntaxNode node);
protected abstract bool CanAddImportForType(Diagnostic diagnostic, SyntaxNode node, out TSimpleNameSyntax nameNode); protected abstract bool CanAddImportForType(string diagnosticId, SyntaxNode node, out TSimpleNameSyntax nameNode);
protected abstract ISet<INamespaceSymbol> GetImportNamespacesInScope(SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken); protected abstract ISet<INamespaceSymbol> GetImportNamespacesInScope(SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken);
protected abstract ITypeSymbol GetDeconstructInfo(SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken); protected abstract ITypeSymbol GetDeconstructInfo(SemanticModel semanticModel, SyntaxNode node, CancellationToken cancellationToken);
...@@ -98,16 +99,17 @@ private async Task<int> HandleDiagnosticAsync(CodeFixContext context, Diagnostic ...@@ -98,16 +99,17 @@ private async Task<int> HandleDiagnosticAsync(CodeFixContext context, Diagnostic
if (this.CanAddImport(node, cancellationToken)) if (this.CanAddImport(node, cancellationToken))
{ {
var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false); var semanticModel = await document.GetSemanticModelAsync(cancellationToken).ConfigureAwait(false);
var allSymbolReferences = await FindResultsAsync(document, semanticModel, diagnostic, node, cancellationToken).ConfigureAwait(false); var allSymbolReferences = await FindResultsAsync(document, semanticModel, diagnostic.Id, node, cancellationToken).ConfigureAwait(false);
// Nothing found at all. No need to proceed. // Nothing found at all. No need to proceed.
foreach (var reference in allSymbolReferences) foreach (var reference in allSymbolReferences)
{ {
cancellationToken.ThrowIfCancellationRequested(); cancellationToken.ThrowIfCancellationRequested();
var codeAction = await reference.CreateCodeActionAsync(document, node, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false); var fixData = await reference.GetFixDataAsync(document, node, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
if (codeAction != null) if (fixData != null)
{ {
var codeAction = CreateCodeAction(document, fixData);
context.RegisterCodeFix(codeAction, diagnostic); context.RegisterCodeFix(codeAction, diagnostic);
count++; count++;
} }
...@@ -120,8 +122,35 @@ private async Task<int> HandleDiagnosticAsync(CodeFixContext context, Diagnostic ...@@ -120,8 +122,35 @@ private async Task<int> HandleDiagnosticAsync(CodeFixContext context, Diagnostic
return count; return count;
} }
private CodeAction CreateCodeAction(
Document document, AddImportFixData fixData)
{
switch (fixData.Kind)
{
case AddImportFixKind.ProjectSymbol:
return new ProjectSymbolReferenceCodeAction(document, fixData);
case AddImportFixKind.MetadataSymbol:
return new MetadataSymbolReferenceCodeAction(document, fixData);
case AddImportFixKind.PackageSymbol:
return new ParentInstallPackageCodeAction(document, fixData, GetPackageInstallerService(document));
case AddImportFixKind.ReferenceAssemblySymbol:
return new AssemblyReferenceCodeAction(document, fixData);
}
throw ExceptionUtilities.Unreachable;
}
private IPackageInstallerService GetPackageInstallerService(Document document)
{
var workspaceServices = document.Project.Solution.Workspace.Services;
return _packageInstallerService ?? workspaceServices.GetService<IPackageInstallerService>();
}
private async Task<ImmutableArray<Reference>> FindResultsAsync( private async Task<ImmutableArray<Reference>> FindResultsAsync(
Document document, SemanticModel semanticModel, Diagnostic diagnostic, SyntaxNode node, CancellationToken cancellationToken) Document document, SemanticModel semanticModel, string diagnosticId, SyntaxNode node, CancellationToken cancellationToken)
{ {
// Caches so we don't produce the same data multiple times while searching // Caches so we don't produce the same data multiple times while searching
// all over the solution. // all over the solution.
...@@ -129,7 +158,7 @@ private async Task<int> HandleDiagnosticAsync(CodeFixContext context, Diagnostic ...@@ -129,7 +158,7 @@ private async Task<int> HandleDiagnosticAsync(CodeFixContext context, Diagnostic
var projectToAssembly = new ConcurrentDictionary<Project, AsyncLazy<IAssemblySymbol>>(concurrencyLevel: 2, capacity: project.Solution.ProjectIds.Count); var projectToAssembly = new ConcurrentDictionary<Project, AsyncLazy<IAssemblySymbol>>(concurrencyLevel: 2, capacity: project.Solution.ProjectIds.Count);
var referenceToCompilation = new ConcurrentDictionary<PortableExecutableReference, Compilation>(concurrencyLevel: 2, capacity: project.Solution.Projects.Sum(p => p.MetadataReferences.Count)); var referenceToCompilation = new ConcurrentDictionary<PortableExecutableReference, Compilation>(concurrencyLevel: 2, capacity: project.Solution.Projects.Sum(p => p.MetadataReferences.Count));
var finder = new SymbolReferenceFinder(this, document, semanticModel, diagnostic, node, cancellationToken); var finder = new SymbolReferenceFinder(this, document, semanticModel, diagnosticId, node, cancellationToken);
// Look for exact matches first: // Look for exact matches first:
var exactReferences = await FindResultsAsync(projectToAssembly, referenceToCompilation, project, finder, exact: true, cancellationToken: cancellationToken).ConfigureAwait(false); var exactReferences = await FindResultsAsync(projectToAssembly, referenceToCompilation, project, finder, exact: true, cancellationToken: cancellationToken).ConfigureAwait(false);
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Tags;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.AddImport
{
internal class AddImportFixData
{
public AddImportFixKind Kind { get; }
/// <summary>
/// Text changes to make to the document. Usually just the import to add. May also
/// include a change to the name node the feature was invoked on to fix the casing of it.
/// May be empty for fixes that don't need to add an import and only do something like
/// add a project/metadata reference.
/// </summary>
public ImmutableArray<TextChange> TextChanges { get; }
/// <summary>
/// String to display in the lightbulb menu.
/// </summary>
public string Title { get; private set; }
/// <summary>
/// Tags that control what glyph is displayed in the lightbulb menu.
/// </summary>
public ImmutableArray<string> Tags { get; private set; }
/// <summary>
/// The priority this item should have in the lightbulb list.
/// </summary>
public CodeActionPriority Priority { get; private set; }
#region When adding P2P refrences.
/// <summary>
/// The optional id for a <see cref="Project"/> we'd like to add a reference to.
/// </summary>
public ProjectId ProjectReferenceToAdd { get; private set; }
#endregion
#region When adding a metadata reference
/// <summary>
/// If we're adding <see cref="PortableExecutableReferenceFilePathToAdd"/> then this
/// is the id for the <see cref="Project"/> we can find that <see cref="PortableExecutableReference"/>
/// referenced from.
/// </summary>
public ProjectId PortableExecutableReferenceProjectId { get; private set; }
/// <summary>
/// If we want to add a <see cref="PortableExecutableReference"/> metadata reference, this
/// is the <see cref="PortableExecutableReference.FilePath"/> for it.
/// </summary>
public string PortableExecutableReferenceFilePathToAdd { get; private set; }
#endregion
#region When adding an assembly reference
public string AssemblyReferenceAssemblyName { get; private set; }
public string AssemblyReferenceFullyQualifiedTypeName { get; private set; }
#endregion
#region When adding a package reference
public string PackageSource { get; private set; }
public string PackageName { get; private set; }
public string PackageVersionOpt { get; private set; }
#endregion
private AddImportFixData(
AddImportFixKind kind,
ImmutableArray<TextChange> textChanges)
{
Kind = kind;
TextChanges = textChanges;
Tags = ImmutableArray<string>.Empty;
}
public static AddImportFixData CreateForProjectSymbol(ImmutableArray<TextChange> textChanges, string title, ImmutableArray<string> tags, CodeActionPriority priority, ProjectId projectReferenceToAdd)
{
return new AddImportFixData(AddImportFixKind.ProjectSymbol, textChanges)
{
Title = title,
Tags = tags,
Priority = priority,
ProjectReferenceToAdd = projectReferenceToAdd
};
}
public static AddImportFixData CreateForMetadataSymbol(ImmutableArray<TextChange> textChanges, string title, ImmutableArray<string> tags, CodeActionPriority priority, ProjectId portableExecutableReferenceProjectId, string portableExecutableReferenceFilePathToAdd)
{
return new AddImportFixData(AddImportFixKind.MetadataSymbol, textChanges)
{
Title = title,
Tags = tags,
Priority = priority,
PortableExecutableReferenceProjectId = portableExecutableReferenceProjectId,
PortableExecutableReferenceFilePathToAdd = portableExecutableReferenceFilePathToAdd
};
}
public static AddImportFixData CreateForReferenceAssemblySymbol(ImmutableArray<TextChange> textChanges, string title, string assemblyReferenceAssemblyName, string assemblyReferenceFullyQualifiedTypeName)
{
return new AddImportFixData(AddImportFixKind.ReferenceAssemblySymbol, textChanges)
{
Title = title,
Tags = WellKnownTagArrays.AddReference,
Priority = CodeActionPriority.Low,
AssemblyReferenceAssemblyName = assemblyReferenceAssemblyName,
AssemblyReferenceFullyQualifiedTypeName = assemblyReferenceFullyQualifiedTypeName
};
}
public static AddImportFixData CreateForPackageSymbol(ImmutableArray<TextChange> textChanges, string packageSource, string packageName, string packageVersionOpt)
{
return new AddImportFixData(AddImportFixKind.PackageSymbol, textChanges)
{
PackageSource = packageSource,
Priority = CodeActionPriority.Low,
PackageName = packageName,
PackageVersionOpt = packageVersionOpt,
};
}
}
}
\ No newline at end of file
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
namespace Microsoft.CodeAnalysis.AddImport
{
internal enum AddImportFixKind
{
ProjectSymbol,
MetadataSymbol,
PackageSymbol,
ReferenceAssemblySymbol,
}
}
\ No newline at end of file
...@@ -18,7 +18,9 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt ...@@ -18,7 +18,9 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
/// </summary> /// </summary>
private abstract class AddImportCodeAction : CodeAction private abstract class AddImportCodeAction : CodeAction
{ {
public sealed override string Title { get; } protected readonly AddImportFixData FixData;
public override string Title { get; }
public sealed override ImmutableArray<string> Tags { get; } public sealed override ImmutableArray<string> Tags { get; }
internal sealed override CodeActionPriority Priority { get; } internal sealed override CodeActionPriority Priority { get; }
...@@ -36,15 +38,15 @@ private abstract class AddImportCodeAction : CodeAction ...@@ -36,15 +38,15 @@ private abstract class AddImportCodeAction : CodeAction
protected AddImportCodeAction( protected AddImportCodeAction(
Document originalDocument, Document originalDocument,
ImmutableArray<TextChange> textChanges, AddImportFixData fixData)
string title, ImmutableArray<string> tags,
CodeActionPriority priority)
{ {
OriginalDocument = originalDocument; OriginalDocument = originalDocument;
Title = title; FixData = fixData;
Tags = tags;
Priority = priority; Title = fixData.Title;
_textChanges = textChanges; Tags = fixData.Tags;
Priority = fixData.Priority;
_textChanges = fixData.TextChanges;
} }
protected async Task<Document> GetUpdatedDocumentAsync(CancellationToken cancellationToken) protected async Task<Document> GetUpdatedDocumentAsync(CancellationToken cancellationToken)
......
...@@ -2,13 +2,10 @@ ...@@ -2,13 +2,10 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Tags;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.AddImport namespace Microsoft.CodeAnalysis.AddImport
...@@ -17,22 +14,14 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt ...@@ -17,22 +14,14 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
{ {
private class AssemblyReferenceCodeAction : AddImportCodeAction private class AssemblyReferenceCodeAction : AddImportCodeAction
{ {
private readonly string _assemblyName;
private readonly string _fullyQualifiedTypeName;
private readonly Lazy<string> _lazyResolvedPath; private readonly Lazy<string> _lazyResolvedPath;
public AssemblyReferenceCodeAction( public AssemblyReferenceCodeAction(
Document originalDocument, Document originalDocument,
ImmutableArray<TextChange> textChanges, AddImportFixData fixData)
string title, : base(originalDocument, fixData)
string assemblyName,
string fullyQualifiedTypeName)
: base(originalDocument, textChanges, title, WellKnownTagArrays.AddReference, CodeActionPriority.Low)
{ {
_assemblyName = assemblyName; Contract.ThrowIfFalse(fixData.Kind == AddImportFixKind.ReferenceAssemblySymbol);
_fullyQualifiedTypeName = fullyQualifiedTypeName;
_lazyResolvedPath = new Lazy<string>(ResolvePath); _lazyResolvedPath = new Lazy<string>(ResolvePath);
} }
...@@ -41,7 +30,9 @@ private string ResolvePath() ...@@ -41,7 +30,9 @@ private string ResolvePath()
var assemblyResolverService = OriginalDocument.Project.Solution.Workspace.Services.GetService<IFrameworkAssemblyPathResolver>(); var assemblyResolverService = OriginalDocument.Project.Solution.Workspace.Services.GetService<IFrameworkAssemblyPathResolver>();
var assemblyPath = assemblyResolverService?.ResolveAssemblyPath( var assemblyPath = assemblyResolverService?.ResolveAssemblyPath(
OriginalDocument.Project.Id, _assemblyName, _fullyQualifiedTypeName); OriginalDocument.Project.Id,
FixData.AssemblyReferenceAssemblyName,
FixData.AssemblyReferenceFullyQualifiedTypeName);
return assemblyPath; return assemblyPath;
} }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Threading; using System.Threading;
...@@ -9,6 +8,7 @@ ...@@ -9,6 +8,7 @@
using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.AddImport namespace Microsoft.CodeAnalysis.AddImport
{ {
...@@ -16,6 +16,8 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt ...@@ -16,6 +16,8 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
{ {
private class InstallPackageAndAddImportCodeAction : AddImportCodeAction private class InstallPackageAndAddImportCodeAction : AddImportCodeAction
{ {
public override string Title { get; }
/// <summary> /// <summary>
/// The operation that will actually install the nuget package. /// The operation that will actually install the nuget package.
/// </summary> /// </summary>
...@@ -23,12 +25,13 @@ private class InstallPackageAndAddImportCodeAction : AddImportCodeAction ...@@ -23,12 +25,13 @@ private class InstallPackageAndAddImportCodeAction : AddImportCodeAction
public InstallPackageAndAddImportCodeAction( public InstallPackageAndAddImportCodeAction(
Document originalDocument, Document originalDocument,
ImmutableArray<TextChange> textChanges, AddImportFixData fixData,
string title, string title,
CodeActionPriority priority,
InstallPackageDirectlyCodeActionOperation installOperation) InstallPackageDirectlyCodeActionOperation installOperation)
: base(originalDocument, textChanges, title, ImmutableArray<string>.Empty, priority) : base(originalDocument, fixData)
{ {
Contract.ThrowIfFalse(fixData.Kind == AddImportFixKind.PackageSymbol);
Title = title;
_installOperation = installOperation; _installOperation = installOperation;
} }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Linq; using System.Linq;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.AddImport namespace Microsoft.CodeAnalysis.AddImport
...@@ -12,38 +9,18 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt ...@@ -12,38 +9,18 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
{ {
private class MetadataSymbolReferenceCodeAction : SymbolReferenceCodeAction private class MetadataSymbolReferenceCodeAction : SymbolReferenceCodeAction
{ {
/// <summary> public MetadataSymbolReferenceCodeAction(Document originalDocument, AddImportFixData fixData)
/// If we're adding <see cref="_portableExecutableReferenceFilePathToAdd"/> then this : base(originalDocument, fixData)
/// is the id for the <see cref="Project"/> we can find that <see cref="PortableExecutableReference"/>
/// referenced from.
/// </summary>
private readonly ProjectId _portableExecutableReferenceProjectId;
/// <summary>
/// If we want to add a <see cref="PortableExecutableReference"/> metadata reference, this
/// is the <see cref="PortableExecutableReference.FilePath"/> for it.
/// </summary>
private readonly string _portableExecutableReferenceFilePathToAdd;
public MetadataSymbolReferenceCodeAction(
Document originalDocument,
ImmutableArray<TextChange> textChanges,
string title, ImmutableArray<string> tags,
CodeActionPriority priority,
ProjectId portableExecutableReferenceProjectId,
string portableExecutableReferenceFilePathToAdd)
: base(originalDocument, textChanges, title, tags, priority)
{ {
_portableExecutableReferenceProjectId = portableExecutableReferenceProjectId; Contract.ThrowIfFalse(fixData.Kind == AddImportFixKind.MetadataSymbol);
_portableExecutableReferenceFilePathToAdd = portableExecutableReferenceFilePathToAdd;
} }
protected override Project UpdateProject(Project project) protected override Project UpdateProject(Project project)
{ {
var projectWithReference = project.Solution.GetProject(_portableExecutableReferenceProjectId); var projectWithReference = project.Solution.GetProject(FixData.PortableExecutableReferenceProjectId);
var reference = projectWithReference.MetadataReferences var reference = projectWithReference.MetadataReferences
.OfType<PortableExecutableReference>() .OfType<PortableExecutableReference>()
.First(pe => pe.FilePath == _portableExecutableReferenceFilePathToAdd); .First(pe => pe.FilePath == FixData.PortableExecutableReferenceFilePathToAdd);
return project.AddMetadataReference(reference); return project.AddMetadataReference(reference);
} }
......
...@@ -2,13 +2,10 @@ ...@@ -2,13 +2,10 @@
using System.Collections.Immutable; using System.Collections.Immutable;
using System.Linq; using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.AddPackage; using Microsoft.CodeAnalysis.AddPackage;
using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Packaging; using Microsoft.CodeAnalysis.Packaging;
using Microsoft.CodeAnalysis.Tags; using Microsoft.CodeAnalysis.Tags;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities; using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.AddImport namespace Microsoft.CodeAnalysis.AddImport
...@@ -35,57 +32,48 @@ private class ParentInstallPackageCodeAction : CodeAction.CodeActionWithNestedAc ...@@ -35,57 +32,48 @@ private class ParentInstallPackageCodeAction : CodeAction.CodeActionWithNestedAc
/// </summary> /// </summary>
public ParentInstallPackageCodeAction( public ParentInstallPackageCodeAction(
Document document, Document document,
ImmutableArray<TextChange> textChanges, AddImportFixData fixData,
IPackageInstallerService installerService, IPackageInstallerService installerService)
string source, : base(string.Format(FeaturesResources.Install_package_0, fixData.PackageName),
string packageName, CreateNestedActions(document, fixData, installerService),
string versionOpt)
: base(string.Format(FeaturesResources.Install_package_0, packageName),
CreateNestedActions(document, textChanges, installerService, source, packageName, versionOpt),
isInlinable: false) isInlinable: false)
{ {
Contract.ThrowIfFalse(fixData.Kind == AddImportFixKind.PackageSymbol);
} }
private static ImmutableArray<CodeAction> CreateNestedActions( private static ImmutableArray<CodeAction> CreateNestedActions(
Document document, Document document,
ImmutableArray<TextChange> textChanges, AddImportFixData fixData,
IPackageInstallerService installerService, IPackageInstallerService installerService)
string source,
string packageName,
string versionOpt)
{ {
// Determine what versions of this package are already installed in some project // Determine what versions of this package are already installed in some project
// in this solution. We'll offer to add those specific versions to this project, // in this solution. We'll offer to add those specific versions to this project,
// followed by an option to "Find and install latest version." // followed by an option to "Find and install latest version."
var installedVersions = installerService.GetInstalledVersions(packageName).NullToEmpty(); var installedVersions = installerService.GetInstalledVersions(fixData.PackageName).NullToEmpty();
var codeActions = ArrayBuilder<CodeAction>.GetInstance(); var codeActions = ArrayBuilder<CodeAction>.GetInstance();
// First add the actions to install a specific version. // First add the actions to install a specific version.
codeActions.AddRange(installedVersions.Select( codeActions.AddRange(installedVersions.Select(
v => CreateCodeAction( v => CreateCodeAction(
document, textChanges, installerService, document, fixData, installerService, versionOpt: v, isLocal: true)));
source, packageName, versionOpt: v, isLocal: true)));
// Now add the action to install the specific version. // Now add the action to install the specific version.
var preferredVersion = versionOpt; var preferredVersion = fixData.PackageVersionOpt;
if (preferredVersion == null || !installedVersions.Contains(preferredVersion)) if (preferredVersion == null || !installedVersions.Contains(preferredVersion))
{ {
codeActions.Add(CreateCodeAction( codeActions.Add(CreateCodeAction(
document, textChanges, installerService, document, fixData, installerService, preferredVersion, isLocal: false));
source, packageName, versionOpt, isLocal: false));
} }
// And finally the action to show the package manager dialog. // And finally the action to show the package manager dialog.
codeActions.Add(new InstallWithPackageManagerCodeAction(installerService, packageName)); codeActions.Add(new InstallWithPackageManagerCodeAction(installerService, fixData.PackageName));
return codeActions.ToImmutableAndFree(); return codeActions.ToImmutableAndFree();
} }
private static CodeAction CreateCodeAction( private static CodeAction CreateCodeAction(
Document document, Document document,
ImmutableArray<TextChange> textChanges, AddImportFixData fixData,
IPackageInstallerService installerService, IPackageInstallerService installerService,
string source,
string packageName,
string versionOpt, string versionOpt,
bool isLocal) bool isLocal)
{ {
...@@ -96,12 +84,12 @@ private class ParentInstallPackageCodeAction : CodeAction.CodeActionWithNestedAc ...@@ -96,12 +84,12 @@ private class ParentInstallPackageCodeAction : CodeAction.CodeActionWithNestedAc
: string.Format(FeaturesResources.Install_version_0, versionOpt); : string.Format(FeaturesResources.Install_version_0, versionOpt);
var installOperation = new InstallPackageDirectlyCodeActionOperation( var installOperation = new InstallPackageDirectlyCodeActionOperation(
installerService, document, source, packageName, versionOpt, installerService, document, fixData.PackageSource, fixData.PackageName, versionOpt,
includePrerelease: false, isLocal: isLocal); includePrerelease: false, isLocal: isLocal);
// Nuget hits should always come after other results. // Nuget hits should always come after other results.
return new InstallPackageAndAddImportCodeAction( return new InstallPackageAndAddImportCodeAction(
document, textChanges, title, CodeActionPriority.Low, installOperation); document, fixData, title, installOperation);
} }
} }
} }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable; using Roslyn.Utilities;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.AddImport namespace Microsoft.CodeAnalysis.AddImport
{ {
...@@ -16,38 +14,30 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt ...@@ -16,38 +14,30 @@ internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSynt
/// </summary> /// </summary>
private class ProjectSymbolReferenceCodeAction : SymbolReferenceCodeAction private class ProjectSymbolReferenceCodeAction : SymbolReferenceCodeAction
{ {
/// <summary>
/// The optional id for a <see cref="Project"/> we'd like to add a reference to.
/// </summary>
private readonly ProjectId _projectReferenceToAdd;
public ProjectSymbolReferenceCodeAction( public ProjectSymbolReferenceCodeAction(
Document originalDocument, Document originalDocument,
ImmutableArray<TextChange> textChanges, AddImportFixData fixData)
string title, ImmutableArray<string> tags, : base(originalDocument, fixData)
CodeActionPriority priority,
ProjectId projectReferenceToAdd)
: base(originalDocument, textChanges, title, tags, priority)
{ {
// We only want to add a project reference if the project the import references Contract.ThrowIfFalse(fixData.Kind == AddImportFixKind.ProjectSymbol);
// is different from the project we started from.
if (projectReferenceToAdd != originalDocument.Project.Id)
{
_projectReferenceToAdd = projectReferenceToAdd;
}
} }
private bool ShouldAddProjectReference()
=> FixData.ProjectReferenceToAdd != null && FixData.ProjectReferenceToAdd != OriginalDocument.Project.Id;
internal override bool PerformFinalApplicabilityCheck internal override bool PerformFinalApplicabilityCheck
=> _projectReferenceToAdd != null; => ShouldAddProjectReference();
internal override bool IsApplicable(Workspace workspace) internal override bool IsApplicable(Workspace workspace)
=> _projectReferenceToAdd != null && workspace.CanAddProjectReference(OriginalDocument.Project.Id, _projectReferenceToAdd); => ShouldAddProjectReference() &&
workspace.CanAddProjectReference(
OriginalDocument.Project.Id, FixData.ProjectReferenceToAdd);
protected override Project UpdateProject(Project project) protected override Project UpdateProject(Project project)
{ {
return _projectReferenceToAdd == null return ShouldAddProjectReference()
? project ? project.AddProjectReference(new ProjectReference(FixData.ProjectReferenceToAdd))
: project.AddProjectReference(new ProjectReference(_projectReferenceToAdd)); : project;
} }
} }
} }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.AddImport namespace Microsoft.CodeAnalysis.AddImport
{ {
...@@ -20,10 +17,8 @@ private abstract class SymbolReferenceCodeAction : AddImportCodeAction ...@@ -20,10 +17,8 @@ private abstract class SymbolReferenceCodeAction : AddImportCodeAction
{ {
protected SymbolReferenceCodeAction( protected SymbolReferenceCodeAction(
Document originalDocument, Document originalDocument,
ImmutableArray<TextChange> textChanges, AddImportFixData fixData)
string title, ImmutableArray<string> tags, : base(originalDocument, fixData)
CodeActionPriority priority)
: base(originalDocument, textChanges, title, tags, priority)
{ {
} }
......
...@@ -2,7 +2,6 @@ ...@@ -2,7 +2,6 @@
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.SymbolSearch; using Microsoft.CodeAnalysis.SymbolSearch;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -23,7 +22,7 @@ private partial class AssemblyReference : Reference ...@@ -23,7 +22,7 @@ private partial class AssemblyReference : Reference
_referenceAssemblyWithType = referenceAssemblyWithType; _referenceAssemblyWithType = referenceAssemblyWithType;
} }
public override async Task<CodeAction> CreateCodeActionAsync( public override async Task<AddImportFixData> GetFixDataAsync(
Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken) Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken)
{ {
var textChanges = await GetTextChangesAsync( var textChanges = await GetTextChangesAsync(
...@@ -33,8 +32,8 @@ private partial class AssemblyReference : Reference ...@@ -33,8 +32,8 @@ private partial class AssemblyReference : Reference
var fullyQualifiedTypeName = string.Join( var fullyQualifiedTypeName = string.Join(
".", _referenceAssemblyWithType.ContainingNamespaceNames.Concat(_referenceAssemblyWithType.TypeName)); ".", _referenceAssemblyWithType.ContainingNamespaceNames.Concat(_referenceAssemblyWithType.TypeName));
return new AssemblyReferenceCodeAction( return AddImportFixData.CreateForReferenceAssemblySymbol(
document, textChanges, title, _referenceAssemblyWithType.AssemblyName, fullyQualifiedTypeName); textChanges, title, _referenceAssemblyWithType.AssemblyName, fullyQualifiedTypeName);
} }
public override bool Equals(object obj) public override bool Equals(object obj)
......
...@@ -49,12 +49,12 @@ private partial class MetadataSymbolReference : SymbolReference ...@@ -49,12 +49,12 @@ private partial class MetadataSymbolReference : SymbolReference
hasExistingImport); hasExistingImport);
} }
protected override CodeAction CreateCodeAction( protected override AddImportFixData GetFixData(
Document document, ImmutableArray<TextChange> textChanges, string description, Document document, ImmutableArray<TextChange> textChanges, string description,
ImmutableArray<string> tags, CodeActionPriority priority) ImmutableArray<string> tags, CodeActionPriority priority)
{ {
return new MetadataSymbolReferenceCodeAction( return AddImportFixData.CreateForMetadataSymbol(
document, textChanges, description, tags, priority, textChanges, description, tags, priority,
_referenceProjectId, _reference.FilePath); _referenceProjectId, _reference.FilePath);
} }
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System.Collections.Immutable;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Packaging; using Microsoft.CodeAnalysis.Packaging;
using Roslyn.Utilities; using Roslyn.Utilities;
...@@ -33,14 +31,14 @@ private partial class PackageReference : Reference ...@@ -33,14 +31,14 @@ private partial class PackageReference : Reference
_versionOpt = versionOpt; _versionOpt = versionOpt;
} }
public override async Task<CodeAction> CreateCodeActionAsync( public override async Task<AddImportFixData> GetFixDataAsync(
Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken) Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken)
{ {
var textChanges = await GetTextChangesAsync( var textChanges = await GetTextChangesAsync(
document, node, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false); document, node, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
return new ParentInstallPackageCodeAction( return AddImportFixData.CreateForPackageSymbol(
document, textChanges, _installerService, _source, _packageName, _versionOpt); textChanges, _source, _packageName, _versionOpt);
} }
public override bool Equals(object obj) public override bool Equals(object obj)
......
...@@ -67,12 +67,12 @@ protected override CodeActionPriority GetPriority(Document document) ...@@ -67,12 +67,12 @@ protected override CodeActionPriority GetPriority(Document document)
return CodeActionPriority.Low; return CodeActionPriority.Low;
} }
protected override CodeAction CreateCodeAction( protected override AddImportFixData GetFixData(
Document document, ImmutableArray<TextChange> textChanges, string description, Document document, ImmutableArray<TextChange> textChanges, string description,
ImmutableArray<string> tags, CodeActionPriority priority) ImmutableArray<string> tags, CodeActionPriority priority)
{ {
return new ProjectSymbolReferenceCodeAction( return AddImportFixData.CreateForProjectSymbol(
document, textChanges, description, tags, priority, _project.Id); textChanges, description, tags, priority, _project.Id);
} }
protected override (string description, bool hasExistingImport) GetDescription( protected override (string description, bool hasExistingImport) GetDescription(
......
...@@ -117,7 +117,7 @@ public override int GetHashCode() ...@@ -117,7 +117,7 @@ public override int GetHashCode()
return (newContextNode, newDocument); return (newContextNode, newDocument);
} }
public abstract Task<CodeAction> CreateCodeActionAsync( public abstract Task<AddImportFixData> GetFixDataAsync(
Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken); Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken);
protected async Task<ImmutableArray<TextChange>> GetTextChangesAsync( protected async Task<ImmutableArray<TextChange>> GetTextChangesAsync(
......
...@@ -71,7 +71,7 @@ public override int GetHashCode() ...@@ -71,7 +71,7 @@ public override int GetHashCode()
return textChanges.ToImmutableArray(); return textChanges.ToImmutableArray();
} }
public sealed override async Task<CodeAction> CreateCodeActionAsync( public sealed override async Task<AddImportFixData> GetFixDataAsync(
Document document, SyntaxNode node, Document document, SyntaxNode node,
bool placeSystemNamespaceFirst, CancellationToken cancellationToken) bool placeSystemNamespaceFirst, CancellationToken cancellationToken)
{ {
...@@ -97,12 +97,12 @@ public override int GetHashCode() ...@@ -97,12 +97,12 @@ public override int GetHashCode()
var textChanges = await GetTextChangesAsync( var textChanges = await GetTextChangesAsync(
document, node, placeSystemNamespaceFirst, hasExistingImport, cancellationToken).ConfigureAwait(false); document, node, placeSystemNamespaceFirst, hasExistingImport, cancellationToken).ConfigureAwait(false);
return CreateCodeAction( return GetFixData(
document, textChanges.ToImmutableArray(), description, document, textChanges.ToImmutableArray(), description,
GetTags(document), GetPriority(document)); GetTags(document), GetPriority(document));
} }
protected abstract CodeAction CreateCodeAction( protected abstract AddImportFixData GetFixData(
Document document, ImmutableArray<TextChange> textChanges, Document document, ImmutableArray<TextChange> textChanges,
string description, ImmutableArray<string> tags, CodeActionPriority priority); string description, ImmutableArray<string> tags, CodeActionPriority priority);
......
...@@ -20,7 +20,7 @@ private partial class SymbolReferenceFinder ...@@ -20,7 +20,7 @@ private partial class SymbolReferenceFinder
{ {
private const string AttributeSuffix = nameof(Attribute); private const string AttributeSuffix = nameof(Attribute);
private readonly Diagnostic _diagnostic; private readonly string _diagnosticId;
private readonly Document _document; private readonly Document _document;
private readonly SemanticModel _semanticModel; private readonly SemanticModel _semanticModel;
...@@ -35,13 +35,13 @@ private partial class SymbolReferenceFinder ...@@ -35,13 +35,13 @@ private partial class SymbolReferenceFinder
public SymbolReferenceFinder( public SymbolReferenceFinder(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> owner, AbstractAddImportCodeFixProvider<TSimpleNameSyntax> owner,
Document document, SemanticModel semanticModel, Document document, SemanticModel semanticModel,
Diagnostic diagnostic, SyntaxNode node, string diagnosticId, SyntaxNode node,
CancellationToken cancellationToken) CancellationToken cancellationToken)
{ {
_owner = owner; _owner = owner;
_document = document; _document = document;
_semanticModel = semanticModel; _semanticModel = semanticModel;
_diagnostic = diagnostic; _diagnosticId = diagnosticId;
_node = node; _node = node;
_containingType = semanticModel.GetEnclosingNamedType(node.SpanStart, cancellationToken); _containingType = semanticModel.GetEnclosingNamedType(node.SpanStart, cancellationToken);
...@@ -155,7 +155,7 @@ private ImmutableArray<SymbolReference> DeDupeAndSortReferences(ImmutableArray<S ...@@ -155,7 +155,7 @@ private ImmutableArray<SymbolReference> DeDupeAndSortReferences(ImmutableArray<S
private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingTypesAsync(SearchScope searchScope) private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingTypesAsync(SearchScope searchScope)
{ {
searchScope.CancellationToken.ThrowIfCancellationRequested(); searchScope.CancellationToken.ThrowIfCancellationRequested();
if (!_owner.CanAddImportForType(_diagnostic, _node, out var nameNode)) if (!_owner.CanAddImportForType(_diagnosticId, _node, out var nameNode))
{ {
return ImmutableArray<SymbolReference>.Empty; return ImmutableArray<SymbolReference>.Empty;
} }
...@@ -223,7 +223,7 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingType ...@@ -223,7 +223,7 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingType
SearchScope searchScope) SearchScope searchScope)
{ {
searchScope.CancellationToken.ThrowIfCancellationRequested(); searchScope.CancellationToken.ThrowIfCancellationRequested();
if (_owner.CanAddImportForNamespace(_diagnostic, _node, out var nameNode)) if (_owner.CanAddImportForNamespace(_diagnosticId, _node, out var nameNode))
{ {
_syntaxFacts.GetNameAndArityOfSimpleName(nameNode, out var name, out var arity); _syntaxFacts.GetNameAndArityOfSimpleName(nameNode, out var name, out var arity);
...@@ -250,7 +250,7 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingType ...@@ -250,7 +250,7 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingType
SearchScope searchScope) SearchScope searchScope)
{ {
searchScope.CancellationToken.ThrowIfCancellationRequested(); searchScope.CancellationToken.ThrowIfCancellationRequested();
if (_owner.CanAddImportForMethod(_diagnostic, _syntaxFacts, _node, out var nameNode) && if (_owner.CanAddImportForMethod(_diagnosticId, _syntaxFacts, _node, out var nameNode) &&
nameNode != null) nameNode != null)
{ {
// We have code like "Color.Black". "Color" bound to a 'Color Color' property, and // We have code like "Color.Black". "Color" bound to a 'Color Color' property, and
...@@ -310,7 +310,7 @@ private bool HasAccessibleStaticFieldOrProperty(INamedTypeSymbol namedType, stri ...@@ -310,7 +310,7 @@ private bool HasAccessibleStaticFieldOrProperty(INamedTypeSymbol namedType, stri
private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingExtensionMethodsAsync(SearchScope searchScope) private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingExtensionMethodsAsync(SearchScope searchScope)
{ {
searchScope.CancellationToken.ThrowIfCancellationRequested(); searchScope.CancellationToken.ThrowIfCancellationRequested();
if (_owner.CanAddImportForMethod(_diagnostic, _syntaxFacts, _node, out var nameNode) && if (_owner.CanAddImportForMethod(_diagnosticId, _syntaxFacts, _node, out var nameNode) &&
nameNode != null) nameNode != null)
{ {
searchScope.CancellationToken.ThrowIfCancellationRequested(); searchScope.CancellationToken.ThrowIfCancellationRequested();
...@@ -368,7 +368,7 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingExte ...@@ -368,7 +368,7 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForMatchingExte
private async Task<ImmutableArray<SymbolReference>> GetReferencesForCollectionInitializerMethodsAsync(SearchScope searchScope) private async Task<ImmutableArray<SymbolReference>> GetReferencesForCollectionInitializerMethodsAsync(SearchScope searchScope)
{ {
searchScope.CancellationToken.ThrowIfCancellationRequested(); searchScope.CancellationToken.ThrowIfCancellationRequested();
if (!_owner.CanAddImportForMethod(_diagnostic, _syntaxFacts, _node, out var nameNode)) if (!_owner.CanAddImportForMethod(_diagnosticId, _syntaxFacts, _node, out var nameNode))
{ {
return ImmutableArray<SymbolReference>.Empty; return ImmutableArray<SymbolReference>.Empty;
} }
...@@ -403,7 +403,7 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForQueryPattern ...@@ -403,7 +403,7 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForQueryPattern
{ {
searchScope.CancellationToken.ThrowIfCancellationRequested(); searchScope.CancellationToken.ThrowIfCancellationRequested();
if (_owner.CanAddImportForQuery(_diagnostic, _node)) if (_owner.CanAddImportForQuery(_diagnosticId, _node))
{ {
var type = _owner.GetQueryClauseInfo(_semanticModel, _node, searchScope.CancellationToken); var type = _owner.GetQueryClauseInfo(_semanticModel, _node, searchScope.CancellationToken);
if (type != null) if (type != null)
...@@ -426,7 +426,7 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForDeconstructA ...@@ -426,7 +426,7 @@ private async Task<ImmutableArray<SymbolReference>> GetReferencesForDeconstructA
{ {
searchScope.CancellationToken.ThrowIfCancellationRequested(); searchScope.CancellationToken.ThrowIfCancellationRequested();
if (_owner.CanAddImportForDeconstruct(_diagnostic, _node)) if (_owner.CanAddImportForDeconstruct(_diagnosticId, _node))
{ {
var type = _owner.GetDeconstructInfo(_semanticModel, _node, searchScope.CancellationToken); var type = _owner.GetDeconstructInfo(_semanticModel, _node, searchScope.CancellationToken);
if (type != null) if (type != null)
......
...@@ -23,7 +23,7 @@ private partial class SymbolReferenceFinder ...@@ -23,7 +23,7 @@ private partial class SymbolReferenceFinder
return; return;
} }
if (!_owner.CanAddImportForType(_diagnostic, _node, out var nameNode)) if (!_owner.CanAddImportForType(_diagnosticId, _node, out var nameNode))
{ {
return; return;
} }
...@@ -63,7 +63,7 @@ private partial class SymbolReferenceFinder ...@@ -63,7 +63,7 @@ private partial class SymbolReferenceFinder
var workspaceServices = _document.Project.Solution.Workspace.Services; var workspaceServices = _document.Project.Solution.Workspace.Services;
var symbolSearchService = _owner._symbolSearchService ?? workspaceServices.GetService<ISymbolSearchService>(); var symbolSearchService = _owner._symbolSearchService ?? workspaceServices.GetService<ISymbolSearchService>();
var installerService = _owner._packageInstallerService ?? workspaceServices.GetService<IPackageInstallerService>(); var installerService = _owner.GetPackageInstallerService(_document);
var language = _document.Project.Language; var language = _document.Project.Language;
......
...@@ -99,6 +99,8 @@ ...@@ -99,6 +99,8 @@
<Compile Include="..\..\..\Compilers\Shared\DesktopShim.cs"> <Compile Include="..\..\..\Compilers\Shared\DesktopShim.cs">
<Link>Shared\Utilities\DesktopShim.cs</Link> <Link>Shared\Utilities\DesktopShim.cs</Link>
</Compile> </Compile>
<Compile Include="AddImport\AddImportFixData.cs" />
<Compile Include="AddImport\AddImportFixKind.cs" />
<Compile Include="AddImport\CodeActions\AddImportCodeAction.cs" /> <Compile Include="AddImport\CodeActions\AddImportCodeAction.cs" />
<Compile Include="AddImport\CodeActions\AssemblyReferenceCodeAction.cs" /> <Compile Include="AddImport\CodeActions\AssemblyReferenceCodeAction.cs" />
<Compile Include="AddImport\CodeActions\MetadataSymbolReferenceCodeAction.cs" /> <Compile Include="AddImport\CodeActions\MetadataSymbolReferenceCodeAction.cs" />
......
...@@ -120,11 +120,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport ...@@ -120,11 +120,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
End Function End Function
Protected Overrides Function CanAddImportForMethod( Protected Overrides Function CanAddImportForMethod(
diagnostic As Diagnostic, diagnosticId As String,
syntaxFacts As ISyntaxFactsService, syntaxFacts As ISyntaxFactsService,
node As SyntaxNode, node As SyntaxNode,
ByRef nameNode As SimpleNameSyntax) As Boolean ByRef nameNode As SimpleNameSyntax) As Boolean
Select Case diagnostic.Id Select Case diagnosticId
Case BC30456, BC30390, BC42309, BC30451 Case BC30456, BC30390, BC42309, BC30451
Exit Select Exit Select
Case BC30512 Case BC30512
...@@ -177,8 +177,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport ...@@ -177,8 +177,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
Return True Return True
End Function End Function
Protected Overrides Function CanAddImportForNamespace(diagnostic As Diagnostic, node As SyntaxNode, ByRef nameNode As SimpleNameSyntax) As Boolean Protected Overrides Function CanAddImportForNamespace(diagnosticId As String, node As SyntaxNode, ByRef nameNode As SimpleNameSyntax) As Boolean
Select Case diagnostic.Id Select Case diagnosticId
Case BC30002, BC30451 Case BC30002, BC30451
Exit Select Exit Select
Case Else Case Else
...@@ -188,13 +188,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport ...@@ -188,13 +188,13 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
Return CanAddImportForTypeOrNamespaceCore(node, nameNode) Return CanAddImportForTypeOrNamespaceCore(node, nameNode)
End Function End Function
Protected Overrides Function CanAddImportForDeconstruct(diagnostic As Diagnostic, node As SyntaxNode) As Boolean Protected Overrides Function CanAddImportForDeconstruct(diagnosticId As String, node As SyntaxNode) As Boolean
' Not supported yet. ' Not supported yet.
Return False Return False
End Function End Function
Protected Overrides Function CanAddImportForQuery(diagnostic As Diagnostic, node As SyntaxNode) As Boolean Protected Overrides Function CanAddImportForQuery(diagnosticId As String, node As SyntaxNode) As Boolean
If diagnostic.Id <> BC36593 Then If diagnosticId <> BC36593 Then
Return False Return False
End If End If
...@@ -208,8 +208,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport ...@@ -208,8 +208,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
End Function End Function
Protected Overrides Function CanAddImportForType( Protected Overrides Function CanAddImportForType(
diagnostic As Diagnostic, node As SyntaxNode, ByRef nameNode As SimpleNameSyntax) As Boolean diagnosticId As String, node As SyntaxNode, ByRef nameNode As SimpleNameSyntax) As Boolean
Select Case diagnostic.Id Select Case diagnosticId
Case BC30002, BC30451, BC32042, BC32045, BC30389, BC31504, BC36610, BC30182 Case BC30002, BC30451, BC32042, BC32045, BC30389, BC31504, BC36610, BC30182
Exit Select Exit Select
Case BC42309 Case BC42309
......
...@@ -540,7 +540,7 @@ public IEnumerable<Project> GetProjectsWithInstalledPackage(Solution solution, s ...@@ -540,7 +540,7 @@ public IEnumerable<Project> GetProjectsWithInstalledPackage(Solution solution, s
{ {
var state = kvp.Value; var state = kvp.Value;
var versionSet = state.InstalledPackageToVersion[packageName]; var versionSet = state.InstalledPackageToVersion[packageName];
if (versionSet.Contains(packageName)) if (versionSet.Contains(version))
{ {
var project = solution.GetProject(kvp.Key); var project = solution.GetProject(kvp.Key);
if (project != null) if (project != null)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册