From 66ed015bd545661a3b4af220873d2946f33ef57f Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Tue, 3 Mar 2020 17:15:12 -0800 Subject: [PATCH] Add ability to run IDE analyzer/fixer tests in CodeStyle layer --- Roslyn.sln | 7 + .../Microsoft.CodeAnalysis.CodeStyle.csproj | 1 - .../Core/Analyzers/PublicAPI.Unshipped.txt | 5 + ...rosoft.CodeAnalysis.CodeStyle.Fixes.csproj | 1 - ...nalysis.CodeStyle.UnitTestUtilities.csproj | 22 +- ....CodeAnalysis.CSharp.EditorFeatures.csproj | 1 + ...sis.CSharp.EditorFeatures.UnitTests.csproj | 1 + ...is.CSharp.EditorFeatures2.UnitTests.csproj | 1 + ...oft.CodeAnalysis.EditorFeatures.Wpf.csproj | 1 + ...crosoft.CodeAnalysis.EditorFeatures.csproj | 1 + .../AbstractChangeSignatureTests.cs | 2 +- .../ChangeSignatureTestState.cs | 0 .../AbstractCodeActionOrUserDiagnosticTest.cs | 285 +++++++++--------- ...ionOrUserDiagnosticTest_TestAddDocument.cs | 153 ++++++++++ .../CodeActions/AbstractCodeActionTest.cs | 2 +- .../CSharpCodeFixVerifier`2+Test.cs | 4 +- .../CodeActions/CSharpCodeFixVerifier`2.cs | 0 .../CodeActions/CodeFixVerifierHelper.cs | 18 +- .../CodeActions/OptionsCollection.cs | 5 + .../VisualBasicCodeFixVerifier`2+Test.cs | 4 +- .../VisualBasicCodeFixVerifier`2.cs | 0 ...agnosticProviderBasedUserDiagnosticTest.cs | 62 +--- ...edUserDiagnosticTest_ParenthesesOptions.cs | 66 ++++ .../AbstractSuppressionAllCodeTests.cs | 0 .../AbstractSuppressionDiagnosticTest.cs | 0 ...iagnosticTest.FixAllDiagnosticProvider.cs} | 0 .../Diagnostics/AbstractUserDiagnosticTest.cs | 166 +--------- ...ctUserDiagnosticTest_GenerateTypeDialog.cs | 176 +++++++++++ ...Features.DiagnosticsTests.Utilities.csproj | 59 ++++ .../AbstractMoveToNamespaceTests.TestState.cs | 0 .../AbstractMoveToNamespaceTests.cs | 0 .../MoveType/AbstractMoveTypeTest.cs | 0 ...deAnalysis.EditorFeatures.UnitTests.csproj | 1 + .../Roslyn.Services.Test.Utilities.csproj | 7 + .../Workspaces/TestHostProject.cs | 5 +- .../TestUtilities/Workspaces/TestWorkspace.cs | 14 +- ...isualBasic.EditorFeatures.UnitTests.vbproj | 1 + ...rosoft.CodeAnalysis.CSharp.Features.csproj | 1 + .../Microsoft.CodeAnalysis.Features.csproj | 1 + ...t.CodeAnalysis.VisualBasic.Features.vbproj | 1 + .../Microsoft.CodeAnalysis.Workspaces.csproj | 7 + .../IEditorConfigStorageLocation.cs | 4 +- .../IEditorConfigStorageLocation2.cs | 4 +- 43 files changed, 711 insertions(+), 378 deletions(-) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/ChangeSignature/AbstractChangeSignatureTests.cs (99%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/ChangeSignature/ChangeSignatureTestState.cs (100%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs (84%) create mode 100644 src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest_TestAddDocument.cs rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/CodeActions/AbstractCodeActionTest.cs (98%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/CodeActions/CSharpCodeFixVerifier`2+Test.cs (97%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/CodeActions/CSharpCodeFixVerifier`2.cs (100%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/CodeActions/CodeFixVerifierHelper.cs (93%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/CodeActions/OptionsCollection.cs (96%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs (95%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/CodeActions/VisualBasicCodeFixVerifier`2.cs (100%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/Diagnostics/AbstractDiagnosticProviderBasedUserDiagnosticTest.cs (76%) create mode 100644 src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractDiagnosticProviderBasedUserDiagnosticTest_ParenthesesOptions.cs rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/Diagnostics/AbstractSuppressionAllCodeTests.cs (100%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/Diagnostics/AbstractSuppressionDiagnosticTest.cs (100%) rename src/EditorFeatures/{TestUtilities/Diagnostics/FixAllDiagnosticProvider.cs => DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest.FixAllDiagnosticProvider.cs} (100%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/Diagnostics/AbstractUserDiagnosticTest.cs (62%) create mode 100644 src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs create mode 100644 src/EditorFeatures/DiagnosticsTestUtilities/Microsoft.CodeAnalysis.EditorFeatures.DiagnosticsTests.Utilities.csproj rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/MoveToNamespace/AbstractMoveToNamespaceTests.TestState.cs (100%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/MoveToNamespace/AbstractMoveToNamespaceTests.cs (100%) rename src/EditorFeatures/{TestUtilities => DiagnosticsTestUtilities}/MoveType/AbstractMoveTypeTest.cs (100%) diff --git a/Roslyn.sln b/Roslyn.sln index 195ddaf0861..3f58a48bea1 100644 --- a/Roslyn.sln +++ b/Roslyn.sln @@ -458,6 +458,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Compiler", "Compiler", "{7A EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Workspace", "Workspace", "{9C1BE25C-5926-4E56-84AE-D2242CB0627E}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Microsoft.CodeAnalysis.EditorFeatures.DiagnosticsTests.Utilities", "src\EditorFeatures\DiagnosticsTestUtilities\Microsoft.CodeAnalysis.EditorFeatures.DiagnosticsTests.Utilities.csproj", "{B64766CD-1A1F-4C1B-B11F-C30F82B8E41E}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Analyzers\VisualBasic\CodeFixes\VisualBasicCodeFixes.projitems*{0141285d-8f6c-42c7-baf3-3c0ccd61c716}*SharedItemsImports = 5 @@ -1201,6 +1203,10 @@ Global {D55FB2BD-CC9E-454B-9654-94AF5D910BF7}.Debug|Any CPU.Build.0 = Debug|Any CPU {D55FB2BD-CC9E-454B-9654-94AF5D910BF7}.Release|Any CPU.ActiveCfg = Release|Any CPU {D55FB2BD-CC9E-454B-9654-94AF5D910BF7}.Release|Any CPU.Build.0 = Release|Any CPU + {B64766CD-1A1F-4C1B-B11F-C30F82B8E41E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B64766CD-1A1F-4C1B-B11F-C30F82B8E41E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B64766CD-1A1F-4C1B-B11F-C30F82B8E41E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B64766CD-1A1F-4C1B-B11F-C30F82B8E41E}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -1414,6 +1420,7 @@ Global {DF17AF27-AA02-482B-8946-5CA8A50D5A2B} = {55A62CFA-1155-46F1-ADF3-BEEE51B58AB5} {7A69EA65-4411-4CD0-B439-035E720C1BD3} = {DF17AF27-AA02-482B-8946-5CA8A50D5A2B} {9C1BE25C-5926-4E56-84AE-D2242CB0627E} = {DF17AF27-AA02-482B-8946-5CA8A50D5A2B} + {B64766CD-1A1F-4C1B-B11F-C30F82B8E41E} = {EE97CB90-33BB-4F3A-9B3D-69375DEC6AC6} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {604E6B91-7BC0-4126-AE07-D4D2FEFC3D29} diff --git a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj index 2f9d50356a7..7012808127b 100644 --- a/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj +++ b/src/CodeStyle/Core/Analyzers/Microsoft.CodeAnalysis.CodeStyle.csproj @@ -22,7 +22,6 @@ - diff --git a/src/CodeStyle/Core/Analyzers/PublicAPI.Unshipped.txt b/src/CodeStyle/Core/Analyzers/PublicAPI.Unshipped.txt index b4390156271..d3e79ca06ae 100644 --- a/src/CodeStyle/Core/Analyzers/PublicAPI.Unshipped.txt +++ b/src/CodeStyle/Core/Analyzers/PublicAPI.Unshipped.txt @@ -1,5 +1,10 @@ Microsoft.CodeAnalysis.Internal.Options.CodeStyleOptions Microsoft.CodeAnalysis.Internal.Options.CodeStyleOptions.CodeStyleOptions() -> void +Microsoft.CodeAnalysis.Internal.Options.IEditorConfigStorageLocation +Microsoft.CodeAnalysis.Internal.Options.IEditorConfigStorageLocation.TryGetOption(System.Collections.Generic.IReadOnlyDictionary rawOptions, System.Type type, out object value) -> bool +Microsoft.CodeAnalysis.Internal.Options.IEditorConfigStorageLocation2 +Microsoft.CodeAnalysis.Internal.Options.IEditorConfigStorageLocation2.GetEditorConfigString(object value, Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions optionSet) -> string +Microsoft.CodeAnalysis.Internal.Options.IEditorConfigStorageLocation2.KeyName.get -> string static readonly Microsoft.CodeAnalysis.Internal.Options.CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInDeclaration -> Microsoft.CodeAnalysis.Internal.Options.PerLanguageOption> static readonly Microsoft.CodeAnalysis.Internal.Options.CodeStyleOptions.PreferIntrinsicPredefinedTypeKeywordInMemberAccess -> Microsoft.CodeAnalysis.Internal.Options.PerLanguageOption> static readonly Microsoft.CodeAnalysis.Internal.Options.CodeStyleOptions.QualifyEventAccess -> Microsoft.CodeAnalysis.Internal.Options.PerLanguageOption> diff --git a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj index ca166bfb592..e8a71ae6df8 100644 --- a/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj +++ b/src/CodeStyle/Core/CodeFixes/Microsoft.CodeAnalysis.CodeStyle.Fixes.csproj @@ -16,7 +16,6 @@ - diff --git a/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTestUtilities.csproj b/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTestUtilities.csproj index 31658eaafb3..93319f413ae 100644 --- a/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTestUtilities.csproj +++ b/src/CodeStyle/Core/Tests/Microsoft.CodeAnalysis.CodeStyle.UnitTestUtilities.csproj @@ -9,13 +9,16 @@ false - - - - - - - + + + + + + + + + + @@ -31,6 +34,11 @@ + + + + + diff --git a/src/EditorFeatures/CSharp/Microsoft.CodeAnalysis.CSharp.EditorFeatures.csproj b/src/EditorFeatures/CSharp/Microsoft.CodeAnalysis.CSharp.EditorFeatures.csproj index 54bff949000..c4580a668d4 100644 --- a/src/EditorFeatures/CSharp/Microsoft.CodeAnalysis.CSharp.EditorFeatures.csproj +++ b/src/EditorFeatures/CSharp/Microsoft.CodeAnalysis.CSharp.EditorFeatures.csproj @@ -32,6 +32,7 @@ + diff --git a/src/EditorFeatures/CSharpTest/Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj b/src/EditorFeatures/CSharpTest/Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj index ad56fce6215..70a43dde152 100644 --- a/src/EditorFeatures/CSharpTest/Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj +++ b/src/EditorFeatures/CSharpTest/Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj @@ -26,6 +26,7 @@ + diff --git a/src/EditorFeatures/CSharpTest2/Microsoft.CodeAnalysis.CSharp.EditorFeatures2.UnitTests.csproj b/src/EditorFeatures/CSharpTest2/Microsoft.CodeAnalysis.CSharp.EditorFeatures2.UnitTests.csproj index f415088dcef..7247cdceb92 100644 --- a/src/EditorFeatures/CSharpTest2/Microsoft.CodeAnalysis.CSharp.EditorFeatures2.UnitTests.csproj +++ b/src/EditorFeatures/CSharpTest2/Microsoft.CodeAnalysis.CSharp.EditorFeatures2.UnitTests.csproj @@ -24,6 +24,7 @@ + diff --git a/src/EditorFeatures/Core.Wpf/Microsoft.CodeAnalysis.EditorFeatures.Wpf.csproj b/src/EditorFeatures/Core.Wpf/Microsoft.CodeAnalysis.EditorFeatures.Wpf.csproj index 0c427bdfeef..de3d32ed696 100644 --- a/src/EditorFeatures/Core.Wpf/Microsoft.CodeAnalysis.EditorFeatures.Wpf.csproj +++ b/src/EditorFeatures/Core.Wpf/Microsoft.CodeAnalysis.EditorFeatures.Wpf.csproj @@ -50,6 +50,7 @@ + diff --git a/src/EditorFeatures/Core/Microsoft.CodeAnalysis.EditorFeatures.csproj b/src/EditorFeatures/Core/Microsoft.CodeAnalysis.EditorFeatures.csproj index 5c807fb6e18..9607fd97580 100644 --- a/src/EditorFeatures/Core/Microsoft.CodeAnalysis.EditorFeatures.csproj +++ b/src/EditorFeatures/Core/Microsoft.CodeAnalysis.EditorFeatures.csproj @@ -78,6 +78,7 @@ + diff --git a/src/EditorFeatures/TestUtilities/ChangeSignature/AbstractChangeSignatureTests.cs b/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/AbstractChangeSignatureTests.cs similarity index 99% rename from src/EditorFeatures/TestUtilities/ChangeSignature/AbstractChangeSignatureTests.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/AbstractChangeSignatureTests.cs index 66db009cf96..c7c86ad5859 100644 --- a/src/EditorFeatures/TestUtilities/ChangeSignature/AbstractChangeSignatureTests.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/AbstractChangeSignatureTests.cs @@ -161,7 +161,7 @@ private string GetSignatureDescriptionString(int[] signature, int? totalParamete /// described above. public async Task TestAllSignatureChangesAsync(string languageName, string markup, int[] signaturePartCounts, ParseOptions parseOptions = null) { - Assert.Equal(signaturePartCounts.Length, 4); + Assert.Equal(4, signaturePartCounts.Length); Assert.True(signaturePartCounts[0] == 0 || signaturePartCounts[0] == 1); Assert.True(signaturePartCounts[3] == 0 || signaturePartCounts[3] == 1); diff --git a/src/EditorFeatures/TestUtilities/ChangeSignature/ChangeSignatureTestState.cs b/src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs similarity index 100% rename from src/EditorFeatures/TestUtilities/ChangeSignature/ChangeSignatureTestState.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/ChangeSignature/ChangeSignatureTestState.cs diff --git a/src/EditorFeatures/TestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs similarity index 84% rename from src/EditorFeatures/TestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs index b2279e5f30e..cace82f08e6 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest.cs @@ -5,29 +5,35 @@ using System; using System.Collections.Generic; using System.Collections.Immutable; +using System.Diagnostics; +using System.IO; using System.Linq; using System.Text; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; -using Microsoft.CodeAnalysis.CodeStyle; -using Microsoft.CodeAnalysis.Editor.Implementation.Preview; using Microsoft.CodeAnalysis.Editor.UnitTests.Extensions; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.UnitTests; -using Roslyn.Test.Utilities; using Roslyn.Utilities; +using Roslyn.Test.Utilities; using Xunit; +#if CODE_STYLE +using Microsoft.CodeAnalysis.Internal.Options; +#else +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Options; +#endif + namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions { [UseExportProvider] - public abstract class AbstractCodeActionOrUserDiagnosticTest + public abstract partial class AbstractCodeActionOrUserDiagnosticTest { public struct TestParameters { @@ -82,6 +88,8 @@ public TestParameters WithIncludeDiagnosticsOutsideSelection(bool includeDiagnos => new TestParameters(parseOptions, compilationOptions, options, fixProviderData, index, priority, retainNonFixableDiagnostics, includeDiagnosticsOutsideSelection, title); } + private const string AutoGeneratedAnalyzerConfigHeader = @"# auto-generated .editorconfig for code style options"; + protected abstract string GetLanguage(); protected abstract ParseOptions GetScriptOptions(); @@ -92,11 +100,134 @@ public TestParameters WithIncludeDiagnosticsOutsideSelection(bool includeDiagnos ? TestWorkspace.Create(initialMarkup, openDocuments: false) : CreateWorkspaceFromFile(initialMarkup, parameters); + // For CodeStyle layer testing, we create an .editorconfig at project root + // to apply the options as workspace options are not available in CodeStyle layer. + // Otherwise, we apply the options directly to the workspace. + +#if CODE_STYLE + // We need to ensure that our projects/documents are rooted for + // execution from CodeStyle layer as we will be adding a rooted .editorconfig to each project + // to apply the options. + if (parameters.options != null) + { + MakeProjectsAndDocumentsRooted(workspace); + AddAnalyzerConfigDocumentWithOptions(workspace, parameters.options); + } +#else workspace.ApplyOptions(parameters.options); +#endif return workspace; } + private static void MakeProjectsAndDocumentsRooted(TestWorkspace workspace) + { + const string defaultRootFilePath = @"z:\"; + var newSolution = workspace.CurrentSolution; + foreach (var projectId in workspace.CurrentSolution.ProjectIds) + { + var project = newSolution.GetProject(projectId); + + string projectRootFilePath; + if (!PathUtilities.IsAbsolute(project.FilePath)) + { + projectRootFilePath = defaultRootFilePath; + newSolution = newSolution.WithProjectFilePath(projectId, Path.Combine(projectRootFilePath, project.FilePath)); + } + else + { + projectRootFilePath = PathUtilities.GetPathRoot(project.FilePath); + } + + foreach (var documentId in project.DocumentIds) + { + var document = newSolution.GetDocument(documentId); + if (!PathUtilities.IsAbsolute(document.FilePath)) + { + newSolution = newSolution.WithDocumentFilePath(documentId, Path.Combine(projectRootFilePath, document.FilePath)); + } + else + { + Assert.Equal(projectRootFilePath, PathUtilities.GetPathRoot(document.FilePath)); + } + } + } + + var applied = workspace.TryApplyChanges(newSolution); + Assert.True(applied); + return; + } + + private static void AddAnalyzerConfigDocumentWithOptions(TestWorkspace workspace, IDictionary options) + { + Debug.Assert(options != null); + var analyzerConfigText = GenerateAnalyzerConfigText(options); + + var newSolution = workspace.CurrentSolution; + foreach (var project in workspace.Projects) + { + Assert.True(PathUtilities.IsAbsolute(project.FilePath)); + var projectRootFilePath = PathUtilities.GetPathRoot(project.FilePath); + var documentId = DocumentId.CreateNewId(project.Id); + newSolution = newSolution.AddAnalyzerConfigDocument( + documentId, + ".editorconfig", + SourceText.From(analyzerConfigText), + filePath: Path.Combine(projectRootFilePath, ".editorconfig")); + } + + var applied = workspace.TryApplyChanges(newSolution); + Assert.True(applied); + return; + + static string GenerateAnalyzerConfigText(IDictionary options) + { + var textBuilder = new StringBuilder(); + + // Add an auto-generated header at the top so we can skip this file in expected baseline validation. + textBuilder.AppendLine(AutoGeneratedAnalyzerConfigHeader); + textBuilder.AppendLine(); + + foreach (var (optionKey, value) in options) + { + foreach (var location in optionKey.Option.StorageLocations) + { + if (location is IEditorConfigStorageLocation2 editorConfigStorageLocation) + { + var editorConfigString = editorConfigStorageLocation.GetEditorConfigString(value, default); + if (editorConfigString != null) + { + textBuilder.AppendLine(GetSectionHeader(optionKey)); + textBuilder.AppendLine(editorConfigString); + textBuilder.AppendLine(); + break; + } + + Assert.False(true, "Unexpected non-editorconfig option"); + } + } + } + + return textBuilder.ToString(); + + static string GetSectionHeader(OptionKey optionKey) + { + if (optionKey.Option.IsPerLanguage) + { + switch (optionKey.Language) + { + case LanguageNames.CSharp: + return "[*.cs]"; + case LanguageNames.VisualBasic: + return "[*.vb]"; + } + } + + return "[*]"; + } + } + } + protected abstract TestWorkspace CreateWorkspaceFromFile(string initialMarkup, TestParameters parameters); private TestParameters WithRegularOptions(TestParameters parameters) @@ -199,138 +330,6 @@ protected Task TestSmartTagGlyphTagsAsync(string initialMarkup, ImmutableArray expectedContainers, - string expectedDocumentName, - TestParameters parameters = default) - { - await TestAddDocument( - initialMarkup, expectedMarkup, - expectedContainers, expectedDocumentName, - WithRegularOptions(parameters)); - await TestAddDocument( - initialMarkup, expectedMarkup, - expectedContainers, expectedDocumentName, - WithScriptOptions(parameters)); - } - - protected async Task> TestAddDocumentAsync( - TestParameters parameters, - TestWorkspace workspace, - string expectedMarkup, - string expectedDocumentName, - ImmutableArray expectedContainers) - { - var (_, action) = await GetCodeActionsAsync(workspace, parameters); - return await TestAddDocument( - workspace, expectedMarkup, expectedContainers, - expectedDocumentName, action); - } - - protected async Task TestAddDocument( - string initialMarkup, - string expectedMarkup, - ImmutableArray expectedContainers, - string expectedDocumentName, - TestParameters parameters = default) - { - using (var workspace = CreateWorkspaceFromOptions(initialMarkup, parameters)) - { - var (_, action) = await GetCodeActionsAsync(workspace, parameters); - await TestAddDocument( - workspace, expectedMarkup, expectedContainers, - expectedDocumentName, action); - } - } - - private async Task> TestAddDocument( - TestWorkspace workspace, - string expectedMarkup, - ImmutableArray expectedFolders, - string expectedDocumentName, - CodeAction action) - { - var operations = await VerifyActionAndGetOperationsAsync(workspace, action, default); - return await TestAddDocument( - workspace, - expectedMarkup, - operations, - hasProjectChange: false, - modifiedProjectId: null, - expectedFolders: expectedFolders, - expectedDocumentName: expectedDocumentName); - } - - protected async Task> TestAddDocument( - TestWorkspace workspace, - string expected, - ImmutableArray operations, - bool hasProjectChange, - ProjectId modifiedProjectId, - ImmutableArray expectedFolders, - string expectedDocumentName) - { - var appliedChanges = ApplyOperationsAndGetSolution(workspace, operations); - var oldSolution = appliedChanges.Item1; - var newSolution = appliedChanges.Item2; - - Document addedDocument = null; - if (!hasProjectChange) - { - addedDocument = SolutionUtilities.GetSingleAddedDocument(oldSolution, newSolution); - } - else - { - Assert.NotNull(modifiedProjectId); - addedDocument = newSolution.GetProject(modifiedProjectId).Documents.SingleOrDefault(doc => doc.Name == expectedDocumentName); - } - - Assert.NotNull(addedDocument); - - AssertEx.Equal(expectedFolders, addedDocument.Folders); - Assert.Equal(expectedDocumentName, addedDocument.Name); - Assert.Equal(expected, (await addedDocument.GetTextAsync()).ToString()); - - var editHandler = workspace.ExportProvider.GetExportedValue(); - if (!hasProjectChange) - { - // If there is just one document change then we expect the preview to be a WpfTextView - var content = (await editHandler.GetPreviews(workspace, operations, CancellationToken.None).GetPreviewsAsync())[0]; - using (var diffView = content as DifferenceViewerPreview) - { - Assert.NotNull(diffView.Viewer); - } - } - else - { - // If there are more changes than just the document we need to browse all the changes and get the document change - var contents = editHandler.GetPreviews(workspace, operations, CancellationToken.None); - var hasPreview = false; - var previews = await contents.GetPreviewsAsync(); - if (previews != null) - { - foreach (var preview in previews) - { - if (preview != null) - { - var diffView = preview as DifferenceViewerPreview; - if (diffView?.Viewer != null) - { - hasPreview = true; - diffView.Dispose(); - break; - } - } - } - } - - Assert.True(hasPreview); - } - - return Tuple.Create(oldSolution, newSolution); - } - internal Task TestInRegularAndScriptAsync( string initialMarkup, string expectedMarkup, @@ -344,7 +343,7 @@ protected Task TestSmartTagGlyphTagsAsync(string initialMarkup, ImmutableArray d.FilePath == analyzerConfigDoc.FilePath); var expectedRoot = await expectedDocument.GetTextAsync(); - VerifyExpectedDocumentText(expectedRoot.ToString(), root.ToString()); + VerifyExpectedDocumentText(expectedRoot.ToString(), actualString); } } } diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest_TestAddDocument.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest_TestAddDocument.cs new file mode 100644 index 00000000000..592d6b2fe9f --- /dev/null +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionOrUserDiagnosticTest_TestAddDocument.cs @@ -0,0 +1,153 @@ +// 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.Collections.Immutable; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CodeActions; +using Microsoft.CodeAnalysis.Editor.Implementation.Preview; +using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; +using Microsoft.CodeAnalysis.UnitTests; +using Roslyn.Test.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions +{ + public abstract partial class AbstractCodeActionOrUserDiagnosticTest + { + protected async Task TestAddDocumentInRegularAndScriptAsync( + string initialMarkup, string expectedMarkup, + ImmutableArray expectedContainers, + string expectedDocumentName, + TestParameters parameters = default) + { + await TestAddDocument( + initialMarkup, expectedMarkup, + expectedContainers, expectedDocumentName, + WithRegularOptions(parameters)); + await TestAddDocument( + initialMarkup, expectedMarkup, + expectedContainers, expectedDocumentName, + WithScriptOptions(parameters)); + } + + protected async Task> TestAddDocumentAsync( + TestParameters parameters, + TestWorkspace workspace, + string expectedMarkup, + string expectedDocumentName, + ImmutableArray expectedContainers) + { + var (_, action) = await GetCodeActionsAsync(workspace, parameters); + return await TestAddDocument( + workspace, expectedMarkup, expectedContainers, + expectedDocumentName, action); + } + + protected async Task TestAddDocument( + string initialMarkup, + string expectedMarkup, + ImmutableArray expectedContainers, + string expectedDocumentName, + TestParameters parameters = default) + { + using (var workspace = CreateWorkspaceFromOptions(initialMarkup, parameters)) + { + var (_, action) = await GetCodeActionsAsync(workspace, parameters); + await TestAddDocument( + workspace, expectedMarkup, expectedContainers, + expectedDocumentName, action); + } + } + + private async Task> TestAddDocument( + TestWorkspace workspace, + string expectedMarkup, + ImmutableArray expectedFolders, + string expectedDocumentName, + CodeAction action) + { + var operations = await VerifyActionAndGetOperationsAsync(workspace, action, default); + return await TestAddDocument( + workspace, + expectedMarkup, + operations, + hasProjectChange: false, + modifiedProjectId: null, + expectedFolders: expectedFolders, + expectedDocumentName: expectedDocumentName); + } + + protected async Task> TestAddDocument( + TestWorkspace workspace, + string expected, + ImmutableArray operations, + bool hasProjectChange, + ProjectId modifiedProjectId, + ImmutableArray expectedFolders, + string expectedDocumentName) + { + var appliedChanges = ApplyOperationsAndGetSolution(workspace, operations); + var oldSolution = appliedChanges.Item1; + var newSolution = appliedChanges.Item2; + + Document addedDocument = null; + if (!hasProjectChange) + { + addedDocument = SolutionUtilities.GetSingleAddedDocument(oldSolution, newSolution); + } + else + { + Assert.NotNull(modifiedProjectId); + addedDocument = newSolution.GetProject(modifiedProjectId).Documents.SingleOrDefault(doc => doc.Name == expectedDocumentName); + } + + Assert.NotNull(addedDocument); + + AssertEx.Equal(expectedFolders, addedDocument.Folders); + Assert.Equal(expectedDocumentName, addedDocument.Name); + Assert.Equal(expected, (await addedDocument.GetTextAsync()).ToString()); + + var editHandler = workspace.ExportProvider.GetExportedValue(); + if (!hasProjectChange) + { + // If there is just one document change then we expect the preview to be a WpfTextView + var content = (await editHandler.GetPreviews(workspace, operations, CancellationToken.None).GetPreviewsAsync())[0]; + using (var diffView = content as DifferenceViewerPreview) + { + Assert.NotNull(diffView.Viewer); + } + } + else + { + // If there are more changes than just the document we need to browse all the changes and get the document change + var contents = editHandler.GetPreviews(workspace, operations, CancellationToken.None); + var hasPreview = false; + var previews = await contents.GetPreviewsAsync(); + if (previews != null) + { + foreach (var preview in previews) + { + if (preview != null) + { + var diffView = preview as DifferenceViewerPreview; + if (diffView?.Viewer != null) + { + hasPreview = true; + diffView.Dispose(); + break; + } + } + } + } + + Assert.True(hasPreview); + } + + return Tuple.Create(oldSolution, newSolution); + } + } +} diff --git a/src/EditorFeatures/TestUtilities/CodeActions/AbstractCodeActionTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs similarity index 98% rename from src/EditorFeatures/TestUtilities/CodeActions/AbstractCodeActionTest.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs index f9e8a203ee0..f1ff9d4cb98 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/AbstractCodeActionTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/AbstractCodeActionTest.cs @@ -23,7 +23,7 @@ namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions { - public abstract class AbstractCodeActionTest : AbstractCodeActionOrUserDiagnosticTest + public abstract partial class AbstractCodeActionTest : AbstractCodeActionOrUserDiagnosticTest { protected abstract CodeRefactoringProvider CreateCodeRefactoringProvider( Workspace workspace, TestParameters parameters); diff --git a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs similarity index 97% rename from src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs index feb2578157b..540c701968d 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2+Test.cs @@ -44,7 +44,6 @@ public Test() compilationOptions = compilationOptions.WithSpecificDiagnosticOptions(compilationOptions.SpecificDiagnosticOptions.SetItems(s_nullableWarnings)); solution = solution.WithProjectCompilationOptions(projectId, compilationOptions); -#if !CODE_STYLE // TODO: Add support for Options based tests in CodeStyle layer var (analyzerConfigSource, remainingOptions) = CodeFixVerifierHelper.ConvertOptionsToAnalyzerConfig(DefaultFileExt, Options); if (analyzerConfigSource is object) { @@ -55,6 +54,7 @@ public Test() } } +#if !CODE_STYLE var options = solution.Options; foreach (var (key, value) in remainingOptions) { @@ -88,13 +88,11 @@ public Test() /// public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.CSharp8; -#if !CODE_STYLE // TODO: Add support for Options based tests in CodeStyle layer /// /// Gets a collection of options to apply to for testing. Values may be added /// using a collection initializer. /// public OptionsCollection Options { get; } = new OptionsCollection(LanguageNames.CSharp); -#endif public Func, Diagnostic?>? DiagnosticSelector { get; set; } diff --git a/src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs similarity index 100% rename from src/EditorFeatures/TestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CSharpCodeFixVerifier`2.cs diff --git a/src/EditorFeatures/TestUtilities/CodeActions/CodeFixVerifierHelper.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CodeFixVerifierHelper.cs similarity index 93% rename from src/EditorFeatures/TestUtilities/CodeActions/CodeFixVerifierHelper.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CodeFixVerifierHelper.cs index 1117542ea4f..5b6c9419172 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/CodeFixVerifierHelper.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/CodeFixVerifierHelper.cs @@ -9,11 +9,17 @@ using System.Linq; using System.Text; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; using Roslyn.Utilities; using Xunit; +#if CODE_STYLE +using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions; +using Microsoft.CodeAnalysis.Internal.Options; +#else +using Microsoft.CodeAnalysis.Options; +#endif + namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions { internal static class CodeFixVerifierHelper @@ -81,7 +87,6 @@ private static void VerifyMessageHelpLinkUri(DiagnosticAnalyzer analyzer) } } -#if !CODE_STYLE public static (SourceText? analyzerConfig, IEnumerable> options) ConvertOptionsToAnalyzerConfig(string defaultFileExtension, OptionsCollection options) { if (options.Count == 0) @@ -120,6 +125,12 @@ public OptionSetWrapper(Dictionary options) _options = options; } +#if CODE_STYLE + public override bool TryGetValue(string key, out string value) + { + throw new NotImplementedException(); + } +#else public override object? GetOption(OptionKey optionKey) { if (!_options.TryGetValue(optionKey, out var value)) @@ -135,7 +146,8 @@ public override OptionSet WithChangedOption(OptionKey optionAndLanguage, object? internal override IEnumerable GetChangedOptions(OptionSet optionSet) => SpecializedCollections.EmptyEnumerable(); - } + #endif + } } } diff --git a/src/EditorFeatures/TestUtilities/CodeActions/OptionsCollection.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/OptionsCollection.cs similarity index 96% rename from src/EditorFeatures/TestUtilities/CodeActions/OptionsCollection.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/OptionsCollection.cs index 21e9c7f85cc..71f7e817983 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/OptionsCollection.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/OptionsCollection.cs @@ -4,8 +4,13 @@ using System.Collections; using System.Collections.Generic; + +#if CODE_STYLE +using Microsoft.CodeAnalysis.Internal.Options; +#else using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Options; +#endif namespace Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions { diff --git a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs similarity index 95% rename from src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs index 4ac072499d2..08ab8823e6f 100644 --- a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeFixVerifier`2+Test.cs @@ -31,7 +31,6 @@ public Test() var parseOptions = (VisualBasicParseOptions)solution.GetRequiredProject(projectId).ParseOptions!; solution = solution.WithProjectParseOptions(projectId, parseOptions.WithLanguageVersion(LanguageVersion)); -#if !CODE_STYLE // TODO: Add support for Options based tests in CodeStyle layer var (analyzerConfigSource, remainingOptions) = CodeFixVerifierHelper.ConvertOptionsToAnalyzerConfig(DefaultFileExt, Options); if (analyzerConfigSource is object) { @@ -42,6 +41,7 @@ public Test() } } +#if !CODE_STYLE var options = solution.Options; foreach (var (key, value) in remainingOptions) { @@ -61,13 +61,11 @@ public Test() /// public LanguageVersion LanguageVersion { get; set; } = LanguageVersion.VisualBasic16; -#if !CODE_STYLE // TODO: Add support for Options based tests in CodeStyle layer /// /// Gets a collection of options to apply to for testing. Values may be added /// using a collection initializer. /// public OptionsCollection Options { get; } = new OptionsCollection(LanguageNames.VisualBasic); -#endif public Func, Diagnostic?>? DiagnosticSelector { get; set; } diff --git a/src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs b/src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs similarity index 100% rename from src/EditorFeatures/TestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/CodeActions/VisualBasicCodeFixVerifier`2.cs diff --git a/src/EditorFeatures/TestUtilities/Diagnostics/AbstractDiagnosticProviderBasedUserDiagnosticTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractDiagnosticProviderBasedUserDiagnosticTest.cs similarity index 76% rename from src/EditorFeatures/TestUtilities/Diagnostics/AbstractDiagnosticProviderBasedUserDiagnosticTest.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractDiagnosticProviderBasedUserDiagnosticTest.cs index 74fffdf3e50..1b9c99e47a0 100644 --- a/src/EditorFeatures/TestUtilities/Diagnostics/AbstractDiagnosticProviderBasedUserDiagnosticTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractDiagnosticProviderBasedUserDiagnosticTest.cs @@ -2,7 +2,6 @@ // 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.Collections.Concurrent; using System.Collections.Generic; using System.Collections.Immutable; @@ -10,19 +9,23 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CodeStyle; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; -using Microsoft.CodeAnalysis.Options; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.UnitTests.Diagnostics; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; +#if CODE_STYLE +using Microsoft.CodeAnalysis.Internal.Options; +#else +using Microsoft.CodeAnalysis.Options; +#endif + namespace Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics { - public abstract class AbstractDiagnosticProviderBasedUserDiagnosticTest : AbstractUserDiagnosticTest + public abstract partial class AbstractDiagnosticProviderBasedUserDiagnosticTest : AbstractUserDiagnosticTest { private readonly ConcurrentDictionary _analyzerAndFixerMap = new ConcurrentDictionary(); @@ -224,56 +227,5 @@ private void AssertNoAnalyzerExceptionDiagnostics(IEnumerable diagno var analyzerExceptionDiagnostics = diagnostics.Where(diag => diag.Descriptor.CustomTags.Contains(WellKnownDiagnosticTags.AnalyzerException)); AssertEx.Empty(analyzerExceptionDiagnostics, "Found analyzer exception diagnostics"); } - - #region Parentheses options - - private static readonly CodeStyleOption IgnorePreference = - new CodeStyleOption(ParenthesesPreference.AlwaysForClarity, NotificationOption.None); - - private static readonly CodeStyleOption RequireForPrecedenceClarityPreference = - new CodeStyleOption(ParenthesesPreference.AlwaysForClarity, NotificationOption.Suggestion); - - private static readonly CodeStyleOption RemoveIfUnnecessaryPreference = - new CodeStyleOption(ParenthesesPreference.NeverIfUnnecessary, NotificationOption.Suggestion); - - private static IEnumerable>> GetAllExceptOtherParenthesesOptions() - { - yield return CodeStyleOptions.ArithmeticBinaryParentheses; - yield return CodeStyleOptions.RelationalBinaryParentheses; - yield return CodeStyleOptions.OtherBinaryParentheses; - } - - protected IDictionary RequireArithmeticBinaryParenthesesForClarity - => GetSingleRequireOption(CodeStyleOptions.ArithmeticBinaryParentheses); - - protected IDictionary RequireRelationalBinaryParenthesesForClarity - => GetSingleRequireOption(CodeStyleOptions.RelationalBinaryParentheses); - - protected IDictionary RequireOtherBinaryParenthesesForClarity - => GetSingleRequireOption(CodeStyleOptions.OtherBinaryParentheses); - - private IEnumerable>> GetAllParenthesesOptions() - => GetAllExceptOtherParenthesesOptions().Concat(CodeStyleOptions.OtherParentheses); - - protected IDictionary IgnoreAllParentheses - => OptionsSet(GetAllParenthesesOptions().Select( - o => SingleOption(o, IgnorePreference)).ToArray()); - - protected IDictionary RemoveAllUnnecessaryParentheses - => OptionsSet(GetAllParenthesesOptions().Select( - o => SingleOption(o, RemoveIfUnnecessaryPreference)).ToArray()); - - protected IDictionary RequireAllParenthesesForClarity - => OptionsSet(GetAllExceptOtherParenthesesOptions() - .Select(o => SingleOption(o, RequireForPrecedenceClarityPreference)) - .Concat(SingleOption(CodeStyleOptions.OtherParentheses, RemoveIfUnnecessaryPreference)).ToArray()); - - private IDictionary GetSingleRequireOption(PerLanguageOption> option) - => OptionsSet(GetAllParenthesesOptions() - .Where(o => o != option) - .Select(o => SingleOption(o, RemoveIfUnnecessaryPreference)) - .Concat(SingleOption(option, RequireForPrecedenceClarityPreference)).ToArray()); - - #endregion } } diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractDiagnosticProviderBasedUserDiagnosticTest_ParenthesesOptions.cs b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractDiagnosticProviderBasedUserDiagnosticTest_ParenthesesOptions.cs new file mode 100644 index 00000000000..f8c83823fc3 --- /dev/null +++ b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractDiagnosticProviderBasedUserDiagnosticTest_ParenthesesOptions.cs @@ -0,0 +1,66 @@ +// 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.Collections.Generic; +using System.Linq; +using Microsoft.CodeAnalysis.CodeStyle; +using Microsoft.CodeAnalysis.Options; +using Roslyn.Utilities; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics +{ + public abstract partial class AbstractDiagnosticProviderBasedUserDiagnosticTest : AbstractUserDiagnosticTest + { + #region Parentheses options + + private static readonly CodeStyleOption IgnorePreference = + new CodeStyleOption(ParenthesesPreference.AlwaysForClarity, NotificationOption.None); + + private static readonly CodeStyleOption RequireForPrecedenceClarityPreference = + new CodeStyleOption(ParenthesesPreference.AlwaysForClarity, NotificationOption.Suggestion); + + private static readonly CodeStyleOption RemoveIfUnnecessaryPreference = + new CodeStyleOption(ParenthesesPreference.NeverIfUnnecessary, NotificationOption.Suggestion); + + private static IEnumerable>> GetAllExceptOtherParenthesesOptions() + { + yield return CodeStyleOptions.ArithmeticBinaryParentheses; + yield return CodeStyleOptions.RelationalBinaryParentheses; + yield return CodeStyleOptions.OtherBinaryParentheses; + } + + protected IDictionary RequireArithmeticBinaryParenthesesForClarity + => GetSingleRequireOption(CodeStyleOptions.ArithmeticBinaryParentheses); + + protected IDictionary RequireRelationalBinaryParenthesesForClarity + => GetSingleRequireOption(CodeStyleOptions.RelationalBinaryParentheses); + + protected IDictionary RequireOtherBinaryParenthesesForClarity + => GetSingleRequireOption(CodeStyleOptions.OtherBinaryParentheses); + + private IEnumerable>> GetAllParenthesesOptions() + => GetAllExceptOtherParenthesesOptions().Concat(CodeStyleOptions.OtherParentheses); + + protected IDictionary IgnoreAllParentheses + => OptionsSet(GetAllParenthesesOptions().Select( + o => SingleOption(o, IgnorePreference)).ToArray()); + + protected IDictionary RemoveAllUnnecessaryParentheses + => OptionsSet(GetAllParenthesesOptions().Select( + o => SingleOption(o, RemoveIfUnnecessaryPreference)).ToArray()); + + protected IDictionary RequireAllParenthesesForClarity + => OptionsSet(GetAllExceptOtherParenthesesOptions() + .Select(o => SingleOption(o, RequireForPrecedenceClarityPreference)) + .Concat(SingleOption(CodeStyleOptions.OtherParentheses, RemoveIfUnnecessaryPreference)).ToArray()); + + private IDictionary GetSingleRequireOption(PerLanguageOption> option) + => OptionsSet(GetAllParenthesesOptions() + .Where(o => o != option) + .Select(o => SingleOption(o, RemoveIfUnnecessaryPreference)) + .Concat(SingleOption(option, RequireForPrecedenceClarityPreference)).ToArray()); + + #endregion + } +} diff --git a/src/EditorFeatures/TestUtilities/Diagnostics/AbstractSuppressionAllCodeTests.cs b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractSuppressionAllCodeTests.cs similarity index 100% rename from src/EditorFeatures/TestUtilities/Diagnostics/AbstractSuppressionAllCodeTests.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractSuppressionAllCodeTests.cs diff --git a/src/EditorFeatures/TestUtilities/Diagnostics/AbstractSuppressionDiagnosticTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractSuppressionDiagnosticTest.cs similarity index 100% rename from src/EditorFeatures/TestUtilities/Diagnostics/AbstractSuppressionDiagnosticTest.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractSuppressionDiagnosticTest.cs diff --git a/src/EditorFeatures/TestUtilities/Diagnostics/FixAllDiagnosticProvider.cs b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest.FixAllDiagnosticProvider.cs similarity index 100% rename from src/EditorFeatures/TestUtilities/Diagnostics/FixAllDiagnosticProvider.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest.FixAllDiagnosticProvider.cs diff --git a/src/EditorFeatures/TestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs similarity index 62% rename from src/EditorFeatures/TestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs index 07be82e324f..95c66312507 100644 --- a/src/EditorFeatures/TestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs +++ b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest.cs @@ -11,23 +11,22 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; -using Microsoft.CodeAnalysis.CodeFixes.Suppression; -using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; -using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics.GenerateType; using Microsoft.CodeAnalysis.Editor.UnitTests.Workspaces; -using Microsoft.CodeAnalysis.GenerateType; -using Microsoft.CodeAnalysis.Options; -using Microsoft.CodeAnalysis.PooledObjects; using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Microsoft.CodeAnalysis.Text; -using Microsoft.CodeAnalysis.UnitTests; using Microsoft.CodeAnalysis.UnitTests.Diagnostics; using Roslyn.Test.Utilities; using Roslyn.Utilities; using Xunit; +#if CODE_STYLE +using Microsoft.CodeAnalysis.Internal.Options; +#else +using Microsoft.CodeAnalysis.Options; +#endif + namespace Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics { public abstract partial class AbstractUserDiagnosticTest : AbstractCodeActionOrUserDiagnosticTest @@ -293,158 +292,5 @@ protected Document GetDocumentAndAnnotatedSpan(TestWorkspace workspace, out stri Assert.True(expectedTextSpans.SetEquals(actualTextSpans)); } - - internal async Task TestWithMockedGenerateTypeDialog( - string initial, - string languageName, - string typeName, - string expected = null, - bool isMissing = false, - Accessibility accessibility = Accessibility.NotApplicable, - TypeKind typeKind = TypeKind.Class, - string projectName = null, - bool isNewFile = false, - string existingFilename = null, - ImmutableArray newFileFolderContainers = default, - string fullFilePath = null, - string newFileName = null, - string assertClassName = null, - bool checkIfUsingsIncluded = false, - bool checkIfUsingsNotIncluded = false, - string expectedTextWithUsings = null, - string defaultNamespace = "", - bool areFoldersValidIdentifiers = true, - GenerateTypeDialogOptions assertGenerateTypeDialogOptions = null, - IList assertTypeKindPresent = null, - IList assertTypeKindAbsent = null, - bool isCancelled = false) - { - using var testState = GenerateTypeTestState.Create(initial, projectName, typeName, existingFilename, languageName); - - // Initialize the viewModel values - testState.TestGenerateTypeOptionsService.SetGenerateTypeOptions( - accessibility: accessibility, - typeKind: typeKind, - typeName: testState.TypeName, - project: testState.ProjectToBeModified, - isNewFile: isNewFile, - newFileName: newFileName, - folders: newFileFolderContainers, - fullFilePath: fullFilePath, - existingDocument: testState.ExistingDocument, - areFoldersValidIdentifiers: areFoldersValidIdentifiers, - isCancelled: isCancelled); - - testState.TestProjectManagementService.SetDefaultNamespace( - defaultNamespace: defaultNamespace); - - var testOptions = new TestParameters(); - var (diagnostics, actions, _) = await GetDiagnosticAndFixesAsync(testState.Workspace, testOptions); - var generateTypeDiagFixes = diagnostics.SingleOrDefault(df => GenerateTypeTestState.FixIds.Contains(df.Id)); - - if (isMissing) - { - Assert.Empty(actions); - return; - } - - var fixActions = MassageActions(actions); - Assert.NotNull(fixActions); - - // Since the dialog option is always fed as the last CodeAction - var index = fixActions.Count() - 1; - var action = fixActions.ElementAt(index); - - Assert.Equal(action.Title, FeaturesResources.Generate_new_type); - var operations = await action.GetOperationsAsync(CancellationToken.None); - Tuple oldSolutionAndNewSolution = null; - - if (!isNewFile) - { - oldSolutionAndNewSolution = await TestOperationsAsync( - testState.Workspace, expected, operations, - conflictSpans: ImmutableArray.Empty, - renameSpans: ImmutableArray.Empty, - warningSpans: ImmutableArray.Empty, - navigationSpans: ImmutableArray.Empty, - expectedChangedDocumentId: testState.ExistingDocument.Id); - } - else - { - oldSolutionAndNewSolution = await TestAddDocument( - testState.Workspace, - expected, - operations, - projectName != null, - testState.ProjectToBeModified.Id, - newFileFolderContainers, - newFileName); - } - - if (checkIfUsingsIncluded) - { - Assert.NotNull(expectedTextWithUsings); - await TestOperationsAsync(testState.Workspace, expectedTextWithUsings, operations, - conflictSpans: ImmutableArray.Empty, - renameSpans: ImmutableArray.Empty, - warningSpans: ImmutableArray.Empty, - navigationSpans: ImmutableArray.Empty, - expectedChangedDocumentId: testState.InvocationDocument.Id); - } - - if (checkIfUsingsNotIncluded) - { - var oldSolution = oldSolutionAndNewSolution.Item1; - var newSolution = oldSolutionAndNewSolution.Item2; - var changedDocumentIds = SolutionUtilities.GetChangedDocuments(oldSolution, newSolution); - - Assert.False(changedDocumentIds.Contains(testState.InvocationDocument.Id)); - } - - // Added into a different project than the triggering project - if (projectName != null) - { - var appliedChanges = ApplyOperationsAndGetSolution(testState.Workspace, operations); - var newSolution = appliedChanges.Item2; - var triggeredProject = newSolution.GetProject(testState.TriggeredProject.Id); - - // Make sure the Project reference is present - Assert.True(triggeredProject.ProjectReferences.Any(pr => pr.ProjectId == testState.ProjectToBeModified.Id)); - } - - // Assert Option Calculation - if (assertClassName != null) - { - Assert.True(assertClassName == testState.TestGenerateTypeOptionsService.ClassName); - } - - if (assertGenerateTypeDialogOptions != null || assertTypeKindPresent != null || assertTypeKindAbsent != null) - { - var generateTypeDialogOptions = testState.TestGenerateTypeOptionsService.GenerateTypeDialogOptions; - - if (assertGenerateTypeDialogOptions != null) - { - Assert.True(assertGenerateTypeDialogOptions.IsPublicOnlyAccessibility == generateTypeDialogOptions.IsPublicOnlyAccessibility); - Assert.True(assertGenerateTypeDialogOptions.TypeKindOptions == generateTypeDialogOptions.TypeKindOptions); - Assert.True(assertGenerateTypeDialogOptions.IsAttribute == generateTypeDialogOptions.IsAttribute); - } - - if (assertTypeKindPresent != null) - { - foreach (var typeKindPresentEach in assertTypeKindPresent) - { - Assert.True((typeKindPresentEach & generateTypeDialogOptions.TypeKindOptions) != 0); - } - } - - if (assertTypeKindAbsent != null) - { - foreach (var typeKindPresentEach in assertTypeKindAbsent) - { - Assert.True((typeKindPresentEach & generateTypeDialogOptions.TypeKindOptions) == 0); - } - } - } - } } } diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs new file mode 100644 index 00000000000..c521b86eaf0 --- /dev/null +++ b/src/EditorFeatures/DiagnosticsTestUtilities/Diagnostics/AbstractUserDiagnosticTest_GenerateTypeDialog.cs @@ -0,0 +1,176 @@ +// 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.Collections.Generic; +using System.Collections.Immutable; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.Editor.UnitTests.CodeActions; +using Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics.GenerateType; +using Microsoft.CodeAnalysis.GenerateType; +using Microsoft.CodeAnalysis.Text; +using Microsoft.CodeAnalysis.UnitTests; +using Roslyn.Utilities; +using Xunit; + +namespace Microsoft.CodeAnalysis.Editor.UnitTests.Diagnostics +{ + public abstract partial class AbstractUserDiagnosticTest : AbstractCodeActionOrUserDiagnosticTest + { + internal async Task TestWithMockedGenerateTypeDialog( + string initial, + string languageName, + string typeName, + string expected = null, + bool isMissing = false, + Accessibility accessibility = Accessibility.NotApplicable, + TypeKind typeKind = TypeKind.Class, + string projectName = null, + bool isNewFile = false, + string existingFilename = null, + ImmutableArray newFileFolderContainers = default, + string fullFilePath = null, + string newFileName = null, + string assertClassName = null, + bool checkIfUsingsIncluded = false, + bool checkIfUsingsNotIncluded = false, + string expectedTextWithUsings = null, + string defaultNamespace = "", + bool areFoldersValidIdentifiers = true, + GenerateTypeDialogOptions assertGenerateTypeDialogOptions = null, + IList assertTypeKindPresent = null, + IList assertTypeKindAbsent = null, + bool isCancelled = false) + { + using var testState = GenerateTypeTestState.Create(initial, projectName, typeName, existingFilename, languageName); + + // Initialize the viewModel values + testState.TestGenerateTypeOptionsService.SetGenerateTypeOptions( + accessibility: accessibility, + typeKind: typeKind, + typeName: testState.TypeName, + project: testState.ProjectToBeModified, + isNewFile: isNewFile, + newFileName: newFileName, + folders: newFileFolderContainers, + fullFilePath: fullFilePath, + existingDocument: testState.ExistingDocument, + areFoldersValidIdentifiers: areFoldersValidIdentifiers, + isCancelled: isCancelled); + + testState.TestProjectManagementService.SetDefaultNamespace( + defaultNamespace: defaultNamespace); + + var testOptions = new TestParameters(); + var (diagnostics, actions, _) = await GetDiagnosticAndFixesAsync(testState.Workspace, testOptions); + var generateTypeDiagFixes = diagnostics.SingleOrDefault(df => GenerateTypeTestState.FixIds.Contains(df.Id)); + + if (isMissing) + { + Assert.Empty(actions); + return; + } + + var fixActions = MassageActions(actions); + Assert.False(fixActions.IsDefault); + + // Since the dialog option is always fed as the last CodeAction + var index = fixActions.Count() - 1; + var action = fixActions.ElementAt(index); + + Assert.Equal(action.Title, FeaturesResources.Generate_new_type); + var operations = await action.GetOperationsAsync(CancellationToken.None); + Tuple oldSolutionAndNewSolution = null; + + if (!isNewFile) + { + oldSolutionAndNewSolution = await TestOperationsAsync( + testState.Workspace, expected, operations, + conflictSpans: ImmutableArray.Empty, + renameSpans: ImmutableArray.Empty, + warningSpans: ImmutableArray.Empty, + navigationSpans: ImmutableArray.Empty, + expectedChangedDocumentId: testState.ExistingDocument.Id); + } + else + { + oldSolutionAndNewSolution = await TestAddDocument( + testState.Workspace, + expected, + operations, + projectName != null, + testState.ProjectToBeModified.Id, + newFileFolderContainers, + newFileName); + } + + if (checkIfUsingsIncluded) + { + Assert.NotNull(expectedTextWithUsings); + await TestOperationsAsync(testState.Workspace, expectedTextWithUsings, operations, + conflictSpans: ImmutableArray.Empty, + renameSpans: ImmutableArray.Empty, + warningSpans: ImmutableArray.Empty, + navigationSpans: ImmutableArray.Empty, + expectedChangedDocumentId: testState.InvocationDocument.Id); + } + + if (checkIfUsingsNotIncluded) + { + var oldSolution = oldSolutionAndNewSolution.Item1; + var newSolution = oldSolutionAndNewSolution.Item2; + var changedDocumentIds = SolutionUtilities.GetChangedDocuments(oldSolution, newSolution); + + Assert.False(changedDocumentIds.Contains(testState.InvocationDocument.Id)); + } + + // Added into a different project than the triggering project + if (projectName != null) + { + var appliedChanges = ApplyOperationsAndGetSolution(testState.Workspace, operations); + var newSolution = appliedChanges.Item2; + var triggeredProject = newSolution.GetProject(testState.TriggeredProject.Id); + + // Make sure the Project reference is present + Assert.True(triggeredProject.ProjectReferences.Any(pr => pr.ProjectId == testState.ProjectToBeModified.Id)); + } + + // Assert Option Calculation + if (assertClassName != null) + { + Assert.True(assertClassName == testState.TestGenerateTypeOptionsService.ClassName); + } + + if (assertGenerateTypeDialogOptions != null || assertTypeKindPresent != null || assertTypeKindAbsent != null) + { + var generateTypeDialogOptions = testState.TestGenerateTypeOptionsService.GenerateTypeDialogOptions; + + if (assertGenerateTypeDialogOptions != null) + { + Assert.True(assertGenerateTypeDialogOptions.IsPublicOnlyAccessibility == generateTypeDialogOptions.IsPublicOnlyAccessibility); + Assert.True(assertGenerateTypeDialogOptions.TypeKindOptions == generateTypeDialogOptions.TypeKindOptions); + Assert.True(assertGenerateTypeDialogOptions.IsAttribute == generateTypeDialogOptions.IsAttribute); + } + + if (assertTypeKindPresent != null) + { + foreach (var typeKindPresentEach in assertTypeKindPresent) + { + Assert.True((typeKindPresentEach & generateTypeDialogOptions.TypeKindOptions) != 0); + } + } + + if (assertTypeKindAbsent != null) + { + foreach (var typeKindPresentEach in assertTypeKindAbsent) + { + Assert.True((typeKindPresentEach & generateTypeDialogOptions.TypeKindOptions) == 0); + } + } + } + } + } +} diff --git a/src/EditorFeatures/DiagnosticsTestUtilities/Microsoft.CodeAnalysis.EditorFeatures.DiagnosticsTests.Utilities.csproj b/src/EditorFeatures/DiagnosticsTestUtilities/Microsoft.CodeAnalysis.EditorFeatures.DiagnosticsTests.Utilities.csproj new file mode 100644 index 00000000000..b1baa3c88bd --- /dev/null +++ b/src/EditorFeatures/DiagnosticsTestUtilities/Microsoft.CodeAnalysis.EditorFeatures.DiagnosticsTests.Utilities.csproj @@ -0,0 +1,59 @@ + + + + + Library + Microsoft.CodeAnalysis.Test.Utilities + net472 + true + true + false + + + + + + + + + + + + + + + global,WORKSPACES + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/EditorFeatures/TestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.TestState.cs b/src/EditorFeatures/DiagnosticsTestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.TestState.cs similarity index 100% rename from src/EditorFeatures/TestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.TestState.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.TestState.cs diff --git a/src/EditorFeatures/TestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.cs b/src/EditorFeatures/DiagnosticsTestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.cs similarity index 100% rename from src/EditorFeatures/TestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/MoveToNamespace/AbstractMoveToNamespaceTests.cs diff --git a/src/EditorFeatures/TestUtilities/MoveType/AbstractMoveTypeTest.cs b/src/EditorFeatures/DiagnosticsTestUtilities/MoveType/AbstractMoveTypeTest.cs similarity index 100% rename from src/EditorFeatures/TestUtilities/MoveType/AbstractMoveTypeTest.cs rename to src/EditorFeatures/DiagnosticsTestUtilities/MoveType/AbstractMoveTypeTest.cs diff --git a/src/EditorFeatures/Test/Microsoft.CodeAnalysis.EditorFeatures.UnitTests.csproj b/src/EditorFeatures/Test/Microsoft.CodeAnalysis.EditorFeatures.UnitTests.csproj index 948e2be434d..fcc4cfe2fd5 100644 --- a/src/EditorFeatures/Test/Microsoft.CodeAnalysis.EditorFeatures.UnitTests.csproj +++ b/src/EditorFeatures/Test/Microsoft.CodeAnalysis.EditorFeatures.UnitTests.csproj @@ -34,6 +34,7 @@ + diff --git a/src/EditorFeatures/TestUtilities/Roslyn.Services.Test.Utilities.csproj b/src/EditorFeatures/TestUtilities/Roslyn.Services.Test.Utilities.csproj index 1e0ea1173fd..b938b5adef0 100644 --- a/src/EditorFeatures/TestUtilities/Roslyn.Services.Test.Utilities.csproj +++ b/src/EditorFeatures/TestUtilities/Roslyn.Services.Test.Utilities.csproj @@ -100,6 +100,13 @@ + + + + + + + diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestHostProject.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestHostProject.cs index 2ba4d84b56b..f1d42c4263f 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestHostProject.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestHostProject.cs @@ -27,7 +27,6 @@ public class TestHostProject private readonly string _assemblyName; private readonly Type _hostObjectType; private readonly VersionStamp _version; - private readonly string _filePath; private readonly string _outputFilePath; private readonly string _defaultNamespace; @@ -35,6 +34,7 @@ public class TestHostProject public IEnumerable AdditionalDocuments; public IEnumerable AnalyzerConfigDocuments; public IEnumerable ProjectReferences; + private string _filePath; public string Name { @@ -124,6 +124,9 @@ public string FilePath } } + internal void OnProjectFilePathChanged(string filePath) + => _filePath = filePath; + public string OutputFilePath { get { return _outputFilePath; } diff --git a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace.cs b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace.cs index 35a6c834326..ef4e17acedd 100644 --- a/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace.cs +++ b/src/EditorFeatures/TestUtilities/Workspaces/TestWorkspace.cs @@ -341,7 +341,7 @@ protected override void ApplyAnalyzerConfigDocumentTextChanged(DocumentId docume protected override void ApplyAnalyzerConfigDocumentAdded(DocumentInfo info, SourceText text) { var hostProject = this.GetTestProject(info.Id.ProjectId); - var hostDocument = new TestHostDocument(text.ToString(), info.Name, id: info.Id); + var hostDocument = new TestHostDocument(text.ToString(), info.Name, id: info.Id, filePath: info.FilePath, folders: info.Folders); hostProject.AddAnalyzerConfigDocument(hostDocument); this.OnAnalyzerConfigDocumentAdded(hostDocument.ToDocumentInfo()); } @@ -354,6 +354,18 @@ protected override void ApplyAnalyzerConfigDocumentRemoved(DocumentId documentId this.OnAnalyzerConfigDocumentRemoved(documentId); } + protected override void ApplyProjectChanges(ProjectChanges projectChanges) + { + if (projectChanges.OldProject.FilePath != projectChanges.NewProject.FilePath) + { + var hostProject = this.GetTestProject(projectChanges.NewProject.Id); + hostProject.OnProjectFilePathChanged(projectChanges.NewProject.FilePath); + base.OnProjectNameChanged(projectChanges.NewProject.Id, projectChanges.NewProject.Name, projectChanges.NewProject.FilePath); + } + + base.ApplyProjectChanges(projectChanges); + } + internal override void SetDocumentContext(DocumentId documentId) { OnDocumentContextUpdated(documentId); diff --git a/src/EditorFeatures/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.UnitTests.vbproj b/src/EditorFeatures/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.UnitTests.vbproj index f5108324b1e..a8289e09209 100644 --- a/src/EditorFeatures/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.UnitTests.vbproj +++ b/src/EditorFeatures/VisualBasicTest/Microsoft.CodeAnalysis.VisualBasic.EditorFeatures.UnitTests.vbproj @@ -37,6 +37,7 @@ + diff --git a/src/Features/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Features.csproj b/src/Features/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Features.csproj index 70d779f8b6a..e38c79579fd 100644 --- a/src/Features/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Features.csproj +++ b/src/Features/CSharp/Portable/Microsoft.CodeAnalysis.CSharp.Features.csproj @@ -42,6 +42,7 @@ + diff --git a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj index 564c3075625..cb717d79bec 100644 --- a/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj +++ b/src/Features/Core/Portable/Microsoft.CodeAnalysis.Features.csproj @@ -77,6 +77,7 @@ + diff --git a/src/Features/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Features.vbproj b/src/Features/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Features.vbproj index 697c94be90f..2028ad87586 100644 --- a/src/Features/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Features.vbproj +++ b/src/Features/VisualBasic/Portable/Microsoft.CodeAnalysis.VisualBasic.Features.vbproj @@ -37,6 +37,7 @@ + diff --git a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj index 791b9029352..10a5d8302be 100644 --- a/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj +++ b/src/Workspaces/Core/Portable/Microsoft.CodeAnalysis.Workspaces.csproj @@ -96,6 +96,7 @@ + @@ -123,6 +124,12 @@ + + + + + + diff --git a/src/Workspaces/Core/Portable/Options/EditorConfig/IEditorConfigStorageLocation.cs b/src/Workspaces/Core/Portable/Options/EditorConfig/IEditorConfigStorageLocation.cs index 4bccc5e5c30..6d324c57865 100644 --- a/src/Workspaces/Core/Portable/Options/EditorConfig/IEditorConfigStorageLocation.cs +++ b/src/Workspaces/Core/Portable/Options/EditorConfig/IEditorConfigStorageLocation.cs @@ -9,11 +9,13 @@ #if CODE_STYLE namespace Microsoft.CodeAnalysis.Internal.Options +{ + public interface IEditorConfigStorageLocation #else namespace Microsoft.CodeAnalysis.Options -#endif { internal interface IEditorConfigStorageLocation +#endif { bool TryGetOption(IReadOnlyDictionary rawOptions, Type type, out object? value); } diff --git a/src/Workspaces/Core/Portable/Options/EditorConfig/IEditorConfigStorageLocation2.cs b/src/Workspaces/Core/Portable/Options/EditorConfig/IEditorConfigStorageLocation2.cs index 7e98c1b2981..5c92f7dd244 100644 --- a/src/Workspaces/Core/Portable/Options/EditorConfig/IEditorConfigStorageLocation2.cs +++ b/src/Workspaces/Core/Portable/Options/EditorConfig/IEditorConfigStorageLocation2.cs @@ -10,11 +10,13 @@ #if CODE_STYLE namespace Microsoft.CodeAnalysis.Internal.Options +{ + public interface IEditorConfigStorageLocation2 : IEditorConfigStorageLocation #else namespace Microsoft.CodeAnalysis.Options -#endif { internal interface IEditorConfigStorageLocation2 : IEditorConfigStorageLocation +#endif { string KeyName { get; } -- GitLab