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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -87,14 +87,14 @@ private static async Task ActionSets(EditorTestWorkspace workspace, CodeRefactor
Assert.False(extensionManager.IsIgnored(provider));
}

private static CodeRefactoringSuggestedAction CreateRefactoringSuggestedAction(EditorTestWorkspace workspace, CodeRefactoringProvider provider, out EditorLayerExtensionManager.ExtensionManager extensionManager)
private static SuggestedActionWithNestedFlavors CreateRefactoringSuggestedAction(EditorTestWorkspace workspace, CodeRefactoringProvider provider, out EditorLayerExtensionManager.ExtensionManager extensionManager)
{
var codeActions = new List<CodeAction>();
RefactoringSetup(workspace, provider, codeActions, out extensionManager, out var textBuffer, out var document);
var suggestedAction = new CodeRefactoringSuggestedAction(
var suggestedAction = new SuggestedActionWithNestedFlavors(
workspace.ExportProvider.GetExportedValue<IThreadingContext>(),
workspace.ExportProvider.GetExportedValue<SuggestedActionsSourceProvider>(),
document, textBuffer, provider, codeActions.First(), fixAllFlavors: null);
document, textBuffer, provider, codeActions.First(), fixAllFlavors: null, diagnostic: null);
return suggestedAction;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions;

internal partial class SuggestedActionWithNestedFlavors
internal sealed partial class SuggestedActionWithNestedFlavors
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Folded CodeRefactoring suggested actions and CodeFix suggested actions into this common type.

{
private sealed class PreviewChangesCodeAction(
CodeAction originalCodeAction,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Collections;
using Microsoft.CodeAnalysis.Copilot;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions;

Expand All @@ -26,7 +24,7 @@ internal partial class SuggestedActionWithNestedFlavors
private sealed class RefineUsingCopilotCodeAction(
Solution originalSolution,
CodeAction originalCodeAction,
DiagnosticData? primaryDiagnostic,
Diagnostic? primaryDiagnostic,
ICopilotCodeAnalysisService copilotCodeAnalysisService) : CodeAction
{
public override string Title => EditorFeaturesResources.Refine_using_Copilot;
Expand Down Expand Up @@ -73,12 +71,8 @@ protected override async Task<ImmutableArray<CodeActionOperation>> ComputeOperat
var oldDocument = changeSummary.OldSolution.GetRequiredDocument(changedDocumentId);
var newDocument = changeSummary.NewSolution.GetRequiredDocument(changedDocumentId);

var convertedPrimaryDiagnostic = primaryDiagnostic != null
? await primaryDiagnostic.ToDiagnosticAsync(oldDocument.Project, cancellationToken).ConfigureAwait(false)
: null;

cancellationToken.ThrowIfCancellationRequested();
return [new OpenRefinementSessionOperation(oldDocument, newDocument, convertedPrimaryDiagnostic, copilotCodeAnalysisService)];
return [new OpenRefinementSessionOperation(oldDocument, newDocument, primaryDiagnostic, copilotCodeAnalysisService)];
}

/// <summary>
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,9 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeFixesAndRefactorings;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
using Microsoft.CodeAnalysis.Internal.Log;
using Microsoft.VisualStudio.Language.Intellisense;
Expand All @@ -24,28 +26,28 @@ internal sealed class RefactorOrFixAllSuggestedAction(
ITextBuffer subjectBuffer,
IRefactorOrFixAllState fixAllState,
CodeAction originalCodeAction,
string? diagnosticTelemetryId,
AbstractFixAllCodeAction fixAllCodeAction)
string? diagnosticTelemetryId)
: SuggestedAction(threadingContext,
sourceProvider,
originalSolution,
subjectBuffer,
fixAllState.FixAllProvider,
fixAllCodeAction),
fixAllState switch
{
FixAllState state => new FixAllCodeAction(state),
RefactorAllState state => new RefactorAllCodeAction(state),
_ => throw ExceptionUtilities.UnexpectedValue(fixAllState)
}),
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

note: this typeswitching goes away and gets nice in a later PR in this series.

ITelemetryDiagnosticID<string?>
{
public CodeAction OriginalCodeAction { get; } = originalCodeAction;

public IRefactorOrFixAllState FixAllState { get; } = fixAllState;

public string? GetDiagnosticID() => diagnosticTelemetryId;

public override bool TryGetTelemetryId(out Guid telemetryId)
{
// We get the telemetry id for the original code action we are fixing,
// not the special 'FixAllCodeAction'. that is the .CodeAction this
// SuggestedAction is pointing at.
telemetryId = OriginalCodeAction.GetTelemetryId(FixAllState.Scope);
telemetryId = originalCodeAction.GetTelemetryId(fixAllState.Scope);
return true;
}

Expand All @@ -54,15 +56,15 @@ protected override async Task InnerInvokeAsync(
{
await this.ThreadingContext.JoinableTaskFactory.SwitchToMainThreadAsync(cancellationToken);

var fixAllKind = FixAllState.FixAllKind;
var fixAllKind = fixAllState.FixAllKind;
var functionId = fixAllKind switch
{
FixAllKind.CodeFix => FunctionId.CodeFixes_FixAllOccurrencesSession,
FixAllKind.Refactoring => FunctionId.Refactoring_FixAllOccurrencesSession,
_ => throw ExceptionUtilities.UnexpectedValue(fixAllKind)
};

using (Logger.LogBlock(functionId, FixAllLogger.CreateCorrelationLogMessage(FixAllState.CorrelationId), cancellationToken))
using (Logger.LogBlock(functionId, FixAllLogger.CreateCorrelationLogMessage(fixAllState.CorrelationId), cancellationToken))
{
await base.InnerInvokeAsync(progress, cancellationToken).ConfigureAwait(false);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.Copilot;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.Host;
Expand All @@ -17,34 +18,37 @@
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Microsoft.VisualStudio.Language.Intellisense;
using Microsoft.VisualStudio.PlatformUI;
using Microsoft.VisualStudio.Text;

namespace Microsoft.CodeAnalysis.Editor.Implementation.Suggestions;

/// <summary>
/// Base type for all SuggestedActions that have 'flavors'. 'Flavors' are child actions that
/// are presented as simple links, not as menu-items, in the light-bulb. Examples of 'flavors'
/// include 'preview changes' (for refactorings and fixes) and 'fix all in document, project, solution'
/// (for refactorings and fixes).
/// Type for all SuggestedActions that have 'flavors'. 'Flavors' are child actions that are presented as simple links,
/// not as menu-items, in the light-bulb. Examples of 'flavors' include 'preview changes' (for refactorings and fixes)
/// and 'fix all in document, project, solution' (for refactorings and fixes).
///
/// Because all derivations support 'preview changes', we bake that logic into this base type.
/// Supports 'preview changes' for all changes.
/// </summary>
internal abstract partial class SuggestedActionWithNestedFlavors(
internal sealed partial class SuggestedActionWithNestedFlavors(
IThreadingContext threadingContext,
SuggestedActionsSourceProvider sourceProvider,
TextDocument originalDocument,
ITextBuffer subjectBuffer,
object provider,
CodeAction codeAction,
SuggestedActionSet? fixAllFlavors)
SuggestedActionSet? fixAllFlavors,
Diagnostic? diagnostic)
: SuggestedAction(threadingContext,
sourceProvider,
originalDocument.Project.Solution,
subjectBuffer,
provider,
codeAction), ISuggestedActionWithFlavors
codeAction), ISuggestedActionWithFlavors, ITelemetryDiagnosticID<string?>
{
private readonly SuggestedActionSet? _fixAllFlavors = fixAllFlavors;
private readonly Diagnostic? _diagnostic = diagnostic;

private ImmutableArray<SuggestedActionSet> _nestedFlavors;

public TextDocument OriginalDocument { get; } = originalDocument;
Expand Down Expand Up @@ -139,7 +143,7 @@ await copilotService.IsAvailableAsync(cancellationToken).ConfigureAwait(false) i

return CreateTrivialAction(
this, new RefineUsingCopilotCodeAction(
this.OriginalSolution, this.CodeAction, this.GetDiagnostic(), copilotService));
this.OriginalSolution, this.CodeAction, _diagnostic, copilotService));
}
}

Expand Down Expand Up @@ -193,8 +197,10 @@ await copilotService.IsAvailableAsync(cancellationToken).ConfigureAwait(false) i
// GetPreviewPane() needs to run on the UI thread.
this.ThreadingContext.ThrowIfNotOnUIThread();

return previewPaneService.GetPreviewPane(GetDiagnostic(), previewContents!);
var diagnosticData = _diagnostic is null ? null : CodeFix.GetDiagnosticData(this.OriginalDocument.Project, _diagnostic);
return previewPaneService.GetPreviewPane(diagnosticData, previewContents!);
}

protected virtual DiagnosticData? GetDiagnostic() => null;
public string? GetDiagnosticID()
=> _diagnostic?.GetTelemetryDiagnosticID();
}
Original file line number Diff line number Diff line change
Expand Up @@ -287,25 +287,20 @@ async Task<ImmutableArray<UnifiedSuggestedActionSet>> GetRefactoringsAsync()
ISuggestedAction ConvertToSuggestedAction(UnifiedSuggestedAction unifiedSuggestedAction)
=> unifiedSuggestedAction switch
{
UnifiedCodeFixSuggestedAction codeFixAction => new CodeFixSuggestedAction(
UnifiedCodeFixSuggestedAction codeFixAction => new SuggestedActionWithNestedFlavors(
_threadingContext, owner, originalDocument, subjectBuffer,
codeFixAction.CodeFix, codeFixAction.Provider, codeFixAction.OriginalCodeAction,
ConvertToSuggestedActionSet(codeFixAction.FixAllFlavors, originalDocument)),
UnifiedCodeRefactoringSuggestedAction codeRefactoringAction => new CodeRefactoringSuggestedAction(
codeFixAction.Provider, codeFixAction.OriginalCodeAction,
ConvertToSuggestedActionSet(codeFixAction.FixAllFlavors, originalDocument),
codeFixAction.CodeFix.PrimaryDiagnostic),
UnifiedCodeRefactoringSuggestedAction codeRefactoringAction => new SuggestedActionWithNestedFlavors(
_threadingContext, owner, originalDocument, subjectBuffer,
codeRefactoringAction.Provider, codeRefactoringAction.OriginalCodeAction,
ConvertToSuggestedActionSet(codeRefactoringAction.FixAllFlavors, originalDocument)),
UnifiedFixAllCodeFixSuggestedAction fixAllAction
ConvertToSuggestedActionSet(codeRefactoringAction.FixAllFlavors, originalDocument),
diagnostic: null),
UnifiedRefactorOrFixAllSuggestedAction refactorOrFixAllAction
=> new RefactorOrFixAllSuggestedAction(
_threadingContext, owner, originalSolution, subjectBuffer,
fixAllAction.FixAllState, fixAllAction.OriginalCodeAction, fixAllAction.TelemetryId,
new FixAllCodeAction(fixAllAction.FixAllState)),
UnifiedRefactorAllCodeRefactoringSuggestedAction fixAllCodeRefactoringAction
=> new RefactorOrFixAllSuggestedAction(
_threadingContext, owner, originalSolution, subjectBuffer,
fixAllCodeRefactoringAction.FixAllState, fixAllCodeRefactoringAction.OriginalCodeAction,
diagnosticTelemetryId: null,
new RefactorAllCodeRefactoringCodeAction(fixAllCodeRefactoringAction.FixAllState)),
refactorOrFixAllAction.FixAllState, refactorOrFixAllAction.OriginalCodeAction, refactorOrFixAllAction.TelemetryId),
UnifiedSuggestedActionWithNestedActions nestedAction => new SuggestedActionWithNestedActions(
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this code will collapse even further in following PRs.

_threadingContext, owner, originalSolution, subjectBuffer,
nestedAction.Provider, nestedAction.OriginalCodeAction,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ namespace Microsoft.CodeAnalysis.CodeRefactorings;
/// <summary>
/// Fix all code action for a code action registered by a <see cref="CodeRefactoringProvider"/>.
/// </summary>
internal sealed class RefactorAllCodeRefactoringCodeAction(IRefactorOrFixAllState fixAllState)
internal sealed class RefactorAllCodeAction(IRefactorOrFixAllState fixAllState)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

named this akin to FixAllCodeAction.

NOte: a following PR merges those into one RefactorOrFixAllCodeAction.

: AbstractFixAllCodeAction(fixAllState, showPreviewChangesDialog: true)
{
protected override IRefactorOrFixAllContext CreateFixAllContext(IRefactorOrFixAllState fixAllState, IProgress<CodeAnalysisProgress> progressTracker, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,22 @@

using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixesAndRefactorings;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.CodeRefactorings;

namespace Microsoft.CodeAnalysis.UnifiedSuggestions;

/// <summary>
/// Similar to FixAllCodeFixSuggestedAction, but in a location that can be used by
/// both local Roslyn and LSP.
/// </summary>
internal sealed class UnifiedFixAllCodeFixSuggestedAction(
internal sealed class UnifiedRefactorOrFixAllSuggestedAction(
CodeAction codeAction,
CodeActionPriority codeActionPriority,
IRefactorOrFixAllState fixAllState,
object provider,
Diagnostic diagnostic)
: UnifiedSuggestedAction(codeAction, codeActionPriority, provider, codeRefactoringKind: null, diagnostic.GetTelemetryDiagnosticID())
CodeRefactoringKind? codeRefactoringKind,
string? telemetryDiagnosticID)
: UnifiedSuggestedAction(codeAction, codeActionPriority, provider, codeRefactoringKind, telemetryDiagnosticID)
{
public IRefactorOrFixAllState FixAllState { get; } = fixAllState;
}

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -243,8 +243,9 @@ static CodeFixGroupKey GetGroupKey(CodeFix fix)
}

var fixAllStateForScope = fixAllState.With(scope: scope, codeActionEquivalenceKey: action.EquivalenceKey);
var fixAllSuggestedAction = new UnifiedFixAllCodeFixSuggestedAction(
action, action.Priority, fixAllStateForScope, fixAllState.Provider, firstDiagnostic);
var fixAllSuggestedAction = new UnifiedRefactorOrFixAllSuggestedAction(
action, action.Priority, fixAllStateForScope, fixAllState.Provider,
codeRefactoringKind: null, firstDiagnostic.GetTelemetryDiagnosticID());

fixAllSuggestedActions.Add(fixAllSuggestedAction);
}
Expand Down Expand Up @@ -611,8 +612,9 @@ async Task<UnifiedSuggestedAction> GetUnifiedSuggestedActionSetAsync(CodeAction
continue;
}

var fixAllSuggestedAction = new UnifiedRefactorAllCodeRefactoringSuggestedAction(
action, action.Priority, provider, fixAllState);
var fixAllSuggestedAction = new UnifiedRefactorOrFixAllSuggestedAction(
action, action.Priority, fixAllState, provider,
provider.Kind, telemetryDiagnosticID: null);

fixAllSuggestedActions.Add(fixAllSuggestedAction);
}
Expand Down
Loading
Loading