Skip to content

Commit 5d1f772

Browse files
authored
Change the indent rule so that the union type has the same indent as the binary expression. (#1527)
1 parent 49d34c9 commit 5d1f772

7 files changed

+175
-17
lines changed

lib/utils/indent-common.js

+2
Original file line numberDiff line numberDiff line change
@@ -1824,6 +1824,8 @@ module.exports.defineVisitor = function create(
18241824
let firstToken = tokenStore.getFirstToken(node)
18251825

18261826
while (
1827+
leftToken &&
1828+
rightToken &&
18271829
isOpeningParenToken(leftToken) &&
18281830
isClosingParenToken(rightToken)
18291831
) {

lib/utils/indent-ts.js

+70-17
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ const {
1919
* @typedef { { type: string } & HasLocation } MaybeNode
2020
*/
2121
/**
22+
* @typedef {import('@typescript-eslint/types').TSESTree.Node} TSESTreeNode
2223
* @typedef {import('@typescript-eslint/types').TSESTree.ClassExpression} ClassExpression
2324
* @typedef {import('@typescript-eslint/types').TSESTree.ClassDeclaration} ClassDeclaration
2425
* @typedef {import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} TSTypeAliasDeclaration
@@ -125,6 +126,48 @@ function defineVisitor({
125126
processSemicolons,
126127
getFirstAndLastTokens
127128
}) {
129+
/**
130+
* Check whether a given token is the first token of:
131+
*
132+
* - A parameter of TSTypeParameterInstantiation
133+
* - An element of TSTupleType
134+
*
135+
* @param {Token} token The token to check.
136+
* @param {TSUnionType | TSIntersectionType} belongingNode The node that the token is belonging to.
137+
* @returns {boolean} `true` if the token is the first token of an element.
138+
*/
139+
function isBeginningOfElement(token, belongingNode) {
140+
/** @type {TSESTreeNode | null} */
141+
let node = belongingNode
142+
143+
while (node != null && node.parent != null) {
144+
/** @type {TSESTreeNode} */
145+
const parent = node.parent
146+
if (parent.type === 'TSTypeParameterInstantiation') {
147+
return (
148+
parent.params.length >= 2 &&
149+
parent.params.some(
150+
(param) =>
151+
getFirstAndLastTokens(param).firstToken.range[0] ===
152+
token.range[0]
153+
)
154+
)
155+
}
156+
if (parent.type === 'TSTupleType') {
157+
return parent.elementTypes.some(
158+
(element) =>
159+
element != null &&
160+
getFirstAndLastTokens(element).firstToken.range[0] ===
161+
token.range[0]
162+
)
163+
}
164+
165+
node = parent
166+
}
167+
168+
return false
169+
}
170+
128171
return {
129172
// Support TypeScript
130173
/** @param {ClassDeclaration | ClassExpression} node */
@@ -463,16 +506,34 @@ function defineVisitor({
463506
// A | B
464507
// A & B
465508
const firstToken = tokenStore.getFirstToken(node)
466-
const types = [...node.types]
467-
if (getFirstAndLastTokens(types[0]).firstToken === firstToken) {
468-
types.shift()
509+
510+
const prevToken = tokenStore.getTokenBefore(firstToken)
511+
const shouldIndent =
512+
prevToken == null ||
513+
prevToken.loc.end.line === firstToken.loc.start.line ||
514+
isBeginningOfElement(firstToken, node)
515+
const offset = shouldIndent ? 1 : 0
516+
517+
const typeTokensList = node.types.map(getFirstAndLastTokens)
518+
const typeTokens = typeTokensList.shift()
519+
if (!typeTokens) {
520+
return
521+
}
522+
let lastToken
523+
if (typeTokens.firstToken === firstToken) {
524+
lastToken = typeTokens.lastToken
525+
} else {
526+
typeTokensList.unshift(typeTokens)
527+
lastToken = firstToken
528+
}
529+
for (const typeTokens of typeTokensList) {
530+
setOffset(
531+
tokenStore.getTokensBetween(lastToken, typeTokens.firstToken),
532+
offset,
533+
firstToken
534+
)
535+
setOffset(typeTokens.firstToken, offset, firstToken)
469536
}
470-
processNodeList(
471-
types,
472-
firstToken,
473-
null,
474-
isBeginningOfLine(firstToken) ? 0 : 1
475-
)
476537
},
477538
TSParenthesizedType(node) {
478539
// (T)
@@ -1253,12 +1314,4 @@ function defineVisitor({
12531314
// ----------------------------------------------------------------------
12541315
TSLiteralType() {}
12551316
}
1256-
/**
1257-
* Check whether the given node or token is the beginning of a line.
1258-
* @param {MaybeNode} node
1259-
*/
1260-
function isBeginningOfLine(node) {
1261-
const prevToken = tokenStore.getTokenBefore(node, { includeComments: true })
1262-
return !prevToken || prevToken.loc.end.line < node.loc.start.line
1263-
}
12641317
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<script lang="ts">
3+
type T =
4+
a
5+
| b
6+
type U =
7+
| a
8+
| b
9+
type V =
10+
a
11+
& b
12+
type W =
13+
& a
14+
& b
15+
type X =
16+
&
17+
(
18+
a
19+
| b
20+
)
21+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<script lang="ts">
3+
type T = a
4+
| b
5+
| c
6+
type U = | a
7+
| b
8+
| c
9+
type V = a
10+
|
11+
b
12+
|
13+
c
14+
const a = a
15+
|
16+
b
17+
|
18+
c
19+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<script lang="ts">
3+
type T = U< a
4+
| b
5+
| c
6+
>
7+
type T = U<
8+
| a
9+
| b
10+
| c
11+
>
12+
type T = U<
13+
& a
14+
& b
15+
& c
16+
>
17+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<script lang="ts">
3+
type T = U<
4+
a
5+
| b
6+
| c,
7+
a
8+
| b
9+
| c
10+
>
11+
type T = U<
12+
a
13+
& b
14+
& c,
15+
a
16+
& b
17+
& c
18+
>
19+
</script>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<!--{"parserOptions": {"parser":"@typescript-eslint/parser"}}-->
2+
<script lang="ts">
3+
type T = [
4+
a
5+
| b
6+
| c
7+
]
8+
type U = [
9+
| a
10+
| b
11+
| c
12+
]
13+
type T2 = [ a
14+
| b
15+
| c,
16+
a
17+
| b
18+
| c
19+
]
20+
type U2 = [ | a
21+
| b
22+
| c,
23+
| a
24+
| b
25+
| c
26+
]
27+
</script>

0 commit comments

Comments
 (0)