From 45c97fd3ad345161498bd46c69562aee69b8be1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saulius=20Menkevi=C4=8Dius?= Date: Wed, 29 Oct 2025 09:33:33 +0200 Subject: [PATCH 1/4] chore(Initialization): Dump client info to debug log --- src/CSharpLanguageServer/Handlers/Initialization.fs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/CSharpLanguageServer/Handlers/Initialization.fs b/src/CSharpLanguageServer/Handlers/Initialization.fs index 621fa55d..01dca613 100644 --- a/src/CSharpLanguageServer/Handlers/Initialization.fs +++ b/src/CSharpLanguageServer/Handlers/Initialization.fs @@ -56,7 +56,9 @@ module Initialization = initializeMSBuild () - logger.LogDebug("handleInitialize: p.Capabilities={caps}", serialize p.Capabilities) + logger.LogDebug("handleInitialize: p.ClientInfo: {clientInfo}", p.ClientInfo |> Option.map serialize) + + logger.LogDebug("handleInitialize: p.Capabilities: {caps}", serialize p.Capabilities) context.Emit(ClientCapabilityChange p.Capabilities) // TODO use p.RootUri From 7145dce054daa50072dfc0ee5f62cab61118c527 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saulius=20Menkevi=C4=8Dius?= Date: Wed, 29 Oct 2025 09:51:15 +0200 Subject: [PATCH 2/4] chore(Util): move module Uri under CSharpLanguageServer.Util --- .../Handlers/Diagnostic.fs | 1 + .../Handlers/DocumentHighlight.fs | 1 + .../Roslyn/Conversions.fs | 23 ------------------- src/CSharpLanguageServer/Util.fs | 18 +++++++++++++++ 4 files changed, 20 insertions(+), 23 deletions(-) diff --git a/src/CSharpLanguageServer/Handlers/Diagnostic.fs b/src/CSharpLanguageServer/Handlers/Diagnostic.fs index 202a3625..ef33f4d0 100644 --- a/src/CSharpLanguageServer/Handlers/Diagnostic.fs +++ b/src/CSharpLanguageServer/Handlers/Diagnostic.fs @@ -8,6 +8,7 @@ open Ionide.LanguageServerProtocol.JsonRpc open CSharpLanguageServer.Roslyn.Conversions open CSharpLanguageServer.State open CSharpLanguageServer.Types +open CSharpLanguageServer.Util [] module Diagnostic = diff --git a/src/CSharpLanguageServer/Handlers/DocumentHighlight.fs b/src/CSharpLanguageServer/Handlers/DocumentHighlight.fs index 02a1eff6..87486b08 100644 --- a/src/CSharpLanguageServer/Handlers/DocumentHighlight.fs +++ b/src/CSharpLanguageServer/Handlers/DocumentHighlight.fs @@ -9,6 +9,7 @@ open Ionide.LanguageServerProtocol.JsonRpc open CSharpLanguageServer.State open CSharpLanguageServer.Roslyn.Conversions +open CSharpLanguageServer.Util [] module DocumentHighlight = diff --git a/src/CSharpLanguageServer/Roslyn/Conversions.fs b/src/CSharpLanguageServer/Roslyn/Conversions.fs index 87e113e7..fe61bf7d 100644 --- a/src/CSharpLanguageServer/Roslyn/Conversions.fs +++ b/src/CSharpLanguageServer/Roslyn/Conversions.fs @@ -10,29 +10,6 @@ open Ionide.LanguageServerProtocol.Types open CSharpLanguageServer.Util -module Uri = - // Unescape some necessary char before passing string to Uri. - // Can't use Uri.UnescapeDataString here. For example, if uri is "file:///z%3a/src/c%23/ProjDir" ("%3a" is - // ":" and "%23" is "#"), Uri.UnescapeDataString will unescape both "%3a" and "%23". Then Uri will think - /// "#/ProjDir" is Fragment instead of part of LocalPath. - let unescape (uri: string) = uri.Replace("%3a", ":", true, null) - - let toPath (uri: string) = - Uri.UnescapeDataString(Uri(unescape uri).LocalPath) - - let fromPath (path: string) = - let metadataPrefix = "$metadata$/" - - if path.StartsWith metadataPrefix then - "csharp:/metadata/" + path.Substring metadataPrefix.Length - else - Uri(path).ToString() - - let toWorkspaceFolder (uri: string) : WorkspaceFolder = - { Uri = uri - Name = Uri.UnescapeDataString(Uri(unescape uri).Segments |> Array.last) } - - module Position = let fromLinePosition (pos: LinePosition) : Position = { Line = uint32 pos.Line diff --git a/src/CSharpLanguageServer/Util.fs b/src/CSharpLanguageServer/Util.fs index 45b74613..5310acfa 100644 --- a/src/CSharpLanguageServer/Util.fs +++ b/src/CSharpLanguageServer/Util.fs @@ -12,6 +12,24 @@ let nonNull name (value: 'T when 'T: null) : 'T = else value +module Uri = + // Unescape some necessary char before passing string to Uri. + // Can't use Uri.UnescapeDataString here. For example, if uri is "file:///z%3a/src/c%23/ProjDir" ("%3a" is + // ":" and "%23" is "#"), Uri.UnescapeDataString will unescape both "%3a" and "%23". Then Uri will think + /// "#/ProjDir" is Fragment instead of part of LocalPath. + let unescape (uri: string) = uri.Replace("%3a", ":", true, null) + + let toPath (uri: string) = + Uri.UnescapeDataString(Uri(unescape uri).LocalPath) + + let fromPath (path: string) = + let metadataPrefix = "$metadata$/" + + if path.StartsWith metadataPrefix then + "csharp:/metadata/" + path.Substring metadataPrefix.Length + else + Uri(path).ToString() + let parseFileUri s : string = Uri(s).LocalPath let tryParseFileUri s : string option = From ebd1ae2b8ef6ca0d64b0ceca339ca893f6500a8e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saulius=20Menkevi=C4=8Dius?= Date: Wed, 29 Oct 2025 10:04:09 +0200 Subject: [PATCH 3/4] fix(Initialization): actually read InitializeParams.rootPath and .rootUri --- .../Handlers/Initialization.fs | 31 +++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/src/CSharpLanguageServer/Handlers/Initialization.fs b/src/CSharpLanguageServer/Handlers/Initialization.fs index 01dca613..c8d8c8ce 100644 --- a/src/CSharpLanguageServer/Handlers/Initialization.fs +++ b/src/CSharpLanguageServer/Handlers/Initialization.fs @@ -15,6 +15,7 @@ open CSharpLanguageServer.State.ServerState open CSharpLanguageServer.Types open CSharpLanguageServer.Logging open CSharpLanguageServer.Roslyn.Solution +open CSharpLanguageServer.Util [] @@ -61,8 +62,34 @@ module Initialization = logger.LogDebug("handleInitialize: p.Capabilities: {caps}", serialize p.Capabilities) context.Emit(ClientCapabilityChange p.Capabilities) - // TODO use p.RootUri - let rootPath = Directory.GetCurrentDirectory() + logger.LogDebug( + "handleInitialize: p.RootPath={rootPath}, p.RootUri={rootUri}, p.WorkspaceFolders={wf}", + p.RootPath, + p.RootUri, + p.WorkspaceFolders + ) + + // TODO use p.WorkspaceFolders + let rootPath, rootPathSource = + p.RootUri + |> Option.map (fun rootUri -> (Uri.toPath rootUri, "InitializeParams.rootUri")) + |> Option.orElse ( + p.RootPath + |> Option.map (fun rootPath -> (rootPath, "InitializeParams.rootPath")) + ) + |> Option.defaultValue (Directory.GetCurrentDirectory(), "Process CWD") + + do! + windowShowMessage ( + sprintf "csharp-ls: will use \"%s\" (%s) as workspace root path" rootPath rootPathSource + ) + + logger.LogDebug( + "handleInitialize: using rootPath \"{rootPath}\" from {rootPathSource}", + rootPath, + rootPathSource + ) + context.Emit(RootPathChange rootPath) // setup timer so actors get period ticks From 252227e27b3157e2883d3af4e06f1669df37dbb2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Saulius=20Menkevi=C4=8Dius?= Date: Wed, 29 Oct 2025 10:07:02 +0200 Subject: [PATCH 4/4] chore(CHANGELOG.md): update --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1e2c58f9..e12e0cc6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). ## [Unreleased] +* Actually ingest InitializeParams.rootPath and .rootUri to determine workspace root: + - By @razzmatazz in https://github.com/razzmatazz/csharp-language-server/pull/283 * Add `--diagnose` command option to run basic diagnostics interactively - By @razzmatazz in https://github.com/razzmatazz/csharp-language-server/pull/224 * Fix `textDocument/codeAction` for extracting an interface