From b637e84d11f2e510ba0ddf5133bfb8674346a628 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 31 Aug 2023 18:07:45 -0700 Subject: [PATCH 1/4] Add unit test integration tests + cleanup test running --- .vscode/launch.json | 67 +++++----- .../advisor.integration.test.ts | 2 +- .../codeActionRename.integration.test.ts | 2 +- .../codeLensProvider.integration.test.ts | 2 +- .../completionProvider.integration.test.ts | 2 +- .../definitionProvider.test.ts | 2 +- .../diagnostics.integration.test.ts | 2 +- ...documentSymbolProvider.integration.test.ts | 2 +- ...nCommentAutoFormatting.integration.test.ts | 2 +- .../dotnetTest.integration.test.ts | 2 +- .../hoverProvider.integration.test.ts | 2 +- .../implementationProvider.test.ts | 2 +- .../inlayHints.integration.test.ts | 2 +- .../languageMiddleware.integration.test.ts | 2 +- .../launchConfiguration.integration.test.ts | 2 +- .../reAnalyze.integration.test.ts | 2 +- .../referenceProvider.test.ts | 2 +- .../semanticTokensProvider.test.ts | 2 +- .../signatureHelp.integration.test.ts | 2 +- .../sourceGeneratorDefinitionProvider.test.ts | 2 +- .../testAssets/omnisharpTestAssetWorkspace.ts | 30 +++++ .../{testAssets.ts => omnisharpTestAssets.ts} | 75 +---------- ...sp_tools_host_slnWithCsproj.code-workspace | 13 -- .../slnWithCsproj/a_FirstInOrder_SlnFile.sln | 85 ------------ .../testAssets/slnWithCsproj/test/test.csproj | 15 --- .../typeDefinitionProvider.test.ts | 2 +- ...virtualDocumentTracker.integration.test.ts | 2 +- ...orkspaceSymbolProvider.integration.test.ts | 2 +- src/lsptoolshost/unitTesting.ts | 53 +++++--- tasks/projectPaths.ts | 8 +- tasks/testTasks.ts | 6 +- test/integrationTests/index.ts | 33 +++-- test/integrationTests/integrationHelpers.ts | 17 ++- .../lspInlayHints.integration.test.ts | 38 +++--- .../omnisharp_BasicRazorApp2_1.code-workspace | 0 ...isharp_lsp_BasicRazorApp2_1.code-workspace | 0 .../BasicRazorApp2_1/BasicRazorApp2_1.csproj | 0 .../BasicRazorApp2_1/Pages/ErrorHaver.razor | 0 .../BasicRazorApp2_1/Pages/Index.cshtml | 0 .../testAssets/BasicRazorApp2_1/Program.cs | 0 .../BasicRazorApp2_1/_ViewImports.cshtml | 0 .../integrationTests}/testAssets/NuGet.config | 0 .../testAssets/basicRazorApp21.ts | 0 .../testAssets/singleCsproj.ts | 0 .../testAssets/singleCsproj/.gitignore | 0 .../omnisharp_lsp_singleCsproj.code-workspace | 0 .../omnisharp_singleCsproj.code-workspace | 0 .../testAssets/singleCsproj/A.cs | 0 .../testAssets/singleCsproj/DocComments.cs | 0 .../testAssets/singleCsproj/ISomeInterface.cs | 0 .../testAssets/singleCsproj/Program.cs | 0 .../singleCsproj/SomeInterfaceImpl.cs | 0 .../testAssets/singleCsproj/completion.cs | 0 .../testAssets/singleCsproj/completionBase.cs | 0 .../testAssets/singleCsproj/definition.cs | 0 .../testAssets/singleCsproj/diagnostics.cs | 0 .../singleCsproj/documentSymbols.cs | 0 .../testAssets/singleCsproj/hover.cs | 0 .../testAssets/singleCsproj/implementation.cs | 0 .../testAssets/singleCsproj/inlayHints.cs | 0 .../testAssets/singleCsproj/reference.cs | 0 .../testAssets/singleCsproj/remap.cs | 0 .../testAssets/singleCsproj/remapped.txt | 0 .../singleCsproj/secondaryDiagnostics.cs | 0 .../testAssets/singleCsproj/semantictokens.cs | 0 .../testAssets/singleCsproj/sigHelp.cs | 0 .../singleCsproj/singleCsproj.csproj | 0 .../testAssets/singleCsproj/typeDefinition.cs | 0 .../testAssets/slnFilterWithCsproj.ts | 0 .../testAssets/slnFilterWithCsproj/.gitignore | 0 ...arp_lsp_slnFilterWithCsproj.code-workspace | 0 ...nisharp_slnFilterWithCsproj.code-workspace | 0 .../slnFilterWithCsproj/SolutionFile.sln | 0 .../slnFilterWithCsproj/SolutionFilter.slnf | 0 .../slnFilterWithCsproj/src/app/A.cs | 0 .../src/app/DocComments.cs | 0 .../src/app/ISomeInterface.cs | 0 .../slnFilterWithCsproj/src/app/Program.cs | 0 .../src/app/SomeInterfaceImpl.cs | 0 .../slnFilterWithCsproj/src/app/app.csproj | 0 .../slnFilterWithCsproj/src/app/completion.cs | 0 .../src/app/completionBase.cs | 0 .../slnFilterWithCsproj/src/app/definition.cs | 0 .../src/app/diagnostics.cs | 0 .../src/app/documentSymbols.cs | 0 .../slnFilterWithCsproj/src/app/hover.cs | 0 .../src/app/implementation.cs | 0 .../slnFilterWithCsproj/src/app/inlayHints.cs | 0 .../slnFilterWithCsproj/src/app/reference.cs | 0 .../slnFilterWithCsproj/src/app/remap.cs | 0 .../slnFilterWithCsproj/src/app/remapped.txt | 0 .../src/app/secondaryDiagnostics.cs | 0 .../src/app/semantictokens.cs | 0 .../slnFilterWithCsproj/src/app/sigHelp.cs | 0 .../src/app/typeDefinition.cs | 0 .../slnFilterWithCsproj/src/lib/Class1.cs | 0 .../slnFilterWithCsproj/src/lib/lib.csproj | 0 .../slnFilterWithCsproj/test/UnitTest1.cs | 0 .../slnFilterWithCsproj/test/test.csproj | 0 .../testAssets/slnWithCsproj.ts | 0 .../testAssets/slnWithCsproj/.gitignore | 0 ...sp_tools_host_slnWithCsproj.code-workspace | 13 ++ ...omnisharp_lsp_slnWithCsproj.code-workspace | 0 .../omnisharp_slnWithCsproj.code-workspace | 0 .../slnWithCsproj/b_SecondInOrder_SlnFile.sln | 15 --- .../testAssets/slnWithCsproj/src/app/A.cs | 0 .../slnWithCsproj/src/app/DocComments.cs | 0 .../slnWithCsproj/src/app/ISomeInterface.cs | 0 .../slnWithCsproj/src/app/Program.cs | 0 .../src/app/SomeInterfaceImpl.cs | 0 .../slnWithCsproj/src/app/app.csproj | 0 .../slnWithCsproj/src/app/completion.cs | 0 .../slnWithCsproj/src/app/completionBase.cs | 0 .../slnWithCsproj/src/app/definition.cs | 0 .../slnWithCsproj/src/app/diagnostics.cs | 0 .../slnWithCsproj/src/app/documentSymbols.cs | 0 .../testAssets/slnWithCsproj/src/app/hover.cs | 0 .../slnWithCsproj/src/app/implementation.cs | 0 .../slnWithCsproj/src/app/inlayHints.cs | 0 .../slnWithCsproj/src/app/reference.cs | 0 .../testAssets/slnWithCsproj/src/app/remap.cs | 0 .../slnWithCsproj/src/app/remapped.txt | 0 .../src/app/secondaryDiagnostics.cs | 0 .../slnWithCsproj/src/app/semantictokens.cs | 0 .../slnWithCsproj/src/app/sigHelp.cs | 0 .../slnWithCsproj/src/app/typeDefinition.cs | 0 .../slnWithCsproj/src/lib/Class1.cs | 0 .../slnWithCsproj/src/lib/lib.csproj | 0 .../slnWithCsproj/test/UnitTest1.cs | 0 .../testAssets/slnWithCsproj/test/test.csproj | 24 ++++ .../testAssets/slnWithGenerator.ts | 0 .../slnWithGenerator/.vscode/settings.json | 0 .../slnWithGenerator/app/GeneratorTrigger.cs | 0 .../slnWithGenerator/app/app.csproj | 0 .../generator/MainGenerator.cs | 0 .../generator/generator.csproj | 0 .../slnWithGenerator/slnWithGenerator.sln | 0 .../integrationTests}/testAssets/spawnGit.ts | 0 .../testAssets/testAssetWorkspace.ts | 0 .../integrationTests/testAssets/testAssets.ts | 91 +++++++++++++ .../unitTests.integration.test.ts | 121 ++++++++++++++++++ 141 files changed, 433 insertions(+), 315 deletions(-) create mode 100644 omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssetWorkspace.ts rename omnisharptest/omnisharpIntegrationTests/testAssets/{testAssets.ts => omnisharpTestAssets.ts} (54%) delete mode 100644 omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/lsp_tools_host_slnWithCsproj.code-workspace delete mode 100644 omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/a_FirstInOrder_SlnFile.sln delete mode 100644 omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/test/test.csproj rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/BasicRazorApp2_1/.vscode/omnisharp_BasicRazorApp2_1.code-workspace (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/BasicRazorApp2_1/.vscode/omnisharp_lsp_BasicRazorApp2_1.code-workspace (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/BasicRazorApp2_1/BasicRazorApp2_1.csproj (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/BasicRazorApp2_1/Pages/ErrorHaver.razor (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/BasicRazorApp2_1/Pages/Index.cshtml (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/BasicRazorApp2_1/Program.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/BasicRazorApp2_1/_ViewImports.cshtml (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/NuGet.config (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/basicRazorApp21.ts (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj.ts (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/.gitignore (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/.vscode/omnisharp_lsp_singleCsproj.code-workspace (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/.vscode/omnisharp_singleCsproj.code-workspace (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/A.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/DocComments.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/ISomeInterface.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/Program.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/SomeInterfaceImpl.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/completion.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/completionBase.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/definition.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/diagnostics.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/documentSymbols.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/hover.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/implementation.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/inlayHints.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/reference.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/remap.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/remapped.txt (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/secondaryDiagnostics.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/semantictokens.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/sigHelp.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/singleCsproj.csproj (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/singleCsproj/typeDefinition.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj.ts (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/.gitignore (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/.vscode/omnisharp_lsp_slnFilterWithCsproj.code-workspace (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/.vscode/omnisharp_slnFilterWithCsproj.code-workspace (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/SolutionFile.sln (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/SolutionFilter.slnf (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/A.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/DocComments.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/ISomeInterface.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/Program.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/SomeInterfaceImpl.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/app.csproj (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/completion.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/completionBase.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/definition.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/diagnostics.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/documentSymbols.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/hover.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/implementation.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/inlayHints.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/reference.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/remap.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/remapped.txt (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/secondaryDiagnostics.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/semantictokens.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/sigHelp.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/app/typeDefinition.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/lib/Class1.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/src/lib/lib.csproj (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/test/UnitTest1.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnFilterWithCsproj/test/test.csproj (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj.ts (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/.gitignore (100%) create mode 100644 test/integrationTests/testAssets/slnWithCsproj/.vscode/lsp_tools_host_slnWithCsproj.code-workspace rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/.vscode/omnisharp_lsp_slnWithCsproj.code-workspace (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/.vscode/omnisharp_slnWithCsproj.code-workspace (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/b_SecondInOrder_SlnFile.sln (78%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/A.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/DocComments.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/ISomeInterface.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/Program.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/SomeInterfaceImpl.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/app.csproj (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/completion.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/completionBase.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/definition.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/diagnostics.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/documentSymbols.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/hover.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/implementation.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/inlayHints.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/reference.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/remap.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/remapped.txt (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/secondaryDiagnostics.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/semantictokens.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/sigHelp.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/app/typeDefinition.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/lib/Class1.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/src/lib/lib.csproj (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithCsproj/test/UnitTest1.cs (100%) create mode 100644 test/integrationTests/testAssets/slnWithCsproj/test/test.csproj rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithGenerator.ts (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithGenerator/.vscode/settings.json (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithGenerator/app/GeneratorTrigger.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithGenerator/app/app.csproj (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithGenerator/generator/MainGenerator.cs (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithGenerator/generator/generator.csproj (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/slnWithGenerator/slnWithGenerator.sln (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/spawnGit.ts (100%) rename {omnisharptest/omnisharpIntegrationTests => test/integrationTests}/testAssets/testAssetWorkspace.ts (100%) create mode 100644 test/integrationTests/testAssets/testAssets.ts create mode 100644 test/integrationTests/unitTests.integration.test.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 016f2ce27..82902bf1e 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,6 +15,34 @@ ], "preLaunchTask": "buildDev" }, + { + "name": "Launch Current File slnWithCsproj Integration Tests", + "type": "extensionHost", + "request": "launch", + "runtimeExecutable": "${execPath}", + "args": [ + // Create a temp profile that has no extensions / user settings. + // This allows us to only have the C# extension + the dotnet runtime installer extension dependency. + "--profile-temp", + "${workspaceRoot}/test/integrationTests/testAssets/slnWithCsproj/.vscode/lsp_tools_host_slnWithCsproj.code-workspace", + "--extensionDevelopmentPath=${workspaceRoot}", + "--extensionTestsPath=${workspaceRoot}/out/test/integrationTests", + ], + "env": { + "CODE_EXTENSIONS_PATH": "${workspaceRoot}", + "TEST_FILE_FILTER": "${file}" + }, + "sourceMaps": true, + "outFiles": [ + "${workspaceRoot}/dist/*.js", + "${workspaceRoot}/out/test/**/*.js" + ], + "resolveSourceMapLocations": [ + "${workspaceFolder}/**", + "!**/node_modules/**" + ], + "preLaunchTask": "buildDev" + }, { "type": "node", "request": "launch", @@ -66,7 +94,7 @@ // Create a temp profile that has no extensions / user settings. // This allows us to only have the C# extension + the dotnet runtime installer extension dependency. "--profile-temp", - "${workspaceRoot}/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj", + "${workspaceRoot}/test/integrationTests/testAssets/singleCsproj/.vscode/omnisharp_singleCsproj.code-workspace", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/omnisharptest/omnisharpIntegrationTests" ], @@ -90,7 +118,7 @@ // Create a temp profile that has no extensions / user settings. // This allows us to only have the C# extension + the dotnet runtime installer extension dependency. "--profile-temp", - "${workspaceRoot}/omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1", + "${workspaceRoot}/test/integrationTests/testAssets/BasicRazorApp2_1", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/omnisharptest/omnisharpIntegrationTests" ], @@ -108,7 +136,7 @@ // Create a temp profile that has no extensions / user settings. // This allows us to only have the C# extension + the dotnet runtime installer extension dependency. "--profile-temp", - "${workspaceRoot}/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_slnWithCsproj.code-workspace", + "${workspaceRoot}/test/integrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_slnWithCsproj.code-workspace", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/omnisharptest/omnisharpIntegrationTests" ], @@ -123,29 +151,6 @@ ], "preLaunchTask": "buildDev" }, - { - "name": "LSP Tools Host: Launch slnWithCsproj Workspace Tests", - "type": "extensionHost", - "request": "launch", - "runtimeExecutable": "${execPath}", - "args": [ - // Create a temp profile that has no extensions / user settings. - // This allows us to only have the C# extension + the dotnet runtime installer extension dependency. - "--profile-temp", - "${workspaceRoot}/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/lsp_tools_host_slnWithCsproj.code-workspace", - "--extensionDevelopmentPath=${workspaceRoot}", - "--extensionTestsPath=${workspaceRoot}/out/test/integrationTests", - ], - "env": { - "CODE_EXTENSIONS_PATH": "${workspaceRoot}", - }, - "sourceMaps": true, - "outFiles": [ - "${workspaceRoot}/dist/*.js", - "${workspaceRoot}/out/test/**/*.js" - ], - "preLaunchTask": "buildDev" - }, { "name": "Omnisharp: Launch singleCsproj Workspace Tests [LSP]", "type": "extensionHost", @@ -155,7 +160,7 @@ // Create a temp profile that has no extensions / user settings. // This allows us to only have the C# extension + the dotnet runtime installer extension dependency. "--profile-temp", - "${workspaceRoot}/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_lsp_slnWithCsproj.code-workspace", + "${workspaceRoot}/test/integrationTests/testAssets/singleCsproj/.vscode/omnisharp_lsp_singleCsproj.code-workspace", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/omnisharptest/omnisharpIntegrationTests" ], @@ -179,7 +184,7 @@ // Create a temp profile that has no extensions / user settings. // This allows us to only have the C# extension + the dotnet runtime installer extension dependency. "--profile-temp", - "${workspaceRoot}/omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1", + "${workspaceRoot}/test/integrationTests/testAssets/BasicRazorApp2_1", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/omnisharptest/omnisharpIntegrationTests" ], @@ -197,7 +202,7 @@ // Create a temp profile that has no extensions / user settings. // This allows us to only have the C# extension + the dotnet runtime installer extension dependency. "--profile-temp", - "${workspaceRoot}/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_lsp_slnWithCsproj.code-workspace", + "${workspaceRoot}/test/integrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_lsp_slnWithCsproj.code-workspace", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/omnisharptest/omnisharpIntegrationTests" ], @@ -221,7 +226,7 @@ // Create a temp profile that has no extensions / user settings. // This allows us to only have the C# extension + the dotnet runtime installer extension dependency. "--profile-temp", - "${workspaceRoot}/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj", + "${workspaceRoot}/test/integrationTests/testAssets/slnFilterWithCsproj", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/omnisharptest/omnisharpIntegrationTests" ], @@ -245,7 +250,7 @@ // Create a temp profile that has no extensions / user settings. // This allows us to only have the C# extension + the dotnet runtime installer extension dependency. "--profile-temp", - "${workspaceRoot}/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator", + "${workspaceRoot}/test/integrationTests/testAssets/slnWithGenerator", "--extensionDevelopmentPath=${workspaceRoot}", "--extensionTestsPath=${workspaceRoot}/out/omnisharptest/omnisharpIntegrationTests" ], diff --git a/omnisharptest/omnisharpIntegrationTests/advisor.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/advisor.integration.test.ts index d8a0aba92..f82080a8d 100644 --- a/omnisharptest/omnisharpIntegrationTests/advisor.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/advisor.integration.test.ts @@ -8,7 +8,7 @@ import * as vscode from 'vscode'; import { expect, should } from 'chai'; import * as path from 'path'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { Advisor } from '../../src/features/diagnosticsProvider'; diff --git a/omnisharptest/omnisharpIntegrationTests/codeActionRename.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/codeActionRename.integration.test.ts index d8b9dff2a..ca79aa97d 100644 --- a/omnisharptest/omnisharpIntegrationTests/codeActionRename.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/codeActionRename.integration.test.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import { should, expect } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import * as path from 'path'; import { assertWithPoll } from './poll'; import { isNotNull } from '../testUtil'; diff --git a/omnisharptest/omnisharpIntegrationTests/codeLensProvider.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/codeLensProvider.integration.test.ts index 6ce594408..b8279cb14 100644 --- a/omnisharptest/omnisharpIntegrationTests/codeLensProvider.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/codeLensProvider.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, expect } from 'chai'; import { activateCSharpExtension, isSlnWithCsproj, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { isNotNull } from '../testUtil'; suite(`CodeLensProvider: ${testAssetWorkspace.description}`, function () { diff --git a/omnisharptest/omnisharpIntegrationTests/completionProvider.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/completionProvider.integration.test.ts index 87ea52127..aa87becf8 100644 --- a/omnisharptest/omnisharpIntegrationTests/completionProvider.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/completionProvider.integration.test.ts @@ -5,7 +5,7 @@ import OmniSharpCompletionProvider from '../../src/features/completionProvider'; import * as vscode from 'vscode'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import * as path from 'path'; import { use, expect, should } from 'chai'; import * as chaiArray from 'chai-arrays'; diff --git a/omnisharptest/omnisharpIntegrationTests/definitionProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/definitionProvider.test.ts index a8daa92af..1a4ad235b 100644 --- a/omnisharptest/omnisharpIntegrationTests/definitionProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/definitionProvider.test.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import OmniSharpDefinitionProvider from '../../src/features/definitionProvider'; import * as path from 'path'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { expect, should } from 'chai'; import { activateCSharpExtension, diff --git a/omnisharptest/omnisharpIntegrationTests/diagnostics.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/diagnostics.integration.test.ts index c3c0a7386..4f9f796ba 100644 --- a/omnisharptest/omnisharpIntegrationTests/diagnostics.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/diagnostics.integration.test.ts @@ -13,7 +13,7 @@ import { isSlnWithGenerator, restartOmniSharpServer, } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { poll, assertWithPoll, pollDoesNotHappen } from './poll'; import { isNotNull } from '../testUtil'; diff --git a/omnisharptest/omnisharpIntegrationTests/documentSymbolProvider.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/documentSymbolProvider.integration.test.ts index cf3fe0b4b..21b644e55 100644 --- a/omnisharptest/omnisharpIntegrationTests/documentSymbolProvider.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/documentSymbolProvider.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, expect } from 'chai'; import * as integrationHelpers from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; suite(`DocumentSymbolProvider: ${testAssetWorkspace.description}`, function () { let fileUri: vscode.Uri; diff --git a/omnisharptest/omnisharpIntegrationTests/documentationCommentAutoFormatting.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/documentationCommentAutoFormatting.integration.test.ts index 902c83896..8cdca19ed 100644 --- a/omnisharptest/omnisharpIntegrationTests/documentationCommentAutoFormatting.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/documentationCommentAutoFormatting.integration.test.ts @@ -8,7 +8,7 @@ import * as chaiArray from 'chai-arrays'; import * as vscode from 'vscode'; import * as path from 'path'; import { isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; use(chaiArray); diff --git a/omnisharptest/omnisharpIntegrationTests/dotnetTest.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/dotnetTest.integration.test.ts index 4bbd5f4b3..9fc8e66c2 100644 --- a/omnisharptest/omnisharpIntegrationTests/dotnetTest.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/dotnetTest.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, expect } from 'chai'; import { activateCSharpExtension, isSlnWithCsproj } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { EventStream } from '../../src/eventStream'; import { EventType } from '../../src/omnisharp/eventType'; import { OmnisharpRequestMessage } from '../../src/omnisharp/loggingEvents'; diff --git a/omnisharptest/omnisharpIntegrationTests/hoverProvider.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/hoverProvider.integration.test.ts index f835fe8b5..8e502cf20 100644 --- a/omnisharptest/omnisharpIntegrationTests/hoverProvider.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/hoverProvider.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, expect } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; export type Test = 'a' | 'b' | ['c', any]; diff --git a/omnisharptest/omnisharpIntegrationTests/implementationProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/implementationProvider.test.ts index 570530ce6..5c530ccca 100644 --- a/omnisharptest/omnisharpIntegrationTests/implementationProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/implementationProvider.test.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import OmniSharpImplementationProvider from '../../src/features/implementationProvider'; import * as path from 'path'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { expect, should } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; diff --git a/omnisharptest/omnisharpIntegrationTests/inlayHints.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/inlayHints.integration.test.ts index 2b01d5019..4f82217b7 100644 --- a/omnisharptest/omnisharpIntegrationTests/inlayHints.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/inlayHints.integration.test.ts @@ -12,7 +12,7 @@ import { isSlnWithGenerator, restartOmniSharpServer, } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import * as path from 'path'; import { InlayHint, LinePositionSpanTextChange } from '../../src/omnisharp/protocol'; import { isNotNull } from '../testUtil'; diff --git a/omnisharptest/omnisharpIntegrationTests/languageMiddleware.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/languageMiddleware.integration.test.ts index b85c2dbf8..680bd98fe 100644 --- a/omnisharptest/omnisharpIntegrationTests/languageMiddleware.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/languageMiddleware.integration.test.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import * as path from 'path'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { expect, should } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; import { LanguageMiddleware, LanguageMiddlewareFeature } from '../../src/omnisharp/languageMiddlewareFeature'; diff --git a/omnisharptest/omnisharpIntegrationTests/launchConfiguration.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/launchConfiguration.integration.test.ts index 4259da579..ad45ff408 100644 --- a/omnisharptest/omnisharpIntegrationTests/launchConfiguration.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/launchConfiguration.integration.test.ts @@ -8,7 +8,7 @@ import * as vscode from 'vscode'; import { should, expect } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { poll } from './poll'; import { isNotNull } from '../testUtil'; diff --git a/omnisharptest/omnisharpIntegrationTests/reAnalyze.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/reAnalyze.integration.test.ts index d265040f0..6864a69c9 100644 --- a/omnisharptest/omnisharpIntegrationTests/reAnalyze.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/reAnalyze.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, expect } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { poll, assertWithPoll } from './poll'; import { EventStream } from '../../src/eventStream'; import { EventType } from '../../src/omnisharp/eventType'; diff --git a/omnisharptest/omnisharpIntegrationTests/referenceProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/referenceProvider.test.ts index 35cc1f567..c8095abb7 100644 --- a/omnisharptest/omnisharpIntegrationTests/referenceProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/referenceProvider.test.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import OmniSharpReferenceProvider from '../../src/features/referenceProvider'; import * as path from 'path'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { expect, should } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; diff --git a/omnisharptest/omnisharpIntegrationTests/semanticTokensProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/semanticTokensProvider.test.ts index 419e17a9f..b2e3af3a2 100644 --- a/omnisharptest/omnisharpIntegrationTests/semanticTokensProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/semanticTokensProvider.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, assert } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; interface ExpectedToken { startLine: number; diff --git a/omnisharptest/omnisharpIntegrationTests/signatureHelp.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/signatureHelp.integration.test.ts index a501c619d..a4b301277 100644 --- a/omnisharptest/omnisharpIntegrationTests/signatureHelp.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/signatureHelp.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { expect, should } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; suite(`SignatureHelp: ${testAssetWorkspace.description}`, function () { let fileUri: vscode.Uri; diff --git a/omnisharptest/omnisharpIntegrationTests/sourceGeneratorDefinitionProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/sourceGeneratorDefinitionProvider.test.ts index eedde2600..1ce7441c6 100644 --- a/omnisharptest/omnisharpIntegrationTests/sourceGeneratorDefinitionProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/sourceGeneratorDefinitionProvider.test.ts @@ -9,7 +9,7 @@ import * as path from 'path'; import OmniSharpDefinitionProvider from '../../src/features/definitionProvider'; import { activateCSharpExtension, isSlnWithGenerator, restartOmniSharpServer } from './integrationHelpers'; import { assertWithPoll, sleep } from './poll'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; suite(`${OmniSharpDefinitionProvider.name}: ${testAssetWorkspace.description}`, () => { let fileUri: vscode.Uri; diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssetWorkspace.ts b/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssetWorkspace.ts new file mode 100644 index 000000000..9d7338c49 --- /dev/null +++ b/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssetWorkspace.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from 'path'; +import * as vscode from 'vscode'; + +import { ITestAssetWorkspace } from '../../../test/integrationTests/testAssets/testAssets'; + +import singleCsproj from '../../../test/integrationTests/testAssets/singleCsproj'; +import slnWithCsproj from '../../../test/integrationTests/testAssets/slnWithCsproj'; +import slnFilterWithCsproj from '../../../test/integrationTests/testAssets/slnFilterWithCsproj'; +import BasicRazorApp2_1 from '../../../test/integrationTests/testAssets/basicRazorApp21'; +import slnWithGenerator from '../../../test/integrationTests/testAssets/slnWithGenerator'; +import { OmnisharpTestAssetWorkspace } from './omnisharpTestAssets'; + +const testAssetWorkspaces: { [x: string]: ITestAssetWorkspace } = { + singleCsproj, + slnWithCsproj, + slnFilterWithCsproj, + BasicRazorApp2_1, + slnWithGenerator, +}; + +const workspaceName = vscode.workspace.workspaceFolders![0].uri.fsPath.split(path.sep).pop(); + +const activeTestAssetWorkspace = new OmnisharpTestAssetWorkspace(testAssetWorkspaces[workspaceName!]); + +export default activeTestAssetWorkspace; diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/testAssets.ts b/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssets.ts similarity index 54% rename from omnisharptest/omnisharpIntegrationTests/testAssets/testAssets.ts rename to omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssets.ts index 07ef976a3..a41fe54bf 100644 --- a/omnisharptest/omnisharpIntegrationTests/testAssets/testAssets.ts +++ b/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssets.ts @@ -3,40 +3,17 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as fs from 'async-file'; -import * as path from 'path'; import * as vscode from 'vscode'; import { EventStream } from '../../../src/eventStream'; import { EventType } from '../../../src/omnisharp/eventType'; import { BaseEvent } from '../../../src/omnisharp/loggingEvents'; -import { ActivationResult } from '../integrationHelpers'; import { poll } from '../poll'; -import spawnGit from './spawnGit'; - -export class TestAssetProject { - constructor(project: ITestAssetProject) { - this.relativeFilePath = project.relativeFilePath; - } - - relativeFilePath: string; - - get projectDirectoryPath(): string { - return path.join(vscode.workspace.workspaceFolders![0].uri.fsPath, path.dirname(this.relativeFilePath)); - } - - async addFileWithContents(fileName: string, contents: string): Promise { - const dir = this.projectDirectoryPath; - const loc = path.join(dir, fileName); - await fs.writeTextFile(loc, contents); - return vscode.Uri.file(loc); - } -} +import { ITestAssetWorkspace, TestAssetWorkspace } from '../../../test/integrationTests/testAssets/testAssets'; +import { ActivationResult } from '../integrationHelpers'; -export class TestAssetWorkspace { +export class OmnisharpTestAssetWorkspace extends TestAssetWorkspace { constructor(workspace: ITestAssetWorkspace) { - this.projects = workspace.projects.map((w) => new TestAssetProject(w)); - - this.description = workspace.description; + super(workspace); } async restore(): Promise { @@ -103,48 +80,4 @@ export class TestAssetWorkspace { subscription.unsubscribe(); } - - get vsCodeDirectoryPath(): string { - return path.join(vscode.workspace.workspaceFolders![0].uri.fsPath, '.vscode'); - } - - get launchJsonPath(): string { - return path.join(this.vsCodeDirectoryPath, 'launch.json'); - } - - get tasksJsonPath(): string { - return path.join(this.vsCodeDirectoryPath, 'tasks.json'); - } - - async cleanupWorkspace(): Promise { - const workspaceRootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; - const cleanUpRoutine = async () => { - await vscode.commands.executeCommand('workbench.action.closeAllEditors'); - await spawnGit(['clean', '-xdf', '.'], { cwd: workspaceRootPath }); - await spawnGit(['checkout', '--', '.'], { cwd: workspaceRootPath }); - }; - - const sleep = async () => new Promise((resolve) => setTimeout(resolve, 2 * 1000)); - - try { - await cleanUpRoutine(); - } catch (error) { - // Its possible that cleanup fails for locked files etc, for this reason retry is added. - await sleep(); - await cleanUpRoutine(); - } - } - - description: string; - - projects: TestAssetProject[]; -} - -export interface ITestAssetProject { - relativeFilePath: string; -} - -export interface ITestAssetWorkspace { - description: string; - projects: ITestAssetProject[]; } diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/lsp_tools_host_slnWithCsproj.code-workspace b/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/lsp_tools_host_slnWithCsproj.code-workspace deleted file mode 100644 index 644cf41f5..000000000 --- a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/lsp_tools_host_slnWithCsproj.code-workspace +++ /dev/null @@ -1,13 +0,0 @@ -{ - "folders": [ - { - "path": ".." - } - ], - "settings": { - "dotnet.defaultSolution": "b_SecondInOrder_SlnFile.sln", - "dotnet.server.trace": "Trace", - "dotnet.server.useOmnisharp": false, - "omnisharp.enableLspDriver": false, - } -} \ No newline at end of file diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/a_FirstInOrder_SlnFile.sln b/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/a_FirstInOrder_SlnFile.sln deleted file mode 100644 index 96b8b7c42..000000000 --- a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/a_FirstInOrder_SlnFile.sln +++ /dev/null @@ -1,85 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio Version 16 -VisualStudioVersion = 16.0.31321.278 -MinimumVisualStudioVersion = 15.0.26124.0 -Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{D28FC441-C95D-47D2-8D5C-E401ABAD7C64}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "app", "src\app\app.csproj", "{D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "lib", "src\lib\lib.csproj", "{717BE881-D74C-45FC-B55D-2085499E1BF8}" -EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "test", "test\test.csproj", "{4679428B-0CA0-4228-B8C0-B676B34A1B30}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "generator", "generator\generator.csproj", "{DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Debug|x64 = Debug|x64 - Debug|x86 = Debug|x86 - Release|Any CPU = Release|Any CPU - Release|x64 = Release|x64 - Release|x86 = Release|x86 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|x64.ActiveCfg = Debug|x64 - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|x64.Build.0 = Debug|x64 - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|x86.ActiveCfg = Debug|x86 - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Debug|x86.Build.0 = Debug|x86 - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|Any CPU.ActiveCfg = Release|Any CPU - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|Any CPU.Build.0 = Release|Any CPU - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|x64.ActiveCfg = Release|x64 - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|x64.Build.0 = Release|x64 - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|x86.ActiveCfg = Release|x86 - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3}.Release|x86.Build.0 = Release|x86 - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|x64.ActiveCfg = Debug|x64 - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|x64.Build.0 = Debug|x64 - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|x86.ActiveCfg = Debug|x86 - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Debug|x86.Build.0 = Debug|x86 - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|Any CPU.Build.0 = Release|Any CPU - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|x64.ActiveCfg = Release|x64 - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|x64.Build.0 = Release|x64 - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|x86.ActiveCfg = Release|x86 - {717BE881-D74C-45FC-B55D-2085499E1BF8}.Release|x86.Build.0 = Release|x86 - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|Any CPU.Build.0 = Debug|Any CPU - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|x64.ActiveCfg = Debug|x64 - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|x64.Build.0 = Debug|x64 - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|x86.ActiveCfg = Debug|x86 - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Debug|x86.Build.0 = Debug|x86 - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|Any CPU.ActiveCfg = Release|Any CPU - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|Any CPU.Build.0 = Release|Any CPU - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|x64.ActiveCfg = Release|x64 - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|x64.Build.0 = Release|x64 - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|x86.ActiveCfg = Release|x86 - {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|x86.Build.0 = Release|x86 - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Debug|x64.ActiveCfg = Debug|Any CPU - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Debug|x64.Build.0 = Debug|Any CPU - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Debug|x86.ActiveCfg = Debug|Any CPU - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Debug|x86.Build.0 = Debug|Any CPU - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Release|Any CPU.ActiveCfg = Release|Any CPU - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Release|Any CPU.Build.0 = Release|Any CPU - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Release|x64.ActiveCfg = Release|Any CPU - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Release|x64.Build.0 = Release|Any CPU - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Release|x86.ActiveCfg = Release|Any CPU - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440}.Release|x86.Build.0 = Release|Any CPU - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection - GlobalSection(NestedProjects) = preSolution - {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3} = {D28FC441-C95D-47D2-8D5C-E401ABAD7C64} - {717BE881-D74C-45FC-B55D-2085499E1BF8} = {D28FC441-C95D-47D2-8D5C-E401ABAD7C64} - {DCFDBE2E-0540-4A9F-AFB7-4CF1F3854440} = {D28FC441-C95D-47D2-8D5C-E401ABAD7C64} - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {7E415A9E-6E39-41C7-A400-051ADE582087} - EndGlobalSection -EndGlobal diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/test/test.csproj b/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/test/test.csproj deleted file mode 100644 index 9f52c5381..000000000 --- a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/test/test.csproj +++ /dev/null @@ -1,15 +0,0 @@ - - - - netcoreapp3.1 - - false - - - - - - - - - diff --git a/omnisharptest/omnisharpIntegrationTests/typeDefinitionProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/typeDefinitionProvider.test.ts index 7ae1aa03b..ff3e670bc 100644 --- a/omnisharptest/omnisharpIntegrationTests/typeDefinitionProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/typeDefinitionProvider.test.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import OmniSharpDefinitionProvider from '../../src/features/definitionProvider'; import * as path from 'path'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { expect, should } from 'chai'; import { activateCSharpExtension, diff --git a/omnisharptest/omnisharpIntegrationTests/virtualDocumentTracker.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/virtualDocumentTracker.integration.test.ts index d2a726418..c71dcf687 100644 --- a/omnisharptest/omnisharpIntegrationTests/virtualDocumentTracker.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/virtualDocumentTracker.integration.test.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import { expect, should } from 'chai'; import { activateCSharpExtension, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; import { IDisposable } from '../../src/disposable'; suite(`Virtual Document Tracking ${testAssetWorkspace.description}`, function () { diff --git a/omnisharptest/omnisharpIntegrationTests/workspaceSymbolProvider.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/workspaceSymbolProvider.integration.test.ts index 6ef129bce..43044fd90 100644 --- a/omnisharptest/omnisharpIntegrationTests/workspaceSymbolProvider.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/workspaceSymbolProvider.integration.test.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import { expect, should } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; suite(`WorkspaceSymbolProvider: ${testAssetWorkspace.description}`, function () { suiteSetup(async function () { diff --git a/src/lsptoolshost/unitTesting.ts b/src/lsptoolshost/unitTesting.ts index 298cda283..acf663bbe 100644 --- a/src/lsptoolshost/unitTesting.ts +++ b/src/lsptoolshost/unitTesting.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import * as languageClient from 'vscode-languageclient/node'; import { RoslynLanguageServer } from './roslynLanguageServer'; -import { RunTestsParams, RunTestsPartialResult, RunTestsRequest } from './roslynProtocol'; +import { RunTestsParams, RunTestsPartialResult, RunTestsRequest, TestProgress } from './roslynProtocol'; export function registerUnitTestingCommands( context: vscode.ExtensionContext, @@ -14,39 +14,44 @@ export function registerUnitTestingCommands( dotnetTestChannel: vscode.OutputChannel ) { context.subscriptions.push( - vscode.commands.registerCommand('dotnet.test.run', async (request) => - runTests(request, languageServer, dotnetTestChannel) + vscode.commands.registerCommand( + 'dotnet.test.run', + async (request): Promise => runTests(request, languageServer, dotnetTestChannel) ) ); context.subscriptions.push( - vscode.commands.registerTextEditorCommand( + // We don't use registerTextEditorCommand because it is required to run synchronously and is not awaitable. + // See https://github.com/microsoft/vscode/issues/16814 for more info. + vscode.commands.registerCommand( 'dotnet.test.runTestsInContext', - async (textEditor: vscode.TextEditor) => { - return runTestsInContext(false, textEditor, languageServer, dotnetTestChannel); - } + async (): Promise => runTestsInContext(false, languageServer, dotnetTestChannel) ) ); context.subscriptions.push( - vscode.commands.registerTextEditorCommand( + vscode.commands.registerCommand( 'dotnet.test.debugTestsInContext', - async (textEditor: vscode.TextEditor) => { - return runTestsInContext(true, textEditor, languageServer, dotnetTestChannel); - } + async (): Promise => runTestsInContext(true, languageServer, dotnetTestChannel) ) ); } async function runTestsInContext( debug: boolean, - textEditor: vscode.TextEditor, languageServer: RoslynLanguageServer, dotnetTestChannel: vscode.OutputChannel -) { - const contextRange: languageClient.Range = { start: textEditor.selection.active, end: textEditor.selection.active }; - const textDocument: languageClient.TextDocumentIdentifier = { uri: textEditor.document.fileName }; +): Promise { + const activeEditor = vscode.window.activeTextEditor; + if (!activeEditor) { + throw new Error('No active editor'); + } + const contextRange: languageClient.Range = { + start: activeEditor.selection.active, + end: activeEditor.selection.active, + }; + const textDocument: languageClient.TextDocumentIdentifier = { uri: activeEditor.document.fileName }; const request: RunTestsParams = { textDocument: textDocument, range: contextRange, attachDebugger: debug }; - await runTests(request, languageServer, dotnetTestChannel); + return runTests(request, languageServer, dotnetTestChannel); } let _testRunInProgress = false; @@ -55,7 +60,7 @@ async function runTests( request: RunTestsParams, languageServer: RoslynLanguageServer, dotnetTestChannel: vscode.OutputChannel -) { +): Promise { if (_testRunInProgress) { vscode.window.showErrorMessage('Test run already in progress'); return; @@ -64,7 +69,8 @@ async function runTests( _testRunInProgress = true; dotnetTestChannel.show(true); - vscode.window + let lastProgress: TestProgress | undefined = undefined; + await vscode.window .withProgress( { location: vscode.ProgressLocation.Notification, @@ -87,6 +93,7 @@ async function runTests( const reportIncrement = ((completed - totalReportedComplete) / totalTests) * 100; progress.report({ message: output.stage, increment: reportIncrement }); totalReportedComplete = completed; + lastProgress = output.progress; } else { progress.report({ message: output.stage }); } @@ -121,7 +128,13 @@ async function runTests( } ) .then( - () => (_testRunInProgress = false), - () => (_testRunInProgress = false) + () => { + _testRunInProgress = false; + }, + () => { + _testRunInProgress = false; + } ); + + return lastProgress; } diff --git a/tasks/projectPaths.ts b/tasks/projectPaths.ts index 5a2fa0dfb..f48bb3521 100644 --- a/tasks/projectPaths.ts +++ b/tasks/projectPaths.ts @@ -21,12 +21,8 @@ export const codeExtensionPath = commandLineOptions.codeExtensionPath || rootPat export const omnisharpTestRootPath = path.join(rootPath, 'out', 'omnisharptest'); export const omnisharpFeatureTestRunnerPath = path.join(omnisharpTestRootPath, 'runFeatureTests.js'); -export const omnisharpTestAssetsRootPath = path.join( - rootPath, - 'omnisharptest', - 'omnisharpIntegrationTests', - 'testAssets' -); + +export const integrationTestAssetsRootPath = path.join(rootPath, 'test', 'integrationTests', 'testAssets'); export const testRootPath = path.join(rootPath, 'out', 'test'); export const integrationTestRunnerPath = path.join(testRootPath, 'integrationTests', 'runIntegrationTests.js'); diff --git a/tasks/testTasks.ts b/tasks/testTasks.ts index d0191f827..e9a56e75e 100644 --- a/tasks/testTasks.ts +++ b/tasks/testTasks.ts @@ -10,7 +10,7 @@ import { omnisharpFeatureTestRunnerPath, mochaPath, rootPath, - omnisharpTestAssetsRootPath, + integrationTestAssetsRootPath, omnisharpTestRootPath, testRootPath, integrationTestRunnerPath, @@ -112,7 +112,7 @@ gulp.task('test', gulp.series('test:unit', 'test:integration')); async function runOmnisharpIntegrationTest(testAssetName: string, engine: 'stdio' | 'lsp') { const workspaceFile = `omnisharp${engine === 'lsp' ? '_lsp' : ''}_${testAssetName}.code-workspace`; - const workspacePath = path.join(omnisharpTestAssetsRootPath, testAssetName, '.vscode', workspaceFile); + const workspacePath = path.join(integrationTestAssetsRootPath, testAssetName, '.vscode', workspaceFile); const codeTestsPath = path.join(omnisharpTestRootPath, 'omnisharpIntegrationTests'); const env = { @@ -142,7 +142,7 @@ async function runOmnisharpIntegrationTest(testAssetName: string, engine: 'stdio async function runIntegrationTest(testAssetName: string) { const workspacePath = path.join( - omnisharpTestAssetsRootPath, + integrationTestAssetsRootPath, testAssetName, '.vscode', `lsp_tools_host_${testAssetName}.code-workspace` diff --git a/test/integrationTests/index.ts b/test/integrationTests/index.ts index 643f65a82..d3323f117 100644 --- a/test/integrationTests/index.ts +++ b/test/integrationTests/index.ts @@ -15,18 +15,27 @@ async function runIntegrationTests() { } const jestConfigPath = path.join(repoRoot, 'jest.config.ts'); - const { results } = await jest.runCLI( - { - config: jestConfigPath, - selectProjects: [jestIntegrationTestProjectName], - // Since we're running tests in the actual vscode process we have to run them serially. - runInBand: true, - // Timeout cannot be overriden in the jest config file, so override here. - testTimeout: 120000, - verbose: true, - } as Config.Argv, - [jestIntegrationTestProjectName] - ); + const jestConfig = { + config: jestConfigPath, + selectProjects: [jestIntegrationTestProjectName], + // Since we're running tests in the actual vscode process we have to run them serially. + runInBand: true, + // Timeout cannot be overriden in the jest config file, so override here. + testTimeout: 120000, + verbose: true, + } as Config.Argv; + + let filter: string; + if (process.env.TEST_FILE_FILTER) { + // If we have just a file, run that with runTestsByPath. + jestConfig.runTestsByPath = true; + jestConfig.testMatch = [process.env.TEST_FILE_FILTER]; + filter = process.env.TEST_FILE_FILTER; + } else { + filter = jestIntegrationTestProjectName; + } + + const { results } = await jest.runCLI(jestConfig, [filter]); if (!results.success) { throw new Error('Tests failed.'); diff --git a/test/integrationTests/integrationHelpers.ts b/test/integrationTests/integrationHelpers.ts index 03cab5c88..331023dfd 100644 --- a/test/integrationTests/integrationHelpers.ts +++ b/test/integrationTests/integrationHelpers.ts @@ -6,6 +6,7 @@ import * as vscode from 'vscode'; import * as path from 'path'; import { CSharpExtensionExports } from '../../src/csharpExtensionExports'; +import { existsSync } from 'fs'; export async function activateCSharpExtension(): Promise { // Ensure the dependent extension exists - when launching via F5 launch.json we can't install the extension prior to opening vscode. @@ -14,7 +15,7 @@ export async function activateCSharpExtension(): Promise { vscode.extensions.getExtension(vscodeDotnetRuntimeExtensionId); if (!dotnetRuntimeExtension) { await vscode.commands.executeCommand('workbench.extensions.installExtension', vscodeDotnetRuntimeExtensionId); - await vscode.commands.executeCommand('workbench.action.reloadWindow'); + await reloadWindow(); } const csharpExtension = vscode.extensions.getExtension('ms-dotnettools.csharp'); @@ -29,6 +30,20 @@ export async function activateCSharpExtension(): Promise { console.log('ms-dotnettools.csharp activated'); } +export async function openFileInWorkspaceAsync(relativeFilePath: string): Promise { + const root = vscode.workspace.workspaceFolders![0].uri.fsPath; + const filePath = path.join(root, relativeFilePath); + if (!existsSync(filePath)) { + throw new Error(`File ${filePath} does not exist`); + } + + await vscode.commands.executeCommand('vscode.open', vscode.Uri.file(filePath)); +} + +export async function reloadWindow(): Promise { + await vscode.commands.executeCommand('workbench.action.reloadWindow'); +} + export function isRazorWorkspace(workspace: typeof vscode.workspace) { return isGivenSln(workspace, 'BasicRazorApp2_1'); } diff --git a/test/integrationTests/lspInlayHints.integration.test.ts b/test/integrationTests/lspInlayHints.integration.test.ts index 70305816a..f0c6ce0f9 100644 --- a/test/integrationTests/lspInlayHints.integration.test.ts +++ b/test/integrationTests/lspInlayHints.integration.test.ts @@ -3,20 +3,16 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ +import * as path from 'path'; import * as vscode from 'vscode'; - import * as jestLib from '@jest/globals'; -import testAssetWorkspace from '../../omnisharptest/omnisharpIntegrationTests/testAssets/testAssetWorkspace'; -import * as path from 'path'; -import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; +import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import * as integrationHelpers from './integrationHelpers'; import { InlayHint, InlayHintKind, Position } from 'vscode-languageserver-protocol'; -const describeif = (condition: boolean) => (condition ? jestLib.describe : jestLib.describe.skip); -const skip = !isRazorWorkspace(vscode.workspace) && !isSlnWithGenerator(vscode.workspace); - -describeif(skip)(`LSP Inlay Hints ${testAssetWorkspace.description}`, function () { - let fileUri: vscode.Uri; +jestLib.describe(`LSP Inlay Hints ${testAssetWorkspace.description}`, function () { jestLib.beforeEach(async function () { + await testAssetWorkspace.restoreLspToolsHostAsync(); const editorConfig = vscode.workspace.getConfiguration('editor'); await editorConfig.update('inlayHints.enabled', true); const dotnetConfig = vscode.workspace.getConfiguration('dotnet'); @@ -35,13 +31,8 @@ describeif(skip)(`LSP Inlay Hints ${testAssetWorkspace.description}`, function ( await csharpConfig.update('inlayHints.enableInlayHintsForLambdaParameterTypes', true); await csharpConfig.update('inlayHints.enableInlayHintsForImplicitObjectCreation', true); - const fileName = 'inlayHints.cs'; - const projectDirectory = testAssetWorkspace.projects[0].projectDirectoryPath; - const filePath = path.join(projectDirectory, fileName); - fileUri = vscode.Uri.file(filePath); - - await vscode.commands.executeCommand('vscode.open', fileUri); - await activateCSharpExtension(); + await integrationHelpers.openFileInWorkspaceAsync(path.join('src', 'app', 'inlayHints.cs')); + await integrationHelpers.activateCSharpExtension(); }); jestLib.afterEach(async () => { @@ -50,19 +41,24 @@ describeif(skip)(`LSP Inlay Hints ${testAssetWorkspace.description}`, function ( jestLib.test('Hints retrieved for region', async () => { const range = new vscode.Range(new vscode.Position(4, 8), new vscode.Position(15, 85)); + const activeDocument = vscode.window.activeTextEditor?.document.uri; + if (!activeDocument) { + throw new Error('No active document'); + } const hints: vscode.InlayHint[] = await vscode.commands.executeCommand( 'vscode.executeInlayHintProvider', - fileUri, + activeDocument, range ); - jestLib.expect(hints).toHaveLength(5); + jestLib.expect(hints).toHaveLength(6); assertInlayHintEqual(hints[0], InlayHint.create(Position.create(6, 12), 'InlayHints', InlayHintKind.Type)); assertInlayHintEqual(hints[1], InlayHint.create(Position.create(7, 27), 'InlayHints', InlayHintKind.Type)); - assertInlayHintEqual(hints[2], InlayHint.create(Position.create(9, 17), 'i:', InlayHintKind.Parameter)); - assertInlayHintEqual(hints[3], InlayHint.create(Position.create(10, 15), 'param1:', InlayHintKind.Parameter)); - assertInlayHintEqual(hints[4], InlayHint.create(Position.create(11, 27), 'param1:', InlayHintKind.Parameter)); + assertInlayHintEqual(hints[2], InlayHint.create(Position.create(8, 28), 'string', InlayHintKind.Type)); + assertInlayHintEqual(hints[3], InlayHint.create(Position.create(9, 17), 'i:', InlayHintKind.Parameter)); + assertInlayHintEqual(hints[4], InlayHint.create(Position.create(10, 15), 'param1:', InlayHintKind.Parameter)); + assertInlayHintEqual(hints[5], InlayHint.create(Position.create(11, 27), 'param1:', InlayHintKind.Parameter)); function assertInlayHintEqual(actual: vscode.InlayHint, expected: InlayHint) { const actualLabel = actual.label as string; diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/.vscode/omnisharp_BasicRazorApp2_1.code-workspace b/test/integrationTests/testAssets/BasicRazorApp2_1/.vscode/omnisharp_BasicRazorApp2_1.code-workspace similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/.vscode/omnisharp_BasicRazorApp2_1.code-workspace rename to test/integrationTests/testAssets/BasicRazorApp2_1/.vscode/omnisharp_BasicRazorApp2_1.code-workspace diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/.vscode/omnisharp_lsp_BasicRazorApp2_1.code-workspace b/test/integrationTests/testAssets/BasicRazorApp2_1/.vscode/omnisharp_lsp_BasicRazorApp2_1.code-workspace similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/.vscode/omnisharp_lsp_BasicRazorApp2_1.code-workspace rename to test/integrationTests/testAssets/BasicRazorApp2_1/.vscode/omnisharp_lsp_BasicRazorApp2_1.code-workspace diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/BasicRazorApp2_1.csproj b/test/integrationTests/testAssets/BasicRazorApp2_1/BasicRazorApp2_1.csproj similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/BasicRazorApp2_1.csproj rename to test/integrationTests/testAssets/BasicRazorApp2_1/BasicRazorApp2_1.csproj diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/Pages/ErrorHaver.razor b/test/integrationTests/testAssets/BasicRazorApp2_1/Pages/ErrorHaver.razor similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/Pages/ErrorHaver.razor rename to test/integrationTests/testAssets/BasicRazorApp2_1/Pages/ErrorHaver.razor diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/Pages/Index.cshtml b/test/integrationTests/testAssets/BasicRazorApp2_1/Pages/Index.cshtml similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/Pages/Index.cshtml rename to test/integrationTests/testAssets/BasicRazorApp2_1/Pages/Index.cshtml diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/Program.cs b/test/integrationTests/testAssets/BasicRazorApp2_1/Program.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/Program.cs rename to test/integrationTests/testAssets/BasicRazorApp2_1/Program.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/_ViewImports.cshtml b/test/integrationTests/testAssets/BasicRazorApp2_1/_ViewImports.cshtml similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/BasicRazorApp2_1/_ViewImports.cshtml rename to test/integrationTests/testAssets/BasicRazorApp2_1/_ViewImports.cshtml diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/NuGet.config b/test/integrationTests/testAssets/NuGet.config similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/NuGet.config rename to test/integrationTests/testAssets/NuGet.config diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/basicRazorApp21.ts b/test/integrationTests/testAssets/basicRazorApp21.ts similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/basicRazorApp21.ts rename to test/integrationTests/testAssets/basicRazorApp21.ts diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj.ts b/test/integrationTests/testAssets/singleCsproj.ts similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj.ts rename to test/integrationTests/testAssets/singleCsproj.ts diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/.gitignore b/test/integrationTests/testAssets/singleCsproj/.gitignore similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/.gitignore rename to test/integrationTests/testAssets/singleCsproj/.gitignore diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/.vscode/omnisharp_lsp_singleCsproj.code-workspace b/test/integrationTests/testAssets/singleCsproj/.vscode/omnisharp_lsp_singleCsproj.code-workspace similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/.vscode/omnisharp_lsp_singleCsproj.code-workspace rename to test/integrationTests/testAssets/singleCsproj/.vscode/omnisharp_lsp_singleCsproj.code-workspace diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/.vscode/omnisharp_singleCsproj.code-workspace b/test/integrationTests/testAssets/singleCsproj/.vscode/omnisharp_singleCsproj.code-workspace similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/.vscode/omnisharp_singleCsproj.code-workspace rename to test/integrationTests/testAssets/singleCsproj/.vscode/omnisharp_singleCsproj.code-workspace diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/A.cs b/test/integrationTests/testAssets/singleCsproj/A.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/A.cs rename to test/integrationTests/testAssets/singleCsproj/A.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/DocComments.cs b/test/integrationTests/testAssets/singleCsproj/DocComments.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/DocComments.cs rename to test/integrationTests/testAssets/singleCsproj/DocComments.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/ISomeInterface.cs b/test/integrationTests/testAssets/singleCsproj/ISomeInterface.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/ISomeInterface.cs rename to test/integrationTests/testAssets/singleCsproj/ISomeInterface.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/Program.cs b/test/integrationTests/testAssets/singleCsproj/Program.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/Program.cs rename to test/integrationTests/testAssets/singleCsproj/Program.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/SomeInterfaceImpl.cs b/test/integrationTests/testAssets/singleCsproj/SomeInterfaceImpl.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/SomeInterfaceImpl.cs rename to test/integrationTests/testAssets/singleCsproj/SomeInterfaceImpl.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/completion.cs b/test/integrationTests/testAssets/singleCsproj/completion.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/completion.cs rename to test/integrationTests/testAssets/singleCsproj/completion.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/completionBase.cs b/test/integrationTests/testAssets/singleCsproj/completionBase.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/completionBase.cs rename to test/integrationTests/testAssets/singleCsproj/completionBase.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/definition.cs b/test/integrationTests/testAssets/singleCsproj/definition.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/definition.cs rename to test/integrationTests/testAssets/singleCsproj/definition.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/diagnostics.cs b/test/integrationTests/testAssets/singleCsproj/diagnostics.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/diagnostics.cs rename to test/integrationTests/testAssets/singleCsproj/diagnostics.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/documentSymbols.cs b/test/integrationTests/testAssets/singleCsproj/documentSymbols.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/documentSymbols.cs rename to test/integrationTests/testAssets/singleCsproj/documentSymbols.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/hover.cs b/test/integrationTests/testAssets/singleCsproj/hover.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/hover.cs rename to test/integrationTests/testAssets/singleCsproj/hover.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/implementation.cs b/test/integrationTests/testAssets/singleCsproj/implementation.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/implementation.cs rename to test/integrationTests/testAssets/singleCsproj/implementation.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/inlayHints.cs b/test/integrationTests/testAssets/singleCsproj/inlayHints.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/inlayHints.cs rename to test/integrationTests/testAssets/singleCsproj/inlayHints.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/reference.cs b/test/integrationTests/testAssets/singleCsproj/reference.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/reference.cs rename to test/integrationTests/testAssets/singleCsproj/reference.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/remap.cs b/test/integrationTests/testAssets/singleCsproj/remap.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/remap.cs rename to test/integrationTests/testAssets/singleCsproj/remap.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/remapped.txt b/test/integrationTests/testAssets/singleCsproj/remapped.txt similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/remapped.txt rename to test/integrationTests/testAssets/singleCsproj/remapped.txt diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/secondaryDiagnostics.cs b/test/integrationTests/testAssets/singleCsproj/secondaryDiagnostics.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/secondaryDiagnostics.cs rename to test/integrationTests/testAssets/singleCsproj/secondaryDiagnostics.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/semantictokens.cs b/test/integrationTests/testAssets/singleCsproj/semantictokens.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/semantictokens.cs rename to test/integrationTests/testAssets/singleCsproj/semantictokens.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/sigHelp.cs b/test/integrationTests/testAssets/singleCsproj/sigHelp.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/sigHelp.cs rename to test/integrationTests/testAssets/singleCsproj/sigHelp.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/singleCsproj.csproj b/test/integrationTests/testAssets/singleCsproj/singleCsproj.csproj similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/singleCsproj.csproj rename to test/integrationTests/testAssets/singleCsproj/singleCsproj.csproj diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/typeDefinition.cs b/test/integrationTests/testAssets/singleCsproj/typeDefinition.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/singleCsproj/typeDefinition.cs rename to test/integrationTests/testAssets/singleCsproj/typeDefinition.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj.ts b/test/integrationTests/testAssets/slnFilterWithCsproj.ts similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj.ts rename to test/integrationTests/testAssets/slnFilterWithCsproj.ts diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/.gitignore b/test/integrationTests/testAssets/slnFilterWithCsproj/.gitignore similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/.gitignore rename to test/integrationTests/testAssets/slnFilterWithCsproj/.gitignore diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/.vscode/omnisharp_lsp_slnFilterWithCsproj.code-workspace b/test/integrationTests/testAssets/slnFilterWithCsproj/.vscode/omnisharp_lsp_slnFilterWithCsproj.code-workspace similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/.vscode/omnisharp_lsp_slnFilterWithCsproj.code-workspace rename to test/integrationTests/testAssets/slnFilterWithCsproj/.vscode/omnisharp_lsp_slnFilterWithCsproj.code-workspace diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/.vscode/omnisharp_slnFilterWithCsproj.code-workspace b/test/integrationTests/testAssets/slnFilterWithCsproj/.vscode/omnisharp_slnFilterWithCsproj.code-workspace similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/.vscode/omnisharp_slnFilterWithCsproj.code-workspace rename to test/integrationTests/testAssets/slnFilterWithCsproj/.vscode/omnisharp_slnFilterWithCsproj.code-workspace diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/SolutionFile.sln b/test/integrationTests/testAssets/slnFilterWithCsproj/SolutionFile.sln similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/SolutionFile.sln rename to test/integrationTests/testAssets/slnFilterWithCsproj/SolutionFile.sln diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/SolutionFilter.slnf b/test/integrationTests/testAssets/slnFilterWithCsproj/SolutionFilter.slnf similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/SolutionFilter.slnf rename to test/integrationTests/testAssets/slnFilterWithCsproj/SolutionFilter.slnf diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/A.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/A.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/A.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/A.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/DocComments.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/DocComments.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/DocComments.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/DocComments.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/ISomeInterface.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/ISomeInterface.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/ISomeInterface.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/ISomeInterface.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/Program.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/Program.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/Program.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/Program.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/SomeInterfaceImpl.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/SomeInterfaceImpl.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/SomeInterfaceImpl.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/SomeInterfaceImpl.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/app.csproj b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/app.csproj similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/app.csproj rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/app.csproj diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/completion.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/completion.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/completion.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/completion.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/completionBase.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/completionBase.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/completionBase.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/completionBase.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/definition.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/definition.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/definition.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/definition.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/diagnostics.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/diagnostics.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/diagnostics.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/diagnostics.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/documentSymbols.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/documentSymbols.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/documentSymbols.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/documentSymbols.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/hover.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/hover.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/hover.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/hover.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/implementation.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/implementation.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/implementation.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/implementation.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/inlayHints.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/inlayHints.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/inlayHints.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/inlayHints.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/reference.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/reference.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/reference.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/reference.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/remap.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/remap.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/remap.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/remap.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/remapped.txt b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/remapped.txt similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/remapped.txt rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/remapped.txt diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/secondaryDiagnostics.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/secondaryDiagnostics.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/secondaryDiagnostics.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/secondaryDiagnostics.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/semantictokens.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/semantictokens.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/semantictokens.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/semantictokens.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/sigHelp.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/sigHelp.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/sigHelp.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/sigHelp.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/typeDefinition.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/app/typeDefinition.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/app/typeDefinition.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/app/typeDefinition.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/lib/Class1.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/src/lib/Class1.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/lib/Class1.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/lib/Class1.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/lib/lib.csproj b/test/integrationTests/testAssets/slnFilterWithCsproj/src/lib/lib.csproj similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/src/lib/lib.csproj rename to test/integrationTests/testAssets/slnFilterWithCsproj/src/lib/lib.csproj diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/test/UnitTest1.cs b/test/integrationTests/testAssets/slnFilterWithCsproj/test/UnitTest1.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/test/UnitTest1.cs rename to test/integrationTests/testAssets/slnFilterWithCsproj/test/UnitTest1.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/test/test.csproj b/test/integrationTests/testAssets/slnFilterWithCsproj/test/test.csproj similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnFilterWithCsproj/test/test.csproj rename to test/integrationTests/testAssets/slnFilterWithCsproj/test/test.csproj diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj.ts b/test/integrationTests/testAssets/slnWithCsproj.ts similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj.ts rename to test/integrationTests/testAssets/slnWithCsproj.ts diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.gitignore b/test/integrationTests/testAssets/slnWithCsproj/.gitignore similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.gitignore rename to test/integrationTests/testAssets/slnWithCsproj/.gitignore diff --git a/test/integrationTests/testAssets/slnWithCsproj/.vscode/lsp_tools_host_slnWithCsproj.code-workspace b/test/integrationTests/testAssets/slnWithCsproj/.vscode/lsp_tools_host_slnWithCsproj.code-workspace new file mode 100644 index 000000000..cef8ba814 --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/.vscode/lsp_tools_host_slnWithCsproj.code-workspace @@ -0,0 +1,13 @@ +{ + "folders": [ + { + "path": ".." + } + ], + "settings": { + "dotnet.defaultSolution": "b_SecondInOrder_SlnFile.sln", + "dotnet.server.trace": "Trace", + "dotnet.server.useOmnisharp": false, + "omnisharp.enableLspDriver": false, + } +} \ No newline at end of file diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_lsp_slnWithCsproj.code-workspace b/test/integrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_lsp_slnWithCsproj.code-workspace similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_lsp_slnWithCsproj.code-workspace rename to test/integrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_lsp_slnWithCsproj.code-workspace diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_slnWithCsproj.code-workspace b/test/integrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_slnWithCsproj.code-workspace similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_slnWithCsproj.code-workspace rename to test/integrationTests/testAssets/slnWithCsproj/.vscode/omnisharp_slnWithCsproj.code-workspace diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/b_SecondInOrder_SlnFile.sln b/test/integrationTests/testAssets/slnWithCsproj/b_SecondInOrder_SlnFile.sln similarity index 78% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/b_SecondInOrder_SlnFile.sln rename to test/integrationTests/testAssets/slnWithCsproj/b_SecondInOrder_SlnFile.sln index 9cef673b8..7878b7d6d 100644 --- a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/b_SecondInOrder_SlnFile.sln +++ b/test/integrationTests/testAssets/slnWithCsproj/b_SecondInOrder_SlnFile.sln @@ -10,8 +10,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "lib", "src\lib\lib.csproj", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "test", "test\test.csproj", "{4679428B-0CA0-4228-B8C0-B676B34A1B30}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "generator", "generator\generator.csproj", "{29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -58,18 +56,6 @@ Global {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|x64.Build.0 = Release|x64 {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|x86.ActiveCfg = Release|x86 {4679428B-0CA0-4228-B8C0-B676B34A1B30}.Release|x86.Build.0 = Release|x86 - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Debug|x64.ActiveCfg = Debug|Any CPU - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Debug|x64.Build.0 = Debug|Any CPU - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Debug|x86.ActiveCfg = Debug|Any CPU - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Debug|x86.Build.0 = Debug|Any CPU - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Release|Any CPU.Build.0 = Release|Any CPU - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Release|x64.ActiveCfg = Release|Any CPU - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Release|x64.Build.0 = Release|Any CPU - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Release|x86.ActiveCfg = Release|Any CPU - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -77,7 +63,6 @@ Global GlobalSection(NestedProjects) = preSolution {D36E1CC9-62CA-45A3-8BD0-6ADC2767FFB3} = {D28FC441-C95D-47D2-8D5C-E401ABAD7C64} {717BE881-D74C-45FC-B55D-2085499E1BF8} = {D28FC441-C95D-47D2-8D5C-E401ABAD7C64} - {29F9B261-D48D-4D9B-9005-FB6D3B4F9CC4} = {D28FC441-C95D-47D2-8D5C-E401ABAD7C64} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {8D6D9870-8770-4AB0-8142-CC80181A8DB7} diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/A.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/A.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/A.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/A.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/DocComments.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/DocComments.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/DocComments.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/DocComments.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/ISomeInterface.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/ISomeInterface.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/ISomeInterface.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/ISomeInterface.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/Program.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/Program.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/Program.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/Program.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/SomeInterfaceImpl.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/SomeInterfaceImpl.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/SomeInterfaceImpl.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/SomeInterfaceImpl.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/app.csproj b/test/integrationTests/testAssets/slnWithCsproj/src/app/app.csproj similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/app.csproj rename to test/integrationTests/testAssets/slnWithCsproj/src/app/app.csproj diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/completion.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/completion.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/completion.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/completion.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/completionBase.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/completionBase.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/completionBase.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/completionBase.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/definition.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/definition.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/definition.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/definition.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/diagnostics.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/diagnostics.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/diagnostics.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/diagnostics.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/documentSymbols.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/documentSymbols.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/documentSymbols.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/documentSymbols.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/hover.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/hover.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/hover.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/hover.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/implementation.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/implementation.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/implementation.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/implementation.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/inlayHints.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/inlayHints.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/inlayHints.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/inlayHints.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/reference.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/reference.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/reference.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/reference.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/remap.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/remap.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/remap.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/remap.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/remapped.txt b/test/integrationTests/testAssets/slnWithCsproj/src/app/remapped.txt similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/remapped.txt rename to test/integrationTests/testAssets/slnWithCsproj/src/app/remapped.txt diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/secondaryDiagnostics.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/secondaryDiagnostics.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/secondaryDiagnostics.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/secondaryDiagnostics.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/semantictokens.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/semantictokens.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/semantictokens.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/semantictokens.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/sigHelp.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/typeDefinition.cs b/test/integrationTests/testAssets/slnWithCsproj/src/app/typeDefinition.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/app/typeDefinition.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/app/typeDefinition.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/lib/Class1.cs b/test/integrationTests/testAssets/slnWithCsproj/src/lib/Class1.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/lib/Class1.cs rename to test/integrationTests/testAssets/slnWithCsproj/src/lib/Class1.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/lib/lib.csproj b/test/integrationTests/testAssets/slnWithCsproj/src/lib/lib.csproj similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/src/lib/lib.csproj rename to test/integrationTests/testAssets/slnWithCsproj/src/lib/lib.csproj diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/test/UnitTest1.cs b/test/integrationTests/testAssets/slnWithCsproj/test/UnitTest1.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithCsproj/test/UnitTest1.cs rename to test/integrationTests/testAssets/slnWithCsproj/test/UnitTest1.cs diff --git a/test/integrationTests/testAssets/slnWithCsproj/test/test.csproj b/test/integrationTests/testAssets/slnWithCsproj/test/test.csproj new file mode 100644 index 000000000..8e0e160f9 --- /dev/null +++ b/test/integrationTests/testAssets/slnWithCsproj/test/test.csproj @@ -0,0 +1,24 @@ + + + + net7.0 + enable + + false + true + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator.ts b/test/integrationTests/testAssets/slnWithGenerator.ts similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator.ts rename to test/integrationTests/testAssets/slnWithGenerator.ts diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/.vscode/settings.json b/test/integrationTests/testAssets/slnWithGenerator/.vscode/settings.json similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/.vscode/settings.json rename to test/integrationTests/testAssets/slnWithGenerator/.vscode/settings.json diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/app/GeneratorTrigger.cs b/test/integrationTests/testAssets/slnWithGenerator/app/GeneratorTrigger.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/app/GeneratorTrigger.cs rename to test/integrationTests/testAssets/slnWithGenerator/app/GeneratorTrigger.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/app/app.csproj b/test/integrationTests/testAssets/slnWithGenerator/app/app.csproj similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/app/app.csproj rename to test/integrationTests/testAssets/slnWithGenerator/app/app.csproj diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/generator/MainGenerator.cs b/test/integrationTests/testAssets/slnWithGenerator/generator/MainGenerator.cs similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/generator/MainGenerator.cs rename to test/integrationTests/testAssets/slnWithGenerator/generator/MainGenerator.cs diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/generator/generator.csproj b/test/integrationTests/testAssets/slnWithGenerator/generator/generator.csproj similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/generator/generator.csproj rename to test/integrationTests/testAssets/slnWithGenerator/generator/generator.csproj diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/slnWithGenerator.sln b/test/integrationTests/testAssets/slnWithGenerator/slnWithGenerator.sln similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/slnWithGenerator/slnWithGenerator.sln rename to test/integrationTests/testAssets/slnWithGenerator/slnWithGenerator.sln diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/spawnGit.ts b/test/integrationTests/testAssets/spawnGit.ts similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/spawnGit.ts rename to test/integrationTests/testAssets/spawnGit.ts diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/testAssetWorkspace.ts b/test/integrationTests/testAssets/testAssetWorkspace.ts similarity index 100% rename from omnisharptest/omnisharpIntegrationTests/testAssets/testAssetWorkspace.ts rename to test/integrationTests/testAssets/testAssetWorkspace.ts diff --git a/test/integrationTests/testAssets/testAssets.ts b/test/integrationTests/testAssets/testAssets.ts new file mode 100644 index 000000000..5f385a078 --- /dev/null +++ b/test/integrationTests/testAssets/testAssets.ts @@ -0,0 +1,91 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as fs from 'async-file'; +import * as path from 'path'; +import * as vscode from 'vscode'; +import spawnGit from '../../../test/integrationTests/testAssets/spawnGit'; +import { execChildProcess } from '../../../src/common'; + +export class TestAssetProject { + constructor(project: ITestAssetProject) { + this.relativeFilePath = project.relativeFilePath; + } + + relativeFilePath: string; + + get projectDirectoryPath(): string { + return path.join(vscode.workspace.workspaceFolders![0].uri.fsPath, path.dirname(this.relativeFilePath)); + } + + async addFileWithContents(fileName: string, contents: string): Promise { + const dir = this.projectDirectoryPath; + const loc = path.join(dir, fileName); + await fs.writeTextFile(loc, contents); + return vscode.Uri.file(loc); + } +} + +export class TestAssetWorkspace { + constructor(workspace: ITestAssetWorkspace) { + this.projects = workspace.projects.map((w) => new TestAssetProject(w)); + + this.description = workspace.description; + } + + get vsCodeDirectoryPath(): string { + return path.join(vscode.workspace.workspaceFolders![0].uri.fsPath, '.vscode'); + } + + get launchJsonPath(): string { + return path.join(this.vsCodeDirectoryPath, 'launch.json'); + } + + get tasksJsonPath(): string { + return path.join(this.vsCodeDirectoryPath, 'tasks.json'); + } + + async cleanupWorkspace(): Promise { + const workspaceRootPath = vscode.workspace.workspaceFolders![0].uri.fsPath; + const cleanUpRoutine = async () => { + await vscode.commands.executeCommand('workbench.action.closeAllEditors'); + await spawnGit(['clean', '-xdf', '.'], { cwd: workspaceRootPath }); + await spawnGit(['checkout', '--', '.'], { cwd: workspaceRootPath }); + }; + + const sleep = async () => new Promise((resolve) => setTimeout(resolve, 2 * 1000)); + + try { + await cleanUpRoutine(); + } catch (error) { + // Its possible that cleanup fails for locked files etc, for this reason retry is added. + await sleep(); + await cleanUpRoutine(); + } + } + + /** + * Temporary workaround for lack of restore support in the roslyn server. + * Replace when https://github.com/dotnet/vscode-csharp/issues/5725 is fixed. + */ + async restoreLspToolsHostAsync(): Promise { + const root = vscode.workspace.workspaceFolders![0].uri.fsPath; + const output = await execChildProcess(`dotnet restore ${root}`, process.cwd(), process.env); + console.log(output); + } + + description: string; + + projects: TestAssetProject[]; +} + +export interface ITestAssetProject { + relativeFilePath: string; +} + +export interface ITestAssetWorkspace { + description: string; + projects: ITestAssetProject[]; +} diff --git a/test/integrationTests/unitTests.integration.test.ts b/test/integrationTests/unitTests.integration.test.ts new file mode 100644 index 000000000..61a0f56bf --- /dev/null +++ b/test/integrationTests/unitTests.integration.test.ts @@ -0,0 +1,121 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import * as path from 'path'; +import * as jestLib from '@jest/globals'; +import testAssetWorkspace from './testAssets/testAssetWorkspace'; +import { activateCSharpExtension, openFileInWorkspaceAsync } from './integrationHelpers'; +import { TestProgress } from '../../src/lsptoolshost/roslynProtocol'; + +jestLib.describe(`Unit Testing ${testAssetWorkspace.description}`, function () { + jestLib.beforeAll(async function () { + await testAssetWorkspace.restoreLspToolsHostAsync(); + }); + + jestLib.beforeEach(async function () { + await activateCSharpExtension(); + const fileName = path.join('test', 'UnitTest1.cs'); + await openFileInWorkspaceAsync(fileName); + }); + + jestLib.afterAll(async () => { + await testAssetWorkspace.cleanupWorkspace(); + }); + + jestLib.test('Unit test code lens items are displayed', async () => { + const codeLenses = await getCodeLensesAsync(); + jestLib.expect(codeLenses).toHaveLength(6); + + const classRange = new vscode.Range(new vscode.Position(5, 17), new vscode.Position(5, 26)); + // Class level debug all tests + jestLib.expect(codeLenses[1].command?.command).toBe('dotnet.test.run'); + jestLib.expect(codeLenses[1].command?.title).toBe('Debug All Tests'); + jestLib.expect(codeLenses[1].command?.arguments![0].attachDebugger).toBe(true); + jestLib.expect(codeLenses[1].range).toStrictEqual(classRange); + + // Class level run all tests + jestLib.expect(codeLenses[2].command?.command).toBe('dotnet.test.run'); + jestLib.expect(codeLenses[2].command?.title).toBe('Run All Tests'); + jestLib.expect(codeLenses[2].command?.arguments![0].attachDebugger).toBe(false); + jestLib.expect(codeLenses[2].range).toStrictEqual(classRange); + + const methodRange = new vscode.Range(new vscode.Position(8, 20), new vscode.Position(8, 25)); + // Method level debug test + jestLib.expect(codeLenses[4].command?.command).toBe('dotnet.test.run'); + jestLib.expect(codeLenses[4].command?.title).toBe('Debug Test'); + jestLib.expect(codeLenses[4].command?.arguments![0].attachDebugger).toBe(true); + jestLib.expect(codeLenses[4].range).toStrictEqual(methodRange); + + // Method level run test + jestLib.expect(codeLenses[5].command?.command).toBe('dotnet.test.run'); + jestLib.expect(codeLenses[5].command?.title).toBe('Run Test'); + jestLib.expect(codeLenses[5].command?.arguments![0].attachDebugger).toBe(false); + jestLib.expect(codeLenses[5].range).toStrictEqual(methodRange); + }); + + jestLib.test('Code lens command executes tests', async () => { + const codeLenses = await getCodeLensesAsync(); + jestLib.expect(codeLenses).toHaveLength(6); + + const runAllTestsCommand = codeLenses[2].command!; + jestLib.expect(runAllTestsCommand.title).toBe('Run All Tests'); + + const testResults = await vscode.commands.executeCommand( + runAllTestsCommand.command, + runAllTestsCommand.arguments![0] + ); + jestLib.expect(testResults).toBeDefined(); + jestLib.expect(testResults?.totalTests).toEqual(1); + jestLib.expect(testResults?.testsPassed).toEqual(1); + jestLib.expect(testResults?.testsFailed).toEqual(0); + jestLib.expect(testResults?.testsSkipped).toEqual(0); + }); + + jestLib.test('dotnet.test.runTestsInContext executes tests', async () => { + const activeEditor = vscode.window.activeTextEditor; + if (!activeEditor) { + throw new Error('No active editor'); + } + + // Ensure the method is selected in the editor. + activeEditor.selection = new vscode.Selection(new vscode.Position(8, 20), new vscode.Position(8, 25)); + const testResults = await vscode.commands.executeCommand( + 'dotnet.test.runTestsInContext', + activeEditor + ); + jestLib.expect(testResults).toBeDefined(); + jestLib.expect(testResults?.totalTests).toEqual(1); + jestLib.expect(testResults?.testsPassed).toEqual(1); + jestLib.expect(testResults?.testsFailed).toEqual(0); + jestLib.expect(testResults?.testsSkipped).toEqual(0); + }); +}); + +async function getCodeLensesAsync(): Promise { + const activeEditor = vscode.window.activeTextEditor; + if (!activeEditor) { + throw new Error('No active editor'); + } + + // The number of code lens items to resolve. Set to a high number so we get pretty much everything in the document. + const resolvedItemCount = 100; + + const codeLenses = ( + await vscode.commands.executeCommand( + 'vscode.executeCodeLensProvider', + activeEditor.document.uri, + resolvedItemCount + ) + ); + return codeLenses.sort((a, b) => { + const rangeCompare = a.range.start.compareTo(b.range.start); + if (rangeCompare !== 0) { + return rangeCompare; + } + + return a.command!.title.localeCompare(b.command!.command); + }); +} From c7ae769646e2b4dd4e1ec997d3cae3ab4f2f44ce Mon Sep 17 00:00:00 2001 From: David Barbet Date: Sat, 2 Sep 2023 01:33:14 -0700 Subject: [PATCH 2/4] Cleanup and fix races in server activation and restart --- .vscode/settings.json | 3 +- src/common.ts | 6 + src/csharpExtensionExports.ts | 2 + src/lsptoolshost/debugger.ts | 6 +- src/lsptoolshost/languageServerEvents.ts | 33 + src/lsptoolshost/onAutoInsert.ts | 95 +++ src/lsptoolshost/razorCommands.ts | 107 +++ src/lsptoolshost/roslynLanguageServer.ts | 617 +++++------------- .../roslynLanguageServerExportChannel.ts | 14 +- ...slynWorkspaceDebugConfigurationProvider.ts | 27 +- .../services/solutionSnapshotProvider.ts | 19 + src/lsptoolshost/showToastNotification.ts | 58 ++ src/main.ts | 51 +- .../src/codeActions/codeActionsHandler.ts | 10 +- .../completion/razorCompletionItemProvider.ts | 6 +- .../src/diagnostics/razorDiagnosticHandler.ts | 4 +- .../src/document/razorDocumentManager.ts | 4 +- .../simplify/razorSimplifyMethodHandler.ts | 4 +- test/integrationTests/integrationHelpers.ts | 32 +- .../lspInlayHints.integration.test.ts | 5 +- .../unitTests.integration.test.ts | 3 +- 21 files changed, 601 insertions(+), 505 deletions(-) create mode 100644 src/lsptoolshost/languageServerEvents.ts create mode 100644 src/lsptoolshost/onAutoInsert.ts create mode 100644 src/lsptoolshost/razorCommands.ts create mode 100644 src/lsptoolshost/services/solutionSnapshotProvider.ts create mode 100644 src/lsptoolshost/showToastNotification.ts diff --git a/.vscode/settings.json b/.vscode/settings.json index 0c125a0b2..a67f54a97 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -20,5 +20,6 @@ "omnisharp.autoStart": false, "editor.formatOnSave": false, "eslint.lintTask.enable": true, - "dotnet.defaultSolution": "disable" + "dotnet.defaultSolution": "disable", + "jest.autoRun": "off" } diff --git a/src/common.ts b/src/common.ts index 313222947..0291d7eac 100644 --- a/src/common.ts +++ b/src/common.ts @@ -226,3 +226,9 @@ export function findPowerShell(): string | undefined { } } } + +export function isNotNull(value: T): asserts value is NonNullable { + if (value === null || value === undefined) { + throw new Error('value is null or undefined.'); + } +} diff --git a/src/csharpExtensionExports.ts b/src/csharpExtensionExports.ts index 6613aab12..35e85b615 100644 --- a/src/csharpExtensionExports.ts +++ b/src/csharpExtensionExports.ts @@ -9,6 +9,7 @@ import { EventStream } from './eventStream'; import TestManager from './features/dotnetTest'; import { GlobalBrokeredServiceContainer } from '@microsoft/servicehub-framework'; import { RequestType } from 'vscode-languageclient/node'; +import { LanguageServerEvents } from './lsptoolshost/languageServerEvents'; export interface OmnisharpExtensionExports { initializationFinished: () => Promise; @@ -32,4 +33,5 @@ export interface CSharpExtensionExperimentalExports { params: Params, token: vscode.CancellationToken ) => Promise; + languageServerEvents: LanguageServerEvents; } diff --git a/src/lsptoolshost/debugger.ts b/src/lsptoolshost/debugger.ts index 5c7bbc705..616d13b80 100644 --- a/src/lsptoolshost/debugger.ts +++ b/src/lsptoolshost/debugger.ts @@ -14,18 +14,20 @@ import OptionProvider from '../shared/observers/optionProvider'; import { ServerStateChange } from './serverStateChange'; import { DotnetConfigurationResolver } from '../shared/dotnetConfigurationProvider'; import { getCSharpDevKit } from '../utils/getCSharpDevKit'; +import { RoslynLanguageServerEvents } from './languageServerEvents'; export function registerDebugger( context: vscode.ExtensionContext, languageServer: RoslynLanguageServer, + languageServerEvents: RoslynLanguageServerEvents, platformInfo: PlatformInformation, optionProvider: OptionProvider, csharpOutputChannel: vscode.OutputChannel ) { const workspaceInformationProvider: IWorkspaceDebugInformationProvider = - new RoslynWorkspaceDebugInformationProvider(languageServer); + new RoslynWorkspaceDebugInformationProvider(languageServer, csharpOutputChannel); - const disposable = languageServer.registerStateChangeEvent(async (state) => { + const disposable = languageServerEvents.onServerStateChange(async (state) => { if (state === ServerStateChange.ProjectInitializationComplete) { const csharpDevkitExtension = getCSharpDevKit(); if (!csharpDevkitExtension) { diff --git a/src/lsptoolshost/languageServerEvents.ts b/src/lsptoolshost/languageServerEvents.ts new file mode 100644 index 000000000..ded1687a2 --- /dev/null +++ b/src/lsptoolshost/languageServerEvents.ts @@ -0,0 +1,33 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { ServerStateChange } from './serverStateChange'; +import { IDisposable } from '../disposable'; + +/** + * Defines events that are fired by the language server. + * These events can be consumed to wait for the server to reach a certain state. + */ +export interface LanguageServerEvents { + readonly onServerStateChange: vscode.Event; +} + +/** + * Implementation that fires events when the language server reaches a certain state. + * This is intentionally separate from the language server itself, so consumers can + * register for events without having to know about the specific current state of the language server. + */ +export class RoslynLanguageServerEvents implements LanguageServerEvents, IDisposable { + public readonly onServerStateChangeEmitter = new vscode.EventEmitter(); + + public get onServerStateChange(): vscode.Event { + return this.onServerStateChangeEmitter.event; + } + + dispose(): void { + this.onServerStateChangeEmitter.dispose(); + } +} diff --git a/src/lsptoolshost/onAutoInsert.ts b/src/lsptoolshost/onAutoInsert.ts new file mode 100644 index 000000000..9a82df014 --- /dev/null +++ b/src/lsptoolshost/onAutoInsert.ts @@ -0,0 +1,95 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { UriConverter } from './uriConverter'; + +import { FormattingOptions, TextDocumentIdentifier } from 'vscode-languageclient/node'; +import OptionProvider from '../shared/observers/optionProvider'; +import * as RoslynProtocol from './roslynProtocol'; +import { RoslynLanguageServer } from './roslynLanguageServer'; + +export function registerOnAutoInsert(optionsProvider: OptionProvider, languageServer: RoslynLanguageServer) { + let source = new vscode.CancellationTokenSource(); + vscode.workspace.onDidChangeTextDocument(async (e) => { + const options = optionsProvider.GetLatestOptions(); + if (!options.languageServerOptions.documentSelector.includes(e.document.languageId)) { + return; + } + + if (e.contentChanges.length > 1 || e.contentChanges.length === 0) { + return; + } + + const change = e.contentChanges[0]; + + if (!change.range.isEmpty) { + return; + } + + const capabilities = await languageServer.getServerCapabilities(); + + if (capabilities._vs_onAutoInsertProvider) { + // Regular expression to match all whitespace characters except the newline character + const changeTrimmed = change.text.replace(/[^\S\n]+/g, ''); + + if (!capabilities._vs_onAutoInsertProvider._vs_triggerCharacters.includes(changeTrimmed)) { + return; + } + + source.cancel(); + source = new vscode.CancellationTokenSource(); + await applyAutoInsertEdit(e, changeTrimmed, languageServer, source.token); + } + }); +} + +async function applyAutoInsertEdit( + e: vscode.TextDocumentChangeEvent, + changeTrimmed: string, + languageServer: RoslynLanguageServer, + token: vscode.CancellationToken +) { + const change = e.contentChanges[0]; + // The server expects the request position to represent the caret position in the text after the change has already been applied. + // We need to calculate what that position would be after the change is applied and send that to the server. + const position = new vscode.Position( + change.range.start.line, + change.range.start.character + (change.text.length - change.rangeLength) + ); + const uri = UriConverter.serialize(e.document.uri); + const textDocument = TextDocumentIdentifier.create(uri); + const formattingOptions = getFormattingOptions(); + const request: RoslynProtocol.OnAutoInsertParams = { + _vs_textDocument: textDocument, + _vs_position: position, + _vs_ch: changeTrimmed, + _vs_options: formattingOptions, + }; + + const response = await languageServer.sendRequest(RoslynProtocol.OnAutoInsertRequest.type, request, token); + if (response) { + const textEdit = response._vs_textEdit; + const startPosition = new vscode.Position(textEdit.range.start.line, textEdit.range.start.character); + const endPosition = new vscode.Position(textEdit.range.end.line, textEdit.range.end.character); + const docComment = new vscode.SnippetString(textEdit.newText); + const code: any = vscode; + const textEdits = [new code.SnippetTextEdit(new vscode.Range(startPosition, endPosition), docComment)]; + const edit = new vscode.WorkspaceEdit(); + edit.set(e.document.uri, textEdits); + + const applied = vscode.workspace.applyEdit(edit); + if (!applied) { + throw new Error('Tried to insert a comment but an error occurred.'); + } + } +} + +function getFormattingOptions(): FormattingOptions { + const editorConfig = vscode.workspace.getConfiguration('editor'); + const tabSize = editorConfig.get('tabSize') ?? 4; + const insertSpaces = editorConfig.get('insertSpaces') ?? true; + return FormattingOptions.create(tabSize, insertSpaces); +} diff --git a/src/lsptoolshost/razorCommands.ts b/src/lsptoolshost/razorCommands.ts new file mode 100644 index 000000000..aa44ada80 --- /dev/null +++ b/src/lsptoolshost/razorCommands.ts @@ -0,0 +1,107 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import { RoslynLanguageServer } from './roslynLanguageServer'; +import * as vscode from 'vscode'; +import { + DidChangeTextDocumentNotification, + DidCloseTextDocumentNotification, + DidCloseTextDocumentParams, + DidChangeTextDocumentParams, + DocumentDiagnosticParams, + RequestType, + DocumentDiagnosticRequest, + DocumentDiagnosticReport, + CancellationToken, + CodeAction, + CodeActionParams, + CodeActionRequest, + CodeActionResolveRequest, + CompletionParams, + CompletionRequest, + CompletionResolveRequest, + CompletionItem, +} from 'vscode-languageclient/node'; +import SerializableSimplifyMethodParams from '../razor/src/simplify/serializableSimplifyMethodParams'; +import { TextEdit } from 'vscode-html-languageservice'; + +// These are commands that are invoked by the Razor extension, and are used to send LSP requests to the Roslyn LSP server +export const roslynDidChangeCommand = 'roslyn.changeRazorCSharp'; +export const roslynDidCloseCommand = 'roslyn.closeRazorCSharp'; +export const roslynPullDiagnosticCommand = 'roslyn.pullDiagnosticRazorCSharp'; +export const provideCodeActionsCommand = 'roslyn.provideCodeActions'; +export const resolveCodeActionCommand = 'roslyn.resolveCodeAction'; +export const provideCompletionsCommand = 'roslyn.provideCompletions'; +export const resolveCompletionsCommand = 'roslyn.resolveCompletion'; +export const roslynSimplifyMethodCommand = 'roslyn.simplifyMethod'; +export const razorInitializeCommand = 'razor.initialize'; + +export function registerRazorCommands(context: vscode.ExtensionContext, languageServer: RoslynLanguageServer) { + // Razor will call into us (via command) for generated file didChange/didClose notifications. We'll then forward these + // notifications along to Roslyn. didOpen notifications are handled separately via the vscode.openTextDocument method. + context.subscriptions.push( + vscode.commands.registerCommand(roslynDidChangeCommand, async (notification: DidChangeTextDocumentParams) => { + await languageServer.sendNotification(DidChangeTextDocumentNotification.method, notification); + }) + ); + context.subscriptions.push( + vscode.commands.registerCommand(roslynDidCloseCommand, async (notification: DidCloseTextDocumentParams) => { + await languageServer.sendNotification(DidCloseTextDocumentNotification.method, notification); + }) + ); + context.subscriptions.push( + vscode.commands.registerCommand(roslynPullDiagnosticCommand, async (request: DocumentDiagnosticParams) => { + const diagnosticRequestType = new RequestType( + DocumentDiagnosticRequest.method + ); + return await languageServer.sendRequest(diagnosticRequestType, request, CancellationToken.None); + }) + ); + context.subscriptions.push( + vscode.commands.registerCommand( + roslynSimplifyMethodCommand, + async (request: SerializableSimplifyMethodParams) => { + const simplifyMethodRequestType = new RequestType( + 'roslyn/simplifyMethod' + ); + return await languageServer.sendRequest(simplifyMethodRequestType, request, CancellationToken.None); + } + ) + ); + + // The VS Code API for code actions (and the vscode.CodeAction type) doesn't support everything that LSP supports, + // namely the data property, which Razor needs to identify which code actions are on their allow list, so we need + // to expose a command for them to directly invoke our code actions LSP endpoints, rather than use built-in commands. + context.subscriptions.push( + vscode.commands.registerCommand(provideCodeActionsCommand, async (request: CodeActionParams) => { + return await languageServer.sendRequest(CodeActionRequest.type, request, CancellationToken.None); + }) + ); + context.subscriptions.push( + vscode.commands.registerCommand(resolveCodeActionCommand, async (request: CodeAction) => { + return await languageServer.sendRequest(CodeActionResolveRequest.type, request, CancellationToken.None); + }) + ); + + context.subscriptions.push( + vscode.commands.registerCommand(provideCompletionsCommand, async (request: CompletionParams) => { + return await languageServer.sendRequest(CompletionRequest.type, request, CancellationToken.None); + }) + ); + context.subscriptions.push( + vscode.commands.registerCommand(resolveCompletionsCommand, async (request: CompletionItem) => { + return await languageServer.sendRequest(CompletionResolveRequest.type, request, CancellationToken.None); + }) + ); + + // Roslyn is responsible for producing a json file containing information for Razor, that comes from the compilation for + // a project. We want to defer this work until necessary, so this command is called by the Razor document manager to tell + // us when they need us to initialize the Razor things. + context.subscriptions.push( + vscode.commands.registerCommand(razorInitializeCommand, async () => { + await languageServer.sendNotification('razor/initialize', {}); + }) + ); +} diff --git a/src/lsptoolshost/roslynLanguageServer.ts b/src/lsptoolshost/roslynLanguageServer.ts index 0837eca73..c448bb14c 100644 --- a/src/lsptoolshost/roslynLanguageServer.ts +++ b/src/lsptoolshost/roslynLanguageServer.ts @@ -13,44 +13,23 @@ import { registerDebugger } from './debugger'; import { UriConverter } from './uriConverter'; import { - DidChangeTextDocumentNotification, - DidCloseTextDocumentNotification, LanguageClientOptions, ServerOptions, - DidCloseTextDocumentParams, - DidChangeTextDocumentParams, - DocumentDiagnosticParams, State, Trace, RequestType, RequestType0, - FormattingOptions, - TextDocumentIdentifier, - DocumentDiagnosticRequest, - DocumentDiagnosticReport, - CancellationToken, - CodeAction, - CodeActionParams, - CodeActionRequest, - CodeActionResolveRequest, - CompletionParams, - CompletionRequest, - CompletionResolveRequest, - CompletionItem, PartialResultParams, ProtocolRequestType, - MessageType, } from 'vscode-languageclient/node'; import { PlatformInformation } from '../shared/platform'; import { readConfigurations } from './configurationMiddleware'; import OptionProvider from '../shared/observers/optionProvider'; import { DynamicFileInfoHandler } from '../razor/src/dynamicFile/dynamicFileInfoHandler'; import ShowInformationMessage from '../shared/observers/utils/showInformationMessage'; -import EventEmitter = require('events'); -import Disposable from '../disposable'; import * as RoslynProtocol from './roslynProtocol'; import { CSharpDevKitExports } from '../csharpDevKitExports'; -import { ISolutionSnapshotProvider, SolutionSnapshotId } from './services/ISolutionSnapshotProvider'; +import { SolutionSnapshotId } from './services/ISolutionSnapshotProvider'; import { Options } from '../shared/options'; import { ServerStateChange } from './serverStateChange'; import TelemetryReporter from '@vscode/extension-telemetry'; @@ -61,59 +40,31 @@ import { DotnetRuntimeExtensionResolver } from './dotnetRuntimeExtensionResolver import { IHostExecutableResolver } from '../shared/constants/IHostExecutableResolver'; import { RoslynLanguageClient } from './roslynLanguageClient'; import { registerUnitTestingCommands } from './unitTesting'; -import SerializableSimplifyMethodParams from '../razor/src/simplify/serializableSimplifyMethodParams'; -import { TextEdit } from 'vscode-html-languageservice'; import { reportProjectConfigurationEvent } from '../shared/projectConfiguration'; import { getDotnetInfo } from '../shared/utils/getDotnetInfo'; import { registerLanguageServerOptionChanges } from './optionChanges'; import { Observable } from 'rxjs'; import { DotnetInfo } from '../shared/utils/dotnetInfo'; +import { RoslynLanguageServerEvents } from './languageServerEvents'; +import { registerShowToastNotification } from './showToastNotification'; +import { registerRazorCommands } from './razorCommands'; -let _languageServer: RoslynLanguageServer; let _channel: vscode.OutputChannel; let _traceChannel: vscode.OutputChannel; -export class RoslynLanguageServer { - // These are commands that are invoked by the Razor extension, and are used to send LSP requests to the Roslyn LSP server - public static readonly roslynDidOpenCommand: string = 'roslyn.openRazorCSharp'; - public static readonly roslynDidChangeCommand: string = 'roslyn.changeRazorCSharp'; - public static readonly roslynDidCloseCommand: string = 'roslyn.closeRazorCSharp'; - public static readonly roslynPullDiagnosticCommand: string = 'roslyn.pullDiagnosticRazorCSharp'; - public static readonly provideCodeActionsCommand: string = 'roslyn.provideCodeActions'; - public static readonly resolveCodeActionCommand: string = 'roslyn.resolveCodeAction'; - public static readonly provideCompletionsCommand: string = 'roslyn.provideCompletions'; - public static readonly resolveCompletionsCommand: string = 'roslyn.resolveCompletion'; - public static readonly roslynSimplifyMethodCommand: string = 'roslyn.simplifyMethod'; - public static readonly razorInitializeCommand: string = 'razor.initialize'; +// Flag indicating if C# Devkit was installed the last time we activated. +// Used to determine if we need to restart the server on extension changes. +let _wasActivatedWithCSharpDevkit: boolean | undefined; +export class RoslynLanguageServer { // These are notifications we will get from the LSP server and will forward to the Razor extension. private static readonly provideRazorDynamicFileInfoMethodName: string = 'razor/provideDynamicFileInfo'; private static readonly removeRazorDynamicFileInfoMethodName: string = 'razor/removeDynamicFileInfo'; - /** - * Event name used to fire events to the _eventBus when the server state changes. - */ - private static readonly serverStateChangeEvent: string = 'serverStateChange'; - /** * The timeout for stopping the language server (in ms). */ private static _stopTimeout = 10000; - private _languageClient: RoslynLanguageClient | undefined; - - /** - * Flag indicating if C# Devkit was installed the last time we activated. - * Used to determine if we need to restart the server on extension changes. - */ - private _wasActivatedWithCSharpDevkit: boolean | undefined; - - /** - * Event emitter that fires events when state related to the server changes. - * For example when the server starts or stops. - * - * Consumers can register to listen for these events if they need to. - */ - private _eventBus = new EventEmitter(); /** * The solution file previously opened; we hold onto this so we can send this back over if the server were to be relaunched for any reason, like some other configuration @@ -126,25 +77,104 @@ export class RoslynLanguageServer { private _projectFiles: vscode.Uri[] = new Array(); constructor( - private platformInfo: PlatformInformation, - private hostExecutableResolver: IHostExecutableResolver, - private optionProvider: OptionProvider, - private context: vscode.ExtensionContext, - private telemetryReporter: TelemetryReporter, - private additionalExtensionPaths: string[] - ) {} + private _languageClient: RoslynLanguageClient, + private _platformInfo: PlatformInformation, + private _optionProvider: OptionProvider, + private _context: vscode.ExtensionContext, + private _telemetryReporter: TelemetryReporter, + private _languageServerEvents: RoslynLanguageServerEvents + ) { + this.registerSetTrace(); + this.registerSendOpenSolution(); + this.registerOnProjectInitializationComplete(); + this.registerReportProjectConfiguration(); + this.registerExtensionsChanged(); + this.registerTelemetryChanged(); + + // Register Razor dynamic file info handling + this.registerDynamicFileInfo(); + + this.registerDebuggerAttach(); + + registerShowToastNotification(this._languageClient); + } + + private registerSetTrace() { + // Set the language client trace level based on the log level option. + // setTrace only works after the client is already running. + this._languageClient.onDidChangeState(async (state) => { + if (state.newState === State.Running) { + const languageClientTraceLevel = RoslynLanguageServer.GetTraceLevel( + this._optionProvider.GetLatestOptions().languageServerOptions.logLevel + ); + + await this._languageClient.setTrace(languageClientTraceLevel); + } + }); + } + + private registerSendOpenSolution() { + this._languageClient.onDidChangeState(async (state) => { + if (state.newState === State.Running) { + if (this._solutionFile || this._projectFiles.length > 0) { + await this.sendOpenSolutionAndProjectsNotifications(); + } else { + await this.openDefaultSolutionOrProjects(); + } + await this.sendOrSubscribeForServiceBrokerConnection(); + this._languageServerEvents.onServerStateChangeEmitter.fire(ServerStateChange.Started); + } + }); + } + + private registerOnProjectInitializationComplete() { + this._languageClient.onNotification(RoslynProtocol.ProjectInitializationCompleteNotification.type, () => { + this._languageServerEvents.onServerStateChangeEmitter.fire(ServerStateChange.ProjectInitializationComplete); + }); + } + + private registerReportProjectConfiguration() { + // Store the dotnet info outside of the notification so we're not running dotnet --info every time the project changes. + let dotnetInfo: DotnetInfo | undefined = undefined; + this._languageClient.onNotification(RoslynProtocol.ProjectConfigurationNotification.type, async (params) => { + if (!dotnetInfo) { + dotnetInfo = await getDotnetInfo([]); + } + reportProjectConfigurationEvent( + this._telemetryReporter, + params, + this._platformInfo, + dotnetInfo, + this._solutionFile?.fsPath, + true + ); + }); + } /** - * Resolves server options and starts the dotnet language server process. The process is started asynchronously and this method will not wait until - * the process is launched. + * Resolves server options and starts the dotnet language server process. + * This promise will complete when the server starts. */ - public async start(): Promise { - const options = this.optionProvider.GetLatestOptions(); - const logLevel = options.languageServerOptions.logLevel; - const languageClientTraceLevel = this.GetTraceLevel(logLevel); + public static async initializeAsync( + platformInfo: PlatformInformation, + hostExecutableResolver: IHostExecutableResolver, + optionProvider: OptionProvider, + context: vscode.ExtensionContext, + telemetryReporter: TelemetryReporter, + additionalExtensionPaths: string[], + languageServerEvents: RoslynLanguageServerEvents + ): Promise { + const options = optionProvider.GetLatestOptions(); const serverOptions: ServerOptions = async () => { - return await this.startServer(logLevel); + return await this.startServer( + platformInfo, + hostExecutableResolver, + optionProvider, + context, + telemetryReporter, + additionalExtensionPaths + ); }; const documentSelector = options.languageServerOptions.documentSelector; @@ -184,142 +214,33 @@ export class RoslynLanguageServer { client.registerProposedFeatures(); - this._languageClient = client; - - // Set the language client trace level based on the log level option. - // setTrace only works after the client is already running. - // We don't use registerOnStateChange here because we need to access the actual _languageClient instance. - this._languageClient.onDidChangeState(async (state) => { - if (state.newState === State.Running) { - await this._languageClient!.setTrace(languageClientTraceLevel); - if (this._solutionFile || this._projectFiles.length > 0) { - await this.sendOpenSolutionAndProjectsNotifications(); - } else { - await this.openDefaultSolutionOrProjects(); - } - await this.sendOrSubscribeForServiceBrokerConnection(); - this._eventBus.emit(RoslynLanguageServer.serverStateChangeEvent, ServerStateChange.Started); - } - }); - - this._languageClient.onNotification(RoslynProtocol.ProjectInitializationCompleteNotification.type, () => { - this._eventBus.emit( - RoslynLanguageServer.serverStateChangeEvent, - ServerStateChange.ProjectInitializationComplete - ); - }); - - // Store the dotnet info outside of the notification so we're not running dotnet --info every time the project changes. - let dotnetInfo: DotnetInfo | undefined = undefined; - this._languageClient.onNotification(RoslynProtocol.ProjectConfigurationNotification.type, async (params) => { - if (!dotnetInfo) { - dotnetInfo = await getDotnetInfo([]); - } - reportProjectConfigurationEvent( - this.telemetryReporter, - params, - this.platformInfo, - dotnetInfo, - this._solutionFile?.fsPath, - true - ); - }); - - this._languageClient.onNotification(RoslynProtocol.ShowToastNotification.type, async (notification) => { - const messageOptions: vscode.MessageOptions = { - modal: false, - }; - const commands = notification.commands.map((command) => command.title); - const executeCommandByName = async (result: string | undefined) => { - if (result) { - const command = notification.commands.find((command) => command.title === result); - if (!command) { - throw new Error(`Unknown command ${result}`); - } - - if (command.arguments) { - await vscode.commands.executeCommand(command.command, ...command.arguments); - } else { - await vscode.commands.executeCommand(command.command); - } - } - }; - - switch (notification.messageType) { - case MessageType.Error: { - const result = await vscode.window.showErrorMessage( - notification.message, - messageOptions, - ...commands - ); - executeCommandByName(result); - break; - } - case MessageType.Warning: { - const result = await vscode.window.showWarningMessage( - notification.message, - messageOptions, - ...commands - ); - executeCommandByName(result); - break; - } - default: { - const result = await vscode.window.showInformationMessage( - notification.message, - messageOptions, - ...commands - ); - executeCommandByName(result); - break; - } - } - }); - - this.registerExtensionsChanged(this._languageClient); - this.registerTelemetryChanged(this._languageClient); - - // Start the client. This will also launch the server - this._languageClient.start(); - - // Register Razor dynamic file info handling - this.registerDynamicFileInfo(this._languageClient); + const server = new RoslynLanguageServer( + client, + platformInfo, + optionProvider, + context, + telemetryReporter, + languageServerEvents + ); - this.registerDebuggerAttach(this._languageClient); + // Start the client. This will also launch the server process. + await client.start(); + return server; } public async stop(): Promise { - await this._languageClient?.stop(RoslynLanguageServer._stopTimeout); - this._languageClient?.dispose(RoslynLanguageServer._stopTimeout); - this._languageClient = undefined; + await this._languageClient.stop(RoslynLanguageServer._stopTimeout); } - /** - * Restarts the language server. This does not wait until the server has been restarted. - * Note that since some options affect how the language server is initialized, we must - * re-create the LanguageClient instance instead of just stopping/starting it. - */ public async restart(): Promise { - await this.stop(); - await this.start(); - } - - /** - * Allows consumers of this server to register for state change events. - * These state change events will be registered each time the underlying _languageClient instance is created. - */ - public registerStateChangeEvent(listener: (event: ServerStateChange) => Promise): Disposable { - this._eventBus.addListener(RoslynLanguageServer.serverStateChangeEvent, listener); - return new Disposable(() => - this._eventBus.removeListener(RoslynLanguageServer.serverStateChangeEvent, listener) - ); + await this._languageClient.restart(); } /** * Returns whether or not the underlying LSP server is running or not. */ public isRunning(): boolean { - return this._languageClient?.state === State.Running; + return this._languageClient.state === State.Running; } /** @@ -334,7 +255,7 @@ export class RoslynLanguageServer { throw new Error('Tried to send request while server is not started.'); } - const response = await this._languageClient!.sendRequest(type, params, token); + const response = await this._languageClient.sendRequest(type, params, token); return response; } @@ -349,7 +270,7 @@ export class RoslynLanguageServer { throw new Error('Tried to send request while server is not started.'); } - const response = await this._languageClient!.sendRequest(type, token); + const response = await this._languageClient.sendRequest(type, token); return response; } @@ -359,9 +280,6 @@ export class RoslynLanguageServer { onProgress: (p: PR) => Promise, cancellationToken?: vscode.CancellationToken ): Promise { - if (!this._languageClient) { - throw new Error('Tried to send request while server is not started.'); - } // Generate a UUID for our partial result token and apply it to our request. const partialResultToken: string = uuid.v4(); params.partialResultToken = partialResultToken; @@ -383,12 +301,12 @@ export class RoslynLanguageServer { throw new Error('Tried to send request while server is not started.'); } - const response = await this._languageClient!.sendNotification(method, params); + const response = await this._languageClient.sendNotification(method, params); return response; } public async registerSolutionSnapshot(token: vscode.CancellationToken): Promise { - const response = await _languageServer.sendRequest0(RoslynProtocol.RegisterSolutionSnapshotRequest.type, token); + const response = await this.sendRequest0(RoslynProtocol.RegisterSolutionSnapshotRequest.type, token); if (response) { return new SolutionSnapshotId(response.id); } @@ -409,7 +327,7 @@ export class RoslynLanguageServer { } private async sendOpenSolutionAndProjectsNotifications(): Promise { - if (this._languageClient !== undefined && this._languageClient.isRunning()) { + if (this._languageClient.isRunning()) { if (this._solutionFile !== undefined) { const protocolUri = this._languageClient.clientOptions.uriConverters!.code2Protocol(this._solutionFile); await this._languageClient.sendNotification(RoslynProtocol.OpenSolutionNotification.type, { @@ -419,7 +337,7 @@ export class RoslynLanguageServer { if (this._projectFiles.length > 0) { const projectProtocolUris = this._projectFiles.map((uri) => - this._languageClient!.clientOptions.uriConverters!.code2Protocol(uri) + this._languageClient.clientOptions.uriConverters!.code2Protocol(uri) ); await this._languageClient.sendNotification(RoslynProtocol.OpenProjectNotification.type, { projects: projectProtocolUris, @@ -429,12 +347,12 @@ export class RoslynLanguageServer { } private async openDefaultSolutionOrProjects(): Promise { - const options = this.optionProvider.GetLatestOptions(); + const options = this._optionProvider.GetLatestOptions(); // If Dev Kit isn't installed, then we are responsible for picking the solution to open, assuming the user hasn't explicitly // disabled it. if ( - !this._wasActivatedWithCSharpDevkit && + !_wasActivatedWithCSharpDevkit && options.commonOptions.defaultSolution !== 'disable' && this._solutionFile === undefined ) { @@ -498,10 +416,10 @@ export class RoslynLanguageServer { // then we have no projects, and so this extension won't have anything to do. if (exports.hasServerProcessLoaded()) { const pipeName = await exports.getBrokeredServiceServerPipeName(); - this._languageClient?.sendNotification('serviceBroker/connect', { pipeName: pipeName }); + this._languageClient.sendNotification('serviceBroker/connect', { pipeName: pipeName }); } else { // We'll subscribe if the process later launches, and call this function again to send the pipe name. - this.context.subscriptions.push( + this._context.subscriptions.push( exports.serverProcessLoaded(async () => this.sendOrSubscribeForServiceBrokerConnection()) ); } @@ -509,19 +427,22 @@ export class RoslynLanguageServer { } public getServerCapabilities(): any { - if (!this._languageClient) { - throw new Error('Tried to send request while server is not started.'); - } - const capabilities: any = this._languageClient.initializeResult?.capabilities; return capabilities; } - private async startServer(logLevel: string | undefined): Promise { - const options = this.optionProvider.GetLatestOptions(); - const serverPath = getServerPath(options, this.platformInfo); + private static async startServer( + platformInfo: PlatformInformation, + hostExecutableResolver: IHostExecutableResolver, + optionProvider: OptionProvider, + context: vscode.ExtensionContext, + telemetryReporter: TelemetryReporter, + additionalExtensionPaths: string[] + ): Promise { + const options = optionProvider.GetLatestOptions(); + const serverPath = getServerPath(options, platformInfo); - const dotnetInfo = await this.hostExecutableResolver.getHostExecutableInfo(options); + const dotnetInfo = await hostExecutableResolver.getHostExecutableInfo(options); const dotnetRuntimePath = path.dirname(dotnetInfo.path); const dotnetExecutablePath = dotnetInfo.path; @@ -541,11 +462,12 @@ export class RoslynLanguageServer { args.push('--debug'); } + const logLevel = options.languageServerOptions.logLevel; if (logLevel) { args.push('--logLevel', logLevel); } - for (const extensionPath of this.additionalExtensionPaths) { + for (const extensionPath of additionalExtensionPaths) { args.push('--extension', extensionPath); } @@ -554,7 +476,7 @@ export class RoslynLanguageServer { // in our activation because C# Dev Kit depends on C# activation completing. const csharpDevkitExtension = vscode.extensions.getExtension(csharpDevkitExtensionId); if (csharpDevkitExtension) { - this._wasActivatedWithCSharpDevkit = true; + _wasActivatedWithCSharpDevkit = true; // Get the starred suggestion dll location from C# Dev Kit IntelliCode (if both C# Dev Kit and C# Dev Kit IntelliCode are installed). const csharpDevkitIntelliCodeExtension = vscode.extensions.getExtension( @@ -578,7 +500,7 @@ export class RoslynLanguageServer { // C# Dev Kit is not installed - continue C#-only activation. _channel.appendLine('Activating C# standalone...'); vscode.commands.executeCommand('setContext', 'dotnet.server.activatedStandalone', true); - this._wasActivatedWithCSharpDevkit = false; + _wasActivatedWithCSharpDevkit = false; } if (logLevel && [Trace.Messages, Trace.Verbose].includes(this.GetTraceLevel(logLevel))) { @@ -586,9 +508,9 @@ export class RoslynLanguageServer { } // shouldn't this arg only be set if it's running with CSDevKit? - args.push('--telemetryLevel', this.telemetryReporter.telemetryLevel); + args.push('--telemetryLevel', telemetryReporter.telemetryLevel); - args.push('--extensionLogDirectory', this.context.logUri.fsPath); + args.push('--extensionLogDirectory', context.logUri.fsPath); let childProcess: cp.ChildProcessWithoutNullStreams; const cpOptions: cp.SpawnOptionsWithoutStdio = { @@ -618,22 +540,24 @@ export class RoslynLanguageServer { return childProcess; } - private registerDynamicFileInfo(client: RoslynLanguageClient) { + private registerDynamicFileInfo() { // When the Roslyn language server sends a request for Razor dynamic file info, we forward that request along to Razor via // a command. - client.onRequest(RoslynLanguageServer.provideRazorDynamicFileInfoMethodName, async (request) => + this._languageClient.onRequest(RoslynLanguageServer.provideRazorDynamicFileInfoMethodName, async (request) => vscode.commands.executeCommand(DynamicFileInfoHandler.provideDynamicFileInfoCommand, request) ); - client.onNotification(RoslynLanguageServer.removeRazorDynamicFileInfoMethodName, async (notification) => - vscode.commands.executeCommand(DynamicFileInfoHandler.removeDynamicFileInfoCommand, notification) + this._languageClient.onNotification( + RoslynLanguageServer.removeRazorDynamicFileInfoMethodName, + async (notification) => + vscode.commands.executeCommand(DynamicFileInfoHandler.removeDynamicFileInfoCommand, notification) ); } - private registerDebuggerAttach(client: RoslynLanguageClient) { - client.onRequest( + private registerDebuggerAttach() { + this._languageClient.onRequest( RoslynProtocol.DebugAttachRequest.type, async (request) => { - const debugOptions = this.optionProvider.GetLatestOptions().commonOptions.unitTestDebuggingOptions; + const debugOptions = this._optionProvider.GetLatestOptions().commonOptions.unitTestDebuggingOptions; const debugConfiguration: vscode.DebugConfiguration = { ...debugOptions, name: '.NET Core Attach', @@ -650,20 +574,20 @@ export class RoslynLanguageServer { ); } - private registerExtensionsChanged(languageClient: RoslynLanguageClient) { + private registerExtensionsChanged() { // subscribe to extension change events so that we can get notified if C# Dev Kit is added/removed later. - languageClient.addDisposable( + this._languageClient.addDisposable( vscode.extensions.onDidChange(async () => { const csharpDevkitExtension = getCSharpDevKit(); - if (this._wasActivatedWithCSharpDevkit === undefined) { + if (_wasActivatedWithCSharpDevkit === undefined) { // Haven't activated yet. return; } const title = vscode.l10n.t('Restart Language Server'); const command = 'dotnet.restartServer'; - if (csharpDevkitExtension && !this._wasActivatedWithCSharpDevkit) { + if (csharpDevkitExtension && !_wasActivatedWithCSharpDevkit) { // We previously started without C# Dev Kit and its now installed. // Offer a prompt to restart the server to use C# Dev Kit. _channel.appendLine(`Detected new installation of ${csharpDevkitExtensionId}`); @@ -677,9 +601,9 @@ export class RoslynLanguageServer { ); } - private registerTelemetryChanged(languageClient: RoslynLanguageClient) { + private registerTelemetryChanged() { // Subscribe to telemetry events so we can enable/disable as needed - languageClient.addDisposable( + this._languageClient.addDisposable( vscode.env.onDidChangeTelemetryEnabled((_: boolean) => { const title = 'Restart Language Server'; const command = 'dotnet.restartServer'; @@ -690,7 +614,7 @@ export class RoslynLanguageServer { ); } - private async getCSharpDevkitExportArgs( + private static async getCSharpDevkitExportArgs( csharpDevkitExtension: vscode.Extension, options: Options ): Promise { @@ -714,7 +638,7 @@ export class RoslynLanguageServer { return args; } - private async getCSharpDevkitIntelliCodeExportArgs( + private static async getCSharpDevkitIntelliCodeExportArgs( csharpDevkitIntelliCodeExtension: vscode.Extension ): Promise { const exports = await csharpDevkitIntelliCodeExtension.activate(); @@ -725,7 +649,7 @@ export class RoslynLanguageServer { return csharpIntelliCodeArgs; } - private async setupDevKitEnvironment( + private static async setupDevKitEnvironment( env: NodeJS.ProcessEnv, csharpDevkitExtension: vscode.Extension ): Promise { @@ -740,14 +664,14 @@ export class RoslynLanguageServer { await exports.setupTelemetryEnvironmentAsync(env); } - private getLanguageServicesDevKitComponentPath(csharpDevKitExports: CSharpDevKitExports): string { + private static getLanguageServicesDevKitComponentPath(csharpDevKitExports: CSharpDevKitExports): string { return path.join( csharpDevKitExports.components['@microsoft/visualstudio-languageservices-devkit'], 'Microsoft.VisualStudio.LanguageServices.DevKit.dll' ); } - private GetTraceLevel(logLevel: string): Trace { + private static GetTraceLevel(logLevel: string): Trace { switch (logLevel) { case 'Trace': return Trace.Verbose; @@ -772,7 +696,7 @@ export class RoslynLanguageServer { } public async getBuildOnlyDiagnosticIds(token: vscode.CancellationToken): Promise { - const response = await _languageServer.sendRequest0(RoslynProtocol.BuildOnlyDiagnosticIdsRequest.type, token); + const response = await this.sendRequest0(RoslynProtocol.BuildOnlyDiagnosticIdsRequest.type, token); if (response) { return response.ids; } @@ -782,14 +706,9 @@ export class RoslynLanguageServer { } /** - * Brokered service implementation. + * Creates and activates the Roslyn language server. + * The returned promise will complete when the server starts. */ -export class SolutionSnapshotProvider implements ISolutionSnapshotProvider { - public async registerSolutionSnapshot(token: vscode.CancellationToken): Promise { - return _languageServer.registerSolutionSnapshot(token); - } -} - export async function activateRoslynLanguageServer( context: vscode.ExtensionContext, platformInfo: PlatformInformation, @@ -797,7 +716,8 @@ export async function activateRoslynLanguageServer( optionObservable: Observable, outputChannel: vscode.OutputChannel, dotnetTestChannel: vscode.OutputChannel, - reporter: TelemetryReporter + reporter: TelemetryReporter, + languageServerEvents: RoslynLanguageServerEvents ): Promise { // Create a channel for outputting general logs from the language server. _channel = outputChannel; @@ -811,64 +731,30 @@ export async function activateRoslynLanguageServer( context.extensionPath ); const additionalExtensionPaths = scanExtensionPlugins(); - _languageServer = new RoslynLanguageServer( + + const languageServer = await RoslynLanguageServer.initializeAsync( platformInfo, hostExecutableResolver, optionProvider, context, reporter, - additionalExtensionPaths + additionalExtensionPaths, + languageServerEvents ); // Register any commands that need to be handled by the extension. - registerCommands(context, _languageServer, optionProvider, hostExecutableResolver, _channel); + registerCommands(context, languageServer, optionProvider, hostExecutableResolver, _channel); - registerRazorCommands(context, _languageServer); + registerRazorCommands(context, languageServer); - registerUnitTestingCommands(context, _languageServer, dotnetTestChannel); + registerUnitTestingCommands(context, languageServer, dotnetTestChannel); // Register any needed debugger components that need to communicate with the language server. - registerDebugger(context, _languageServer, platformInfo, optionProvider, _channel); + registerDebugger(context, languageServer, languageServerEvents, platformInfo, optionProvider, _channel); context.subscriptions.push(registerLanguageServerOptionChanges(optionObservable)); - const options = optionProvider.GetLatestOptions(); - let source = new vscode.CancellationTokenSource(); - vscode.workspace.onDidChangeTextDocument(async (e) => { - if (!options.languageServerOptions.documentSelector.includes(e.document.languageId)) { - return; - } - - if (e.contentChanges.length > 1 || e.contentChanges.length === 0) { - return; - } - - const change = e.contentChanges[0]; - - if (!change.range.isEmpty) { - return; - } - - const capabilities = await _languageServer.getServerCapabilities(); - - if (capabilities._vs_onAutoInsertProvider) { - // Regular expression to match all whitespace characters except the newline character - const changeTrimmed = change.text.replace(/[^\S\n]+/g, ''); - - if (!capabilities._vs_onAutoInsertProvider._vs_triggerCharacters.includes(changeTrimmed)) { - return; - } - - source.cancel(); - source = new vscode.CancellationTokenSource(); - await applyAutoInsertEdit(e, changeTrimmed, source.token); - } - }); - - // Start the language server. - await _languageServer.start(); - - return _languageServer; + return languageServer; function scanExtensionPlugins(): string[] { return vscode.extensions.all.flatMap((extension) => { @@ -929,157 +815,6 @@ function getInstalledServerPath(platformInfo: PlatformInformation): string { return pathWithExtension; } -export async function waitForProjectInitialization(): Promise { - return new Promise((resolve, _) => { - _languageServer.registerStateChangeEvent(async (state) => { - if (state === ServerStateChange.ProjectInitializationComplete) { - resolve(); - } - }); - }); -} - -function registerRazorCommands(context: vscode.ExtensionContext, languageServer: RoslynLanguageServer) { - // Razor will call into us (via command) for generated file didChange/didClose notifications. We'll then forward these - // notifications along to Roslyn. didOpen notifications are handled separately via the vscode.openTextDocument method. - context.subscriptions.push( - vscode.commands.registerCommand( - RoslynLanguageServer.roslynDidChangeCommand, - async (notification: DidChangeTextDocumentParams) => { - await languageServer.sendNotification(DidChangeTextDocumentNotification.method, notification); - } - ) - ); - context.subscriptions.push( - vscode.commands.registerCommand( - RoslynLanguageServer.roslynDidCloseCommand, - async (notification: DidCloseTextDocumentParams) => { - await languageServer.sendNotification(DidCloseTextDocumentNotification.method, notification); - } - ) - ); - context.subscriptions.push( - vscode.commands.registerCommand( - RoslynLanguageServer.roslynPullDiagnosticCommand, - async (request: DocumentDiagnosticParams) => { - const diagnosticRequestType = new RequestType( - DocumentDiagnosticRequest.method - ); - return await languageServer.sendRequest(diagnosticRequestType, request, CancellationToken.None); - } - ) - ); - context.subscriptions.push( - vscode.commands.registerCommand( - RoslynLanguageServer.roslynSimplifyMethodCommand, - async (request: SerializableSimplifyMethodParams) => { - const simplifyMethodRequestType = new RequestType( - 'roslyn/simplifyMethod' - ); - return await languageServer.sendRequest(simplifyMethodRequestType, request, CancellationToken.None); - } - ) - ); - - // The VS Code API for code actions (and the vscode.CodeAction type) doesn't support everything that LSP supports, - // namely the data property, which Razor needs to identify which code actions are on their allow list, so we need - // to expose a command for them to directly invoke our code actions LSP endpoints, rather than use built-in commands. - context.subscriptions.push( - vscode.commands.registerCommand( - RoslynLanguageServer.provideCodeActionsCommand, - async (request: CodeActionParams) => { - return await languageServer.sendRequest(CodeActionRequest.type, request, CancellationToken.None); - } - ) - ); - context.subscriptions.push( - vscode.commands.registerCommand(RoslynLanguageServer.resolveCodeActionCommand, async (request: CodeAction) => { - return await languageServer.sendRequest(CodeActionResolveRequest.type, request, CancellationToken.None); - }) - ); - - context.subscriptions.push( - vscode.commands.registerCommand( - RoslynLanguageServer.provideCompletionsCommand, - async (request: CompletionParams) => { - return await languageServer.sendRequest(CompletionRequest.type, request, CancellationToken.None); - } - ) - ); - context.subscriptions.push( - vscode.commands.registerCommand( - RoslynLanguageServer.resolveCompletionsCommand, - async (request: CompletionItem) => { - return await languageServer.sendRequest(CompletionResolveRequest.type, request, CancellationToken.None); - } - ) - ); - - // Roslyn is responsible for producing a json file containing information for Razor, that comes from the compilation for - // a project. We want to defer this work until necessary, so this command is called by the Razor document manager to tell - // us when they need us to initialize the Razor things. - context.subscriptions.push( - vscode.commands.registerCommand(RoslynLanguageServer.razorInitializeCommand, async () => { - await languageServer.sendNotification('razor/initialize', {}); - }) - ); -} - -async function applyAutoInsertEdit( - e: vscode.TextDocumentChangeEvent, - changeTrimmed: string, - token: vscode.CancellationToken -) { - const change = e.contentChanges[0]; - // The server expects the request position to represent the caret position in the text after the change has already been applied. - // We need to calculate what that position would be after the change is applied and send that to the server. - const position = new vscode.Position( - change.range.start.line, - change.range.start.character + (change.text.length - change.rangeLength) - ); - const uri = UriConverter.serialize(e.document.uri); - const textDocument = TextDocumentIdentifier.create(uri); - const formattingOptions = getFormattingOptions(); - const request: RoslynProtocol.OnAutoInsertParams = { - _vs_textDocument: textDocument, - _vs_position: position, - _vs_ch: changeTrimmed, - _vs_options: formattingOptions, - }; - - const response = await _languageServer.sendRequest(RoslynProtocol.OnAutoInsertRequest.type, request, token); - if (response) { - const textEdit = response._vs_textEdit; - const startPosition = new vscode.Position(textEdit.range.start.line, textEdit.range.start.character); - const endPosition = new vscode.Position(textEdit.range.end.line, textEdit.range.end.character); - const docComment = new vscode.SnippetString(textEdit.newText); - const code: any = vscode; - const textEdits = [new code.SnippetTextEdit(new vscode.Range(startPosition, endPosition), docComment)]; - const edit = new vscode.WorkspaceEdit(); - edit.set(e.document.uri, textEdits); - - const applied = vscode.workspace.applyEdit(edit); - if (!applied) { - throw new Error('Tried to insert a comment but an error occurred.'); - } - } -} - -function getFormattingOptions(): FormattingOptions { - const editorConfig = vscode.workspace.getConfiguration('editor'); - const tabSize = editorConfig.get('tabSize') ?? 4; - const insertSpaces = editorConfig.get('insertSpaces') ?? true; - return FormattingOptions.create(tabSize, insertSpaces); -} - -// this method is called when your extension is deactivated -export async function deactivate() { - if (!_languageServer) { - return undefined; - } - return _languageServer.stop(); -} - // VS code will have a default session id when running under tests. Since we may still // report telemetry, we need to give a unique session id instead of the default value. function getSessionId(): string { diff --git a/src/lsptoolshost/roslynLanguageServerExportChannel.ts b/src/lsptoolshost/roslynLanguageServerExportChannel.ts index 1adfe69a0..be5372881 100644 --- a/src/lsptoolshost/roslynLanguageServerExportChannel.ts +++ b/src/lsptoolshost/roslynLanguageServerExportChannel.ts @@ -7,24 +7,14 @@ import { RequestType } from 'vscode-languageclient/node'; import { RoslynLanguageServer } from './roslynLanguageServer'; export class RoslynLanguageServerExport { - private _server: RoslynLanguageServer | undefined; - - constructor(private serverPromise: Promise) {} - - private async ensureServer(): Promise { - if (this._server === undefined) { - this._server = await this.serverPromise; - } - - return this._server; - } + constructor(private _serverInitialized: Promise) {} public async sendRequest( type: RequestType, params: Params, token: vscode.CancellationToken ): Promise { - const server = await this.ensureServer(); + const server = await this._serverInitialized; // We need to recreate the type parameter to ensure that the prototypes line up. The `RequestType` we receive could have been // from a different version. const newType = new RequestType(type.method); diff --git a/src/lsptoolshost/roslynWorkspaceDebugConfigurationProvider.ts b/src/lsptoolshost/roslynWorkspaceDebugConfigurationProvider.ts index f5e3cb990..9e820c656 100644 --- a/src/lsptoolshost/roslynWorkspaceDebugConfigurationProvider.ts +++ b/src/lsptoolshost/roslynWorkspaceDebugConfigurationProvider.ts @@ -11,11 +11,15 @@ import { } from '../shared/IWorkspaceDebugInformationProvider'; import { isBlazorWebAssemblyHosted, isBlazorWebAssemblyProject, isWebProject } from '../shared/utils'; import { RoslynLanguageServer } from './roslynLanguageServer'; -import { WorkspaceDebugConfigurationParams, WorkspaceDebugConfigurationRequest } from './roslynProtocol'; +import { + ProjectDebugConfiguration, + WorkspaceDebugConfigurationParams, + WorkspaceDebugConfigurationRequest, +} from './roslynProtocol'; import { UriConverter } from './uriConverter'; export class RoslynWorkspaceDebugInformationProvider implements IWorkspaceDebugInformationProvider { - constructor(private server: RoslynLanguageServer) {} + constructor(private server: RoslynLanguageServer, private outputChannel: vscode.OutputChannel) {} public async getWorkspaceDebugInformation( workspaceFolder: vscode.Uri @@ -28,11 +32,20 @@ export class RoslynWorkspaceDebugInformationProvider implements IWorkspaceDebugI workspacePath: UriConverter.serialize(workspaceFolder), }; - const response = await this.server.sendRequest( - WorkspaceDebugConfigurationRequest.type, - params, - new vscode.CancellationTokenSource().token - ); + let response: ProjectDebugConfiguration[]; + try { + response = await this.server.sendRequest( + WorkspaceDebugConfigurationRequest.type, + params, + new vscode.CancellationTokenSource().token + ); + } catch (e) { + // Server errors are already logged by the language client, but its totally possible + // that we fail because the server is restarting or a process got killed, etc. + // Catch the error and log to the correct output (instead of going to the extension host output). + this.outputChannel.appendLine(`Failed to get debug configuration: ${e}`); + return; + } // LSP serializes and deserializes URIs as (URI formatted) strings not actual types. So convert to the actual type here. const projects: ProjectDebugInformation[] | undefined = await mapAsync(response, async (p) => { diff --git a/src/lsptoolshost/services/solutionSnapshotProvider.ts b/src/lsptoolshost/services/solutionSnapshotProvider.ts new file mode 100644 index 000000000..41908edb8 --- /dev/null +++ b/src/lsptoolshost/services/solutionSnapshotProvider.ts @@ -0,0 +1,19 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { RoslynLanguageServer } from '../roslynLanguageServer'; +import { ISolutionSnapshotProvider, SolutionSnapshotId } from './ISolutionSnapshotProvider'; + +/** + * Brokered service implementation. + */ +export class SolutionSnapshotProvider implements ISolutionSnapshotProvider { + constructor(private _languageServerPromise: Promise) {} + public async registerSolutionSnapshot(token: vscode.CancellationToken): Promise { + const languageServer = await this._languageServerPromise; + return languageServer.registerSolutionSnapshot(token); + } +} diff --git a/src/lsptoolshost/showToastNotification.ts b/src/lsptoolshost/showToastNotification.ts new file mode 100644 index 000000000..df57ac54f --- /dev/null +++ b/src/lsptoolshost/showToastNotification.ts @@ -0,0 +1,58 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as vscode from 'vscode'; +import { RoslynLanguageClient } from './roslynLanguageClient'; +import { MessageType } from 'vscode-languageserver-protocol'; +import { ShowToastNotification } from './roslynProtocol'; + +export function registerShowToastNotification(client: RoslynLanguageClient) { + client.onNotification(ShowToastNotification.type, async (notification) => { + const messageOptions: vscode.MessageOptions = { + modal: false, + }; + const commands = notification.commands.map((command) => command.title); + const executeCommandByName = async (result: string | undefined) => { + if (result) { + const command = notification.commands.find((command) => command.title === result); + if (!command) { + throw new Error(`Unknown command ${result}`); + } + + if (command.arguments) { + await vscode.commands.executeCommand(command.command, ...command.arguments); + } else { + await vscode.commands.executeCommand(command.command); + } + } + }; + + switch (notification.messageType) { + case MessageType.Error: { + const result = await vscode.window.showErrorMessage(notification.message, messageOptions, ...commands); + executeCommandByName(result); + break; + } + case MessageType.Warning: { + const result = await vscode.window.showWarningMessage( + notification.message, + messageOptions, + ...commands + ); + executeCommandByName(result); + break; + } + default: { + const result = await vscode.window.showInformationMessage( + notification.message, + messageOptions, + ...commands + ); + executeCommandByName(result); + break; + } + } + }); +} diff --git a/src/main.ts b/src/main.ts index 20b960b9b..667e3a85d 100644 --- a/src/main.ts +++ b/src/main.ts @@ -41,12 +41,7 @@ import { installRuntimeDependencies } from './installRuntimeDependencies'; import { isValidDownload } from './packageManager/isValidDownload'; import { BackgroundWorkStatusBarObserver } from './observers/backgroundWorkStatusBarObserver'; import { getDotnetPackApi } from './dotnetPack'; -import { - RoslynLanguageServer, - SolutionSnapshotProvider, - activateRoslynLanguageServer, - waitForProjectInitialization, -} from './lsptoolshost/roslynLanguageServer'; +import { RoslynLanguageServer, activateRoslynLanguageServer } from './lsptoolshost/roslynLanguageServer'; import { MigrateOptions } from './shared/migrateOptions'; import { getBrokeredServiceContainer } from './lsptoolshost/services/brokeredServicesHosting'; import { CSharpDevKitExports } from './csharpDevKitExports'; @@ -58,6 +53,9 @@ import { BlazorDebugConfigurationProvider } from './razor/src/blazorDebug/blazor import { RazorOmnisharpDownloader } from './razor/razorOmnisharpDownloader'; import { RoslynLanguageServerExport } from './lsptoolshost/roslynLanguageServerExportChannel'; import { registerOmnisharpOptionChanges } from './omnisharp/omnisharpOptionChanges'; +import { RoslynLanguageServerEvents } from './lsptoolshost/languageServerEvents'; +import { ServerStateChange } from './lsptoolshost/serverStateChange'; +import { SolutionSnapshotProvider } from './lsptoolshost/services/solutionSnapshotProvider'; export async function activate( context: vscode.ExtensionContext @@ -122,7 +120,9 @@ export async function activate( let omnisharpLangServicePromise: Promise | undefined = undefined; let omnisharpRazorPromise: Promise | undefined = undefined; - let roslynLanguageServerPromise: Promise | undefined = undefined; + const roslynLanguageServerEvents = new RoslynLanguageServerEvents(); + context.subscriptions.push(roslynLanguageServerEvents); + let roslynLanguageServerStartedPromise: Promise | undefined = undefined; let projectInitializationCompletePromise: Promise | undefined = undefined; if (!useOmnisharpServer) { @@ -142,16 +142,27 @@ export async function activate( ); context.subscriptions.push(optionProvider); - roslynLanguageServerPromise = activateRoslynLanguageServer( + + // Setup a listener for project initialization complete before we start the server. + projectInitializationCompletePromise = new Promise((resolve, _) => { + roslynLanguageServerEvents.onServerStateChange(async (state) => { + if (state === ServerStateChange.ProjectInitializationComplete) { + resolve(); + } + }); + }); + + // Start the server, but do not await the completion to avoid blocking activation. + roslynLanguageServerStartedPromise = activateRoslynLanguageServer( context, platformInfo, optionProvider, optionStream, csharpChannel, dotnetTestChannel, - reporter + reporter, + roslynLanguageServerEvents ); - projectInitializationCompletePromise = waitForProjectInitialization(); } else { const dotnetChannel = vscode.window.createOutputChannel('.NET'); const dotnetChannelObserver = new DotNetChannelObserver(dotnetChannel); @@ -312,18 +323,24 @@ export async function activate( if (!useOmnisharpServer) { tryGetCSharpDevKitExtensionExports(csharpLogObserver); - const languageServerExport = new RoslynLanguageServerExport(roslynLanguageServerPromise!); + // If we got here, the server should definitely have been created. + util.isNotNull(roslynLanguageServerStartedPromise); + util.isNotNull(projectInitializationCompletePromise); + + const languageServerExport = new RoslynLanguageServerExport(roslynLanguageServerStartedPromise); return { initializationFinished: async () => { await coreClrDebugPromise; - await roslynLanguageServerPromise; + await roslynLanguageServerStartedPromise; await projectInitializationCompletePromise; }, - profferBrokeredServices: (container) => profferBrokeredServices(context, container), + profferBrokeredServices: (container) => + profferBrokeredServices(context, container, roslynLanguageServerStartedPromise!), logDirectory: context.logUri.fsPath, determineBrowserType: BlazorDebugConfigurationProvider.determineBrowserType, experimental: { sendServerRequest: async (t, p, ct) => await languageServerExport.sendRequest(t, p, ct), + languageServerEvents: roslynLanguageServerEvents, }, }; } else { @@ -386,11 +403,15 @@ function tryGetCSharpDevKitExtensionExports(csharpLogObserver: CsharpLoggerObser ); } -function profferBrokeredServices(context: vscode.ExtensionContext, serviceContainer: GlobalBrokeredServiceContainer) { +function profferBrokeredServices( + context: vscode.ExtensionContext, + serviceContainer: GlobalBrokeredServiceContainer, + languageServerPromise: Promise +) { context.subscriptions.push( serviceContainer.profferServiceFactory( Descriptors.solutionSnapshotProviderRegistration, - (_mk, _op, _sb) => new SolutionSnapshotProvider() + (_mk, _op, _sb) => new SolutionSnapshotProvider(languageServerPromise) ) ); } diff --git a/src/razor/src/codeActions/codeActionsHandler.ts b/src/razor/src/codeActions/codeActionsHandler.ts index abd382827..017f1f611 100644 --- a/src/razor/src/codeActions/codeActionsHandler.ts +++ b/src/razor/src/codeActions/codeActionsHandler.ts @@ -9,11 +9,11 @@ import { RazorDocumentManager } from '../document/razorDocumentManager'; import { RazorLanguageServerClient } from '../razorLanguageServerClient'; import { RazorLogger } from '../razorLogger'; import { SerializableDelegatedCodeActionParams } from './serializableDelegatedCodeActionParams'; -import { RoslynLanguageServer } from '../../../lsptoolshost/roslynLanguageServer'; import { LanguageKind } from '../rpc/languageKind'; import { UriConverter } from '../../../lsptoolshost/uriConverter'; import { SerializableRazorResolveCodeActionParams } from './serializableRazorResolveCodeActionParams'; import { RazorDocumentSynchronizer } from '../document/razorDocumentSynchronizer'; +import { provideCodeActionsCommand, resolveCodeActionCommand } from '../../../lsptoolshost/razorCommands'; export class CodeActionsHandler { private static readonly provideCodeActionsEndpoint = 'razor/provideCodeActions'; @@ -84,9 +84,7 @@ export class CodeActionsHandler { const virtualCSharpUri = UriConverter.serialize(razorDocument.csharpDocument.uri); codeActionParams.textDocument = TextDocumentIdentifier.create(virtualCSharpUri); - return ( - await vscode.commands.executeCommand(RoslynLanguageServer.provideCodeActionsCommand, codeActionParams) - ); + return await vscode.commands.executeCommand(provideCodeActionsCommand, codeActionParams); } catch (error) { this.logger.logWarning(`${CodeActionsHandler.provideCodeActionsEndpoint} failed with ${error}`); } @@ -124,9 +122,7 @@ export class CodeActionsHandler { // Call Roslyn. Since this code action came from Roslyn, we don't even have to point it // to the virtual C# document. - return ( - await vscode.commands.executeCommand(RoslynLanguageServer.resolveCodeActionCommand, codeAction) - ); + return await vscode.commands.executeCommand(resolveCodeActionCommand, codeAction); } catch (error) { this.logger.logWarning(`${CodeActionsHandler.resolveCodeActionsEndpoint} failed with ${error}`); } diff --git a/src/razor/src/completion/razorCompletionItemProvider.ts b/src/razor/src/completion/razorCompletionItemProvider.ts index a76aadd04..c0b11440d 100644 --- a/src/razor/src/completion/razorCompletionItemProvider.ts +++ b/src/razor/src/completion/razorCompletionItemProvider.ts @@ -12,7 +12,6 @@ import { RazorLogger } from '../razorLogger'; import { getUriPath } from '../uriPaths'; import { ProvisionalCompletionOrchestrator } from './provisionalCompletionOrchestrator'; import { LanguageKind } from '../rpc/languageKind'; -import { RoslynLanguageServer } from '../../../lsptoolshost/roslynLanguageServer'; import { CompletionItem, CompletionList, @@ -23,6 +22,7 @@ import { import { UriConverter } from '../../../lsptoolshost/uriConverter'; import * as RazorConventions from '../razorConventions'; import { MappingHelpers } from '../mapping/mappingHelpers'; +import { provideCompletionsCommand, resolveCompletionsCommand } from '../../../lsptoolshost/razorCommands'; export class RazorCompletionItemProvider extends RazorLanguageFeatureBase implements vscode.CompletionItemProvider { public static async getCompletions( @@ -59,7 +59,7 @@ export class RazorCompletionItemProvider extends RazorLanguageFeatureBase implem // that field because it doesn't exist in the declared vs code // CompletionItem type. completions = await vscode.commands.executeCommand( - RoslynLanguageServer.provideCompletionsCommand, + provideCompletionsCommand, params ); } else { @@ -236,7 +236,7 @@ export class RazorCompletionItemProvider extends RazorLanguageFeatureBase implem // equivalent vscode command to generically do that. if ((item).data) { const newItem = await vscode.commands.executeCommand( - RoslynLanguageServer.resolveCompletionsCommand, + resolveCompletionsCommand, item ); diff --git a/src/razor/src/diagnostics/razorDiagnosticHandler.ts b/src/razor/src/diagnostics/razorDiagnosticHandler.ts index 321348057..8c63228f4 100644 --- a/src/razor/src/diagnostics/razorDiagnosticHandler.ts +++ b/src/razor/src/diagnostics/razorDiagnosticHandler.ts @@ -6,13 +6,13 @@ import * as vscode from 'vscode'; import { DocumentDiagnosticReport, DocumentDiagnosticParams, RequestType } from 'vscode-languageclient'; import { RazorLanguageServerClient } from '../razorLanguageServerClient'; -import { RoslynLanguageServer } from '../../../lsptoolshost/roslynLanguageServer'; import { RazorDocumentManager } from '../document/razorDocumentManager'; import { UriConverter } from '../../../lsptoolshost/uriConverter'; import { RazorLanguageServiceClient } from '../razorLanguageServiceClient'; import { RazorLanguageFeatureBase } from '../razorLanguageFeatureBase'; import { RazorDocumentSynchronizer } from '../document/razorDocumentSynchronizer'; import { RazorLogger } from '../razorLogger'; +import { roslynPullDiagnosticCommand } from '../../../lsptoolshost/razorCommands'; export class RazorDiagnosticHandler extends RazorLanguageFeatureBase { private static readonly razorPullDiagnosticsCommand = 'razor/csharpPullDiagnostics'; @@ -52,7 +52,7 @@ export class RazorDiagnosticHandler extends RazorLanguageFeatureBase { const virtualCSharpUri = razorDocument.csharpDocument.uri; request.textDocument.uri = UriConverter.serialize(virtualCSharpUri); const response: DocumentDiagnosticReport = await vscode.commands.executeCommand( - RoslynLanguageServer.roslynPullDiagnosticCommand, + roslynPullDiagnosticCommand, request ); diff --git a/src/razor/src/document/razorDocumentManager.ts b/src/razor/src/document/razorDocumentManager.ts index 411358873..fa3c8aceb 100644 --- a/src/razor/src/document/razorDocumentManager.ts +++ b/src/razor/src/document/razorDocumentManager.ts @@ -4,7 +4,6 @@ *--------------------------------------------------------------------------------------------*/ import * as vscode from 'vscode'; -import { RoslynLanguageServer } from '../../../lsptoolshost/roslynLanguageServer'; import { CSharpProjectedDocument } from '../csharp/csharpProjectedDocument'; import { HtmlProjectedDocument } from '../html/htmlProjectedDocument'; import { RazorLanguage } from '../razorLanguage'; @@ -17,6 +16,7 @@ import { IRazorDocumentChangeEvent } from './IRazorDocumentChangeEvent'; import { IRazorDocumentManager } from './IRazorDocumentManager'; import { RazorDocumentChangeKind } from './razorDocumentChangeKind'; import { createDocument } from './razorDocumentFactory'; +import { razorInitializeCommand } from '../../../lsptoolshost/razorCommands'; export class RazorDocumentManager implements IRazorDocumentManager { public roslynActivated = false; @@ -172,7 +172,7 @@ export class RazorDocumentManager implements IRazorDocumentManager { // don't work, which is a poor experience. This is the compromise. if (this.roslynActivated && !this.razorDocumentGenerationInitialized && this.anyRazorDocumentOpen) { this.razorDocumentGenerationInitialized = true; - vscode.commands.executeCommand(RoslynLanguageServer.razorInitializeCommand); + vscode.commands.executeCommand(razorInitializeCommand); for (const document of this.documents) { await this.ensureDocumentAndProjectedDocumentsOpen(document); } diff --git a/src/razor/src/simplify/razorSimplifyMethodHandler.ts b/src/razor/src/simplify/razorSimplifyMethodHandler.ts index 478a4547e..2c340e85c 100644 --- a/src/razor/src/simplify/razorSimplifyMethodHandler.ts +++ b/src/razor/src/simplify/razorSimplifyMethodHandler.ts @@ -13,9 +13,9 @@ import { RazorLanguageFeatureBase } from '../razorLanguageFeatureBase'; import { RazorDocumentSynchronizer } from '../document/razorDocumentSynchronizer'; import { RazorLogger } from '../razorLogger'; import { SerializableDelegatedSimplifyMethodParams } from './serializableDelegatedSimplifyMethodParams'; -import { RoslynLanguageServer } from '../../../lsptoolshost/roslynLanguageServer'; import SerializableSimplifyMethodParams from './serializableSimplifyMethodParams'; import { TextEdit } from 'vscode-html-languageservice'; +import { roslynSimplifyMethodCommand } from '../../../lsptoolshost/razorCommands'; export class RazorSimplifyMethodHandler extends RazorLanguageFeatureBase { private static readonly razorSimplifyMethodCommand = 'razor/simplifyMethod'; @@ -62,7 +62,7 @@ export class RazorSimplifyMethodHandler extends RazorLanguageFeatureBase { const params = new SerializableSimplifyMethodParams(identifier, request.textEdit); const response: TextEdit[] | undefined = await vscode.commands.executeCommand( - RoslynLanguageServer.roslynSimplifyMethodCommand, + roslynSimplifyMethodCommand, params ); diff --git a/test/integrationTests/integrationHelpers.ts b/test/integrationTests/integrationHelpers.ts index 331023dfd..ee56fb104 100644 --- a/test/integrationTests/integrationHelpers.ts +++ b/test/integrationTests/integrationHelpers.ts @@ -7,6 +7,8 @@ import * as vscode from 'vscode'; import * as path from 'path'; import { CSharpExtensionExports } from '../../src/csharpExtensionExports'; import { existsSync } from 'fs'; +import { ServerStateChange } from '../../src/lsptoolshost/serverStateChange'; +import testAssetWorkspace from './testAssets/testAssetWorkspace'; export async function activateCSharpExtension(): Promise { // Ensure the dependent extension exists - when launching via F5 launch.json we can't install the extension prior to opening vscode. @@ -15,7 +17,7 @@ export async function activateCSharpExtension(): Promise { vscode.extensions.getExtension(vscodeDotnetRuntimeExtensionId); if (!dotnetRuntimeExtension) { await vscode.commands.executeCommand('workbench.extensions.installExtension', vscodeDotnetRuntimeExtensionId); - await reloadWindow(); + await vscode.commands.executeCommand('workbench.action.reloadWindow'); } const csharpExtension = vscode.extensions.getExtension('ms-dotnettools.csharp'); @@ -23,11 +25,33 @@ export async function activateCSharpExtension(): Promise { throw new Error('Failed to find installation of ms-dotnettools.csharp'); } + // Run a restore manually to make sure the project is up to date since we don't have automatic restore. + await testAssetWorkspace.restoreLspToolsHostAsync(); + + // If the extension is already active, we need to restart it to ensure we start with a clean server state. + // For example, a previous test may have changed configs, deleted restored packages or made other changes that would put it in an invalid state. + let shouldRestart = false; + if (csharpExtension.isActive) { + shouldRestart = true; + } + // Explicitly await the extension activation even if completed so that we capture any errors it threw during activation. await csharpExtension.activate(); - await csharpExtension.exports.initializationFinished(); console.log('ms-dotnettools.csharp activated'); + + if (shouldRestart) { + // Register to wait for initialization events and restart the server. + const waitForInitialProjectLoad = new Promise((resolve, _) => { + csharpExtension.exports.experimental.languageServerEvents.onServerStateChange(async (state) => { + if (state === ServerStateChange.ProjectInitializationComplete) { + resolve(); + } + }); + }); + await vscode.commands.executeCommand('dotnet.restartServer'); + await waitForInitialProjectLoad; + } } export async function openFileInWorkspaceAsync(relativeFilePath: string): Promise { @@ -40,10 +64,6 @@ export async function openFileInWorkspaceAsync(relativeFilePath: string): Promis await vscode.commands.executeCommand('vscode.open', vscode.Uri.file(filePath)); } -export async function reloadWindow(): Promise { - await vscode.commands.executeCommand('workbench.action.reloadWindow'); -} - export function isRazorWorkspace(workspace: typeof vscode.workspace) { return isGivenSln(workspace, 'BasicRazorApp2_1'); } diff --git a/test/integrationTests/lspInlayHints.integration.test.ts b/test/integrationTests/lspInlayHints.integration.test.ts index f0c6ce0f9..ed307e14f 100644 --- a/test/integrationTests/lspInlayHints.integration.test.ts +++ b/test/integrationTests/lspInlayHints.integration.test.ts @@ -11,8 +11,7 @@ import * as integrationHelpers from './integrationHelpers'; import { InlayHint, InlayHintKind, Position } from 'vscode-languageserver-protocol'; jestLib.describe(`LSP Inlay Hints ${testAssetWorkspace.description}`, function () { - jestLib.beforeEach(async function () { - await testAssetWorkspace.restoreLspToolsHostAsync(); + jestLib.beforeAll(async function () { const editorConfig = vscode.workspace.getConfiguration('editor'); await editorConfig.update('inlayHints.enabled', true); const dotnetConfig = vscode.workspace.getConfiguration('dotnet'); @@ -35,7 +34,7 @@ jestLib.describe(`LSP Inlay Hints ${testAssetWorkspace.description}`, function ( await integrationHelpers.activateCSharpExtension(); }); - jestLib.afterEach(async () => { + jestLib.afterAll(async () => { await testAssetWorkspace.cleanupWorkspace(); }); diff --git a/test/integrationTests/unitTests.integration.test.ts b/test/integrationTests/unitTests.integration.test.ts index 61a0f56bf..c7bd2ad5b 100644 --- a/test/integrationTests/unitTests.integration.test.ts +++ b/test/integrationTests/unitTests.integration.test.ts @@ -12,11 +12,10 @@ import { TestProgress } from '../../src/lsptoolshost/roslynProtocol'; jestLib.describe(`Unit Testing ${testAssetWorkspace.description}`, function () { jestLib.beforeAll(async function () { - await testAssetWorkspace.restoreLspToolsHostAsync(); + await activateCSharpExtension(); }); jestLib.beforeEach(async function () { - await activateCSharpExtension(); const fileName = path.join('test', 'UnitTest1.cs'); await openFileInWorkspaceAsync(fileName); }); From 18779e73637efa5e40c287c0bd6dc7585619c751 Mon Sep 17 00:00:00 2001 From: David Barbet Date: Tue, 5 Sep 2023 14:48:09 -0700 Subject: [PATCH 3/4] Fix missing on autoinsert registration --- src/lsptoolshost/roslynLanguageServer.ts | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lsptoolshost/roslynLanguageServer.ts b/src/lsptoolshost/roslynLanguageServer.ts index c448bb14c..fc13aae3e 100644 --- a/src/lsptoolshost/roslynLanguageServer.ts +++ b/src/lsptoolshost/roslynLanguageServer.ts @@ -48,6 +48,7 @@ import { DotnetInfo } from '../shared/utils/dotnetInfo'; import { RoslynLanguageServerEvents } from './languageServerEvents'; import { registerShowToastNotification } from './showToastNotification'; import { registerRazorCommands } from './razorCommands'; +import { registerOnAutoInsert } from './onAutoInsert'; let _channel: vscode.OutputChannel; let _traceChannel: vscode.OutputChannel; @@ -752,6 +753,8 @@ export async function activateRoslynLanguageServer( // Register any needed debugger components that need to communicate with the language server. registerDebugger(context, languageServer, languageServerEvents, platformInfo, optionProvider, _channel); + registerOnAutoInsert(optionProvider, languageServer); + context.subscriptions.push(registerLanguageServerOptionChanges(optionObservable)); return languageServer; From f584cc31e684dec291bf10d781541c16a659202a Mon Sep 17 00:00:00 2001 From: David Barbet Date: Thu, 7 Sep 2023 14:04:31 -0700 Subject: [PATCH 4/4] Rename files based on feedback --- .../advisor.integration.test.ts | 2 +- .../codeActionRename.integration.test.ts | 2 +- .../codeLensProvider.integration.test.ts | 2 +- .../completionProvider.integration.test.ts | 2 +- .../definitionProvider.test.ts | 2 +- .../diagnostics.integration.test.ts | 2 +- ...documentSymbolProvider.integration.test.ts | 2 +- ...nCommentAutoFormatting.integration.test.ts | 2 +- .../dotnetTest.integration.test.ts | 2 +- .../hoverProvider.integration.test.ts | 2 +- .../implementationProvider.test.ts | 2 +- .../inlayHints.integration.test.ts | 2 +- .../languageMiddleware.integration.test.ts | 2 +- .../launchConfiguration.integration.test.ts | 2 +- .../reAnalyze.integration.test.ts | 2 +- .../referenceProvider.test.ts | 2 +- .../semanticTokensProvider.test.ts | 2 +- .../signatureHelp.integration.test.ts | 2 +- .../sourceGeneratorDefinitionProvider.test.ts | 2 +- .../testAssets/activeTestAssetWorkspace.ts | 30 +++++++ .../testAssets/omnisharpTestAssetWorkspace.ts | 89 +++++++++++++++---- .../testAssets/omnisharpTestAssets.ts | 83 ----------------- .../typeDefinitionProvider.test.ts | 2 +- ...virtualDocumentTracker.integration.test.ts | 2 +- ...orkspaceSymbolProvider.integration.test.ts | 2 +- 25 files changed, 123 insertions(+), 123 deletions(-) create mode 100644 omnisharptest/omnisharpIntegrationTests/testAssets/activeTestAssetWorkspace.ts delete mode 100644 omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssets.ts diff --git a/omnisharptest/omnisharpIntegrationTests/advisor.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/advisor.integration.test.ts index f82080a8d..a8845a1dc 100644 --- a/omnisharptest/omnisharpIntegrationTests/advisor.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/advisor.integration.test.ts @@ -8,7 +8,7 @@ import * as vscode from 'vscode'; import { expect, should } from 'chai'; import * as path from 'path'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { Advisor } from '../../src/features/diagnosticsProvider'; diff --git a/omnisharptest/omnisharpIntegrationTests/codeActionRename.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/codeActionRename.integration.test.ts index ca79aa97d..bb0484903 100644 --- a/omnisharptest/omnisharpIntegrationTests/codeActionRename.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/codeActionRename.integration.test.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import { should, expect } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import * as path from 'path'; import { assertWithPoll } from './poll'; import { isNotNull } from '../testUtil'; diff --git a/omnisharptest/omnisharpIntegrationTests/codeLensProvider.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/codeLensProvider.integration.test.ts index b8279cb14..3f2f0f313 100644 --- a/omnisharptest/omnisharpIntegrationTests/codeLensProvider.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/codeLensProvider.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, expect } from 'chai'; import { activateCSharpExtension, isSlnWithCsproj, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { isNotNull } from '../testUtil'; suite(`CodeLensProvider: ${testAssetWorkspace.description}`, function () { diff --git a/omnisharptest/omnisharpIntegrationTests/completionProvider.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/completionProvider.integration.test.ts index aa87becf8..246a25ae4 100644 --- a/omnisharptest/omnisharpIntegrationTests/completionProvider.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/completionProvider.integration.test.ts @@ -5,7 +5,7 @@ import OmniSharpCompletionProvider from '../../src/features/completionProvider'; import * as vscode from 'vscode'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import * as path from 'path'; import { use, expect, should } from 'chai'; import * as chaiArray from 'chai-arrays'; diff --git a/omnisharptest/omnisharpIntegrationTests/definitionProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/definitionProvider.test.ts index 1a4ad235b..6683038f7 100644 --- a/omnisharptest/omnisharpIntegrationTests/definitionProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/definitionProvider.test.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import OmniSharpDefinitionProvider from '../../src/features/definitionProvider'; import * as path from 'path'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { expect, should } from 'chai'; import { activateCSharpExtension, diff --git a/omnisharptest/omnisharpIntegrationTests/diagnostics.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/diagnostics.integration.test.ts index 4f9f796ba..d1eda9ab3 100644 --- a/omnisharptest/omnisharpIntegrationTests/diagnostics.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/diagnostics.integration.test.ts @@ -13,7 +13,7 @@ import { isSlnWithGenerator, restartOmniSharpServer, } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { poll, assertWithPoll, pollDoesNotHappen } from './poll'; import { isNotNull } from '../testUtil'; diff --git a/omnisharptest/omnisharpIntegrationTests/documentSymbolProvider.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/documentSymbolProvider.integration.test.ts index 21b644e55..eca66ae76 100644 --- a/omnisharptest/omnisharpIntegrationTests/documentSymbolProvider.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/documentSymbolProvider.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, expect } from 'chai'; import * as integrationHelpers from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; suite(`DocumentSymbolProvider: ${testAssetWorkspace.description}`, function () { let fileUri: vscode.Uri; diff --git a/omnisharptest/omnisharpIntegrationTests/documentationCommentAutoFormatting.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/documentationCommentAutoFormatting.integration.test.ts index 8cdca19ed..f5fa7a1de 100644 --- a/omnisharptest/omnisharpIntegrationTests/documentationCommentAutoFormatting.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/documentationCommentAutoFormatting.integration.test.ts @@ -8,7 +8,7 @@ import * as chaiArray from 'chai-arrays'; import * as vscode from 'vscode'; import * as path from 'path'; import { isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; use(chaiArray); diff --git a/omnisharptest/omnisharpIntegrationTests/dotnetTest.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/dotnetTest.integration.test.ts index 9fc8e66c2..dd4a76669 100644 --- a/omnisharptest/omnisharpIntegrationTests/dotnetTest.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/dotnetTest.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, expect } from 'chai'; import { activateCSharpExtension, isSlnWithCsproj } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { EventStream } from '../../src/eventStream'; import { EventType } from '../../src/omnisharp/eventType'; import { OmnisharpRequestMessage } from '../../src/omnisharp/loggingEvents'; diff --git a/omnisharptest/omnisharpIntegrationTests/hoverProvider.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/hoverProvider.integration.test.ts index 8e502cf20..1b5273e12 100644 --- a/omnisharptest/omnisharpIntegrationTests/hoverProvider.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/hoverProvider.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, expect } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; export type Test = 'a' | 'b' | ['c', any]; diff --git a/omnisharptest/omnisharpIntegrationTests/implementationProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/implementationProvider.test.ts index 5c530ccca..8582905ec 100644 --- a/omnisharptest/omnisharpIntegrationTests/implementationProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/implementationProvider.test.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import OmniSharpImplementationProvider from '../../src/features/implementationProvider'; import * as path from 'path'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { expect, should } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; diff --git a/omnisharptest/omnisharpIntegrationTests/inlayHints.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/inlayHints.integration.test.ts index 4f82217b7..c6d0023d7 100644 --- a/omnisharptest/omnisharpIntegrationTests/inlayHints.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/inlayHints.integration.test.ts @@ -12,7 +12,7 @@ import { isSlnWithGenerator, restartOmniSharpServer, } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import * as path from 'path'; import { InlayHint, LinePositionSpanTextChange } from '../../src/omnisharp/protocol'; import { isNotNull } from '../testUtil'; diff --git a/omnisharptest/omnisharpIntegrationTests/languageMiddleware.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/languageMiddleware.integration.test.ts index 680bd98fe..b5c7204ba 100644 --- a/omnisharptest/omnisharpIntegrationTests/languageMiddleware.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/languageMiddleware.integration.test.ts @@ -5,7 +5,7 @@ import * as vscode from 'vscode'; import * as path from 'path'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { expect, should } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; import { LanguageMiddleware, LanguageMiddlewareFeature } from '../../src/omnisharp/languageMiddlewareFeature'; diff --git a/omnisharptest/omnisharpIntegrationTests/launchConfiguration.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/launchConfiguration.integration.test.ts index ad45ff408..1b8249bfa 100644 --- a/omnisharptest/omnisharpIntegrationTests/launchConfiguration.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/launchConfiguration.integration.test.ts @@ -8,7 +8,7 @@ import * as vscode from 'vscode'; import { should, expect } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { poll } from './poll'; import { isNotNull } from '../testUtil'; diff --git a/omnisharptest/omnisharpIntegrationTests/reAnalyze.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/reAnalyze.integration.test.ts index 6864a69c9..e03541bad 100644 --- a/omnisharptest/omnisharpIntegrationTests/reAnalyze.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/reAnalyze.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, expect } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { poll, assertWithPoll } from './poll'; import { EventStream } from '../../src/eventStream'; import { EventType } from '../../src/omnisharp/eventType'; diff --git a/omnisharptest/omnisharpIntegrationTests/referenceProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/referenceProvider.test.ts index c8095abb7..71bc637ea 100644 --- a/omnisharptest/omnisharpIntegrationTests/referenceProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/referenceProvider.test.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import OmniSharpReferenceProvider from '../../src/features/referenceProvider'; import * as path from 'path'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { expect, should } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; diff --git a/omnisharptest/omnisharpIntegrationTests/semanticTokensProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/semanticTokensProvider.test.ts index b2e3af3a2..c8aabbb49 100644 --- a/omnisharptest/omnisharpIntegrationTests/semanticTokensProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/semanticTokensProvider.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { should, assert } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; interface ExpectedToken { startLine: number; diff --git a/omnisharptest/omnisharpIntegrationTests/signatureHelp.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/signatureHelp.integration.test.ts index a4b301277..3e16d1268 100644 --- a/omnisharptest/omnisharpIntegrationTests/signatureHelp.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/signatureHelp.integration.test.ts @@ -8,7 +8,7 @@ import * as path from 'path'; import { expect, should } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; suite(`SignatureHelp: ${testAssetWorkspace.description}`, function () { let fileUri: vscode.Uri; diff --git a/omnisharptest/omnisharpIntegrationTests/sourceGeneratorDefinitionProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/sourceGeneratorDefinitionProvider.test.ts index 1ce7441c6..4585c3df7 100644 --- a/omnisharptest/omnisharpIntegrationTests/sourceGeneratorDefinitionProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/sourceGeneratorDefinitionProvider.test.ts @@ -9,7 +9,7 @@ import * as path from 'path'; import OmniSharpDefinitionProvider from '../../src/features/definitionProvider'; import { activateCSharpExtension, isSlnWithGenerator, restartOmniSharpServer } from './integrationHelpers'; import { assertWithPoll, sleep } from './poll'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; suite(`${OmniSharpDefinitionProvider.name}: ${testAssetWorkspace.description}`, () => { let fileUri: vscode.Uri; diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/activeTestAssetWorkspace.ts b/omnisharptest/omnisharpIntegrationTests/testAssets/activeTestAssetWorkspace.ts new file mode 100644 index 000000000..2bf613dc0 --- /dev/null +++ b/omnisharptest/omnisharpIntegrationTests/testAssets/activeTestAssetWorkspace.ts @@ -0,0 +1,30 @@ +/*--------------------------------------------------------------------------------------------- + * Copyright (c) Microsoft Corporation. All rights reserved. + * Licensed under the MIT License. See License.txt in the project root for license information. + *--------------------------------------------------------------------------------------------*/ + +import * as path from 'path'; +import * as vscode from 'vscode'; + +import { ITestAssetWorkspace } from '../../../test/integrationTests/testAssets/testAssets'; + +import singleCsproj from '../../../test/integrationTests/testAssets/singleCsproj'; +import slnWithCsproj from '../../../test/integrationTests/testAssets/slnWithCsproj'; +import slnFilterWithCsproj from '../../../test/integrationTests/testAssets/slnFilterWithCsproj'; +import BasicRazorApp2_1 from '../../../test/integrationTests/testAssets/basicRazorApp21'; +import slnWithGenerator from '../../../test/integrationTests/testAssets/slnWithGenerator'; +import { OmnisharpTestAssetWorkspace } from './omnisharpTestAssetWorkspace'; + +const testAssetWorkspaces: { [x: string]: ITestAssetWorkspace } = { + singleCsproj, + slnWithCsproj, + slnFilterWithCsproj, + BasicRazorApp2_1, + slnWithGenerator, +}; + +const workspaceName = vscode.workspace.workspaceFolders![0].uri.fsPath.split(path.sep).pop(); + +const activeTestAssetWorkspace = new OmnisharpTestAssetWorkspace(testAssetWorkspaces[workspaceName!]); + +export default activeTestAssetWorkspace; diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssetWorkspace.ts b/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssetWorkspace.ts index 9d7338c49..a41fe54bf 100644 --- a/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssetWorkspace.ts +++ b/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssetWorkspace.ts @@ -3,28 +3,81 @@ * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ -import * as path from 'path'; import * as vscode from 'vscode'; +import { EventStream } from '../../../src/eventStream'; +import { EventType } from '../../../src/omnisharp/eventType'; +import { BaseEvent } from '../../../src/omnisharp/loggingEvents'; +import { poll } from '../poll'; +import { ITestAssetWorkspace, TestAssetWorkspace } from '../../../test/integrationTests/testAssets/testAssets'; +import { ActivationResult } from '../integrationHelpers'; -import { ITestAssetWorkspace } from '../../../test/integrationTests/testAssets/testAssets'; +export class OmnisharpTestAssetWorkspace extends TestAssetWorkspace { + constructor(workspace: ITestAssetWorkspace) { + super(workspace); + } -import singleCsproj from '../../../test/integrationTests/testAssets/singleCsproj'; -import slnWithCsproj from '../../../test/integrationTests/testAssets/slnWithCsproj'; -import slnFilterWithCsproj from '../../../test/integrationTests/testAssets/slnFilterWithCsproj'; -import BasicRazorApp2_1 from '../../../test/integrationTests/testAssets/basicRazorApp21'; -import slnWithGenerator from '../../../test/integrationTests/testAssets/slnWithGenerator'; -import { OmnisharpTestAssetWorkspace } from './omnisharpTestAssets'; + async restore(): Promise { + await vscode.commands.executeCommand('dotnet.restore.all'); + } -const testAssetWorkspaces: { [x: string]: ITestAssetWorkspace } = { - singleCsproj, - slnWithCsproj, - slnFilterWithCsproj, - BasicRazorApp2_1, - slnWithGenerator, -}; + async restoreAndWait(activation: ActivationResult): Promise { + await this.restore(); -const workspaceName = vscode.workspace.workspaceFolders![0].uri.fsPath.split(path.sep).pop(); + // Wait for activity to settle before proceeding + await this.waitForIdle(activation.eventStream); + } -const activeTestAssetWorkspace = new OmnisharpTestAssetWorkspace(testAssetWorkspaces[workspaceName!]); + async waitForEvent( + stream: EventStream, + captureType: EventType, + stopCondition: (e: T) => boolean = (_) => true, + timeout: number = 25 * 1000 + ): Promise { + let event: T | undefined = undefined; -export default activeTestAssetWorkspace; + const subscription = stream.subscribe((e: BaseEvent) => { + if (e.type === captureType) { + const tEvent = e; + + if (stopCondition(tEvent)) { + event = tEvent; + subscription.unsubscribe(); + } + } + }); + + await poll( + () => event, + timeout, + 500, + (e) => !!e + ); + + return event; + } + + async waitForIdle(stream: EventStream, timeout: number = 25 * 1000): Promise { + let event: BaseEvent | undefined = { type: 0 }; + + const subscription = stream.subscribe( + (e: BaseEvent) => e.type !== EventType.BackgroundDiagnosticStatus && (event = e) + ); + await poll( + () => event, + timeout, + 500, + (e) => { + if (e) { + // We're still getting real events, set the event to undefined so we can check if it changed in the next poll. + event = undefined; + return false; + } else { + // The event is still undefined (set by the last poll) which means we haven't recieved any new events - we can exit here. + return true; + } + } + ); + + subscription.unsubscribe(); + } +} diff --git a/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssets.ts b/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssets.ts deleted file mode 100644 index a41fe54bf..000000000 --- a/omnisharptest/omnisharpIntegrationTests/testAssets/omnisharpTestAssets.ts +++ /dev/null @@ -1,83 +0,0 @@ -/*--------------------------------------------------------------------------------------------- - * Copyright (c) Microsoft Corporation. All rights reserved. - * Licensed under the MIT License. See License.txt in the project root for license information. - *--------------------------------------------------------------------------------------------*/ - -import * as vscode from 'vscode'; -import { EventStream } from '../../../src/eventStream'; -import { EventType } from '../../../src/omnisharp/eventType'; -import { BaseEvent } from '../../../src/omnisharp/loggingEvents'; -import { poll } from '../poll'; -import { ITestAssetWorkspace, TestAssetWorkspace } from '../../../test/integrationTests/testAssets/testAssets'; -import { ActivationResult } from '../integrationHelpers'; - -export class OmnisharpTestAssetWorkspace extends TestAssetWorkspace { - constructor(workspace: ITestAssetWorkspace) { - super(workspace); - } - - async restore(): Promise { - await vscode.commands.executeCommand('dotnet.restore.all'); - } - - async restoreAndWait(activation: ActivationResult): Promise { - await this.restore(); - - // Wait for activity to settle before proceeding - await this.waitForIdle(activation.eventStream); - } - - async waitForEvent( - stream: EventStream, - captureType: EventType, - stopCondition: (e: T) => boolean = (_) => true, - timeout: number = 25 * 1000 - ): Promise { - let event: T | undefined = undefined; - - const subscription = stream.subscribe((e: BaseEvent) => { - if (e.type === captureType) { - const tEvent = e; - - if (stopCondition(tEvent)) { - event = tEvent; - subscription.unsubscribe(); - } - } - }); - - await poll( - () => event, - timeout, - 500, - (e) => !!e - ); - - return event; - } - - async waitForIdle(stream: EventStream, timeout: number = 25 * 1000): Promise { - let event: BaseEvent | undefined = { type: 0 }; - - const subscription = stream.subscribe( - (e: BaseEvent) => e.type !== EventType.BackgroundDiagnosticStatus && (event = e) - ); - await poll( - () => event, - timeout, - 500, - (e) => { - if (e) { - // We're still getting real events, set the event to undefined so we can check if it changed in the next poll. - event = undefined; - return false; - } else { - // The event is still undefined (set by the last poll) which means we haven't recieved any new events - we can exit here. - return true; - } - } - ); - - subscription.unsubscribe(); - } -} diff --git a/omnisharptest/omnisharpIntegrationTests/typeDefinitionProvider.test.ts b/omnisharptest/omnisharpIntegrationTests/typeDefinitionProvider.test.ts index ff3e670bc..121a67ad1 100644 --- a/omnisharptest/omnisharpIntegrationTests/typeDefinitionProvider.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/typeDefinitionProvider.test.ts @@ -6,7 +6,7 @@ import * as vscode from 'vscode'; import OmniSharpDefinitionProvider from '../../src/features/definitionProvider'; import * as path from 'path'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { expect, should } from 'chai'; import { activateCSharpExtension, diff --git a/omnisharptest/omnisharpIntegrationTests/virtualDocumentTracker.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/virtualDocumentTracker.integration.test.ts index c71dcf687..64df57f10 100644 --- a/omnisharptest/omnisharpIntegrationTests/virtualDocumentTracker.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/virtualDocumentTracker.integration.test.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import { expect, should } from 'chai'; import { activateCSharpExtension, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; import { IDisposable } from '../../src/disposable'; suite(`Virtual Document Tracking ${testAssetWorkspace.description}`, function () { diff --git a/omnisharptest/omnisharpIntegrationTests/workspaceSymbolProvider.integration.test.ts b/omnisharptest/omnisharpIntegrationTests/workspaceSymbolProvider.integration.test.ts index 43044fd90..fd14cd18c 100644 --- a/omnisharptest/omnisharpIntegrationTests/workspaceSymbolProvider.integration.test.ts +++ b/omnisharptest/omnisharpIntegrationTests/workspaceSymbolProvider.integration.test.ts @@ -7,7 +7,7 @@ import * as vscode from 'vscode'; import { expect, should } from 'chai'; import { activateCSharpExtension, isRazorWorkspace, isSlnWithGenerator } from './integrationHelpers'; -import testAssetWorkspace from './testAssets/omnisharpTestAssetWorkspace'; +import testAssetWorkspace from './testAssets/activeTestAssetWorkspace'; suite(`WorkspaceSymbolProvider: ${testAssetWorkspace.description}`, function () { suiteSetup(async function () {