diff --git a/lib/utils/indent-common.js b/lib/utils/indent-common.js index 79858b495..4db6dea7f 100644 --- a/lib/utils/indent-common.js +++ b/lib/utils/indent-common.js @@ -1171,11 +1171,18 @@ module.exports.defineVisitor = function create( const firstToken = tokenStore.getFirstToken(node) const rightToken = tokenStore.getLastToken(node) const leftToken = /** @type {Token} */ ( - tokenStore.getTokenAfter(node.callee, isOpeningParenToken) + tokenStore.getTokenAfter( + node.typeParameters || node.callee, + isOpeningParenToken + ) ) + if (node.typeParameters) { + setOffset(tokenStore.getFirstToken(node.typeParameters), 1, firstToken) + } + for (const optionalToken of tokenStore.getTokensBetween( - tokenStore.getLastToken(node.callee), + tokenStore.getLastToken(node.typeParameters || node.callee), leftToken, isOptionalToken )) { @@ -1692,12 +1699,16 @@ module.exports.defineVisitor = function create( const rightToken = tokenStore.getLastToken(node) const leftToken = isClosingParenToken(rightToken) ? tokenStore.getFirstTokenBetween( - node.callee, + node.typeParameters || node.callee, rightToken, isOpeningParenToken ) : null + if (node.typeParameters) { + setOffset(tokenStore.getFirstToken(node.typeParameters), 1, calleeToken) + } + setOffset(calleeToken, 1, newToken) if (leftToken != null) { setOffset(leftToken, 1, calleeToken) diff --git a/lib/utils/indent-ts.js b/lib/utils/indent-ts.js index f2f5b69cf..4c046f490 100644 --- a/lib/utils/indent-ts.js +++ b/lib/utils/indent-ts.js @@ -29,6 +29,7 @@ const { isTypeNode } = require('./ts-ast-utils') * @typedef {import('@typescript-eslint/types').TSESTree.TSImportEqualsDeclaration} TSImportEqualsDeclaration * @typedef {import('@typescript-eslint/types').TSESTree.TSAbstractMethodDefinition} TSAbstractMethodDefinition * @typedef {import('@typescript-eslint/types').TSESTree.TSAbstractPropertyDefinition} TSAbstractPropertyDefinition + * @typedef {import('@typescript-eslint/types').TSESTree.TSAbstractAccessorProperty} TSAbstractAccessorProperty * @typedef {import('@typescript-eslint/types').TSESTree.TSEnumMember} TSEnumMember * @typedef {import('@typescript-eslint/types').TSESTree.TSPropertySignature} TSPropertySignature * @typedef {import('@typescript-eslint/types').TSESTree.TSIndexSignature} TSIndexSignature @@ -50,6 +51,10 @@ const { isTypeNode } = require('./ts-ast-utils') * @typedef {import('@typescript-eslint/types').TSESTree.TSInferType} TSInferType * @typedef {import('@typescript-eslint/types').TSESTree.TSOptionalType} TSOptionalType * @typedef {import('@typescript-eslint/types').TSESTree.TSNonNullExpression} TSNonNullExpression + * @typedef {import('@typescript-eslint/types').TSESTree.TSAsExpression} TSAsExpression + * @typedef {import('@typescript-eslint/types').TSESTree.TSSatisfiesExpression} TSSatisfiesExpression + * @typedef {import('@typescript-eslint/types').TSESTree.TSTypeReference} TSTypeReference + * @typedef {import('@typescript-eslint/types').TSESTree.TSInstantiationExpression} TSInstantiationExpression * @typedef {import('@typescript-eslint/types').TSESTree.JSXChild} JSXChild * @typedef {import('@typescript-eslint/types').TSESTree.TypeNode} TypeNode * @@ -206,15 +211,16 @@ function defineVisitor({ * | TSImportEqualsDeclaration * | TSAbstractMethodDefinition * | TSAbstractPropertyDefinition - * | TSAbstractClassProperty + * | TSAbstractAccessorProperty * | TSEnumMember - * | ClassProperty * | TSPropertySignature * | TSIndexSignature - * | TSMethodSignature} node + * | TSMethodSignature + * | ClassProperty + * | TSAbstractClassProperty} node */ ['TSTypeAliasDeclaration, TSCallSignatureDeclaration, TSConstructSignatureDeclaration, TSImportEqualsDeclaration,' + - 'TSAbstractMethodDefinition, TSAbstractPropertyDefinition, TSEnumMember,' + + 'TSAbstractMethodDefinition, TSAbstractPropertyDefinition, TSAbstractAccessorProperty, TSEnumMember,' + 'TSPropertySignature, TSIndexSignature, TSMethodSignature,' + // Deprecated in @typescript-eslint/parser v5 'ClassProperty, TSAbstractClassProperty'](node) { @@ -279,40 +285,57 @@ function defineVisitor({ } }, /** - * Process as expression + * Process as expression or satisfies expression * * e.g. * ``` * var foo = bar as boolean * // ^^^^^^^^^^^^^^ * ``` + * + * e.g. + * ``` + * var foo = bar satisfies Bar + * // ^^^^^^^^^^^^^^^^^ + * ``` + * + * @param {TSAsExpression | TSSatisfiesExpression} node */ - TSAsExpression(node) { + 'TSAsExpression, TSSatisfiesExpression'(node) { const expressionTokens = getFirstAndLastTokens(node.expression) - const asToken = tokenStore.getTokenAfter(expressionTokens.lastToken) + const asOrSatisfiesToken = tokenStore.getTokenAfter( + expressionTokens.lastToken + ) setOffset( - [asToken, getFirstAndLastTokens(node.typeAnnotation).firstToken], + [ + asOrSatisfiesToken, + getFirstAndLastTokens(node.typeAnnotation).firstToken + ], 1, expressionTokens.firstToken ) }, /** - * Process type reference + * Process type reference and instantiation expression * * e.g. * ``` * const foo: Type

* // ^^^^^^^ * ``` + * + * e.g. + * ``` + * const ErrorMap = Map; + * // ^^^^^^^^^^^^^^^^^^ + * ``` + * + * @param {TSTypeReference | TSInstantiationExpression} node */ - TSTypeReference(node) { + 'TSTypeReference, TSInstantiationExpression'(node) { if (node.typeParameters) { - const typeNameTokens = getFirstAndLastTokens(node.typeName) - setOffset( - tokenStore.getFirstToken(node.typeParameters), - 1, - typeNameTokens.firstToken - ) + const firstToken = tokenStore.getFirstToken(node) + setOffset(tokenStore.getFirstToken(node.typeParameters), 1, firstToken) } }, /** @@ -1053,10 +1076,10 @@ function defineVisitor({ * // ^^^^^^^ * ``` * - * @param {TSAbstractMethodDefinition | TSAbstractPropertyDefinition | TSEnumMember | TSAbstractClassProperty | ClassProperty} node + * @param {TSAbstractMethodDefinition | TSAbstractPropertyDefinition | TSAbstractAccessorProperty | TSEnumMember | TSAbstractClassProperty | ClassProperty} node * */ - ['TSAbstractMethodDefinition, TSAbstractPropertyDefinition, TSEnumMember,' + + ['TSAbstractMethodDefinition, TSAbstractPropertyDefinition, TSAbstractAccessorProperty, TSEnumMember,' + // Deprecated in @typescript-eslint/parser v5 'ClassProperty, TSAbstractClassProperty'](node) { const { keyNode, valueNode } = @@ -1302,6 +1325,42 @@ function defineVisitor({ setOffset(atToken, 0, tokenStore.getFirstToken(decorators[0])) } }, + AccessorProperty(node) { + const keyNode = node.key + const valueNode = node.value + const firstToken = tokenStore.getFirstToken(node) + const keyTokens = getFirstAndLastTokens(keyNode) + const prefixTokens = tokenStore.getTokensBetween( + firstToken, + keyTokens.firstToken + ) + if (node.computed) { + prefixTokens.pop() // pop opening bracket character (`[`) + } + setOffset(prefixTokens, 0, firstToken) + let lastKeyToken + if (node.computed) { + const leftBracketToken = tokenStore.getTokenBefore(keyTokens.firstToken) + const rightBracketToken = (lastKeyToken = tokenStore.getTokenAfter( + keyTokens.lastToken + )) + setOffset(leftBracketToken, 0, firstToken) + processNodeList([keyNode], leftBracketToken, rightBracketToken, 1) + } else { + setOffset(keyTokens.firstToken, 0, firstToken) + lastKeyToken = keyTokens.lastToken + } + + if (valueNode != null) { + const initToken = tokenStore.getFirstToken(valueNode) + setOffset( + [...tokenStore.getTokensBetween(lastKeyToken, initToken), initToken], + 1, + lastKeyToken + ) + } + processSemicolons(node) + }, ImportAttribute(node) { const firstToken = tokenStore.getFirstToken(node) const keyTokens = getFirstAndLastTokens(node.key) diff --git a/package.json b/package.json index 3f2fb7287..da3d9633c 100644 --- a/package.json +++ b/package.json @@ -71,7 +71,7 @@ "@types/node": "^13.13.5", "@types/semver": "^7.3.9", "@types/xml-name-validator": "^4.0.0", - "@typescript-eslint/parser": "^5.23.0", + "@typescript-eslint/parser": "^5.45.0", "assert": "^2.0.0", "env-cmd": "^10.1.0", "esbuild": "^0.15.15", @@ -90,7 +90,7 @@ "mocha": "^10.0.0", "nyc": "^15.1.0", "prettier": "^2.6.2", - "typescript": "^4.6.4", + "typescript": "^4.9.3", "vitepress": "^1.0.0-alpha.29" } } diff --git a/tests/fixtures/script-indent/ts-abstract-accessor-property-01.vue b/tests/fixtures/script-indent/ts-abstract-accessor-property-01.vue new file mode 100644 index 000000000..563b10304 --- /dev/null +++ b/tests/fixtures/script-indent/ts-abstract-accessor-property-01.vue @@ -0,0 +1,12 @@ + + diff --git a/tests/fixtures/script-indent/ts-accessor-property-01.vue b/tests/fixtures/script-indent/ts-accessor-property-01.vue new file mode 100644 index 000000000..c7fa3c38e --- /dev/null +++ b/tests/fixtures/script-indent/ts-accessor-property-01.vue @@ -0,0 +1,8 @@ + + diff --git a/tests/fixtures/script-indent/ts-accessor-property-02.vue b/tests/fixtures/script-indent/ts-accessor-property-02.vue new file mode 100644 index 000000000..a09369195 --- /dev/null +++ b/tests/fixtures/script-indent/ts-accessor-property-02.vue @@ -0,0 +1,10 @@ + + diff --git a/tests/fixtures/script-indent/ts-accessor-property-03.vue b/tests/fixtures/script-indent/ts-accessor-property-03.vue new file mode 100644 index 000000000..856502bbd --- /dev/null +++ b/tests/fixtures/script-indent/ts-accessor-property-03.vue @@ -0,0 +1,9 @@ + + diff --git a/tests/fixtures/script-indent/ts-accessor-property-04.vue b/tests/fixtures/script-indent/ts-accessor-property-04.vue new file mode 100644 index 000000000..f0ba8795c --- /dev/null +++ b/tests/fixtures/script-indent/ts-accessor-property-04.vue @@ -0,0 +1,10 @@ + + diff --git a/tests/fixtures/script-indent/ts-accessor-property-05.vue b/tests/fixtures/script-indent/ts-accessor-property-05.vue new file mode 100644 index 000000000..4328991d0 --- /dev/null +++ b/tests/fixtures/script-indent/ts-accessor-property-05.vue @@ -0,0 +1,12 @@ + + diff --git a/tests/fixtures/script-indent/ts-call-expression-01.vue b/tests/fixtures/script-indent/ts-call-expression-01.vue new file mode 100644 index 000000000..20600bc1f --- /dev/null +++ b/tests/fixtures/script-indent/ts-call-expression-01.vue @@ -0,0 +1,12 @@ + + diff --git a/tests/fixtures/script-indent/ts-instantiation-expression-01.vue b/tests/fixtures/script-indent/ts-instantiation-expression-01.vue new file mode 100644 index 000000000..b58602542 --- /dev/null +++ b/tests/fixtures/script-indent/ts-instantiation-expression-01.vue @@ -0,0 +1,8 @@ + + diff --git a/tests/fixtures/script-indent/ts-new-expression-01.vue b/tests/fixtures/script-indent/ts-new-expression-01.vue new file mode 100644 index 000000000..8559f7787 --- /dev/null +++ b/tests/fixtures/script-indent/ts-new-expression-01.vue @@ -0,0 +1,13 @@ + + diff --git a/tests/fixtures/script-indent/ts-satisfies-operators-01.vue b/tests/fixtures/script-indent/ts-satisfies-operators-01.vue new file mode 100644 index 000000000..fbb78af6a --- /dev/null +++ b/tests/fixtures/script-indent/ts-satisfies-operators-01.vue @@ -0,0 +1,8 @@ + + diff --git a/typings/eslint-plugin-vue/util-types/ast/es-ast.ts b/typings/eslint-plugin-vue/util-types/ast/es-ast.ts index b3d5b6e2e..800943419 100644 --- a/typings/eslint-plugin-vue/util-types/ast/es-ast.ts +++ b/typings/eslint-plugin-vue/util-types/ast/es-ast.ts @@ -525,6 +525,7 @@ export interface NewExpression extends HasParentNode { type: 'NewExpression' callee: Expression arguments: (Expression | SpreadElement)[] + typeParameters?: TSTypeParameterInstantiation } interface BaseMemberExpression extends HasParentNode { type: 'MemberExpression'