| File: AddImport\CodeActions\ProjectSymbolReferenceCodeAction.cs | Web Access |
| Project: src\roslyn\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.AddImport; internal abstract partial class AbstractAddImportFeatureService<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 sealed class ProjectSymbolReferenceCodeAction : SymbolReferenceCodeAction { /// <summary> /// This code action may or may not add a project reference. If it does, it requires a non document change /// (and is thus restricted in which hosts it can run). If it doesn't, it can run anywhere. /// </summary> public ProjectSymbolReferenceCodeAction( Document originalDocument, AddImportFixData fixData) : base(originalDocument, fixData, additionalTags: ShouldAddProjectReference(originalDocument, fixData) ? RequiresNonDocumentChangeTags : []) { Contract.ThrowIfFalse(fixData.Kind == AddImportFixKind.ProjectSymbol); } private static bool ShouldAddProjectReference(Document originalDocument, AddImportFixData fixData) => fixData.ProjectReferenceToAdd != null && fixData.ProjectReferenceToAdd != originalDocument.Project.Id; protected override Task<CodeActionOperation?> UpdateProjectAsync(Project project, bool isPreview, CancellationToken cancellationToken) { if (!ShouldAddProjectReference(this.OriginalDocument, this.FixData)) return SpecializedTasks.Null<CodeActionOperation>(); var projectWithAddedReference = project.AddProjectReference(new ProjectReference(FixData.ProjectReferenceToAdd)); var applyOperation = new ApplyChangesOperation(projectWithAddedReference.Solution); if (isPreview) { return Task.FromResult<CodeActionOperation?>(applyOperation); } return Task.FromResult<CodeActionOperation?>(new AddProjectReferenceCodeActionOperation(OriginalDocument.Project.Id, FixData.ProjectReferenceToAdd, applyOperation)); } private sealed class AddProjectReferenceCodeActionOperation(ProjectId referencingProject, ProjectId referencedProject, ApplyChangesOperation applyOperation) : CodeActionOperation { private readonly ProjectId _referencingProject = referencingProject; private readonly ProjectId _referencedProject = referencedProject; private readonly ApplyChangesOperation _applyOperation = applyOperation; internal override bool ApplyDuringTests => true; public override void Apply(Workspace workspace, CancellationToken cancellationToken) { if (!CanApply(workspace)) return; _applyOperation.Apply(workspace, cancellationToken); } internal override Task<bool> TryApplyAsync( Workspace workspace, Solution originalSolution, IProgress<CodeAnalysisProgress> progressTracker, CancellationToken cancellationToken) { if (!CanApply(workspace)) return SpecializedTasks.False; return _applyOperation.TryApplyAsync(workspace, originalSolution, progressTracker, cancellationToken); } private bool CanApply(Workspace workspace) { return workspace.CanAddProjectReference(_referencingProject, _referencedProject); } } } }