Attach comments to correct node (#541)

This commit is contained in:
강동윤 2019-12-28 22:02:58 +09:00 committed by GitHub
parent 3cf1caa4b1
commit 702800e0d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
42 changed files with 115 additions and 67 deletions

View File

@ -1,6 +1,6 @@
[package]
name = "swc_common"
version = "0.4.3"
version = "0.4.4"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"

View File

@ -27,10 +27,18 @@ impl Comments {
});
}
pub fn take_trailing_comments(&self, pos: BytePos) -> Option<Vec<Comment>> {
self.trailing.remove(&pos)
}
pub fn trailing_comments(&self, pos: BytePos) -> Option<ReadGuard<'_, BytePos, Vec<Comment>>> {
self.trailing.get(&pos)
}
pub fn take_leading_comments(&self, pos: BytePos) -> Option<Vec<Comment>> {
self.leading.remove(&pos)
}
pub fn leading_comments(&self, pos: BytePos) -> Option<ReadGuard<'_, BytePos, Vec<Comment>>> {
self.leading.get(&pos)
}

View File

@ -1,6 +1,6 @@
[package]
name = "swc_ecma_codegen"
version = "0.11.0"
version = "0.12.0"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
@ -12,7 +12,7 @@ edition = "2018"
bitflags = "1"
hashbrown = "0.6"
swc_atoms = { version = "0.2", path ="../../atoms" }
swc_common = { version = "0.4.0", path ="../../common" }
swc_common = { version = "0.4.4", path ="../../common" }
swc_ecma_ast = { version = "0.13.0", path ="../ast" }
swc_ecma_codegen_macros = { version = "0.4", path ="./macros" }
sourcemap = "4.1.1"

View File

@ -119,7 +119,6 @@ fn emit_colors(b: &mut Bencher) {
Some(&mut src_map_builder),
),
handlers,
pos_of_leading_comments: Default::default(),
};
emitter.emit_module(&module)

View File

@ -48,7 +48,7 @@ impl<'a> Emitter<'a> {
None => return Ok(()),
};
let cmts = comments.trailing_comments(pos);
let cmts = comments.take_trailing_comments(pos);
write_comments!(self, prefix_space, &cmts)
}
@ -63,11 +63,6 @@ impl<'a> Emitter<'a> {
None => return Ok(()),
};
if self.pos_of_leading_comments.contains(&pos) {
return Ok(());
}
self.pos_of_leading_comments.insert(pos);
write_comments!(self, false, comments.leading_comments(pos))
write_comments!(self, false, comments.take_leading_comments(pos))
}
}

View File

@ -7,7 +7,6 @@ use self::{
text_writer::WriteJs,
util::{SourceMapperExt, SpanExt, StartsWithAlphaNum},
};
use hashbrown::HashSet;
use std::{io, sync::Arc};
use swc_atoms::JsWord;
use swc_common::{comments::Comments, BytePos, SourceMap, Span, Spanned, SyntaxContext, DUMMY_SP};
@ -56,7 +55,6 @@ pub struct Emitter<'a> {
pub comments: Option<&'a Comments>,
pub wr: Box<(dyn 'a + WriteJs)>,
pub handlers: Box<(dyn 'a + Handlers)>,
pub pos_of_leading_comments: HashSet<BytePos>,
}
impl<'a> Emitter<'a> {
@ -1371,6 +1369,8 @@ impl<'a> Emitter<'a> {
}
}
child.emit_with(self)?;
// Emit this child.
if should_emit_intervening_comments {
let comment_range = child.comment_range();
@ -1379,8 +1379,6 @@ impl<'a> Emitter<'a> {
should_emit_intervening_comments = may_emit_intervening_comments;
}
child.emit_with(self)?;
if should_decrease_indent_after_emit {
self.wr.decrease_indent()?;
should_decrease_indent_after_emit = false;
@ -1684,10 +1682,8 @@ impl<'a> Emitter<'a> {
let need_paren = if let Some(cmt) = self.comments {
let lo = node.arg.span().lo();
!self.pos_of_leading_comments.contains(&lo) && {
// see #415
cmt.leading_comments(lo).is_some()
}
// see #415
cmt.leading_comments(lo).is_some()
} else {
false
};

View File

@ -29,7 +29,6 @@ impl Builder {
wr: Box::new(text_writer::JsWriter::new(self.cm.clone(), "\n", s, None)),
comments: Some(&self.comments),
handlers: Box::new(Noop),
pos_of_leading_comments: Default::default(),
};
let ret = op(&mut e);

View File

@ -7,8 +7,6 @@ c: {
for(var b = 3; b < 4; b++){
if (b > 5) break; // this break refers to the for, not to the switch; thus it
// this break refers to the for, not to the switch; thus it
// shouldn't ruin our optimization
d.e(b);
}

View File

@ -1,5 +1,6 @@
while(true){
break; /* Multiline
break;
/* Multiline
Comment */
a;
}

View File

@ -1,3 +1,4 @@
switch(a){
case 1: b();
case 1: /* perfect */
b();
}

View File

@ -1,4 +1,5 @@
b: while(1){
continue; /**/
continue;
/**/
a;
}

View File

@ -2,6 +2,4 @@
throw 'a';
with (b); // This should be removed.
// This should be removed.
}());

View File

@ -1,3 +1,3 @@
if (a) {
b(); /* Some comment */
b();
}

View File

@ -1,4 +1,5 @@
b: while(1){
continue; /**/
continue;
/**/
a;
}

View File

@ -1 +1,2 @@
(a + b) * c;
(a + /* assignment */
b) * c;

View File

@ -1,4 +1,2 @@
for(;;)continue; // should be empty statement
// should be empty statement

View File

@ -1 +1 @@
var //fooa = 1; //foo
var a = 1//foo;

View File

@ -1,4 +1,5 @@
({
(/* comment */
{
a: null,
b: null
});

View File

@ -1,5 +1,6 @@
b: while(1){
continue; /*
continue;
/*
*/
a;
}

View File

@ -1,3 +1,4 @@
({
(/* comment */
{
a: null
});

View File

@ -1,5 +1,6 @@
while(true){
continue; /* Multiline
continue;
/* Multiline
Comment */
a;
}

View File

@ -1,4 +1,5 @@
({
(/* comment */
{
/* comment 2 */
a: null
});

View File

@ -1 +1,2 @@
throw a;
throw /* */
a;

View File

@ -22,8 +22,6 @@
var a;
if (b) return; // I would insert something there, but I'm sort of lazy so whatever.
// I would insert something there, but I'm sort of lazy so whatever.
a = new c();
return a;
})();

View File

@ -1,4 +1,3 @@
switch(a){
case 1: /* perfect */
b(); /* perfect */
case 1: b();
}

View File

@ -1,4 +1,2 @@
while(true)continue; // should be empty statement
// should be empty statement

View File

@ -1,4 +1,2 @@
for(var a in b)continue; // should be empty statement
// should be empty statement

View File

@ -1,4 +1,5 @@
b: while(1){
continue; /* */
continue;
/* */
a;
}

View File

@ -1,2 +1,2 @@
var /* comment */
a;
var a/* comment */
;

View File

@ -1,5 +1,6 @@
b: while(1){
continue; /*
continue;
/*
*/
a;
}

View File

@ -165,7 +165,6 @@ fn error_tests(tests: &mut Vec<TestDescAndFn>) -> Result<(), io::Error> {
),
comments: Some(&comments),
handlers,
pos_of_leading_comments: Default::default(),
};
// Parse source

View File

@ -1,6 +1,6 @@
[package]
name = "swc_ecma_parser"
version = "0.15.1"
version = "0.15.2"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"

View File

@ -42,7 +42,10 @@ enum TokenType {
JSXText,
JSXTagStart,
JSXTagEnd,
Other { before_expr: bool },
Other {
before_expr: bool,
can_have_trailing_comment: bool,
},
}
impl TokenType {
fn before_expr(self) -> bool {
@ -57,7 +60,7 @@ impl TokenType {
TokenType::JSXText | TokenType::Colon | TokenType::LBrace | TokenType::Semi => true,
TokenType::BinOp(b) => b.before_expr(),
TokenType::Keyword(k) => k.before_expr(),
TokenType::Other { before_expr } => before_expr,
TokenType::Other { before_expr, .. } => before_expr,
}
}
}
@ -80,6 +83,18 @@ impl<'a> From<&'a Token> for TokenType {
Token::Word(Word::Keyword(k)) => TokenType::Keyword(k),
_ => TokenType::Other {
before_expr: t.before_expr(),
can_have_trailing_comment: match *t {
Token::Num(..)
| Token::Str { .. }
| Token::Word(Word::Ident(..))
| Token::DollarLBrace
| Token::Regex(..)
| Token::BigInt(..)
| Token::JSXText { .. }
| Token::RBrace => true,
_ => false,
},
},
}
}
@ -278,9 +293,14 @@ impl State {
.unwrap_or(false)
}
pub fn last_was_return(&self) -> bool {
pub fn can_have_trailing_comment(&self) -> bool {
match self.token_type {
Some(TokenType::Keyword(Keyword::Return)) => true,
Some(TokenType::Keyword(..)) => false,
Some(TokenType::Semi) | Some(TokenType::LBrace) => true,
Some(TokenType::Other {
can_have_trailing_comment,
..
}) => can_have_trailing_comment,
_ => false,
}
}

View File

@ -218,7 +218,7 @@ impl<'a, I: Input> Lexer<'a, I> {
false
};
let is_for_next = self.state.had_line_break || self.state.last_was_return();
let is_for_next = self.state.had_line_break || !self.state.can_have_trailing_comment();
while let Some(c) = self.cur() {
if was_star && c == '/' {
@ -234,13 +234,14 @@ impl<'a, I: Input> Lexer<'a, I> {
span: Span::new(start, pos, SyntaxContext::empty()),
text: s.into(),
};
let peek = self.input.peek();
if is_for_next {
self.leading_comments_buffer.as_mut().unwrap().push(cmt);
} else {
comments.add_trailing(self.state.prev_hi, cmt);
}
}
// TODO: push comment
return Ok(());
}
if c.is_line_break() {

View File

@ -212,7 +212,6 @@ fn exec(c: PresetConfig, dir: PathBuf) -> Result<(), Error> {
None,
),
handlers,
pos_of_leading_comments: Default::default(),
};
emitter.emit_module(m).expect("failed to emit module");

View File

@ -1,6 +1,6 @@
[package]
name = "swc_ecma_transforms"
version = "0.3.0"
version = "0.3.1"
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
license = "Apache-2.0/MIT"
repository = "https://github.com/swc-project/swc.git"
@ -31,7 +31,7 @@ smallvec = "1"
[dev-dependencies]
testing = { version = "0.4", path ="../../testing" }
swc_ecma_codegen = { version = "0.11.0", path ="../codegen" }
swc_ecma_codegen = { version = "0.12.0", path ="../codegen" }
tempfile = "3"
pretty_assertions = "0.6"
sourcemap = "4.1.1"

View File

@ -151,7 +151,6 @@ impl<'a> Tester<'a> {
),
comments: None,
handlers,
pos_of_leading_comments: Default::default(),
};
// println!("Emitting: {:?}", module);

View File

@ -161,7 +161,6 @@ impl<'a> Tester<'a> {
),
comments: None,
handlers,
pos_of_leading_comments: Default::default(),
};
// println!("Emitting: {:?}", module);

View File

@ -184,7 +184,6 @@ fn error_tests(tests: &mut Vec<TestDescAndFn>) -> Result<(), io::Error> {
),
comments: None,
handlers,
pos_of_leading_comments: Default::default(),
};
let mut expected_emitter = Emitter {
cfg: swc_ecma_codegen::Config { minify: false },
@ -194,7 +193,6 @@ fn error_tests(tests: &mut Vec<TestDescAndFn>) -> Result<(), io::Error> {
),
comments: None,
handlers: handlers2,
pos_of_leading_comments: Default::default(),
};
// Parse source

View File

@ -161,7 +161,6 @@ impl Compiler {
},
),
handlers,
pos_of_leading_comments: Default::default(),
};
emitter

View File

@ -298,3 +298,33 @@ fn env_query_chrome_71() {
fn project_env() {
project("tests/projects/env/");
}
#[test]
fn issue_532() {
let f = file("tests/projects/issue-532-block/input.js")
.unwrap()
.replace(" ", "");
let f = f.trim();
println!("{}", f);
assert_eq!(
f,
"\
/*pre:1*/
test();
test(123/*post:3*/
);
test(/*pre:4*/
123);
test(/*pre:5*/
123/*post:6*/
);
test(/*pre:7*/
123,/*pre:8*/
456);
test(123/*post:9*/
,456/*post:10*/
);"
)
}

View File

@ -0,0 +1,7 @@
/*pre: 1*/
test(/*2*/);
test(123/*post: 3*/);
test(/*pre: 4*/123);
test(/*pre: 5*/123/*post: 6*/);
test(/*pre: 7*/123,/*pre: 8*/456);
test(123/*post: 9*/,456/*post: 10*/);