New ASI hazards, ruin semicolon-less coding style
semicolon-less, leading semicolon
The leading semicolon rule is simple:
when starting a statement in new line,
insert leading semicolon iff the first
character is (
, [
, +
, -
, /
and ```.
test()
;[1, 2, 3, 4].forEach(n => console.log(n))
Public field add several new ASI hazards
class Test {
x = 1
[key] = 2 // miss leading semicolon
}
class Test {
x = 1
[Symbol.iterator]() { ... } // miss leading semicolon
}
class Test {
x = 1
*f() { ... } // miss leading semicolon
}
These three cases are ok. The first two
already covered by leading semicolon rule.
For the third, we need to add *
case.
It's ok, actually make the rule simpler:
... iff the first character is:
-
([
(open parens) -
+-*/
(the notation of four arithmetic binary operators) -
`` ` (template string)
-
rarely use
-
syntax error
class Test1 {
out
in
name
}
\
// Test2 actually is class { out = 'out' in name }
class Test2 {
out = 'out'
in
name
}
This case is bad. We need an extra leading
semicolon rule: insert leading semicolon
if you are in class body and the first
character token is in
or instanceof
.
- no error
- different semantics
class Test1 {
set = new Set
\
/** f method ... */
f(x) { ... }
}
\
// Test2 actually is class { set f() { ... } }
class Test2 {
set
\
/** f method ... */
f(x) { ... }
}
This case is the worst. We need a special rule:
insert leading semicolon if you are in class body
and the previous line is set
, get
or static
.
The core value of the leading semicolon rule is you never look backward, and this case just ruin it.
-
no error
-
different semantics
-
eslint
Possible Solutions
New ESLint rule: no-keyword-name-field
class Test {
out
'in'
'instanceof'
'set'
'get'
'static'
f() { ... }
}
class Test {
'set' = new Set
'in' = 'India'
}
So weird...
New ESLint rule: prefer-decorator-for-field
class Test {
@field out = new WritableStream()
@field in = new ReadableStream()
@field set = new Set()
f() { ... }
}
- rely on linter
- rely on decorator (only stage 2)
- rely on transpiler
- coding style agreement
Add keyword!
class Test {
<keyword> out = new WritableStream()
<keyword> in = new ReadableStream()
<keyword> set = new Set()
f() { ... }
}
- 工具链实现成本
- 版本更新
- 代码规范跟进
- 版本更新
- 下游配置
- 版本更新
- 团队讨论
Transfer the cost from committee (100) to community (1,000,000)