refactor(lsp): reuse CliGraphResolverOptions::sloppy_imports_resolver (#23764)

This commit is contained in:
Nayeem Rahman 2024-05-13 17:55:31 +01:00 committed by GitHub
parent 03a76f33ad
commit 88529f0b47
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 119 additions and 322 deletions

View File

@ -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,
)

View File

@ -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
}

View File

@ -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()),
},
)),

View File

@ -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,

View File

@ -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))
}),
}))
}

View File

@ -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());
}
}

View File

@ -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();

View File

@ -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,