mirror of
https://github.com/denoland/deno.git
synced 2024-11-28 16:20:57 -05:00
refactor(lsp): reuse CliGraphResolverOptions::sloppy_imports_resolver (#23764)
This commit is contained in:
parent
03a76f33ad
commit
88529f0b47
8 changed files with 119 additions and 322 deletions
|
@ -65,7 +65,7 @@ pub struct GraphValidOptions {
|
|||
/// for the CLI.
|
||||
pub fn graph_valid(
|
||||
graph: &ModuleGraph,
|
||||
fs: &dyn FileSystem,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
roots: &[ModuleSpecifier],
|
||||
options: GraphValidOptions,
|
||||
) -> Result<(), AnyError> {
|
||||
|
@ -99,7 +99,7 @@ pub fn graph_valid(
|
|||
)
|
||||
}
|
||||
ModuleGraphError::ModuleError(e) => {
|
||||
enhanced_module_error_message(fs, e)
|
||||
enhanced_module_error_message(fs.clone(), e)
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -661,7 +661,7 @@ impl ModuleGraphBuilder {
|
|||
) -> Result<(), AnyError> {
|
||||
graph_valid(
|
||||
graph,
|
||||
self.fs.as_ref(),
|
||||
self.fs.clone(),
|
||||
roots,
|
||||
GraphValidOptions {
|
||||
is_vendoring: false,
|
||||
|
@ -705,14 +705,13 @@ pub fn enhanced_resolution_error_message(error: &ResolutionError) -> String {
|
|||
}
|
||||
|
||||
pub fn enhanced_module_error_message(
|
||||
fs: &dyn FileSystem,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
error: &ModuleError,
|
||||
) -> String {
|
||||
let additional_message = match error {
|
||||
ModuleError::LoadingErr(specifier, _, _) // ex. "Is a directory" error
|
||||
| ModuleError::Missing(specifier, _) => {
|
||||
SloppyImportsResolver::resolve_with_fs(
|
||||
fs,
|
||||
SloppyImportsResolver::new(fs).resolve(
|
||||
specifier,
|
||||
ResolutionMode::Execution,
|
||||
)
|
||||
|
|
|
@ -800,7 +800,7 @@ fn generate_lint_diagnostics(
|
|||
break;
|
||||
}
|
||||
// ignore any npm package files
|
||||
if snapshot.resolver.in_npm_package(specifier) {
|
||||
if snapshot.resolver.in_node_modules(specifier) {
|
||||
continue;
|
||||
}
|
||||
let version = document.maybe_lsp_version();
|
||||
|
@ -1231,7 +1231,7 @@ impl DenoDiagnostic {
|
|||
Self::NoCacheJsr(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing jsr package: {}", pkg_req), Some(json!({ "specifier": specifier }))),
|
||||
Self::NoCacheNpm(pkg_req, specifier) => (lsp::DiagnosticSeverity::ERROR, format!("Uncached or missing npm package: {}", pkg_req), Some(json!({ "specifier": specifier }))),
|
||||
Self::NoLocal(specifier) => {
|
||||
let sloppy_resolution = SloppyImportsResolver::resolve_with_fs(&deno_fs::RealFs, specifier, ResolutionMode::Execution);
|
||||
let sloppy_resolution = SloppyImportsResolver::new(Arc::new(deno_fs::RealFs)).resolve(specifier, ResolutionMode::Execution);
|
||||
let data = sloppy_resolution.as_lsp_quick_fix_message().map(|message| {
|
||||
json!({
|
||||
"specifier": specifier,
|
||||
|
@ -1434,7 +1434,7 @@ fn diagnose_dependency(
|
|||
dependency_key: &str,
|
||||
dependency: &deno_graph::Dependency,
|
||||
) {
|
||||
if snapshot.resolver.in_npm_package(referrer) {
|
||||
if snapshot.resolver.in_node_modules(referrer) {
|
||||
return; // ignore, surface typescript errors instead
|
||||
}
|
||||
|
||||
|
|
|
@ -12,8 +12,6 @@ use super::tsc;
|
|||
use super::tsc::AssetDocument;
|
||||
|
||||
use crate::graph_util::CliJsrUrlProvider;
|
||||
use crate::lsp::logging::lsp_warn;
|
||||
use deno_graph::source::Resolver;
|
||||
use deno_runtime::fs_util::specifier_to_file_path;
|
||||
|
||||
use dashmap::DashMap;
|
||||
|
@ -31,7 +29,6 @@ use deno_core::ModuleSpecifier;
|
|||
use deno_graph::source::ResolutionMode;
|
||||
use deno_graph::Resolution;
|
||||
use deno_runtime::deno_node;
|
||||
use deno_runtime::deno_node::NodeResolution;
|
||||
use deno_runtime::deno_node::NodeResolutionMode;
|
||||
use deno_semver::jsr::JsrPackageReqReference;
|
||||
use deno_semver::npm::NpmPackageReqReference;
|
||||
|
@ -388,7 +385,7 @@ impl Document {
|
|||
d.with_new_resolver(
|
||||
s,
|
||||
&CliJsrUrlProvider,
|
||||
Some(&graph_resolver),
|
||||
Some(graph_resolver),
|
||||
Some(npm_resolver),
|
||||
),
|
||||
)
|
||||
|
@ -398,7 +395,7 @@ impl Document {
|
|||
maybe_types_dependency = self.maybe_types_dependency.as_ref().map(|d| {
|
||||
Arc::new(d.with_new_resolver(
|
||||
&CliJsrUrlProvider,
|
||||
Some(&graph_resolver),
|
||||
Some(graph_resolver),
|
||||
Some(npm_resolver),
|
||||
))
|
||||
});
|
||||
|
@ -663,17 +660,9 @@ fn resolve_media_type(
|
|||
maybe_language_id: Option<LanguageId>,
|
||||
resolver: &LspResolver,
|
||||
) -> MediaType {
|
||||
if resolver.in_npm_package(specifier) {
|
||||
match resolver.url_to_node_resolution(specifier.clone()) {
|
||||
Ok(Some(resolution)) => {
|
||||
let (_, media_type) =
|
||||
NodeResolution::into_specifier_and_media_type(Some(resolution));
|
||||
return media_type;
|
||||
}
|
||||
Err(err) => {
|
||||
lsp_warn!("Node resolution failed for '{}': {}", specifier, err);
|
||||
}
|
||||
_ => {}
|
||||
if resolver.in_node_modules(specifier) {
|
||||
if let Some(media_type) = resolver.node_media_type(specifier) {
|
||||
return media_type;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -979,7 +968,7 @@ impl Documents {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn resolve_specifier(
|
||||
pub fn resolve_document_specifier(
|
||||
&self,
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Option<ModuleSpecifier> {
|
||||
|
@ -998,7 +987,7 @@ impl Documents {
|
|||
|
||||
/// Return `true` if the specifier can be resolved to a document.
|
||||
pub fn exists(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
let specifier = self.resolve_specifier(specifier);
|
||||
let specifier = self.resolve_document_specifier(specifier);
|
||||
if let Some(specifier) = specifier {
|
||||
if self.open_docs.contains_key(&specifier) {
|
||||
return true;
|
||||
|
@ -1035,7 +1024,7 @@ impl Documents {
|
|||
&self,
|
||||
original_specifier: &ModuleSpecifier,
|
||||
) -> Option<Arc<Document>> {
|
||||
let specifier = self.resolve_specifier(original_specifier)?;
|
||||
let specifier = self.resolve_document_specifier(original_specifier)?;
|
||||
if let Some(document) = self.open_docs.get(&specifier) {
|
||||
Some(document.clone())
|
||||
} else {
|
||||
|
@ -1048,13 +1037,6 @@ impl Documents {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn is_open(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
let Some(specifier) = self.resolve_specifier(specifier) else {
|
||||
return false;
|
||||
};
|
||||
self.open_docs.contains_key(&specifier)
|
||||
}
|
||||
|
||||
/// Return a collection of documents that are contained in the document store
|
||||
/// based on the provided filter.
|
||||
pub fn documents(&self, filter: DocumentsFilter) -> Vec<Arc<Document>> {
|
||||
|
@ -1108,17 +1090,6 @@ impl Documents {
|
|||
let dependencies = document.as_ref().map(|d| d.dependencies());
|
||||
let mut results = Vec::new();
|
||||
for specifier in specifiers {
|
||||
if self.resolver.in_npm_package(referrer) {
|
||||
// we're in an npm package, so use node resolution
|
||||
results.push(Some(NodeResolution::into_specifier_and_media_type(
|
||||
self
|
||||
.resolver
|
||||
.node_resolve(specifier, referrer, NodeResolutionMode::Types)
|
||||
.ok()
|
||||
.flatten(),
|
||||
)));
|
||||
continue;
|
||||
}
|
||||
if specifier.starts_with("asset:") {
|
||||
if let Ok(specifier) = ModuleSpecifier::parse(specifier) {
|
||||
let media_type = MediaType::from_specifier(&specifier);
|
||||
|
@ -1136,20 +1107,6 @@ impl Documents {
|
|||
} else {
|
||||
results.push(None);
|
||||
}
|
||||
} else if let Some(specifier) = self
|
||||
.resolver
|
||||
.resolve_graph_import(specifier)
|
||||
.and_then(|r| r.maybe_specifier())
|
||||
{
|
||||
results.push(self.resolve_dependency(specifier, referrer));
|
||||
} else if let Ok(npm_req_ref) =
|
||||
NpmPackageReqReference::from_str(specifier)
|
||||
{
|
||||
results.push(node_resolve_npm_req_ref(
|
||||
&npm_req_ref,
|
||||
referrer,
|
||||
&self.resolver,
|
||||
));
|
||||
} else if let Ok(specifier) = self.resolver.as_graph_resolver().resolve(
|
||||
specifier,
|
||||
&deno_graph::Range {
|
||||
|
@ -1314,7 +1271,11 @@ impl Documents {
|
|||
}
|
||||
|
||||
if let Ok(npm_ref) = NpmPackageReqReference::from_specifier(specifier) {
|
||||
return node_resolve_npm_req_ref(&npm_ref, referrer, &self.resolver);
|
||||
return self.resolver.npm_to_file_url(
|
||||
&npm_ref,
|
||||
referrer,
|
||||
NodeResolutionMode::Types,
|
||||
);
|
||||
}
|
||||
let Some(doc) = self.get(specifier) else {
|
||||
return Some((specifier.clone(), MediaType::from_specifier(specifier)));
|
||||
|
@ -1328,23 +1289,6 @@ impl Documents {
|
|||
}
|
||||
}
|
||||
|
||||
fn node_resolve_npm_req_ref(
|
||||
npm_req_ref: &NpmPackageReqReference,
|
||||
referrer: &ModuleSpecifier,
|
||||
resolver: &LspResolver,
|
||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||
Some(NodeResolution::into_specifier_and_media_type(
|
||||
resolver
|
||||
.resolve_npm_req_reference(
|
||||
npm_req_ref,
|
||||
referrer,
|
||||
NodeResolutionMode::Types,
|
||||
)
|
||||
.ok()
|
||||
.flatten(),
|
||||
))
|
||||
}
|
||||
|
||||
/// Loader that will look at the open documents.
|
||||
pub struct OpenDocumentsGraphLoader<'a> {
|
||||
pub inner_loader: &'a mut dyn deno_graph::source::Loader,
|
||||
|
@ -1441,7 +1385,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()),
|
||||
maybe_resolver: Some(resolver.as_graph_resolver()),
|
||||
maybe_npm_resolver: Some(resolver.as_graph_npm_resolver()),
|
||||
},
|
||||
)),
|
||||
|
|
|
@ -243,7 +243,7 @@ impl LanguageServer {
|
|||
.await?;
|
||||
graph_util::graph_valid(
|
||||
&graph,
|
||||
factory.fs().as_ref(),
|
||||
factory.fs().clone(),
|
||||
&roots,
|
||||
graph_util::GraphValidOptions {
|
||||
is_vendoring: false,
|
||||
|
|
|
@ -19,11 +19,11 @@ use crate::npm::ManagedCliNpmResolver;
|
|||
use crate::resolver::CliGraphResolver;
|
||||
use crate::resolver::CliGraphResolverOptions;
|
||||
use crate::resolver::CliNodeResolver;
|
||||
use crate::resolver::SloppyImportsFsEntry;
|
||||
use crate::resolver::SloppyImportsResolver;
|
||||
use crate::util::progress_bar::ProgressBar;
|
||||
use crate::util::progress_bar::ProgressBarStyle;
|
||||
use dashmap::DashMap;
|
||||
use deno_ast::MediaType;
|
||||
use deno_cache_dir::HttpCache;
|
||||
use deno_core::error::AnyError;
|
||||
use deno_core::url::Url;
|
||||
|
@ -31,7 +31,6 @@ use deno_graph::source::NpmResolver;
|
|||
use deno_graph::source::Resolver;
|
||||
use deno_graph::GraphImport;
|
||||
use deno_graph::ModuleSpecifier;
|
||||
use deno_graph::Resolution;
|
||||
use deno_npm::NpmSystemInfo;
|
||||
use deno_runtime::deno_fs;
|
||||
use deno_runtime::deno_node::NodeResolution;
|
||||
|
@ -64,7 +63,6 @@ pub struct LspResolver {
|
|||
redirect_resolver: Option<Arc<RedirectResolver>>,
|
||||
graph_imports: Arc<IndexMap<ModuleSpecifier, GraphImport>>,
|
||||
config: Arc<Config>,
|
||||
unstable_sloppy_imports: bool,
|
||||
}
|
||||
|
||||
impl Default for LspResolver {
|
||||
|
@ -78,7 +76,6 @@ impl Default for LspResolver {
|
|||
redirect_resolver: None,
|
||||
graph_imports: Default::default(),
|
||||
config: Default::default(),
|
||||
unstable_sloppy_imports: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -146,10 +143,6 @@ impl LspResolver {
|
|||
npm_config_hash,
|
||||
redirect_resolver,
|
||||
graph_imports,
|
||||
unstable_sloppy_imports: config_data
|
||||
.and_then(|d| d.config_file.as_ref())
|
||||
.map(|cf| cf.has_unstable("sloppy-imports"))
|
||||
.unwrap_or(false),
|
||||
config: Arc::new(config.clone()),
|
||||
})
|
||||
}
|
||||
|
@ -172,7 +165,6 @@ impl LspResolver {
|
|||
redirect_resolver: self.redirect_resolver.clone(),
|
||||
graph_imports: self.graph_imports.clone(),
|
||||
config: self.config.clone(),
|
||||
unstable_sloppy_imports: self.unstable_sloppy_imports,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -192,17 +184,28 @@ impl LspResolver {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn as_graph_resolver(&self) -> LspGraphResolver {
|
||||
LspGraphResolver {
|
||||
inner: &self.graph_resolver,
|
||||
unstable_sloppy_imports: self.unstable_sloppy_imports,
|
||||
}
|
||||
pub fn as_graph_resolver(&self) -> &dyn Resolver {
|
||||
self.graph_resolver.as_ref()
|
||||
}
|
||||
|
||||
pub fn as_graph_npm_resolver(&self) -> &dyn NpmResolver {
|
||||
self.graph_resolver.as_ref()
|
||||
}
|
||||
|
||||
pub fn maybe_managed_npm_resolver(&self) -> Option<&ManagedCliNpmResolver> {
|
||||
self.npm_resolver.as_ref().and_then(|r| r.as_managed())
|
||||
}
|
||||
|
||||
pub fn graph_import_specifiers(
|
||||
&self,
|
||||
) -> impl Iterator<Item = &ModuleSpecifier> {
|
||||
self
|
||||
.graph_imports
|
||||
.values()
|
||||
.flat_map(|i| i.dependencies.values())
|
||||
.flat_map(|value| value.get_type().or_else(|| value.get_code()))
|
||||
}
|
||||
|
||||
pub fn jsr_to_registry_url(
|
||||
&self,
|
||||
req_ref: &JsrPackageReqReference,
|
||||
|
@ -222,81 +225,41 @@ impl LspResolver {
|
|||
self.jsr_resolver.as_ref()?.lookup_req_for_nv(nv)
|
||||
}
|
||||
|
||||
pub fn maybe_managed_npm_resolver(&self) -> Option<&ManagedCliNpmResolver> {
|
||||
self.npm_resolver.as_ref().and_then(|r| r.as_managed())
|
||||
}
|
||||
|
||||
pub fn graph_import_specifiers(
|
||||
pub fn npm_to_file_url(
|
||||
&self,
|
||||
) -> impl Iterator<Item = &ModuleSpecifier> {
|
||||
self
|
||||
.graph_imports
|
||||
.values()
|
||||
.flat_map(|i| i.dependencies.values())
|
||||
.flat_map(|value| value.get_type().or_else(|| value.get_code()))
|
||||
req_ref: &NpmPackageReqReference,
|
||||
referrer: &ModuleSpecifier,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Option<(ModuleSpecifier, MediaType)> {
|
||||
let node_resolver = self.node_resolver.as_ref()?;
|
||||
Some(NodeResolution::into_specifier_and_media_type(
|
||||
node_resolver
|
||||
.resolve_req_reference(
|
||||
req_ref,
|
||||
&PermissionsContainer::allow_all(),
|
||||
referrer,
|
||||
mode,
|
||||
)
|
||||
.ok(),
|
||||
))
|
||||
}
|
||||
|
||||
pub fn resolve_graph_import(&self, specifier: &str) -> Option<&Resolution> {
|
||||
for graph_imports in self.graph_imports.values() {
|
||||
let maybe_dep = graph_imports.dependencies.get(specifier);
|
||||
if maybe_dep.is_some() {
|
||||
return maybe_dep.map(|d| &d.maybe_type);
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub fn in_npm_package(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
pub fn in_node_modules(&self, specifier: &ModuleSpecifier) -> bool {
|
||||
if let Some(npm_resolver) = &self.npm_resolver {
|
||||
return npm_resolver.in_npm_package(specifier);
|
||||
}
|
||||
false
|
||||
}
|
||||
|
||||
pub fn node_resolve(
|
||||
pub fn node_media_type(
|
||||
&self,
|
||||
specifier: &str,
|
||||
referrer: &ModuleSpecifier,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<NodeResolution>, AnyError> {
|
||||
let Some(node_resolver) = self.node_resolver.as_ref() else {
|
||||
return Ok(None);
|
||||
};
|
||||
node_resolver.resolve(
|
||||
specifier,
|
||||
referrer,
|
||||
mode,
|
||||
&PermissionsContainer::allow_all(),
|
||||
)
|
||||
}
|
||||
|
||||
pub fn resolve_npm_req_reference(
|
||||
&self,
|
||||
req_ref: &NpmPackageReqReference,
|
||||
referrer: &ModuleSpecifier,
|
||||
mode: NodeResolutionMode,
|
||||
) -> Result<Option<NodeResolution>, AnyError> {
|
||||
let Some(node_resolver) = self.node_resolver.as_ref() else {
|
||||
return Ok(None);
|
||||
};
|
||||
node_resolver
|
||||
.resolve_req_reference(
|
||||
req_ref,
|
||||
&PermissionsContainer::allow_all(),
|
||||
referrer,
|
||||
mode,
|
||||
)
|
||||
.map(Some)
|
||||
}
|
||||
|
||||
pub fn url_to_node_resolution(
|
||||
&self,
|
||||
specifier: ModuleSpecifier,
|
||||
) -> Result<Option<NodeResolution>, AnyError> {
|
||||
let Some(node_resolver) = self.node_resolver.as_ref() else {
|
||||
return Ok(None);
|
||||
};
|
||||
node_resolver.url_to_node_resolution(specifier).map(Some)
|
||||
specifier: &ModuleSpecifier,
|
||||
) -> Option<MediaType> {
|
||||
let node_resolver = self.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 get_closest_package_json(
|
||||
|
@ -335,68 +298,6 @@ impl LspResolver {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct LspGraphResolver<'a> {
|
||||
inner: &'a CliGraphResolver,
|
||||
unstable_sloppy_imports: bool,
|
||||
}
|
||||
|
||||
impl<'a> Resolver for LspGraphResolver<'a> {
|
||||
fn default_jsx_import_source(&self) -> Option<String> {
|
||||
self.inner.default_jsx_import_source()
|
||||
}
|
||||
|
||||
fn default_jsx_import_source_types(&self) -> Option<String> {
|
||||
self.inner.default_jsx_import_source_types()
|
||||
}
|
||||
|
||||
fn jsx_import_source_module(&self) -> &str {
|
||||
self.inner.jsx_import_source_module()
|
||||
}
|
||||
|
||||
fn resolve(
|
||||
&self,
|
||||
specifier_text: &str,
|
||||
referrer_range: &deno_graph::Range,
|
||||
mode: deno_graph::source::ResolutionMode,
|
||||
) -> Result<deno_ast::ModuleSpecifier, deno_graph::source::ResolveError> {
|
||||
let specifier = self.inner.resolve(specifier_text, referrer_range, mode)?;
|
||||
if self.unstable_sloppy_imports && specifier.scheme() == "file" {
|
||||
Ok(
|
||||
SloppyImportsResolver::resolve_with_stat_sync(
|
||||
&specifier,
|
||||
mode,
|
||||
|path| {
|
||||
path.metadata().ok().and_then(|m| {
|
||||
if m.is_file() {
|
||||
Some(SloppyImportsFsEntry::File)
|
||||
} else if m.is_dir() {
|
||||
Some(SloppyImportsFsEntry::Dir)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
.into_specifier()
|
||||
.into_owned(),
|
||||
)
|
||||
} else {
|
||||
Ok(specifier)
|
||||
}
|
||||
}
|
||||
|
||||
fn resolve_types(
|
||||
&self,
|
||||
specifier: &deno_ast::ModuleSpecifier,
|
||||
) -> Result<
|
||||
Option<(deno_ast::ModuleSpecifier, Option<deno_graph::Range>)>,
|
||||
deno_graph::source::ResolveError,
|
||||
> {
|
||||
self.inner.resolve_types(specifier)
|
||||
}
|
||||
}
|
||||
|
||||
async fn create_npm_resolver(
|
||||
config_data: &ConfigData,
|
||||
cache: &LspCache,
|
||||
|
@ -467,6 +368,8 @@ fn create_graph_resolver(
|
|||
node_resolver: Option<&Arc<CliNodeResolver>>,
|
||||
) -> Arc<CliGraphResolver> {
|
||||
let config_file = config_data.and_then(|d| d.config_file.as_deref());
|
||||
let unstable_sloppy_imports =
|
||||
config_file.is_some_and(|cf| cf.has_unstable("sloppy-imports"));
|
||||
Arc::new(CliGraphResolver::new(CliGraphResolverOptions {
|
||||
node_resolver: node_resolver.cloned(),
|
||||
npm_resolver: npm_resolver.cloned(),
|
||||
|
@ -484,8 +387,9 @@ fn create_graph_resolver(
|
|||
bare_node_builtins_enabled: config_file
|
||||
.map(|cf| cf.has_unstable("bare-node-builtins"))
|
||||
.unwrap_or(false),
|
||||
// not used in the LSP as the LspGraphResolver handles this
|
||||
sloppy_imports_resolver: None,
|
||||
sloppy_imports_resolver: unstable_sloppy_imports.then(|| {
|
||||
SloppyImportsResolver::new_without_stat_cache(Arc::new(deno_fs::RealFs))
|
||||
}),
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -4053,7 +4053,7 @@ fn op_is_node_file(state: &mut OpState, #[string] path: String) -> bool {
|
|||
let state = state.borrow::<State>();
|
||||
let mark = state.performance.mark("tsc.op.op_is_node_file");
|
||||
let r = match ModuleSpecifier::parse(&path) {
|
||||
Ok(specifier) => state.state_snapshot.resolver.in_npm_package(&specifier),
|
||||
Ok(specifier) => state.state_snapshot.resolver.in_node_modules(&specifier),
|
||||
Err(_) => false,
|
||||
};
|
||||
state.performance.measure(mark);
|
||||
|
@ -4250,12 +4250,14 @@ fn op_respond(
|
|||
fn op_script_names(state: &mut OpState) -> Vec<String> {
|
||||
let state = state.borrow_mut::<State>();
|
||||
let mark = state.performance.mark("tsc.op.op_script_names");
|
||||
let documents = &state.state_snapshot.documents;
|
||||
let all_docs = documents.documents(DocumentsFilter::AllDiagnosable);
|
||||
let mut seen = HashSet::new();
|
||||
let mut result = Vec::new();
|
||||
|
||||
if documents.has_injected_types_node_package() {
|
||||
if state
|
||||
.state_snapshot
|
||||
.documents
|
||||
.has_injected_types_node_package()
|
||||
{
|
||||
// ensure this is first so it resolves the node types first
|
||||
let specifier = "asset:///node_types.d.ts";
|
||||
result.push(specifier.to_string());
|
||||
|
@ -4269,25 +4271,17 @@ fn op_script_names(state: &mut OpState) -> Vec<String> {
|
|||
}
|
||||
}
|
||||
|
||||
// finally include the documents and all their dependencies
|
||||
for doc in &all_docs {
|
||||
let specifiers = std::iter::once(doc.specifier()).chain(
|
||||
doc
|
||||
.dependencies()
|
||||
.values()
|
||||
.filter_map(|dep| dep.get_type().or_else(|| dep.get_code())),
|
||||
);
|
||||
for specifier in specifiers {
|
||||
if seen.insert(specifier.as_str()) {
|
||||
if let Some(specifier) = documents.resolve_specifier(specifier) {
|
||||
// only include dependencies we know to exist otherwise typescript will error
|
||||
if documents.exists(&specifier)
|
||||
&& (specifier.scheme() == "file" || documents.is_open(&specifier))
|
||||
{
|
||||
result.push(specifier.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
// finally include the documents
|
||||
let docs = state
|
||||
.state_snapshot
|
||||
.documents
|
||||
.documents(DocumentsFilter::AllDiagnosable);
|
||||
for doc in &docs {
|
||||
let specifier = doc.specifier();
|
||||
if seen.insert(specifier.as_str())
|
||||
&& (doc.is_open() || specifier.scheme() == "file")
|
||||
{
|
||||
result.push(specifier.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
106
cli/resolver.rs
106
cli/resolver.rs
|
@ -1,5 +1,6 @@
|
|||
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
||||
|
||||
use dashmap::DashMap;
|
||||
use deno_ast::MediaType;
|
||||
use deno_core::anyhow::anyhow;
|
||||
use deno_core::anyhow::Context;
|
||||
|
@ -33,7 +34,6 @@ use deno_semver::npm::NpmPackageReqReference;
|
|||
use deno_semver::package::PackageReq;
|
||||
use import_map::ImportMap;
|
||||
use std::borrow::Cow;
|
||||
use std::collections::HashMap;
|
||||
use std::collections::HashSet;
|
||||
use std::path::Path;
|
||||
use std::path::PathBuf;
|
||||
|
@ -858,38 +858,6 @@ impl NpmResolver for CliGraphResolver {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct SloppyImportsStatCache {
|
||||
fs: Arc<dyn FileSystem>,
|
||||
cache: Mutex<HashMap<PathBuf, Option<SloppyImportsFsEntry>>>,
|
||||
}
|
||||
|
||||
impl SloppyImportsStatCache {
|
||||
pub fn new(fs: Arc<dyn FileSystem>) -> Self {
|
||||
Self {
|
||||
fs,
|
||||
cache: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn stat_sync(&self, path: &Path) -> Option<SloppyImportsFsEntry> {
|
||||
// there will only ever be one thread in here at a
|
||||
// time, so it's ok to hold the lock for so long
|
||||
let mut cache = self.cache.lock();
|
||||
if let Some(entry) = cache.get(path) {
|
||||
return *entry;
|
||||
}
|
||||
|
||||
let entry = self
|
||||
.fs
|
||||
.stat_sync(path)
|
||||
.ok()
|
||||
.and_then(|stat| SloppyImportsFsEntry::from_fs_stat(&stat));
|
||||
cache.insert(path.to_owned(), entry);
|
||||
entry
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub enum SloppyImportsFsEntry {
|
||||
File,
|
||||
|
@ -989,33 +957,27 @@ impl<'a> SloppyImportsResolution<'a> {
|
|||
|
||||
#[derive(Debug)]
|
||||
pub struct SloppyImportsResolver {
|
||||
stat_cache: SloppyImportsStatCache,
|
||||
fs: Arc<dyn FileSystem>,
|
||||
cache: Option<DashMap<PathBuf, Option<SloppyImportsFsEntry>>>,
|
||||
}
|
||||
|
||||
impl SloppyImportsResolver {
|
||||
pub fn new(fs: Arc<dyn FileSystem>) -> Self {
|
||||
Self {
|
||||
stat_cache: SloppyImportsStatCache::new(fs),
|
||||
fs,
|
||||
cache: Some(Default::default()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn resolve_with_fs<'a>(
|
||||
fs: &dyn FileSystem,
|
||||
pub fn new_without_stat_cache(fs: Arc<dyn FileSystem>) -> Self {
|
||||
Self { fs, cache: None }
|
||||
}
|
||||
|
||||
pub fn resolve<'a>(
|
||||
&self,
|
||||
specifier: &'a ModuleSpecifier,
|
||||
mode: ResolutionMode,
|
||||
) -> SloppyImportsResolution<'a> {
|
||||
Self::resolve_with_stat_sync(specifier, mode, |path| {
|
||||
fs.stat_sync(path)
|
||||
.ok()
|
||||
.and_then(|stat| SloppyImportsFsEntry::from_fs_stat(&stat))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn resolve_with_stat_sync(
|
||||
specifier: &ModuleSpecifier,
|
||||
mode: ResolutionMode,
|
||||
stat_sync: impl Fn(&Path) -> Option<SloppyImportsFsEntry>,
|
||||
) -> SloppyImportsResolution {
|
||||
fn path_without_ext(
|
||||
path: &Path,
|
||||
media_type: MediaType,
|
||||
|
@ -1065,7 +1027,7 @@ impl SloppyImportsResolver {
|
|||
}
|
||||
|
||||
let probe_paths: Vec<(PathBuf, SloppyImportsResolutionReason)> =
|
||||
match (stat_sync)(&path) {
|
||||
match self.stat_sync(&path) {
|
||||
Some(SloppyImportsFsEntry::File) => {
|
||||
if mode.is_types() {
|
||||
let media_type = MediaType::from_specifier(specifier);
|
||||
|
@ -1243,7 +1205,7 @@ impl SloppyImportsResolver {
|
|||
};
|
||||
|
||||
for (probe_path, reason) in probe_paths {
|
||||
if (stat_sync)(&probe_path) == Some(SloppyImportsFsEntry::File) {
|
||||
if self.stat_sync(&probe_path) == Some(SloppyImportsFsEntry::File) {
|
||||
if let Ok(specifier) = ModuleSpecifier::from_file_path(probe_path) {
|
||||
match reason {
|
||||
SloppyImportsResolutionReason::JsToTs => {
|
||||
|
@ -1263,14 +1225,22 @@ impl SloppyImportsResolver {
|
|||
SloppyImportsResolution::None(specifier)
|
||||
}
|
||||
|
||||
pub fn resolve<'a>(
|
||||
&self,
|
||||
specifier: &'a ModuleSpecifier,
|
||||
mode: ResolutionMode,
|
||||
) -> SloppyImportsResolution<'a> {
|
||||
Self::resolve_with_stat_sync(specifier, mode, |path| {
|
||||
self.stat_cache.stat_sync(path)
|
||||
})
|
||||
fn stat_sync(&self, path: &Path) -> Option<SloppyImportsFsEntry> {
|
||||
if let Some(cache) = &self.cache {
|
||||
if let Some(entry) = cache.get(path) {
|
||||
return *entry;
|
||||
}
|
||||
}
|
||||
|
||||
let entry = self
|
||||
.fs
|
||||
.stat_sync(path)
|
||||
.ok()
|
||||
.and_then(|stat| SloppyImportsFsEntry::from_fs_stat(&stat));
|
||||
if let Some(cache) = &self.cache {
|
||||
cache.insert(path.to_owned(), entry);
|
||||
}
|
||||
entry
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1278,7 +1248,6 @@ impl SloppyImportsResolver {
|
|||
mod test {
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use deno_runtime::deno_fs::RealFs;
|
||||
use test_util::TestContext;
|
||||
|
||||
use super::*;
|
||||
|
@ -1346,21 +1315,8 @@ mod test {
|
|||
#[test]
|
||||
fn test_unstable_sloppy_imports() {
|
||||
fn resolve(specifier: &ModuleSpecifier) -> SloppyImportsResolution {
|
||||
SloppyImportsResolver::resolve_with_stat_sync(
|
||||
specifier,
|
||||
ResolutionMode::Execution,
|
||||
|path| {
|
||||
RealFs.stat_sync(path).ok().and_then(|stat| {
|
||||
if stat.is_file {
|
||||
Some(SloppyImportsFsEntry::File)
|
||||
} else if stat.is_directory {
|
||||
Some(SloppyImportsFsEntry::Dir)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
},
|
||||
)
|
||||
SloppyImportsResolver::new(Arc::new(deno_fs::RealFs))
|
||||
.resolve(specifier, ResolutionMode::Execution)
|
||||
}
|
||||
|
||||
let context = TestContext::default();
|
||||
|
|
2
cli/tools/vendor/build.rs
vendored
2
cli/tools/vendor/build.rs
vendored
|
@ -126,7 +126,7 @@ pub async fn build<
|
|||
// surface any errors
|
||||
graph_util::graph_valid(
|
||||
&graph,
|
||||
&deno_fs::RealFs,
|
||||
Arc::new(deno_fs::RealFs),
|
||||
&graph.roots,
|
||||
graph_util::GraphValidOptions {
|
||||
is_vendoring: true,
|
||||
|
|
Loading…
Reference in a new issue