Skip to content

Commit 932351a

Browse files
committed
refactor: use deno_ast
1 parent ffba355 commit 932351a

18 files changed

+572
-627
lines changed

Cargo.toml

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,11 @@ wasm = ["serde_json", "dprint-core/wasm"]
2525
tracing = ["dprint-core/tracing"]
2626

2727
[dependencies]
28+
deno_ast = { version = "0.4.0", features = ["view"] }
2829
dprint-core = { version = "0.46.4", features = ["formatting"] }
2930
rustc-hash = "1.1.0"
3031
serde = { version = "1.0.118", features = ["derive"] }
3132
serde_json = { version = "1.0", optional = true }
32-
swc_ast_view = { version = "0.39.0", package = "dprint-swc-ecma-ast-view" }
33-
swc_common = "0.13.4"
34-
swc_ecmascript = { version = "0.73.0", features = ["parser"] }
3533

3634
[target.'cfg(target_arch = "wasm32")'.dependencies]
3735
parking_lot_core = "=0.8.0" # https://github.com/Amanieu/parking_lot/issues/269 todo: submit pr to parking_lot

src/format_text.rs

Lines changed: 73 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
use std::path::Path;
22

3+
use deno_ast::ParsedSource;
34
use dprint_core::configuration::resolve_new_line_kind;
45
use dprint_core::formatting::*;
56
use dprint_core::types::ErrBox;
6-
use swc_common::comments::SingleThreadedCommentsMapInner;
7-
use swc_ecmascript::parser::token::TokenAndSpan;
7+
8+
use crate::swc::ensure_no_specific_syntax_errors;
89

910
use super::configuration::Configuration;
1011
use super::parsing::parse;
@@ -39,75 +40,40 @@ use super::swc::parse_swc_ast;
3940
/// ```
4041
pub fn format_text(file_path: &Path, file_text: &str, config: &Configuration) -> Result<String, ErrBox> {
4142
if super::utils::file_text_has_ignore_comment(file_text, &config.ignore_file_comment_text) {
42-
return Ok(String::from(file_text));
43+
Ok(String::from(file_text))
44+
} else {
45+
let parsed_source = parse_swc_ast(file_path, file_text)?;
46+
inner_format(&parsed_source, config)
4347
}
44-
45-
let parsed_source_file = parse_swc_ast(file_path, file_text)?;
46-
Ok(dprint_core::formatting::format(
47-
|| {
48-
let print_items = parse(
49-
&SourceFileInfo {
50-
is_jsx: parsed_source_file.is_jsx,
51-
module: &parsed_source_file.module,
52-
info: &parsed_source_file.info,
53-
tokens: &parsed_source_file.tokens,
54-
leading_comments: &parsed_source_file.leading_comments,
55-
trailing_comments: &parsed_source_file.trailing_comments,
56-
},
57-
config,
58-
);
59-
// println!("{}", print_items.get_as_text());
60-
print_items
61-
},
62-
config_to_print_options(file_text, config),
63-
))
6448
}
6549

66-
#[derive(Clone)]
67-
pub struct SourceFileInfo<'a> {
68-
pub is_jsx: bool,
69-
pub module: &'a swc_ecmascript::ast::Module,
70-
pub info: &'a dyn swc_ast_view::SourceFile,
71-
pub tokens: &'a [TokenAndSpan],
72-
pub leading_comments: &'a SingleThreadedCommentsMapInner,
73-
pub trailing_comments: &'a SingleThreadedCommentsMapInner,
50+
/// Formats an already parsed source. This is useful as a performance optimization.
51+
pub fn format_parsed_source(source: &ParsedSource, config: &Configuration) -> Result<String, ErrBox> {
52+
if super::utils::file_text_has_ignore_comment(source.source().text_str(), &config.ignore_file_comment_text) {
53+
Ok(source.source().text_str().to_string())
54+
} else {
55+
inner_format(source, config)
56+
}
7457
}
7558

76-
/// Formats the already parsed file. This is useful as a performance optimization.
77-
pub fn format_parsed_file(info: &SourceFileInfo<'_>, config: &Configuration) -> String {
78-
if super::utils::file_text_has_ignore_comment(info.info.text(), &config.ignore_file_comment_text) {
79-
return info.info.text().to_string();
80-
}
59+
fn inner_format(parsed_source: &ParsedSource, config: &Configuration) -> Result<String, ErrBox> {
60+
ensure_no_specific_syntax_errors(parsed_source)?;
8161

82-
dprint_core::formatting::format(
62+
Ok(dprint_core::formatting::format(
8363
|| {
84-
let print_items = parse(&info, config);
64+
let print_items = parse(&parsed_source, config);
8565
// println!("{}", print_items.get_as_text());
8666
print_items
8767
},
88-
config_to_print_options(info.info.text(), config),
89-
)
68+
config_to_print_options(parsed_source.source().text_str(), config),
69+
))
9070
}
9171

9272
#[cfg(feature = "tracing")]
9373
pub fn trace_file(file_path: &Path, file_text: &str, config: &Configuration) -> dprint_core::formatting::TracingResult {
94-
let parsed_source_file = parse_swc_ast(file_path, file_text).expect("Expected to parse to SWC AST.");
95-
dprint_core::formatting::trace_printing(
96-
|| {
97-
parse(
98-
&SourceFileInfo {
99-
is_jsx: parsed_source_file.is_jsx,
100-
info: &parsed_source_file.info,
101-
module: &parsed_source_file.module,
102-
tokens: &parsed_source_file.tokens,
103-
leading_comments: &parsed_source_file.leading_comments,
104-
trailing_comments: &parsed_source_file.trailing_comments,
105-
},
106-
config,
107-
)
108-
},
109-
config_to_print_options(file_text, config),
110-
)
74+
let parsed_source = parse_swc_ast(file_path, file_text).unwrap();
75+
ensure_no_specific_syntax_errors(parsed_source).unwrap();
76+
dprint_core::formatting::trace_printing(|| parse(&parsed_source, config), config_to_print_options(file_text, config))
11177
}
11278

11379
fn config_to_print_options(file_text: &str, config: &Configuration) -> PrintOptions {
@@ -118,3 +84,53 @@ fn config_to_print_options(file_text: &str, config: &Configuration) -> PrintOpti
11884
new_line_text: resolve_new_line_kind(file_text, config.new_line_kind),
11985
}
12086
}
87+
88+
#[cfg(test)]
89+
mod test {
90+
use std::path::PathBuf;
91+
92+
use crate::configuration::ConfigurationBuilder;
93+
94+
use super::*;
95+
96+
#[test]
97+
fn it_should_error_for_no_equals_sign_in_var_decl() {
98+
run_diagnostic_test(
99+
"./test.ts",
100+
"const Methods {\nf: (x, y) => x + y,\n};",
101+
concat!("Line 1, column 15: Expected a semicolon\n", "\n", " const Methods {\n", " ~"),
102+
);
103+
}
104+
105+
#[test]
106+
fn it_should_error_when_var_stmts_sep_by_comma() {
107+
run_diagnostic_test(
108+
"./test.ts",
109+
"let a = 0, let b = 1;",
110+
concat!(
111+
"Line 1, column 16: Expected a semicolon\n",
112+
"\n",
113+
" let a = 0, let b = 1;\n",
114+
" ~"
115+
),
116+
);
117+
}
118+
119+
#[test]
120+
fn it_should_error_for_exected_expr_issue_121() {
121+
run_diagnostic_test(
122+
"./test.ts",
123+
"type T =\n | unknown\n { } & unknown;",
124+
concat!("Line 3, column 7: Expression expected\n", "\n", " { } & unknown;\n", " ~"),
125+
);
126+
}
127+
128+
fn run_diagnostic_test(file_path: &str, text: &str, expected: &str) {
129+
let file_path = PathBuf::from(file_path);
130+
let parsed_source = crate::swc::parse_swc_ast(&file_path, text).unwrap();
131+
let config = ConfigurationBuilder::new().build();
132+
// ensure it happens for both of these methods
133+
assert_eq!(format_text(&file_path, text, &config).err().unwrap().to_string(), expected);
134+
assert_eq!(format_parsed_source(&parsed_source, &config).err().unwrap().to_string(), expected);
135+
}
136+
}

src/lib.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ mod parsing;
66
mod swc;
77
mod utils;
88

9-
pub use format_text::format_parsed_file;
9+
pub use format_text::format_parsed_source;
1010
pub use format_text::format_text;
11-
pub use format_text::SourceFileInfo;
1211

1312
#[cfg(feature = "tracing")]
1413
pub use format_text::trace_file;

src/parsing/comments.rs

Lines changed: 14 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
1-
use swc_ast_view::*;
2-
use swc_common::BytePos;
3-
use swc_ecmascript::parser::token::Token;
4-
use swc_ecmascript::parser::token::TokenAndSpan;
1+
use deno_ast::swc::common::BytePos;
2+
use deno_ast::swc::parser::token::Token;
3+
use deno_ast::swc::parser::token::TokenAndSpan;
4+
use deno_ast::view::*;
55

66
pub struct CommentTracker<'a> {
7-
module: &'a Module<'a>,
7+
program: &'a Program<'a>,
88
tokens: &'a [TokenAndSpan],
99
token_index: usize,
1010
}
1111

1212
impl<'a> CommentTracker<'a> {
13-
pub fn new(module: &'a Module<'a>, tokens: &'a [TokenAndSpan]) -> CommentTracker<'a> {
13+
pub fn new(program: &'a Program<'a>, tokens: &'a [TokenAndSpan]) -> CommentTracker<'a> {
1414
CommentTracker {
15-
module,
15+
program,
1616
tokens,
1717
token_index: 0,
1818
}
@@ -26,18 +26,18 @@ impl<'a> CommentTracker<'a> {
2626
// get any comments stored at the beginning of the file
2727
// todo: investigate what's required here
2828
let file_start = BytePos(0);
29-
iterator.extend(file_start.leading_comments_fast(self.module));
30-
iterator.extend(file_start.trailing_comments_fast(self.module));
29+
iterator.extend(file_start.leading_comments_fast(self.program));
30+
iterator.extend(file_start.trailing_comments_fast(self.program));
3131
} else if let Some(previous_token) = self.tokens.get(self.token_index - 1) {
32-
iterator.extend(previous_token.hi().trailing_comments_fast(self.module));
32+
iterator.extend(previous_token.hi().trailing_comments_fast(self.program));
3333
}
3434

3535
while let Some(token) = self.tokens.get(self.token_index) {
36-
iterator.extend(token.lo().leading_comments_fast(self.module));
36+
iterator.extend(token.lo().leading_comments_fast(self.program));
3737

3838
let token_hi = token.hi();
3939
if token_hi < pos {
40-
iterator.extend(token_hi.trailing_comments_fast(self.module));
40+
iterator.extend(token_hi.trailing_comments_fast(self.program));
4141
self.token_index += 1;
4242
} else {
4343
break;
@@ -52,7 +52,7 @@ impl<'a> CommentTracker<'a> {
5252
let mut iterator = CommentsIterator::new(Vec::new());
5353

5454
while let Some(token) = self.tokens.get(self.token_index) {
55-
iterator.extend(token.lo().leading_comments_fast(self.module));
55+
iterator.extend(token.lo().leading_comments_fast(self.program));
5656

5757
let is_comma = token.token == Token::Comma;
5858
if !is_comma && token.lo() >= end {
@@ -61,7 +61,7 @@ impl<'a> CommentTracker<'a> {
6161

6262
let token_hi = token.hi();
6363
if is_comma || token_hi <= end {
64-
iterator.extend(token.hi().trailing_comments_fast(self.module));
64+
iterator.extend(token.hi().trailing_comments_fast(self.program));
6565
self.token_index += 1;
6666
} else {
6767
break;

src/parsing/context.rs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1+
use deno_ast::swc::common::comments::Comment;
2+
use deno_ast::swc::common::BytePos;
3+
use deno_ast::swc::common::Span;
4+
use deno_ast::swc::common::Spanned;
5+
use deno_ast::swc::parser::token::TokenAndSpan;
6+
use deno_ast::view::*;
17
use dprint_core::formatting::{ConditionReference, Info};
28
use rustc_hash::FxHashMap;
39
use rustc_hash::FxHashSet;
4-
use swc_ast_view::*;
5-
use swc_common::comments::Comment;
6-
use swc_common::BytePos;
7-
use swc_common::Span;
8-
use swc_common::Spanned;
9-
use swc_ecmascript::parser::token::TokenAndSpan;
1010

1111
use super::*;
1212
use crate::configuration::*;
1313
use crate::utils::Stack;
1414

1515
pub struct Context<'a> {
1616
pub is_jsx: bool,
17-
pub module: &'a Module<'a>,
17+
pub program: &'a Program<'a>,
1818
pub config: &'a Configuration,
1919
pub comments: CommentTracker<'a>,
2020
pub token_finder: TokenFinder<'a>,
@@ -33,13 +33,13 @@ pub struct Context<'a> {
3333
}
3434

3535
impl<'a> Context<'a> {
36-
pub fn new(is_jsx: bool, tokens: &'a [TokenAndSpan], current_node: Node<'a>, module: &'a Module, config: &'a Configuration) -> Context<'a> {
36+
pub fn new(is_jsx: bool, tokens: &'a [TokenAndSpan], current_node: Node<'a>, program: &'a Program<'a>, config: &'a Configuration) -> Context<'a> {
3737
Context {
3838
is_jsx,
39-
module,
39+
program,
4040
config,
41-
comments: CommentTracker::new(module, tokens),
42-
token_finder: TokenFinder::new(module),
41+
comments: CommentTracker::new(program, tokens),
42+
token_finder: TokenFinder::new(program),
4343
current_node,
4444
parent_stack: Stack::new(),
4545
handled_comments: FxHashSet::default(),
@@ -136,7 +136,7 @@ impl<'a> Context<'a> {
136136

137137
#[cfg(debug_assertions)]
138138
pub fn assert_text(&self, span: Span, expected_text: &str) {
139-
let actual_text = span.text_fast(self.module);
139+
let actual_text = span.text_fast(self.program);
140140
if actual_text != expected_text {
141141
panic!("Debug Panic Expected text `{}`, but found `{}`", expected_text, actual_text)
142142
}

0 commit comments

Comments
 (0)