Skip to content

Commit 6cfd8b2

Browse files
committed
Make the indent rules supports ECMAScript 2020
1 parent 67b3e79 commit 6cfd8b2

26 files changed

+341
-25
lines changed

Diff for: docs/rules/html-indent.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ description: enforce consistent indentation in `<template>`
1515
This rule enforces a consistent indentation style in `<template>`. The default style is 2 spaces.
1616

1717
- This rule checks all tags, also all expressions in directives and mustaches.
18-
- In the expressions, this rule supports ECMAScript 2017 syntaxes. It ignores unknown AST nodes, but it might be confused by non-standard syntaxes.
18+
- In the expressions, this rule supports ECMAScript 2020 syntaxes. It ignores unknown AST nodes, but it might be confused by non-standard syntaxes.
1919

2020
<eslint-code-block fix :rules="{'vue/html-indent': ['error']}">
2121

Diff for: lib/utils/indent-common.js

+68-20
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ const KNOWN_NODES = new Set([
5050
'IfStatement',
5151
'ImportDeclaration',
5252
'ImportDefaultSpecifier',
53+
'ImportExpression',
5354
'ImportNamespaceSpecifier',
5455
'ImportSpecifier',
5556
'LabeledStatement',
@@ -61,6 +62,8 @@ const KNOWN_NODES = new Set([
6162
'NewExpression',
6263
'ObjectExpression',
6364
'ObjectPattern',
65+
'OptionalCallExpression',
66+
'OptionalMemberExpression',
6467
'Program',
6568
'Property',
6669
'RestElement',
@@ -99,6 +102,7 @@ const KNOWN_NODES = new Set([
99102
'VStartTag',
100103
'VText'
101104
])
105+
102106
const LT_CHAR = /[\r\n\u2028\u2029]/
103107
const LINES = /[^\r\n\u2028\u2029]+(?:$|\r\n|[\r\n\u2028\u2029])/g
104108
const BLOCK_COMMENT_PREFIX = /^\s*\*/
@@ -290,6 +294,14 @@ function isSemicolon(token) {
290294
function isComma(token) {
291295
return token != null && token.type === 'Punctuator' && token.value === ','
292296
}
297+
/**
298+
* Check whether the given token is a wildcard.
299+
* @param {Token} token The token to check.
300+
* @returns {boolean} `true` if the token is a wildcard.
301+
*/
302+
function isWildcard(token) {
303+
return token != null && token.type === 'Punctuator' && token.value === '*'
304+
}
293305

294306
/**
295307
* Check whether the given token is a whitespace.
@@ -704,7 +716,11 @@ module.exports.defineVisitor = function create(
704716
}
705717
return true
706718
}
707-
if (t === 'CallExpression' || t === 'NewExpression') {
719+
if (
720+
t === 'CallExpression' ||
721+
t === 'NewExpression' ||
722+
t === 'OptionalCallExpression'
723+
) {
708724
const openParen = tokenStore.getTokenAfter(
709725
parent.callee,
710726
isNotRightParen
@@ -1290,7 +1306,7 @@ module.exports.defineVisitor = function create(
12901306
}
12911307
},
12921308

1293-
CallExpression(node) {
1309+
'CallExpression, OptionalCallExpression'(node) {
12941310
const firstToken = tokenStore.getFirstToken(node)
12951311
const rightToken = tokenStore.getLastToken(node)
12961312
const leftToken = tokenStore.getTokenAfter(node.callee, isLeftParen)
@@ -1299,6 +1315,15 @@ module.exports.defineVisitor = function create(
12991315
processNodeList(node.arguments, leftToken, rightToken, 1)
13001316
},
13011317

1318+
ImportExpression(node) {
1319+
const firstToken = tokenStore.getFirstToken(node)
1320+
const rightToken = tokenStore.getLastToken(node)
1321+
const leftToken = tokenStore.getTokenAfter(firstToken, isLeftParen)
1322+
1323+
setOffset(leftToken, 1, firstToken)
1324+
processNodeList([node.source], leftToken, rightToken, 1)
1325+
},
1326+
13021327
CatchClause(node) {
13031328
const firstToken = tokenStore.getFirstToken(node)
13041329
const bodyToken = tokenStore.getFirstToken(node.body)
@@ -1379,7 +1404,20 @@ module.exports.defineVisitor = function create(
13791404
if (isSemicolon(last(tokens))) {
13801405
tokens.pop()
13811406
}
1382-
setOffset(tokens, 1, firstToken)
1407+
if (!node.exported) {
1408+
setOffset(tokens, 1, firstToken)
1409+
} else {
1410+
// export * as foo from "mod"
1411+
const starToken = tokens.find(isWildcard)
1412+
const asToken = tokenStore.getTokenAfter(starToken)
1413+
const exportedToken = tokenStore.getTokenAfter(asToken)
1414+
const afterTokens = tokens.slice(tokens.indexOf(exportedToken) + 1)
1415+
1416+
setOffset(starToken, 1, firstToken)
1417+
setOffset(asToken, 1, starToken)
1418+
setOffset(exportedToken, 1, starToken)
1419+
setOffset(afterTokens, 1, firstToken)
1420+
}
13831421
},
13841422

13851423
ExportDefaultDeclaration(node) {
@@ -1397,20 +1435,25 @@ module.exports.defineVisitor = function create(
13971435
const declarationToken = tokenStore.getFirstToken(node, 1)
13981436
setOffset(declarationToken, 1, exportToken)
13991437
} else {
1400-
// export {foo, bar}; or export {foo, bar} from "mod";
1401-
const leftParenToken = tokenStore.getFirstToken(node, 1)
1402-
const rightParenToken = tokenStore.getLastToken(node, isRightBrace)
1403-
setOffset(leftParenToken, 0, exportToken)
1404-
processNodeList(node.specifiers, leftParenToken, rightParenToken, 1)
1405-
1406-
const maybeFromToken = tokenStore.getTokenAfter(rightParenToken)
1407-
if (
1408-
maybeFromToken != null &&
1409-
sourceCode.getText(maybeFromToken) === 'from'
1410-
) {
1411-
const fromToken = maybeFromToken
1412-
const nameToken = tokenStore.getTokenAfter(fromToken)
1413-
setOffset([fromToken, nameToken], 1, exportToken)
1438+
const firstSpecifier = node.specifiers[0]
1439+
if (!firstSpecifier || firstSpecifier.type === 'ExportSpecifier') {
1440+
// export {foo, bar}; or export {foo, bar} from "mod";
1441+
const leftParenToken = tokenStore.getFirstToken(node, 1)
1442+
const rightParenToken = tokenStore.getLastToken(node, isRightBrace)
1443+
setOffset(leftParenToken, 0, exportToken)
1444+
processNodeList(node.specifiers, leftParenToken, rightParenToken, 1)
1445+
1446+
const maybeFromToken = tokenStore.getTokenAfter(rightParenToken)
1447+
if (
1448+
maybeFromToken != null &&
1449+
sourceCode.getText(maybeFromToken) === 'from'
1450+
) {
1451+
const fromToken = maybeFromToken
1452+
const nameToken = tokenStore.getTokenAfter(fromToken)
1453+
setOffset([fromToken, nameToken], 1, exportToken)
1454+
}
1455+
} else {
1456+
// maybe babel-eslint
14141457
}
14151458
}
14161459
},
@@ -1423,7 +1466,9 @@ module.exports.defineVisitor = function create(
14231466

14241467
'ForInStatement, ForOfStatement'(node) {
14251468
const forToken = tokenStore.getFirstToken(node)
1426-
const leftParenToken = tokenStore.getTokenAfter(forToken)
1469+
const awaitToken =
1470+
(node.await && tokenStore.getTokenAfter(forToken)) || null
1471+
const leftParenToken = tokenStore.getTokenAfter(awaitToken || forToken)
14271472
const leftToken = tokenStore.getTokenAfter(leftParenToken)
14281473
const inToken = tokenStore.getTokenAfter(leftToken, isNotRightParen)
14291474
const rightToken = tokenStore.getTokenAfter(inToken)
@@ -1432,6 +1477,9 @@ module.exports.defineVisitor = function create(
14321477
isNotLeftParen
14331478
)
14341479

1480+
if (awaitToken != null) {
1481+
setOffset(awaitToken, 0, forToken)
1482+
}
14351483
setOffset(leftParenToken, 1, forToken)
14361484
setOffset(leftToken, 1, leftParenToken)
14371485
setOffset(inToken, 1, leftToken)
@@ -1623,7 +1671,7 @@ module.exports.defineVisitor = function create(
16231671
}
16241672
},
16251673

1626-
ImportNamespaceSpecifier(node) {
1674+
'ImportNamespaceSpecifier, ExportNamespaceSpecifier'(node) {
16271675
const tokens = tokenStore.getTokens(node)
16281676
const firstToken = tokens.shift()
16291677
setOffset(tokens, 1, firstToken)
@@ -1637,7 +1685,7 @@ module.exports.defineVisitor = function create(
16371685
setOffset([colonToken, bodyToken], 1, labelToken)
16381686
},
16391687

1640-
'MemberExpression, MetaProperty'(node) {
1688+
'MemberExpression, MetaProperty, OptionalMemberExpression'(node) {
16411689
const objectToken = tokenStore.getFirstToken(node)
16421690
if (node.computed) {
16431691
const leftBracketToken = tokenStore.getTokenBefore(

Diff for: package.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@
5656
},
5757
"devDependencies": {
5858
"@types/node": "^13.13.5",
59-
"@typescript-eslint/parser": "^2.31.0",
59+
"@typescript-eslint/parser": "^3.0.2",
6060
"@vuepress/plugin-pwa": "^1.4.1",
6161
"babel-eslint": "^10.1.0",
6262
"chai": "^4.2.0",
@@ -72,7 +72,7 @@
7272
"mocha": "^7.1.2",
7373
"nyc": "^15.0.1",
7474
"prettier": "^2.0.5",
75-
"typescript": "^3.8.3",
75+
"typescript": "^3.9.3",
7676
"vue-eslint-editor": "^1.1.0",
7777
"vuepress": "^1.4.1"
7878
},
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!--{}-->
2+
<template>
3+
<div v-bind:a="a
4+
??
5+
b
6+
"/>
7+
</template>

Diff for: tests/fixtures/html-indent/optional-chaining-01.vue

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<!-- TODO If ESLint supports the new syntax by default, remove the parser specification and test. -->
3+
4+
<template>
5+
<div v-bind:a="
6+
obj
7+
?.aaa
8+
?.bbb
9+
?.ccc
10+
"/>
11+
</template>

Diff for: tests/fixtures/html-indent/optional-chaining-02.vue

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<!-- TODO If ESLint supports the new syntax by default, remove the parser specification and test. -->
3+
<template>
4+
<div v-bind:a="
5+
obj?.
6+
aaa?.
7+
bbb?.
8+
ccc
9+
"/>
10+
</template>

Diff for: tests/fixtures/html-indent/optional-chaining-03.vue

+10
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<!-- TODO If ESLint supports the new syntax by default, remove the parser specification and test. -->
3+
<template>
4+
<div v-bind:a="
5+
obj?.
6+
[aaa]?.
7+
[bbb]
8+
?.[ccc]
9+
"/>
10+
</template>

Diff for: tests/fixtures/html-indent/optional-chaining-04.vue

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<!-- TODO If ESLint supports the new syntax by default, remove the parser specification and test. -->
3+
<template>
4+
<div v-bind:a="
5+
obj?.
6+
(
7+
aaa
8+
)?.
9+
(
10+
bbb
11+
)
12+
?.(
13+
ccc
14+
)
15+
"/>
16+
</template>

Diff for: tests/fixtures/script-indent/bigint-01.vue

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!--{}-->
2+
<script>
3+
var a =
4+
10n
5+
+
6+
5n
7+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
<!--{}-->
2+
<script>
3+
export
4+
*
5+
as
6+
foo
7+
from
8+
"mod"
9+
;
10+
export
11+
*
12+
as
13+
bar
14+
from
15+
"mod"
16+
</script>

Diff for: tests/fixtures/script-indent/for-await-of-01.vue

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<!--{}-->
2+
<script>
3+
async function fn() {
4+
for
5+
await
6+
(
7+
a
8+
of
9+
b
10+
)
11+
{
12+
;
13+
}
14+
}
15+
</script>
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!--{}-->
2+
<script>
3+
const fs = import
4+
(
5+
'fs'
6+
)
7+
</script>
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!--{}-->
2+
<script>
3+
const module = import
4+
(
5+
m.
6+
n
7+
)
8+
</script>
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<!--{}-->
2+
<script>
3+
async function fn() {
4+
return await
5+
import
6+
(
7+
m.
8+
n
9+
)
10+
}
11+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<!--{}-->
2+
<script>
3+
var v = a
4+
??
5+
b
6+
</script>
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<!--{}-->
2+
<script>
3+
var obj = {
4+
a:
5+
1,
6+
...obj1,
7+
b:
8+
2,
9+
...
10+
obj2,
11+
}
12+
</script>
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<!-- TODO If ESLint supports the new syntax by default, remove the parser specification and test. -->
3+
<script>
4+
obj
5+
?.aaa
6+
?.bbb
7+
?.ccc
8+
</script>
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<!-- TODO If ESLint supports the new syntax by default, remove the parser specification and test. -->
3+
<script>
4+
obj?.
5+
aaa?.
6+
bbb?.
7+
ccc
8+
</script>
+8
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<!-- TODO If ESLint supports the new syntax by default, remove the parser specification and test. -->
3+
<script>
4+
obj?.
5+
[aaa]?.
6+
[bbb]
7+
?.[ccc]
8+
</script>
+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<!-- TODO If ESLint supports the new syntax by default, remove the parser specification and test. -->
3+
<script>
4+
obj?.
5+
(
6+
aaa
7+
)?.
8+
(
9+
bbb
10+
)
11+
?.(
12+
ccc
13+
)
14+
</script>

0 commit comments

Comments
 (0)