summaryrefslogtreecommitdiff
path: root/cli/tools/registry/graph.rs
diff options
context:
space:
mode:
Diffstat (limited to 'cli/tools/registry/graph.rs')
-rw-r--r--cli/tools/registry/graph.rs73
1 files changed, 73 insertions, 0 deletions
diff --git a/cli/tools/registry/graph.rs b/cli/tools/registry/graph.rs
index 4d061e3da..2a3b4cc17 100644
--- a/cli/tools/registry/graph.rs
+++ b/cli/tools/registry/graph.rs
@@ -10,7 +10,11 @@ use deno_core::anyhow::bail;
use deno_core::anyhow::Context;
use deno_core::error::AnyError;
use deno_graph::FastCheckDiagnostic;
+use deno_graph::ModuleEntryRef;
use deno_graph::ModuleGraph;
+use deno_graph::ResolutionResolved;
+use deno_graph::WalkOptions;
+use lsp_types::Url;
use super::diagnostics::PublishDiagnostic;
use super::diagnostics::PublishDiagnosticsCollector;
@@ -64,6 +68,75 @@ pub fn resolve_config_file_roots_from_exports(
Ok(exports)
}
+pub fn collect_invalid_external_imports(
+ graph: &ModuleGraph,
+ diagnostics_collector: &PublishDiagnosticsCollector,
+) {
+ let mut visited = HashSet::new();
+ let mut skip_specifiers: HashSet<Url> = HashSet::new();
+
+ let mut collect_if_invalid =
+ |skip_specifiers: &mut HashSet<Url>, resolution: &ResolutionResolved| {
+ if visited.insert(resolution.specifier.clone()) {
+ match resolution.specifier.scheme() {
+ "file" | "data" => {}
+ "jsr" | "npm" => {
+ skip_specifiers.insert(resolution.specifier.clone());
+ }
+ "http" | "https" => {
+ skip_specifiers.insert(resolution.specifier.clone());
+ diagnostics_collector.push(
+ PublishDiagnostic::InvalidExternalImport {
+ kind: format!("non-JSR '{}'", resolution.specifier.scheme()),
+ imported: resolution.specifier.clone(),
+ referrer: resolution.range.clone(),
+ },
+ );
+ }
+ _ => {
+ skip_specifiers.insert(resolution.specifier.clone());
+ diagnostics_collector.push(
+ PublishDiagnostic::InvalidExternalImport {
+ kind: format!("'{}'", resolution.specifier.scheme()),
+ imported: resolution.specifier.clone(),
+ referrer: resolution.range.clone(),
+ },
+ );
+ }
+ }
+ }
+ };
+
+ let options = WalkOptions {
+ check_js: true,
+ follow_dynamic: true,
+ follow_type_only: true,
+ };
+ let mut iter = graph.walk(&graph.roots, options);
+ while let Some((specifier, entry)) = iter.next() {
+ if skip_specifiers.contains(specifier) {
+ iter.skip_previous_dependencies();
+ continue;
+ }
+
+ let ModuleEntryRef::Module(module) = entry else {
+ continue;
+ };
+ let Some(module) = module.esm() else {
+ continue;
+ };
+
+ for (_, dep) in &module.dependencies {
+ if let Some(resolved) = dep.maybe_code.ok() {
+ collect_if_invalid(&mut skip_specifiers, resolved);
+ }
+ if let Some(resolved) = dep.maybe_type.ok() {
+ collect_if_invalid(&mut skip_specifiers, resolved);
+ }
+ }
+ }
+}
+
/// Collects diagnostics from the module graph for the given packages.
/// Returns true if any diagnostics were collected.
pub fn collect_fast_check_type_graph_diagnostics(