Skip to content

Commit

Permalink
feat: expose analyzing deps without a ParsedSource and improvements t…
Browse files Browse the repository at this point in the history
…o Comments (#195)
  • Loading branch information
dsherret authored Dec 18, 2023
1 parent 637ef29 commit 6dfab72
Show file tree
Hide file tree
Showing 7 changed files with 73 additions and 43 deletions.
1 change: 0 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ on:
inputs:
releaseKind:
description: 'Kind of release'
default: 'minor'
type: choice
options:
- patch
Expand Down
2 changes: 1 addition & 1 deletion rust-toolchain.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[toolchain]
channel = "1.73.0"
channel = "1.74.1"
components = ["clippy", "rustfmt"]
profile = "minimal"
39 changes: 33 additions & 6 deletions src/comments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use crate::swc::common::comments::SingleThreadedComments;
use crate::swc::common::comments::SingleThreadedCommentsMapInner;
use crate::swc::common::BytePos as SwcBytePos;
use crate::SourcePos;

use std::cell::RefCell;
use std::rc::Rc;
use std::sync::Arc;
Expand All @@ -35,7 +36,14 @@ impl MultiThreadedComments {
let (leading, trailing) = comments.take_all();
let leading = Rc::try_unwrap(leading).unwrap().into_inner();
let trailing = Rc::try_unwrap(trailing).unwrap().into_inner();
MultiThreadedComments {
Self::from_leading_and_trailing(leading, trailing)
}

pub fn from_leading_and_trailing(
leading: SingleThreadedCommentsMapInner,
trailing: SingleThreadedCommentsMapInner,
) -> Self {
Self {
inner: Arc::new(MultiThreadedCommentsInner { leading, trailing }),
}
}
Expand All @@ -51,6 +59,19 @@ impl MultiThreadedComments {
SingleThreadedComments::from_leading_and_trailing(leading, trailing)
}

pub fn into_single_threaded(self) -> SingleThreadedComments {
let inner = match Arc::try_unwrap(self.inner) {
Ok(inner) => inner,
Err(inner) => MultiThreadedCommentsInner {
leading: inner.leading.clone(),
trailing: inner.trailing.clone(),
},
};
let leading = Rc::new(RefCell::new(inner.leading));
let trailing = Rc::new(RefCell::new(inner.trailing));
SingleThreadedComments::from_leading_and_trailing(leading, trailing)
}

/// Gets a reference to the leading comment map.
pub fn leading_map(&self) -> &SingleThreadedCommentsMapInner {
&self.inner.leading
Expand All @@ -63,16 +84,19 @@ impl MultiThreadedComments {

/// Gets a vector of all the comments sorted by position.
pub fn get_vec(&self) -> Vec<Comment> {
let mut comments = self
let mut comments = self.iter_unstable().cloned().collect::<Vec<_>>();
comments.sort_by_key(|comment| comment.span.lo);
comments
}

/// Iterates through all the comments in an unstable order.
pub fn iter_unstable(&self) -> impl Iterator<Item = &Comment> {
self
.inner
.leading
.values()
.chain(self.inner.trailing.values())
.flatten()
.cloned()
.collect::<Vec<_>>();
comments.sort_by_key(|comment| comment.span.lo);
comments
}

pub fn has_leading(&self, pos: SourcePos) -> bool {
Expand All @@ -91,6 +115,9 @@ impl MultiThreadedComments {
self.inner.trailing.get(&pos.as_byte_pos())
}

/// Gets the comments as an `SwcComments` trait.
///
/// Calling this is fast because it uses a shared reference.
pub fn as_swc_comments(&self) -> Box<dyn SwcComments> {
Box::new(SwcMultiThreadedComments(self.clone()))
}
Expand Down
56 changes: 32 additions & 24 deletions src/dep.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use std::collections::HashMap;

use ast::Module;
use serde::Deserialize;
use serde::Serialize;

Expand All @@ -10,9 +11,9 @@ use crate::swc::ast::Callee;
use crate::swc::ast::Expr;
use crate::swc::atoms::Atom;
use crate::swc::common::comments::CommentKind;
use crate::swc::common::comments::Comments;
use crate::swc::visit::Visit;
use crate::swc::visit::VisitWith;
use crate::MultiThreadedComments;
use crate::ParsedSource;
use crate::SourcePos;
use crate::SourceRange;
Expand All @@ -21,20 +22,27 @@ use crate::SourceRangedForSpanned;
impl ParsedSource {
/// Analyzes the module for a list of its imports and exports.
pub fn analyze_dependencies(&self) -> Vec<DependencyDescriptor> {
let module = match self.program_ref() {
ast::Program::Module(module) => module,
ast::Program::Script(_) => return vec![],
};

let mut v = DependencyCollector {
comments: &self.comments().as_swc_comments(),
items: vec![],
};
module.visit_with(&mut v);
v.items
match self.program_ref() {
ast::Program::Module(module) => {
analyze_module_dependencies(module, self.comments())
}
ast::Program::Script(_) => vec![],
}
}
}

pub fn analyze_module_dependencies(
module: &Module,
comments: &MultiThreadedComments,
) -> Vec<DependencyDescriptor> {
let mut v = DependencyCollector {
comments,
items: vec![],
};
module.visit_with(&mut v);
v.items
}

#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub enum DependencyKind {
Expand Down Expand Up @@ -157,23 +165,23 @@ pub enum DynamicTemplatePart {
}

struct DependencyCollector<'a> {
comments: &'a dyn Comments,
comments: &'a MultiThreadedComments,
pub items: Vec<DependencyDescriptor>,
}

impl<'a> DependencyCollector<'a> {
fn get_leading_comments(&self, start: SourcePos) -> Vec<DependencyComment> {
self
.comments
.get_leading(start.as_byte_pos())
.unwrap_or_default()
.into_iter()
.map(|c| DependencyComment {
kind: c.kind,
range: c.range(),
text: c.text,
})
.collect()
match self.comments.get_leading(start) {
Some(leading) => leading
.iter()
.map(|c| DependencyComment {
kind: c.kind,
range: c.range(),
text: c.text.clone(),
})
.collect(),
None => Vec::new(),
}
}
}

Expand Down
9 changes: 2 additions & 7 deletions src/parsed_source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -117,13 +117,8 @@ impl ParsedSource {

/// Get the source's leading comments, where triple slash directives might
/// be located.
pub fn get_leading_comments(&self) -> Vec<Comment> {
self
.inner
.comments
.get_leading(self.inner.program.range().start)
.cloned()
.unwrap_or_default()
pub fn get_leading_comments(&self) -> Option<&Vec<Comment>> {
self.inner.comments.get_leading(self.inner.program.start())
}

/// Gets the tokens found in the source file.
Expand Down
4 changes: 2 additions & 2 deletions src/parsing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,8 +299,8 @@ mod test {
program.script().body[0],
crate::swc::ast::Stmt::Expr(..)
));
assert_eq!(program.get_leading_comments().len(), 1);
assert_eq!(program.get_leading_comments()[0].text, " 1");
assert_eq!(program.get_leading_comments().unwrap().len(), 1);
assert_eq!(program.get_leading_comments().unwrap()[0].text, " 1");
assert_eq!(program.tokens().len(), 3);
assert_eq!(program.comments().get_vec().len(), 2);
}
Expand Down
5 changes: 3 additions & 2 deletions src/transpiling/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,8 @@ impl ParsedSource {
Ok(specifier) => FileName::Url(specifier),
Err(_) => FileName::Custom(self.specifier().to_string()),
};
source_map.new_source_file(file_name, self.text_info().text().to_string());
source_map
.new_source_file(file_name, self.text_info().text_str().to_string());
// needs to align with what's done internally in source map
assert_eq!(1, self.text_info().range().start.as_byte_pos().0);
// we need the comments to be mutable, so make it single threaded
Expand Down Expand Up @@ -473,7 +474,7 @@ fn is_fatal_syntax_error(error_kind: &SyntaxError) -> bool {
)
}

pub(crate) fn swc_codegen_config() -> crate::swc::codegen::Config {
pub fn swc_codegen_config() -> crate::swc::codegen::Config {
// NOTICE ON UPGRADE: This struct has #[non_exhaustive] on it,
// which prevents creating a struct expr here. For that reason,
// inspect the struct on swc upgrade and explicitly specify any
Expand Down

0 comments on commit 6dfab72

Please sign in to comment.