astring
astring copied to clipboard
Control of semicolon behaviour
Motivation
I'm using astring as part of an atom plugin to help with code generation. It would be great to be able to control whether semicolons are emitted, so that I can match the current style directives of the current project. Right now, semicolons are implemented as a whole bunch of state.write(';') instances.
It would be awesome to have a config option to control semicolon emission. I'm thinking that you could replace all those writes with a semantic state.terminate(), which can check if it should print a semicolon or not.
The only alternative to control this is to basically fork the entire baseGenerator, so you can remove all those writes.
This could be handled through a custom output stream, that removes semicolons:
const output = {
code: '',
write(code) {
switch (code) {
case ';':
break
case ');':
this.code += ')'
break
case 'debugger;':
this.code += 'debugger'
break
default:
this.code += code
break
}
},
}
const { code } = astring.generate(ast, { output })
console.log('Code without semicolons:', code)
There are however two known issues to this:
- Not all semicolons can be removed, in particular, when the next expression starts with a parenthesis.
- Using a custom output stream has some performance hits.
Thus, a more precise handling is required. This could be a first step towards version 2. Pull requests are welcome.
+1 ! I was just about to go for "The only alternative to control this" according to @eddiesholl before checking the issues here.
I will submit a PR right after
I looked at this issue and it isn't super hard to implement. For example use an extra function param on statement level. noSemi.
Then in BlockStatement and Program within the iteration loop set the param value to either true or false. Depends if the element is the last one in that array.
Before looping you always set the value to false.
Then you can print semi only if noSemi is falsy.
Don't forget the IfStatement edge case!
Regarding parents. For example as in this example this will be smashed into one, but still valid JS.
{
(Foo)
Bar
} `
Quick follow up. If you want an option to enable the semis it's possible if you avoid printing the semicolon if .!Opt.Semi || noSemi.
Also be aware that noSemi has to be falsy before entering any blocks.
@KFlash did you check my PR above ?