@@ -31,7 +31,9 @@ pub struct Client {
3131 pub(crate) capabilities: OnceCell<lsp::ServerCapabilities>,
3232 offset_encoding: OffsetEncoding,
3333 config: Option<Value>,
34− root_markers: Vec<String>,
34+ root_path: Option<std::path::PathBuf>,
35+ root_uri: Option<lsp::Url>,
36+ workspace_folders: Vec<lsp::WorkspaceFolder>,
3537}
3638
3739impl Client {
@@ -40,7 +42,7 @@ impl Client {
4042 cmd: &str,
4143 args: &[String],
4244 config: Option<Value>,
43− root_markers: Vec<String>,
45+ root_markers: &[String],
4446 id: usize,
4547 ) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
4648 // Resolve path to the binary
@@ -65,6 +67,27 @@ impl Client {
6567 let (server_rx, server_tx, initialize_notify) =
6668 Transport::start(reader, writer, stderr, id);
6769
70+ let root_path = find_root(None, root_markers);
71+
72+ let root_uri = root_path
73+ .clone()
74+ .and_then(|root| lsp::Url::from_file_path(root).ok());
75+
76+ // TODO: support multiple workspace folders
77+ let workspace_folders = root_uri
78+ .clone()
79+ .map(|root| {
80+ vec![lsp::WorkspaceFolder {
81+ name: root
82+ .path_segments()
83+ .and_then(|segments| segments.last())
84+ .map(|basename| basename.to_string())
85+ .unwrap_or_default(),
86+ uri: root,
87+ }]
88+ })
89+ .unwrap_or_default();
90+
6891 let client = Self {
6992 id,
7093 _process: process,
@@ -73,7 +96,10 @@ impl Client {
7396 capabilities: OnceCell::new(),
7497 offset_encoding: OffsetEncoding::Utf8,
7598 config,
76− root_markers,
99+
100+ root_path,
101+ root_uri,
102+ workspace_folders,
77103 };
78104
79105 Ok((client, server_rx, initialize_notify))
@@ -117,6 +143,10 @@ impl Client {
117143 self.config.as_ref()
118144 }
119145
146+ pub fn workspace_folders(&self) -> &[lsp::WorkspaceFolder] {
147+ &self.workspace_folders
148+ }
149+
120150 /// Execute a RPC request on the language server.
121151 async fn request<R: lsp::request::Request>(&self, params: R::Params) -> Result<R::Result>
122152 where
@@ -234,13 +264,6 @@ impl Client {
234264 // -------------------------------------------------------------------------------------------
235265
236266 pub(crate) async fn initialize(&self) -> Result<lsp::InitializeResult> {
237− // TODO: delay any requests that are triggered prior to initialize
238− let root_path = find_root(None, &self.root_markers);
239−
240− let root_uri = root_path
241− .clone()
242− .and_then(|root| lsp::Url::from_file_path(root).ok());
243−
244267 if self.config.is_some() {
245268 log::info!("Using custom LSP config: {}", self.config.as_ref().unwrap());
246269 }
@@ -248,10 +271,14 @@ impl Client {
248271 #[allow(deprecated)]
249272 let params = lsp::InitializeParams {
250273 process_id: Some(std::process::id()),
274+ workspace_folders: Some(self.workspace_folders.clone()),
251275 // root_path is obsolete, but some clients like pyright still use it so we specify both.
252276 // clients will prefer _uri if possible
253− root_path: root_path.and_then(|path| path.to_str().map(|path| path.to_owned())),
254− root_uri,
277+ root_path: self
278+ .root_path
279+ .clone()
280+ .and_then(|path| path.to_str().map(|path| path.to_owned())),
281+ root_uri: self.root_uri.clone(),
255282 initialization_options: self.config.clone(),
256283 capabilities: lsp::ClientCapabilities {
257284 workspace: Some(lsp::WorkspaceClientCapabilities {
@@ -259,6 +286,7 @@ impl Client {
259286 did_change_configuration: Some(lsp::DynamicRegistrationClientCapabilities {
260287 dynamic_registration: Some(false),
261288 }),
289+ workspace_folders: Some(true),
262290 ..Default::default()
263291 }),
264292 text_document: Some(lsp::TextDocumentClientCapabilities {
@@ -314,7 +342,6 @@ impl Client {
314342 ..Default::default()
315343 },
316344 trace: None,
317− workspace_folders: None,
318345 client_info: None,
319346 locale: None, // TODO
320347 };