Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions cli/lsp/completions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -864,6 +864,7 @@ mod tests {
use std::collections::HashMap;

use deno_core::resolve_url;
use deno_resolver::deno_json::CompilerOptionsKey;
use pretty_assertions::assert_eq;
use test_util::TempDir;

Expand Down Expand Up @@ -907,7 +908,11 @@ mod tests {
.global()
.set(&specifier, HashMap::default(), source.as_bytes())
.expect("could not cache file");
let module = document_modules.module_for_specifier(&specifier, None);
let module = document_modules.module_for_specifier(
&specifier,
None,
Some(&CompilerOptionsKey::WorkspaceConfig(None)),
);
assert!(module.is_some(), "source could not be setup");
}
document_modules
Expand Down Expand Up @@ -992,7 +997,7 @@ mod tests {
&[("https://deno.land/x/a/b/c.ts", "console.log(1);\n")],
);
let module = document_modules
.module_for_specifier(&specifier, None)
.module_for_specifier(&specifier, None, None)
.unwrap();
let actual =
get_remote_completions(&module, "h", &range, &document_modules);
Expand Down
70 changes: 62 additions & 8 deletions cli/lsp/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,9 +58,11 @@ use super::performance::Performance;
use super::tsc;
use super::tsc::MaybeAmbientModules;
use super::tsc::TsServer;
use crate::lsp::documents::OpenDocument;
use crate::lsp::lint::LspLinter;
use crate::lsp::logging::lsp_warn;
use crate::lsp::lsp_custom::DiagnosticBatchNotificationParams;
use crate::lsp::urls::uri_to_url;
use crate::sys::CliSys;
use crate::tsc::DiagnosticCategory;
use crate::type_checker::ambient_modules_to_regex_string;
Expand Down Expand Up @@ -871,7 +873,11 @@ fn to_lsp_related_information(
let uri = resolve_url(file_name)
.ok()
.and_then(|s| {
document_modules.module_for_specifier(&s, module.scope.as_deref())
document_modules.module_for_specifier(
&s,
module.scope.as_deref(),
Some(&module.compiler_options_key),
)
})
.map(|m| m.uri.as_ref().clone())
.unwrap_or_else(|| Uri::from_str("unknown:").unwrap());
Expand Down Expand Up @@ -1022,11 +1028,49 @@ async fn generate_ts_diagnostics(
ts_server: &tsc::TsServer,
token: CancellationToken,
) -> Result<(DiagnosticVec, AmbientModulesByKey), AnyError> {
let (mut records, ambient_modules_by_key, unresolved_documents) =
generate_ts_diagnostics_inner(
snapshot.document_modules.documents.open_docs(),
&snapshot,
ts_server,
&token,
)
.await?;
// Some documents may not have been mapped to any primary module the first
// time because they are remote/npm deps, and the compiler-options scope could
// not be inferred. But these will often have been transitively assigned while
// tsc requested the deps of the other documents. Do a second pass for them.
let (records_from_second_pass, _, _) = generate_ts_diagnostics_inner(
unresolved_documents.into_iter(),
&snapshot,
ts_server,
&token,
)
.await?;
records.extend(records_from_second_pass);
Ok((records, ambient_modules_by_key))
}

async fn generate_ts_diagnostics_inner<'a>(
documents: impl Iterator<Item = &'a Arc<OpenDocument>>,
snapshot: &Arc<language_server::StateSnapshot>,
ts_server: &tsc::TsServer,
token: &CancellationToken,
) -> Result<
(
DiagnosticVec,
AmbientModulesByKey,
// Documents that couldn't be resolved to a primary module.
Vec<&'a Arc<OpenDocument>>,
),
AnyError,
> {
let mut records = Vec::new();
let mut ambient_modules_by_key = HashMap::new();
let mut enabled_modules_by_key = BTreeMap::<_, Vec<_>>::new();
let mut disabled_documents = Vec::new();
for document in snapshot.document_modules.documents.open_docs() {
let mut unresolved_documents = Vec::new();
for document in documents {
if document.is_diagnosable() {
if let Some(module) = snapshot
.document_modules
Expand All @@ -1043,6 +1087,14 @@ async fn generate_ts_diagnostics(
.push(module);
continue;
}
} else {
let url = uri_to_url(&document.uri);
if url.scheme() != "file"
|| snapshot.resolver.in_node_modules(&url)
|| snapshot.cache.in_cache_directory(&url)
{
unresolved_documents.push(document);
}
}
}
disabled_documents.push(document.clone());
Expand All @@ -1063,7 +1115,7 @@ async fn generate_ts_diagnostics(
enabled_modules_by_key
{
let (diagnostics_list, ambient_modules) = ts_server
.get_diagnostics(snapshot.clone(), &enabled_modules, &token)
.get_diagnostics(snapshot.clone(), &enabled_modules, token)
.await?;
enabled_modules_with_diagnostics
.extend(enabled_modules.into_iter().zip(diagnostics_list));
Expand Down Expand Up @@ -1097,7 +1149,7 @@ async fn generate_ts_diagnostics(
},
});
}
Ok((records, ambient_modules_by_key))
Ok((records, ambient_modules_by_key, unresolved_documents))
}

#[derive(Debug, Deserialize)]
Expand Down Expand Up @@ -1553,10 +1605,11 @@ fn diagnose_resolution(
diagnostics.push(DenoDiagnostic::DenoWarn(message.clone()));
}
}
match snapshot
.document_modules
.module_for_specifier(specifier, referrer_module.scope.as_deref())
{
match snapshot.document_modules.module_for_specifier(
specifier,
referrer_module.scope.as_deref(),
Some(&referrer_module.compiler_options_key),
) {
Some(module) => {
if let Some(headers) = &module.headers {
if let Some(message) = headers.get("x-deno-warning") {
Expand Down Expand Up @@ -1964,6 +2017,7 @@ mod tests {
compiler_options_resolver,
linter_resolver,
resolver,
cache: Arc::new(cache),
},
)
}
Expand Down
74 changes: 62 additions & 12 deletions cli/lsp/documents.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1167,8 +1167,15 @@ impl DocumentModules {
self.documents.close_notebook(uri)
}

pub fn release(&self, specifier: &Url, scope: Option<&Url>) {
let Some(module) = self.module_for_specifier(specifier, scope) else {
pub fn release(
&self,
specifier: &Url,
scope: Option<&Url>,
compiler_options_key: Option<&CompilerOptionsKey>,
) {
let Some(module) =
self.module_for_specifier(specifier, scope, compiler_options_key)
else {
return;
};
self.documents.remove_server_doc(&module.uri);
Expand Down Expand Up @@ -1201,6 +1208,7 @@ impl DocumentModules {
document: &Document,
specifier: Option<&Arc<Url>>,
scope: Option<&Url>,
compiler_options_key: Option<&CompilerOptionsKey>,
) -> Option<Arc<DocumentModule>> {
let modules = self.modules_for_scope(scope)?;
if let Some(module) = modules.get(document) {
Expand All @@ -1209,15 +1217,27 @@ impl DocumentModules {
let specifier = specifier
.cloned()
.or_else(|| self.infer_specifier(document))?;
let (compiler_options_key, compiler_options_data) =
let scheme = specifier.scheme();
let (compiler_options_key, compiler_options_data) = if scheme != "file"
|| self.resolver.in_node_modules(&specifier)
|| self.cache.in_global_cache_directory(&specifier)
{
let key = compiler_options_key?;
let value = self
.compiler_options_resolver
.for_key(key)
.expect("Key should be in sync with resolver.");
(key, value)
} else {
self.compiler_options_resolver.entry_for_specifier(
if specifier.scheme() != "file" && scope.is_some() {
if scheme != "file" && scope.is_some() {
#[allow(clippy::unnecessary_unwrap)]
scope.unwrap()
} else {
&specifier
},
);
)
};
let module = Arc::new(DocumentModule::new(
document,
specifier,
Expand All @@ -1238,13 +1258,14 @@ impl DocumentModules {
document: &Document,
scope: Option<&Url>,
) -> Option<Arc<DocumentModule>> {
self.module_inner(document, None, scope)
self.module_inner(document, None, scope, None)
}

pub fn module_for_specifier(
&self,
specifier: &Url,
scope: Option<&Url>,
compiler_options_key: Option<&CompilerOptionsKey>,
) -> Option<Arc<DocumentModule>> {
let scoped_resolver = self.resolver.get_scoped_resolver(scope);
let specifier = match JsrPackageReqReference::from_specifier(specifier) {
Expand All @@ -1258,7 +1279,12 @@ impl DocumentModules {
self
.documents
.get_for_specifier(&specifier, scope, &self.cache)?;
self.module_inner(&document, Some(&Arc::new(specifier)), scope)
self.module_inner(
&document,
Some(&Arc::new(specifier)),
scope,
compiler_options_key,
)
}

pub fn primary_module(
Expand Down Expand Up @@ -1586,8 +1612,10 @@ impl DocumentModules {
raw_specifiers: &[(bool, String)],
referrer: &Url,
scope: Option<&Url>,
compiler_options_key: Option<&CompilerOptionsKey>,
) -> Vec<Option<(Url, MediaType)>> {
let referrer_module = self.module_for_specifier(referrer, scope);
let referrer_module =
self.module_for_specifier(referrer, scope, compiler_options_key);
let dependencies = referrer_module.as_ref().map(|d| &d.dependencies);
let mut results = Vec::new();
let scoped_resolver = self.resolver.get_scoped_resolver(scope);
Expand All @@ -1607,9 +1635,21 @@ impl DocumentModules {
dependencies.as_ref().and_then(|d| d.get(raw_specifier))
{
if let Some(specifier) = dep.maybe_type.maybe_specifier() {
self.resolve_dependency(specifier, referrer, resolution_mode, scope)
self.resolve_dependency(
specifier,
referrer,
resolution_mode,
scope,
compiler_options_key,
)
} else if let Some(specifier) = dep.maybe_code.maybe_specifier() {
self.resolve_dependency(specifier, referrer, resolution_mode, scope)
self.resolve_dependency(
specifier,
referrer,
resolution_mode,
scope,
compiler_options_key,
)
} else {
None
}
Expand All @@ -1626,6 +1666,7 @@ impl DocumentModules {
referrer,
resolution_mode,
scope,
compiler_options_key,
),
_ => None,
}
Expand All @@ -1642,6 +1683,7 @@ impl DocumentModules {
referrer: &Url,
resolution_mode: ResolutionMode,
scope: Option<&Url>,
compiler_options_key: Option<&CompilerOptionsKey>,
) -> Option<(Url, MediaType)> {
if let Some(module_name) = specifier.as_str().strip_prefix("node:") {
if deno_node::is_builtin_node_module(module_name) {
Expand All @@ -1664,7 +1706,9 @@ impl DocumentModules {
specifier = s;
media_type = Some(mt);
}
let Some(module) = self.module_for_specifier(&specifier, scope) else {
let Some(module) =
self.module_for_specifier(&specifier, scope, compiler_options_key)
else {
let media_type =
media_type.unwrap_or_else(|| MediaType::from_specifier(&specifier));
return Some((specifier, media_type));
Expand All @@ -1674,7 +1718,13 @@ impl DocumentModules {
.as_ref()
.and_then(|d| d.dependency.maybe_specifier())
{
self.resolve_dependency(types, &specifier, module.resolution_mode, scope)
self.resolve_dependency(
types,
&specifier,
module.resolution_mode,
scope,
compiler_options_key,
)
} else {
Some((module.specifier.as_ref().clone(), module.media_type))
}
Expand Down
10 changes: 6 additions & 4 deletions cli/lsp/language_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ pub struct StateSnapshot {
pub linter_resolver: Arc<LspLinterResolver>,
pub document_modules: DocumentModules,
pub resolver: Arc<LspResolver>,
pub cache: Arc<LspCache>,
}

#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
Expand Down Expand Up @@ -637,10 +638,10 @@ impl Inner {
document: &Document,
) -> LspResult<Option<Arc<DocumentModule>>> {
let Some(module) = self.document_modules.primary_module(document) else {
if document
.uri()
.scheme()
.is_some_and(|s| s.eq_lowercase("deno"))
let url = uri_to_url(document.uri());
if url.scheme() != "file"
|| self.resolver.in_node_modules(&url)
|| self.cache.in_cache_directory(&url)
{
return Ok(None);
}
Expand Down Expand Up @@ -698,6 +699,7 @@ impl Inner {
linter_resolver: self.linter_resolver.clone(),
document_modules: self.document_modules.clone(),
resolver: self.resolver.snapshot(),
cache: Arc::new(self.cache.clone()),
})
}

Expand Down
Loading
Loading