diff --git a/lib/rules/logical-assignment-operators.js b/lib/rules/logical-assignment-operators.js index cb1cbe5a16b..27ca585e995 100644 --- a/lib/rules/logical-assignment-operators.js +++ b/lib/rules/logical-assignment-operators.js @@ -370,8 +370,11 @@ module.exports = { return; } - const requiresOuterParenthesis = logical.parent.type !== "ExpressionStatement" && - (astUtils.getPrecedence({ type: "AssignmentExpression" }) < astUtils.getPrecedence(logical.parent)); + const parentPrecedence = astUtils.getPrecedence(logical.parent); + const requiresOuterParenthesis = logical.parent.type !== "ExpressionStatement" && ( + parentPrecedence === -1 || + astUtils.getPrecedence({ type: "AssignmentExpression" }) < parentPrecedence + ); if (!astUtils.isParenthesised(sourceCode, logical) && requiresOuterParenthesis) { yield ruleFixer.insertTextBefore(logical, "("); diff --git a/lib/rules/prefer-exponentiation-operator.js b/lib/rules/prefer-exponentiation-operator.js index dd4ba2c8e04..6d807f9cfea 100644 --- a/lib/rules/prefer-exponentiation-operator.js +++ b/lib/rules/prefer-exponentiation-operator.js @@ -55,11 +55,12 @@ function doesExponentNeedParens(exponent) { function doesExponentiationExpressionNeedParens(node, sourceCode) { const parent = node.parent.type === "ChainExpression" ? node.parent.parent : node.parent; + const parentPrecedence = astUtils.getPrecedence(parent); const needsParens = ( parent.type === "ClassDeclaration" || ( parent.type.endsWith("Expression") && - astUtils.getPrecedence(parent) >= PRECEDENCE_OF_EXPONENTIATION_EXPR && + (parentPrecedence === -1 || parentPrecedence >= PRECEDENCE_OF_EXPONENTIATION_EXPR) && !(parent.type === "BinaryExpression" && parent.operator === "**" && parent.right === node) && !((parent.type === "CallExpression" || parent.type === "NewExpression") && parent.arguments.includes(node)) && !(parent.type === "MemberExpression" && parent.computed && parent.property === node) && diff --git a/lib/rules/utils/ast-utils.js b/lib/rules/utils/ast-utils.js index aed2c42f9a3..39e53b1057d 100644 --- a/lib/rules/utils/ast-utils.js +++ b/lib/rules/utils/ast-utils.js @@ -9,6 +9,7 @@ // Requirements //------------------------------------------------------------------------------ +const { KEYS: eslintVisitorKeys } = require("eslint-visitor-keys"); const esutils = require("esutils"); const espree = require("espree"); const escapeRegExp = require("escape-string-regexp"); @@ -1461,7 +1462,16 @@ module.exports = { return 19; default: - return 20; + if (node.type in eslintVisitorKeys) { + return 20; + } + + /* + * if the node is not a standard node that we know about, then assume it has the lowest precedence + * this will mean that rules will wrap unknown nodes in parentheses where applicable instead of + * unwrapping them and potentially changing the meaning of the code or introducing a syntax error. + */ + return -1; } }, diff --git a/tests/fixtures/parsers/typescript-parsers/boolean-cast-with-assertion.js b/tests/fixtures/parsers/typescript-parsers/boolean-cast-with-assertion.js new file mode 100644 index 00000000000..caecf5c9191 --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/boolean-cast-with-assertion.js @@ -0,0 +1,333 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser 5.59.11 (TS 5.1.3) + * Source code: + * if (!Boolean(a as any)) { } + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "IfStatement", + test: { + type: "UnaryExpression", + operator: "!", + prefix: true, + argument: { + type: "CallExpression", + callee: { + type: "Identifier", + decorators: [], + name: "Boolean", + optional: false, + range: [5, 12], + loc: { + start: { + line: 1, + column: 5, + }, + end: { + line: 1, + column: 12, + }, + }, + }, + arguments: [ + { + type: "TSAsExpression", + expression: { + type: "Identifier", + decorators: [], + name: "a", + optional: false, + range: [13, 14], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 14, + }, + }, + }, + typeAnnotation: { + type: "TSAnyKeyword", + range: [18, 21], + loc: { + start: { + line: 1, + column: 18, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + range: [13, 21], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + ], + optional: false, + range: [5, 22], + loc: { + start: { + line: 1, + column: 5, + }, + end: { + line: 1, + column: 22, + }, + }, + }, + range: [4, 22], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 22, + }, + }, + }, + consequent: { + type: "BlockStatement", + body: [], + range: [24, 27], + loc: { + start: { + line: 1, + column: 24, + }, + end: { + line: 1, + column: 27, + }, + }, + }, + alternate: null, + range: [0, 27], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 27, + }, + }, + }, + ], + comments: [], + range: [0, 27], + sourceType: "script", + tokens: [ + { + type: "Keyword", + value: "if", + range: [0, 2], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 2, + }, + }, + }, + { + type: "Punctuator", + value: "(", + range: [3, 4], + loc: { + start: { + line: 1, + column: 3, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + { + type: "Punctuator", + value: "!", + range: [4, 5], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + { + type: "Identifier", + value: "Boolean", + range: [5, 12], + loc: { + start: { + line: 1, + column: 5, + }, + end: { + line: 1, + column: 12, + }, + }, + }, + { + type: "Punctuator", + value: "(", + range: [12, 13], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + { + type: "Identifier", + value: "a", + range: [13, 14], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 14, + }, + }, + }, + { + type: "Identifier", + value: "as", + range: [15, 17], + loc: { + start: { + line: 1, + column: 15, + }, + end: { + line: 1, + column: 17, + }, + }, + }, + { + type: "Identifier", + value: "any", + range: [18, 21], + loc: { + start: { + line: 1, + column: 18, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [21, 22], + loc: { + start: { + line: 1, + column: 21, + }, + end: { + line: 1, + column: 22, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [22, 23], + loc: { + start: { + line: 1, + column: 22, + }, + end: { + line: 1, + column: 23, + }, + }, + }, + { + type: "Punctuator", + value: "{", + range: [24, 25], + loc: { + start: { + line: 1, + column: 24, + }, + end: { + line: 1, + column: 25, + }, + }, + }, + { + type: "Punctuator", + value: "}", + range: [26, 27], + loc: { + start: { + line: 1, + column: 26, + }, + end: { + line: 1, + column: 27, + }, + }, + }, + ], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 27, + }, + }, +}); diff --git a/tests/fixtures/parsers/typescript-parsers/exponentiation-with-assertion-1.js b/tests/fixtures/parsers/typescript-parsers/exponentiation-with-assertion-1.js new file mode 100644 index 00000000000..7921af52872 --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/exponentiation-with-assertion-1.js @@ -0,0 +1,321 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser 5.59.11 (TS 5.1.3) + * Source code: + * Math.pow(a, b as any) + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "MemberExpression", + object: { + type: "Identifier", + decorators: [], + name: "Math", + optional: false, + range: [0, 4], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "pow", + optional: false, + range: [5, 8], + loc: { + start: { + line: 1, + column: 5, + }, + end: { + line: 1, + column: 8, + }, + }, + }, + computed: false, + optional: false, + range: [0, 8], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 8, + }, + }, + }, + arguments: [ + { + type: "Identifier", + decorators: [], + name: "a", + optional: false, + range: [9, 10], + loc: { + start: { + line: 1, + column: 9, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + { + type: "TSAsExpression", + expression: { + type: "Identifier", + decorators: [], + name: "b", + optional: false, + range: [12, 13], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + typeAnnotation: { + type: "TSAnyKeyword", + range: [17, 20], + loc: { + start: { + line: 1, + column: 17, + }, + end: { + line: 1, + column: 20, + }, + }, + }, + range: [12, 20], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 20, + }, + }, + }, + ], + optional: false, + range: [0, 21], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + range: [0, 21], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + ], + comments: [], + range: [0, 21], + sourceType: "script", + tokens: [ + { + type: "Identifier", + value: "Math", + range: [0, 4], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [4, 5], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + { + type: "Identifier", + value: "pow", + range: [5, 8], + loc: { + start: { + line: 1, + column: 5, + }, + end: { + line: 1, + column: 8, + }, + }, + }, + { + type: "Punctuator", + value: "(", + range: [8, 9], + loc: { + start: { + line: 1, + column: 8, + }, + end: { + line: 1, + column: 9, + }, + }, + }, + { + type: "Identifier", + value: "a", + range: [9, 10], + loc: { + start: { + line: 1, + column: 9, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + { + type: "Punctuator", + value: ",", + range: [10, 11], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 11, + }, + }, + }, + { + type: "Identifier", + value: "b", + range: [12, 13], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + { + type: "Identifier", + value: "as", + range: [14, 16], + loc: { + start: { + line: 1, + column: 14, + }, + end: { + line: 1, + column: 16, + }, + }, + }, + { + type: "Identifier", + value: "any", + range: [17, 20], + loc: { + start: { + line: 1, + column: 17, + }, + end: { + line: 1, + column: 20, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [20, 21], + loc: { + start: { + line: 1, + column: 20, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + ], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 21, + }, + }, +}); diff --git a/tests/fixtures/parsers/typescript-parsers/exponentiation-with-assertion-2.js b/tests/fixtures/parsers/typescript-parsers/exponentiation-with-assertion-2.js new file mode 100644 index 00000000000..cbdfa49e142 --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/exponentiation-with-assertion-2.js @@ -0,0 +1,321 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser 5.59.11 (TS 5.1.3) + * Source code: + * Math.pow(a as any, b) + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "CallExpression", + callee: { + type: "MemberExpression", + object: { + type: "Identifier", + decorators: [], + name: "Math", + optional: false, + range: [0, 4], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "pow", + optional: false, + range: [5, 8], + loc: { + start: { + line: 1, + column: 5, + }, + end: { + line: 1, + column: 8, + }, + }, + }, + computed: false, + optional: false, + range: [0, 8], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 8, + }, + }, + }, + arguments: [ + { + type: "TSAsExpression", + expression: { + type: "Identifier", + decorators: [], + name: "a", + optional: false, + range: [9, 10], + loc: { + start: { + line: 1, + column: 9, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + typeAnnotation: { + type: "TSAnyKeyword", + range: [14, 17], + loc: { + start: { + line: 1, + column: 14, + }, + end: { + line: 1, + column: 17, + }, + }, + }, + range: [9, 17], + loc: { + start: { + line: 1, + column: 9, + }, + end: { + line: 1, + column: 17, + }, + }, + }, + { + type: "Identifier", + decorators: [], + name: "b", + optional: false, + range: [19, 20], + loc: { + start: { + line: 1, + column: 19, + }, + end: { + line: 1, + column: 20, + }, + }, + }, + ], + optional: false, + range: [0, 21], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + range: [0, 21], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + ], + comments: [], + range: [0, 21], + sourceType: "script", + tokens: [ + { + type: "Identifier", + value: "Math", + range: [0, 4], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [4, 5], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + { + type: "Identifier", + value: "pow", + range: [5, 8], + loc: { + start: { + line: 1, + column: 5, + }, + end: { + line: 1, + column: 8, + }, + }, + }, + { + type: "Punctuator", + value: "(", + range: [8, 9], + loc: { + start: { + line: 1, + column: 8, + }, + end: { + line: 1, + column: 9, + }, + }, + }, + { + type: "Identifier", + value: "a", + range: [9, 10], + loc: { + start: { + line: 1, + column: 9, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + { + type: "Identifier", + value: "as", + range: [11, 13], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + { + type: "Identifier", + value: "any", + range: [14, 17], + loc: { + start: { + line: 1, + column: 14, + }, + end: { + line: 1, + column: 17, + }, + }, + }, + { + type: "Punctuator", + value: ",", + range: [17, 18], + loc: { + start: { + line: 1, + column: 17, + }, + end: { + line: 1, + column: 18, + }, + }, + }, + { + type: "Identifier", + value: "b", + range: [19, 20], + loc: { + start: { + line: 1, + column: 19, + }, + end: { + line: 1, + column: 20, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [20, 21], + loc: { + start: { + line: 1, + column: 20, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + ], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 21, + }, + }, +}); diff --git a/tests/fixtures/parsers/typescript-parsers/exponentiation-with-assertion-3.js b/tests/fixtures/parsers/typescript-parsers/exponentiation-with-assertion-3.js new file mode 100644 index 00000000000..422d8736ff3 --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/exponentiation-with-assertion-3.js @@ -0,0 +1,321 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser 5.59.11 (TS 5.1.3) + * Source code: + * Math.pow(a, b) as any + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "TSAsExpression", + expression: { + type: "CallExpression", + callee: { + type: "MemberExpression", + object: { + type: "Identifier", + decorators: [], + name: "Math", + optional: false, + range: [0, 4], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "pow", + optional: false, + range: [5, 8], + loc: { + start: { + line: 1, + column: 5, + }, + end: { + line: 1, + column: 8, + }, + }, + }, + computed: false, + optional: false, + range: [0, 8], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 8, + }, + }, + }, + arguments: [ + { + type: "Identifier", + decorators: [], + name: "a", + optional: false, + range: [9, 10], + loc: { + start: { + line: 1, + column: 9, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + { + type: "Identifier", + decorators: [], + name: "b", + optional: false, + range: [12, 13], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + ], + optional: false, + range: [0, 14], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 14, + }, + }, + }, + typeAnnotation: { + type: "TSAnyKeyword", + range: [18, 21], + loc: { + start: { + line: 1, + column: 18, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + range: [0, 21], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + range: [0, 21], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + ], + comments: [], + range: [0, 21], + sourceType: "script", + tokens: [ + { + type: "Identifier", + value: "Math", + range: [0, 4], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [4, 5], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + { + type: "Identifier", + value: "pow", + range: [5, 8], + loc: { + start: { + line: 1, + column: 5, + }, + end: { + line: 1, + column: 8, + }, + }, + }, + { + type: "Punctuator", + value: "(", + range: [8, 9], + loc: { + start: { + line: 1, + column: 8, + }, + end: { + line: 1, + column: 9, + }, + }, + }, + { + type: "Identifier", + value: "a", + range: [9, 10], + loc: { + start: { + line: 1, + column: 9, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + { + type: "Punctuator", + value: ",", + range: [10, 11], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 11, + }, + }, + }, + { + type: "Identifier", + value: "b", + range: [12, 13], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [13, 14], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 14, + }, + }, + }, + { + type: "Identifier", + value: "as", + range: [15, 17], + loc: { + start: { + line: 1, + column: 15, + }, + end: { + line: 1, + column: 17, + }, + }, + }, + { + type: "Identifier", + value: "any", + range: [18, 21], + loc: { + start: { + line: 1, + column: 18, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + ], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 21, + }, + }, +}); diff --git a/tests/fixtures/parsers/typescript-parsers/logical-assignment-with-assertion.js b/tests/fixtures/parsers/typescript-parsers/logical-assignment-with-assertion.js new file mode 100644 index 00000000000..675559196e1 --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/logical-assignment-with-assertion.js @@ -0,0 +1,209 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser 5.59.11 (TS 5.1.3) + * Source code: + * a ||= b as number; + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "AssignmentExpression", + operator: "||=", + left: { + type: "Identifier", + decorators: [], + name: "a", + optional: false, + range: [0, 1], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 1, + }, + }, + }, + right: { + type: "TSAsExpression", + expression: { + type: "Identifier", + decorators: [], + name: "b", + optional: false, + range: [6, 7], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 7, + }, + }, + }, + typeAnnotation: { + type: "TSNumberKeyword", + range: [11, 17], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 17, + }, + }, + }, + range: [6, 17], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 17, + }, + }, + }, + range: [0, 17], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 17, + }, + }, + }, + range: [0, 18], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 18, + }, + }, + }, + ], + comments: [], + range: [0, 18], + sourceType: "script", + tokens: [ + { + type: "Identifier", + value: "a", + range: [0, 1], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 1, + }, + }, + }, + { + type: "Punctuator", + value: "||=", + range: [2, 5], + loc: { + start: { + line: 1, + column: 2, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + { + type: "Identifier", + value: "b", + range: [6, 7], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 7, + }, + }, + }, + { + type: "Identifier", + value: "as", + range: [8, 10], + loc: { + start: { + line: 1, + column: 8, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + { + type: "Identifier", + value: "number", + range: [11, 17], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 17, + }, + }, + }, + { + type: "Punctuator", + value: ";", + range: [17, 18], + loc: { + start: { + line: 1, + column: 17, + }, + end: { + line: 1, + column: 18, + }, + }, + }, + ], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 18, + }, + }, +}); diff --git a/tests/fixtures/parsers/typescript-parsers/logical-with-assignment-with-assertion-1.js b/tests/fixtures/parsers/typescript-parsers/logical-with-assignment-with-assertion-1.js new file mode 100644 index 00000000000..914ff4d0c24 --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/logical-with-assignment-with-assertion-1.js @@ -0,0 +1,538 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser 5.59.11 (TS 5.1.3) + * Source code: + * a.b.c || (a.b.c = d as number) + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "LogicalExpression", + operator: "||", + left: { + type: "MemberExpression", + object: { + type: "MemberExpression", + object: { + type: "Identifier", + decorators: [], + name: "a", + optional: false, + range: [0, 1], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 1, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "b", + optional: false, + range: [2, 3], + loc: { + start: { + line: 1, + column: 2, + }, + end: { + line: 1, + column: 3, + }, + }, + }, + computed: false, + optional: false, + range: [0, 3], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 3, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "c", + optional: false, + range: [4, 5], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + computed: false, + optional: false, + range: [0, 5], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + right: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "MemberExpression", + object: { + type: "MemberExpression", + object: { + type: "Identifier", + decorators: [], + name: "a", + optional: false, + range: [10, 11], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 11, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "b", + optional: false, + range: [12, 13], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + computed: false, + optional: false, + range: [10, 13], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "c", + optional: false, + range: [14, 15], + loc: { + start: { + line: 1, + column: 14, + }, + end: { + line: 1, + column: 15, + }, + }, + }, + computed: false, + optional: false, + range: [10, 15], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 15, + }, + }, + }, + right: { + type: "TSAsExpression", + expression: { + type: "Identifier", + decorators: [], + name: "d", + optional: false, + range: [18, 19], + loc: { + start: { + line: 1, + column: 18, + }, + end: { + line: 1, + column: 19, + }, + }, + }, + typeAnnotation: { + type: "TSNumberKeyword", + range: [23, 29], + loc: { + start: { + line: 1, + column: 23, + }, + end: { + line: 1, + column: 29, + }, + }, + }, + range: [18, 29], + loc: { + start: { + line: 1, + column: 18, + }, + end: { + line: 1, + column: 29, + }, + }, + }, + range: [10, 29], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 29, + }, + }, + }, + range: [0, 30], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 30, + }, + }, + }, + range: [0, 30], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 30, + }, + }, + }, + ], + comments: [], + range: [0, 30], + sourceType: "script", + tokens: [ + { + type: "Identifier", + value: "a", + range: [0, 1], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 1, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [1, 2], + loc: { + start: { + line: 1, + column: 1, + }, + end: { + line: 1, + column: 2, + }, + }, + }, + { + type: "Identifier", + value: "b", + range: [2, 3], + loc: { + start: { + line: 1, + column: 2, + }, + end: { + line: 1, + column: 3, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [3, 4], + loc: { + start: { + line: 1, + column: 3, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + { + type: "Identifier", + value: "c", + range: [4, 5], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + { + type: "Punctuator", + value: "||", + range: [6, 8], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 8, + }, + }, + }, + { + type: "Punctuator", + value: "(", + range: [9, 10], + loc: { + start: { + line: 1, + column: 9, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + { + type: "Identifier", + value: "a", + range: [10, 11], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 11, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [11, 12], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 12, + }, + }, + }, + { + type: "Identifier", + value: "b", + range: [12, 13], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [13, 14], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 14, + }, + }, + }, + { + type: "Identifier", + value: "c", + range: [14, 15], + loc: { + start: { + line: 1, + column: 14, + }, + end: { + line: 1, + column: 15, + }, + }, + }, + { + type: "Punctuator", + value: "=", + range: [16, 17], + loc: { + start: { + line: 1, + column: 16, + }, + end: { + line: 1, + column: 17, + }, + }, + }, + { + type: "Identifier", + value: "d", + range: [18, 19], + loc: { + start: { + line: 1, + column: 18, + }, + end: { + line: 1, + column: 19, + }, + }, + }, + { + type: "Identifier", + value: "as", + range: [20, 22], + loc: { + start: { + line: 1, + column: 20, + }, + end: { + line: 1, + column: 22, + }, + }, + }, + { + type: "Identifier", + value: "number", + range: [23, 29], + loc: { + start: { + line: 1, + column: 23, + }, + end: { + line: 1, + column: 29, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [29, 30], + loc: { + start: { + line: 1, + column: 29, + }, + end: { + line: 1, + column: 30, + }, + }, + }, + ], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 30, + }, + }, +}); diff --git a/tests/fixtures/parsers/typescript-parsers/logical-with-assignment-with-assertion-2.js b/tests/fixtures/parsers/typescript-parsers/logical-with-assignment-with-assertion-2.js new file mode 100644 index 00000000000..644060ab1d7 --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/logical-with-assignment-with-assertion-2.js @@ -0,0 +1,568 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser 5.59.11 (TS 5.1.3) + * Source code: + * a.b.c || (a.b.c = (d as number)) + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "LogicalExpression", + operator: "||", + left: { + type: "MemberExpression", + object: { + type: "MemberExpression", + object: { + type: "Identifier", + decorators: [], + name: "a", + optional: false, + range: [0, 1], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 1, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "b", + optional: false, + range: [2, 3], + loc: { + start: { + line: 1, + column: 2, + }, + end: { + line: 1, + column: 3, + }, + }, + }, + computed: false, + optional: false, + range: [0, 3], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 3, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "c", + optional: false, + range: [4, 5], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + computed: false, + optional: false, + range: [0, 5], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + right: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "MemberExpression", + object: { + type: "MemberExpression", + object: { + type: "Identifier", + decorators: [], + name: "a", + optional: false, + range: [10, 11], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 11, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "b", + optional: false, + range: [12, 13], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + computed: false, + optional: false, + range: [10, 13], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "c", + optional: false, + range: [14, 15], + loc: { + start: { + line: 1, + column: 14, + }, + end: { + line: 1, + column: 15, + }, + }, + }, + computed: false, + optional: false, + range: [10, 15], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 15, + }, + }, + }, + right: { + type: "TSAsExpression", + expression: { + type: "Identifier", + decorators: [], + name: "d", + optional: false, + range: [19, 20], + loc: { + start: { + line: 1, + column: 19, + }, + end: { + line: 1, + column: 20, + }, + }, + }, + typeAnnotation: { + type: "TSNumberKeyword", + range: [24, 30], + loc: { + start: { + line: 1, + column: 24, + }, + end: { + line: 1, + column: 30, + }, + }, + }, + range: [19, 30], + loc: { + start: { + line: 1, + column: 19, + }, + end: { + line: 1, + column: 30, + }, + }, + }, + range: [10, 31], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 31, + }, + }, + }, + range: [0, 32], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 32, + }, + }, + }, + range: [0, 32], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 32, + }, + }, + }, + ], + comments: [], + range: [0, 32], + sourceType: "script", + tokens: [ + { + type: "Identifier", + value: "a", + range: [0, 1], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 1, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [1, 2], + loc: { + start: { + line: 1, + column: 1, + }, + end: { + line: 1, + column: 2, + }, + }, + }, + { + type: "Identifier", + value: "b", + range: [2, 3], + loc: { + start: { + line: 1, + column: 2, + }, + end: { + line: 1, + column: 3, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [3, 4], + loc: { + start: { + line: 1, + column: 3, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + { + type: "Identifier", + value: "c", + range: [4, 5], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + { + type: "Punctuator", + value: "||", + range: [6, 8], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 8, + }, + }, + }, + { + type: "Punctuator", + value: "(", + range: [9, 10], + loc: { + start: { + line: 1, + column: 9, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + { + type: "Identifier", + value: "a", + range: [10, 11], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 11, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [11, 12], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 12, + }, + }, + }, + { + type: "Identifier", + value: "b", + range: [12, 13], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [13, 14], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 14, + }, + }, + }, + { + type: "Identifier", + value: "c", + range: [14, 15], + loc: { + start: { + line: 1, + column: 14, + }, + end: { + line: 1, + column: 15, + }, + }, + }, + { + type: "Punctuator", + value: "=", + range: [16, 17], + loc: { + start: { + line: 1, + column: 16, + }, + end: { + line: 1, + column: 17, + }, + }, + }, + { + type: "Punctuator", + value: "(", + range: [18, 19], + loc: { + start: { + line: 1, + column: 18, + }, + end: { + line: 1, + column: 19, + }, + }, + }, + { + type: "Identifier", + value: "d", + range: [19, 20], + loc: { + start: { + line: 1, + column: 19, + }, + end: { + line: 1, + column: 20, + }, + }, + }, + { + type: "Identifier", + value: "as", + range: [21, 23], + loc: { + start: { + line: 1, + column: 21, + }, + end: { + line: 1, + column: 23, + }, + }, + }, + { + type: "Identifier", + value: "number", + range: [24, 30], + loc: { + start: { + line: 1, + column: 24, + }, + end: { + line: 1, + column: 30, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [30, 31], + loc: { + start: { + line: 1, + column: 30, + }, + end: { + line: 1, + column: 31, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [31, 32], + loc: { + start: { + line: 1, + column: 31, + }, + end: { + line: 1, + column: 32, + }, + }, + }, + ], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 32, + }, + }, +}); diff --git a/tests/fixtures/parsers/typescript-parsers/logical-with-assignment-with-assertion-3.js b/tests/fixtures/parsers/typescript-parsers/logical-with-assignment-with-assertion-3.js new file mode 100644 index 00000000000..8824fc2f609 --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/logical-with-assignment-with-assertion-3.js @@ -0,0 +1,568 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser 5.59.11 (TS 5.1.3) + * Source code: + * (a.b.c || (a.b.c = d)) as number + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "TSAsExpression", + expression: { + type: "LogicalExpression", + operator: "||", + left: { + type: "MemberExpression", + object: { + type: "MemberExpression", + object: { + type: "Identifier", + decorators: [], + name: "a", + optional: false, + range: [1, 2], + loc: { + start: { + line: 1, + column: 1, + }, + end: { + line: 1, + column: 2, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "b", + optional: false, + range: [3, 4], + loc: { + start: { + line: 1, + column: 3, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + computed: false, + optional: false, + range: [1, 4], + loc: { + start: { + line: 1, + column: 1, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "c", + optional: false, + range: [5, 6], + loc: { + start: { + line: 1, + column: 5, + }, + end: { + line: 1, + column: 6, + }, + }, + }, + computed: false, + optional: false, + range: [1, 6], + loc: { + start: { + line: 1, + column: 1, + }, + end: { + line: 1, + column: 6, + }, + }, + }, + right: { + type: "AssignmentExpression", + operator: "=", + left: { + type: "MemberExpression", + object: { + type: "MemberExpression", + object: { + type: "Identifier", + decorators: [], + name: "a", + optional: false, + range: [11, 12], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 12, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "b", + optional: false, + range: [13, 14], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 14, + }, + }, + }, + computed: false, + optional: false, + range: [11, 14], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 14, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "c", + optional: false, + range: [15, 16], + loc: { + start: { + line: 1, + column: 15, + }, + end: { + line: 1, + column: 16, + }, + }, + }, + computed: false, + optional: false, + range: [11, 16], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 16, + }, + }, + }, + right: { + type: "Identifier", + decorators: [], + name: "d", + optional: false, + range: [19, 20], + loc: { + start: { + line: 1, + column: 19, + }, + end: { + line: 1, + column: 20, + }, + }, + }, + range: [11, 20], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 20, + }, + }, + }, + range: [1, 21], + loc: { + start: { + line: 1, + column: 1, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + typeAnnotation: { + type: "TSNumberKeyword", + range: [26, 32], + loc: { + start: { + line: 1, + column: 26, + }, + end: { + line: 1, + column: 32, + }, + }, + }, + range: [0, 32], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 32, + }, + }, + }, + range: [0, 32], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 32, + }, + }, + }, + ], + comments: [], + range: [0, 32], + sourceType: "script", + tokens: [ + { + type: "Punctuator", + value: "(", + range: [0, 1], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 1, + }, + }, + }, + { + type: "Identifier", + value: "a", + range: [1, 2], + loc: { + start: { + line: 1, + column: 1, + }, + end: { + line: 1, + column: 2, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [2, 3], + loc: { + start: { + line: 1, + column: 2, + }, + end: { + line: 1, + column: 3, + }, + }, + }, + { + type: "Identifier", + value: "b", + range: [3, 4], + loc: { + start: { + line: 1, + column: 3, + }, + end: { + line: 1, + column: 4, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [4, 5], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + { + type: "Identifier", + value: "c", + range: [5, 6], + loc: { + start: { + line: 1, + column: 5, + }, + end: { + line: 1, + column: 6, + }, + }, + }, + { + type: "Punctuator", + value: "||", + range: [7, 9], + loc: { + start: { + line: 1, + column: 7, + }, + end: { + line: 1, + column: 9, + }, + }, + }, + { + type: "Punctuator", + value: "(", + range: [10, 11], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 11, + }, + }, + }, + { + type: "Identifier", + value: "a", + range: [11, 12], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 12, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [12, 13], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 13, + }, + }, + }, + { + type: "Identifier", + value: "b", + range: [13, 14], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 14, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [14, 15], + loc: { + start: { + line: 1, + column: 14, + }, + end: { + line: 1, + column: 15, + }, + }, + }, + { + type: "Identifier", + value: "c", + range: [15, 16], + loc: { + start: { + line: 1, + column: 15, + }, + end: { + line: 1, + column: 16, + }, + }, + }, + { + type: "Punctuator", + value: "=", + range: [17, 18], + loc: { + start: { + line: 1, + column: 17, + }, + end: { + line: 1, + column: 18, + }, + }, + }, + { + type: "Identifier", + value: "d", + range: [19, 20], + loc: { + start: { + line: 1, + column: 19, + }, + end: { + line: 1, + column: 20, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [20, 21], + loc: { + start: { + line: 1, + column: 20, + }, + end: { + line: 1, + column: 21, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [21, 22], + loc: { + start: { + line: 1, + column: 21, + }, + end: { + line: 1, + column: 22, + }, + }, + }, + { + type: "Identifier", + value: "as", + range: [23, 25], + loc: { + start: { + line: 1, + column: 23, + }, + end: { + line: 1, + column: 25, + }, + }, + }, + { + type: "Identifier", + value: "number", + range: [26, 32], + loc: { + start: { + line: 1, + column: 26, + }, + end: { + line: 1, + column: 32, + }, + }, + }, + ], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 32, + }, + }, +}); diff --git a/tests/fixtures/parsers/typescript-parsers/member-call-expr-with-assertion.js b/tests/fixtures/parsers/typescript-parsers/member-call-expr-with-assertion.js new file mode 100644 index 00000000000..e26e115e94e --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/member-call-expr-with-assertion.js @@ -0,0 +1,366 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser 5.59.11 (TS 5.1.3) + * Source code: + * const x = (1 satisfies number).toFixed(); + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "VariableDeclaration", + declarations: [ + { + type: "VariableDeclarator", + definite: false, + id: { + type: "Identifier", + decorators: [], + name: "x", + optional: false, + range: [6, 7], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 7, + }, + }, + }, + init: { + type: "CallExpression", + callee: { + type: "MemberExpression", + object: { + type: "TSSatisfiesExpression", + expression: { + type: "Literal", + value: 1, + raw: "1", + range: [11, 12], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 12, + }, + }, + }, + typeAnnotation: { + type: "TSNumberKeyword", + range: [23, 29], + loc: { + start: { + line: 1, + column: 23, + }, + end: { + line: 1, + column: 29, + }, + }, + }, + range: [11, 29], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 29, + }, + }, + }, + property: { + type: "Identifier", + decorators: [], + name: "toFixed", + optional: false, + range: [31, 38], + loc: { + start: { + line: 1, + column: 31, + }, + end: { + line: 1, + column: 38, + }, + }, + }, + computed: false, + optional: false, + range: [10, 38], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 38, + }, + }, + }, + arguments: [], + optional: false, + range: [10, 40], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 40, + }, + }, + }, + range: [6, 40], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 40, + }, + }, + }, + ], + declare: false, + kind: "const", + range: [0, 41], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 41, + }, + }, + }, + ], + comments: [], + range: [0, 41], + sourceType: "script", + tokens: [ + { + type: "Keyword", + value: "const", + range: [0, 5], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + { + type: "Identifier", + value: "x", + range: [6, 7], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 7, + }, + }, + }, + { + type: "Punctuator", + value: "=", + range: [8, 9], + loc: { + start: { + line: 1, + column: 8, + }, + end: { + line: 1, + column: 9, + }, + }, + }, + { + type: "Punctuator", + value: "(", + range: [10, 11], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 11, + }, + }, + }, + { + type: "Numeric", + value: "1", + range: [11, 12], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 12, + }, + }, + }, + { + type: "Identifier", + value: "satisfies", + range: [13, 22], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 22, + }, + }, + }, + { + type: "Identifier", + value: "number", + range: [23, 29], + loc: { + start: { + line: 1, + column: 23, + }, + end: { + line: 1, + column: 29, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [29, 30], + loc: { + start: { + line: 1, + column: 29, + }, + end: { + line: 1, + column: 30, + }, + }, + }, + { + type: "Punctuator", + value: ".", + range: [30, 31], + loc: { + start: { + line: 1, + column: 30, + }, + end: { + line: 1, + column: 31, + }, + }, + }, + { + type: "Identifier", + value: "toFixed", + range: [31, 38], + loc: { + start: { + line: 1, + column: 31, + }, + end: { + line: 1, + column: 38, + }, + }, + }, + { + type: "Punctuator", + value: "(", + range: [38, 39], + loc: { + start: { + line: 1, + column: 38, + }, + end: { + line: 1, + column: 39, + }, + }, + }, + { + type: "Punctuator", + value: ")", + range: [39, 40], + loc: { + start: { + line: 1, + column: 39, + }, + end: { + line: 1, + column: 40, + }, + }, + }, + { + type: "Punctuator", + value: ";", + range: [40, 41], + loc: { + start: { + line: 1, + column: 40, + }, + end: { + line: 1, + column: 41, + }, + }, + }, + ], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 41, + }, + }, +}); diff --git a/tests/fixtures/parsers/typescript-parsers/unneeded-ternary-1.js b/tests/fixtures/parsers/typescript-parsers/unneeded-ternary-1.js new file mode 100644 index 00000000000..2b44484d892 --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/unneeded-ternary-1.js @@ -0,0 +1,238 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser 5.59.11 (TS 5.1.3) + * Source code: + * foo as any ? false : true + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "ConditionalExpression", + test: { + type: "TSAsExpression", + expression: { + type: "Identifier", + decorators: [], + name: "foo", + optional: false, + range: [0, 3], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 3, + }, + }, + }, + typeAnnotation: { + type: "TSAnyKeyword", + range: [7, 10], + loc: { + start: { + line: 1, + column: 7, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + range: [0, 10], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + consequent: { + type: "Literal", + value: false, + raw: "false", + range: [13, 18], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 18, + }, + }, + }, + alternate: { + type: "Literal", + value: true, + raw: "true", + range: [21, 25], + loc: { + start: { + line: 1, + column: 21, + }, + end: { + line: 1, + column: 25, + }, + }, + }, + range: [0, 25], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 25, + }, + }, + }, + range: [0, 25], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 25, + }, + }, + }, + ], + comments: [], + range: [0, 25], + sourceType: "script", + tokens: [ + { + type: "Identifier", + value: "foo", + range: [0, 3], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 3, + }, + }, + }, + { + type: "Identifier", + value: "as", + range: [4, 6], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 6, + }, + }, + }, + { + type: "Identifier", + value: "any", + range: [7, 10], + loc: { + start: { + line: 1, + column: 7, + }, + end: { + line: 1, + column: 10, + }, + }, + }, + { + type: "Punctuator", + value: "?", + range: [11, 12], + loc: { + start: { + line: 1, + column: 11, + }, + end: { + line: 1, + column: 12, + }, + }, + }, + { + type: "Boolean", + value: "false", + range: [13, 18], + loc: { + start: { + line: 1, + column: 13, + }, + end: { + line: 1, + column: 18, + }, + }, + }, + { + type: "Punctuator", + value: ":", + range: [19, 20], + loc: { + start: { + line: 1, + column: 19, + }, + end: { + line: 1, + column: 20, + }, + }, + }, + { + type: "Boolean", + value: "true", + range: [21, 25], + loc: { + start: { + line: 1, + column: 21, + }, + end: { + line: 1, + column: 25, + }, + }, + }, + ], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 25, + }, + }, +}); diff --git a/tests/fixtures/parsers/typescript-parsers/unneeded-ternary-2.js b/tests/fixtures/parsers/typescript-parsers/unneeded-ternary-2.js new file mode 100644 index 00000000000..eaac150cf1a --- /dev/null +++ b/tests/fixtures/parsers/typescript-parsers/unneeded-ternary-2.js @@ -0,0 +1,240 @@ +"use strict"; + +/** + * Parser: @typescript-eslint/parser 5.59.11 (TS 5.1.3) + * Source code: + * foo ? foo : bar as any + */ + +exports.parse = () => ({ + type: "Program", + body: [ + { + type: "ExpressionStatement", + expression: { + type: "ConditionalExpression", + test: { + type: "Identifier", + decorators: [], + name: "foo", + optional: false, + range: [0, 3], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 3, + }, + }, + }, + consequent: { + type: "Identifier", + decorators: [], + name: "foo", + optional: false, + range: [6, 9], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 9, + }, + }, + }, + alternate: { + type: "TSAsExpression", + expression: { + type: "Identifier", + decorators: [], + name: "bar", + optional: false, + range: [12, 15], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 15, + }, + }, + }, + typeAnnotation: { + type: "TSAnyKeyword", + range: [19, 22], + loc: { + start: { + line: 1, + column: 19, + }, + end: { + line: 1, + column: 22, + }, + }, + }, + range: [12, 22], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 22, + }, + }, + }, + range: [0, 22], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 22, + }, + }, + }, + range: [0, 22], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 22, + }, + }, + }, + ], + comments: [], + range: [0, 22], + sourceType: "script", + tokens: [ + { + type: "Identifier", + value: "foo", + range: [0, 3], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 3, + }, + }, + }, + { + type: "Punctuator", + value: "?", + range: [4, 5], + loc: { + start: { + line: 1, + column: 4, + }, + end: { + line: 1, + column: 5, + }, + }, + }, + { + type: "Identifier", + value: "foo", + range: [6, 9], + loc: { + start: { + line: 1, + column: 6, + }, + end: { + line: 1, + column: 9, + }, + }, + }, + { + type: "Punctuator", + value: ":", + range: [10, 11], + loc: { + start: { + line: 1, + column: 10, + }, + end: { + line: 1, + column: 11, + }, + }, + }, + { + type: "Identifier", + value: "bar", + range: [12, 15], + loc: { + start: { + line: 1, + column: 12, + }, + end: { + line: 1, + column: 15, + }, + }, + }, + { + type: "Identifier", + value: "as", + range: [16, 18], + loc: { + start: { + line: 1, + column: 16, + }, + end: { + line: 1, + column: 18, + }, + }, + }, + { + type: "Identifier", + value: "any", + range: [19, 22], + loc: { + start: { + line: 1, + column: 19, + }, + end: { + line: 1, + column: 22, + }, + }, + }, + ], + loc: { + start: { + line: 1, + column: 0, + }, + end: { + line: 1, + column: 22, + }, + }, +}); diff --git a/tests/lib/rules/logical-assignment-operators.js b/tests/lib/rules/logical-assignment-operators.js index ba839b5c6a8..36756815a90 100644 --- a/tests/lib/rules/logical-assignment-operators.js +++ b/tests/lib/rules/logical-assignment-operators.js @@ -9,7 +9,8 @@ //------------------------------------------------------------------------------ const rule = require("../../../lib/rules/logical-assignment-operators"), - { RuleTester } = require("../../../lib/rule-tester"); + { RuleTester } = require("../../../lib/rule-tester"), + parser = require("../../fixtures/fixture-parser"); //------------------------------------------------------------------------------ // Tests @@ -1456,5 +1457,60 @@ ruleTester.run("logical-assignment-operators", rule, { output: "a = a ?? b + c", options: ["never"], errors: [{ messageId: "unexpected", type: "AssignmentExpression", data: { operator: "??=" } }] - }] + }, + + // https://github.com/eslint/eslint/issues/17173 + { + code: "a ||= b as number;", + output: "a = a || (b as number);", + options: ["never"], + parser: parser("typescript-parsers/logical-assignment-with-assertion"), + errors: [{ messageId: "unexpected", type: "AssignmentExpression", data: { operator: "||=" } }] + }, + { + code: "a.b.c || (a.b.c = d as number)", + output: null, + parser: parser("typescript-parsers/logical-with-assignment-with-assertion-1"), + errors: [{ + messageId: "logical", + type: "LogicalExpression", + data: { operator: "||=" }, + suggestions: [{ + messageId: "convertLogical", + data: { operator: "||=" }, + output: "a.b.c ||= d as number" + }] + }] + }, + { + code: "a.b.c || (a.b.c = (d as number))", + output: null, + parser: parser("typescript-parsers/logical-with-assignment-with-assertion-2"), + errors: [{ + messageId: "logical", + type: "LogicalExpression", + data: { operator: "||=" }, + suggestions: [{ + messageId: "convertLogical", + data: { operator: "||=" }, + output: "a.b.c ||= (d as number)" + }] + }] + }, + { + code: "(a.b.c || (a.b.c = d)) as number", + output: null, + parser: parser("typescript-parsers/logical-with-assignment-with-assertion-3"), + errors: [{ + messageId: "logical", + type: "LogicalExpression", + data: { operator: "||=" }, + suggestions: [{ + messageId: "convertLogical", + data: { operator: "||=" }, + output: "(a.b.c ||= d) as number" + }] + }] + } + ] }); diff --git a/tests/lib/rules/no-extra-boolean-cast.js b/tests/lib/rules/no-extra-boolean-cast.js index 8aecb4ca37f..2e95cb740bb 100644 --- a/tests/lib/rules/no-extra-boolean-cast.js +++ b/tests/lib/rules/no-extra-boolean-cast.js @@ -10,7 +10,8 @@ //------------------------------------------------------------------------------ const rule = require("../../../lib/rules/no-extra-boolean-cast"), - { RuleTester } = require("../../../lib/rule-tester"); + { RuleTester } = require("../../../lib/rule-tester"), + parser = require("../../fixtures/fixture-parser"); //------------------------------------------------------------------------------ // Tests @@ -2423,6 +2424,15 @@ ruleTester.run("no-extra-boolean-cast", rule, { options: [{ enforceForLogicalOperands: true }], parserOptions: { ecmaVersion: 2020 }, errors: [{ messageId: "unexpectedCall" }] + }, + + // https://github.com/eslint/eslint/issues/17173 + { + code: "if (!Boolean(a as any)) { }", + output: "if (!(a as any)) { }", + parser: parser("typescript-parsers/boolean-cast-with-assertion"), + parserOptions: { ecmaVersion: 2020 }, + errors: [{ messageId: "unexpectedCall" }] } ] }); diff --git a/tests/lib/rules/no-extra-parens.js b/tests/lib/rules/no-extra-parens.js index 71e1e2e9845..c160ace3c36 100644 --- a/tests/lib/rules/no-extra-parens.js +++ b/tests/lib/rules/no-extra-parens.js @@ -10,7 +10,8 @@ //------------------------------------------------------------------------------ const rule = require("../../../lib/rules/no-extra-parens"), - { RuleTester } = require("../../../lib/rule-tester"); + { RuleTester } = require("../../../lib/rule-tester"), + parser = require("../../fixtures/fixture-parser"); //------------------------------------------------------------------------------ // Helpers @@ -783,6 +784,12 @@ ruleTester.run("no-extra-parens", rule, { { code: "((a)) = function () {};", options: ["functions"] + }, + + // https://github.com/eslint/eslint/issues/17173 + { + code: "const x = (1 satisfies number).toFixed();", + parser: parser("typescript-parsers/member-call-expr-with-assertion") } ], diff --git a/tests/lib/rules/no-unneeded-ternary.js b/tests/lib/rules/no-unneeded-ternary.js index 7ad11d2b2e5..3714e70bec8 100644 --- a/tests/lib/rules/no-unneeded-ternary.js +++ b/tests/lib/rules/no-unneeded-ternary.js @@ -10,7 +10,8 @@ //------------------------------------------------------------------------------ const rule = require("../../../lib/rules/no-unneeded-ternary"), - { RuleTester } = require("../../../lib/rule-tester"); + { RuleTester } = require("../../../lib/rule-tester"), + parser = require("../../fixtures/fixture-parser"); //------------------------------------------------------------------------------ // Tests @@ -427,6 +428,29 @@ ruleTester.run("no-unneeded-ternary", rule, { endLine: 1, endColumn: 27 }] + }, + + // https://github.com/eslint/eslint/issues/17173 + { + code: "foo as any ? false : true", + output: "!(foo as any)", + parser: parser("typescript-parsers/unneeded-ternary-1"), + parserOptions: { ecmaVersion: 6 }, + errors: [{ + messageId: "unnecessaryConditionalExpression", + type: "ConditionalExpression" + }] + }, + { + code: "foo ? foo : bar as any", + output: "foo || (bar as any)", + options: [{ defaultAssignment: false }], + parser: parser("typescript-parsers/unneeded-ternary-2"), + parserOptions: { ecmaVersion: 6 }, + errors: [{ + messageId: "unnecessaryConditionalAssignment", + type: "ConditionalExpression" + }] } ] }); diff --git a/tests/lib/rules/prefer-exponentiation-operator.js b/tests/lib/rules/prefer-exponentiation-operator.js index 2de358e2c8f..8765330c00f 100644 --- a/tests/lib/rules/prefer-exponentiation-operator.js +++ b/tests/lib/rules/prefer-exponentiation-operator.js @@ -11,6 +11,7 @@ const rule = require("../../../lib/rules/prefer-exponentiation-operator"); const { RuleTester } = require("../../../lib/rule-tester"); +const parser = require("../../fixtures/fixture-parser"); //------------------------------------------------------------------------------ // Helpers @@ -357,6 +358,41 @@ ruleTester.run("prefer-exponentiation-operator", rule, { invalid("Math?.pow(a, b)", "a**b"), invalid("Math?.pow?.(a, b)", "a**b"), invalid("(Math?.pow)(a, b)", "a**b"), - invalid("(Math?.pow)?.(a, b)", "a**b") + invalid("(Math?.pow)?.(a, b)", "a**b"), + + // https://github.com/eslint/eslint/issues/17173 + { + code: "Math.pow(a, b as any)", + output: "a**(b as any)", + parser: parser("typescript-parsers/exponentiation-with-assertion-1"), + errors: [ + { + messageId: "useExponentiation", + type: "CallExpression" + } + ] + }, + { + code: "Math.pow(a as any, b)", + output: "(a as any)**b", + parser: parser("typescript-parsers/exponentiation-with-assertion-2"), + errors: [ + { + messageId: "useExponentiation", + type: "CallExpression" + } + ] + }, + { + code: "Math.pow(a, b) as any", + output: "(a**b) as any", + parser: parser("typescript-parsers/exponentiation-with-assertion-3"), + errors: [ + { + messageId: "useExponentiation", + type: "CallExpression" + } + ] + } ] });