提交 5ed5d1b2 编写于 作者: M Manish Vasani

Few more API and functionality changes for disconnected baselining scenario:

1) Add an API to the suppression fix service to create a baseline for a given project/solution
2) Don't show preview changes dialog for baseline operation.
上级 416551e5
......@@ -59,7 +59,7 @@ internal class CodeFixSuggestedAction : SuggestedActionWithFlavors, ITelemetryDi
foreach (var scope in fixAllCodeActionContext.SupportedScopes)
{
var fixAllContext = fixAllCodeActionContext.GetContextForScopeAndActionId(scope, action.EquivalenceKey);
var fixAllAction = new FixAllCodeAction(fixAllContext, fixAllCodeActionContext.FixAllProvider);
var fixAllAction = new FixAllCodeAction(fixAllContext, fixAllCodeActionContext.FixAllProvider, showPreviewChangesDialog: true);
var fixAllSuggestedAction = new FixAllSuggestedAction(workspace, subjectBuffer, editHandler,
fixAllAction, fixAllCodeActionContext.FixAllProvider, fixAllCodeActionContext.OriginalDiagnostics.First());
fixAllSuggestedActions.Add(fixAllSuggestedAction);
......
......@@ -31,7 +31,7 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
return this;
}
public async Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(FixAllProvider fixAllProvider, FixAllContext fixAllContext, string fixAllPreviewChangesTitle, string waitDialogMessage)
public async Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(FixAllProvider fixAllProvider, FixAllContext fixAllContext, string fixAllTitle, string waitDialogMessage, bool showPreviewChangesDialog)
{
// Compute fix all occurrences code fix for the given fix all context.
// Bring up a cancellable wait dialog.
......@@ -40,7 +40,7 @@ public async Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(Fix
using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesComputation, fixAllContext.CancellationToken))
{
var result = _waitIndicator.Wait(
fixAllPreviewChangesTitle,
fixAllTitle,
waitDialogMessage,
allowCancel: true,
action: waitContext =>
......@@ -75,10 +75,10 @@ public async Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(Fix
}
FixAllLogger.LogComputationResult(completed: true);
return await GetFixAllOperationsAsync(codeAction, fixAllContext, fixAllPreviewChangesTitle).ConfigureAwait(false);
return await GetFixAllOperationsAsync(codeAction, fixAllContext, fixAllTitle, showPreviewChangesDialog).ConfigureAwait(false);
}
private async Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(CodeAction codeAction, FixAllContext fixAllContext, string fixAllPreviewChangesTitle)
private async Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(CodeAction codeAction, FixAllContext fixAllContext, string fixAllPreviewChangesTitle, bool showPreviewChangesDialog)
{
// We have computed the fix all occurrences code fix.
// Now fetch the new solution with applied fix and bring up the Preview changes dialog.
......@@ -96,32 +96,35 @@ private async Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(Co
cancellationToken.ThrowIfCancellationRequested();
var newSolution = await codeAction.GetChangedSolutionInternalAsync(cancellationToken).ConfigureAwait(false);
cancellationToken.ThrowIfCancellationRequested();
using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesPreviewChanges, cancellationToken))
if (showPreviewChangesDialog)
{
var previewService = workspace.Services.GetService<IPreviewDialogService>();
var glyph = fixAllContext.Project.Language == LanguageNames.CSharp ?
Glyph.CSharpProject :
Glyph.BasicProject;
var changedSolution = previewService.PreviewChanges(
string.Format(EditorFeaturesResources.PreviewChangesOf, fixAllPreviewChangesTitle),
"vs.codefix.fixall",
codeAction.Title,
fixAllPreviewChangesTitle,
glyph,
newSolution,
fixAllContext.Project.Solution);
if (changedSolution == null)
cancellationToken.ThrowIfCancellationRequested();
using (Logger.LogBlock(FunctionId.CodeFixes_FixAllOccurrencesPreviewChanges, cancellationToken))
{
// User clicked cancel.
FixAllLogger.LogPreviewChangesResult(applied: false);
return null;
}
var previewService = workspace.Services.GetService<IPreviewDialogService>();
var glyph = fixAllContext.Project.Language == LanguageNames.CSharp ?
Glyph.CSharpProject :
Glyph.BasicProject;
var changedSolution = previewService.PreviewChanges(
string.Format(EditorFeaturesResources.PreviewChangesOf, fixAllPreviewChangesTitle),
"vs.codefix.fixall",
codeAction.Title,
fixAllPreviewChangesTitle,
glyph,
newSolution,
fixAllContext.Project.Solution);
FixAllLogger.LogPreviewChangesResult(applied: true, allChangesApplied: changedSolution == newSolution);
newSolution = changedSolution;
if (changedSolution == null)
{
// User clicked cancel.
FixAllLogger.LogPreviewChangesResult(applied: false);
return null;
}
FixAllLogger.LogPreviewChangesResult(applied: true, allChangesApplied: changedSolution == newSolution);
newSolution = changedSolution;
}
}
// Get a code action, with apply changes operation replaced with the newSolution.
......
......@@ -35,12 +35,13 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
CodeFixProvider fixProvider,
FixAllProvider fixAllProvider,
string equivalenceKey,
string previewChangesTitle,
string waitDialogAndPreviewChangesTitle,
string waitDialogMessage,
bool showPreviewChangesDialog,
CancellationToken cancellationToken)
{
var fixMultipleContext = FixMultipleContext.Create(diagnosticsToFix, fixProvider, equivalenceKey, cancellationToken);
ComputeAndApplyFix(fixMultipleContext, workspace, fixAllProvider, previewChangesTitle, waitDialogMessage, cancellationToken);
ComputeAndApplyFix(fixMultipleContext, workspace, fixAllProvider, waitDialogAndPreviewChangesTitle, waitDialogMessage, showPreviewChangesDialog, cancellationToken);
}
public void ComputeAndApplyFix(
......@@ -49,23 +50,25 @@ public IWorkspaceService CreateService(HostWorkspaceServices workspaceServices)
CodeFixProvider fixProvider,
FixAllProvider fixAllProvider,
string equivalenceKey,
string previewChangesTitle,
string waitDialogAndPreviewChangesTitle,
string waitDialogMessage,
bool showPreviewChangesDialog,
CancellationToken cancellationToken)
{
var fixMultipleContext = FixMultipleContext.Create(diagnosticsToFix, fixProvider, equivalenceKey, cancellationToken);
ComputeAndApplyFix(fixMultipleContext, workspace, fixAllProvider, previewChangesTitle, waitDialogMessage, cancellationToken);
ComputeAndApplyFix(fixMultipleContext, workspace, fixAllProvider, waitDialogAndPreviewChangesTitle, waitDialogMessage, showPreviewChangesDialog, cancellationToken);
}
private void ComputeAndApplyFix(
FixMultipleContext fixMultipleContext,
Workspace workspace,
FixAllProvider fixAllProvider,
string previewChangesTitle,
string waitDialogAndPreviewChangesTitle,
string waitDialogMessage,
bool showPreviewChangesDialog,
CancellationToken cancellationToken)
{
var fixMultipleCodeAction = new FixMultipleCodeAction(fixMultipleContext, fixAllProvider, title: previewChangesTitle, previewChangesDialogTitle: previewChangesTitle, computingFixWaitDialogMessage: waitDialogMessage);
var fixMultipleCodeAction = new FixMultipleCodeAction(fixMultipleContext, fixAllProvider, title: waitDialogAndPreviewChangesTitle, previewChangesDialogTitle: waitDialogAndPreviewChangesTitle, computingFixWaitDialogMessage: waitDialogMessage, showPreviewChangesDialog: showPreviewChangesDialog);
var fixMultipleSuggestedAction = new FixMultipleSuggestedAction(workspace, _editHandler, fixMultipleCodeAction, fixAllProvider);
fixMultipleSuggestedAction.Invoke(cancellationToken);
}
......
......@@ -17,12 +17,14 @@ internal partial class FixAllCodeAction : CodeAction
{
private readonly FixAllContext _fixAllContext;
private readonly FixAllProvider _fixAllProvider;
private readonly bool _showPreviewChangesDialog;
private static readonly HashSet<string> s_predefinedCodeFixProviderNames = GetPredefinedCodeFixProviderNames();
internal FixAllCodeAction(FixAllContext fixAllContext, FixAllProvider fixAllProvider)
internal FixAllCodeAction(FixAllContext fixAllContext, FixAllProvider fixAllProvider, bool showPreviewChangesDialog)
{
_fixAllContext = fixAllContext;
_fixAllProvider = fixAllProvider;
_showPreviewChangesDialog = showPreviewChangesDialog;
}
public override string Title
......@@ -54,7 +56,7 @@ protected override async Task<IEnumerable<CodeActionOperation>> ComputeOperation
var service = _fixAllContext.Project.Solution.Workspace.Services.GetService<IFixAllGetFixesService>();
// Use the new cancellation token instead of the stale one present inside _fixAllContext.
return await service.GetFixAllOperationsAsync(_fixAllProvider, _fixAllContext.WithCancellationToken(cancellationToken), FixAllPreviewChangesTitle, ComputingFixAllWaitDialogMessage).ConfigureAwait(false);
return await service.GetFixAllOperationsAsync(_fixAllProvider, _fixAllContext.WithCancellationToken(cancellationToken), FixAllPreviewChangesTitle, ComputingFixAllWaitDialogMessage, _showPreviewChangesDialog).ConfigureAwait(false);
}
private static bool IsInternalCodeFixProvider(CodeFixProvider fixer)
......
......@@ -11,8 +11,8 @@ internal partial class FixMultipleCodeAction : FixAllCodeAction
private readonly string _previewChangesDialogTitle;
private readonly string _computingFixWaitDialogMessage;
internal FixMultipleCodeAction(FixMultipleContext fixMultipleContext, FixAllProvider fixAllProvider, string title, string previewChangesDialogTitle, string computingFixWaitDialogMessage)
: base (fixMultipleContext, fixAllProvider)
internal FixMultipleCodeAction(FixMultipleContext fixMultipleContext, FixAllProvider fixAllProvider, string title, string previewChangesDialogTitle, string computingFixWaitDialogMessage, bool showPreviewChangesDialog)
: base (fixMultipleContext, fixAllProvider, showPreviewChangesDialog)
{
_title = title;
_previewChangesDialogTitle = previewChangesDialogTitle;
......
......@@ -13,6 +13,6 @@ internal interface IFixAllGetFixesService : IWorkspaceService
/// Computes the fix all occurrences code fix, brings up the preview changes dialog for the fix and
/// returns the code action operations corresponding to the fix.
/// </summary>
Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(FixAllProvider fixAllProvider, FixAllContext fixAllContext, string fixAllPreviewChangesTitle, string waitDialogMessage);
Task<IEnumerable<CodeActionOperation>> GetFixAllOperationsAsync(FixAllProvider fixAllProvider, FixAllContext fixAllContext, string fixAllTitle, string waitDialogMessage, bool showPreviewChangesDialog);
}
}
......@@ -18,8 +18,9 @@ internal interface IFixMultipleOccurrencesService : IWorkspaceService
CodeFixProvider fixProvider,
FixAllProvider fixAllProvider,
string equivalenceKey,
string previewChangesTitle,
string waitDialogAndPreviewChangesTitle,
string waitDialogMessage,
bool showPreviewChangesDialog,
CancellationToken cancellationToken);
/// <summary>
......@@ -32,8 +33,9 @@ internal interface IFixMultipleOccurrencesService : IWorkspaceService
CodeFixProvider fixProvider,
FixAllProvider fixAllProvider,
string equivalenceKey,
string previewChangesTitle,
string waitDialogAndPreviewChangesTitle,
string waitDialogMessage,
bool showPreviewChangesDialog,
CancellationToken cancellationToken);
}
}
......@@ -57,7 +57,7 @@ internal class DiagnosticAnalyzerDriver
owner.GetOnAnalyzerException(project.Id),
concurrentAnalysis: false,
logAnalyzerExecutionTime: true,
reportDiagnosticsWithSourceSuppression: true);
reportSuppressedDiagnostics: true);
_lazyCompilationWithAnalyzers = null;
}
......
......@@ -20,9 +20,9 @@ internal partial class DiagnosticTableControlEventProcessorProvider : AbstractTa
[ImportingConstructor]
public DiagnosticTableControlEventProcessorProvider(
VisualStudioDiagnosticListSuppressionStateService suppressionStateService)
IVisualStudioDiagnosticListSuppressionStateService suppressionStateService)
{
_suppressionStateService = suppressionStateService;
_suppressionStateService = (VisualStudioDiagnosticListSuppressionStateService)suppressionStateService;
}
protected override EventProcessor CreateEventProcessor()
......
......@@ -10,6 +10,12 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Suppression
/// <remarks>TODO: Move to the core platform layer.</remarks>
internal interface IVisualStudioSuppressionFixService
{
/// <summary>
/// Adds source suppressions for all the diagnostics in the error list, i.e. baseline all active issues.
/// </summary>
/// <param name="projectHierarchyOpt">An optional project hierarchy object in the solution explorer. If non-null, then only the diagnostics from the project will be suppressed.</param>
void AddSuppressions(IVsHierarchy projectHierarchyOpt);
/// <summary>
/// Adds source suppressions for diagnostics.
/// </summary>
......
......@@ -18,8 +18,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.TableDataSource
/// <summary>
/// Service to maintain information about the suppression state of specific set of items in the error list.
/// </summary>
[Export(typeof(VisualStudioDiagnosticListSuppressionStateService))]
internal class VisualStudioDiagnosticListSuppressionStateService
[Export(typeof(IVisualStudioDiagnosticListSuppressionStateService))]
internal class VisualStudioDiagnosticListSuppressionStateService : IVisualStudioDiagnosticListSuppressionStateService
{
private readonly VisualStudioWorkspace _workspace;
private readonly IVsUIShell _shellService;
......@@ -171,7 +171,7 @@ private static AbstractTableEntriesSnapshot<DiagnosticData> GetEntriesSnapshot(I
/// <summary>
/// Gets <see cref="DiagnosticData"/> objects for error list entries, filtered based on the given parameters.
/// </summary>
public ImmutableArray<DiagnosticData> GetItems(bool selectedEntriesOnly, bool isAddSuppression, bool isSuppressionInSource, CancellationToken cancellationToken)
public ImmutableArray<DiagnosticData> GetItems(bool selectedEntriesOnly, bool isAddSuppression, bool isSuppressionInSource, bool onlyCompilerDiagnostics, CancellationToken cancellationToken)
{
var builder = ImmutableArray.CreateBuilder<DiagnosticData>();
var entries = selectedEntriesOnly ? _tableControl.SelectedEntries : _tableControl.Entries;
......@@ -187,11 +187,17 @@ public ImmutableArray<DiagnosticData> GetItems(bool selectedEntriesOnly, bool is
diagnosticData = roslynSnapshot.GetItem(index)?.Primary;
if (diagnosticData != null && diagnosticData.HasTextSpan)
{
var isCompilerDiagnostic = SuppressionHelpers.IsCompilerDiagnostic(diagnosticData);
if (onlyCompilerDiagnostics && !isCompilerDiagnostic)
{
continue;
}
if (isAddSuppression)
{
// Compiler diagnostics can only be suppressed in source.
if (!diagnosticData.IsSuppressed &&
(isSuppressionInSource || !SuppressionHelpers.IsCompilerDiagnostic(diagnosticData)))
(isSuppressionInSource || !isCompilerDiagnostic))
{
builder.Add(diagnosticData);
}
......
......@@ -16,11 +16,11 @@ internal partial class VisualStudioDiagnosticListTableCommandHandler
[ImportingConstructor]
public VisualStudioDiagnosticListTableCommandHandler(
VisualStudioSuppressionFixService suppressionFixService,
VisualStudioDiagnosticListSuppressionStateService suppressionStateService)
IVisualStudioSuppressionFixService suppressionFixService,
IVisualStudioDiagnosticListSuppressionStateService suppressionStateService)
{
_suppressionFixService = suppressionFixService;
_suppressionStateService = suppressionStateService;
_suppressionFixService = (VisualStudioSuppressionFixService)suppressionFixService;
_suppressionStateService = (VisualStudioDiagnosticListSuppressionStateService)suppressionStateService;
}
public void Initialize(IServiceProvider serviceProvider)
......
......@@ -23,8 +23,8 @@ namespace Microsoft.VisualStudio.LanguageServices.Implementation.Suppression
/// <summary>
/// Service to compute and apply bulk suppression fixes.
/// </summary>
[Export(typeof(VisualStudioSuppressionFixService))]
internal sealed class VisualStudioSuppressionFixService
[Export(typeof(IVisualStudioSuppressionFixService))]
internal sealed class VisualStudioSuppressionFixService : IVisualStudioSuppressionFixService
{
private readonly VisualStudioWorkspaceImpl _workspace;
private readonly IWpfTableControl _tableControl;
......@@ -40,13 +40,13 @@ internal sealed class VisualStudioSuppressionFixService
VisualStudioWorkspaceImpl workspace,
IDiagnosticAnalyzerService diagnosticService,
ICodeFixService codeFixService,
VisualStudioDiagnosticListSuppressionStateService suppressionStateService,
IVisualStudioDiagnosticListSuppressionStateService suppressionStateService,
IWaitIndicator waitIndicator)
{
_workspace = workspace;
_diagnosticService = diagnosticService;
_codeFixService = codeFixService;
_suppressionStateService = suppressionStateService;
_suppressionStateService = (VisualStudioDiagnosticListSuppressionStateService)suppressionStateService;
_waitIndicator = waitIndicator;
_fixMultipleOccurencesService = workspace.Services.GetService<IFixMultipleOccurrencesService>();
......@@ -54,6 +54,16 @@ internal sealed class VisualStudioSuppressionFixService
_tableControl = errorList?.TableControl;
}
public void AddSuppressions(IVsHierarchy projectHierarchyOpt)
{
Func<Project, bool> shouldFixInProject = GetShouldFixInProjectDelegate(_workspace, projectHierarchyOpt);
// Apply suppressions fix in global suppressions file for non-compiler diagnostics and
// in source only for compiler diagnostics.
ApplySuppressionFix(shouldFixInProject, selectedEntriesOnly: false, isAddSuppression: true, isSuppressionInSource: false, onlyCompilerDiagnostics: false, showPreviewChangesDialog: false);
ApplySuppressionFix(shouldFixInProject, selectedEntriesOnly: false, isAddSuppression: true, isSuppressionInSource: true, onlyCompilerDiagnostics: true, showPreviewChangesDialog: false);
}
public void AddSuppressions(bool selectedErrorListEntriesOnly, bool suppressInSource, IVsHierarchy projectHierarchyOpt)
{
if (_tableControl == null)
......@@ -62,7 +72,7 @@ public void AddSuppressions(bool selectedErrorListEntriesOnly, bool suppressInSo
}
Func<Project, bool> shouldFixInProject = GetShouldFixInProjectDelegate(_workspace, projectHierarchyOpt);
ApplySuppressionFix(selectedErrorListEntriesOnly, suppressInSource, shouldFixInProject);
ApplySuppressionFix(shouldFixInProject, selectedErrorListEntriesOnly, isAddSuppression: true, isSuppressionInSource: suppressInSource, onlyCompilerDiagnostics: false, showPreviewChangesDialog: true);
}
private static Func<Project, bool> GetShouldFixInProjectDelegate(VisualStudioWorkspaceImpl workspace, IVsHierarchy projectHierarchyOpt)
......@@ -92,7 +102,7 @@ public void RemoveSuppressions(bool selectedErrorListEntriesOnly, IVsHierarchy p
// TODO
}
private void ApplySuppressionFix(bool selectedEntriesOnly, bool suppressInSource, Func<Project, bool> shouldFixInProject)
private void ApplySuppressionFix(Func<Project, bool> shouldFixInProject, bool selectedEntriesOnly, bool isAddSuppression, bool isSuppressionInSource, bool onlyCompilerDiagnostics, bool showPreviewChangesDialog)
{
ImmutableDictionary<Document, ImmutableArray<Diagnostic>> diagnosticsToFixMap = null;
......@@ -107,9 +117,10 @@ private void ApplySuppressionFix(bool selectedEntriesOnly, bool suppressInSource
{
var diagnosticsToFix = _suppressionStateService.GetItems(
selectedEntriesOnly,
isAddSuppression: true,
isSuppressionInSource: suppressInSource,
cancellationToken: waitContext.CancellationToken);
isAddSuppression,
isSuppressionInSource,
onlyCompilerDiagnostics,
waitContext.CancellationToken);
if (diagnosticsToFix.IsEmpty)
{
......@@ -131,7 +142,7 @@ private void ApplySuppressionFix(bool selectedEntriesOnly, bool suppressInSource
return;
}
var equivalenceKey = suppressInSource ? FeaturesResources.SuppressWithPragma : FeaturesResources.SuppressWithGlobalSuppressMessage;
var equivalenceKey = isSuppressionInSource ? FeaturesResources.SuppressWithPragma : FeaturesResources.SuppressWithGlobalSuppressMessage;
// We have different suppression fixers for every language.
// So we need to group diagnostics by the containing project language and apply fixes separately.
......@@ -144,7 +155,7 @@ private void ApplySuppressionFix(bool selectedEntriesOnly, bool suppressInSource
foreach (var group in groups)
{
var language = group.Key;
var previewChangesTitle = hasMultipleLangauges ? string.Format(ServicesVSResources.SuppressMultipleOccurrencesForLanguage, language) : ServicesVSResources.SuppressMultipleOccurrences;
var waitDialogAndPreviewChangesTitle = hasMultipleLangauges ? string.Format(ServicesVSResources.SuppressMultipleOccurrencesForLanguage, language) : ServicesVSResources.SuppressMultipleOccurrences;
var waitDialogMessage = hasMultipleLangauges ? string.Format(ServicesVSResources.ComputingSuppressionFixForLanguage, language) : ServicesVSResources.ComputingSuppressionFix;
ImmutableDictionary<Document, ImmutableArray<Diagnostic>> documentDiagnosticsPerLanguage = null;
......@@ -192,8 +203,9 @@ private void ApplySuppressionFix(bool selectedEntriesOnly, bool suppressInSource
suppressionFixer,
suppressionFixer.GetFixAllProvider(),
equivalenceKey,
previewChangesTitle,
waitDialogAndPreviewChangesTitle,
waitDialogMessage,
showPreviewChangesDialog,
CancellationToken.None);
newSolution = _workspace.CurrentSolution;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册