diff options
Diffstat (limited to 'cli/lsp')
-rw-r--r-- | cli/lsp/cache.rs | 7 | ||||
-rw-r--r-- | cli/lsp/diagnostics.rs | 15 | ||||
-rw-r--r-- | cli/lsp/documents.rs | 149 | ||||
-rw-r--r-- | cli/lsp/language_server.rs | 50 |
4 files changed, 92 insertions, 129 deletions
diff --git a/cli/lsp/cache.rs b/cli/lsp/cache.rs index e21bcff2d..b05dcbc38 100644 --- a/cli/lsp/cache.rs +++ b/cli/lsp/cache.rs @@ -21,7 +21,10 @@ use std::thread; use tokio::sync::mpsc; use tokio::sync::oneshot; -type Request = (Vec<ModuleSpecifier>, oneshot::Sender<Result<(), AnyError>>); +type Request = ( + Vec<(ModuleSpecifier, deno_graph::ModuleKind)>, + oneshot::Sender<Result<(), AnyError>>, +); /// A "server" that handles requests from the language server to cache modules /// in its own thread. @@ -105,7 +108,7 @@ impl CacheServer { /// client. pub async fn cache( &self, - roots: Vec<ModuleSpecifier>, + roots: Vec<(ModuleSpecifier, deno_graph::ModuleKind)>, ) -> Result<(), AnyError> { let (tx, rx) = oneshot::channel::<Result<(), AnyError>>(); if self.0.send((roots, tx)).is_err() { diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs index f1ed42544..62b89e526 100644 --- a/cli/lsp/diagnostics.rs +++ b/cli/lsp/diagnostics.rs @@ -20,6 +20,7 @@ use deno_core::error::AnyError; use deno_core::resolve_url; use deno_core::serde_json::json; use deno_core::ModuleSpecifier; +use deno_graph::Resolved; use deno_runtime::tokio_util::create_basic_runtime; use log::error; use lspower::lsp; @@ -547,13 +548,13 @@ fn resolution_error_as_code( use deno_graph::SpecifierError; match err { - ResolutionError::InvalidDowngrade(_, _) => { + ResolutionError::InvalidDowngrade { .. } => { lsp::NumberOrString::String("invalid-downgrade".to_string()) } - ResolutionError::InvalidLocalImport(_, _) => { + ResolutionError::InvalidLocalImport { .. } => { lsp::NumberOrString::String("invalid-local-import".to_string()) } - ResolutionError::InvalidSpecifier(err, _) => match err { + ResolutionError::InvalidSpecifier { error, .. } => match error { SpecifierError::ImportPrefixMissing(_, _) => { lsp::NumberOrString::String("import-prefix-missing".to_string()) } @@ -561,7 +562,7 @@ fn resolution_error_as_code( lsp::NumberOrString::String("invalid-url".to_string()) } }, - ResolutionError::ResolverError(_, _, _) => { + ResolutionError::ResolverError { .. } => { lsp::NumberOrString::String("resolver-error".to_string()) } } @@ -575,7 +576,9 @@ fn diagnose_dependency( maybe_assert_type: Option<&str>, ) { match resolved { - Some(Ok((specifier, range))) => { + Resolved::Ok { + specifier, range, .. + } => { if let Some(doc) = documents.get(specifier) { if let Some(message) = doc.maybe_warning() { diagnostics.push(lsp::Diagnostic { @@ -633,7 +636,7 @@ fn diagnose_dependency( }); } } - Some(Err(err)) => diagnostics.push(lsp::Diagnostic { + Resolved::Err(err) => diagnostics.push(lsp::Diagnostic { range: documents::to_lsp_range(err.range()), severity: Some(lsp::DiagnosticSeverity::ERROR), code: Some(resolution_error_as_code(err)), diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs index 5d583330d..19753389d 100644 --- a/cli/lsp/documents.rs +++ b/cli/lsp/documents.rs @@ -22,7 +22,9 @@ use deno_core::error::AnyError; use deno_core::parking_lot::Mutex; use deno_core::url; use deno_core::ModuleSpecifier; +use deno_graph::source::ResolveResponse; use deno_graph::Module; +use deno_graph::Resolved; use lspower::lsp; use once_cell::sync::Lazy; use std::collections::BTreeMap; @@ -213,58 +215,6 @@ impl AssetOrDocument { } } -// TODO(@kitsonk) expose the synthetic module from deno_graph -#[derive(Debug)] -struct SyntheticModule { - dependencies: BTreeMap<String, deno_graph::Resolved>, - specifier: ModuleSpecifier, -} - -impl SyntheticModule { - pub fn new( - specifier: ModuleSpecifier, - dependencies: Vec<(String, Option<lsp::Range>)>, - maybe_resolver: Option<&dyn deno_graph::source::Resolver>, - ) -> Self { - let dependencies = dependencies - .iter() - .map(|(dep, maybe_range)| { - let range = to_deno_graph_range(&specifier, maybe_range.as_ref()); - let result = if let Some(resolver) = maybe_resolver { - resolver.resolve(dep, &specifier).map_err(|err| { - if let Some(specifier_error) = - err.downcast_ref::<deno_graph::SpecifierError>() - { - deno_graph::ResolutionError::InvalidSpecifier( - specifier_error.clone(), - range.clone(), - ) - } else { - deno_graph::ResolutionError::ResolverError( - Arc::new(err), - dep.to_string(), - range.clone(), - ) - } - }) - } else { - deno_core::resolve_import(dep, specifier.as_str()).map_err(|err| { - deno_graph::ResolutionError::ResolverError( - Arc::new(err.into()), - dep.to_string(), - range.clone(), - ) - }) - }; - (dep.to_string(), Some(result.map(|s| (s, range)))) - }) - .collect(); - Self { - dependencies, - specifier, - } - } -} #[derive(Debug, Clone)] struct DocumentInner { /// contains the last-known-good set of dependencies from parsing the module @@ -274,7 +224,7 @@ struct DocumentInner { maybe_language_id: Option<LanguageId>, maybe_lsp_version: Option<i32>, maybe_module: - Option<Result<deno_graph::EsModule, deno_graph::ModuleGraphError>>, + Option<Result<deno_graph::Module, deno_graph::ModuleGraphError>>, maybe_navigation_tree: Option<Arc<tsc::NavigationTree>>, maybe_warning: Option<String>, specifier: ModuleSpecifier, @@ -299,16 +249,14 @@ impl Document { // we only ever do `Document::new` on on disk resources that are supposed to // be diagnosable, unlike `Document::open`, so it is safe to unconditionally // parse the module. - let maybe_module = match deno_graph::parse_module( + let maybe_module = Some(deno_graph::parse_module( &specifier, maybe_headers, content.clone(), + Some(&deno_graph::ModuleKind::Esm), maybe_resolver, Some(&parser), - ) { - Ok(m) => m.to_maybe_es_module().map(Ok), - Err(err) => Some(Err(err)), - }; + )); let dependencies = if let Some(Ok(module)) = &maybe_module { Arc::new(module.dependencies.clone()) } else { @@ -340,16 +288,14 @@ impl Document { let maybe_headers = language_id.as_headers(); let parser = SourceParser::default(); let maybe_module = if language_id.is_diagnosable() { - match deno_graph::parse_module( + Some(deno_graph::parse_module( &specifier, maybe_headers, content.clone(), + Some(&deno_graph::ModuleKind::Esm), maybe_resolver, Some(&parser), - ) { - Ok(m) => m.to_maybe_es_module().map(Ok), - Err(err) => Some(Err(err)), - } + )) } else { None }; @@ -411,16 +357,14 @@ impl Document { .map(|li| li.as_headers()) .flatten(); let parser = SourceParser::default(); - match deno_graph::parse_module( + Some(deno_graph::parse_module( &self.0.specifier, maybe_headers, content.clone(), + Some(&deno_graph::ModuleKind::Esm), maybe_resolver, Some(&parser), - ) { - Ok(m) => m.to_maybe_es_module().map(Ok), - Err(err) => Some(Err(err)), - } + )) } else { None }; @@ -504,10 +448,19 @@ impl Document { } pub fn maybe_types_dependency(&self) -> deno_graph::Resolved { - let module_result = self.0.maybe_module.as_ref()?; - let module = module_result.as_ref().ok()?; - let (_, maybe_dep) = module.maybe_types_dependency.as_ref()?; - maybe_dep.clone() + let module_result = match self.0.maybe_module.as_ref() { + Some(module_result) => module_result, + _ => return deno_graph::Resolved::None, + }; + let module = match module_result.as_ref() { + Ok(module) => module, + Err(_) => return deno_graph::Resolved::None, + }; + if let Some((_, maybe_dep)) = module.maybe_types_dependency.as_ref() { + maybe_dep.clone() + } else { + deno_graph::Resolved::None + } } pub fn media_type(&self) -> MediaType { @@ -525,18 +478,18 @@ impl Document { fn maybe_module( &self, - ) -> Option<&Result<deno_graph::EsModule, deno_graph::ModuleGraphError>> { + ) -> Option<&Result<deno_graph::Module, deno_graph::ModuleGraphError>> { self.0.maybe_module.as_ref() } pub fn maybe_parsed_source( &self, ) -> Option<Result<deno_ast::ParsedSource, deno_graph::ModuleGraphError>> { - self.maybe_module().map(|r| { - r.as_ref() - .map(|m| m.parsed_source.clone()) - .map_err(|err| err.clone()) - }) + let module_result = self.maybe_module()?; + match module_result { + Ok(module) => Some(Ok(module.maybe_parsed_source.clone()?)), + Err(err) => Some(Err(err.clone())), + } } pub fn maybe_navigation_tree(&self) -> Option<Arc<tsc::NavigationTree>> { @@ -576,14 +529,9 @@ impl Document { } } -pub(crate) fn to_hover_text( - result: &Result< - (ModuleSpecifier, deno_graph::Range), - deno_graph::ResolutionError, - >, -) -> String { +pub(crate) fn to_hover_text(result: &Resolved) -> String { match result { - Ok((specifier, _)) => match specifier.scheme() { + Resolved::Ok { specifier, .. } => match specifier.scheme() { "data" => "_(a data url)_".to_string(), "blob" => "_(a blob url)_".to_string(), _ => format!( @@ -593,7 +541,8 @@ pub(crate) fn to_hover_text( ) .replace('@', "​@"), }, - Err(_) => "_[errored]_".to_string(), + Resolved::Err(_) => "_[errored]_".to_string(), + Resolved::None => "_[missing]_".to_string(), } } @@ -802,7 +751,7 @@ pub(crate) struct Documents { file_system_docs: Arc<Mutex<FileSystemDocuments>>, /// Any imports to the context supplied by configuration files. This is like /// the imports into the a module graph in CLI. - imports: Arc<HashMap<ModuleSpecifier, SyntheticModule>>, + imports: Arc<HashMap<ModuleSpecifier, Module>>, /// The optional import map that should be used when resolving dependencies. maybe_import_map: Option<ImportMapResolver>, /// The optional JSX resolver, which is used when JSX imports are configured. @@ -913,7 +862,7 @@ impl Documents { ) -> bool { let maybe_resolver = self.get_maybe_resolver(); let maybe_specifier = if let Some(resolver) = maybe_resolver { - resolver.resolve(specifier, referrer).ok() + resolver.resolve(specifier, referrer).to_result().ok() } else { deno_core::resolve_import(specifier, referrer.as_str()).ok() }; @@ -1043,14 +992,14 @@ impl Documents { results.push(None); } } else if let Some(dep) = dependencies.get(&specifier) { - if let Some(Ok((specifier, _))) = &dep.maybe_type { + if let Resolved::Ok { specifier, .. } = &dep.maybe_type { results.push(self.resolve_dependency(specifier)); - } else if let Some(Ok((specifier, _))) = &dep.maybe_code { + } else if let Resolved::Ok { specifier, .. } = &dep.maybe_code { results.push(self.resolve_dependency(specifier)); } else { results.push(None); } - } else if let Some(Some(Ok((specifier, _)))) = + } else if let Some(Resolved::Ok { specifier, .. }) = self.resolve_imports_dependency(&specifier) { // clone here to avoid double borrow of self @@ -1121,9 +1070,7 @@ impl Documents { imports .into_iter() .map(|(referrer, dependencies)| { - let dependencies = - dependencies.into_iter().map(|s| (s, None)).collect(); - let module = SyntheticModule::new( + let module = Module::new_from_type_imports( referrer.clone(), dependencies, self.get_maybe_resolver(), @@ -1167,7 +1114,9 @@ impl Documents { .insert(specifier.clone()); } } - if let Some((_, Some(Ok((dep, _))))) = &module.maybe_types_dependency { + if let Some((_, Resolved::Ok { specifier: dep, .. })) = + &module.maybe_types_dependency + { dependents_map .entry(dep.clone()) .or_default() @@ -1198,12 +1147,10 @@ impl Documents { .map(|m| { m.maybe_types_dependency .as_ref() - .map(|(_, o)| o.as_ref().map(|r| r.as_ref().ok()).flatten()) - .flatten() + .map(|(_, resolved)| resolved.clone()) }) - .flatten() - .cloned(); - if let Some((specifier, _)) = maybe_types_dependency { + .flatten(); + if let Some(Resolved::Ok { specifier, .. }) = maybe_types_dependency { self.resolve_dependency(&specifier) } else { let media_type = doc.media_type(); @@ -1221,7 +1168,7 @@ impl Documents { for module in self.imports.values() { let maybe_dep = module.dependencies.get(specifier); if maybe_dep.is_some() { - return maybe_dep; + return maybe_dep.map(|d| &d.maybe_type); } } None diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs index b21081e85..426710b83 100644 --- a/cli/lsp/language_server.rs +++ b/cli/lsp/language_server.rs @@ -8,6 +8,7 @@ use deno_core::serde_json; use deno_core::serde_json::json; use deno_core::serde_json::Value; use deno_core::ModuleSpecifier; +use deno_graph::Resolved; use import_map::ImportMap; use log::error; use log::info; @@ -1058,34 +1059,38 @@ impl Inner { .get_code() .map(|s| self.documents.get(s)) .flatten() - .map(|d| d.maybe_types_dependency()) - .flatten(); - let value = match (&dep.maybe_code, &dep.maybe_type, &dep_maybe_types_dependency) { - (Some(code_dep), Some(type_dep), None) => format!( + .map(|d| d.maybe_types_dependency()); + let value = match (dep.maybe_code.is_none(), dep.maybe_type.is_none(), &dep_maybe_types_dependency) { + (false, false, None) => format!( "**Resolved Dependency**\n\n**Code**: {}\n\n**Types**: {}\n", - to_hover_text(code_dep), - to_hover_text(type_dep) + to_hover_text(&dep.maybe_code), + to_hover_text(&dep.maybe_type) ), - (Some(code_dep), Some(type_dep), Some(types_dep)) => format!( + (false, false, Some(types_dep)) if !types_dep.is_none() => format!( "**Resolved Dependency**\n\n**Code**: {}\n**Types**: {}\n**Import Types**: {}\n", - to_hover_text(code_dep), - to_hover_text(types_dep), - to_hover_text(type_dep) + to_hover_text(&dep.maybe_code), + to_hover_text(&dep.maybe_type), + to_hover_text(types_dep) ), - (Some(code_dep), None, None) => format!( - "**Resolved Dependency**\n\n**Code**: {}\n", - to_hover_text(code_dep) + (false, false, Some(_)) => format!( + "**Resolved Dependency**\n\n**Code**: {}\n\n**Types**: {}\n", + to_hover_text(&dep.maybe_code), + to_hover_text(&dep.maybe_type) ), - (Some(code_dep), None, Some(types_dep)) => format!( + (false, true, Some(types_dep)) if !types_dep.is_none() => format!( "**Resolved Dependency**\n\n**Code**: {}\n\n**Types**: {}\n", - to_hover_text(code_dep), + to_hover_text(&dep.maybe_code), to_hover_text(types_dep) ), - (None, Some(type_dep), _) => format!( + (false, true, _) => format!( + "**Resolved Dependency**\n\n**Code**: {}\n", + to_hover_text(&dep.maybe_code) + ), + (true, false, _) => format!( "**Resolved Dependency**\n\n**Types**: {}\n", - to_hover_text(type_dep) + to_hover_text(&dep.maybe_type) ), - (None, None, _) => unreachable!("{}", json!(params)), + (true, true, _) => unreachable!("{}", json!(params)), }; let value = if let Some(docs) = self.module_registries.get_hover(&dep).await { @@ -2677,10 +2682,15 @@ impl Inner { params .uris .iter() - .map(|t| self.url_map.normalize_url(&t.uri)) + .map(|t| { + ( + self.url_map.normalize_url(&t.uri), + deno_graph::ModuleKind::Esm, + ) + }) .collect() } else { - vec![referrer.clone()] + vec![(referrer.clone(), deno_graph::ModuleKind::Esm)] }; if self.maybe_cache_server.is_none() { |