2024-01-10 17:40:30 -05:00
|
|
|
// Copyright 2018-2024 the Deno authors. All rights reserved. MIT license.
|
|
|
|
|
|
|
|
use std::collections::HashSet;
|
2024-02-08 20:40:26 -05:00
|
|
|
use std::sync::Arc;
|
2024-01-10 17:40:30 -05:00
|
|
|
|
2024-02-08 20:40:26 -05:00
|
|
|
use deno_ast::SourceTextInfo;
|
2024-01-24 16:59:18 -05:00
|
|
|
use deno_graph::ModuleEntryRef;
|
2024-01-10 17:40:30 -05:00
|
|
|
use deno_graph::ModuleGraph;
|
2024-01-24 16:59:18 -05:00
|
|
|
use deno_graph::ResolutionResolved;
|
|
|
|
use deno_graph::WalkOptions;
|
|
|
|
use lsp_types::Url;
|
2024-01-10 17:40:30 -05:00
|
|
|
|
2024-01-23 10:37:43 -05:00
|
|
|
use super::diagnostics::PublishDiagnostic;
|
|
|
|
use super::diagnostics::PublishDiagnosticsCollector;
|
|
|
|
|
2024-01-24 16:59:18 -05:00
|
|
|
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 =
|
2024-02-08 20:40:26 -05:00
|
|
|
|skip_specifiers: &mut HashSet<Url>,
|
|
|
|
text: &Arc<str>,
|
|
|
|
resolution: &ResolutionResolved| {
|
2024-01-24 16:59:18 -05:00
|
|
|
if visited.insert(resolution.specifier.clone()) {
|
|
|
|
match resolution.specifier.scheme() {
|
2024-01-31 23:18:44 -05:00
|
|
|
"file" | "data" | "node" => {}
|
2024-01-24 16:59:18 -05:00
|
|
|
"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()),
|
2024-02-08 20:40:26 -05:00
|
|
|
text_info: SourceTextInfo::new(text.clone()),
|
2024-01-24 16:59:18 -05:00
|
|
|
imported: resolution.specifier.clone(),
|
|
|
|
referrer: resolution.range.clone(),
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
_ => {
|
|
|
|
skip_specifiers.insert(resolution.specifier.clone());
|
|
|
|
diagnostics_collector.push(
|
|
|
|
PublishDiagnostic::InvalidExternalImport {
|
|
|
|
kind: format!("'{}'", resolution.specifier.scheme()),
|
2024-02-08 20:40:26 -05:00
|
|
|
text_info: SourceTextInfo::new(text.clone()),
|
2024-01-24 16:59:18 -05:00
|
|
|
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;
|
|
|
|
};
|
2024-01-31 22:15:22 -05:00
|
|
|
let Some(module) = module.js() else {
|
2024-01-24 16:59:18 -05:00
|
|
|
continue;
|
|
|
|
};
|
|
|
|
|
|
|
|
for (_, dep) in &module.dependencies {
|
|
|
|
if let Some(resolved) = dep.maybe_code.ok() {
|
2024-02-08 20:40:26 -05:00
|
|
|
collect_if_invalid(&mut skip_specifiers, &module.source, resolved);
|
2024-01-24 16:59:18 -05:00
|
|
|
}
|
|
|
|
if let Some(resolved) = dep.maybe_type.ok() {
|
2024-02-08 20:40:26 -05:00
|
|
|
collect_if_invalid(&mut skip_specifiers, &module.source, resolved);
|
2024-01-24 16:59:18 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|