Skip to content

Commit ad0fcd4

Browse files
authored
Merge pull request dotnet#68 from dibarbet/enable_diags
Enable diagnostics
2 parents e50b446 + 1efb85b commit ad0fcd4

File tree

7 files changed

+103
-26
lines changed

7 files changed

+103
-26
lines changed

src/Features/LanguageServer/Directory.Packages.props

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
<PropertyGroup>
44
<MicrosoftBuildLocatorVersion>1.5.5</MicrosoftBuildLocatorVersion>
5-
<MicrosoftCodeAnalysisVersion>4.5.0-2.22560.8</MicrosoftCodeAnalysisVersion>
5+
<MicrosoftCodeAnalysisVersion>4.5.0-2.22577.2</MicrosoftCodeAnalysisVersion>
66
<MicrosoftCodeAnalysisCSharpFeaturesVersion>$(MicrosoftCodeAnalysisVersion)</MicrosoftCodeAnalysisCSharpFeaturesVersion>
77
<MicrosoftCodeAnalysisLanguageServerProtocolVersion>$(MicrosoftCodeAnalysisVersion)</MicrosoftCodeAnalysisLanguageServerProtocolVersion>
88
<MicrosoftCodeAnalysisCSharpLanguageServerProtocolVersion>$(MicrosoftCodeAnalysisVersion)</MicrosoftCodeAnalysisCSharpLanguageServerProtocolVersion>
@@ -13,8 +13,8 @@
1313
<MicrosoftExtensionsLoggingAbstractionsVersion>6.0.2</MicrosoftExtensionsLoggingAbstractionsVersion>
1414
<MicrosoftExtensionsLoggingConsoleVersion>$(MicrosoftExtensionsLoggingVersion)</MicrosoftExtensionsLoggingConsoleVersion>
1515
<MicrosoftVisualStudioCompositionVersion>17.2.41</MicrosoftVisualStudioCompositionVersion>
16-
<MicrosoftVisualStudioLanguageServerProtocolVersion>17.4.1012</MicrosoftVisualStudioLanguageServerProtocolVersion>
16+
<MicrosoftVisualStudioLanguageServerProtocolVersion>17.5.20-preview</MicrosoftVisualStudioLanguageServerProtocolVersion>
1717
<NerdbankStreamsVersion>2.9.112</NerdbankStreamsVersion>
18-
<StreamJsonRpcVersion>2.13.21-alpha</StreamJsonRpcVersion>
18+
<StreamJsonRpcVersion>2.14.17-alpha</StreamJsonRpcVersion>
1919
</PropertyGroup>
2020
</Project>

src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/AbstractLanguageServerHostTests.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using Microsoft.CodeAnalysis.Host.Mef;
56
using Microsoft.Extensions.Logging;
67
using Microsoft.VisualStudio.Composition;
78
using Microsoft.VisualStudio.LanguageServer.Protocol;
@@ -46,7 +47,8 @@ public static async Task<TestLspServer> CreateAsync(ClientCapabilities clientCap
4647
private TestLspServer(ExportProvider exportProvider, ILogger logger)
4748
{
4849
var (clientStream, serverStream) = FullDuplexStream.CreatePair();
49-
_languageServerHost = new LanguageServerHost(serverStream, serverStream, logger, exportProvider);
50+
var hostServices = MefV1HostServices.Create(exportProvider.AsExportProvider());
51+
_languageServerHost = new LanguageServerHost(serverStream, serverStream, exportProvider, hostServices, logger);
5052

5153
_clientRpc = new JsonRpc(new HeaderDelimitedMessageHandler(clientStream, clientStream, new JsonMessageFormatter()))
5254
{

src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/ExportProviderBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public static async Task<ExportProvider> CreateExportProviderAsync()
1717
var baseDirectory = AppContext.BaseDirectory;
1818

1919
// Load any Roslyn assemblies from the extension directory
20-
var assembliesToDiscover = Directory.EnumerateFiles(baseDirectory, "Microsoft.CodeAnalysis.*.dll");
20+
var assembliesToDiscover = Directory.EnumerateFiles(baseDirectory, "Microsoft.CodeAnalysis*.dll");
2121

2222
var discovery = PartDiscovery.Combine(
2323
new AttributedPartDiscovery(Resolver.DefaultInstance, isNonPublicSupported: true), // "NuGet MEF" attributes (Microsoft.Composition)
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
// See the LICENSE file in the project root for more information.
4+
5+
using System.Collections.Immutable;
6+
using Microsoft.CodeAnalysis.Diagnostics;
7+
using Microsoft.CodeAnalysis.Host;
8+
using Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSCode.API;
9+
using Microsoft.CodeAnalysis.MSBuild;
10+
using Microsoft.Extensions.Logging;
11+
using Microsoft.VisualStudio.Composition;
12+
13+
namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace;
14+
internal class LanguageServerWorkspace : Workspace
15+
{
16+
/// <summary>
17+
/// Set of assemblies to look for host installed analyzers.
18+
/// Similar to https://github.com/dotnet/roslyn/blob/9fee6f5461baae5152c956c3c3024ca15b85feb9/src/VisualStudio/Setup/source.extension.vsixmanifest#L51
19+
/// except only include dlls applicable to VSCode.
20+
/// </summary>
21+
private static readonly ImmutableArray<string> s_hostAnalyzerDlls = ImmutableArray.Create(
22+
"Microsoft.CodeAnalysis.CSharp.dll",
23+
"Microsoft.CodeAnalysis.VisualBasic.dll",
24+
"Microsoft.CodeAnalysis.Features.dll",
25+
"Microsoft.CodeAnalysis.Workspaces.dll",
26+
"Microsoft.CodeAnalysis.CSharp.Workspaces.dll",
27+
"Microsoft.CodeAnalysis.VisualBasic.Workspaces.dll",
28+
"Microsoft.CodeAnalysis.CSharp.Features.dll",
29+
"Microsoft.CodeAnalysis.VisualBasic.Features.dll");
30+
31+
public LanguageServerWorkspace(Solution solution, HostServices host, VSCodeAnalyzerLoader vsCodeAnalyzerLoader, ILogger logger, string? workspaceKind) : base(host, workspaceKind)
32+
{
33+
SetCurrentSolution(solution);
34+
InitializeDiagnostics(vsCodeAnalyzerLoader, logger);
35+
}
36+
37+
internal static async Task<Workspace> CreateWorkspaceAsync(string solutionPath, ExportProvider exportProvider, HostServices hostServices, ILoggerFactory loggerFactory)
38+
{
39+
var logger = loggerFactory.CreateLogger(nameof(LanguageServerWorkspace));
40+
try
41+
{
42+
// This is weird. Really we don't need a workspace other than it is a useful tool to keep track of LSP changes.
43+
// But no changes should ever be applied from the LSP host (instead the client should be applying them).
44+
//
45+
// So we use the MSBuildWorkspace type to create the solution. But we can't use the MSBuild workspace itself
46+
// because it doesn't support adding analyzers to the solution (and generallly we shouldn't be calling TryApplyChanges).
47+
// Instead we just take the solution and it put in this workspace type where we can call SetCurrentSolution.
48+
//
49+
// This is all going to get refactored anyway when we do more project system stuff.
50+
using var msbuildWorkspace = MSBuildWorkspace.Create(hostServices);
51+
var solution = await msbuildWorkspace.OpenSolutionAsync(solutionPath).ConfigureAwait(false);
52+
53+
var vscodeAnalyzerLoader = exportProvider.GetExportedValue<VSCodeAnalyzerLoader>();
54+
var hostWorkspace = new LanguageServerWorkspace(solution, hostServices, vscodeAnalyzerLoader, logger, WorkspaceKind.Host);
55+
// SetCurrentSolution does raise workspace events. For now manually register until we figure out how workspaces will work.
56+
exportProvider.GetExportedValue<LspWorkspaceRegistrationService>().Register(hostWorkspace);
57+
58+
return hostWorkspace;
59+
}
60+
catch (Exception ex)
61+
{
62+
logger.LogError(ex, $"Failed to load workspace for {solutionPath}");
63+
throw;
64+
}
65+
}
66+
67+
internal void InitializeDiagnostics(VSCodeAnalyzerLoader vscodeAnalyzerLoader, ILogger logger)
68+
{
69+
var baseDirectory = AppContext.BaseDirectory;
70+
var references = new List<AnalyzerFileReference>();
71+
var analyzerLoader = VSCodeAnalyzerLoader.CreateAnalyzerAssemblyLoader();
72+
foreach (var assemblyName in s_hostAnalyzerDlls)
73+
{
74+
var path = Path.Combine(baseDirectory, assemblyName);
75+
if (!File.Exists(path))
76+
continue;
77+
78+
references.Add(new AnalyzerFileReference(path, analyzerLoader));
79+
}
80+
81+
var newSolution = this.CurrentSolution.WithAnalyzerReferences(references);
82+
SetCurrentSolution(newSolution);
83+
logger.LogDebug($"Loaded host analyzers:{Environment.NewLine}{string.Join(Environment.NewLine, references.Select(r => r.FullPath))}");
84+
85+
vscodeAnalyzerLoader.InitializeDiagnosticsServices(this);
86+
}
87+
}

src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// The .NET Foundation licenses this file to you under the MIT license.
33
// See the LICENSE file in the project root for more information.
44

5+
using Microsoft.CodeAnalysis.Host;
56
using Microsoft.CodeAnalysis.LanguageServer.Handler;
67
using Microsoft.CodeAnalysis.LanguageServer.LanguageServer;
78
using Microsoft.CommonLanguageServerProtocol.Framework;
@@ -17,7 +18,7 @@ internal sealed class LanguageServerHost
1718
private readonly ILogger _logger;
1819
private readonly AbstractLanguageServer<RequestContext> _roslynLanguageServer;
1920

20-
public LanguageServerHost(Stream inputStream, Stream outputStream, ILogger logger, ExportProvider exportProvider)
21+
public LanguageServerHost(Stream inputStream, Stream outputStream, ExportProvider exportProvider, HostServices hostServices, ILogger logger)
2122
{
2223
_logger = logger;
2324

@@ -32,7 +33,7 @@ public LanguageServerHost(Stream inputStream, Stream outputStream, ILogger logge
3233
var roslynLspFactory = exportProvider.GetExportedValue<ILanguageServerFactory>();
3334
var capabilitiesProvider = new ServerCapabilitiesProvider(exportProvider.GetExportedValue<ExperimentalCapabilitiesProvider>());
3435
var lspLogger = new HostLspLogger(logger);
35-
_roslynLanguageServer = roslynLspFactory.Create(_jsonRpc, capabilitiesProvider, WellKnownLspServerKinds.CSharpVisualBasicLspServer, lspLogger);
36+
_roslynLanguageServer = roslynLspFactory.Create(_jsonRpc, capabilitiesProvider, WellKnownLspServerKinds.CSharpVisualBasicLspServer, lspLogger, hostServices);
3637
}
3738

3839
public async Task StartAsync()

src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/WorkspaceRegistrationService.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ public override string GetHostWorkspaceKind()
2323
{
2424
// For now mark the host workspace kind as the 'main' workspace where
2525
// 'workspace/XXXX' requests go to.
26-
return WorkspaceKind.MSBuild;
26+
return WorkspaceKind.Host;
2727
}
2828
}

src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs

Lines changed: 5 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
using Microsoft.CodeAnalysis;
88
using Microsoft.CodeAnalysis.Host.Mef;
99
using Microsoft.CodeAnalysis.LanguageServer;
10+
using Microsoft.CodeAnalysis.LanguageServer.ExternalAccess.VSCode.API;
11+
using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace;
1012
using Microsoft.CodeAnalysis.MSBuild;
1113
using Microsoft.Extensions.Logging;
1214
using Microsoft.VisualStudio.Composition;
@@ -36,10 +38,10 @@
3638
MSBuildLocator.RegisterInstance(msbuildInstances.First());
3739

3840
var exportProvider = await ExportProviderBuilder.CreateExportProviderAsync();
39-
40-
using (var workspace = CreateWorkspaceAsync(solutionPath, exportProvider, logger))
41+
var hostServices = MefV1HostServices.Create(exportProvider.AsExportProvider());
42+
using (var workspace = await LanguageServerWorkspace.CreateWorkspaceAsync(solutionPath, exportProvider, hostServices, loggerFactory))
4143
{
42-
var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), logger, exportProvider);
44+
var jsonRpc = new LanguageServerHost(Console.OpenStandardInput(), Console.OpenStandardOutput(), exportProvider, hostServices, loggerFactory.CreateLogger(nameof(LanguageServerHost)));
4345

4446
await jsonRpc.StartAsync().ConfigureAwait(false);
4547
}
@@ -66,18 +68,3 @@ static string GetSolutionPath(string[] args)
6668
return args[solutionPathIndex];
6769
}
6870

69-
static async Task<Workspace> CreateWorkspaceAsync(string solutionPath, ExportProvider exportProvider, ILogger logger)
70-
{
71-
try
72-
{
73-
var msbuildWorkspace = MSBuildWorkspace.Create(MefV1HostServices.Create(exportProvider.AsExportProvider()));
74-
await msbuildWorkspace.OpenSolutionAsync(solutionPath);
75-
return msbuildWorkspace;
76-
}
77-
catch (Exception ex)
78-
{
79-
logger.LogError(ex, $"Failed to load workspace for {solutionPath}");
80-
throw;
81-
}
82-
}
83-

0 commit comments

Comments
 (0)