diff --git a/src/OmniSharp.WebAssembly/CompilerLoggerPathRemapper.cs b/src/OmniSharp.WebAssembly/CompilerLoggerPathRemapper.cs index e08475a17d..ec6d1d7212 100644 --- a/src/OmniSharp.WebAssembly/CompilerLoggerPathRemapper.cs +++ b/src/OmniSharp.WebAssembly/CompilerLoggerPathRemapper.cs @@ -1,12 +1,14 @@ using System; using System.Composition; + using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; + namespace OmniSharp.WebAssembly; [Export(typeof(IPathRemapper)), Shared] -internal class CompilerLoggerPathRemapper : IPathRemapper +public class CompilerLoggerPathRemapper : IPathRemapper { private readonly string _compilerLogBasePath; private readonly string _workspaceBasePath; @@ -24,6 +26,52 @@ public CompilerLoggerPathRemapper(IServiceProvider serviceProvider) public string Remap(string path) { - return path.Replace(_workspaceBasePath, _compilerLogBasePath); + return Remap(path, _workspaceBasePath, _compilerLogBasePath); + } + + public static string Remap(string path, string workspacePath, string compilerLogBasePath) + { + var inputPathParts = GetPathParts(path); + var workspacePathParts = GetPathParts(workspacePath); + + for (var i = 0; i < workspacePathParts.Length; i++) + { + if (i > inputPathParts.Length) + { + // input path is shorter than the base workspace path. + return path; + } + + // VSCode gives paths on windows like 'c:\workspace\file.txt' while the input path to the workspace + // will usually be uppercase drive letter. We don't know what platform we're on, so we just do a + // case insensitive comparison and hope for the best. + if (!string.Equals(workspacePathParts[i], inputPathParts[i], StringComparison.OrdinalIgnoreCase)) + { + // input path doesn't match workspace path. + return path; + } + } + + var startingIndex = workspacePathParts.Length; + + // If the input path has no more parts remaining its the same and we can just return it. + if (startingIndex > inputPathParts.Length - 1) + { + return path; + } + + var remaining = inputPathParts[workspacePathParts.Length..]; + // input path begins with workspace base path. + // combine the compilerLogBasePath with the remaining input path parts. + // Note that the compiler log could have been generated on a different platform with + // different directory separators, so use whatever it uses as thats what we need to match to in the workspace. + var directorySeparator = compilerLogBasePath.Contains(@"\") ? @"\" : @"/"; + var remapped = $"{compilerLogBasePath}{directorySeparator}{string.Join(directorySeparator, remaining)}"; + return remapped; + } + + private static string[] GetPathParts(string path) + { + return path.Split(new string[] { @"\", @"/" }, StringSplitOptions.RemoveEmptyEntries); } } diff --git a/src/OmniSharp.WebAssembly/Host.cs b/src/OmniSharp.WebAssembly/Host.cs index 7602e0dcfa..7c2aff9028 100644 --- a/src/OmniSharp.WebAssembly/Host.cs +++ b/src/OmniSharp.WebAssembly/Host.cs @@ -35,6 +35,8 @@ public static async Task InitializeAsync(byte[] compilerLogBytes, string CompilerLoggerProjectSystem.CompilerLogBytes = compilerLogBytes; var configurationResult = new ConfigurationBuilder(environment).Build((builder) => { + // Json serialization thinks backslashes in windows file paths are escapes so we need to escape them. + workspaceBasePath = workspaceBasePath.Replace(@"\", @"\\"); var jsonOptions = $@"{{ ""CompilerLogger"": {{ diff --git a/tests/WebAssembly/TestWithWebAssembly/Client/InitializationOptions.cs b/tests/WebAssembly/TestWithWebAssembly/Client/InitializationOptions.cs new file mode 100644 index 0000000000..74b8375a6c --- /dev/null +++ b/tests/WebAssembly/TestWithWebAssembly/Client/InitializationOptions.cs @@ -0,0 +1,14 @@ +using System.ComponentModel.DataAnnotations; + +using Microsoft.AspNetCore.Components.Forms; + +namespace TestWithWebAssembly.Client; + +public class InitializationOptions +{ + [Required] + public string? WorkspacePath { get; set; } + + [Required] + public IBrowserFile? CompilerLog { get; set; } +} diff --git a/tests/WebAssembly/TestWithWebAssembly/Pages/Index.razor b/tests/WebAssembly/TestWithWebAssembly/Pages/Index.razor index 0aa0349618..036198dc74 100644 --- a/tests/WebAssembly/TestWithWebAssembly/Pages/Index.razor +++ b/tests/WebAssembly/TestWithWebAssembly/Pages/Index.razor @@ -7,18 +7,36 @@ Index -

Hello, world!

+

Initialize Server

- + + + - - - + Choose compiler log
+ +
+ +
+
+ +
+
- +

Send Request

- -
+ + + + + +
+
+ +
+
+ +

Server Logs

@foreach (var line in Text) @@ -31,6 +49,8 @@ @code { + private InitializationOptions initializationOptions = new(); + private InputJsonRequest inputText = new(); public bool IsServerRunning = false; @@ -46,12 +66,19 @@ return Task.CompletedTask; } - private async Task LoadFiles(InputFileChangeEventArgs e) + private Task LoadFiles(InputFileChangeEventArgs e) + { + initializationOptions.CompilerLog = e.File; + return Task.CompletedTask; + } + + private async Task HandleValidInitializeAsync() { + _logger.LogInformation("Initializing server..."); var memoryStream = new MemoryStream(); - var stream = e.File.OpenReadStream(maxAllowedSize: 2147483648); + var stream = initializationOptions.CompilerLog!.OpenReadStream(maxAllowedSize: 2147483648); await stream.CopyToAsync(memoryStream); - var response = await OmniSharp.WebAssembly.Program.InitializeAsync(memoryStream.ToArray(), "/home/fred/git/wasm-test", new StreamReader(new MemoryStream()), new RazorLogger(this, "Output"), _loggerProvider!); + var response = await OmniSharp.WebAssembly.Program.InitializeAsync(memoryStream.ToArray(), initializationOptions.WorkspacePath!, new StreamReader(new MemoryStream()), new RazorLogger(this, "Output"), _loggerProvider!); if (response == "done") { IsServerRunning = true; @@ -59,7 +86,7 @@ new RazorLogger(this, "Result").LogInformation(response); } - private Task HandleValidSubmit() + private Task HandleSubmitRequest() { _logger.LogInformation("Submitting request"); return OmniSharp.WebAssembly.Program.InvokeRequestAsync(inputText.RequestJson!); diff --git a/tests/WebAssembly/TestWithoutWebAssembly/Program.cs b/tests/WebAssembly/TestWithoutWebAssembly/Program.cs index 926f691178..922c51bb97 100644 --- a/tests/WebAssembly/TestWithoutWebAssembly/Program.cs +++ b/tests/WebAssembly/TestWithoutWebAssembly/Program.cs @@ -1,4 +1,5 @@ using OmniSharp.Services; +using OmniSharp.WebAssembly; namespace TestWebAssemblyDriver; @@ -6,6 +7,8 @@ internal class Program { static async Task Main(string[] args) { + var result = CompilerLoggerPathRemapper.Remap(@"c:\workspace\a\b\test.txt", @"C:\workspace\", @"/home/workspace"); + var compilerLogBytes = File.ReadAllBytes(@"/home/fred/Downloads/msbuild.compilerlog"); var response = await OmniSharp.WebAssembly.Program.InitializeAsync(compilerLogBytes, "/home/fred/git/wasm-test", Console.In, new SharedTextWriter(Console.Out)); Console.WriteLine(response);