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

Merge pull request #19893 from CyrusNajmabadi/addUsingOOP2

Move AddImport types to be more data based.
......@@ -149,9 +149,7 @@ private void ProduceTags(TaggerContext<TTag> context, DocumentSnapshotSpan spanT
}
private bool IsSuppressed(NormalizedSnapshotSpanCollection suppressedSpans, SnapshotSpan span)
{
return suppressedSpans != null && suppressedSpans.IntersectsWith(span);
}
=> suppressedSpans != null && suppressedSpans.IntersectsWith(span);
internal void OnDiagnosticsUpdated(DiagnosticsUpdatedArgs e, SourceText sourceText, ITextSnapshot editorSnapshot)
{
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Option Strict Off
Imports Microsoft.CodeAnalysis.CodeActions
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.Diagnostics
......
// 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.Immutable;
using System.Composition;
......@@ -8,10 +7,9 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.AddImport;
using Microsoft.CodeAnalysis.AddImports;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixes.AddImport;
using Microsoft.CodeAnalysis.CSharp.Extensions;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
......@@ -520,12 +518,8 @@ private string GetUsingDirectiveString(INamespaceOrTypeSymbol namespaceOrTypeSym
{
var root = GetCompilationUnitSyntaxNode(contextNode, cancellationToken);
// Suppress diagnostics on the import we create. Because we only get here when we are
// adding a nuget package, it is certainly the case that in the preview this will not
// bind properly. It will look silly to show such an error, so we just suppress things.
var usingDirective = SyntaxFactory.UsingDirective(
CreateNameSyntax(namespaceParts, namespaceParts.Count - 1)).WithAdditionalAnnotations(
SuppressDiagnosticsAnnotation.Create());
CreateNameSyntax(namespaceParts, namespaceParts.Count - 1));
var compilation = await document.Project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var service = document.GetLanguageService<IAddImportsService>();
......
......@@ -7,6 +7,7 @@
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Internal.Log;
......@@ -16,7 +17,7 @@
using Microsoft.CodeAnalysis.SymbolSearch;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
: CodeFixProvider, IEqualityComparer<PortableExecutableReference>
......
// 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.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
/// <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.
/// </summary>
private abstract class AddImportCodeAction : CodeAction
{
public sealed override string Title { get; }
public sealed override ImmutableArray<string> Tags { get; }
internal sealed override CodeActionPriority Priority { get; }
public sealed override string EquivalenceKey => this.Title;
/// <summary>
/// The <see cref="Document"/> we started the add-import analysis in.
/// </summary>
protected readonly Document OriginalDocument;
/// <summary>
/// The changes to make to <see cref="OriginalDocument"/> to add the import.
/// </summary>
private readonly ImmutableArray<TextChange> _textChanges;
protected AddImportCodeAction(
Document originalDocument,
ImmutableArray<TextChange> textChanges,
string title, ImmutableArray<string> tags,
CodeActionPriority priority)
{
OriginalDocument = originalDocument;
Title = title;
Tags = tags;
Priority = priority;
_textChanges = textChanges;
}
protected async Task<Document> GetUpdatedDocumentAsync(CancellationToken cancellationToken)
{
var oldText = await OriginalDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);
var newText = oldText.WithChanges(_textChanges);
var newDocument = OriginalDocument.WithText(newText);
return newDocument;
}
}
}
}
\ No newline at end of file
......@@ -8,77 +8,57 @@
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Tags;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
private partial class AssemblyReference
{
private class AssemblyReferenceCodeAction : CodeAction
private class AssemblyReferenceCodeAction : AddImportCodeAction
{
private readonly AssemblyReference _reference;
private readonly string _title;
private readonly Document _document;
private readonly SyntaxNode _node;
private readonly bool _placeSystemNamespaceFirst;
public override string Title => _title;
public override ImmutableArray<string> Tags => WellKnownTagArrays.AddReference;
private readonly string _assemblyName;
private readonly string _fullyQualifiedTypeName;
private readonly Lazy<string> _lazyResolvedPath;
public AssemblyReferenceCodeAction(
AssemblyReference reference,
Document document,
SyntaxNode node,
bool placeSystemNamespaceFirst)
Document originalDocument,
ImmutableArray<TextChange> textChanges,
string title,
string assemblyName,
string fullyQualifiedTypeName)
: base(originalDocument, textChanges, title, WellKnownTagArrays.AddReference, CodeActionPriority.Low)
{
_reference = reference;
_document = document;
_node = node;
_placeSystemNamespaceFirst = placeSystemNamespaceFirst;
_assemblyName = assemblyName;
_fullyQualifiedTypeName = fullyQualifiedTypeName;
_title = $"{reference.provider.GetDescription(reference.SearchResult.NameParts)} ({string.Format(FeaturesResources.from_0, reference._referenceAssemblyWithType.AssemblyName)})";
_lazyResolvedPath = new Lazy<string>(ResolvePath);
}
// Adding a reference is always low priority.
internal override CodeActionPriority Priority => CodeActionPriority.Low;
private string ResolvePath()
{
var assemblyResolverService = _document.Project.Solution.Workspace.Services.GetService<IFrameworkAssemblyPathResolver>();
var assemblyResolverService = OriginalDocument.Project.Solution.Workspace.Services.GetService<IFrameworkAssemblyPathResolver>();
var packageWithType = _reference._referenceAssemblyWithType;
var fullyQualifiedName = string.Join(".", packageWithType.ContainingNamespaceNames.Concat(packageWithType.TypeName));
var assemblyPath = assemblyResolverService?.ResolveAssemblyPath(
_document.Project.Id, packageWithType.AssemblyName, fullyQualifiedName);
OriginalDocument.Project.Id, _assemblyName, _fullyQualifiedTypeName);
return assemblyPath;
}
internal override bool PerformFinalApplicabilityCheck => true;
internal override bool PerformFinalApplicabilityCheck
=> true;
internal override bool IsApplicable(Workspace workspace)
{
return !string.IsNullOrWhiteSpace(_lazyResolvedPath.Value);
}
=> !string.IsNullOrWhiteSpace(_lazyResolvedPath.Value);
protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(CancellationToken cancellationToken)
{
var service = _document.Project.Solution.Workspace.Services.GetService<IMetadataService>();
var service = OriginalDocument.Project.Solution.Workspace.Services.GetService<IMetadataService>();
var resolvedPath = _lazyResolvedPath.Value;
var reference = service.GetReference(resolvedPath, MetadataReferenceProperties.Assembly);
// First add the "using/import" directive in the code.
(SyntaxNode node, Document document) = await _reference.ReplaceNameNodeAsync(
_node, _document, cancellationToken).ConfigureAwait(false);
var newDocument = await _reference.provider.AddImportAsync(
node, _reference.SearchResult.NameParts, document, _placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
var newDocument = await GetUpdatedDocumentAsync(cancellationToken).ConfigureAwait(false);
// Now add the actual assembly reference.
var newProject = newDocument.Project;
......@@ -89,6 +69,5 @@ protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperation
return SpecializedCollections.SingletonEnumerable<CodeActionOperation>(operation);
}
}
}
}
}
\ 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.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
......@@ -8,59 +9,27 @@
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
private partial class PackageReference
{
private struct InstallPackageAndAddImportData
private class InstallPackageAndAddImportCodeAction : AddImportCodeAction
{
/// <summary>
/// The document before we added the import. Used so we can roll back if installing
/// the package failed.
/// </summary>
public readonly Document OldDocument;
/// <summary>
/// The document after the import has been added.
/// </summary>
public readonly Document NewDocument;
/// <summary>
/// The operation that will actually install the nuget package.
/// </summary>
public readonly InstallPackageDirectlyCodeActionOperation InstallOperation;
public InstallPackageAndAddImportData(
Document oldDocument, Document newDocument,
InstallPackageDirectlyCodeActionOperation installOperation)
{
OldDocument = oldDocument;
NewDocument = newDocument;
InstallOperation = installOperation;
}
}
private class InstallPackageAndAddImportCodeAction : CodeAction
{
private readonly string _title;
private readonly CodeActionPriority _priority;
private readonly AsyncLazy<InstallPackageAndAddImportData> _installData;
public override string Title => _title;
public override string EquivalenceKey => _title;
internal override CodeActionPriority Priority => _priority;
private readonly InstallPackageDirectlyCodeActionOperation _installOperation;
public InstallPackageAndAddImportCodeAction(
string title, CodeActionPriority priority,
AsyncLazy<InstallPackageAndAddImportData> installData)
Document originalDocument,
ImmutableArray<TextChange> textChanges,
string title,
CodeActionPriority priority,
InstallPackageDirectlyCodeActionOperation installOperation)
: base(originalDocument, textChanges, title, ImmutableArray<string>.Empty, priority)
{
_title = title;
_priority = priority;
_installData = installData;
_installOperation = installOperation;
}
/// <summary>
......@@ -71,19 +40,31 @@ private class InstallPackageAndAddImportCodeAction : CodeAction
/// </summary>
protected override async Task<IEnumerable<CodeActionOperation>> ComputePreviewOperationsAsync(CancellationToken cancellationToken)
{
var installData = await _installData.GetValueAsync(cancellationToken).ConfigureAwait(false);
// Make a SolutionChangeAction. This way we can let it generate the diff
// preview appropriately.
var solutionChangeAction = new SolutionChangeAction(
"", c => Task.FromResult(installData.NewDocument.Project.Solution));
"", c => GetUpdatedSolutionAsync(c));
var result = ArrayBuilder<CodeActionOperation>.GetInstance();
result.AddRange(await solutionChangeAction.GetPreviewOperationsAsync(cancellationToken).ConfigureAwait(false));
result.Add(installData.InstallOperation);
result.Add(_installOperation);
return result.ToImmutableAndFree();
}
private async Task<Solution> GetUpdatedSolutionAsync(CancellationToken cancellationToken)
{
var newDocument = await GetUpdatedDocumentAsync(cancellationToken).ConfigureAwait(false);
var newRoot = await newDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
// Suppress diagnostics on the import we create. Because we only get here when we are
// adding a nuget package, it is certainly the case that in the preview this will not
// bind properly. It will look silly to show such an error, so we just suppress things.
var updatedRoot = newRoot.WithAdditionalAnnotations(SuppressDiagnosticsAnnotation.Create());
var updatedDocument = newDocument.WithSyntaxRoot(updatedRoot);
return updatedDocument.Project.Solution;
}
/// <summary>
/// However, for application purposes, we end up returning a single operation
/// that will then apply all our sub actions in order, stopping the moment
......@@ -92,14 +73,14 @@ protected override async Task<IEnumerable<CodeActionOperation>> ComputePreviewOp
protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(
CancellationToken cancellationToken)
{
var installData = await _installData.GetValueAsync(cancellationToken).ConfigureAwait(false);
var updatedDocument = await GetUpdatedDocumentAsync(cancellationToken).ConfigureAwait(false);
var oldText = await installData.OldDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);
var newText = await installData.NewDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);
var oldText = await OriginalDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);
var newText = await updatedDocument.GetTextAsync(cancellationToken).ConfigureAwait(false);
return ImmutableArray.Create<CodeActionOperation>(
new InstallPackageAndAddImportOperation(
installData.OldDocument.Id, oldText, newText, installData.InstallOperation));
OriginalDocument.Id, oldText, newText, _installOperation));
}
}
......@@ -111,7 +92,7 @@ private class InstallPackageAndAddImportOperation : CodeActionOperation
private readonly InstallPackageDirectlyCodeActionOperation _installPackageOperation;
public InstallPackageAndAddImportOperation(
DocumentId changedDocumentId,
DocumentId changedDocumentId,
SourceText oldText,
SourceText newText,
InstallPackageDirectlyCodeActionOperation item2)
......@@ -147,6 +128,5 @@ internal override bool TryApply(Workspace workspace, IProgressTracker progressTr
return false;
}
}
}
}
}
\ No newline at end of file
......@@ -4,21 +4,24 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Packaging;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
private partial class PackageReference : Reference
{
private class InstallWithPackageManagerCodeAction : CodeAction
{
private readonly PackageReference reference;
private readonly IPackageInstallerService _installerService;
private readonly string _packageName;
public InstallWithPackageManagerCodeAction(PackageReference reference)
public InstallWithPackageManagerCodeAction(
IPackageInstallerService installerService,
string packageName)
{
this.reference = reference;
_installerService = installerService;
_packageName = packageName;
}
public override string Title => FeaturesResources.Install_with_package_manager;
......@@ -26,26 +29,27 @@ public InstallWithPackageManagerCodeAction(PackageReference reference)
protected override Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(CancellationToken cancellationToken)
{
return Task.FromResult(SpecializedCollections.SingletonEnumerable<CodeActionOperation>(
new InstallWithPackageManagerCodeActionOperation(reference)));
new InstallWithPackageManagerCodeActionOperation(_installerService, _packageName)));
}
private class InstallWithPackageManagerCodeActionOperation : CodeActionOperation
{
private readonly PackageReference reference;
private readonly IPackageInstallerService _installerService;
private readonly string _packageName;
public InstallWithPackageManagerCodeActionOperation(PackageReference reference)
public InstallWithPackageManagerCodeActionOperation(
IPackageInstallerService installerService,
string packageName)
{
this.reference = reference;
_installerService = installerService;
_packageName = packageName;
}
public override string Title => FeaturesResources.Install_with_package_manager;
public override void Apply(Workspace workspace, CancellationToken cancellationToken)
{
reference._installerService.ShowManagePackagesDialog(reference._packageName);
}
=> _installerService.ShowManagePackagesDialog(_packageName);
}
}
}
}
}
}
\ 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.
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
private class MetadataSymbolReferenceCodeAction : SymbolReferenceCodeAction
{
/// <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>
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;
_portableExecutableReferenceFilePathToAdd = portableExecutableReferenceFilePathToAdd;
}
protected override Project UpdateProject(Project project)
{
var projectWithReference = project.Solution.GetProject(_portableExecutableReferenceProjectId);
var reference = projectWithReference.MetadataReferences
.OfType<PortableExecutableReference>()
.First(pe => pe.FilePath == _portableExecutableReferenceFilePathToAdd);
return project.AddMetadataReference(reference);
}
}
}
}
\ No newline at end of file
......@@ -6,24 +6,22 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.AddPackage;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Packaging;
using Microsoft.CodeAnalysis.Tags;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
private partial class PackageReference : Reference
{
/// <summary>
/// This is the top level 'Install Nuget Package' code action we show in
/// the lightbulb. It will have children to 'Install Latest',
/// 'Install Version 'X' ..., and 'Install with package manager'.
/// </summary>
private class ParentCodeAction : CodeAction.CodeActionWithNestedActions
private class ParentInstallPackageCodeAction : CodeAction.CodeActionWithNestedActions
{
private readonly PackageReference _reference;
public override ImmutableArray<string> Tags => WellKnownTagArrays.NuGet;
// Adding a nuget reference is lower priority than other fixes..
......@@ -35,50 +33,59 @@ private class ParentCodeAction : CodeAction.CodeActionWithNestedActions
/// navigate through, and we don't want our child items confusingly being added to the
/// top level light-bulb where it's not clear what effect they would have if invoked.
/// </summary>
public ParentCodeAction(
PackageReference reference,
public ParentInstallPackageCodeAction(
Document document,
SyntaxNode node,
bool placeSystemNamespaceFirst)
: base(string.Format(FeaturesResources.Install_package_0, reference._packageName),
CreateNestedActions(reference, document, node, placeSystemNamespaceFirst),
ImmutableArray<TextChange> textChanges,
IPackageInstallerService installerService,
string source,
string packageName,
string versionOpt)
: base(string.Format(FeaturesResources.Install_package_0, packageName),
CreateNestedActions(document, textChanges, installerService, source, packageName, versionOpt),
isInlinable: false)
{
_reference = reference;
}
private static ImmutableArray<CodeAction> CreateNestedActions(
PackageReference reference, Document document,
SyntaxNode node, bool placeSystemNamespaceFirst)
Document document,
ImmutableArray<TextChange> textChanges,
IPackageInstallerService installerService,
string source,
string packageName,
string versionOpt)
{
// 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,
// followed by an option to "Find and install latest version."
var installedVersions = reference._installerService.GetInstalledVersions(reference._packageName).NullToEmpty();
var installedVersions = installerService.GetInstalledVersions(packageName).NullToEmpty();
var codeActions = ArrayBuilder<CodeAction>.GetInstance();
// First add the actions to install a specific version.
codeActions.AddRange(installedVersions.Select(
v => CreateCodeAction(reference, document, node, placeSystemNamespaceFirst, versionOpt: v, isLocal: true)));
v => CreateCodeAction(
document, textChanges, installerService,
source, packageName, versionOpt: v, isLocal: true)));
// Now add the action to install the specific version.
var preferredVersion = reference._versionOpt;
var preferredVersion = versionOpt;
if (preferredVersion == null || !installedVersions.Contains(preferredVersion))
{
codeActions.Add(CreateCodeAction(reference, document, node, placeSystemNamespaceFirst,
versionOpt: reference._versionOpt, isLocal: false));
codeActions.Add(CreateCodeAction(
document, textChanges, installerService,
source, packageName, versionOpt, isLocal: false));
}
// And finally the action to show the package manager dialog.
codeActions.Add(new InstallWithPackageManagerCodeAction(reference));
codeActions.Add(new InstallWithPackageManagerCodeAction(installerService, packageName));
return codeActions.ToImmutableAndFree();
}
private static CodeAction CreateCodeAction(
PackageReference reference,
Document document,
SyntaxNode node,
bool placeSystemNamespaceFirst,
ImmutableArray<TextChange> textChanges,
IPackageInstallerService installerService,
string source,
string packageName,
string versionOpt,
bool isLocal)
{
......@@ -88,47 +95,14 @@ private class ParentCodeAction : CodeAction.CodeActionWithNestedActions
? string.Format(FeaturesResources.Use_local_version_0, versionOpt)
: string.Format(FeaturesResources.Install_version_0, versionOpt);
var installData = new AsyncLazy<InstallPackageAndAddImportData>(
c => GetInstallDataAsync(reference, versionOpt, isLocal, document, node, placeSystemNamespaceFirst, c),
cacheResult: true);
// Nuget hits should always come after other results.
return new InstallPackageAndAddImportCodeAction(
title, CodeActionPriority.Low, installData);
}
private static async Task<InstallPackageAndAddImportData> GetInstallDataAsync(
PackageReference reference,
string versionOpt,
bool isLocal,
Document document,
SyntaxNode node,
bool placeSystemNamespaceFirst,
CancellationToken cancellationToken)
{
var oldDocument = document;
(node, document) = await reference.ReplaceNameNodeAsync(
node, document, cancellationToken).ConfigureAwait(false);
var newDocument = await reference.provider.AddImportAsync(
node, reference.SearchResult.NameParts, document, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
// We're going to be manually applying this new document to the workspace
// (so we can roll it back ourselves if installing the nuget package fails).
// As such, we need to do the postprocessing ourselves of tihs document to
// ensure things like formatting/simplification happen to it.
newDocument = await CleanupDocumentAsync(
newDocument, cancellationToken).ConfigureAwait(false);
var installOperation = new InstallPackageDirectlyCodeActionOperation(
reference._installerService, document, reference._source,
reference._packageName, versionOpt,
installerService, document, source, packageName, versionOpt,
includePrerelease: false, isLocal: isLocal);
return new InstallPackageAndAddImportData(
oldDocument, newDocument, installOperation);
// Nuget hits should always come after other results.
return new InstallPackageAndAddImportCodeAction(
document, textChanges, title, CodeActionPriority.Low, installOperation);
}
}
}
}
}
\ 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.
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
/// <summary>
/// Code action for adding an import when we find a symbol in source in either our
/// starting project, or some other unreferenced project in the solution. If we
/// find a source symbol in a different project, we'll also add a p2p reference when
/// we apply the code action.
/// </summary>
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(
Document originalDocument,
ImmutableArray<TextChange> textChanges,
string title, ImmutableArray<string> tags,
CodeActionPriority priority,
ProjectId projectReferenceToAdd)
: base(originalDocument, textChanges, title, tags, priority)
{
// We only want to add a project reference if the project the import references
// is different from the project we started from.
if (projectReferenceToAdd != originalDocument.Project.Id)
{
_projectReferenceToAdd = projectReferenceToAdd;
}
}
internal override bool PerformFinalApplicabilityCheck
=> _projectReferenceToAdd != null;
internal override bool IsApplicable(Workspace workspace)
=> _projectReferenceToAdd != null && workspace.CanAddProjectReference(OriginalDocument.Project.Id, _projectReferenceToAdd);
protected override Project UpdateProject(Project project)
{
return _projectReferenceToAdd == null
? project
: project.AddProjectReference(new ProjectReference(_projectReferenceToAdd));
}
}
}
}
\ 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.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Shared.Utilities;
using Roslyn.Utilities;
using Microsoft.CodeAnalysis.Text;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
private partial class SymbolReference
{
/// <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.
/// </summary>
private class SymbolReferenceCodeAction : CodeAction
private abstract class SymbolReferenceCodeAction : AddImportCodeAction
{
private readonly AsyncLazy<CodeActionOperation> _getOperation;
private readonly Func<Workspace, bool> _isApplicable;
public override string Title { get; }
public override ImmutableArray<string> Tags { get; }
public override string EquivalenceKey => this.Title;
internal override CodeActionPriority Priority { get; }
public SymbolReferenceCodeAction(
protected SymbolReferenceCodeAction(
Document originalDocument,
ImmutableArray<TextChange> textChanges,
string title, ImmutableArray<string> tags,
CodeActionPriority priority,
AsyncLazy<CodeActionOperation> getOperation,
Func<Workspace, bool> isApplicable)
CodeActionPriority priority)
: base(originalDocument, textChanges, title, tags, priority)
{
Title = title;
Tags = tags;
Priority = priority;
_getOperation = getOperation;
_isApplicable = isApplicable;
}
protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperationsAsync(CancellationToken cancellationToken)
=> ImmutableArray.Create(await _getOperation.GetValueAsync(cancellationToken).ConfigureAwait(false));
protected override async Task<Solution> GetChangedSolutionAsync(CancellationToken cancellationToken)
{
var updatedDocument = await GetUpdatedDocumentAsync(cancellationToken).ConfigureAwait(false);
internal override bool PerformFinalApplicabilityCheck
=> _isApplicable != null;
// Defer to subtype to add any p2p or metadata refs as appropriate.
var updatedProject = UpdateProject(updatedDocument.Project);
var updatedSolution = updatedProject.Solution;
return updatedSolution;
}
internal override bool IsApplicable(Workspace workspace)
=> _isApplicable == null ? true : _isApplicable(workspace);
}
protected abstract Project UpdateProject(Project project);
}
}
}
\ No newline at end of file
......@@ -6,7 +6,7 @@
using Microsoft.CodeAnalysis.SymbolSearch;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......@@ -23,11 +23,18 @@ private partial class AssemblyReference : Reference
_referenceAssemblyWithType = referenceAssemblyWithType;
}
public override Task<CodeAction> CreateCodeActionAsync(
public override async Task<CodeAction> CreateCodeActionAsync(
Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken)
{
return Task.FromResult<CodeAction>(new AssemblyReferenceCodeAction(
this, document, node, placeSystemNamespaceFirst));
var textChanges = await GetTextChangesAsync(
document, node, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
var title = $"{this.provider.GetDescription(this.SearchResult.NameParts)} ({string.Format(FeaturesResources.from_0, _referenceAssemblyWithType.AssemblyName)})";
var fullyQualifiedTypeName = string.Join(
".", _referenceAssemblyWithType.ContainingNamespaceNames.Concat(_referenceAssemblyWithType.TypeName));
return new AssemblyReferenceCodeAction(
document, textChanges, title, _referenceAssemblyWithType.AssemblyName, fullyQualifiedTypeName);
}
public override bool Equals(object obj)
......
......@@ -6,22 +6,26 @@
using System.Threading;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Tags;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
private partial class MetadataSymbolReference : SymbolReference
{
private readonly ProjectId _referenceProjectId;
private readonly PortableExecutableReference _reference;
public MetadataSymbolReference(
AbstractAddImportCodeFixProvider<TSimpleNameSyntax> provider,
SymbolResult<INamespaceOrTypeSymbol> symbolResult,
ProjectId referenceProjectId,
PortableExecutableReference reference)
: base(provider, symbolResult)
{
_referenceProjectId = referenceProjectId;
_reference = reference;
}
......@@ -45,8 +49,14 @@ private partial class MetadataSymbolReference : SymbolReference
hasExistingImport);
}
protected override Solution GetUpdatedSolution(Document newDocument)
=> newDocument.Project.AddMetadataReference(_reference).Solution;
protected override CodeAction CreateCodeAction(
Document document, ImmutableArray<TextChange> textChanges, string description,
ImmutableArray<string> tags, CodeActionPriority priority)
{
return new MetadataSymbolReferenceCodeAction(
document, textChanges, description, tags, priority,
_referenceProjectId, _reference.FilePath);
}
// Adding metadata references should be considered lower pri than anything else.
protected override CodeActionPriority GetPriority(Document document)
......
// 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.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Packaging;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......@@ -32,11 +33,14 @@ private partial class PackageReference : Reference
_versionOpt = versionOpt;
}
public override Task<CodeAction> CreateCodeActionAsync(
public override async Task<CodeAction> CreateCodeActionAsync(
Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken)
{
return Task.FromResult<CodeAction>(new ParentCodeAction(
this, document, node, placeSystemNamespaceFirst));
var textChanges = await GetTextChangesAsync(
document, node, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
return new ParentInstallPackageCodeAction(
document, textChanges, _installerService, _source, _packageName, _versionOpt);
}
public override bool Equals(object obj)
......
// 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.Immutable;
using System.Threading;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Tags;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......@@ -67,19 +67,12 @@ protected override CodeActionPriority GetPriority(Document document)
return CodeActionPriority.Low;
}
protected override Solution GetUpdatedSolution(Document newDocument)
protected override CodeAction CreateCodeAction(
Document document, ImmutableArray<TextChange> textChanges, string description,
ImmutableArray<string> tags, CodeActionPriority priority)
{
if (_project.Id == newDocument.Project.Id)
{
// This reference was found while searching in the project for our document. No
// need to make any solution changes.
return newDocument.Project.Solution;
}
// If this reference came from searching another project, then add a project reference
// as well.
var newProject = newDocument.Project.AddProjectReference(new ProjectReference(_project.Id));
return newProject.Solution;
return new ProjectSymbolReferenceCodeAction(
document, textChanges, description, tags, priority, _project.Id);
}
protected override (string description, bool hasExistingImport) GetDescription(
......@@ -100,17 +93,6 @@ protected override Solution GetUpdatedSolution(Document newDocument)
return (description, hasExistingImport);
}
protected override Func<Workspace, bool> GetIsApplicableCheck(Project contextProject)
{
if (contextProject.Id == _project.Id)
{
// no need to do applicability check for a reference in our own project.
return null;
}
return workspace => workspace.CanAddProjectReference(contextProject.Id, _project.Id);
}
public override bool Equals(object obj)
{
var reference = obj as ProjectSymbolReference;
......
// 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.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......@@ -115,7 +117,28 @@ public override int GetHashCode()
return (newContextNode, newDocument);
}
public abstract Task<CodeAction> CreateCodeActionAsync(Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken);
public abstract Task<CodeAction> CreateCodeActionAsync(
Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken);
protected async Task<ImmutableArray<TextChange>> GetTextChangesAsync(
Document document, SyntaxNode node, bool placeSystemNamespaceFirst, CancellationToken cancellationToken)
{
var originalDocument = document;
(node, document) = await this.ReplaceNameNodeAsync(
node, document, cancellationToken).ConfigureAwait(false);
var newDocument = await this.provider.AddImportAsync(
node, this.SearchResult.NameParts, document, placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
var cleanedDocument = await CodeAction.CleanupDocumentAsync(
newDocument, cancellationToken).ConfigureAwait(false);
var textChanges = await cleanedDocument.GetTextChangesAsync(
originalDocument, cancellationToken).ConfigureAwait(false);
return textChanges.ToImmutableArray();
}
}
}
}
\ No newline at end of file
......@@ -2,14 +2,13 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......@@ -43,27 +42,9 @@ public override bool Equals(object obj)
}
public override int GetHashCode()
{
return Hash.Combine(this.SymbolResult.DesiredName, base.GetHashCode());
}
private async Task<CodeActionOperation> GetOperationAsync(
Document document, SyntaxNode node,
bool placeSystemNamespaceFirst, bool hasExistingImport,
CancellationToken cancellationToken)
{
var newDocument = await UpdateDocumentAsync(
document, node, placeSystemNamespaceFirst, hasExistingImport, cancellationToken).ConfigureAwait(false);
var updatedSolution = GetUpdatedSolution(newDocument);
var operation = new ApplyChangesOperation(updatedSolution);
return operation;
}
=> Hash.Combine(this.SymbolResult.DesiredName, base.GetHashCode());
protected virtual Solution GetUpdatedSolution(Document newDocument)
=> newDocument.Project.Solution;
private async Task<Document> UpdateDocumentAsync(
private async Task<ImmutableArray<TextChange>> GetTextChangesAsync(
Document document, SyntaxNode contextNode,
bool placeSystemNamespaceFirst, bool hasExistingImport,
CancellationToken cancellationToken)
......@@ -71,18 +52,26 @@ protected virtual Solution GetUpdatedSolution(Document newDocument)
// Defer to the language to add the actual import/using.
if (hasExistingImport)
{
return document;
return ImmutableArray<TextChange>.Empty;
}
(var newContextNode, var newDocument) = await ReplaceNameNodeAsync(
contextNode, document, cancellationToken).ConfigureAwait(false);
return await provider.AddImportAsync(
var updatedDocument = await provider.AddImportAsync(
newContextNode, this.SymbolResult.Symbol, newDocument,
placeSystemNamespaceFirst, cancellationToken).ConfigureAwait(false);
var cleanedDocument = await CodeAction.CleanupDocumentAsync(
updatedDocument, cancellationToken).ConfigureAwait(false);
var textChanges = await cleanedDocument.GetTextChangesAsync(
document, cancellationToken).ConfigureAwait(false);
return textChanges.ToImmutableArray();
}
public override async Task<CodeAction> CreateCodeActionAsync(
public sealed override async Task<CodeAction> CreateCodeActionAsync(
Document document, SyntaxNode node,
bool placeSystemNamespaceFirst, CancellationToken cancellationToken)
{
......@@ -105,22 +94,19 @@ protected virtual Solution GetUpdatedSolution(Document newDocument)
description = $"{this.SearchResult.DesiredName} - {description}";
}
var getOperation = new AsyncLazy<CodeActionOperation>(
c => this.GetOperationAsync(document, node, placeSystemNamespaceFirst, hasExistingImport, c),
cacheResult: true);
var textChanges = await GetTextChangesAsync(
document, node, placeSystemNamespaceFirst, hasExistingImport, cancellationToken).ConfigureAwait(false);
return new SymbolReferenceCodeAction(
description, GetTags(document), GetPriority(document),
getOperation,
this.GetIsApplicableCheck(document.Project));
return CreateCodeAction(
document, textChanges.ToImmutableArray(), description,
GetTags(document), GetPriority(document));
}
protected abstract CodeActionPriority GetPriority(Document document);
protected abstract CodeAction CreateCodeAction(
Document document, ImmutableArray<TextChange> textChanges,
string description, ImmutableArray<string> tags, CodeActionPriority priority);
protected virtual Func<Workspace, bool> GetIsApplicableCheck(Project project)
{
return null;
}
protected abstract CodeActionPriority GetPriority(Document document);
protected virtual (string description, bool hasExistingImport) GetDescription(
Document document, SyntaxNode node,
......
......@@ -5,7 +5,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.FindSymbols;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......
......@@ -6,7 +6,7 @@
using Microsoft.CodeAnalysis.FindSymbols;
using Microsoft.CodeAnalysis.FindSymbols.SymbolTree;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......@@ -38,6 +38,7 @@ public override SymbolReference CreateReference<T>(SymbolResult<T> searchResult)
return new MetadataSymbolReference(
provider,
searchResult.WithSymbol<INamespaceOrTypeSymbol>(searchResult.Symbol),
_assemblyProjectId,
_metadataReference);
}
......
......@@ -2,7 +2,7 @@
using System.Threading;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......
......@@ -7,7 +7,7 @@
using Microsoft.CodeAnalysis.FindSymbols;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......
......@@ -8,7 +8,7 @@
using Microsoft.CodeAnalysis.FindSymbols.SymbolTree;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......
......@@ -12,7 +12,7 @@
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......
......@@ -6,7 +6,7 @@
using Microsoft.CodeAnalysis.SymbolSearch;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......
......@@ -6,7 +6,7 @@
using Microsoft.CodeAnalysis.LanguageServices;
using Microsoft.CodeAnalysis.Shared.Extensions;
namespace Microsoft.CodeAnalysis.CodeFixes.AddImport
namespace Microsoft.CodeAnalysis.AddImport
{
internal abstract partial class AbstractAddImportCodeFixProvider<TSimpleNameSyntax>
{
......
......@@ -99,7 +99,10 @@
<Compile Include="..\..\..\Compilers\Shared\DesktopShim.cs">
<Link>Shared\Utilities\DesktopShim.cs</Link>
</Compile>
<Compile Include="AddImport\CodeActions\AddImportCodeAction.cs" />
<Compile Include="AddImport\CodeActions\AssemblyReferenceCodeAction.cs" />
<Compile Include="AddImport\CodeActions\MetadataSymbolReferenceCodeAction.cs" />
<Compile Include="AddImport\CodeActions\ProjectSymbolReferenceCodeAction.cs" />
<Compile Include="AddImport\SearchScopes\AllSymbolsProjectSearchScope.cs" />
<Compile Include="AddImport\SearchScopes\MetadataSymbolsSearchScope.cs" />
<Compile Include="AddImport\SearchScopes\ProjectSearchScope.cs" />
......@@ -118,8 +121,8 @@
<Compile Include="ConvertNumericLiteral\AbstractConvertNumericLiteralCodeRefactoringProvider.cs" />
<Compile Include="CodeRefactorings\UseNamedArguments\AbstractUseNamedArgumentsCodeRefactoringProvider.cs" />
<Compile Include="CodeStyle\AbstractCodeStyleDiagnosticAnalyzer.cs" />
<Compile Include="AddImport\CodeActions\PackageReference.InstallPackageAndAddImportCodeAction.cs" />
<Compile Include="AddImport\CodeActions\PackageReference.InstallWithPackageManagerCodeAction.cs" />
<Compile Include="AddImport\CodeActions\InstallPackageAndAddImportCodeAction.cs" />
<Compile Include="AddImport\CodeActions\InstallWithPackageManagerCodeAction.cs" />
<Compile Include="ConflictMarkerResolution\AbstractConflictMarkerCodeFixProvider.cs" />
<Compile Include="Completion\Providers\AbstractCrefCompletionProvider.cs" />
<Compile Include="ConvertToInterpolatedString\AbstractConvertConcatenationToInterpolatedStringRefactoringProvider.cs" />
......@@ -184,7 +187,7 @@
<Compile Include="Navigation\NavigableItemFactory.cs" />
<Compile Include="Navigation\NavigableItemFactory.DeclaredSymbolNavigableItem.cs" />
<Compile Include="Navigation\NavigableItemFactory.SymbolLocationNavigableItem.cs" />
<Compile Include="AddImport\CodeActions\PackageReference.ParentCodeAction.cs" />
<Compile Include="AddImport\CodeActions\ParentInstallPackageCodeAction.cs" />
<Compile Include="Remote\RemoteArguments.cs" />
<Compile Include="RQName\Nodes\ResolvedRQNode.cs" />
<Compile Include="RQName\Nodes\RQArrayOrPointerType.cs" />
......
......@@ -3,11 +3,10 @@
Imports System.Collections.Immutable
Imports System.Composition
Imports System.Threading
Imports Microsoft.CodeAnalysis.AddImport
Imports Microsoft.CodeAnalysis.AddImports
Imports Microsoft.CodeAnalysis.CaseCorrection
Imports Microsoft.CodeAnalysis.CodeActions
Imports Microsoft.CodeAnalysis.CodeFixes
Imports Microsoft.CodeAnalysis.CodeFixes.AddImport
Imports Microsoft.CodeAnalysis.Formatting
Imports Microsoft.CodeAnalysis.LanguageServices
Imports Microsoft.CodeAnalysis.Packaging
......@@ -381,11 +380,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.AddImport
Dim nameSyntax = CreateNameSyntax(nameSpaceParts, nameSpaceParts.Count - 1)
Dim importsStatement = GetImportsStatement(nameSyntax)
' Suppress diagnostics on the import we create. Because we only get here when we are
' adding a NuGet package, it is certainly the case that in the preview this will not
' bind properly. It will look silly to show such an error, so we just suppress things.
importsStatement = importsStatement.WithAdditionalAnnotations(SuppressDiagnosticsAnnotation.Create())
Return AddImportAsync(
contextNode, Document, placeSystemNamespaceFirst,
importsStatement, cancellationToken)
......
......@@ -2,7 +2,7 @@
using System;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes.AddImport;
using Microsoft.CodeAnalysis.AddImport;
using Microsoft.VisualStudio.OLE.Interop;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
......
......@@ -3,7 +3,7 @@
using System.Linq;
using System.Threading;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes.AddImport;
using Microsoft.CodeAnalysis.AddImport;
using Microsoft.VisualStudio.OLE.Interop;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.ProjectSystem
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册