From 8299f11dfad36a9162e010245b380ba25001b15c Mon Sep 17 00:00:00 2001 From: Artem Pianykh Date: Sat, 14 Dec 2024 17:23:30 +0000 Subject: [PATCH] fix: Check for a bogus root folder in workspace/didChangeWorkspaceFolders request (#380) Sometimes, LSP clients can send bogus folders (CWD, or homedir) as part of added folders in didChangeWorkspaceFolders. Whenever this happens marksman treats the root as the real root of the project folders and recursively scans/indexes mardown documents underneath.This is problematic when such root is a homedir because it makes marksman scan too much and potentially fail. Fixes #377 Potentially, addresses #373 too --- Marksman/Folder.fs | 31 +++++++++++++++++++++++++++++++ Marksman/Folder.fsi | 1 + Marksman/Server.fs | 33 ++------------------------------- Marksman/State.fs | 6 +++++- 4 files changed, 39 insertions(+), 32 deletions(-) diff --git a/Marksman/Folder.fs b/Marksman/Folder.fs index a04e638..3a4a50a 100644 --- a/Marksman/Folder.fs +++ b/Marksman/Folder.fs @@ -249,6 +249,37 @@ module Folder = let private ignoreFiles = [ ".ignore"; ".gitignore"; ".hgignore" ] + let private isRealWorkspaceFolder (root: RootPath) : bool = + let root = RootPath.toSystem root + + if Directory.Exists(root) then + let markerFiles = [| ".marksman.toml" |] + let markerDirs = [| ".git"; ".hg"; ".svn" |] + + let hasMarkerFile () = + Array.exists (fun marker -> File.Exists(Path.Join(root, marker))) markerFiles + + let hasMarkerDir () = + Array.exists (fun marker -> Directory.Exists(Path.Join(root, marker))) markerDirs + + hasMarkerDir () || hasMarkerFile () + else + false + + // Context is in + // * https://github.com/helix-editor/helix/issues/4436 + // * https://github.com/artempyanykh/marksman/discussions/377 + let checkWorkspaceFolderWithWarn (folderId: FolderId) : bool = + if isRealWorkspaceFolder folderId.data then + true + else + logger.warn ( + Log.setMessage "Workspace folder is bogus" + >> Log.addContext "root" folderId.data + ) + + false + let isSingleFile folder = match folder.data with | SingleFile _ -> true diff --git a/Marksman/Folder.fsi b/Marksman/Folder.fsi index ec96d72..2b6c2dd 100644 --- a/Marksman/Folder.fsi +++ b/Marksman/Folder.fsi @@ -24,6 +24,7 @@ module Folder = val docs: Folder -> seq val docCount: Folder -> int + val checkWorkspaceFolderWithWarn: FolderId -> bool val tryLoad: userConfig: option -> name: string -> FolderId -> option val singleFile: doc: Doc -> config: option -> Folder diff --git a/Marksman/Server.fs b/Marksman/Server.fs index 110ec51..6b2f54a 100644 --- a/Marksman/Server.fs +++ b/Marksman/Server.fs @@ -28,41 +28,12 @@ open Newtonsoft.Json.Linq module ServerUtil = let logger = LogProvider.getLoggerByName "ServerUtil" - let private isRealWorkspaceFolder (root: RootPath) : bool = - let root = RootPath.toSystem root - - if Directory.Exists(root) then - let markerFiles = [| ".marksman.toml" |] - let markerDirs = [| ".git"; ".hg"; ".svn" |] - - let hasMarkerFile () = - Array.exists (fun marker -> File.Exists(Path.Join(root, marker))) markerFiles - - let hasMarkerDir () = - Array.exists (fun marker -> Directory.Exists(Path.Join(root, marker))) markerDirs - - hasMarkerDir () || hasMarkerFile () - else - false - - // Remove this and related logic when https://github.com/helix-editor/helix/issues/4436 is resolved. - let checkWorkspaceFolderWithWarn (folderId: FolderId) : bool = - if isRealWorkspaceFolder folderId.data then - true - else - logger.warn ( - Log.setMessage "Workspace folder is bogus" - >> Log.addContext "root" folderId.data - ) - - false - let extractWorkspaceFolders (par: InitializeParams) : Map = match par.WorkspaceFolders with | Some folders -> folders |> Array.map (fun { Name = name; Uri = uri } -> name, UriWith.mkRoot uri) - |> Array.filter (fun (_, folderId) -> checkWorkspaceFolderWithWarn folderId) + |> Array.filter (fun (_, folderId) -> Folder.checkWorkspaceFolderWithWarn folderId) |> Map.ofArray | _ -> let rootUri = @@ -75,7 +46,7 @@ module ServerUtil = // No folders are configured. The client can still add folders later using a notification. Map.empty | Some rootUri -> - if checkWorkspaceFolderWithWarn rootUri then + if Folder.checkWorkspaceFolderWithWarn rootUri then let rootName = RootPath.filename rootUri.data Map.ofList [ rootName, rootUri ] diff --git a/Marksman/State.fs b/Marksman/State.fs index f1096da..636e01c 100644 --- a/Marksman/State.fs +++ b/Marksman/State.fs @@ -180,7 +180,11 @@ module State = for f in added do let rootUri = UriWith.mkRoot f.Uri - let folder = Folder.tryLoad userConfig f.Name rootUri + let folder = + if Folder.checkWorkspaceFolderWithWarn rootUri then + Folder.tryLoad userConfig f.Name rootUri + else + None match folder with | Some folder -> yield folder