This change modifies the build scripts to use --legacy-peer-deps flag when installing npm dependencies to resolve potential peer dependency conflicts during the build process. The change is applied to both bash (build.sh) and batch (build.bat) build scripts.
293 lines
12 KiB
JavaScript
293 lines
12 KiB
JavaScript
/**
|
|
* @fileoverview enforce consistent line breaks inside function parentheses
|
|
* @author Teddy Katz
|
|
* @deprecated in ESLint v8.53.0
|
|
*/
|
|
"use strict";
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Requirements
|
|
//------------------------------------------------------------------------------
|
|
|
|
const astUtils = require("./utils/ast-utils");
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Rule Definition
|
|
//------------------------------------------------------------------------------
|
|
|
|
/** @type {import('../shared/types').Rule} */
|
|
module.exports = {
|
|
meta: {
|
|
deprecated: true,
|
|
replacedBy: [],
|
|
type: "layout",
|
|
|
|
docs: {
|
|
description: "Enforce consistent line breaks inside function parentheses",
|
|
recommended: false,
|
|
url: "https://eslint.org/docs/latest/rules/function-paren-newline"
|
|
},
|
|
|
|
fixable: "whitespace",
|
|
|
|
schema: [
|
|
{
|
|
oneOf: [
|
|
{
|
|
enum: ["always", "never", "consistent", "multiline", "multiline-arguments"]
|
|
},
|
|
{
|
|
type: "object",
|
|
properties: {
|
|
minItems: {
|
|
type: "integer",
|
|
minimum: 0
|
|
}
|
|
},
|
|
additionalProperties: false
|
|
}
|
|
]
|
|
}
|
|
],
|
|
|
|
messages: {
|
|
expectedBefore: "Expected newline before ')'.",
|
|
expectedAfter: "Expected newline after '('.",
|
|
expectedBetween: "Expected newline between arguments/params.",
|
|
unexpectedBefore: "Unexpected newline before ')'.",
|
|
unexpectedAfter: "Unexpected newline after '('."
|
|
}
|
|
},
|
|
|
|
create(context) {
|
|
const sourceCode = context.sourceCode;
|
|
const rawOption = context.options[0] || "multiline";
|
|
const multilineOption = rawOption === "multiline";
|
|
const multilineArgumentsOption = rawOption === "multiline-arguments";
|
|
const consistentOption = rawOption === "consistent";
|
|
let minItems;
|
|
|
|
if (typeof rawOption === "object") {
|
|
minItems = rawOption.minItems;
|
|
} else if (rawOption === "always") {
|
|
minItems = 0;
|
|
} else if (rawOption === "never") {
|
|
minItems = Infinity;
|
|
} else {
|
|
minItems = null;
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Helpers
|
|
//----------------------------------------------------------------------
|
|
|
|
/**
|
|
* Determines whether there should be newlines inside function parens
|
|
* @param {ASTNode[]} elements The arguments or parameters in the list
|
|
* @param {boolean} hasLeftNewline `true` if the left paren has a newline in the current code.
|
|
* @returns {boolean} `true` if there should be newlines inside the function parens
|
|
*/
|
|
function shouldHaveNewlines(elements, hasLeftNewline) {
|
|
if (multilineArgumentsOption && elements.length === 1) {
|
|
return hasLeftNewline;
|
|
}
|
|
if (multilineOption || multilineArgumentsOption) {
|
|
return elements.some((element, index) => index !== elements.length - 1 && element.loc.end.line !== elements[index + 1].loc.start.line);
|
|
}
|
|
if (consistentOption) {
|
|
return hasLeftNewline;
|
|
}
|
|
return elements.length >= minItems;
|
|
}
|
|
|
|
/**
|
|
* Validates parens
|
|
* @param {Object} parens An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token
|
|
* @param {ASTNode[]} elements The arguments or parameters in the list
|
|
* @returns {void}
|
|
*/
|
|
function validateParens(parens, elements) {
|
|
const leftParen = parens.leftParen;
|
|
const rightParen = parens.rightParen;
|
|
const tokenAfterLeftParen = sourceCode.getTokenAfter(leftParen);
|
|
const tokenBeforeRightParen = sourceCode.getTokenBefore(rightParen);
|
|
const hasLeftNewline = !astUtils.isTokenOnSameLine(leftParen, tokenAfterLeftParen);
|
|
const hasRightNewline = !astUtils.isTokenOnSameLine(tokenBeforeRightParen, rightParen);
|
|
const needsNewlines = shouldHaveNewlines(elements, hasLeftNewline);
|
|
|
|
if (hasLeftNewline && !needsNewlines) {
|
|
context.report({
|
|
node: leftParen,
|
|
messageId: "unexpectedAfter",
|
|
fix(fixer) {
|
|
return sourceCode.getText().slice(leftParen.range[1], tokenAfterLeftParen.range[0]).trim()
|
|
|
|
// If there is a comment between the ( and the first element, don't do a fix.
|
|
? null
|
|
: fixer.removeRange([leftParen.range[1], tokenAfterLeftParen.range[0]]);
|
|
}
|
|
});
|
|
} else if (!hasLeftNewline && needsNewlines) {
|
|
context.report({
|
|
node: leftParen,
|
|
messageId: "expectedAfter",
|
|
fix: fixer => fixer.insertTextAfter(leftParen, "\n")
|
|
});
|
|
}
|
|
|
|
if (hasRightNewline && !needsNewlines) {
|
|
context.report({
|
|
node: rightParen,
|
|
messageId: "unexpectedBefore",
|
|
fix(fixer) {
|
|
return sourceCode.getText().slice(tokenBeforeRightParen.range[1], rightParen.range[0]).trim()
|
|
|
|
// If there is a comment between the last element and the ), don't do a fix.
|
|
? null
|
|
: fixer.removeRange([tokenBeforeRightParen.range[1], rightParen.range[0]]);
|
|
}
|
|
});
|
|
} else if (!hasRightNewline && needsNewlines) {
|
|
context.report({
|
|
node: rightParen,
|
|
messageId: "expectedBefore",
|
|
fix: fixer => fixer.insertTextBefore(rightParen, "\n")
|
|
});
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Validates a list of arguments or parameters
|
|
* @param {Object} parens An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token
|
|
* @param {ASTNode[]} elements The arguments or parameters in the list
|
|
* @returns {void}
|
|
*/
|
|
function validateArguments(parens, elements) {
|
|
const leftParen = parens.leftParen;
|
|
const tokenAfterLeftParen = sourceCode.getTokenAfter(leftParen);
|
|
const hasLeftNewline = !astUtils.isTokenOnSameLine(leftParen, tokenAfterLeftParen);
|
|
const needsNewlines = shouldHaveNewlines(elements, hasLeftNewline);
|
|
|
|
for (let i = 0; i <= elements.length - 2; i++) {
|
|
const currentElement = elements[i];
|
|
const nextElement = elements[i + 1];
|
|
const hasNewLine = currentElement.loc.end.line !== nextElement.loc.start.line;
|
|
|
|
if (!hasNewLine && needsNewlines) {
|
|
context.report({
|
|
node: currentElement,
|
|
messageId: "expectedBetween",
|
|
fix: fixer => fixer.insertTextBefore(nextElement, "\n")
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Gets the left paren and right paren tokens of a node.
|
|
* @param {ASTNode} node The node with parens
|
|
* @throws {TypeError} Unexpected node type.
|
|
* @returns {Object} An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token.
|
|
* Can also return `null` if an expression has no parens (e.g. a NewExpression with no arguments, or an ArrowFunctionExpression
|
|
* with a single parameter)
|
|
*/
|
|
function getParenTokens(node) {
|
|
switch (node.type) {
|
|
case "NewExpression":
|
|
if (!node.arguments.length &&
|
|
!(
|
|
astUtils.isOpeningParenToken(sourceCode.getLastToken(node, { skip: 1 })) &&
|
|
astUtils.isClosingParenToken(sourceCode.getLastToken(node)) &&
|
|
node.callee.range[1] < node.range[1]
|
|
)
|
|
) {
|
|
|
|
// If the NewExpression does not have parens (e.g. `new Foo`), return null.
|
|
return null;
|
|
}
|
|
|
|
// falls through
|
|
|
|
case "CallExpression":
|
|
return {
|
|
leftParen: sourceCode.getTokenAfter(node.callee, astUtils.isOpeningParenToken),
|
|
rightParen: sourceCode.getLastToken(node)
|
|
};
|
|
|
|
case "FunctionDeclaration":
|
|
case "FunctionExpression": {
|
|
const leftParen = sourceCode.getFirstToken(node, astUtils.isOpeningParenToken);
|
|
const rightParen = node.params.length
|
|
? sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isClosingParenToken)
|
|
: sourceCode.getTokenAfter(leftParen);
|
|
|
|
return { leftParen, rightParen };
|
|
}
|
|
|
|
case "ArrowFunctionExpression": {
|
|
const firstToken = sourceCode.getFirstToken(node, { skip: (node.async ? 1 : 0) });
|
|
|
|
if (!astUtils.isOpeningParenToken(firstToken)) {
|
|
|
|
// If the ArrowFunctionExpression has a single param without parens, return null.
|
|
return null;
|
|
}
|
|
|
|
const rightParen = node.params.length
|
|
? sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isClosingParenToken)
|
|
: sourceCode.getTokenAfter(firstToken);
|
|
|
|
return {
|
|
leftParen: firstToken,
|
|
rightParen
|
|
};
|
|
}
|
|
|
|
case "ImportExpression": {
|
|
const leftParen = sourceCode.getFirstToken(node, 1);
|
|
const rightParen = sourceCode.getLastToken(node);
|
|
|
|
return { leftParen, rightParen };
|
|
}
|
|
|
|
default:
|
|
throw new TypeError(`unexpected node with type ${node.type}`);
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------
|
|
// Public
|
|
//----------------------------------------------------------------------
|
|
|
|
return {
|
|
[[
|
|
"ArrowFunctionExpression",
|
|
"CallExpression",
|
|
"FunctionDeclaration",
|
|
"FunctionExpression",
|
|
"ImportExpression",
|
|
"NewExpression"
|
|
]](node) {
|
|
const parens = getParenTokens(node);
|
|
let params;
|
|
|
|
if (node.type === "ImportExpression") {
|
|
params = [node.source];
|
|
} else if (astUtils.isFunction(node)) {
|
|
params = node.params;
|
|
} else {
|
|
params = node.arguments;
|
|
}
|
|
|
|
if (parens) {
|
|
validateParens(parens, params);
|
|
|
|
if (multilineArgumentsOption) {
|
|
validateArguments(parens, params);
|
|
}
|
|
}
|
|
}
|
|
};
|
|
}
|
|
};
|