summaryrefslogtreecommitdiff
path: root/cli/lsp
diff options
context:
space:
mode:
Diffstat (limited to 'cli/lsp')
-rw-r--r--cli/lsp/analysis.rs37
-rw-r--r--cli/lsp/completions.rs22
-rw-r--r--cli/lsp/config.rs12
-rw-r--r--cli/lsp/diagnostics.rs1
-rw-r--r--cli/lsp/documents.rs136
-rw-r--r--cli/lsp/language_server.rs40
-rw-r--r--cli/lsp/repl.rs2
-rw-r--r--cli/lsp/resolver.rs287
-rw-r--r--cli/lsp/tsc.rs34
9 files changed, 400 insertions, 171 deletions
diff --git a/cli/lsp/analysis.rs b/cli/lsp/analysis.rs
index 683a59c21..9f26de70c 100644
--- a/cli/lsp/analysis.rs
+++ b/cli/lsp/analysis.rs
@@ -39,6 +39,7 @@ use deno_semver::package::PackageReq;
use deno_semver::package::PackageReqReference;
use deno_semver::Version;
use import_map::ImportMap;
+use node_resolver::NodeModuleKind;
use once_cell::sync::Lazy;
use regex::Regex;
use std::borrow::Cow;
@@ -467,6 +468,7 @@ impl<'a> TsResponseImportMapper<'a> {
&self,
specifier: &str,
referrer: &ModuleSpecifier,
+ referrer_kind: NodeModuleKind,
) -> Option<String> {
let specifier_stem = specifier.strip_suffix(".js").unwrap_or(specifier);
let specifiers = std::iter::once(Cow::Borrowed(specifier)).chain(
@@ -477,7 +479,7 @@ impl<'a> TsResponseImportMapper<'a> {
for specifier in specifiers {
if let Some(specifier) = self
.resolver
- .as_graph_resolver(Some(&self.file_referrer))
+ .as_cli_resolver(Some(&self.file_referrer))
.resolve(
&specifier,
&deno_graph::Range {
@@ -485,6 +487,7 @@ impl<'a> TsResponseImportMapper<'a> {
start: deno_graph::Position::zeroed(),
end: deno_graph::Position::zeroed(),
},
+ referrer_kind,
ResolutionMode::Types,
)
.ok()
@@ -507,10 +510,11 @@ impl<'a> TsResponseImportMapper<'a> {
&self,
specifier_text: &str,
referrer: &ModuleSpecifier,
+ referrer_kind: NodeModuleKind,
) -> bool {
self
.resolver
- .as_graph_resolver(Some(&self.file_referrer))
+ .as_cli_resolver(Some(&self.file_referrer))
.resolve(
specifier_text,
&deno_graph::Range {
@@ -518,6 +522,7 @@ impl<'a> TsResponseImportMapper<'a> {
start: deno_graph::Position::zeroed(),
end: deno_graph::Position::zeroed(),
},
+ referrer_kind,
deno_graph::source::ResolutionMode::Types,
)
.is_ok()
@@ -586,6 +591,7 @@ fn try_reverse_map_package_json_exports(
/// like an import and rewrite the import specifier to include the extension
pub fn fix_ts_import_changes(
referrer: &ModuleSpecifier,
+ referrer_kind: NodeModuleKind,
changes: &[tsc::FileTextChanges],
language_server: &language_server::Inner,
) -> Result<Vec<tsc::FileTextChanges>, AnyError> {
@@ -602,8 +608,8 @@ pub fn fix_ts_import_changes(
if let Some(captures) = IMPORT_SPECIFIER_RE.captures(line) {
let specifier =
captures.iter().skip(1).find_map(|s| s).unwrap().as_str();
- if let Some(new_specifier) =
- import_mapper.check_unresolved_specifier(specifier, referrer)
+ if let Some(new_specifier) = import_mapper
+ .check_unresolved_specifier(specifier, referrer, referrer_kind)
{
line.replace(specifier, &new_specifier)
} else {
@@ -633,6 +639,7 @@ pub fn fix_ts_import_changes(
/// resolution by Deno (includes the extension).
fn fix_ts_import_action<'a>(
referrer: &ModuleSpecifier,
+ referrer_kind: NodeModuleKind,
action: &'a tsc::CodeFixAction,
language_server: &language_server::Inner,
) -> Option<Cow<'a, tsc::CodeFixAction>> {
@@ -652,7 +659,7 @@ fn fix_ts_import_action<'a>(
};
let import_mapper = language_server.get_ts_response_import_mapper(referrer);
if let Some(new_specifier) =
- import_mapper.check_unresolved_specifier(specifier, referrer)
+ import_mapper.check_unresolved_specifier(specifier, referrer, referrer_kind)
{
let description = action.description.replace(specifier, &new_specifier);
let changes = action
@@ -683,7 +690,7 @@ fn fix_ts_import_action<'a>(
fix_id: None,
fix_all_description: None,
}))
- } else if !import_mapper.is_valid_import(specifier, referrer) {
+ } else if !import_mapper.is_valid_import(specifier, referrer, referrer_kind) {
None
} else {
Some(Cow::Borrowed(action))
@@ -1017,6 +1024,7 @@ impl CodeActionCollection {
pub fn add_ts_fix_action(
&mut self,
specifier: &ModuleSpecifier,
+ specifier_kind: NodeModuleKind,
action: &tsc::CodeFixAction,
diagnostic: &lsp::Diagnostic,
language_server: &language_server::Inner,
@@ -1034,7 +1042,8 @@ impl CodeActionCollection {
"The action returned from TypeScript is unsupported.",
));
}
- let Some(action) = fix_ts_import_action(specifier, action, language_server)
+ let Some(action) =
+ fix_ts_import_action(specifier, specifier_kind, action, language_server)
else {
return Ok(());
};
@@ -1276,6 +1285,9 @@ impl CodeActionCollection {
import_start_from_specifier(document, i)
})?;
let referrer = document.specifier();
+ let referrer_kind = language_server
+ .is_cjs_resolver
+ .get_doc_module_kind(document);
let file_referrer = document.file_referrer();
let config_data = language_server
.config
@@ -1298,10 +1310,11 @@ impl CodeActionCollection {
if !config_data.byonm {
return None;
}
- if !language_server
- .resolver
- .is_bare_package_json_dep(&dep_key, referrer)
- {
+ if !language_server.resolver.is_bare_package_json_dep(
+ &dep_key,
+ referrer,
+ referrer_kind,
+ ) {
return None;
}
NpmPackageReqReference::from_str(&format!("npm:{}", &dep_key)).ok()?
@@ -1320,7 +1333,7 @@ impl CodeActionCollection {
}
if language_server
.resolver
- .npm_to_file_url(&npm_ref, document.specifier(), file_referrer)
+ .npm_to_file_url(&npm_ref, referrer, referrer_kind, file_referrer)
.is_some()
{
// The package import has types.
diff --git a/cli/lsp/completions.rs b/cli/lsp/completions.rs
index 1590743b2..3ee8ae93e 100644
--- a/cli/lsp/completions.rs
+++ b/cli/lsp/completions.rs
@@ -9,6 +9,7 @@ use super::jsr::CliJsrSearchApi;
use super::lsp_custom;
use super::npm::CliNpmSearchApi;
use super::registries::ModuleRegistry;
+use super::resolver::LspIsCjsResolver;
use super::resolver::LspResolver;
use super::search::PackageSearchApi;
use super::tsc;
@@ -35,6 +36,7 @@ use deno_semver::package::PackageNv;
use import_map::ImportMap;
use indexmap::IndexSet;
use lsp_types::CompletionList;
+use node_resolver::NodeModuleKind;
use once_cell::sync::Lazy;
use regex::Regex;
use tower_lsp::lsp_types as lsp;
@@ -159,15 +161,17 @@ pub async fn get_import_completions(
jsr_search_api: &CliJsrSearchApi,
npm_search_api: &CliNpmSearchApi,
documents: &Documents,
+ is_cjs_resolver: &LspIsCjsResolver,
resolver: &LspResolver,
maybe_import_map: Option<&ImportMap>,
) -> Option<lsp::CompletionResponse> {
let document = documents.get(specifier)?;
+ let specifier_kind = is_cjs_resolver.get_doc_module_kind(&document);
let file_referrer = document.file_referrer();
let (text, _, range) = document.get_maybe_dependency(position)?;
let range = to_narrow_lsp_range(document.text_info(), &range);
let resolved = resolver
- .as_graph_resolver(file_referrer)
+ .as_cli_resolver(file_referrer)
.resolve(
&text,
&Range {
@@ -175,6 +179,7 @@ pub async fn get_import_completions(
start: deno_graph::Position::zeroed(),
end: deno_graph::Position::zeroed(),
},
+ specifier_kind,
ResolutionMode::Execution,
)
.ok();
@@ -201,7 +206,7 @@ pub async fn get_import_completions(
// completions for import map specifiers
Some(lsp::CompletionResponse::List(completion_list))
} else if let Some(completion_list) =
- get_local_completions(specifier, &text, &range, resolver)
+ get_local_completions(specifier, specifier_kind, &text, &range, resolver)
{
// completions for local relative modules
Some(lsp::CompletionResponse::List(completion_list))
@@ -355,24 +360,26 @@ fn get_import_map_completions(
/// Return local completions that are relative to the base specifier.
fn get_local_completions(
- base: &ModuleSpecifier,
+ referrer: &ModuleSpecifier,
+ referrer_kind: NodeModuleKind,
text: &str,
range: &lsp::Range,
resolver: &LspResolver,
) -> Option<CompletionList> {
- if base.scheme() != "file" {
+ if referrer.scheme() != "file" {
return None;
}
let parent = &text[..text.char_indices().rfind(|(_, c)| *c == '/')?.0 + 1];
let resolved_parent = resolver
- .as_graph_resolver(Some(base))
+ .as_cli_resolver(Some(referrer))
.resolve(
parent,
&Range {
- specifier: base.clone(),
+ specifier: referrer.clone(),
start: deno_graph::Position::zeroed(),
end: deno_graph::Position::zeroed(),
},
+ referrer_kind,
ResolutionMode::Execution,
)
.ok()?;
@@ -385,7 +392,7 @@ fn get_local_completions(
let de = de.ok()?;
let label = de.path().file_name()?.to_string_lossy().to_string();
let entry_specifier = resolve_path(de.path().to_str()?, &cwd).ok()?;
- if entry_specifier == *base {
+ if entry_specifier == *referrer {
return None;
}
let full_text = format!("{parent}{label}");
@@ -905,6 +912,7 @@ mod tests {
ModuleSpecifier::from_file_path(file_c).expect("could not create");
let actual = get_local_completions(
&specifier,
+ NodeModuleKind::Esm,
"./",
&lsp::Range {
start: lsp::Position {
diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs
index 34bf64446..ea77e36bc 100644
--- a/cli/lsp/config.rs
+++ b/cli/lsp/config.rs
@@ -4,6 +4,7 @@ use deno_ast::MediaType;
use deno_config::deno_json::DenoJsonCache;
use deno_config::deno_json::FmtConfig;
use deno_config::deno_json::FmtOptionsConfig;
+use deno_config::deno_json::JsxImportSourceConfig;
use deno_config::deno_json::LintConfig;
use deno_config::deno_json::NodeModulesDirMode;
use deno_config::deno_json::TestConfig;
@@ -1654,6 +1655,17 @@ impl ConfigData {
self.member_dir.maybe_pkg_json()
}
+ pub fn maybe_jsx_import_source_config(
+ &self,
+ ) -> Option<JsxImportSourceConfig> {
+ self
+ .member_dir
+ .workspace
+ .to_maybe_jsx_import_source_config()
+ .ok()
+ .flatten()
+ }
+
pub fn scope_contains_specifier(&self, specifier: &ModuleSpecifier) -> bool {
specifier.as_str().starts_with(self.scope.as_str())
|| self
diff --git a/cli/lsp/diagnostics.rs b/cli/lsp/diagnostics.rs
index 83c00d27e..e4fb82e58 100644
--- a/cli/lsp/diagnostics.rs
+++ b/cli/lsp/diagnostics.rs
@@ -1707,6 +1707,7 @@ mod tests {
documents: Arc::new(documents),
assets: Default::default(),
config: Arc::new(config),
+ is_cjs_resolver: Default::default(),
resolver,
},
)
diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs
index ce13c3215..b62fa8553 100644
--- a/cli/lsp/documents.rs
+++ b/cli/lsp/documents.rs
@@ -3,7 +3,9 @@
use super::cache::calculate_fs_version;
use super::cache::LspCache;
use super::config::Config;
+use super::resolver::LspIsCjsResolver;
use super::resolver::LspResolver;
+use super::resolver::SingleReferrerGraphResolver;
use super::testing::TestCollector;
use super::testing::TestModule;
use super::text::LineIndex;
@@ -33,6 +35,7 @@ use deno_semver::npm::NpmPackageReqReference;
use deno_semver::package::PackageReq;
use indexmap::IndexMap;
use indexmap::IndexSet;
+use node_resolver::NodeModuleKind;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
@@ -293,6 +296,8 @@ pub struct Document {
/// Contains the last-known-good set of dependencies from parsing the module.
config: Arc<Config>,
dependencies: Arc<IndexMap<String, deno_graph::Dependency>>,
+ /// If this is maybe a CJS script and maybe not an ES module.
+ is_script: Option<bool>,
// TODO(nayeemrmn): This is unused, use it for scope attribution for remote
// modules.
file_referrer: Option<ModuleSpecifier>,
@@ -323,6 +328,7 @@ impl Document {
maybe_lsp_version: Option<i32>,
maybe_language_id: Option<LanguageId>,
maybe_headers: Option<HashMap<String, String>>,
+ is_cjs_resolver: &LspIsCjsResolver,
resolver: Arc<LspResolver>,
config: Arc<Config>,
cache: &Arc<LspCache>,
@@ -342,6 +348,7 @@ impl Document {
maybe_headers.as_ref(),
media_type,
file_referrer.as_ref(),
+ is_cjs_resolver,
&resolver,
)
} else {
@@ -367,6 +374,7 @@ impl Document {
file_referrer.as_ref(),
),
file_referrer,
+ is_script: maybe_module.as_ref().map(|m| m.is_script),
maybe_types_dependency,
line_index,
maybe_language_id,
@@ -388,6 +396,7 @@ impl Document {
fn with_new_config(
&self,
+ is_cjs_resolver: &LspIsCjsResolver,
resolver: Arc<LspResolver>,
config: Arc<Config>,
) -> Arc<Self> {
@@ -399,6 +408,7 @@ impl Document {
let dependencies;
let maybe_types_dependency;
let maybe_parsed_source;
+ let is_script;
let maybe_test_module_fut;
if media_type != self.media_type {
let parsed_source_result =
@@ -408,6 +418,7 @@ impl Document {
&parsed_source_result,
self.maybe_headers.as_ref(),
self.file_referrer.as_ref(),
+ is_cjs_resolver,
&resolver,
)
.ok();
@@ -415,6 +426,7 @@ impl Document {
.as_ref()
.map(|m| Arc::new(m.dependencies.clone()))
.unwrap_or_default();
+ is_script = maybe_module.as_ref().map(|m| m.is_script);
maybe_types_dependency = maybe_module
.as_ref()
.and_then(|m| Some(Arc::new(m.maybe_types_dependency.clone()?)));
@@ -422,10 +434,19 @@ impl Document {
maybe_test_module_fut =
get_maybe_test_module_fut(maybe_parsed_source.as_ref(), &config);
} else {
- let graph_resolver =
- resolver.as_graph_resolver(self.file_referrer.as_ref());
+ let cli_resolver = resolver.as_cli_resolver(self.file_referrer.as_ref());
let npm_resolver =
resolver.create_graph_npm_resolver(self.file_referrer.as_ref());
+ let config_data = resolver.as_config_data(self.file_referrer.as_ref());
+ let jsx_import_source_config =
+ config_data.and_then(|d| d.maybe_jsx_import_source_config());
+ let resolver = SingleReferrerGraphResolver {
+ valid_referrer: &self.specifier,
+ referrer_kind: is_cjs_resolver
+ .get_lsp_referrer_kind(&self.specifier, self.is_script),
+ cli_resolver,
+ jsx_import_source_config: jsx_import_source_config.as_ref(),
+ };
dependencies = Arc::new(
self
.dependencies
@@ -436,7 +457,7 @@ impl Document {
d.with_new_resolver(
s,
&CliJsrUrlProvider,
- Some(graph_resolver),
+ Some(&resolver),
Some(&npm_resolver),
),
)
@@ -446,10 +467,11 @@ impl Document {
maybe_types_dependency = self.maybe_types_dependency.as_ref().map(|d| {
Arc::new(d.with_new_resolver(
&CliJsrUrlProvider,
- Some(graph_resolver),
+ Some(&resolver),
Some(&npm_resolver),
))
});
+ is_script = self.is_script;
maybe_parsed_source = self.maybe_parsed_source().cloned();
maybe_test_module_fut = self
.maybe_test_module_fut
@@ -461,6 +483,7 @@ impl Document {
// updated properties
dependencies,
file_referrer: self.file_referrer.clone(),
+ is_script,
maybe_types_dependency,
maybe_navigation_tree: Mutex::new(None),
// maintain - this should all be copies/clones
@@ -485,6 +508,7 @@ impl Document {
fn with_change(
&self,
+ is_cjs_resolver: &LspIsCjsResolver,
version: i32,
changes: Vec<lsp::TextDocumentContentChangeEvent>,
) -> Result<Arc<Self>, AnyError> {
@@ -518,6 +542,7 @@ impl Document {
self.maybe_headers.as_ref(),
media_type,
self.file_referrer.as_ref(),
+ is_cjs_resolver,
self.resolver.as_ref(),
)
} else {
@@ -541,6 +566,7 @@ impl Document {
get_maybe_test_module_fut(maybe_parsed_source.as_ref(), &self.config);
Ok(Arc::new(Self {
config: self.config.clone(),
+ is_script: maybe_module.as_ref().map(|m| m.is_script),
specifier: self.specifier.clone(),
file_referrer: self.file_referrer.clone(),
maybe_fs_version: self.maybe_fs_version.clone(),
@@ -575,6 +601,7 @@ impl Document {
),
maybe_language_id: self.maybe_language_id,
dependencies: self.dependencies.clone(),
+ is_script: self.is_script,
maybe_types_dependency: self.maybe_types_dependency.clone(),
text: self.text.clone(),
text_info_cell: once_cell::sync::OnceCell::new(),
@@ -602,6 +629,7 @@ impl Document {
),
maybe_language_id: self.maybe_language_id,
dependencies: self.dependencies.clone(),
+ is_script: self.is_script,
maybe_types_dependency: self.maybe_types_dependency.clone(),
text: self.text.clone(),
text_info_cell: once_cell::sync::OnceCell::new(),
@@ -650,6 +678,13 @@ impl Document {
})
}
+ /// If this is maybe a CJS script and maybe not an ES module.
+ ///
+ /// Use `LspIsCjsResolver` to determine for sure.
+ pub fn is_script(&self) -> Option<bool> {
+ self.is_script
+ }
+
pub fn line_index(&self) -> Arc<LineIndex> {
self.line_index.clone()
}
@@ -797,6 +832,7 @@ impl FileSystemDocuments {
pub fn get(
&self,
specifier: &ModuleSpecifier,
+ is_cjs_resolver: &LspIsCjsResolver,
resolver: &Arc<LspResolver>,
config: &Arc<Config>,
cache: &Arc<LspCache>,
@@ -820,7 +856,14 @@ impl FileSystemDocuments {
};
if dirty {
// attempt to update the file on the file system
- self.refresh_document(specifier, resolver, config, cache, file_referrer)
+ self.refresh_document(
+ specifier,
+ is_cjs_resolver,
+ resolver,
+ config,
+ cache,
+ file_referrer,
+ )
} else {
old_doc
}
@@ -831,6 +874,7 @@ impl FileSystemDocuments {
fn refresh_document(
&self,
specifier: &ModuleSpecifier,
+ is_cjs_resolver: &LspIsCjsResolver,
resolver: &Arc<LspResolver>,
config: &Arc<Config>,
cache: &Arc<LspCache>,
@@ -847,6 +891,7 @@ impl FileSystemDocuments {
None,
None,
None,
+ is_cjs_resolver,
resolver.clone(),
config.clone(),
cache,
@@ -863,6 +908,7 @@ impl FileSystemDocuments {
None,
None,
None,
+ is_cjs_resolver,
resolver.clone(),
config.clone(),
cache,
@@ -890,6 +936,7 @@ impl FileSystemDocuments {
None,
None,
maybe_headers,
+ is_cjs_resolver,
resolver.clone(),
config.clone(),
cache,
@@ -930,6 +977,11 @@ pub struct Documents {
/// The DENO_DIR that the documents looks for non-file based modules.
cache: Arc<LspCache>,
config: Arc<Config>,
+ /// Resolver for detecting if a document is CJS or ESM.
+ is_cjs_resolver: Arc<LspIsCjsResolver>,
+ /// A resolver that takes into account currently loaded import map and JSX
+ /// settings.
+ resolver: Arc<LspResolver>,
/// A flag that indicates that stated data is potentially invalid and needs to
/// be recalculated before being considered valid.
dirty: bool,
@@ -937,9 +989,6 @@ pub struct Documents {
open_docs: HashMap<ModuleSpecifier, Arc<Document>>,
/// Documents stored on the file system.
file_system_docs: Arc<FileSystemDocuments>,
- /// A resolver that takes into account currently loaded import map and JSX
- /// settings.
- resolver: Arc<LspResolver>,
/// The npm package requirements found in npm specifiers.
npm_reqs_by_scope:
Arc<BTreeMap<Option<ModuleSpecifier>, BTreeSet<PackageReq>>>,
@@ -970,6 +1019,7 @@ impl Documents {
// the cache for remote modules here in order to get the
// x-typescript-types?
None,
+ &self.is_cjs_resolver,
self.resolver.clone(),
self.config.clone(),
&self.cache,
@@ -1004,7 +1054,7 @@ impl Documents {
))
})?;
self.dirty = true;
- let doc = doc.with_change(version, changes)?;
+ let doc = doc.with_change(&self.is_cjs_resolver, version, changes)?;
self.open_docs.insert(doc.specifier().clone(), doc.clone());
Ok(doc)
}
@@ -1133,6 +1183,7 @@ impl Documents {
if let Some(old_doc) = old_doc {
self.file_system_docs.get(
specifier,
+ &self.is_cjs_resolver,
&self.resolver,
&self.config,
&self.cache,
@@ -1157,6 +1208,7 @@ impl Documents {
} else {
self.file_system_docs.get(
&specifier,
+ &self.is_cjs_resolver,
&self.resolver,
&self.config,
&self.cache,
@@ -1215,12 +1267,15 @@ impl Documents {
referrer: &ModuleSpecifier,
file_referrer: Option<&ModuleSpecifier>,
) -> Vec<Option<(ModuleSpecifier, MediaType)>> {
- let document = self.get(referrer);
- let file_referrer = document
+ let referrer_doc = self.get(referrer);
+ let file_referrer = referrer_doc
.as_ref()
.and_then(|d| d.file_referrer())
.or(file_referrer);
- let dependencies = document.as_ref().map(|d| d.dependencies());
+ let dependencies = referrer_doc.as_ref().map(|d| d.dependencies());
+ let referrer_kind = self
+ .is_cjs_resolver
+ .get_maybe_doc_module_kind(referrer, referrer_doc.as_deref());
let mut results = Vec::new();
for raw_specifier in raw_specifiers {
if raw_specifier.starts_with("asset:") {
@@ -1237,31 +1292,35 @@ impl Documents {
results.push(self.resolve_dependency(
specifier,
referrer,
+ referrer_kind,
file_referrer,
));
} else if let Some(specifier) = dep.maybe_code.maybe_specifier() {
results.push(self.resolve_dependency(
specifier,
referrer,
+ referrer_kind,
file_referrer,
));
} else {
results.push(None);
}
} else if let Ok(specifier) =
- self.resolver.as_graph_resolver(file_referrer).resolve(
+ self.resolver.as_cli_resolver(file_referrer).resolve(
raw_specifier,
&deno_graph::Range {
specifier: referrer.clone(),
start: deno_graph::Position::zeroed(),
end: deno_graph::Position::zeroed(),
},
+ referrer_kind,
ResolutionMode::Types,
)
{
results.push(self.resolve_dependency(
&specifier,
referrer,
+ referrer_kind,
file_referrer,
));
} else {
@@ -1280,7 +1339,11 @@ impl Documents {
) {
self.config = Arc::new(config.clone());
self.cache = Arc::new(cache.clone());
+ self.is_cjs_resolver = Arc::new(LspIsCjsResolver::new(cache));
self.resolver = resolver.clone();
+
+ node_resolver::PackageJsonThreadLocalCache::clear();
+
{
let fs_docs = &self.file_system_docs;
// Clean up non-existent documents.
@@ -1300,14 +1363,21 @@ impl Documents {
if !config.specifier_enabled(doc.specifier()) {
continue;
}
- *doc = doc.with_new_config(self.resolver.clone(), self.config.clone());
+ *doc = doc.with_new_config(
+ &self.is_cjs_resolver,
+ self.resolver.clone(),
+ self.config.clone(),
+ );
}
for mut doc in self.file_system_docs.docs.iter_mut() {
if !config.specifier_enabled(doc.specifier()) {
continue;
}
- *doc.value_mut() =
- doc.with_new_config(self.resolver.clone(), self.config.clone());
+ *doc.value_mut() = doc.with_new_config(
+ &self.is_cjs_resolver,
+ self.resolver.clone(),
+ self.config.clone(),
+ );
}
self.open_docs = open_docs;
let mut preload_count = 0;
@@ -1324,6 +1394,7 @@ impl Documents {
{
fs_docs.refresh_document(
specifier,
+ &self.is_cjs_resolver,
&self.resolver,
&self.config,
&self.cache,
@@ -1409,6 +1480,7 @@ impl Documents {
&self,
specifier: &ModuleSpecifier,
referrer: &ModuleSpecifier,
+ referrer_kind: NodeModuleKind,
file_referrer: Option<&ModuleSpecifier>,
) -> Option<(ModuleSpecifier, MediaType)> {
if let Some(module_name) = specifier.as_str().strip_prefix("node:") {
@@ -1422,10 +1494,12 @@ impl Documents {
let mut specifier = specifier.clone();
let mut media_type = None;
if let Ok(npm_ref) = NpmPackageReqReference::from_specifier(&specifier) {
- let (s, mt) =
- self
- .resolver
- .npm_to_file_url(&npm_ref, referrer, file_referrer)?;
+ let (s, mt) = self.resolver.npm_to_file_url(
+ &npm_ref,
+ referrer,
+ referrer_kind,
+ file_referrer,
+ )?;
specifier = s;
media_type = Some(mt);
}
@@ -1435,7 +1509,8 @@ impl Documents {
return Some((specifier, media_type));
};
if let Some(types) = doc.maybe_types_dependency().maybe_specifier() {
- self.resolve_dependency(types, &specifier, file_referrer)
+ let specifier_kind = self.is_cjs_resolver.get_doc_module_kind(&doc);
+ self.resolve_dependency(types, &specifier, specifier_kind, file_referrer)
} else {
Some((doc.specifier().clone(), doc.media_type()))
}
@@ -1503,6 +1578,7 @@ fn parse_and_analyze_module(
maybe_headers: Option<&HashMap<String, String>>,
media_type: MediaType,
file_referrer: Option<&ModuleSpecifier>,
+ is_cjs_resolver: &LspIsCjsResolver,
resolver: &LspResolver,
) -> (Option<ParsedSourceResult>, Option<ModuleResult>) {
let parsed_source_result = parse_source(specifier.clone(), text, media_type);
@@ -1511,6 +1587,7 @@ fn parse_and_analyze_module(
&parsed_source_result,
maybe_headers,
file_referrer,
+ is_cjs_resolver,
resolver,
);
(Some(parsed_source_result), Some(module_result))
@@ -1536,11 +1613,26 @@ fn analyze_module(
parsed_source_result: &ParsedSourceResult,
maybe_headers: Option<&HashMap<String, String>>,
file_referrer: Option<&ModuleSpecifier>,
+ is_cjs_resolver: &LspIsCjsResolver,
resolver: &LspResolver,
) -> ModuleResult {
match parsed_source_result {
Ok(parsed_source) => {
let npm_resolver = resolver.create_graph_npm_resolver(file_referrer);
+ let cli_resolver = resolver.as_cli_resolver(file_referrer);
+ let config_data = resolver.as_config_data(file_referrer);
+ let valid_referrer = specifier.clone();
+ let jsx_import_source_config =
+ config_data.and_then(|d| d.maybe_jsx_import_source_config());
+ let resolver = SingleReferrerGraphResolver {
+ valid_referrer: &valid_referrer,
+ referrer_kind: is_cjs_resolver.get_lsp_referrer_kind(
+ &specifier,
+ Some(parsed_source.compute_is_script()),
+ ),
+ cli_resolver,
+ jsx_import_source_config: jsx_import_source_config.as_ref(),
+ };
Ok(deno_graph::parse_module_from_ast(
deno_graph::ParseModuleFromAstOptions {
graph_kind: deno_graph::GraphKind::TypesOnly,
@@ -1551,7 +1643,7 @@ fn analyze_module(
// dynamic imports like import(`./dir/${something}`) in the LSP
file_system: &deno_graph::source::NullFileSystem,
jsr_url_provider: &CliJsrUrlProvider,
- maybe_resolver: Some(resolver.as_graph_resolver(file_referrer)),
+ maybe_resolver: Some(&resolver),
maybe_npm_resolver: Some(&npm_resolver),
},
))
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index 2554fa34b..b2bd72416 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -22,6 +22,7 @@ use deno_semver::jsr::JsrPackageReqReference;
use indexmap::Equivalent;
use indexmap::IndexSet;
use log::error;
+use node_resolver::NodeModuleKind;
use serde::Deserialize;
use serde_json::from_value;
use std::collections::BTreeMap;
@@ -77,6 +78,7 @@ use super::parent_process_checker;
use super::performance::Performance;
use super::refactor;
use super::registries::ModuleRegistry;
+use super::resolver::LspIsCjsResolver;
use super::resolver::LspResolver;
use super::testing;
use super::text;
@@ -144,6 +146,7 @@ pub struct StateSnapshot {
pub project_version: usize,
pub assets: AssetsSnapshot,
pub config: Arc<Config>,
+ pub is_cjs_resolver: Arc<LspIsCjsResolver>,
pub documents: Arc<Documents>,
pub resolver: Arc<LspResolver>,
}
@@ -203,6 +206,7 @@ pub struct Inner {
pub documents: Documents,
http_client_provider: Arc<HttpClientProvider>,
initial_cwd: PathBuf,
+ pub is_cjs_resolver: Arc<LspIsCjsResolver>,
jsr_search_api: CliJsrSearchApi,
/// Handles module registries, which allow discovery of modules
module_registry: ModuleRegistry,
@@ -480,6 +484,7 @@ impl Inner {
let initial_cwd = std::env::current_dir().unwrap_or_else(|_| {
panic!("Could not resolve current working directory")
});
+ let is_cjs_resolver = Arc::new(LspIsCjsResolver::new(&cache));
Self {
assets,
@@ -491,6 +496,7 @@ impl Inner {
documents,
http_client_provider,
initial_cwd: initial_cwd.clone(),
+ is_cjs_resolver,
jsr_search_api,
project_version: 0,
task_queue: Default::default(),
@@ -601,6 +607,7 @@ impl Inner {
project_version: self.project_version,
assets: self.assets.snapshot(),
config: Arc::new(self.config.clone()),
+ is_cjs_resolver: self.is_cjs_resolver.clone(),
documents: Arc::new(self.documents.clone()),
resolver: self.resolver.snapshot(),
})
@@ -622,6 +629,7 @@ impl Inner {
}
});
self.cache = LspCache::new(global_cache_url);
+ self.is_cjs_resolver = Arc::new(LspIsCjsResolver::new(&self.cache));
let deno_dir = self.cache.deno_dir();
let workspace_settings = self.config.workspace_settings();
let maybe_root_path = self
@@ -982,7 +990,7 @@ impl Inner {
spawn(async move {
let specifier = {
let inner = ls.inner.read().await;
- let resolver = inner.resolver.as_graph_resolver(Some(&referrer));
+ let resolver = inner.resolver.as_cli_resolver(Some(&referrer));
let Ok(specifier) = resolver.resolve(
&specifier,
&deno_graph::Range {
@@ -990,6 +998,7 @@ impl Inner {
start: deno_graph::Position::zeroed(),
end: deno_graph::Position::zeroed(),
},
+ NodeModuleKind::Esm,
deno_graph::source::ResolutionMode::Types,
) else {
return;
@@ -1622,6 +1631,10 @@ impl Inner {
let file_diagnostics = self
.diagnostics_server
.get_ts_diagnostics(&specifier, asset_or_doc.document_lsp_version());
+ let specifier_kind = asset_or_doc
+ .document()
+ .map(|d| self.is_cjs_resolver.get_doc_module_kind(d))
+ .unwrap_or(NodeModuleKind::Esm);
let mut includes_no_cache = false;
for diagnostic in &fixable_diagnostics {
match diagnostic.source.as_deref() {
@@ -1660,7 +1673,13 @@ impl Inner {
.await;
for action in actions {
code_actions
- .add_ts_fix_action(&specifier, &action, diagnostic, self)
+ .add_ts_fix_action(
+ &specifier,
+ specifier_kind,
+ &action,
+ diagnostic,
+ self,
+ )
.map_err(|err| {
error!("Unable to convert fix: {:#}", err);
LspError::internal_error()
@@ -1806,10 +1825,9 @@ impl Inner {
error!("Unable to decode code action data: {:#}", err);
LspError::invalid_params("The CodeAction's data is invalid.")
})?;
- let scope = self
- .get_asset_or_document(&code_action_data.specifier)
- .ok()
- .and_then(|d| d.scope().cloned());
+ let maybe_asset_or_doc =
+ self.get_asset_or_document(&code_action_data.specifier).ok();
+ let scope = maybe_asset_or_doc.as_ref().and_then(|d| d.scope().cloned());
let combined_code_actions = self
.ts_server
.get_combined_code_fix(
@@ -1836,6 +1854,11 @@ impl Inner {
let changes = if code_action_data.fix_id == "fixMissingImport" {
fix_ts_import_changes(
&code_action_data.specifier,
+ maybe_asset_or_doc
+ .as_ref()
+ .and_then(|d| d.document())
+ .map(|d| self.is_cjs_resolver.get_doc_module_kind(d))
+ .unwrap_or(NodeModuleKind::Esm),
&combined_code_actions.changes,
self,
)
@@ -1889,6 +1912,10 @@ impl Inner {
if kind_suffix == ".rewrite.function.returnType" {
refactor_edit_info.edits = fix_ts_import_changes(
&action_data.specifier,
+ asset_or_doc
+ .document()
+ .map(|d| self.is_cjs_resolver.get_doc_module_kind(d))
+ .unwrap_or(NodeModuleKind::Esm),
&refactor_edit_info.edits,
self,
)
@@ -2238,6 +2265,7 @@ impl Inner {
&self.jsr_search_api,
&self.npm_search_api,
&self.documents,
+ &self.is_cjs_resolver,
self.resolver.as_ref(),
self
.config
diff --git a/cli/lsp/repl.rs b/cli/lsp/repl.rs
index fa5809045..b4aaa8cd0 100644
--- a/cli/lsp/repl.rs
+++ b/cli/lsp/repl.rs
@@ -263,7 +263,7 @@ impl ReplLanguageServer {
}
fn get_document_uri(&self) -> Uri {
- uri_parse_unencoded(self.cwd_uri.join("$deno$repl.ts").unwrap().as_str())
+ uri_parse_unencoded(self.cwd_uri.join("$deno$repl.mts").unwrap().as_str())
.unwrap()
}
}
diff --git a/cli/lsp/resolver.rs b/cli/lsp/resolver.rs
index f5df24d57..37f63b912 100644
--- a/cli/lsp/resolver.rs
+++ b/cli/lsp/resolver.rs
@@ -2,16 +2,18 @@
use dashmap::DashMap;
use deno_ast::MediaType;
-use deno_ast::ParsedSource;
use deno_cache_dir::npm::NpmCacheDir;
use deno_cache_dir::HttpCache;
+use deno_config::deno_json::JsxImportSourceConfig;
use deno_config::workspace::PackageJsonDepResolution;
use deno_config::workspace::WorkspaceResolver;
use deno_core::url::Url;
-use deno_graph::source::Resolver;
+use deno_graph::source::ResolutionMode;
use deno_graph::GraphImport;
use deno_graph::ModuleSpecifier;
+use deno_graph::Range;
use deno_npm::NpmSystemInfo;
+use deno_path_util::url_from_directory_path;
use deno_path_util::url_to_file_path;
use deno_runtime::deno_fs;
use deno_runtime::deno_node::NodeResolver;
@@ -24,6 +26,7 @@ use deno_semver::package::PackageReq;
use indexmap::IndexMap;
use node_resolver::errors::ClosestPkgJsonError;
use node_resolver::InNpmPackageChecker;
+use node_resolver::NodeModuleKind;
use node_resolver::NodeResolutionMode;
use std::borrow::Cow;
use std::collections::BTreeMap;
@@ -33,6 +36,7 @@ use std::collections::HashSet;
use std::sync::Arc;
use super::cache::LspCache;
+use super::documents::Document;
use super::jsr::JsrCacheResolver;
use crate::args::create_default_npmrc;
use crate::args::CacheSetting;
@@ -53,21 +57,20 @@ use crate::npm::CliNpmResolverCreateOptions;
use crate::npm::CliNpmResolverManagedSnapshotOption;
use crate::npm::CreateInNpmPkgCheckerOptions;
use crate::npm::ManagedCliNpmResolver;
-use crate::resolver::CjsTracker;
-use crate::resolver::CjsTrackerOptions;
use crate::resolver::CliDenoResolverFs;
-use crate::resolver::CliGraphResolver;
-use crate::resolver::CliGraphResolverOptions;
use crate::resolver::CliNodeResolver;
+use crate::resolver::CliResolver;
+use crate::resolver::CliResolverOptions;
+use crate::resolver::IsCjsResolver;
use crate::resolver::WorkerCliNpmGraphResolver;
use crate::tsc::into_specifier_and_media_type;
+use crate::util::fs::canonicalize_path_maybe_not_exists;
use crate::util::progress_bar::ProgressBar;
use crate::util::progress_bar::ProgressBarStyle;
#[derive(Debug, Clone)]
struct LspScopeResolver {
- cjs_tracker: Option<Arc<LspCjsTracker>>,
- graph_resolver: Arc<CliGraphResolver>,
+ resolver: Arc<CliResolver>,
jsr_resolver: Option<Arc<JsrCacheResolver>>,
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
node_resolver: Option<Arc<CliNodeResolver>>,
@@ -81,8 +84,7 @@ struct LspScopeResolver {
impl Default for LspScopeResolver {
fn default() -> Self {
Self {
- cjs_tracker: None,
- graph_resolver: create_graph_resolver(None, None, None),
+ resolver: create_cli_resolver(None, None, None),
jsr_resolver: None,
npm_resolver: None,
node_resolver: None,
@@ -103,7 +105,6 @@ impl LspScopeResolver {
) -> Self {
let mut npm_resolver = None;
let mut node_resolver = None;
- let mut lsp_cjs_tracker = None;
let fs = Arc::new(deno_fs::RealFs);
let pkg_json_resolver = Arc::new(PackageJsonResolver::new(
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
@@ -118,14 +119,7 @@ impl LspScopeResolver {
.await;
if let Some(npm_resolver) = &npm_resolver {
let in_npm_pkg_checker = create_in_npm_pkg_checker(npm_resolver);
- let cjs_tracker = create_cjs_tracker(
- in_npm_pkg_checker.clone(),
- pkg_json_resolver.clone(),
- );
- lsp_cjs_tracker =
- Some(Arc::new(LspCjsTracker::new(cjs_tracker.clone())));
node_resolver = Some(create_node_resolver(
- cjs_tracker,
fs.clone(),
in_npm_pkg_checker,
npm_resolver,
@@ -133,7 +127,7 @@ impl LspScopeResolver {
));
}
}
- let graph_resolver = create_graph_resolver(
+ let cli_resolver = create_cli_resolver(
config_data.map(|d| d.as_ref()),
npm_resolver.as_ref(),
node_resolver.as_ref(),
@@ -146,7 +140,9 @@ impl LspScopeResolver {
cache.for_specifier(config_data.map(|d| d.scope.as_ref())),
config_data.and_then(|d| d.lockfile.clone()),
)));
- let npm_graph_resolver = graph_resolver.create_graph_npm_resolver();
+ let npm_graph_resolver = cli_resolver.create_graph_npm_resolver();
+ let maybe_jsx_import_source_config =
+ config_data.and_then(|d| d.maybe_jsx_import_source_config());
let graph_imports = config_data
.and_then(|d| d.member_dir.workspace.to_compiler_option_types().ok())
.map(|imports| {
@@ -154,11 +150,18 @@ impl LspScopeResolver {
imports
.into_iter()
.map(|(referrer, imports)| {
+ let resolver = SingleReferrerGraphResolver {
+ valid_referrer: &referrer,
+ referrer_kind: NodeModuleKind::Esm,
+ cli_resolver: &cli_resolver,
+ jsx_import_source_config: maybe_jsx_import_source_config
+ .as_ref(),
+ };
let graph_import = GraphImport::new(
&referrer,
imports,
&CliJsrUrlProvider,
- Some(graph_resolver.as_ref()),
+ Some(&resolver),
Some(&npm_graph_resolver),
);
(referrer, graph_import)
@@ -182,6 +185,8 @@ impl LspScopeResolver {
.resolve_req_reference(
&req_ref,
&referrer,
+ // todo(dsherret): this is wrong because it doesn't consider CJS referrers
+ NodeModuleKind::Esm,
NodeResolutionMode::Types,
)
.ok()?,
@@ -195,8 +200,7 @@ impl LspScopeResolver {
let package_json_deps_by_resolution =
Arc::new(package_json_deps_by_resolution.unwrap_or_default());
Self {
- cjs_tracker: lsp_cjs_tracker,
- graph_resolver,
+ resolver: cli_resolver,
jsr_resolver,
npm_resolver,
node_resolver,
@@ -216,30 +220,22 @@ impl LspScopeResolver {
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
));
let mut node_resolver = None;
- let mut lsp_cjs_tracker = None;
if let Some(npm_resolver) = &npm_resolver {
let in_npm_pkg_checker = create_in_npm_pkg_checker(npm_resolver);
- let cjs_tracker = create_cjs_tracker(
- in_npm_pkg_checker.clone(),
- pkg_json_resolver.clone(),
- );
- lsp_cjs_tracker = Some(Arc::new(LspCjsTracker::new(cjs_tracker.clone())));
node_resolver = Some(create_node_resolver(
- cjs_tracker,
fs,
in_npm_pkg_checker,
npm_resolver,
pkg_json_resolver.clone(),
));
}
- let graph_resolver = create_graph_resolver(
+ let graph_resolver = create_cli_resolver(
self.config_data.as_deref(),
npm_resolver.as_ref(),
node_resolver.as_ref(),
);
Arc::new(Self {
- cjs_tracker: lsp_cjs_tracker,
- graph_resolver,
+ resolver: graph_resolver,
jsr_resolver: self.jsr_resolver.clone(),
npm_resolver,
node_resolver,
@@ -334,12 +330,12 @@ impl LspResolver {
}
}
- pub fn as_graph_resolver(
+ pub fn as_cli_resolver(
&self,
file_referrer: Option<&ModuleSpecifier>,
- ) -> &dyn Resolver {
+ ) -> &CliResolver {
let resolver = self.get_scope_resolver(file_referrer);
- resolver.graph_resolver.as_ref()
+ resolver.resolver.as_ref()
}
pub fn create_graph_npm_resolver(
@@ -347,15 +343,15 @@ impl LspResolver {
file_referrer: Option<&ModuleSpecifier>,
) -> WorkerCliNpmGraphResolver {
let resolver = self.get_scope_resolver(file_referrer);
- resolver.graph_resolver.create_graph_npm_resolver()
+ resolver.resolver.create_graph_npm_resolver()
}
- pub fn maybe_cjs_tracker(
+ pub fn as_config_data(
&self,
file_referrer: Option<&ModuleSpecifier>,
- ) -> Option<&Arc<LspCjsTracker>> {
+ ) -> Option<&Arc<ConfigData>> {
let resolver = self.get_scope_resolver(file_referrer);
- resolver.cjs_tracker.as_ref()
+ resolver.config_data.as_ref()
}
pub fn maybe_node_resolver(
@@ -429,13 +425,19 @@ impl LspResolver {
&self,
req_ref: &NpmPackageReqReference,
referrer: &ModuleSpecifier,
+ referrer_kind: NodeModuleKind,
file_referrer: Option<&ModuleSpecifier>,
) -> Option<(ModuleSpecifier, MediaType)> {
let resolver = self.get_scope_resolver(file_referrer);
let node_resolver = resolver.node_resolver.as_ref()?;
Some(into_specifier_and_media_type(Some(
node_resolver
- .resolve_req_reference(req_ref, referrer, NodeResolutionMode::Types)
+ .resolve_req_reference(
+ req_ref,
+ referrer,
+ referrer_kind,
+ NodeResolutionMode::Types,
+ )
.ok()?,
)))
}
@@ -478,6 +480,7 @@ impl LspResolver {
&self,
specifier_text: &str,
referrer: &ModuleSpecifier,
+ referrer_kind: NodeModuleKind,
) -> bool {
let resolver = self.get_scope_resolver(Some(referrer));
let Some(node_resolver) = resolver.node_resolver.as_ref() else {
@@ -487,6 +490,7 @@ impl LspResolver {
.resolve_if_for_npm_pkg(
specifier_text,
referrer,
+ referrer_kind,
NodeResolutionMode::Types,
)
.ok()
@@ -615,21 +619,6 @@ async fn create_npm_resolver(
Some(create_cli_npm_resolver_for_lsp(options).await)
}
-fn create_cjs_tracker(
- in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
- pkg_json_resolver: Arc<PackageJsonResolver>,
-) -> Arc<CjsTracker> {
- Arc::new(CjsTracker::new(
- in_npm_pkg_checker,
- pkg_json_resolver,
- CjsTrackerOptions {
- // todo(dsherret): support in the lsp by stabilizing the feature
- // so that we don't have to pipe the config in here
- unstable_detect_cjs: false,
- },
- ))
-}
-
fn create_in_npm_pkg_checker(
npm_resolver: &Arc<dyn CliNpmResolver>,
) -> Arc<dyn InNpmPackageChecker> {
@@ -649,7 +638,6 @@ fn create_in_npm_pkg_checker(
}
fn create_node_resolver(
- cjs_tracker: Arc<CjsTracker>,
fs: Arc<dyn deno_fs::FileSystem>,
in_npm_pkg_checker: Arc<dyn InNpmPackageChecker>,
npm_resolver: &Arc<dyn CliNpmResolver>,
@@ -662,7 +650,6 @@ fn create_node_resolver(
pkg_json_resolver.clone(),
));
Arc::new(CliNodeResolver::new(
- cjs_tracker.clone(),
fs,
in_npm_pkg_checker,
node_resolver_inner,
@@ -670,13 +657,12 @@ fn create_node_resolver(
))
}
-fn create_graph_resolver(
+fn create_cli_resolver(
config_data: Option<&ConfigData>,
npm_resolver: Option<&Arc<dyn CliNpmResolver>>,
node_resolver: Option<&Arc<CliNodeResolver>>,
-) -> Arc<CliGraphResolver> {
- let workspace = config_data.map(|d| &d.member_dir.workspace);
- Arc::new(CliGraphResolver::new(CliGraphResolverOptions {
+) -> Arc<CliResolver> {
+ Arc::new(CliResolver::new(CliResolverOptions {
node_resolver: node_resolver.cloned(),
npm_resolver: npm_resolver.cloned(),
workspace_resolver: config_data.map(|d| d.resolver.clone()).unwrap_or_else(
@@ -691,9 +677,6 @@ fn create_graph_resolver(
))
},
),
- maybe_jsx_import_source_config: workspace.and_then(|workspace| {
- workspace.to_maybe_jsx_import_source_config().ok().flatten()
- }),
maybe_vendor_dir: config_data.and_then(|d| d.vendor_dir.as_ref()),
bare_node_builtins_enabled: config_data
.is_some_and(|d| d.unstable.contains("bare-node-builtins")),
@@ -726,6 +709,141 @@ impl std::fmt::Debug for RedirectResolver {
}
}
+#[derive(Debug)]
+pub struct LspIsCjsResolver {
+ inner: IsCjsResolver,
+}
+
+impl Default for LspIsCjsResolver {
+ fn default() -> Self {
+ LspIsCjsResolver::new(&Default::default())
+ }
+}
+
+impl LspIsCjsResolver {
+ pub fn new(cache: &LspCache) -> Self {
+ #[derive(Debug)]
+ struct LspInNpmPackageChecker {
+ global_cache_dir: ModuleSpecifier,
+ }
+
+ impl LspInNpmPackageChecker {
+ pub fn new(cache: &LspCache) -> Self {
+ let npm_folder_path = cache.deno_dir().npm_folder_path();
+ Self {
+ global_cache_dir: url_from_directory_path(
+ &canonicalize_path_maybe_not_exists(&npm_folder_path)
+ .unwrap_or(npm_folder_path),
+ )
+ .unwrap_or_else(|_| {
+ ModuleSpecifier::parse("file:///invalid/").unwrap()
+ }),
+ }
+ }
+ }
+
+ impl InNpmPackageChecker for LspInNpmPackageChecker {
+ fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
+ if specifier.scheme() != "file" {
+ return false;
+ }
+ if specifier
+ .as_str()
+ .starts_with(self.global_cache_dir.as_str())
+ {
+ return true;
+ }
+ specifier.as_str().contains("/node_modules/")
+ }
+ }
+
+ let fs = Arc::new(deno_fs::RealFs);
+ let pkg_json_resolver = Arc::new(PackageJsonResolver::new(
+ deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
+ ));
+
+ LspIsCjsResolver {
+ inner: IsCjsResolver::new(
+ Arc::new(LspInNpmPackageChecker::new(cache)),
+ pkg_json_resolver,
+ crate::resolver::IsCjsResolverOptions {
+ detect_cjs: true,
+ is_node_main: false,
+ },
+ ),
+ }
+ }
+
+ pub fn get_maybe_doc_module_kind(
+ &self,
+ specifier: &ModuleSpecifier,
+ maybe_document: Option<&Document>,
+ ) -> NodeModuleKind {
+ self.get_lsp_referrer_kind(
+ specifier,
+ maybe_document.and_then(|d| d.is_script()),
+ )
+ }
+
+ pub fn get_doc_module_kind(&self, document: &Document) -> NodeModuleKind {
+ self.get_lsp_referrer_kind(document.specifier(), document.is_script())
+ }
+
+ pub fn get_lsp_referrer_kind(
+ &self,
+ specifier: &ModuleSpecifier,
+ is_script: Option<bool>,
+ ) -> NodeModuleKind {
+ self.inner.get_lsp_referrer_kind(specifier, is_script)
+ }
+}
+
+#[derive(Debug)]
+pub struct SingleReferrerGraphResolver<'a> {
+ pub valid_referrer: &'a ModuleSpecifier,
+ pub referrer_kind: NodeModuleKind,
+ pub cli_resolver: &'a CliResolver,
+ pub jsx_import_source_config: Option<&'a JsxImportSourceConfig>,
+}
+
+impl<'a> deno_graph::source::Resolver for SingleReferrerGraphResolver<'a> {
+ fn default_jsx_import_source(&self) -> Option<String> {
+ self
+ .jsx_import_source_config
+ .and_then(|c| c.default_specifier.clone())
+ }
+
+ fn default_jsx_import_source_types(&self) -> Option<String> {
+ self
+ .jsx_import_source_config
+ .and_then(|c| c.default_types_specifier.clone())
+ }
+
+ fn jsx_import_source_module(&self) -> &str {
+ self
+ .jsx_import_source_config
+ .map(|c| c.module.as_str())
+ .unwrap_or(deno_graph::source::DEFAULT_JSX_IMPORT_SOURCE_MODULE)
+ }
+
+ fn resolve(
+ &self,
+ specifier_text: &str,
+ referrer_range: &Range,
+ mode: ResolutionMode,
+ ) -> Result<ModuleSpecifier, deno_graph::source::ResolveError> {
+ // this resolver assumes it will only be used with a single referrer
+ // with the provided referrer kind
+ debug_assert_eq!(referrer_range.specifier, *self.valid_referrer);
+ self.cli_resolver.resolve(
+ specifier_text,
+ referrer_range,
+ self.referrer_kind,
+ mode,
+ )
+ }
+}
+
impl RedirectResolver {
fn new(
cache: Arc<dyn HttpCache>,
@@ -842,45 +960,6 @@ impl RedirectResolver {
}
}
-#[derive(Debug)]
-pub struct LspCjsTracker {
- cjs_tracker: Arc<CjsTracker>,
-}
-
-impl LspCjsTracker {
- pub fn new(cjs_tracker: Arc<CjsTracker>) -> Self {
- Self { cjs_tracker }
- }
-
- pub fn is_cjs(
- &self,
- specifier: &ModuleSpecifier,
- media_type: MediaType,
- maybe_parsed_source: Option<&ParsedSource>,
- ) -> bool {
- if let Some(module_kind) =
- self.cjs_tracker.get_known_kind(specifier, media_type)
- {
- module_kind.is_cjs()
- } else {
- let maybe_is_script = maybe_parsed_source.map(|p| p.compute_is_script());
- maybe_is_script
- .and_then(|is_script| {
- self
- .cjs_tracker
- .is_cjs_with_known_is_script(specifier, media_type, is_script)
- .ok()
- })
- .unwrap_or_else(|| {
- self
- .cjs_tracker
- .is_maybe_cjs(specifier, media_type)
- .unwrap_or(false)
- })
- }
- }
-}
-
#[cfg(test)]
mod tests {
use super::*;
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs
index 6f63ced5b..c9b24176a 100644
--- a/cli/lsp/tsc.rs
+++ b/cli/lsp/tsc.rs
@@ -69,6 +69,7 @@ use indexmap::IndexMap;
use indexmap::IndexSet;
use lazy_regex::lazy_regex;
use log::error;
+use node_resolver::NodeModuleKind;
use once_cell::sync::Lazy;
use regex::Captures;
use regex::Regex;
@@ -4401,25 +4402,15 @@ fn op_load<'s>(
None
} else {
let asset_or_document = state.get_asset_or_document(&specifier);
- asset_or_document.map(|doc| {
- let maybe_cjs_tracker = state
- .state_snapshot
- .resolver
- .maybe_cjs_tracker(Some(&specifier));
- LoadResponse {
- data: doc.text(),
- script_kind: crate::tsc::as_ts_script_kind(doc.media_type()),
- version: state.script_version(&specifier),
- is_cjs: maybe_cjs_tracker
- .map(|t| {
- t.is_cjs(
- &specifier,
- doc.media_type(),
- doc.maybe_parsed_source().and_then(|p| p.as_ref().ok()),
- )
- })
- .unwrap_or(false),
- }
+ asset_or_document.map(|doc| LoadResponse {
+ data: doc.text(),
+ script_kind: crate::tsc::as_ts_script_kind(doc.media_type()),
+ version: state.script_version(&specifier),
+ is_cjs: doc
+ .document()
+ .map(|d| state.state_snapshot.is_cjs_resolver.get_doc_module_kind(d))
+ .unwrap_or(NodeModuleKind::Esm)
+ == NodeModuleKind::Cjs,
})
};
@@ -4662,6 +4653,10 @@ fn op_script_names(state: &mut OpState) -> ScriptNames {
let (types, _) = documents.resolve_dependency(
types,
specifier,
+ state
+ .state_snapshot
+ .is_cjs_resolver
+ .get_doc_module_kind(doc),
doc.file_referrer(),
)?;
let types_doc = documents.get_or_load(&types, doc.file_referrer())?;
@@ -5544,6 +5539,7 @@ mod tests {
documents: Arc::new(documents),
assets: Default::default(),
config: Arc::new(config),
+ is_cjs_resolver: Default::default(),
resolver,
});
let performance = Arc::new(Performance::default());