Skip to content

Commit

Permalink
Add utility getCallExpressionTokens (#2345)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker committed May 9, 2024
1 parent b82542d commit e59d9ee
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 42 deletions.
21 changes: 14 additions & 7 deletions rules/no-array-push-push.js
@@ -1,6 +1,9 @@
'use strict';
const {hasSideEffect, isCommaToken, isSemicolonToken} = require('@eslint-community/eslint-utils');
const getCallExpressionArgumentsText = require('./utils/get-call-expression-arguments-text.js');
const {hasSideEffect, isSemicolonToken} = require('@eslint-community/eslint-utils');
const {
getCallExpressionTokens,
getCallExpressionArgumentsText,
} = require('./utils/index.js');
const isSameReference = require('./utils/is-same-reference.js');
const {isNodeMatches} = require('./utils/is-node-matches.js');
const getPreviousNode = require('./utils/get-previous-node.js');
Expand Down Expand Up @@ -78,13 +81,17 @@ function create(context) {

const fix = function * (fixer) {
if (secondCallArguments.length > 0) {
const text = getCallExpressionArgumentsText(secondCall, sourceCode);
const text = getCallExpressionArgumentsText(sourceCode, secondCall);

const {
trailingCommaToken,
closingParenthesisToken,
} = getCallExpressionTokens(sourceCode, firstCall);

const [penultimateToken, lastToken] = sourceCode.getLastTokens(firstCall, 2);
yield (
isCommaToken(penultimateToken)
? fixer.insertTextAfter(penultimateToken, ` ${text}`)
: fixer.insertTextBefore(lastToken, firstCall.arguments.length > 0 ? `, ${text}` : text)
trailingCommaToken
? fixer.insertTextAfter(trailingCommaToken, ` ${text}`)
: fixer.insertTextBefore(closingParenthesisToken, firstCall.arguments.length > 0 ? `, ${text}` : text)
);
}

Expand Down
8 changes: 5 additions & 3 deletions rules/no-magic-array-flat-depth.js
@@ -1,6 +1,6 @@
'use strict';
const {isOpeningParenToken} = require('@eslint-community/eslint-utils');
const {isMethodCall, isNumberLiteral} = require('./ast/index.js');
const {getCallExpressionTokens} = require('./utils/index.js');

const MESSAGE_ID = 'no-magic-array-flat-depth';
const messages = {
Expand All @@ -25,8 +25,10 @@ const create = context => ({
}

const {sourceCode} = context;
const openingParenthesisToken = sourceCode.getTokenAfter(callExpression.callee, isOpeningParenToken);
const closingParenthesisToken = sourceCode.getLastToken(callExpression);
const {
openingParenthesisToken,
closingParenthesisToken,
} = getCallExpressionTokens(sourceCode, callExpression);
if (sourceCode.commentsExistBetween(openingParenthesisToken, closingParenthesisToken)) {
return;
}
Expand Down
22 changes: 11 additions & 11 deletions rules/prefer-module.js
@@ -1,7 +1,7 @@
'use strict';
const {isOpeningParenToken} = require('@eslint-community/eslint-utils');
const isShadowed = require('./utils/is-shadowed.js');
const assertToken = require('./utils/assert-token.js');
const {getCallExpressionTokens} = require('./utils/index.js');
const {isStaticRequire, isReferenceIdentifier, isFunction} = require('./ast/index.js');
const {
removeParentheses,
Expand Down Expand Up @@ -77,12 +77,12 @@ function fixRequireCall(node, sourceCode) {
if (parent.type === 'ExpressionStatement' && parent.parent.type === 'Program') {
return function * (fixer) {
yield fixer.replaceText(callee, 'import');
const openingParenthesisToken = sourceCode.getTokenAfter(
callee,
isOpeningParenToken,
);

const {
openingParenthesisToken,
closingParenthesisToken,
} = getCallExpressionTokens(sourceCode, requireCall);
yield fixer.replaceText(openingParenthesisToken, ' ');
const closingParenthesisToken = sourceCode.getLastToken(requireCall);
yield fixer.remove(closingParenthesisToken);

for (const node of [callee, requireCall, source]) {
Expand Down Expand Up @@ -137,12 +137,12 @@ function fixRequireCall(node, sourceCode) {
yield fixer.replaceText(equalToken, ' from ');

yield fixer.remove(callee);
const openingParenthesisToken = sourceCode.getTokenAfter(
callee,
isOpeningParenToken,
);

const {
openingParenthesisToken,
closingParenthesisToken,
} = getCallExpressionTokens(sourceCode, requireCall);
yield fixer.remove(openingParenthesisToken);
const closingParenthesisToken = sourceCode.getLastToken(requireCall);
yield fixer.remove(closingParenthesisToken);

for (const node of [callee, requireCall, source]) {
Expand Down
27 changes: 12 additions & 15 deletions rules/prefer-structured-clone.js
@@ -1,11 +1,10 @@
'use strict';
const {
isCommaToken,
isOpeningParenToken,
} = require('@eslint-community/eslint-utils');
const {isCallExpression, isMethodCall} = require('./ast/index.js');
const {removeParentheses} = require('./fix/index.js');
const {isNodeMatchesNameOrPath} = require('./utils/index.js');
const {
isNodeMatchesNameOrPath,
getCallExpressionTokens,
} = require('./utils/index.js');

const MESSAGE_ID_ERROR = 'prefer-structured-clone/error';
const MESSAGE_ID_SUGGESTION = 'prefer-structured-clone/suggestion';
Expand Down Expand Up @@ -75,19 +74,17 @@ const create = context => {
yield fixer.remove(jsonStringify.callee);
yield * removeParentheses(jsonStringify.callee, fixer, sourceCode);

const openingParenthesisToken = sourceCode.getTokenAfter(jsonStringify.callee, isOpeningParenToken);
yield fixer.remove(openingParenthesisToken);

const [
penultimateToken,
const {
openingParenthesisToken,
closingParenthesisToken,
] = sourceCode.getLastTokens(jsonStringify, 2);

if (isCommaToken(penultimateToken)) {
yield fixer.remove(penultimateToken);
}
trailingCommaToken,
} = getCallExpressionTokens(sourceCode, jsonStringify);

yield fixer.remove(openingParenthesisToken);
yield fixer.remove(closingParenthesisToken);
if (trailingCommaToken) {
yield fixer.remove(trailingCommaToken);
}
},
},
],
Expand Down
17 changes: 11 additions & 6 deletions rules/utils/get-call-expression-arguments-text.js
@@ -1,21 +1,26 @@
'use strict';
const {isOpeningParenToken} = require('@eslint-community/eslint-utils');
const getCallExpressionTokens = require('./get-call-expression-tokens.js');

/** @typedef {import('estree').CallExpression} CallExpression */

/**
Get the text of the arguments list of `CallExpression`.
@param {Node} node - The `CallExpression` node.
@param {import('eslint').SourceCode} sourceCode - The source code object.
@param {CallExpression} callExpression - The `CallExpression` node.
@param {SourceCode} sourceCode - The source code object.
@returns {string}
*/
const getCallExpressionArgumentsText = (node, sourceCode) => {
const openingParenthesisToken = sourceCode.getTokenAfter(node.callee, isOpeningParenToken);
const closingParenthesisToken = sourceCode.getLastToken(node);
function getCallExpressionArgumentsText(sourceCode, callExpression) {
const {
openingParenthesisToken,
closingParenthesisToken,
} = getCallExpressionTokens(sourceCode, callExpression);

return sourceCode.text.slice(
openingParenthesisToken.range[1],
closingParenthesisToken.range[0],
);
};
}

module.exports = getCallExpressionArgumentsText;
37 changes: 37 additions & 0 deletions rules/utils/get-call-expression-tokens.js
@@ -0,0 +1,37 @@
'use strict';

const {
isOpeningParenToken,
isCommaToken,
} = require('@eslint-community/eslint-utils');

/** @typedef {import('estree').CallExpression} CallExpression */
/** @typedef {import('eslint').AST.Token} Token */

/**
Get the `openingParenthesisToken`, `closingParenthesisToken`, and `trailingCommaToken` of `CallExpression`.
@param {import('eslint').SourceCode} sourceCode - The source code object.
@param {CallExpression} callExpression - The `CallExpression` node.
@returns {{
openingParenthesisToken: Token,
closingParenthesisToken: Token,
trailingCommaToken: Token | undefined,
}}
*/
function getCallExpressionTokens(sourceCode, callExpression) {
const openingParenthesisToken = sourceCode.getTokenAfter(callExpression.callee, isOpeningParenToken);
const [
penultimateToken,
closingParenthesisToken,
] = sourceCode.getLastTokens(callExpression, 2);
const trailingCommaToken = isCommaToken(penultimateToken) ? penultimateToken : undefined;

return {
openingParenthesisToken,
closingParenthesisToken,
trailingCommaToken,
};
}

module.exports = getCallExpressionTokens;
2 changes: 2 additions & 0 deletions rules/utils/index.js
Expand Up @@ -18,6 +18,8 @@ module.exports = {
avoidCapture: require('./avoid-capture.js'),
escapeString: require('./escape-string.js'),
getBooleanAncestor,
getCallExpressionArgumentsText: require('./get-call-expression-arguments-text.js'),
getCallExpressionTokens: require('./get-call-expression-tokens.js'),
getParentheses,
getParenthesizedRange,
getParenthesizedText,
Expand Down

0 comments on commit e59d9ee

Please sign in to comment.