@@ -31,7 +31,9 @@ pub struct Client {
31 pub(crate) capabilities: OnceCell<lsp::ServerCapabilities>,
31 pub(crate) capabilities: OnceCell<lsp::ServerCapabilities>,
32 offset_encoding: OffsetEncoding,
32 offset_encoding: OffsetEncoding,
33 config: Option<Value>,
33 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>,
37impl Client {
39impl Client {
@@ -40,7 +42,7 @@ impl Client {
40 cmd: &str,
42 cmd: &str,
41 args: &[String],
43 args: &[String],
42 config: Option<Value>,
44 config: Option<Value>,
43− root_markers: Vec<String>,
45+ root_markers: &[String],
44 id: usize,
46 id: usize,
45 ) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
47 ) -> Result<(Self, UnboundedReceiver<(usize, Call)>, Arc<Notify>)> {
46 // Resolve path to the binary
48 // Resolve path to the binary
@@ -65,6 +67,27 @@ impl Client {
65 let (server_rx, server_tx, initialize_notify) =
67 let (server_rx, server_tx, initialize_notify) =
66 Transport::start(reader, writer, stderr, id);
68 Transport::start(reader, writer, stderr, id);
70+ let root_path = find_root(None, root_markers);
72+ let root_uri = root_path
74+ .and_then(|root| lsp::Url::from_file_path(root).ok());
76+ // TODO: support multiple workspace folders
77+ let workspace_folders = root_uri
80+ vec![lsp::WorkspaceFolder {
83+ .and_then(|segments| segments.last())
84+ .map(|basename| basename.to_string())
85+ .unwrap_or_default(),
89+ .unwrap_or_default();
68 let client = Self {
91 let client = Self {
70 _process: process,
93 _process: process,
@@ -73,7 +96,10 @@ impl Client {
73 capabilities: OnceCell::new(),
96 capabilities: OnceCell::new(),
74 offset_encoding: OffsetEncoding::Utf8,
97 offset_encoding: OffsetEncoding::Utf8,
79 Ok((client, server_rx, initialize_notify))
105 Ok((client, server_rx, initialize_notify))
@@ -117,6 +143,10 @@ impl Client {
117 self.config.as_ref()
143 self.config.as_ref()
146+ pub fn workspace_folders(&self) -> &[lsp::WorkspaceFolder] {
147+ &self.workspace_folders
120 /// Execute a RPC request on the language server.
150 /// Execute a RPC request on the language server.
121 async fn request<R: lsp::request::Request>(&self, params: R::Params) -> Result<R::Result>
151 async fn request<R: lsp::request::Request>(&self, params: R::Params) -> Result<R::Result>
@@ -234,13 +264,6 @@ impl Client {
234 // -------------------------------------------------------------------------------------------
264 // -------------------------------------------------------------------------------------------
236 pub(crate) async fn initialize(&self) -> Result<lsp::InitializeResult> {
266 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);
240− let root_uri = root_path
242− .and_then(|root| lsp::Url::from_file_path(root).ok());
244 if self.config.is_some() {
267 if self.config.is_some() {
245 log::info!("Using custom LSP config: {}", self.config.as_ref().unwrap());
268 log::info!("Using custom LSP config: {}", self.config.as_ref().unwrap());
@@ -248,10 +271,14 @@ impl Client {
248 #[allow(deprecated)]
271 #[allow(deprecated)]
249 let params = lsp::InitializeParams {
272 let params = lsp::InitializeParams {
250 process_id: Some(std::process::id()),
273 process_id: Some(std::process::id()),
274+ workspace_folders: Some(self.workspace_folders.clone()),
251 // root_path is obsolete, but some clients like pyright still use it so we specify both.
275 // root_path is obsolete, but some clients like pyright still use it so we specify both.
252 // clients will prefer _uri if possible
276 // clients will prefer _uri if possible
253− root_path: root_path.and_then(|path| path.to_str().map(|path| path.to_owned())),
280+ .and_then(|path| path.to_str().map(|path| path.to_owned())),
254− root_uri,
281+ root_uri: self.root_uri.clone(),
255 initialization_options: self.config.clone(),
282 initialization_options: self.config.clone(),
256 capabilities: lsp::ClientCapabilities {
283 capabilities: lsp::ClientCapabilities {
257 workspace: Some(lsp::WorkspaceClientCapabilities {
284 workspace: Some(lsp::WorkspaceClientCapabilities {
@@ -259,6 +286,7 @@ impl Client {
259 did_change_configuration: Some(lsp::DynamicRegistrationClientCapabilities {
286 did_change_configuration: Some(lsp::DynamicRegistrationClientCapabilities {
260 dynamic_registration: Some(false),
287 dynamic_registration: Some(false),
289+ workspace_folders: Some(true),
262 ..Default::default()
290 ..Default::default()
264 text_document: Some(lsp::TextDocumentClientCapabilities {
292 text_document: Some(lsp::TextDocumentClientCapabilities {
@@ -314,7 +342,6 @@ impl Client {
314 ..Default::default()
342 ..Default::default()
316 trace: None,
344 trace: None,
317− workspace_folders: None,
318 client_info: None,
345 client_info: None,
319 locale: None, // TODO
346 locale: None, // TODO