diff --git a/Directory.Packages.props b/Directory.Packages.props
index b5f1f3c..225ecdb 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -3,7 +3,6 @@
true
true
- 17.7.2
diff --git a/dotnet-bsp.sln b/dotnet-bsp.sln
index 65d19cd..b4eb515 100644
--- a/dotnet-bsp.sln
+++ b/dotnet-bsp.sln
@@ -13,6 +13,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "dotnet-bsp", "src\bsp-serve
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bsp-server.tests", "test\bsp-server.tests.csproj", "{4EE3A425-382F-42ED-934E-6A9676533962}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bsp-client", "src\bsp-client\bsp-client.csproj", "{7F8753C3-6598-4773-96EA-6EB3463A3849}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -38,10 +40,15 @@ Global
{4EE3A425-382F-42ED-934E-6A9676533962}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4EE3A425-382F-42ED-934E-6A9676533962}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4EE3A425-382F-42ED-934E-6A9676533962}.Release|Any CPU.Build.0 = Release|Any CPU
+ {7F8753C3-6598-4773-96EA-6EB3463A3849}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {7F8753C3-6598-4773-96EA-6EB3463A3849}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {7F8753C3-6598-4773-96EA-6EB3463A3849}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {7F8753C3-6598-4773-96EA-6EB3463A3849}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4C290E5D-5CAD-42D7-B776-E581695D4E4A} = {992A1911-5B82-4DF3-9880-83E07F114A2D}
{CC0B3E75-9BE0-466E-9723-CEBA3D4A79C6} = {992A1911-5B82-4DF3-9880-83E07F114A2D}
{A88E3B50-D12B-4925-9522-E57878D2AB54} = {992A1911-5B82-4DF3-9880-83E07F114A2D}
+ {7F8753C3-6598-4773-96EA-6EB3463A3849} = {992A1911-5B82-4DF3-9880-83E07F114A2D}
EndGlobalSection
EndGlobal
diff --git a/src/bsp-client/BspConnectionDetails.cs b/src/bsp-client/BspConnectionDetails.cs
new file mode 100644
index 0000000..463afa2
--- /dev/null
+++ b/src/bsp-client/BspConnectionDetails.cs
@@ -0,0 +1,15 @@
+namespace bsp_client;
+
+public record BspConnectionDetails
+{
+ /** The name of the build tool. */
+ public required string Name { get; init; }
+ /** The version of the build tool. */
+ public required string Version { get; init; }
+ /** The bsp version of the build tool. */
+ public required string BspVersion { get; init; }
+ /** A collection of languages supported by this BSP server. */
+ public required string[] Languages { get; init; }
+ /** Command arguments runnable via system processes to start a BSP server */
+ public required string[] Argv { get; init; }
+}
\ No newline at end of file
diff --git a/test/TestHelpers/BuildServerClient.cs b/src/bsp-client/BuildServerClient.cs
similarity index 86%
rename from test/TestHelpers/BuildServerClient.cs
rename to src/bsp-client/BuildServerClient.cs
index 81cea3c..9e5318d 100644
--- a/test/TestHelpers/BuildServerClient.cs
+++ b/src/bsp-client/BuildServerClient.cs
@@ -1,13 +1,17 @@
using StreamJsonRpc;
+using System;
using System.Diagnostics;
+using System.IO;
+using System.Threading;
+using System.Threading.Tasks;
-namespace test;
+namespace bsp_client;
public sealed class BuildServerClient : IDisposable
{
private readonly JsonRpc _jsonRpc;
- public BuildServerClient(Stream sendingStream, Stream receivingStream, ServerCallbacks serverCallbacks, TraceListener? traceListener = null)
+ public BuildServerClient(Stream sendingStream, Stream receivingStream, IServerCallbacks serverCallbacks, TraceListener? traceListener = null)
{
_jsonRpc = new JsonRpc(sendingStream, receivingStream);
_jsonRpc.AddLocalRpcTarget(serverCallbacks);
diff --git a/test/TestHelpers/BuildServerClientTestExtensions.cs b/src/bsp-client/BuildServerClientExtensions.cs
similarity index 78%
rename from test/TestHelpers/BuildServerClientTestExtensions.cs
rename to src/bsp-client/BuildServerClientExtensions.cs
index a513c06..ead398e 100644
--- a/test/TestHelpers/BuildServerClientTestExtensions.cs
+++ b/src/bsp-client/BuildServerClientExtensions.cs
@@ -1,22 +1,13 @@
+using System.Threading;
+using System.Threading.Tasks;
using bsp4csharp.Protocol;
-using dotnet_bsp;
-namespace test;
+namespace bsp_client;
public static class BuildServerClientExtensions
{
- public static Task BuildInitializeAsync(this BuildServerClient client, string workspaceRootPath, CancellationToken cancellationToken)
- {
- var initParams = new InitializeBuildParams
- {
- DisplayName = "TestClient",
- Version = "1.0.0",
- BspVersion = "2.1.1",
- RootUri = UriFixer.WithFileSchema(workspaceRootPath),
- Capabilities = new BuildClientCapabilities()
- };
- initParams.Capabilities.LanguageIds.Add("csharp");
-
+ public static Task BuildInitializeAsync(this BuildServerClient client, InitializeBuildParams initParams, CancellationToken cancellationToken)
+ {
return client.SendRequestAsync(Methods.BuildInitialize, initParams, cancellationToken);
}
diff --git a/src/bsp-client/BuildServerFactory.cs b/src/bsp-client/BuildServerFactory.cs
new file mode 100644
index 0000000..230b1fe
--- /dev/null
+++ b/src/bsp-client/BuildServerFactory.cs
@@ -0,0 +1,90 @@
+using Microsoft.Extensions.Logging;
+using System;
+using System.Diagnostics;
+using System.IO;
+using System.Runtime.InteropServices;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace bsp_client;
+
+public class BuildServerFactory
+{
+ private BuildServerFactory()
+ {
+ }
+
+ public static BuildServer CreateServer(BspConnectionDetails connectionDetails, ILogger logger)
+ {
+ return new BuildServer(connectionDetails, logger);
+ }
+}
+
+public sealed class BuildServer : IDisposable
+{
+ private readonly Stream _serverStdin;
+ private readonly Stream _serverStdout;
+ private readonly Process _process;
+ private readonly ILogger _logger;
+
+ public BuildServer(BspConnectionDetails connectionDetails, ILogger logger)
+ {
+ var command = connectionDetails.Argv[0];
+ var args = connectionDetails.Argv[1..];
+ _process = new Process
+ {
+ StartInfo = new ProcessStartInfo(command, args)
+ {
+ CreateNoWindow = true,
+ RedirectStandardInput = true,
+ RedirectStandardOutput = true,
+ // RedirectStandardError = true,
+ }
+ };
+
+ _process.Start();
+
+ _serverStdin = _process.StandardInput.BaseStream;
+ _serverStdout = _process.StandardOutput.BaseStream;
+ _process.ErrorDataReceived += ErrorDataReceived;
+ _logger = logger;
+ }
+
+ private void ErrorDataReceived(object sender, DataReceivedEventArgs e)
+ {
+ _logger.LogError(e.Data);
+ }
+
+ public BuildServerClient CreateClient(
+ IServerCallbacks serverCallbacks,
+ TraceListener? traceListener = null)
+ {
+ return new BuildServerClient(_serverStdin, _serverStdout, serverCallbacks, traceListener);
+ }
+
+ public Task WaitForExitAsync(CancellationToken cancellationToken)
+ {
+ return _process.WaitForExitAsync(cancellationToken);
+ }
+
+ public int ExitCode => _process.ExitCode;
+
+ public void Dispose()
+ {
+ // var errors = _process.StandardError.ReadToEnd();
+ // _logger.LogError(errors);
+ if (!_process.HasExited)
+ {
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ _process.Kill();
+ }
+ else
+ {
+ _process.Kill(ProcessExtensions.SIGINT);
+ }
+ }
+
+ _process.Dispose();
+ }
+}
\ No newline at end of file
diff --git a/src/bsp-client/IServerCallbacks.cs b/src/bsp-client/IServerCallbacks.cs
new file mode 100644
index 0000000..9c0ac5b
--- /dev/null
+++ b/src/bsp-client/IServerCallbacks.cs
@@ -0,0 +1,28 @@
+using bsp4csharp.Protocol;
+using StreamJsonRpc;
+using System.Threading.Tasks;
+
+namespace bsp_client;
+
+public interface IServerCallbacks
+{
+ [JsonRpcMethod(Methods.BuildPublishDiagnostics, UseSingleObjectParameterDeserialization = true)]
+ public Task BuildPublishDiagnosticsRecievedAsync(PublishDiagnosticsParams publishDiagnosticsParams);
+
+ [JsonRpcMethod(Methods.BuildLogMessage, UseSingleObjectParameterDeserialization = true)]
+ public void BuildLogMessage(LogMessageParams logMessageParams);
+
+ [JsonRpcMethod(Methods.BuildTaskStart, UseSingleObjectParameterDeserialization = true)]
+ public Task BuildTaskStartAsync(TaskStartParams taskStartParams);
+
+ [JsonRpcMethod(Methods.BuildTaskProgress, UseSingleObjectParameterDeserialization = true)]
+ public Task BuildTaskProgressAsync(TaskProgressParams taskProgressParams);
+
+ [JsonRpcMethod(Methods.BuildTaskFinish, UseSingleObjectParameterDeserialization = true)]
+ public Task BuildTaskFinishAsync(TaskFinishParams taskFinishParams);
+
+ // public const string BuildShowMessage = "build/showMessage";
+ // public const string BuildTargetDidChange = "buildTarget/didChange";
+ // public const string RunPrintStdout = "run/printStdout";
+ // public const string RunPrintStderr = "run/printStderr";
+}
\ No newline at end of file
diff --git a/src/bsp-client/ProcessExtensions.cs b/src/bsp-client/ProcessExtensions.cs
new file mode 100644
index 0000000..963b5a8
--- /dev/null
+++ b/src/bsp-client/ProcessExtensions.cs
@@ -0,0 +1,17 @@
+using System.Diagnostics;
+using System.Runtime.InteropServices;
+
+namespace bsp_client;
+
+public static class ProcessExtensions
+{
+ [DllImport ("libc", SetLastError=true, EntryPoint="kill")]
+ private static extern int sys_kill (int pid, int sig);
+
+ public static int SIGINT = 2;
+
+ public static void Kill(this Process process, int sig)
+ {
+ sys_kill(process.Id, sig);
+ }
+}
\ No newline at end of file
diff --git a/src/bsp-client/bsp-client.csproj b/src/bsp-client/bsp-client.csproj
new file mode 100644
index 0000000..ff5bc2e
--- /dev/null
+++ b/src/bsp-client/bsp-client.csproj
@@ -0,0 +1,17 @@
+
+
+
+ bsp_client
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/bsp-client/packages.lock.json b/src/bsp-client/packages.lock.json
new file mode 100644
index 0000000..99e410f
--- /dev/null
+++ b/src/bsp-client/packages.lock.json
@@ -0,0 +1,156 @@
+{
+ "version": 2,
+ "dependencies": {
+ "net8.0": {
+ "Microsoft.Extensions.DependencyInjection": {
+ "type": "Direct",
+ "requested": "[10.0.5, )",
+ "resolved": "10.0.5",
+ "contentHash": "v1SVsowG6YE1YnHVGmLWz57YTRCQRx9pH5ebIESXfm5isI9gA3QaMyg/oMTzPpXYZwSAVDzYItGJKfmV+pqXkQ==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5"
+ }
+ },
+ "Microsoft.Extensions.Logging": {
+ "type": "Direct",
+ "requested": "[10.0.5, )",
+ "resolved": "10.0.5",
+ "contentHash": "+XTMKQyDWg4ODoNHU/BN3BaI1jhGO7VCS+BnzT/4IauiG6y2iPAte7MyD7rHKS+hNP0TkFkjrae8DFjDUxtcxg==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "10.0.5",
+ "Microsoft.Extensions.Logging.Abstractions": "10.0.5",
+ "Microsoft.Extensions.Options": "10.0.5"
+ }
+ },
+ "StreamJsonRpc": {
+ "type": "Direct",
+ "requested": "[2.22.23, )",
+ "resolved": "2.22.23",
+ "contentHash": "Ahq6uUFPnU9alny5h4agyX74th3PRq3NQCRNaDOqWcx20WT06mH/wENSk5IbHDc8BmfreQVEIBx5IXLBbsLFIA==",
+ "dependencies": {
+ "MessagePack": "2.5.192",
+ "Microsoft.VisualStudio.Threading.Only": "17.13.61",
+ "Microsoft.VisualStudio.Validation": "17.8.8",
+ "Nerdbank.Streams": "2.12.87",
+ "Newtonsoft.Json": "13.0.3",
+ "System.IO.Pipelines": "8.0.0"
+ }
+ },
+ "MessagePack": {
+ "type": "Transitive",
+ "resolved": "2.5.192",
+ "contentHash": "Jtle5MaFeIFkdXtxQeL9Tu2Y3HsAQGoSntOzrn6Br/jrl6c8QmG22GEioT5HBtZJR0zw0s46OnKU8ei2M3QifA==",
+ "dependencies": {
+ "MessagePack.Annotations": "2.5.192",
+ "Microsoft.NET.StringTools": "17.6.3"
+ }
+ },
+ "MessagePack.Annotations": {
+ "type": "Transitive",
+ "resolved": "2.5.192",
+ "contentHash": "jaJuwcgovWIZ8Zysdyf3b7b34/BrADw4v82GaEZymUhDd3ScMPrYd/cttekeDteJJPXseJxp04yTIcxiVUjTWg=="
+ },
+ "Microsoft.Extensions.DependencyInjection.Abstractions": {
+ "type": "Transitive",
+ "resolved": "10.0.5",
+ "contentHash": "iVMtq9eRvzyhx8949EGT0OCYJfXi737SbRVzWXE5GrOgGj5AaZ9eUuxA/BSUfmOMALKn/g8KfFaNQw0eiB3lyA=="
+ },
+ "Microsoft.Extensions.Options": {
+ "type": "Transitive",
+ "resolved": "10.0.5",
+ "contentHash": "MDaQMdUplw0AIRhWWmbLA7yQEXaLIHb+9CTroTiNS8OlI0LMXS4LCxtopqauiqGCWlRgJ+xyraVD8t6veRAFbw==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5",
+ "Microsoft.Extensions.Primitives": "10.0.5"
+ }
+ },
+ "Microsoft.Extensions.Primitives": {
+ "type": "Transitive",
+ "resolved": "10.0.5",
+ "contentHash": "/HUHJ0tw/LQvD0DZrz50eQy/3z7PfX7WWEaXnjKTV9/TNdcgFlNTZGo49QhS7PTmhDqMyHRMqAXSBxLh0vso4g=="
+ },
+ "Microsoft.VisualStudio.Threading.Only": {
+ "type": "Transitive",
+ "resolved": "17.13.61",
+ "contentHash": "vl5a2URJYCO5m+aZZtNlAXAMz28e2pUotRuoHD7RnCWOCeoyd8hWp5ZBaLNYq4iEj2oeJx5ZxiSboAjVmB20Qg==",
+ "dependencies": {
+ "Microsoft.VisualStudio.Validation": "17.8.8"
+ }
+ },
+ "Microsoft.VisualStudio.Validation": {
+ "type": "Transitive",
+ "resolved": "17.8.8",
+ "contentHash": "rWXThIpyQd4YIXghNkiv2+VLvzS+MCMKVRDR0GAMlflsdo+YcAN2g2r5U1Ah98OFjQMRexTFtXQQ2LkajxZi3g=="
+ },
+ "Nerdbank.Streams": {
+ "type": "Transitive",
+ "resolved": "2.12.87",
+ "contentHash": "oDKOeKZ865I5X8qmU3IXMyrAnssYEiYWTobPGdrqubN3RtTzEHIv+D6fwhdcfrdhPJzHjCkK/ORztR/IsnmA6g==",
+ "dependencies": {
+ "Microsoft.VisualStudio.Threading.Only": "17.13.61",
+ "Microsoft.VisualStudio.Validation": "17.8.8",
+ "System.IO.Pipelines": "8.0.0"
+ }
+ },
+ "Newtonsoft.Json": {
+ "type": "Transitive",
+ "resolved": "13.0.3",
+ "contentHash": "HrC5BXdl00IP9zeV+0Z848QWPAoCr9P3bDEZguI+gkLcBKAOxix/tLEAAHC+UvDNPv4a2d18lOReHMOagPa+zQ=="
+ },
+ "System.Diagnostics.DiagnosticSource": {
+ "type": "Transitive",
+ "resolved": "10.0.5",
+ "contentHash": "CCbzHQ26L3jskdwHh+4bxxW84lUMIrAAmeSlpO69AlrQV0DKbj1/I+feLaLSuZeqXPr9UlSy0OcgZoXOk2a6/g=="
+ },
+ "System.IO.Pipelines": {
+ "type": "Transitive",
+ "resolved": "8.0.0",
+ "contentHash": "FHNOatmUq0sqJOkTx+UF/9YK1f180cnW5FVqnQMvYUN0elp6wFzbtPSiqbo1/ru8ICp43JM1i7kKkk6GsNGHlA=="
+ },
+ "System.Memory": {
+ "type": "Transitive",
+ "resolved": "4.6.0",
+ "contentHash": "OEkbBQoklHngJ8UD8ez2AERSk2g+/qpAaSWWCBFbpH727HxDq5ydVkuncBaKcKfwRqXGWx64dS6G1SUScMsitg=="
+ },
+ "System.Runtime.CompilerServices.Unsafe": {
+ "type": "Transitive",
+ "resolved": "6.1.0",
+ "contentHash": "5o/HZxx6RVqYlhKSq8/zronDkALJZUT2Vz0hx43f0gwe8mwlM0y2nYlqdBwLMzr262Bwvpikeb/yEwkAa5PADg=="
+ },
+ "bp": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "[10.0.5, )",
+ "Microsoft.Extensions.Logging": "[10.0.5, )",
+ "StreamJsonRpc": "[2.22.23, )"
+ }
+ },
+ "bsp4csharp": {
+ "type": "Project",
+ "dependencies": {
+ "bp": "[1.0.0, )"
+ }
+ },
+ "Microsoft.Extensions.Logging.Abstractions": {
+ "type": "CentralTransitive",
+ "requested": "[10.0.5, )",
+ "resolved": "10.0.5",
+ "contentHash": "9HOdqlDtPptVcmKAjsQ/Nr5Rxfq6FMYLdhvZh1lVmeKR738qeYecQD7+ldooXf+u2KzzR1kafSphWngIM3C6ug==",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection.Abstractions": "10.0.5",
+ "System.Diagnostics.DiagnosticSource": "10.0.5"
+ }
+ },
+ "Microsoft.NET.StringTools": {
+ "type": "CentralTransitive",
+ "requested": "[18.0.2, )",
+ "resolved": "18.0.2",
+ "contentHash": "cTZw3GHkAlqZACYGeQT3niS3UfVQ8CH0O5+zUdhxstrg1Z8Q2ViXYFKjSxHmEXTX85mrOT/QnHZOeQhhSsIrkQ==",
+ "dependencies": {
+ "System.Memory": "4.6.0",
+ "System.Runtime.CompilerServices.Unsafe": "6.1.0"
+ }
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/bsp-server/Logging/MSBuildLogger.cs b/src/bsp-server/Logging/MSBuildLogger.cs
index b22b793..a28bfbc 100644
--- a/src/bsp-server/Logging/MSBuildLogger.cs
+++ b/src/bsp-server/Logging/MSBuildLogger.cs
@@ -1,7 +1,6 @@
using BaseProtocol;
using bsp4csharp.Protocol;
using Microsoft.Build.Framework;
-using Newtonsoft.Json;
using Methods = bsp4csharp.Protocol.Methods;
namespace dotnet_bsp.Logging;
@@ -24,7 +23,7 @@ internal class MSBuildLogger(IBaseProtocolClientManager baseProtocolClientManage
public LoggerVerbosity Verbosity { get; set; } = LoggerVerbosity.Normal;
- public string Parameters { get; set; } = string.Empty;
+ public string? Parameters { get; set; } = string.Empty;
public void Initialize(IEventSource eventSource)
{
@@ -41,10 +40,7 @@ public void Initialize(IEventSource eventSource)
private void TargetStarted(object sender, TargetStartedEventArgs e)
{
- if (_buildStartTimestamp == null)
- {
- _buildStartTimestamp = _timeProvider.GetUtcNow();
- }
+ _buildStartTimestamp = _timeProvider.GetUtcNow();
if (_targetsOfInterest.Contains(e.TargetName, StringComparer.InvariantCultureIgnoreCase))
{
diff --git a/src/bsp4csharp/Protocol/BuildClientCapabilities.cs b/src/bsp4csharp/Protocol/BuildClientCapabilities.cs
index ac346e1..8518d05 100644
--- a/src/bsp4csharp/Protocol/BuildClientCapabilities.cs
+++ b/src/bsp4csharp/Protocol/BuildClientCapabilities.cs
@@ -12,5 +12,5 @@ public class BuildClientCapabilities
/// languages than those that appear in this list.
///
[DataMember(Name = "languageIds")]
- public ICollection LanguageIds { get; } = new List();
+ public ICollection LanguageIds { get; init; } = new List();
}
\ No newline at end of file
diff --git a/test/BuildServerProtocolTests.cs b/test/BuildServerProtocolTests.cs
index d5261c2..f689d80 100644
--- a/test/BuildServerProtocolTests.cs
+++ b/test/BuildServerProtocolTests.cs
@@ -1,6 +1,7 @@
using bsp4csharp.Protocol;
using dotnet_bsp;
using Xunit.Abstractions;
+using bsp_client;
namespace test;
@@ -32,7 +33,8 @@ public Task InitializeAsync()
public async Task RequestWorkspaceBuildTargets_AfterInitialize_Success()
{
// Arrange
- _ = await _client.BuildInitializeAsync(TestProjectPath.AspnetWithoutErrors, _cancellationToken);
+ var initParams = TestData.GetInitParams(TestProjectPath.AspnetWithoutErrors);
+ _ = await _client.BuildInitializeAsync(initParams, _cancellationToken);
await _client.BuildInitializedAsync();
// Act
@@ -68,7 +70,8 @@ public async Task RequestWorkspaceBuildTargets_AfterInitialize_Success()
public async Task RequestBuildTargetCompile_ForProjectWithErrors_Success(string testProjectName, string expectedDiagnosticCode, string expectedDiagnosticMessage, int expectedDiagnosticsCount)
{
// Arrange
- _ = await _client.BuildInitializeAsync(TestProjectPath.GetFullPathFor(testProjectName), _cancellationToken);
+ var initParams = TestData.GetInitParams(TestProjectPath.GetFullPathFor(testProjectName));
+ _ = await _client.BuildInitializeAsync(initParams, _cancellationToken);
await _client.BuildInitializedAsync();
var buildTargets = await _client.WorkspaceBuildTargetsAsync(_cancellationToken);
diff --git a/test/InitializeAndInitializedTests.cs b/test/InitializeAndInitializedTests.cs
index 05f93c5..061afc2 100644
--- a/test/InitializeAndInitializedTests.cs
+++ b/test/InitializeAndInitializedTests.cs
@@ -1,5 +1,6 @@
using StreamJsonRpc;
using Xunit.Abstractions;
+using bsp_client;
namespace test;
@@ -32,7 +33,8 @@ public async Task RequestInitializeBuild_Success()
// Arrange
// Act
- var initResult = await _client.BuildInitializeAsync(TestProjectPath.AspnetWithoutErrors, _cancellationToken);
+ var initParams = TestData.GetInitParams(TestProjectPath.AspnetWithoutErrors);
+ var initResult = await _client.BuildInitializeAsync(initParams, _cancellationToken);
// Assert
Assert.Equal("dotnet-bsp", initResult.DisplayName);
@@ -69,7 +71,8 @@ public async Task Requests_BeforeInitializeBuildRequest_ShouldFail()
public async Task Requests_BeforeInitializedBuildNotification_ShouldFail()
{
// Arrange
- _ = await _client.BuildInitializeAsync(TestProjectPath.AspnetWithoutErrors, _cancellationToken);
+ var initParams = TestData.GetInitParams(TestProjectPath.AspnetWithoutErrors);
+ _ = await _client.BuildInitializeAsync(initParams, _cancellationToken);
// Act
var act = () => _client.WorkspaceBuildTargetsAsync(_cancellationToken);
diff --git a/test/ShutdownAndExitTests.cs b/test/ShutdownAndExitTests.cs
index b6a9915..a1f560d 100644
--- a/test/ShutdownAndExitTests.cs
+++ b/test/ShutdownAndExitTests.cs
@@ -1,4 +1,5 @@
using Xunit.Abstractions;
+using bsp_client;
namespace test;
@@ -18,7 +19,8 @@ public async Task RequestToExit_WithShutdownRequestedBefore_SuccessWithExitCodeZ
cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(3));
var cancellationToken = cancellationTokenSource.Token;
- _ = await client.BuildInitializeAsync(TestProjectPath.AspnetWithoutErrors, cancellationToken);
+ var initParams = TestData.GetInitParams(TestProjectPath.AspnetWithoutErrors);
+ _ = await client.BuildInitializeAsync(initParams, cancellationToken);
await client.BuildInitializedAsync();
await client.ShutdownAsync();
@@ -44,7 +46,8 @@ public async Task RequestToExit_WithoutShutdownFirst_FailWithExitCodeOne()
cancellationTokenSource.CancelAfter(TimeSpan.FromSeconds(3));
var cancellationToken = cancellationTokenSource.Token;
- _ = await client.BuildInitializeAsync(TestProjectPath.AspnetWithoutErrors, cancellationToken);
+ var initParams = TestData.GetInitParams(TestProjectPath.AspnetWithoutErrors);
+ _ = await client.BuildInitializeAsync(initParams, cancellationToken);
await client.BuildInitializedAsync();
// Act
diff --git a/test/TestHelpers/BuildServerFactory.cs b/test/TestHelpers/BuildServerFactory.cs
index f6dd9a4..44e8591 100644
--- a/test/TestHelpers/BuildServerFactory.cs
+++ b/test/TestHelpers/BuildServerFactory.cs
@@ -1,7 +1,7 @@
-using dotnet_bsp;
using Microsoft.Extensions.Logging;
using System.Diagnostics;
using System.Runtime.InteropServices;
+using bsp_client;
namespace test;
@@ -58,7 +58,7 @@ private void ErrorDataReceived(object sender, DataReceivedEventArgs e)
_logger.LogError(e.Data);
}
- public BuildServerClient CreateClient(ServerCallbacks serverCallbacks, TraceListener? traceListener = null)
+ public BuildServerClient CreateClient(IServerCallbacks serverCallbacks, TraceListener? traceListener = null)
{
return new BuildServerClient(_serverStdin, _serverStdout, serverCallbacks, traceListener);
}
diff --git a/test/TestHelpers/ServerCallbacks.cs b/test/TestHelpers/ServerCallbacks.cs
index 9eff0d0..f715d28 100644
--- a/test/TestHelpers/ServerCallbacks.cs
+++ b/test/TestHelpers/ServerCallbacks.cs
@@ -2,10 +2,11 @@
using StreamJsonRpc;
using Xunit.Abstractions;
using Microsoft.Extensions.Logging;
+using bsp_client;
namespace test;
-public class ServerCallbacks(ITestOutputHelper testOutputHelper, LogLevel logLevel = LogLevel.Warning)
+public class ServerCallbacks(ITestOutputHelper testOutputHelper, LogLevel logLevel = LogLevel.Warning) : IServerCallbacks
{
private readonly List _diagnosticsCollection = [];
public IReadOnlyCollection Diagnostics => _diagnosticsCollection.AsReadOnly();
diff --git a/test/TestHelpers/TestProjectPath.cs b/test/TestHelpers/TestProjectPath.cs
index 18d4fed..cb5ac8e 100644
--- a/test/TestHelpers/TestProjectPath.cs
+++ b/test/TestHelpers/TestProjectPath.cs
@@ -1,5 +1,7 @@
-namespace test;
+using bsp4csharp.Protocol;
+using dotnet_bsp;
+namespace test;
public static class TestProject
{
@@ -12,6 +14,24 @@ public static class TestProject
public const string MsTestSlnTests = "mstest-sln-tests";
}
+internal static class TestData
+{
+ internal static InitializeBuildParams GetInitParams(string workspaceRootPath)
+ {
+ return new InitializeBuildParams
+ {
+ DisplayName = "TestClient",
+ Version = "1.0.0",
+ BspVersion = "2.1.1",
+ RootUri = UriFixer.WithFileSchema(workspaceRootPath),
+ Capabilities = new BuildClientCapabilities
+ {
+ LanguageIds = ["csharp"]
+ }
+ };
+ }
+}
+
internal static class TestProjectPath
{
private static readonly string TestProjectDir = Path.GetFullPath(AppContext.BaseDirectory + "../../../../test-projects");
diff --git a/test/TestHelpers/UriFixer.cs b/test/TestHelpers/UriFixer.cs
new file mode 100644
index 0000000..58dd5da
--- /dev/null
+++ b/test/TestHelpers/UriFixer.cs
@@ -0,0 +1,10 @@
+namespace test;
+
+public static class UriFixer
+{
+ public static Uri WithFileSchema(string filePath)
+ {
+ // workaround for "file://" schema being not serialized: https://github.com/dotnet/runtime/issues/90140
+ return new Uri($"file://{filePath}", UriKind.Absolute);
+ }
+}
\ No newline at end of file
diff --git a/test/TestsRelatedEndpointsTests.cs b/test/TestsRelatedEndpointsTests.cs
index 2c1f245..fe4d3de 100644
--- a/test/TestsRelatedEndpointsTests.cs
+++ b/test/TestsRelatedEndpointsTests.cs
@@ -3,6 +3,7 @@
using dotnet_bsp.Handlers;
using Newtonsoft.Json.Linq;
using Xunit.Abstractions;
+using bsp_client;
namespace test;
@@ -149,7 +150,8 @@ public async Task RequestBuildTargetTestCaseDiscovery_ForFramework_Success(strin
CleanupOutputDirectories(testProjectPath);
- _ = await _client.BuildInitializeAsync(testProjectPath, _cancellationToken);
+ var initParams = TestData.GetInitParams(testProjectPath);
+ _ = await _client.BuildInitializeAsync(initParams, _cancellationToken);
await _client.BuildInitializedAsync();
var buildTargets = await _client.WorkspaceBuildTargetsAsync(_cancellationToken);
@@ -356,7 +358,8 @@ public async Task RequestBuildTargetTest_ForTestableBuildTarget_Success(
CleanupOutputDirectories(testProjectPath);
- _ = await _client.BuildInitializeAsync(testProjectPath, _cancellationToken);
+ var initParams = TestData.GetInitParams(testProjectPath);
+ _ = await _client.BuildInitializeAsync(initParams, _cancellationToken);
await _client.BuildInitializedAsync();
// Act
diff --git a/test/bsp-server.tests.csproj b/test/bsp-server.tests.csproj
index 055a8c1..c61eb0f 100644
--- a/test/bsp-server.tests.csproj
+++ b/test/bsp-server.tests.csproj
@@ -24,6 +24,7 @@
+
diff --git a/test/packages.lock.json b/test/packages.lock.json
index fd949ce..b54130e 100644
--- a/test/packages.lock.json
+++ b/test/packages.lock.json
@@ -282,6 +282,15 @@
"StreamJsonRpc": "[2.22.23, )"
}
},
+ "bsp-client": {
+ "type": "Project",
+ "dependencies": {
+ "Microsoft.Extensions.DependencyInjection": "[10.0.5, )",
+ "Microsoft.Extensions.Logging": "[10.0.5, )",
+ "StreamJsonRpc": "[2.22.23, )",
+ "bsp4csharp": "[1.0.0, )"
+ }
+ },
"bsp4csharp": {
"type": "Project",
"dependencies": {