mirror of
https://github.com/denoland/deno.git
synced 2024-11-21 15:04:11 -05:00
refactor: use dependency analyzer from SWC (#7334)
This commit is contained in:
parent
5b100cb874
commit
dbd941148c
3 changed files with 31 additions and 135 deletions
13
Cargo.lock
generated
13
Cargo.lock
generated
|
@ -412,6 +412,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"sourcemap",
|
||||
"swc_common",
|
||||
"swc_ecma_dep_graph",
|
||||
"swc_ecmascript",
|
||||
"sys-info",
|
||||
"tempfile",
|
||||
|
@ -2260,6 +2261,18 @@ dependencies = [
|
|||
"syn 1.0.36",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_dep_graph"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bb38c4567ac35d625c0da0a70d68449e38b23c1ae95df9ca6837811e2711136e"
|
||||
dependencies = [
|
||||
"swc_atoms",
|
||||
"swc_common",
|
||||
"swc_ecma_ast",
|
||||
"swc_ecma_visit",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "swc_ecma_parser"
|
||||
version = "0.37.0"
|
||||
|
|
|
@ -63,6 +63,7 @@ sys-info = "0.7.0"
|
|||
sourcemap = "6.0.1"
|
||||
swc_common = { version = "=0.10.2", features = ["sourcemap"] }
|
||||
swc_ecmascript = { version = "=0.7.0", features = ["codegen", "parser", "react", "transforms", "visit"] }
|
||||
swc_ecma_dep_graph = "0.3.0"
|
||||
tempfile = "3.1.0"
|
||||
termcolor = "1.1.0"
|
||||
tokio = { version = "0.2.22", features = ["full"] }
|
||||
|
|
152
cli/tsc.rs
152
cli/tsc.rs
|
@ -55,10 +55,9 @@ use std::sync::atomic::Ordering;
|
|||
use std::sync::Arc;
|
||||
use std::sync::Mutex;
|
||||
use std::task::Poll;
|
||||
use swc_common::comments::Comment;
|
||||
use swc_common::comments::CommentKind;
|
||||
use swc_common::Span;
|
||||
use swc_ecmascript::visit::Node;
|
||||
use swc_ecmascript::visit::Visit;
|
||||
use swc_ecma_dep_graph as dep_graph;
|
||||
use url::Url;
|
||||
|
||||
pub const AVAILABLE_LIBS: &[&str] = &[
|
||||
|
@ -1437,121 +1436,6 @@ pub async fn runtime_transpile(
|
|||
Ok(v)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
enum DependencyKind {
|
||||
Import,
|
||||
DynamicImport,
|
||||
Export,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
struct DependencyDescriptor {
|
||||
span: Span,
|
||||
specifier: String,
|
||||
kind: DependencyKind,
|
||||
}
|
||||
|
||||
struct DependencyVisitor {
|
||||
dependencies: Vec<DependencyDescriptor>,
|
||||
}
|
||||
|
||||
impl Visit for DependencyVisitor {
|
||||
fn visit_import_decl(
|
||||
&mut self,
|
||||
import_decl: &swc_ecmascript::ast::ImportDecl,
|
||||
_parent: &dyn Node,
|
||||
) {
|
||||
let src_str = import_decl.src.value.to_string();
|
||||
self.dependencies.push(DependencyDescriptor {
|
||||
specifier: src_str,
|
||||
kind: DependencyKind::Import,
|
||||
span: import_decl.span,
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_named_export(
|
||||
&mut self,
|
||||
named_export: &swc_ecmascript::ast::NamedExport,
|
||||
_parent: &dyn Node,
|
||||
) {
|
||||
if let Some(src) = &named_export.src {
|
||||
let src_str = src.value.to_string();
|
||||
self.dependencies.push(DependencyDescriptor {
|
||||
specifier: src_str,
|
||||
kind: DependencyKind::Export,
|
||||
span: named_export.span,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_export_all(
|
||||
&mut self,
|
||||
export_all: &swc_ecmascript::ast::ExportAll,
|
||||
_parent: &dyn Node,
|
||||
) {
|
||||
let src_str = export_all.src.value.to_string();
|
||||
self.dependencies.push(DependencyDescriptor {
|
||||
specifier: src_str,
|
||||
kind: DependencyKind::Export,
|
||||
span: export_all.span,
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_ts_import_type(
|
||||
&mut self,
|
||||
ts_import_type: &swc_ecmascript::ast::TsImportType,
|
||||
_parent: &dyn Node,
|
||||
) {
|
||||
// TODO(bartlomieju): possibly add separate DependencyKind
|
||||
let src_str = ts_import_type.arg.value.to_string();
|
||||
self.dependencies.push(DependencyDescriptor {
|
||||
specifier: src_str,
|
||||
kind: DependencyKind::Import,
|
||||
span: ts_import_type.arg.span,
|
||||
});
|
||||
}
|
||||
|
||||
fn visit_call_expr(
|
||||
&mut self,
|
||||
call_expr: &swc_ecmascript::ast::CallExpr,
|
||||
parent: &dyn Node,
|
||||
) {
|
||||
use swc_ecmascript::ast::Expr::*;
|
||||
use swc_ecmascript::ast::ExprOrSuper::*;
|
||||
|
||||
swc_ecmascript::visit::visit_call_expr(self, call_expr, parent);
|
||||
let boxed_expr = match call_expr.callee.clone() {
|
||||
Super(_) => return,
|
||||
Expr(boxed) => boxed,
|
||||
};
|
||||
|
||||
match &*boxed_expr {
|
||||
Ident(ident) => {
|
||||
if &ident.sym.to_string() != "import" {
|
||||
return;
|
||||
}
|
||||
}
|
||||
_ => return,
|
||||
};
|
||||
|
||||
if let Some(arg) = call_expr.args.get(0) {
|
||||
match &*arg.expr {
|
||||
Lit(lit) => {
|
||||
if let swc_ecmascript::ast::Lit::Str(str_) = lit {
|
||||
let src_str = str_.value.to_string();
|
||||
self.dependencies.push(DependencyDescriptor {
|
||||
specifier: src_str,
|
||||
kind: DependencyKind::DynamicImport,
|
||||
span: call_expr.span,
|
||||
});
|
||||
}
|
||||
}
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
pub struct ImportDesc {
|
||||
pub specifier: String,
|
||||
|
@ -1587,39 +1471,39 @@ pub fn pre_process_file(
|
|||
let parser = AstParser::default();
|
||||
let parse_result = parser.parse_module(file_name, media_type, source_code);
|
||||
let module = parse_result?;
|
||||
let mut collector = DependencyVisitor {
|
||||
dependencies: vec![],
|
||||
};
|
||||
let module_span = module.span;
|
||||
collector.visit_module(&module, &module);
|
||||
|
||||
let dependency_descriptors = collector.dependencies;
|
||||
let dependency_descriptors = dep_graph::analyze_dependencies(
|
||||
&module,
|
||||
&parser.source_map,
|
||||
&parser.comments,
|
||||
);
|
||||
|
||||
// for each import check if there's relevant @deno-types directive
|
||||
let imports = dependency_descriptors
|
||||
.iter()
|
||||
.filter(|desc| desc.kind != dep_graph::DependencyKind::Require)
|
||||
.filter(|desc| {
|
||||
if analyze_dynamic_imports {
|
||||
return true;
|
||||
}
|
||||
|
||||
desc.kind != DependencyKind::DynamicImport
|
||||
!desc.is_dynamic
|
||||
})
|
||||
.map(|desc| {
|
||||
let location = parser.get_span_location(desc.span);
|
||||
let deno_types = get_deno_types(&parser, desc.span);
|
||||
let deno_types = get_deno_types(&desc.leading_comments);
|
||||
ImportDesc {
|
||||
specifier: desc.specifier.to_string(),
|
||||
deno_types,
|
||||
location: location.into(),
|
||||
location: Location {
|
||||
filename: file_name.to_string(),
|
||||
col: desc.col,
|
||||
line: desc.line,
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
|
||||
// analyze comment from beginning of the file and find TS directives
|
||||
let comments = parser
|
||||
.comments
|
||||
.with_leading(module_span.lo(), |cmts| cmts.to_vec());
|
||||
let comments = parser.get_span_comments(module.span);
|
||||
|
||||
let mut references = vec![];
|
||||
for comment in comments {
|
||||
|
@ -1640,9 +1524,7 @@ pub fn pre_process_file(
|
|||
Ok((imports, references))
|
||||
}
|
||||
|
||||
fn get_deno_types(parser: &AstParser, span: Span) -> Option<String> {
|
||||
let comments = parser.get_span_comments(span);
|
||||
|
||||
fn get_deno_types(comments: &[Comment]) -> Option<String> {
|
||||
if comments.is_empty() {
|
||||
return None;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue