diff --git a/lib/utils/indent-common.js b/lib/utils/indent-common.js
index 8ec6bbe41..5d80b83bb 100644
--- a/lib/utils/indent-common.js
+++ b/lib/utils/indent-common.js
@@ -1824,6 +1824,8 @@ module.exports.defineVisitor = function create(
let firstToken = tokenStore.getFirstToken(node)
while (
+ leftToken &&
+ rightToken &&
isOpeningParenToken(leftToken) &&
isClosingParenToken(rightToken)
) {
diff --git a/lib/utils/indent-ts.js b/lib/utils/indent-ts.js
index 4801ab211..9afcdb34f 100644
--- a/lib/utils/indent-ts.js
+++ b/lib/utils/indent-ts.js
@@ -19,6 +19,7 @@ const {
* @typedef { { type: string } & HasLocation } MaybeNode
*/
/**
+ * @typedef {import('@typescript-eslint/types').TSESTree.Node} TSESTreeNode
* @typedef {import('@typescript-eslint/types').TSESTree.ClassExpression} ClassExpression
* @typedef {import('@typescript-eslint/types').TSESTree.ClassDeclaration} ClassDeclaration
* @typedef {import('@typescript-eslint/types').TSESTree.TSTypeAliasDeclaration} TSTypeAliasDeclaration
@@ -125,6 +126,48 @@ function defineVisitor({
processSemicolons,
getFirstAndLastTokens
}) {
+ /**
+ * Check whether a given token is the first token of:
+ *
+ * - A parameter of TSTypeParameterInstantiation
+ * - An element of TSTupleType
+ *
+ * @param {Token} token The token to check.
+ * @param {TSUnionType | TSIntersectionType} belongingNode The node that the token is belonging to.
+ * @returns {boolean} `true` if the token is the first token of an element.
+ */
+ function isBeginningOfElement(token, belongingNode) {
+ /** @type {TSESTreeNode | null} */
+ let node = belongingNode
+
+ while (node != null && node.parent != null) {
+ /** @type {TSESTreeNode} */
+ const parent = node.parent
+ if (parent.type === 'TSTypeParameterInstantiation') {
+ return (
+ parent.params.length >= 2 &&
+ parent.params.some(
+ (param) =>
+ getFirstAndLastTokens(param).firstToken.range[0] ===
+ token.range[0]
+ )
+ )
+ }
+ if (parent.type === 'TSTupleType') {
+ return parent.elementTypes.some(
+ (element) =>
+ element != null &&
+ getFirstAndLastTokens(element).firstToken.range[0] ===
+ token.range[0]
+ )
+ }
+
+ node = parent
+ }
+
+ return false
+ }
+
return {
// Support TypeScript
/** @param {ClassDeclaration | ClassExpression} node */
@@ -463,16 +506,34 @@ function defineVisitor({
// A | B
// A & B
const firstToken = tokenStore.getFirstToken(node)
- const types = [...node.types]
- if (getFirstAndLastTokens(types[0]).firstToken === firstToken) {
- types.shift()
+
+ const prevToken = tokenStore.getTokenBefore(firstToken)
+ const shouldIndent =
+ prevToken == null ||
+ prevToken.loc.end.line === firstToken.loc.start.line ||
+ isBeginningOfElement(firstToken, node)
+ const offset = shouldIndent ? 1 : 0
+
+ const typeTokensList = node.types.map(getFirstAndLastTokens)
+ const typeTokens = typeTokensList.shift()
+ if (!typeTokens) {
+ return
+ }
+ let lastToken
+ if (typeTokens.firstToken === firstToken) {
+ lastToken = typeTokens.lastToken
+ } else {
+ typeTokensList.unshift(typeTokens)
+ lastToken = firstToken
+ }
+ for (const typeTokens of typeTokensList) {
+ setOffset(
+ tokenStore.getTokensBetween(lastToken, typeTokens.firstToken),
+ offset,
+ firstToken
+ )
+ setOffset(typeTokens.firstToken, offset, firstToken)
}
- processNodeList(
- types,
- firstToken,
- null,
- isBeginningOfLine(firstToken) ? 0 : 1
- )
},
TSParenthesizedType(node) {
// (T)
@@ -1253,12 +1314,4 @@ function defineVisitor({
// ----------------------------------------------------------------------
TSLiteralType() {}
}
- /**
- * Check whether the given node or token is the beginning of a line.
- * @param {MaybeNode} node
- */
- function isBeginningOfLine(node) {
- const prevToken = tokenStore.getTokenBefore(node, { includeComments: true })
- return !prevToken || prevToken.loc.end.line < node.loc.start.line
- }
}
diff --git a/tests/fixtures/script-indent/ts-union-intersection-02.vue b/tests/fixtures/script-indent/ts-union-intersection-02.vue
new file mode 100644
index 000000000..04b722218
--- /dev/null
+++ b/tests/fixtures/script-indent/ts-union-intersection-02.vue
@@ -0,0 +1,21 @@
+
+
diff --git a/tests/fixtures/script-indent/ts-union-intersection-03.vue b/tests/fixtures/script-indent/ts-union-intersection-03.vue
new file mode 100644
index 000000000..78928f2e5
--- /dev/null
+++ b/tests/fixtures/script-indent/ts-union-intersection-03.vue
@@ -0,0 +1,19 @@
+
+
diff --git a/tests/fixtures/script-indent/ts-union-intersection-04.vue b/tests/fixtures/script-indent/ts-union-intersection-04.vue
new file mode 100644
index 000000000..7396edc48
--- /dev/null
+++ b/tests/fixtures/script-indent/ts-union-intersection-04.vue
@@ -0,0 +1,17 @@
+
+
diff --git a/tests/fixtures/script-indent/ts-union-intersection-05.vue b/tests/fixtures/script-indent/ts-union-intersection-05.vue
new file mode 100644
index 000000000..d6013535a
--- /dev/null
+++ b/tests/fixtures/script-indent/ts-union-intersection-05.vue
@@ -0,0 +1,19 @@
+
+
diff --git a/tests/fixtures/script-indent/ts-union-intersection-06.vue b/tests/fixtures/script-indent/ts-union-intersection-06.vue
new file mode 100644
index 000000000..a363a2847
--- /dev/null
+++ b/tests/fixtures/script-indent/ts-union-intersection-06.vue
@@ -0,0 +1,27 @@
+
+