From 3b61104e2a8984255f74827b0f1c23476ccd8209 Mon Sep 17 00:00:00 2001 From: Nayeem Rahman Date: Tue, 26 Mar 2024 15:52:20 +0000 Subject: refactor(lsp): unify config file data into ConfigTree (#23032) --- cli/lsp/tsc.rs | 121 ++++++++++++++++++++++++++------------------------------- 1 file changed, 55 insertions(+), 66 deletions(-) (limited to 'cli/lsp/tsc.rs') diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs index e88aba07b..1d7dac4e9 100644 --- a/cli/lsp/tsc.rs +++ b/cli/lsp/tsc.rs @@ -3,6 +3,7 @@ use super::analysis::CodeActionData; use super::code_lens; use super::config; +use super::config::ConfigTree; use super::documents::AssetOrDocument; use super::documents::DocumentsFilter; use super::language_server; @@ -22,7 +23,6 @@ use super::urls::INVALID_SPECIFIER; use crate::args::jsr_url; use crate::args::FmtOptionsConfig; -use crate::args::TsConfig; use crate::cache::HttpCache; use crate::lsp::cache::CacheMetadata; use crate::lsp::documents::Documents; @@ -221,6 +221,7 @@ pub struct TsServer { sender: mpsc::UnboundedSender, receiver: Mutex>>, specifier_map: Arc, + config_tree: Arc, inspector_server: Mutex>>, } @@ -238,7 +239,11 @@ impl std::fmt::Debug for TsServer { } impl TsServer { - pub fn new(performance: Arc, cache: Arc) -> Self { + pub fn new( + performance: Arc, + cache: Arc, + config_tree: Arc, + ) -> Self { let (tx, request_rx) = mpsc::unbounded_channel::(); Self { performance, @@ -246,6 +251,7 @@ impl TsServer { sender: tx, receiver: Mutex::new(Some(request_rx)), specifier_map: Arc::new(TscSpecifierMap::new()), + config_tree, inspector_server: Mutex::new(None), } } @@ -268,6 +274,7 @@ impl TsServer { let performance = self.performance.clone(); let cache = self.cache.clone(); let specifier_map = self.specifier_map.clone(); + let config_tree = self.config_tree.clone(); let _join_handle = thread::spawn(move || { run_tsc_thread( receiver, @@ -275,6 +282,7 @@ impl TsServer { cache.clone(), specifier_map.clone(), maybe_inspector_server, + config_tree, ) }); } @@ -343,18 +351,6 @@ impl TsServer { self.request(snapshot, req).await } - pub async fn configure( - &self, - snapshot: Arc, - tsconfig: TsConfig, - ) -> Result { - let req = TscRequest { - method: "$configure", - args: json!([tsconfig]), - }; - self.request(snapshot, req).await - } - pub async fn get_supported_code_fixes( &self, snapshot: Arc, @@ -3482,7 +3478,7 @@ impl CompletionEntry { { if let Ok(import_specifier) = resolve_url(&import_data.file_name) { if let Some(new_module_specifier) = language_server - .get_ts_response_import_mapper() + .get_ts_response_import_mapper(specifier) .check_specifier(&import_specifier, specifier) .or_else(|| relative_specifier(specifier, &import_specifier)) { @@ -3849,6 +3845,7 @@ struct State { response: Option, state_snapshot: Arc, specifier_map: Arc, + config_tree: Arc, token: CancellationToken, } @@ -3856,6 +3853,7 @@ impl State { fn new( state_snapshot: Arc, specifier_map: Arc, + config_tree: Arc, performance: Arc, ) -> Self { Self { @@ -3864,6 +3862,7 @@ impl State { response: None, state_snapshot, specifier_map, + config_tree, token: Default::default(), } } @@ -4077,10 +4076,20 @@ fn op_script_version( Ok(r) } +#[op2] +#[serde] +fn op_ts_config(state: &mut OpState) -> serde_json::Value { + let state = state.borrow_mut::(); + let mark = state.performance.mark("tsc.op.op_ts_config"); + let r = json!(state.config_tree.root_ts_config()); + state.performance.measure(mark); + r +} + #[op2] #[string] fn op_project_version(state: &mut OpState) -> String { - let state = state.borrow_mut::(); + let state: &mut State = state.borrow_mut::(); let mark = state.performance.mark("tsc.op.op_project_version"); let r = state.state_snapshot.documents.project_version(); state.performance.measure(mark); @@ -4093,13 +4102,19 @@ fn run_tsc_thread( cache: Arc, specifier_map: Arc, maybe_inspector_server: Option>, + config_tree: Arc, ) { let has_inspector_server = maybe_inspector_server.is_some(); // Create and setup a JsRuntime based on a snapshot. It is expected that the // supplied snapshot is an isolate that contains the TypeScript language // server. let mut tsc_runtime = JsRuntime::new(RuntimeOptions { - extensions: vec![deno_tsc::init_ops(performance, cache, specifier_map)], + extensions: vec![deno_tsc::init_ops( + performance, + cache, + specifier_map, + config_tree, + )], startup_snapshot: Some(tsc::compiler_snapshot()), inspector: maybe_inspector_server.is_some(), ..Default::default() @@ -4166,12 +4181,14 @@ deno_core::extension!(deno_tsc, op_respond, op_script_names, op_script_version, + op_ts_config, op_project_version, ], options = { performance: Arc, cache: Arc, specifier_map: Arc, + config_tree: Arc, }, state = |state, options| { state.put(State::new( @@ -4180,10 +4197,10 @@ deno_core::extension!(deno_tsc, cache_metadata: CacheMetadata::new(options.cache.clone()), config: Default::default(), documents: Documents::new(options.cache.clone()), - maybe_import_map: None, npm: None, }), options.specifier_map, + options.config_tree, options.performance, )); }, @@ -4344,9 +4361,10 @@ pub struct UserPreferences { impl UserPreferences { pub fn from_config_for_specifier( config: &config::Config, - fmt_config: &FmtOptionsConfig, specifier: &ModuleSpecifier, ) -> Self { + let fmt_options = config.tree.fmt_options_for_specifier(specifier); + let fmt_config = &fmt_options.options; let base_preferences = Self { allow_incomplete_completions: Some(true), allow_text_changes_in_new_files: Some(specifier.scheme() == "file"), @@ -4450,7 +4468,8 @@ impl UserPreferences { language_settings.preferences.use_aliases_for_renames, ), // Only use workspace settings for quote style if there's no `deno.json`. - quote_preference: if config.has_config_file() { + quote_preference: if config.tree.has_config_file_for_specifier(specifier) + { base_preferences.quote_preference } else { Some(language_settings.preferences.quote_style) @@ -4630,7 +4649,6 @@ mod tests { assets: Default::default(), cache_metadata: CacheMetadata::new(cache), config: Default::default(), - maybe_import_map: None, npm: None, } } @@ -4645,13 +4663,21 @@ mod tests { Arc::new(GlobalHttpCache::new(location.clone(), RealDenoCacheEnv)); let snapshot = Arc::new(mock_state_snapshot(sources, &location)); let performance = Arc::new(Performance::default()); - let ts_server = TsServer::new(performance, cache.clone()); + let config_tree = Arc::new(ConfigTree::default()); + config_tree + .inject_config_file( + deno_config::ConfigFile::new( + &json!({ + "compilerOptions": config, + }) + .to_string(), + resolve_url("file:///deno.json").unwrap(), + ) + .unwrap(), + ) + .await; + let ts_server = TsServer::new(performance, cache.clone(), config_tree); ts_server.start(None); - let ts_config = TsConfig::new(config); - assert!(ts_server - .configure(snapshot.clone(), ts_config,) - .await - .unwrap()); (ts_server, snapshot, cache) } @@ -4670,43 +4696,6 @@ mod tests { assert_eq!(actual, r"test [`a link`](http://deno.land/x/mod.ts) test"); } - #[tokio::test] - async fn test_project_configure() { - let temp_dir = TempDir::new(); - setup( - &temp_dir, - json!({ - "target": "esnext", - "module": "esnext", - "noEmit": true, - }), - &[], - ) - .await; - } - - #[tokio::test] - async fn test_project_reconfigure() { - let temp_dir = TempDir::new(); - let (ts_server, snapshot, _) = setup( - &temp_dir, - json!({ - "target": "esnext", - "module": "esnext", - "noEmit": true, - }), - &[], - ) - .await; - let ts_config = TsConfig::new(json!({ - "target": "esnext", - "module": "esnext", - "noEmit": true, - "lib": ["deno.ns", "deno.worker"] - })); - assert!(ts_server.configure(snapshot, ts_config).await.unwrap()); - } - #[tokio::test] async fn test_get_diagnostics() { let temp_dir = TempDir::new(); @@ -4716,6 +4705,7 @@ mod tests { "target": "esnext", "module": "esnext", "noEmit": true, + "lib": [], }), &[( "file:///a.ts", @@ -5468,11 +5458,10 @@ mod tests { .inlay_hints .variable_types .suppress_when_type_matches_name = true; - let mut config = config::Config::new(); + let mut config = config::Config::default(); config.set_workspace_settings(settings, vec![]); let user_preferences = UserPreferences::from_config_for_specifier( &config, - &Default::default(), &ModuleSpecifier::parse("file:///foo.ts").unwrap(), ); assert_eq!( -- cgit v1.2.3