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