From dc90c1e977d2a40286920ca65713e9013f911a9c Mon Sep 17 00:00:00 2001 From: Adam Babcock Date: Thu, 30 May 2019 23:40:22 -0500 Subject: [PATCH] prefer-exponentiation-operator: Fix operator precedence bugs (#305) --- rules/prefer-exponentiation-operator.js | 31 ++++++++++++++++++------ test/prefer-exponentiation-operator.js | 32 ++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 8 deletions(-) diff --git a/rules/prefer-exponentiation-operator.js b/rules/prefer-exponentiation-operator.js index 6b8adffeeb..059795389d 100644 --- a/rules/prefer-exponentiation-operator.js +++ b/rules/prefer-exponentiation-operator.js @@ -12,17 +12,34 @@ const isMathPow = node => { ); }; -const parseArgument = (context, arg) => { - if (arg.type === 'Identifier') { - return arg.name; - } +const parseArgument = (source, arg) => { + const text = source.getText(arg); - return context.getSourceCode().getText(arg); + switch (arg.type) { + case 'Identifier': + return arg.name; + case 'Literal': + return text; + case 'CallExpression': + return text; + case 'UnaryExpression': + return text; + default: + // Handle cases like Math.pow(2, 2-1); + return `(${text})`; + } }; const fix = (context, node, fixer) => { - const base = parseArgument(context, node.arguments[0]); - const exponent = parseArgument(context, node.arguments[1]); + const source = context.getSourceCode(); + const comments = source.getCommentsInside(node); + + if (comments && comments.length > 0) { + return; + } + + const base = parseArgument(source, node.arguments[0]); + const exponent = parseArgument(source, node.arguments[1]); const replacement = `${base} ** ${exponent}`; diff --git a/test/prefer-exponentiation-operator.js b/test/prefer-exponentiation-operator.js index 39493aa25f..25cd9cabce 100644 --- a/test/prefer-exponentiation-operator.js +++ b/test/prefer-exponentiation-operator.js @@ -24,7 +24,7 @@ ruleTester.run('prefer-exponentiation-operator', rule, { { code: 'const x = Math.pow(-2, (2 - 4) +0 -0.2);', errors: [{message}], - output: 'const x = -2 ** (2 - 4) +0 -0.2;' + output: 'const x = -2 ** ((2 - 4) +0 -0.2);' }, { code: 'const x = Math.pow(Math.pow(2, 4), 8);', @@ -48,6 +48,36 @@ ruleTester.run('prefer-exponentiation-operator', rule, { code: 'const x = Math.pow(foo(), bar());', errors: [{message}], output: 'const x = foo() ** bar();' + }, + { + code: 'const x = Math.pow(-2, 2 - 4);', + errors: [{message}], + output: 'const x = -2 ** (2 - 4);' + }, + { + code: 'const x = Math.pow(4 - 2, 2 - 4);', + errors: [{message}], + output: 'const x = (4 - 2) ** (2 - 4);' + }, + { + code: 'const x = Math.pow(\n2,\n2);', + errors: [{message}], + output: 'const x = 2 ** 2;' + }, + { + code: 'const x = Math.pow(\n2,2 +\n2);', + errors: [{message}], + output: 'const x = 2 ** (2 +\n2);' + }, + { + code: 'const x = Math.pow(\n2, // foo\n2);', + errors: [{message}], + output: 'const x = Math.pow(\n2, // foo\n2);' + }, + { + code: 'const x = Math.pow(// foo\n2, 2);', + errors: [{message}], + output: 'const x = Math.pow(// foo\n2, 2);' } ] });