diff options
author | Kitson Kelly <me@kitsonkelly.com> | 2021-06-24 22:41:04 +1000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-06-24 22:41:04 +1000 |
commit | 8ed83cba7e2eeabb3af1fd65579dacd782f50644 (patch) | |
tree | 30d93dbea20fd4a20cd5dc262a069fdcb456fdb0 | |
parent | 40310eaebfaa38eff929213f2d6b912b87ad3edf (diff) |
fix(lsp): handle invalid config setting better (#11104)
Fixes #11100
Fixes #10808
-rw-r--r-- | cli/lsp/language_server.rs | 95 | ||||
-rw-r--r-- | cli/tests/integration_tests_lsp.rs | 24 | ||||
-rw-r--r-- | cli/tests/lsp/initialize_params.json | 1 | ||||
-rw-r--r-- | cli/tests/lsp/initialize_params_bad_config_option.json | 62 |
4 files changed, 144 insertions, 38 deletions
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index 3e30d2d69..6fc450b1e 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -324,6 +324,59 @@ impl Inner { Ok(navigation_tree) } + fn merge_user_tsconfig( + &mut self, + maybe_config: &Option<String>, + maybe_root_uri: &Option<Url>, + tsconfig: &mut TsConfig, + ) -> Result<(), AnyError> { + self.maybe_config_file = None; + self.maybe_config_uri = None; + if let Some(config_str) = maybe_config { + if !config_str.is_empty() { + info!("Updating TypeScript configuration from: \"{}\"", config_str); + let config_url = if let Ok(url) = Url::from_file_path(config_str) { + Ok(url) + } else if let Some(root_uri) = maybe_root_uri { + let root_path = root_uri + .to_file_path() + .map_err(|_| anyhow!("Bad root_uri: {}", root_uri))?; + let config_path = root_path.join(config_str); + Url::from_file_path(config_path).map_err(|_| { + anyhow!("Bad file path for configuration file: \"{}\"", config_str) + }) + } else { + Err(anyhow!( + "The path to the configuration file (\"{}\") is not resolvable.", + config_str + )) + }?; + info!(" Resolved configuration file: \"{}\"", config_url); + + let config_file = { + let buffer = config_url + .to_file_path() + .map_err(|_| anyhow!("Bad uri: \"{}\"", config_url))?; + let path = buffer + .to_str() + .ok_or_else(|| anyhow!("Bad uri: \"{}\"", config_url))?; + ConfigFile::read(path)? + }; + let (value, maybe_ignored_options) = + config_file.as_compiler_options()?; + tsconfig.merge(&value); + self.maybe_config_file = Some(config_file); + self.maybe_config_uri = Some(config_url); + if let Some(ignored_options) = maybe_ignored_options { + // TODO(@kitsonk) turn these into diagnostics that can be sent to the + // client + warn!("{}", ignored_options); + } + } + } + Ok(()) + } + pub(crate) fn snapshot(&self) -> LspResult<StateSnapshot> { Ok(StateSnapshot { assets: self.assets.clone(), @@ -453,44 +506,10 @@ impl Inner { } (workspace_settings.config, config.root_uri.clone()) }; - if let Some(config_str) = &maybe_config { - info!("Updating TypeScript configuration from: \"{}\"", config_str); - let config_url = if let Ok(url) = Url::from_file_path(config_str) { - Ok(url) - } else if let Some(root_uri) = &maybe_root_uri { - let root_path = root_uri - .to_file_path() - .map_err(|_| anyhow!("Bad root_uri: {}", root_uri))?; - let config_path = root_path.join(config_str); - Url::from_file_path(config_path).map_err(|_| { - anyhow!("Bad file path for configuration file: \"{}\"", config_str) - }) - } else { - Err(anyhow!( - "The path to the configuration file (\"{}\") is not resolvable.", - config_str - )) - }?; - info!(" Resolved configuration file: \"{}\"", config_url); - - let config_file = { - let buffer = config_url - .to_file_path() - .map_err(|_| anyhow!("Bad uri: \"{}\"", config_url))?; - let path = buffer - .to_str() - .ok_or_else(|| anyhow!("Bad uri: \"{}\"", config_url))?; - ConfigFile::read(path)? - }; - let (value, maybe_ignored_options) = config_file.as_compiler_options()?; - tsconfig.merge(&value); - self.maybe_config_file = Some(config_file); - self.maybe_config_uri = Some(config_url); - if let Some(ignored_options) = maybe_ignored_options { - // TODO(@kitsonk) turn these into diagnostics that can be sent to the - // client - warn!("{}", ignored_options); - } + if let Err(err) = + self.merge_user_tsconfig(&maybe_config, &maybe_root_uri, &mut tsconfig) + { + self.client.show_message(MessageType::Warning, err).await; } let _ok: bool = self .ts_server diff --git a/cli/tests/integration_tests_lsp.rs b/cli/tests/integration_tests_lsp.rs index 04c66625c..c33f6721f 100644 --- a/cli/tests/integration_tests_lsp.rs +++ b/cli/tests/integration_tests_lsp.rs @@ -172,6 +172,30 @@ fn lsp_tsconfig_types() { } #[test] +fn lsp_tsconfig_bad_config_path() { + let mut client = init("initialize_params_bad_config_option.json"); + let (method, maybe_params) = client.read_notification().unwrap(); + assert_eq!(method, "window/showMessage"); + assert_eq!(maybe_params, Some(lsp::ShowMessageParams { + typ: lsp::MessageType::Warning, + message: "The path to the configuration file (\"bad_tsconfig.json\") is not resolvable.".to_string() + })); + let diagnostics = did_open( + &mut client, + json!({ + "textDocument": { + "uri": "file:///a/file.ts", + "languageId": "typescript", + "version": 1, + "text": "console.log(Deno.args);\n" + } + }), + ); + let diagnostics = diagnostics.into_iter().flat_map(|x| x.diagnostics); + assert_eq!(diagnostics.count(), 0); +} + +#[test] fn lsp_triple_slash_types() { let mut params: lsp::InitializeParams = serde_json::from_value(load_fixture("initialize_params.json")).unwrap(); diff --git a/cli/tests/lsp/initialize_params.json b/cli/tests/lsp/initialize_params.json index 01b334cd5..f0b2d1dad 100644 --- a/cli/tests/lsp/initialize_params.json +++ b/cli/tests/lsp/initialize_params.json @@ -12,6 +12,7 @@ "references": true, "test": true }, + "config": "", "importMap": null, "lint": true, "suggest": { diff --git a/cli/tests/lsp/initialize_params_bad_config_option.json b/cli/tests/lsp/initialize_params_bad_config_option.json new file mode 100644 index 000000000..fbff31566 --- /dev/null +++ b/cli/tests/lsp/initialize_params_bad_config_option.json @@ -0,0 +1,62 @@ +{ + "processId": 0, + "clientInfo": { + "name": "test-harness", + "version": "1.0.0" + }, + "rootUri": null, + "initializationOptions": { + "enable": true, + "codeLens": { + "implementations": true, + "references": true, + "test": true + }, + "config": "bad_tsconfig.json", + "importMap": null, + "lint": true, + "suggest": { + "autoImports": true, + "completeFunctionCalls": false, + "names": true, + "paths": true, + "imports": { + "hosts": {} + } + }, + "unstable": false + }, + "capabilities": { + "textDocument": { + "codeAction": { + "codeActionLiteralSupport": { + "codeActionKind": { + "valueSet": [ + "quickfix" + ] + } + }, + "isPreferredSupport": true, + "dataSupport": true, + "resolveSupport": { + "properties": [ + "edit" + ] + } + }, + "foldingRange": { + "lineFoldingOnly": true + }, + "synchronization": { + "dynamicRegistration": true, + "willSave": true, + "willSaveWaitUntil": true, + "didSave": true + } + }, + "workspace": { + "configuration": true, + "workspaceFolders": true + } + } +} |