summaryrefslogtreecommitdiff
path: root/cli/lsp
diff options
context:
space:
mode:
authorDavid Sherret <dsherret@users.noreply.github.com>2024-11-01 12:27:00 -0400
committerGitHub <noreply@github.com>2024-11-01 12:27:00 -0400
commit826e42a5b5880c974ae019a7a21aade6a718062c (patch)
treea46502ecc3c73e4f7fc3a4517d83c7b2f3d0c0d3 /cli/lsp
parent4774eab64d5176e997b6431f03f075782321b3d9 (diff)
fix: improved support for cjs and cts modules (#26558)
* cts support * better cjs/cts type checking * deno compile cjs/cts support * More efficient detect cjs (going towards stabilization) * Determination of whether .js, .ts, .jsx, or .tsx is cjs or esm is only done after loading * Support `import x = require(...);` Co-authored-by: Bartek IwaƄczuk <biwanczuk@gmail.com>
Diffstat (limited to 'cli/lsp')
-rw-r--r--cli/lsp/analysis.rs21
-rw-r--r--cli/lsp/code_lens.rs4
-rw-r--r--cli/lsp/config.rs2
-rw-r--r--cli/lsp/documents.rs20
-rw-r--r--cli/lsp/language_server.rs2
-rw-r--r--cli/lsp/resolver.rs228
-rw-r--r--cli/lsp/testing/collectors.rs2
-rw-r--r--cli/lsp/tsc.rs27
8 files changed, 220 insertions, 86 deletions
diff --git a/cli/lsp/analysis.rs b/cli/lsp/analysis.rs
index 39f1ae648..0769c9047 100644
--- a/cli/lsp/analysis.rs
+++ b/cli/lsp/analysis.rs
@@ -36,7 +36,6 @@ use deno_semver::package::PackageReq;
use deno_semver::package::PackageReqReference;
use deno_semver::Version;
use import_map::ImportMap;
-use node_resolver::NpmResolver;
use once_cell::sync::Lazy;
use regex::Regex;
use std::borrow::Cow;
@@ -336,7 +335,12 @@ impl<'a> TsResponseImportMapper<'a> {
.resolver
.maybe_managed_npm_resolver(Some(&self.file_referrer))
{
- if npm_resolver.in_npm_package(specifier) {
+ let in_npm_pkg = self
+ .resolver
+ .maybe_node_resolver(Some(&self.file_referrer))
+ .map(|n| n.in_npm_package(specifier))
+ .unwrap_or(false);
+ if in_npm_pkg {
if let Ok(Some(pkg_id)) =
npm_resolver.resolve_pkg_id_from_specifier(specifier)
{
@@ -1199,14 +1203,11 @@ impl CodeActionCollection {
}),
);
- match parsed_source.program_ref() {
- deno_ast::swc::ast::Program::Module(module) => module
- .body
- .iter()
- .find(|i| i.range().contains(&specifier_range))
- .map(|i| text_info.line_and_column_index(i.range().start)),
- deno_ast::swc::ast::Program::Script(_) => None,
- }
+ parsed_source
+ .program_ref()
+ .body()
+ .find(|i| i.range().contains(&specifier_range))
+ .map(|i| text_info.line_and_column_index(i.range().start))
}
async fn deno_types_for_npm_action(
diff --git a/cli/lsp/code_lens.rs b/cli/lsp/code_lens.rs
index e117888fb..a57ca3ac9 100644
--- a/cli/lsp/code_lens.rs
+++ b/cli/lsp/code_lens.rs
@@ -421,7 +421,7 @@ pub fn collect_test(
) -> Result<Vec<lsp::CodeLens>, AnyError> {
let mut collector =
DenoTestCollector::new(specifier.clone(), parsed_source.clone());
- parsed_source.module().visit_with(&mut collector);
+ parsed_source.program().visit_with(&mut collector);
Ok(collector.take())
}
@@ -581,7 +581,7 @@ mod tests {
.unwrap();
let mut collector =
DenoTestCollector::new(specifier, parsed_module.clone());
- parsed_module.module().visit_with(&mut collector);
+ parsed_module.program().visit_with(&mut collector);
assert_eq!(
collector.take(),
vec![
diff --git a/cli/lsp/config.rs b/cli/lsp/config.rs
index cac0637a0..34bf64446 100644
--- a/cli/lsp/config.rs
+++ b/cli/lsp/config.rs
@@ -985,7 +985,7 @@ impl Config {
| MediaType::Tsx => Some(&workspace_settings.typescript),
MediaType::Json
| MediaType::Wasm
- | MediaType::TsBuildInfo
+ | MediaType::Css
| MediaType::SourceMap
| MediaType::Unknown => None,
}
diff --git a/cli/lsp/documents.rs b/cli/lsp/documents.rs
index 7d1ca6810..8609aed05 100644
--- a/cli/lsp/documents.rs
+++ b/cli/lsp/documents.rs
@@ -272,7 +272,7 @@ fn get_maybe_test_module_fut(
parsed_source.specifier().clone(),
parsed_source.text_info_lazy().clone(),
);
- parsed_source.module().visit_with(&mut collector);
+ parsed_source.program().visit_with(&mut collector);
Arc::new(collector.take())
})
.map(Result::ok)
@@ -332,12 +332,8 @@ impl Document {
.filter(|s| cache.is_valid_file_referrer(s))
.cloned()
.or(file_referrer);
- let media_type = resolve_media_type(
- &specifier,
- maybe_headers.as_ref(),
- maybe_language_id,
- &resolver,
- );
+ let media_type =
+ resolve_media_type(&specifier, maybe_headers.as_ref(), maybe_language_id);
let (maybe_parsed_source, maybe_module) =
if media_type_is_diagnosable(media_type) {
parse_and_analyze_module(
@@ -399,7 +395,6 @@ impl Document {
&self.specifier,
self.maybe_headers.as_ref(),
self.maybe_language_id,
- &resolver,
);
let dependencies;
let maybe_types_dependency;
@@ -764,14 +759,7 @@ fn resolve_media_type(
specifier: &ModuleSpecifier,
maybe_headers: Option<&HashMap<String, String>>,
maybe_language_id: Option<LanguageId>,
- resolver: &LspResolver,
) -> MediaType {
- if resolver.in_node_modules(specifier) {
- if let Some(media_type) = resolver.node_media_type(specifier) {
- return media_type;
- }
- }
-
if let Some(language_id) = maybe_language_id {
return MediaType::from_specifier_and_content_type(
specifier,
@@ -1561,7 +1549,7 @@ fn parse_source(
text: Arc<str>,
media_type: MediaType,
) -> ParsedSourceResult {
- deno_ast::parse_module(deno_ast::ParseParams {
+ deno_ast::parse_program(deno_ast::ParseParams {
specifier,
text,
media_type,
diff --git a/cli/lsp/language_server.rs b/cli/lsp/language_server.rs
index a592245ce..4fa0e3afb 100644
--- a/cli/lsp/language_server.rs
+++ b/cli/lsp/language_server.rs
@@ -904,7 +904,7 @@ impl Inner {
| MediaType::Tsx => {}
MediaType::Wasm
| MediaType::SourceMap
- | MediaType::TsBuildInfo
+ | MediaType::Css
| MediaType::Unknown => {
if path.extension().and_then(|s| s.to_str()) != Some("jsonc") {
continue;
diff --git a/cli/lsp/resolver.rs b/cli/lsp/resolver.rs
index 00587f8f5..9ce76005e 100644
--- a/cli/lsp/resolver.rs
+++ b/cli/lsp/resolver.rs
@@ -2,6 +2,8 @@
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::workspace::PackageJsonDepResolution;
use deno_config::workspace::WorkspaceResolver;
@@ -14,15 +16,15 @@ use deno_path_util::url_to_file_path;
use deno_runtime::deno_fs;
use deno_runtime::deno_node::NodeResolver;
use deno_runtime::deno_node::PackageJson;
+use deno_runtime::deno_node::PackageJsonResolver;
use deno_semver::jsr::JsrPackageReqReference;
use deno_semver::npm::NpmPackageReqReference;
use deno_semver::package::PackageNv;
use deno_semver::package::PackageReq;
use indexmap::IndexMap;
use node_resolver::errors::ClosestPkgJsonError;
-use node_resolver::NodeResolution;
+use node_resolver::InNpmPackageChecker;
use node_resolver::NodeResolutionMode;
-use node_resolver::NpmResolver;
use std::borrow::Cow;
use std::collections::BTreeMap;
use std::collections::BTreeSet;
@@ -36,6 +38,7 @@ use crate::args::create_default_npmrc;
use crate::args::CacheSetting;
use crate::args::CliLockfile;
use crate::args::NpmInstallDepsProvider;
+use crate::cache::DenoCacheEnvFsAdapter;
use crate::graph_util::CliJsrUrlProvider;
use crate::http_util::HttpClientProvider;
use crate::lsp::config::Config;
@@ -43,26 +46,32 @@ use crate::lsp::config::ConfigData;
use crate::lsp::logging::lsp_warn;
use crate::npm::create_cli_npm_resolver_for_lsp;
use crate::npm::CliByonmNpmResolverCreateOptions;
+use crate::npm::CliManagedInNpmPkgCheckerCreateOptions;
+use crate::npm::CliManagedNpmResolverCreateOptions;
use crate::npm::CliNpmResolver;
use crate::npm::CliNpmResolverCreateOptions;
-use crate::npm::CliNpmResolverManagedCreateOptions;
use crate::npm::CliNpmResolverManagedSnapshotOption;
+use crate::npm::CreateInNpmPkgCheckerOptions;
use crate::npm::ManagedCliNpmResolver;
-use crate::resolver::CjsResolutionStore;
+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::WorkerCliNpmGraphResolver;
+use crate::tsc::into_specifier_and_media_type;
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>,
jsr_resolver: Option<Arc<JsrCacheResolver>>,
npm_resolver: Option<Arc<dyn CliNpmResolver>>,
node_resolver: Option<Arc<CliNodeResolver>>,
+ pkg_json_resolver: Option<Arc<PackageJsonResolver>>,
redirect_resolver: Option<Arc<RedirectResolver>>,
graph_imports: Arc<IndexMap<ModuleSpecifier, GraphImport>>,
config_data: Option<Arc<ConfigData>>,
@@ -71,10 +80,12 @@ struct LspScopeResolver {
impl Default for LspScopeResolver {
fn default() -> Self {
Self {
+ cjs_tracker: None,
graph_resolver: create_graph_resolver(None, None, None),
jsr_resolver: None,
npm_resolver: None,
node_resolver: None,
+ pkg_json_resolver: None,
redirect_resolver: None,
graph_imports: Default::default(),
config_data: None,
@@ -90,14 +101,35 @@ 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()),
+ ));
if let Some(http_client) = http_client_provider {
npm_resolver = create_npm_resolver(
config_data.map(|d| d.as_ref()),
cache,
http_client,
+ &pkg_json_resolver,
)
.await;
- node_resolver = create_node_resolver(npm_resolver.as_ref());
+ 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,
+ pkg_json_resolver.clone(),
+ ));
+ }
}
let graph_resolver = create_graph_resolver(
config_data.map(|d| d.as_ref()),
@@ -134,10 +166,12 @@ impl LspScopeResolver {
})
.unwrap_or_default();
Self {
+ cjs_tracker: lsp_cjs_tracker,
graph_resolver,
jsr_resolver,
npm_resolver,
node_resolver,
+ pkg_json_resolver: Some(pkg_json_resolver),
redirect_resolver,
graph_imports,
config_data: config_data.cloned(),
@@ -147,18 +181,40 @@ impl LspScopeResolver {
fn snapshot(&self) -> Arc<Self> {
let npm_resolver =
self.npm_resolver.as_ref().map(|r| r.clone_snapshotted());
- let node_resolver = create_node_resolver(npm_resolver.as_ref());
+ let fs = Arc::new(deno_fs::RealFs);
+ let pkg_json_resolver = Arc::new(PackageJsonResolver::new(
+ 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(
self.config_data.as_deref(),
npm_resolver.as_ref(),
node_resolver.as_ref(),
);
Arc::new(Self {
+ cjs_tracker: lsp_cjs_tracker,
graph_resolver,
jsr_resolver: self.jsr_resolver.clone(),
npm_resolver,
node_resolver,
redirect_resolver: self.redirect_resolver.clone(),
+ pkg_json_resolver: Some(pkg_json_resolver),
graph_imports: self.graph_imports.clone(),
config_data: self.config_data.clone(),
})
@@ -261,6 +317,22 @@ impl LspResolver {
resolver.graph_resolver.create_graph_npm_resolver()
}
+ pub fn maybe_cjs_tracker(
+ &self,
+ file_referrer: Option<&ModuleSpecifier>,
+ ) -> Option<&Arc<LspCjsTracker>> {
+ let resolver = self.get_scope_resolver(file_referrer);
+ resolver.cjs_tracker.as_ref()
+ }
+
+ pub fn maybe_node_resolver(
+ &self,
+ file_referrer: Option<&ModuleSpecifier>,
+ ) -> Option<&Arc<CliNodeResolver>> {
+ let resolver = self.get_scope_resolver(file_referrer);
+ resolver.node_resolver.as_ref()
+ }
+
pub fn maybe_managed_npm_resolver(
&self,
file_referrer: Option<&ModuleSpecifier>,
@@ -328,7 +400,7 @@ impl LspResolver {
) -> Option<(ModuleSpecifier, MediaType)> {
let resolver = self.get_scope_resolver(file_referrer);
let node_resolver = resolver.node_resolver.as_ref()?;
- Some(NodeResolution::into_specifier_and_media_type(Some(
+ Some(into_specifier_and_media_type(Some(
node_resolver
.resolve_req_reference(req_ref, referrer, NodeResolutionMode::Types)
.ok()?,
@@ -346,14 +418,10 @@ impl LspResolver {
.contains("/node_modules/")
}
- let global_npm_resolver = self
- .get_scope_resolver(Some(specifier))
- .npm_resolver
- .as_ref()
- .and_then(|npm_resolver| npm_resolver.as_managed())
- .filter(|r| r.root_node_modules_path().is_none());
- if let Some(npm_resolver) = &global_npm_resolver {
- if npm_resolver.in_npm_package(specifier) {
+ if let Some(node_resolver) =
+ &self.get_scope_resolver(Some(specifier)).node_resolver
+ {
+ if node_resolver.in_npm_package(specifier) {
return true;
}
}
@@ -361,18 +429,6 @@ impl LspResolver {
has_node_modules_dir(specifier)
}
- pub fn node_media_type(
- &self,
- specifier: &ModuleSpecifier,
- ) -> Option<MediaType> {
- let resolver = self.get_scope_resolver(Some(specifier));
- let node_resolver = resolver.node_resolver.as_ref()?;
- let resolution = node_resolver
- .url_to_node_resolution(specifier.clone())
- .ok()?;
- Some(NodeResolution::into_specifier_and_media_type(Some(resolution)).1)
- }
-
pub fn is_bare_package_json_dep(
&self,
specifier_text: &str,
@@ -398,10 +454,10 @@ impl LspResolver {
referrer: &ModuleSpecifier,
) -> Result<Option<Arc<PackageJson>>, ClosestPkgJsonError> {
let resolver = self.get_scope_resolver(Some(referrer));
- let Some(node_resolver) = resolver.node_resolver.as_ref() else {
+ let Some(pkg_json_resolver) = resolver.pkg_json_resolver.as_ref() else {
return Ok(None);
};
- node_resolver.get_closest_package_json(referrer)
+ pkg_json_resolver.get_closest_package_json(referrer)
}
pub fn resolve_redirects(
@@ -457,11 +513,13 @@ async fn create_npm_resolver(
config_data: Option<&ConfigData>,
cache: &LspCache,
http_client_provider: &Arc<HttpClientProvider>,
+ pkg_json_resolver: &Arc<PackageJsonResolver>,
) -> Option<Arc<dyn CliNpmResolver>> {
let enable_byonm = config_data.map(|d| d.byonm).unwrap_or(false);
let options = if enable_byonm {
CliNpmResolverCreateOptions::Byonm(CliByonmNpmResolverCreateOptions {
fs: CliDenoResolverFs(Arc::new(deno_fs::RealFs)),
+ pkg_json_resolver: pkg_json_resolver.clone(),
root_node_modules_dir: config_data.and_then(|config_data| {
config_data.node_modules_dir.clone().or_else(|| {
url_to_file_path(&config_data.scope)
@@ -471,7 +529,15 @@ async fn create_npm_resolver(
}),
})
} else {
- CliNpmResolverCreateOptions::Managed(CliNpmResolverManagedCreateOptions {
+ let npmrc = config_data
+ .and_then(|d| d.npmrc.clone())
+ .unwrap_or_else(create_default_npmrc);
+ let npm_cache_dir = Arc::new(NpmCacheDir::new(
+ &DenoCacheEnvFsAdapter(&deno_fs::RealFs),
+ cache.deno_dir().npm_folder_path(),
+ npmrc.get_all_known_registries_urls(),
+ ));
+ CliNpmResolverCreateOptions::Managed(CliManagedNpmResolverCreateOptions {
http_client_provider: http_client_provider.clone(),
snapshot: match config_data.and_then(|d| d.lockfile.as_ref()) {
Some(lockfile) => {
@@ -485,7 +551,7 @@ async fn create_npm_resolver(
// updating it. Only the cache request should update the lockfile.
maybe_lockfile: None,
fs: Arc::new(deno_fs::RealFs),
- npm_global_cache_dir: cache.deno_dir().npm_folder_path(),
+ npm_cache_dir,
// Use an "only" cache setting in order to make the
// user do an explicit "cache" command and prevent
// the cache from being filled with lots of packages while
@@ -496,9 +562,7 @@ async fn create_npm_resolver(
.and_then(|d| d.node_modules_dir.clone()),
// only used for top level install, so we can ignore this
npm_install_deps_provider: Arc::new(NpmInstallDepsProvider::empty()),
- npmrc: config_data
- .and_then(|d| d.npmrc.clone())
- .unwrap_or_else(create_default_npmrc),
+ npmrc,
npm_system_info: NpmSystemInfo::default(),
lifecycle_scripts: Default::default(),
})
@@ -506,28 +570,59 @@ async fn create_npm_resolver(
Some(create_cli_npm_resolver_for_lsp(options).await)
}
-fn create_node_resolver(
- npm_resolver: Option<&Arc<dyn CliNpmResolver>>,
-) -> Option<Arc<CliNodeResolver>> {
- use once_cell::sync::Lazy;
+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,
+ },
+ ))
+}
- // it's not ideal to share this across all scopes and to
- // never clear it, but it's fine for the time being
- static CJS_RESOLUTIONS: Lazy<Arc<CjsResolutionStore>> =
- Lazy::new(Default::default);
+fn create_in_npm_pkg_checker(
+ npm_resolver: &Arc<dyn CliNpmResolver>,
+) -> Arc<dyn InNpmPackageChecker> {
+ crate::npm::create_in_npm_pkg_checker(match npm_resolver.as_inner() {
+ crate::npm::InnerCliNpmResolverRef::Byonm(_) => {
+ CreateInNpmPkgCheckerOptions::Byonm
+ }
+ crate::npm::InnerCliNpmResolverRef::Managed(m) => {
+ CreateInNpmPkgCheckerOptions::Managed(
+ CliManagedInNpmPkgCheckerCreateOptions {
+ root_cache_dir_url: m.global_cache_root_url(),
+ maybe_node_modules_path: m.maybe_node_modules_path(),
+ },
+ )
+ }
+ })
+}
- let npm_resolver = npm_resolver?;
- let fs = Arc::new(deno_fs::RealFs);
+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>,
+ pkg_json_resolver: Arc<PackageJsonResolver>,
+) -> Arc<CliNodeResolver> {
let node_resolver_inner = Arc::new(NodeResolver::new(
deno_runtime::deno_node::DenoFsNodeResolverEnv::new(fs.clone()),
+ in_npm_pkg_checker.clone(),
npm_resolver.clone().into_npm_resolver(),
+ pkg_json_resolver.clone(),
));
- Some(Arc::new(CliNodeResolver::new(
- CJS_RESOLUTIONS.clone(),
+ Arc::new(CliNodeResolver::new(
+ cjs_tracker.clone(),
fs,
+ in_npm_pkg_checker,
node_resolver_inner,
npm_resolver.clone(),
- )))
+ ))
}
fn create_graph_resolver(
@@ -702,6 +797,45 @@ 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/testing/collectors.rs b/cli/lsp/testing/collectors.rs
index 2f2ddb877..2dd7ec0d9 100644
--- a/cli/lsp/testing/collectors.rs
+++ b/cli/lsp/testing/collectors.rs
@@ -650,7 +650,7 @@ pub mod tests {
.unwrap();
let text_info = parsed_module.text_info_lazy().clone();
let mut collector = TestCollector::new(specifier, text_info);
- parsed_module.module().visit_with(&mut collector);
+ parsed_module.program().visit_with(&mut collector);
collector.take()
}
diff --git a/cli/lsp/tsc.rs b/cli/lsp/tsc.rs
index 0f31d7dd3..5fcdb3575 100644
--- a/cli/lsp/tsc.rs
+++ b/cli/lsp/tsc.rs
@@ -4362,14 +4362,25 @@ fn op_load<'s>(
None
} else {
let asset_or_document = state.get_asset_or_document(&specifier);
- 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: matches!(
- doc.media_type(),
- MediaType::Cjs | MediaType::Cts | MediaType::Dcts
- ),
+ 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),
+ }
})
};