From caedd4a8fca1a94fc7ebb372e2f2d7016cf01778 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Wed, 20 Feb 2019 08:12:30 -0600 Subject: [PATCH] Do not apply Fix All operations to generated code Fixes #33507 --- .../Core/CodeFixes/FixAllContextHelper.cs | 10 +- .../CSharp/CSharpCodeActions.cs | 140 ++++++++++++++++++ 2 files changed, 147 insertions(+), 3 deletions(-) diff --git a/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs b/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs index 83f4662c6da83..92ef8a3789232 100644 --- a/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs +++ b/src/CodeStyle/Core/CodeFixes/FixAllContextHelper.cs @@ -74,12 +74,13 @@ public static async Task>> GetDocumentDiagnosticsToFixAsync( ImmutableArray diagnostics, ImmutableArray projects, + Func isGeneratedCode, CancellationToken cancellationToken) { var treeToDocumentMap = await GetTreeToDocumentMapAsync(projects, cancellationToken).ConfigureAwait(false); @@ -89,8 +90,11 @@ private static async Task +using System; +using $$System.Threading; + +class D +{ + public IntPtr X1 { get; set; } +}"; + var expectedGeneratedSource = @"// +using System; + +class D +{ + public IntPtr X1 { get; set; } +}"; + + MarkupTestFile.GetPosition(generatedSourceMarkup, out var generatedSource, out int generatedSourcePosition); + + VisualStudio.SolutionExplorer.AddFile(new ProjectUtils.Project(ProjectName), "D.cs", generatedSource, open: false); + + // Switch to the main document we'll be editing + VisualStudio.SolutionExplorer.OpenFile(new ProjectUtils.Project(ProjectName), "Class1.cs"); + + // Verify that applying a Fix All operation does not change generated files. + // This is a regression test for correctness with respect to the design. + SetUpEditor(markup); + VisualStudio.WaitForApplicationIdle(CancellationToken.None); + VisualStudio.Editor.InvokeCodeActionList(); + VisualStudio.Editor.Verify.CodeAction( + "Remove Unnecessary Usings", + applyFix: true, + fixAllScope: scope); + + Assert.Equal(expectedText, VisualStudio.Editor.GetText()); + + VisualStudio.SolutionExplorer.OpenFile(new ProjectUtils.Project(ProjectName), "D.cs"); + Assert.Equal(generatedSource, VisualStudio.Editor.GetText()); + + // Verify that a Fix All in Document in the generated file still does nothing. + // ⚠ This is a statement of the current behavior, and not a claim regarding correctness of the design. + // The current behavior is observable; any change to this behavior should be part of an intentional design + // change. + VisualStudio.Editor.MoveCaret(generatedSourcePosition); + VisualStudio.Editor.InvokeCodeActionList(); + VisualStudio.Editor.Verify.CodeAction( + "Remove Unnecessary Usings", + applyFix: true, + fixAllScope: FixAllScope.Document); + + Assert.Equal(generatedSource, VisualStudio.Editor.GetText()); + + // Verify that the code action can still be applied manually from within the generated file. + // This is a regression test for correctness with respect to the design. + VisualStudio.Editor.MoveCaret(generatedSourcePosition); + VisualStudio.Editor.InvokeCodeActionList(); + VisualStudio.Editor.Verify.CodeAction( + "Remove Unnecessary Usings", + applyFix: true, + fixAllScope: null); + + Assert.Equal(expectedGeneratedSource, VisualStudio.Editor.GetText()); + } + + [CriticalWpfTheory] + [InlineData(FixAllScope.Project)] + [InlineData(FixAllScope.Solution)] + [Trait(Traits.Feature, Traits.Features.CodeActionsFixAllOccurrences)] + [WorkItem(33507, "https://github.com/dotnet/roslyn/issues/33507")] + public void FixAllOccurrencesTriggeredFromGeneratedCode(FixAllScope scope) + { + var markup = @"// +using System; +using $$System.Threading; + +class C +{ + public IntPtr X1 { get; set; } +}"; + var secondFile = @" +using System; +using System.Threading; + +class D +{ + public IntPtr X1 { get; set; } +}"; + var expectedSecondFile = @" +using System; + +class D +{ + public IntPtr X1 { get; set; } +}"; + + VisualStudio.SolutionExplorer.AddFile(new ProjectUtils.Project(ProjectName), "D.cs", secondFile, open: false); + + // Switch to the main document we'll be editing + VisualStudio.SolutionExplorer.OpenFile(new ProjectUtils.Project(ProjectName), "Class1.cs"); + + // Verify that applying a Fix All operation does not change generated file, but does change other files. + // ⚠ This is a statement of the current behavior, and not a claim regarding correctness of the design. + // The current behavior is observable; any change to this behavior should be part of an intentional design + // change. + MarkupTestFile.GetPosition(markup, out var expectedText, out int _); + SetUpEditor(markup); + VisualStudio.WaitForApplicationIdle(CancellationToken.None); + VisualStudio.Editor.InvokeCodeActionList(); + VisualStudio.Editor.Verify.CodeAction( + "Remove Unnecessary Usings", + applyFix: true, + fixAllScope: scope); + + Assert.Equal(expectedText, VisualStudio.Editor.GetText()); + + VisualStudio.SolutionExplorer.OpenFile(new ProjectUtils.Project(ProjectName), "D.cs"); + Assert.Equal(expectedSecondFile, VisualStudio.Editor.GetText()); + } + [WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsGenerateMethod)] public void ClassificationInPreviewPane() {