Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
kitsonk committed Aug 18, 2020
1 parent 5cd878a commit d75cb1d
Show file tree
Hide file tree
Showing 3 changed files with 102 additions and 98 deletions.
179 changes: 92 additions & 87 deletions compiler/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ use swc_ecmascript::visit::Visit;

static TARGET: JscTarget = JscTarget::Es2020;

#[derive(Debug, Clone, Eq, PartialEq)]
#[derive(Debug, Clone, Default, Eq, PartialEq)]
pub struct Location {
pub filename: String,
pub line: usize,
Expand Down Expand Up @@ -193,8 +193,9 @@ impl Default for EmitTranspileOptions {
#[derive(Clone)]
pub struct ParsedModule {
comments: SingleThreadedComments,
pub leading_comments: Vec<Comment>,
module: Module,
source_map: Rc<SourceMap>,
pub source_map: Rc<SourceMap>,
}

impl fmt::Debug for ParsedModule {
Expand All @@ -204,27 +205,17 @@ impl fmt::Debug for ParsedModule {
}

impl ParsedModule {
pub fn get_leading_comments(&self, span: &Span) -> Vec<Comment> {
self
.comments
.with_leading(span.lo, |comments| comments.to_vec())
}

/// Identifies all syntactical dependencies of a module (e.g. `import` and
/// `export` statements).
pub fn get_dependencies(&self) -> Vec<DependencyDescriptor> {
let mut collector = DependencyCollector(Vec::new());
let mut collector = DependencyCollector {
comments: &self.comments,
items: Vec::new(),
source_map: &self.source_map,
};
collector.visit_module(&self.module, &self.module);

collector.0
}

pub fn get_location(&self, span: &Span) -> Location {
self.source_map.lookup_char_pos(span.lo).into()
}

pub fn get_module_leading_comments(&self) -> Vec<Comment> {
self.get_leading_comments(&self.module.span)
collector.items
}

pub fn transpile(
Expand Down Expand Up @@ -343,8 +334,11 @@ pub fn parse(
sm.lookup_char_pos(span.lo)
}))
})?;
let leading_comments =
comments.with_leading(module.span.lo, |comments| comments.to_vec());

Ok(ParsedModule {
leading_comments,
module,
source_map: Rc::new(source_map),
comments,
Expand All @@ -355,35 +349,46 @@ pub fn parse(
pub struct DependencyDescriptor {
pub is_dynamic: bool,
pub is_type: bool,
pub span: Span,
pub leading_comments: Vec<Comment>,
pub location: Location,
pub specifier: String,
}

impl DependencyDescriptor {
pub fn default() -> Self {
impl Default for DependencyDescriptor {
fn default() -> Self {
DependencyDescriptor {
is_dynamic: false,
is_type: false,
span: Span::default(),
leading_comments: Vec::new(),
location: Location::default(),
specifier: String::default(),
}
}
}

struct DependencyCollector(Vec<DependencyDescriptor>);
struct DependencyCollector<'a> {
comments: &'a SingleThreadedComments,
pub items: Vec<DependencyDescriptor>,
source_map: &'a SourceMap,
}

impl Visit for DependencyCollector {
impl<'a> Visit for DependencyCollector<'a> {
fn visit_import_decl(
&mut self,
node: &swc_ecmascript::ast::ImportDecl,
_parent: &dyn visit::Node,
) {
let specifier = node.src.value.to_string();
let span = node.span;
self.0.push(DependencyDescriptor {
span,
let location: Location = self.source_map.lookup_char_pos(span.lo).into();
let leading_comments = self
.comments
.with_leading(span.lo, |comments| comments.to_vec());
self.items.push(DependencyDescriptor {
leading_comments,
location,
specifier,
..DependencyDescriptor::default()
..Default::default()
});
}

Expand All @@ -395,10 +400,15 @@ impl Visit for DependencyCollector {
if let Some(src) = &node.src {
let specifier = src.value.to_string();
let span = node.span;
self.0.push(DependencyDescriptor {
span,
let location: Location = self.source_map.lookup_char_pos(span.lo).into();
let leading_comments = self
.comments
.with_leading(span.lo, |comments| comments.to_vec());
self.items.push(DependencyDescriptor {
leading_comments,
location,
specifier,
..DependencyDescriptor::default()
..Default::default()
});
}
}
Expand All @@ -410,10 +420,15 @@ impl Visit for DependencyCollector {
) {
let specifier = node.src.value.to_string();
let span = node.span;
self.0.push(DependencyDescriptor {
span,
let location: Location = self.source_map.lookup_char_pos(span.lo).into();
let leading_comments = self
.comments
.with_leading(span.lo, |comments| comments.to_vec());
self.items.push(DependencyDescriptor {
leading_comments,
location,
specifier,
..DependencyDescriptor::default()
..Default::default()
});
}

Expand All @@ -424,11 +439,16 @@ impl Visit for DependencyCollector {
) {
let specifier = node.arg.value.to_string();
let span = node.span;
self.0.push(DependencyDescriptor {
let location: Location = self.source_map.lookup_char_pos(span.lo).into();
let leading_comments = self
.comments
.with_leading(span.lo, |comments| comments.to_vec());
self.items.push(DependencyDescriptor {
is_type: true,
span,
leading_comments,
location,
specifier,
..DependencyDescriptor::default()
..Default::default()
});
}

Expand Down Expand Up @@ -460,11 +480,17 @@ impl Visit for DependencyCollector {
if let swc_ecmascript::ast::Lit::Str(str_) = lit {
let specifier = str_.value.to_string();
let span = node.span;
self.0.push(DependencyDescriptor {
let location: Location =
self.source_map.lookup_char_pos(span.lo).into();
let leading_comments = self
.comments
.with_leading(span.lo, |comments| comments.to_vec());
self.items.push(DependencyDescriptor {
is_dynamic: true,
span,
leading_comments,
location,
specifier,
..DependencyDescriptor::default()
..Default::default()
});
}
}
Expand All @@ -475,8 +501,6 @@ impl Visit for DependencyCollector {
#[cfg(test)]
mod tests {
use super::*;
use swc_common::BytePos;
use swc_common::SyntaxContext;

#[test]
fn test_parsed_module_get_dependencies() {
Expand All @@ -495,65 +519,46 @@ mod tests {
DependencyDescriptor {
is_dynamic: false,
is_type: false,
span: Span {
lo: BytePos(0),
hi: BytePos(33),
ctxt: SyntaxContext::empty()
leading_comments: Vec::new(),
location: Location {
filename: "https://deno.land/x/mod.js".to_owned(),
col: 0,
line: 0,
},
specifier: "./test.ts".to_owned()
},
DependencyDescriptor {
is_dynamic: true,
is_type: false,
span: Span {
lo: BytePos(56),
hi: BytePos(74),
ctxt: SyntaxContext::empty()
leading_comments: Vec::new(),
location: Location {
filename: "https://deno.land/x/mod.js".to_owned(),
col: 18,
line: 1,
},
specifier: "./foo.ts".to_owned()
}
]
);
}

#[test]
fn test_parsed_module_get_location() {
let specifier =
ModuleSpecifier::resolve_url_or_path("https://deno.land/x/mod.ts")
.unwrap();
let source = r#"import * as bar from "./test.ts";"#;
let parsed_module = parse(&specifier, source, MediaType::TypeScript)
.expect("could not parse module");
let dependencies = parsed_module.get_dependencies();
let first = dependencies.first().unwrap();
let actual = parsed_module.get_location(&first.span);
assert_eq!(
actual,
Location {
filename: "https://deno.land/x/mod.ts".to_owned(),
line: 1,
col: 0
}
);
}

#[test]
fn test_parsed_module_get_leading_comments() {
let specifier =
ModuleSpecifier::resolve_url_or_path("https://deno.land/x/mod.ts")
.unwrap();
let source = r#"// this is the first comment
// this is the second comment
import * as bar from "./test.ts";"#;
let parsed_module = parse(&specifier, source, MediaType::TypeScript)
.expect("could not parse module");
let dependencies = parsed_module.get_dependencies();
let first = dependencies.first().unwrap();
let actual = parsed_module.get_leading_comments(&first.span);
assert_eq!(actual[0].text, " this is the first comment".to_string());
assert_eq!(actual[1].text, " this is the second comment".to_string());
assert_eq!(actual.len(), 2);
}
// #[test]
// fn test_parsed_module_get_leading_comments() {
// let specifier =
// ModuleSpecifier::resolve_url_or_path("https://deno.land/x/mod.ts")
// .unwrap();
// let source = r#"// this is the first comment
// // this is the second comment
// import * as bar from "./test.ts";"#;
// let parsed_module = parse(&specifier, source, MediaType::TypeScript)
// .expect("could not parse module");
// let dependencies = parsed_module.get_dependencies();
// let first = dependencies.first().unwrap();
// let actual = parsed_module.get_leading_comments(&first.span);
// assert_eq!(actual[0].text, " this is the first comment".to_string());
// assert_eq!(actual[1].text, " this is the second comment".to_string());
// assert_eq!(actual.len(), 2);
// }

#[test]
fn test_transpile() {
Expand Down
1 change: 0 additions & 1 deletion compiler/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,6 @@ pub mod tests {
}

type Handler = Rc<RefCell<MockSpecifierHandler>>;

type SetupResult = Result<(GraphBuilder, Handler, Box<[u8]>)>;

fn setup(rebuild: bool, maybe_import_map: Option<ImportMap>) -> SetupResult {
Expand Down
20 changes: 10 additions & 10 deletions compiler/module_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -405,10 +405,12 @@ impl Module {
let parsed_module = parse(&self.specifier, &self.source, self.media_type)?;

// Parse out any triple slash references
let leading_comments = parsed_module.get_module_leading_comments();
for comment in leading_comments.iter() {
for comment in parsed_module.leading_comments.iter() {
if let Some(ts_reference) = parse_ts_reference(&comment.text) {
let location = parsed_module.get_location(&comment.span);
let location: Location = parsed_module
.source_map
.lookup_char_pos(comment.span.lo)
.into();
match ts_reference {
TypeScriptReference::Path(import) => {
let specifier = self.resolve_import(&import, Some(location))?;
Expand All @@ -435,16 +437,14 @@ impl Module {
// Parse out all the syntactical dependencies for a module
let dependencies = parsed_module.get_dependencies();
for desc in dependencies.iter() {
let location = parsed_module.get_location(&desc.span);
let specifier = self.resolve_import(&desc.specifier, Some(location))?;
let specifier =
self.resolve_import(&desc.specifier, Some(desc.location.clone()))?;

// Parse out any `@deno-types` pragmas and modify dependency
let comments = parsed_module.get_leading_comments(&desc.span);
let maybe_types_specifier = if !comments.is_empty() {
let comment = comments.last().unwrap();
let maybe_types_specifier = if !desc.leading_comments.is_empty() {
let comment = desc.leading_comments.last().unwrap();
if let Some(deno_types) = parse_deno_types(&comment.text).as_ref() {
let location = parsed_module.get_location(&comment.span);
Some(self.resolve_import(deno_types, Some(location))?)
Some(self.resolve_import(deno_types, Some(desc.location.clone()))?)
} else {
None
}
Expand Down

0 comments on commit d75cb1d

Please sign in to comment.