diff --git a/eng/build.ps1 b/eng/build.ps1 index 00832c7786a6b..723e276649239 100644 --- a/eng/build.ps1 +++ b/eng/build.ps1 @@ -417,8 +417,9 @@ function TestUsingRunTests() { Copy-Item -Path (Join-Path $TempDir "servicehub\logs") -Destination (Join-Path $LogDir "servicehub") -Recurse if ($lspEditor) { - Write-Host "Copying LSP logs to $LogDir" + Write-Host "Copying LSP and telemetry logs to $LogDir" Copy-Item -Path (Join-Path $TempDir "VisualStudio\LSP") -Destination (Join-Path $LogDir "LSP") -Recurse + Copy-Item -Path (Join-Path $TempDir "VSTelemetryLog") -Destination (Join-Path $LogDir "Telemetry") -Recurse } } } @@ -559,7 +560,6 @@ function Setup-IntegrationTestRun() { $env:ROSLYN_OOP64BIT = "$oop64bit" $env:ROSLYN_LSPEDITOR = "$lspEditor" - $env:LogLevel = "Verbose" } function Prepare-TempDir() { diff --git a/src/EditorFeatures/Core.Wpf/InlineRename/CommandHandlers/RenameCommandHandler_RenameHandler.cs b/src/EditorFeatures/Core.Wpf/InlineRename/CommandHandlers/RenameCommandHandler_RenameHandler.cs index ef7e6ca6347f7..dc1ab07721623 100644 --- a/src/EditorFeatures/Core.Wpf/InlineRename/CommandHandlers/RenameCommandHandler_RenameHandler.cs +++ b/src/EditorFeatures/Core.Wpf/InlineRename/CommandHandlers/RenameCommandHandler_RenameHandler.cs @@ -10,7 +10,6 @@ using Microsoft.CodeAnalysis.Editor.Shared.Extensions; using Microsoft.CodeAnalysis.Notification; using Roslyn.Utilities; -using Microsoft.CodeAnalysis.Editor.Shared.Utilities; namespace Microsoft.CodeAnalysis.Editor.Implementation.InlineRename { @@ -109,8 +108,7 @@ private static bool CanRename(RenameCommandArgs args) { return args.SubjectBuffer.TryGetWorkspace(out var workspace) && workspace.CanApplyChange(ApplyChangesKind.ChangeDocument) && - args.SubjectBuffer.SupportsRename() && - !workspace.Services.GetService().IsInLspEditorContext(); + args.SubjectBuffer.SupportsRename(); } private static void ShowErrorDialog(Workspace workspace, string message) diff --git a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs index bb585ad70d166..9a9c19a21a071 100644 --- a/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs +++ b/src/EditorFeatures/Core.Wpf/Suggestions/SuggestedActionsSource.cs @@ -178,11 +178,6 @@ public bool TryGetTelemetryId(out Guid telemetryId) return null; } - if (range.Snapshot.TextBuffer.IsInLspEditorContext()) - { - return null; - } - if (_workspaceStatusService != null) { using (operationContext?.AddScope(allowCancellation: true, description: EditorFeaturesWpfResources.Gathering_Suggestions_Waiting_for_the_solution_to_fully_load)) diff --git a/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationUtilities.cs b/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationUtilities.cs index 650ddeb2d30c9..3a3fee06b01ca 100644 --- a/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationUtilities.cs +++ b/src/EditorFeatures/Core/Implementation/Classification/SemanticClassificationUtilities.cs @@ -34,6 +34,7 @@ public static async Task ProduceTagsAsync( IClassificationService classificationService, ClassificationTypeMap typeMap) { + // Let LSP handle semantic classification when running in the LSP editor. if (spanToTag.SnapshotSpan.Snapshot.TextBuffer.IsInLspEditorContext()) { return; diff --git a/src/VisualStudio/Core/Def/Implementation/LanguageClient/AlwaysActivateInProcLanguageClient.cs b/src/VisualStudio/Core/Def/Implementation/LanguageClient/AlwaysActivateInProcLanguageClient.cs index 7adb0bbc61b1d..f5740fe280d55 100644 --- a/src/VisualStudio/Core/Def/Implementation/LanguageClient/AlwaysActivateInProcLanguageClient.cs +++ b/src/VisualStudio/Core/Def/Implementation/LanguageClient/AlwaysActivateInProcLanguageClient.cs @@ -54,7 +54,8 @@ protected internal override VSServerCapabilities GetCapabilities() var serverCapabilities = new VSServerCapabilities(); // If the LSP editor feature flag is enabled advertise support for LSP features here so they are available locally and remote. - if (Workspace.Services.GetRequiredService().IsExperimentEnabled(VisualStudioWorkspaceContextService.LspEditorFeatureFlagName)) + bool shouldUseLspEditor = Workspace.Services.GetRequiredService().IsExperimentEnabled(VisualStudioWorkspaceContextService.LspEditorFeatureFlagName); + if (shouldUseLspEditor) { serverCapabilities = _defaultCapabilitiesProvider.GetCapabilities(); } @@ -65,7 +66,10 @@ protected internal override VSServerCapabilities GetCapabilities() OpenClose = true, }; serverCapabilities.SupportsDiagnosticRequests = this.Workspace.IsPullDiagnostics(InternalDiagnosticsOptions.NormalDiagnosticMode); - serverCapabilities.DisableGoToWorkspaceSymbols = true; + + // When using the lsp editor, set this to false to allow LSP to power goto. + // Otherwise set to true to disable LSP for goto + serverCapabilities.DisableGoToWorkspaceSymbols = !shouldUseLspEditor; serverCapabilities.WorkspaceSymbolProvider = true; return serverCapabilities; diff --git a/src/VisualStudio/Core/Def/Implementation/NavigateTo/VisualStudioNavigateToItemProviderFactory.cs b/src/VisualStudio/Core/Def/Implementation/NavigateTo/VisualStudioNavigateToItemProviderFactory.cs index 7d452ce39d426..00fcd99935d09 100644 --- a/src/VisualStudio/Core/Def/Implementation/NavigateTo/VisualStudioNavigateToItemProviderFactory.cs +++ b/src/VisualStudio/Core/Def/Implementation/NavigateTo/VisualStudioNavigateToItemProviderFactory.cs @@ -5,6 +5,7 @@ using System; using System.Composition; using Microsoft.CodeAnalysis.Editor.Implementation.NavigateTo; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Shared.TestHooks; using Microsoft.VisualStudio.Language.NavigateTo.Interfaces; @@ -25,8 +26,15 @@ public VisualStudioNavigateToItemProviderFactory(VisualStudioWorkspace workspace _workspace = workspace; } - public bool TryCreateNavigateToItemProvider(IServiceProvider serviceProvider, out INavigateToItemProvider provider) + public bool TryCreateNavigateToItemProvider(IServiceProvider serviceProvider, out INavigateToItemProvider? provider) { + // Let LSP handle goto when running under the LSP editor. + if (_workspace.Services.GetRequiredService().IsInLspEditorContext()) + { + provider = null; + return false; + } + provider = new NavigateToItemProvider(_workspace, _asyncListener); return true; } diff --git a/src/VisualStudio/Core/Def/Implementation/VisualStudioSupportsFeatureService.cs b/src/VisualStudio/Core/Def/Implementation/VisualStudioSupportsFeatureService.cs index c02c80fed5a6c..909d97227a2a0 100644 --- a/src/VisualStudio/Core/Def/Implementation/VisualStudioSupportsFeatureService.cs +++ b/src/VisualStudio/Core/Def/Implementation/VisualStudioSupportsFeatureService.cs @@ -10,6 +10,8 @@ using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Editor.Shared; +using Microsoft.CodeAnalysis.Editor.Shared.Extensions; +using Microsoft.CodeAnalysis.Editor.Shared.Utilities; using Microsoft.CodeAnalysis.Host.Mef; using Microsoft.CodeAnalysis.Shared; using Microsoft.CodeAnalysis.Text; @@ -31,13 +33,38 @@ public VisualStudioTextBufferSupportsFeatureService() } public bool SupportsCodeFixes(ITextBuffer textBuffer) - => SupportsCodeFixesWorker(GetContainedDocumentId(textBuffer)); + { + // Disable code fix entry points when running under the LSP editor. + // The LSP client will handle displaying lightbulbs. + if (textBuffer.IsInLspEditorContext()) + { + return false; + } + + return SupportsCodeFixesWorker(GetContainedDocumentId(textBuffer)); + } public bool SupportsRefactorings(ITextBuffer textBuffer) - => SupportsRefactoringsWorker(GetContainedDocumentId(textBuffer)); + { + // Disable code fix entry points when running under the LSP editor. + // The LSP client will handle displaying lightbulbs. + if (textBuffer.IsInLspEditorContext()) + { + return false; + } + + return SupportsRefactoringsWorker(GetContainedDocumentId(textBuffer)); + } public bool SupportsRename(ITextBuffer textBuffer) { + // Disable rename entry points when running under the LSP editor. + // The LSP client will handle the rename request. + if (textBuffer.IsInLspEditorContext()) + { + return false; + } + var sourceTextContainer = textBuffer.AsTextContainer(); if (Workspace.TryGetWorkspace(sourceTextContainer, out var workspace)) { diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpGoToImplementation.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpGoToImplementation.cs index dfda9c909c42e..c2560749eb9ad 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpGoToImplementation.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/CSharp/CSharpGoToImplementation.cs @@ -71,7 +71,7 @@ public void GoToImplementationOpensProvisionalTabIfDocumentNotOpen() } // TODO: Enable this once the GoToDefinition tests are merged - [WpfFact, Trait(Traits.Feature, Traits.Features.GoToImplementation), Trait(Traits.Editor, Traits.Editors.LanguageServerProtocol)] + [WpfFact, Trait(Traits.Feature, Traits.Features.GoToImplementation)] public void GoToImplementationFromMetadataAsSource() { var project = new ProjectUtils.Project(ProjectName); diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/LanguageServerProtocol/LspGoToDefinition.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/LanguageServerProtocol/LspGoToDefinition.cs index 2655e230b5389..819bdcc1132a1 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/LanguageServerProtocol/LspGoToDefinition.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/LanguageServerProtocol/LspGoToDefinition.cs @@ -27,9 +27,39 @@ public LspGoToDefinition(VisualStudioInstanceFactory instanceFactory) } [WpfFact, Trait(Traits.Feature, Traits.Features.GoToDefinition), Trait(Traits.Editor, Traits.Editors.LanguageServerProtocol)] - public void GoToDefinitionLSP() + public void GoToDefinitionWithMultipleLSP() { - Assert.True(false); + SetUpEditor( +@"partial class /*Marker*/ $$PartialClass { } + +partial class PartialClass { int i = 0; }"); + + VisualStudio.Editor.GoToDefinition("Class1.cs"); + + const string programReferencesCaption = "'PartialClass' references"; + VisualStudio.Editor.WaitForActiveWindow(programReferencesCaption); + var results = VisualStudio.FindReferencesWindow.GetContents(programReferencesCaption); + + var activeWindowCaption = VisualStudio.Shell.GetActiveWindowCaption(); + Assert.Equal(expected: programReferencesCaption, actual: activeWindowCaption); + + Assert.Collection( + results, + new Action[] + { + reference => + { + Assert.Equal(expected: "partial class /*Marker*/ PartialClass { }", actual: reference.Code); + Assert.Equal(expected: 0, actual: reference.Line); + Assert.Equal(expected: 25, actual: reference.Column); + }, + reference => + { + Assert.Equal(expected: "partial class PartialClass { int i = 0; }", actual: reference.Code); + Assert.Equal(expected: 2, actual: reference.Line); + Assert.Equal(expected: 14, actual: reference.Column); + } + }); } } } diff --git a/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicGoToImplementation.cs b/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicGoToImplementation.cs index 4bf561cb763d3..99714e2fa0e90 100644 --- a/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicGoToImplementation.cs +++ b/src/VisualStudio/IntegrationTest/IntegrationTests/VisualBasic/BasicGoToImplementation.cs @@ -22,7 +22,7 @@ public BasicGoToImplementation(VisualStudioInstanceFactory instanceFactory) { } - [WpfFact, Trait(Traits.Feature, Traits.Features.GoToImplementation), Trait(Traits.Editor, Traits.Editors.LanguageServerProtocol)] + [WpfFact, Trait(Traits.Feature, Traits.Features.GoToImplementation)] public void SimpleGoToImplementation() { var project = new ProjectUtils.Project(ProjectName); diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/Editor_InProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/Editor_InProc.cs index aab0c33046b3d..3336d43532170 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/Editor_InProc.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/InProcess/Editor_InProc.cs @@ -159,12 +159,23 @@ public string GetActiveBufferName() return GetDTE().ActiveDocument.Name; } + public string GetActiveWindowName() + { + return GetDTE().ActiveWindow.Caption; + } + public void WaitForActiveView(string expectedView) { using var cts = new CancellationTokenSource(Helper.HangMitigatingTimeout); Retry(_ => GetActiveBufferName(), (actual, _) => actual == expectedView, TimeSpan.FromMilliseconds(100), cts.Token); } + public void WaitForActiveWindow(string expectedWindow) + { + using var cts = new CancellationTokenSource(Helper.HangMitigatingTimeout); + Retry(_ => GetActiveWindowName(), (actual, _) => actual == expectedWindow, TimeSpan.FromMilliseconds(100), cts.Token); + } + public void Activate() => GetDTE().ActiveDocument.Activate(); diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/Editor_OutOfProc.cs b/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/Editor_OutOfProc.cs index ab947f52b3719..085b47187fe64 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/Editor_OutOfProc.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/OutOfProcess/Editor_OutOfProc.cs @@ -255,6 +255,9 @@ public void SetUseSuggestionMode(bool value) public void WaitForActiveView(string viewName) => _editorInProc.WaitForActiveView(viewName); + public void WaitForActiveWindow(string windowName) + => _editorInProc.WaitForActiveWindow(windowName); + public string[] GetErrorTags() => _editorInProc.GetErrorTags(); diff --git a/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs b/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs index 5f7f912e949bc..8842ad8b2f4d6 100644 --- a/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs +++ b/src/VisualStudio/IntegrationTest/TestUtilities/VisualStudioInstanceFactory.cs @@ -312,6 +312,8 @@ private static Process StartNewVisualStudioProcess(string installationPath, int var vsExeFile = Path.Combine(installationPath, @"Common7\IDE\devenv.exe"); var vsRegEditExeFile = Path.Combine(installationPath, @"Common7\IDE\VsRegEdit.exe"); + var usingLspEditor = string.Equals(Environment.GetEnvironmentVariable("ROSLYN_LSPEDITOR"), "true", StringComparison.OrdinalIgnoreCase); + if (_firstLaunch) { if (majorVersion == 16) @@ -332,8 +334,9 @@ private static Process StartNewVisualStudioProcess(string installationPath, int // Disable background download UI to avoid toasts Process.Start(CreateSilentStartInfo(vsRegEditExeFile, $"set \"{installationPath}\" {Settings.Default.VsRootSuffix} HKCU \"FeatureFlags\\Setup\\BackgroundDownload\" Value dword 0")).WaitForExit(); - var lspRegistryValue = string.Equals(Environment.GetEnvironmentVariable("ROSLYN_LSPEDITOR"), "true", StringComparison.OrdinalIgnoreCase) ? "1" : "0"; + var lspRegistryValue = usingLspEditor ? "1" : "0"; Process.Start(CreateSilentStartInfo(vsRegEditExeFile, $"set \"{installationPath}\" {Settings.Default.VsRootSuffix} HKCU \"FeatureFlags\\Roslyn\\LSP\\Editor\" Value dword {lspRegistryValue}")).WaitForExit(); + Registry.SetValue(@"HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\Telemetry\Channels", "fileLogger", 1, RegistryValueKind.DWord); // Remove legacy experiment setting for controlling async completion to ensure it does not interfere. // We no longer set this value, but it could be in place from an earlier test run on the same machine. @@ -372,6 +375,12 @@ private static Process StartNewVisualStudioProcess(string installationPath, int processStartInfo.Environment.Remove("DotNetRoot"); processStartInfo.Environment.Remove("DotNetTool"); + if (usingLspEditor) + { + // When running under the LSP editor set logging to verbose to ensure LSP client logs are captured. + processStartInfo.Environment.Add("LogLevel", "Verbose"); + } + // The first element of the path in CI is a .dotnet used for the Roslyn build. Make sure to remove that. if (processStartInfo.Environment.TryGetValue("BUILD_SOURCESDIRECTORY", out var sourcesDirectory)) { diff --git a/src/VisualStudio/Setup.Dependencies/Roslyn.VisualStudio.Setup.Dependencies.csproj b/src/VisualStudio/Setup.Dependencies/Roslyn.VisualStudio.Setup.Dependencies.csproj index 6b30fd02bbd6e..06955957e73a7 100644 --- a/src/VisualStudio/Setup.Dependencies/Roslyn.VisualStudio.Setup.Dependencies.csproj +++ b/src/VisualStudio/Setup.Dependencies/Roslyn.VisualStudio.Setup.Dependencies.csproj @@ -35,6 +35,7 @@ + @@ -60,6 +61,7 @@ +