build: update npm install command to use --legacy-peer-deps

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.
This commit is contained in:
Luiz Costa committed 2025-11-18 10:23:55 -03:00
1 parent 20129a1ac7
commit ac4f232e5e
787 files changed
+82341 -121690

No files matched your search

+382 -404
View File
@@ -18,8 +18,8 @@ const astUtils = require("./utils/ast-utils");
const LT = `[${Array.from(astUtils.LINEBREAKS).join("")}]`;
const PADDING_LINE_SEQUENCE = new RegExp(
String.raw`^(\s*?${LT})\s*${LT}(\s*;?)$`,
"u",
String.raw`^(\s*?${LT})\s*${LT}(\s*;?)$`,
"u"
);
const CJS_EXPORT = /^(?:module\s*\.\s*)?exports(?:\s*\.|\s*\[|$)/u;
const CJS_IMPORT = /^require\(/u;
@@ -31,10 +31,10 @@ const CJS_IMPORT = /^require\(/u;
* @private
*/
function newKeywordTester(keyword) {
return {
test: (node, sourceCode) =>
sourceCode.getFirstToken(node).value === keyword,
};
return {
test: (node, sourceCode) =>
sourceCode.getFirstToken(node).value === keyword
};
}
/**
@@ -44,11 +44,11 @@ function newKeywordTester(keyword) {
* @private
*/
function newSinglelineKeywordTester(keyword) {
return {
test: (node, sourceCode) =>
node.loc.start.line === node.loc.end.line &&
sourceCode.getFirstToken(node).value === keyword,
};
return {
test: (node, sourceCode) =>
node.loc.start.line === node.loc.end.line &&
sourceCode.getFirstToken(node).value === keyword
};
}
/**
@@ -58,11 +58,11 @@ function newSinglelineKeywordTester(keyword) {
* @private
*/
function newMultilineKeywordTester(keyword) {
return {
test: (node, sourceCode) =>
node.loc.start.line !== node.loc.end.line &&
sourceCode.getFirstToken(node).value === keyword,
};
return {
test: (node, sourceCode) =>
node.loc.start.line !== node.loc.end.line &&
sourceCode.getFirstToken(node).value === keyword
};
}
/**
@@ -72,9 +72,10 @@ function newMultilineKeywordTester(keyword) {
* @private
*/
function newNodeTypeTester(type) {
return {
test: node => node.type === type,
};
return {
test: node =>
node.type === type
};
}
/**
@@ -84,17 +85,15 @@ function newNodeTypeTester(type) {
* @private
*/
function isIIFEStatement(node) {
if (node.type === "ExpressionStatement") {
let call = astUtils.skipChainExpression(node.expression);
if (node.type === "ExpressionStatement") {
let call = astUtils.skipChainExpression(node.expression);
if (call.type === "UnaryExpression") {
call = astUtils.skipChainExpression(call.argument);
}
return (
call.type === "CallExpression" && astUtils.isFunction(call.callee)
);
}
return false;
if (call.type === "UnaryExpression") {
call = astUtils.skipChainExpression(call.argument);
}
return call.type === "CallExpression" && astUtils.isFunction(call.callee);
}
return false;
}
/**
@@ -106,37 +105,30 @@ function isIIFEStatement(node) {
* @private
*/
function isBlockLikeStatement(sourceCode, node) {
// do-while with a block is a block-like statement.
if (
node.type === "DoWhileStatement" &&
node.body.type === "BlockStatement"
) {
return true;
}
/*
* IIFE is a block-like statement specially from
* JSCS#disallowPaddingNewLinesAfterBlocks.
*/
if (isIIFEStatement(node)) {
return true;
}
// do-while with a block is a block-like statement.
if (node.type === "DoWhileStatement" && node.body.type === "BlockStatement") {
return true;
}
// Checks the last token is a closing brace of blocks.
const lastToken = sourceCode.getLastToken(
node,
astUtils.isNotSemicolonToken,
);
const belongingNode =
lastToken && astUtils.isClosingBraceToken(lastToken)
? sourceCode.getNodeByRangeIndex(lastToken.range[0])
: null;
/*
* IIFE is a block-like statement specially from
* JSCS#disallowPaddingNewLinesAfterBlocks.
*/
if (isIIFEStatement(node)) {
return true;
}
return (
Boolean(belongingNode) &&
(belongingNode.type === "BlockStatement" ||
belongingNode.type === "SwitchStatement")
);
// Checks the last token is a closing brace of blocks.
const lastToken = sourceCode.getLastToken(node, astUtils.isNotSemicolonToken);
const belongingNode = lastToken && astUtils.isClosingBraceToken(lastToken)
? sourceCode.getNodeByRangeIndex(lastToken.range[0])
: null;
return Boolean(belongingNode) && (
belongingNode.type === "BlockStatement" ||
belongingNode.type === "SwitchStatement"
);
}
/**
@@ -153,19 +145,19 @@ function isBlockLikeStatement(sourceCode, node) {
* @private
*/
function getActualLastToken(sourceCode, node) {
const semiToken = sourceCode.getLastToken(node);
const prevToken = sourceCode.getTokenBefore(semiToken);
const nextToken = sourceCode.getTokenAfter(semiToken);
const isSemicolonLessStyle = Boolean(
prevToken &&
nextToken &&
prevToken.range[0] >= node.range[0] &&
astUtils.isSemicolonToken(semiToken) &&
semiToken.loc.start.line !== prevToken.loc.end.line &&
semiToken.loc.end.line === nextToken.loc.start.line,
);
const semiToken = sourceCode.getLastToken(node);
const prevToken = sourceCode.getTokenBefore(semiToken);
const nextToken = sourceCode.getTokenAfter(semiToken);
const isSemicolonLessStyle = Boolean(
prevToken &&
nextToken &&
prevToken.range[0] >= node.range[0] &&
astUtils.isSemicolonToken(semiToken) &&
semiToken.loc.start.line !== prevToken.loc.end.line &&
semiToken.loc.end.line === nextToken.loc.start.line
);
return isSemicolonLessStyle ? prevToken : semiToken;
return isSemicolonLessStyle ? prevToken : semiToken;
}
/**
@@ -177,7 +169,7 @@ function getActualLastToken(sourceCode, node) {
* @private
*/
function replacerToRemovePaddingLines(_, trailingSpaces, indentSpaces) {
return trailingSpaces + indentSpaces;
return trailingSpaces + indentSpaces;
}
/**
@@ -186,7 +178,8 @@ function replacerToRemovePaddingLines(_, trailingSpaces, indentSpaces) {
* @returns {void}
* @private
*/
function verifyForAny() {}
function verifyForAny() {
}
/**
* Check and report statements for `never` configuration.
@@ -202,29 +195,29 @@ function verifyForAny() {}
* @private
*/
function verifyForNever(context, _, nextNode, paddingLines) {
if (paddingLines.length === 0) {
return;
}
if (paddingLines.length === 0) {
return;
}
context.report({
node: nextNode,
messageId: "unexpectedBlankLine",
fix(fixer) {
if (paddingLines.length >= 2) {
return null;
}
context.report({
node: nextNode,
messageId: "unexpectedBlankLine",
fix(fixer) {
if (paddingLines.length >= 2) {
return null;
}
const prevToken = paddingLines[0][0];
const nextToken = paddingLines[0][1];
const start = prevToken.range[1];
const end = nextToken.range[0];
const text = context.sourceCode.text
.slice(start, end)
.replace(PADDING_LINE_SEQUENCE, replacerToRemovePaddingLines);
const prevToken = paddingLines[0][0];
const nextToken = paddingLines[0][1];
const start = prevToken.range[1];
const end = nextToken.range[0];
const text = context.sourceCode.text
.slice(start, end)
.replace(PADDING_LINE_SEQUENCE, replacerToRemovePaddingLines);
return fixer.replaceTextRange([start, end], text);
},
});
return fixer.replaceTextRange([start, end], text);
}
});
}
/**
@@ -241,55 +234,58 @@ function verifyForNever(context, _, nextNode, paddingLines) {
* @private
*/
function verifyForAlways(context, prevNode, nextNode, paddingLines) {
if (paddingLines.length > 0) {
return;
}
if (paddingLines.length > 0) {
return;
}
context.report({
node: nextNode,
messageId: "expectedBlankLine",
fix(fixer) {
const sourceCode = context.sourceCode;
let prevToken = getActualLastToken(sourceCode, prevNode);
const nextToken =
sourceCode.getFirstTokenBetween(prevToken, nextNode, {
includeComments: true,
context.report({
node: nextNode,
messageId: "expectedBlankLine",
fix(fixer) {
const sourceCode = context.sourceCode;
let prevToken = getActualLastToken(sourceCode, prevNode);
const nextToken = sourceCode.getFirstTokenBetween(
prevToken,
nextNode,
{
includeComments: true,
/**
* Skip the trailing comments of the previous node.
* This inserts a blank line after the last trailing comment.
*
* For example:
*
* foo(); // trailing comment.
* // comment.
* bar();
*
* Get fixed to:
*
* foo(); // trailing comment.
*
* // comment.
* bar();
* @param {Token} token The token to check.
* @returns {boolean} `true` if the token is not a trailing comment.
* @private
*/
filter(token) {
if (astUtils.isTokenOnSameLine(prevToken, token)) {
prevToken = token;
return false;
}
return true;
},
}) || nextNode;
const insertText = astUtils.isTokenOnSameLine(prevToken, nextToken)
? "\n\n"
: "\n";
/**
* Skip the trailing comments of the previous node.
* This inserts a blank line after the last trailing comment.
*
* For example:
*
* foo(); // trailing comment.
* // comment.
* bar();
*
* Get fixed to:
*
* foo(); // trailing comment.
*
* // comment.
* bar();
* @param {Token} token The token to check.
* @returns {boolean} `true` if the token is not a trailing comment.
* @private
*/
filter(token) {
if (astUtils.isTokenOnSameLine(prevToken, token)) {
prevToken = token;
return false;
}
return true;
}
}
) || nextNode;
const insertText = astUtils.isTokenOnSameLine(prevToken, nextToken)
? "\n\n"
: "\n";
return fixer.insertTextAfter(prevToken, insertText);
},
});
return fixer.insertTextAfter(prevToken, insertText);
}
});
}
/**
@@ -299,9 +295,9 @@ function verifyForAlways(context, prevNode, nextNode, paddingLines) {
* @private
*/
const PaddingTypes = {
any: { verify: verifyForAny },
never: { verify: verifyForNever },
always: { verify: verifyForAlways },
any: { verify: verifyForAny },
never: { verify: verifyForNever },
always: { verify: verifyForAlways }
};
/**
@@ -310,303 +306,285 @@ const PaddingTypes = {
* @private
*/
const StatementTypes = {
"*": { test: () => true },
"block-like": {
test: (node, sourceCode) => isBlockLikeStatement(sourceCode, node),
},
"cjs-export": {
test: (node, sourceCode) =>
node.type === "ExpressionStatement" &&
node.expression.type === "AssignmentExpression" &&
CJS_EXPORT.test(sourceCode.getText(node.expression.left)),
},
"cjs-import": {
test: (node, sourceCode) =>
node.type === "VariableDeclaration" &&
node.declarations.length > 0 &&
Boolean(node.declarations[0].init) &&
CJS_IMPORT.test(sourceCode.getText(node.declarations[0].init)),
},
directive: {
test: astUtils.isDirective,
},
expression: {
test: node =>
node.type === "ExpressionStatement" && !astUtils.isDirective(node),
},
iife: {
test: isIIFEStatement,
},
"multiline-block-like": {
test: (node, sourceCode) =>
node.loc.start.line !== node.loc.end.line &&
isBlockLikeStatement(sourceCode, node),
},
"multiline-expression": {
test: node =>
node.loc.start.line !== node.loc.end.line &&
node.type === "ExpressionStatement" &&
!astUtils.isDirective(node),
},
"*": { test: () => true },
"block-like": {
test: (node, sourceCode) => isBlockLikeStatement(sourceCode, node)
},
"cjs-export": {
test: (node, sourceCode) =>
node.type === "ExpressionStatement" &&
node.expression.type === "AssignmentExpression" &&
CJS_EXPORT.test(sourceCode.getText(node.expression.left))
},
"cjs-import": {
test: (node, sourceCode) =>
node.type === "VariableDeclaration" &&
node.declarations.length > 0 &&
Boolean(node.declarations[0].init) &&
CJS_IMPORT.test(sourceCode.getText(node.declarations[0].init))
},
directive: {
test: astUtils.isDirective
},
expression: {
test: node => node.type === "ExpressionStatement" && !astUtils.isDirective(node)
},
iife: {
test: isIIFEStatement
},
"multiline-block-like": {
test: (node, sourceCode) =>
node.loc.start.line !== node.loc.end.line &&
isBlockLikeStatement(sourceCode, node)
},
"multiline-expression": {
test: node =>
node.loc.start.line !== node.loc.end.line &&
node.type === "ExpressionStatement" &&
!astUtils.isDirective(node)
},
"multiline-const": newMultilineKeywordTester("const"),
"multiline-let": newMultilineKeywordTester("let"),
"multiline-var": newMultilineKeywordTester("var"),
"singleline-const": newSinglelineKeywordTester("const"),
"singleline-let": newSinglelineKeywordTester("let"),
"singleline-var": newSinglelineKeywordTester("var"),
"multiline-const": newMultilineKeywordTester("const"),
"multiline-let": newMultilineKeywordTester("let"),
"multiline-var": newMultilineKeywordTester("var"),
"singleline-const": newSinglelineKeywordTester("const"),
"singleline-let": newSinglelineKeywordTester("let"),
"singleline-var": newSinglelineKeywordTester("var"),
block: newNodeTypeTester("BlockStatement"),
empty: newNodeTypeTester("EmptyStatement"),
function: newNodeTypeTester("FunctionDeclaration"),
block: newNodeTypeTester("BlockStatement"),
empty: newNodeTypeTester("EmptyStatement"),
function: newNodeTypeTester("FunctionDeclaration"),
break: newKeywordTester("break"),
case: newKeywordTester("case"),
class: newKeywordTester("class"),
const: newKeywordTester("const"),
continue: newKeywordTester("continue"),
debugger: newKeywordTester("debugger"),
default: newKeywordTester("default"),
do: newKeywordTester("do"),
export: newKeywordTester("export"),
for: newKeywordTester("for"),
if: newKeywordTester("if"),
import: newKeywordTester("import"),
let: newKeywordTester("let"),
return: newKeywordTester("return"),
switch: newKeywordTester("switch"),
throw: newKeywordTester("throw"),
try: newKeywordTester("try"),
var: newKeywordTester("var"),
while: newKeywordTester("while"),
with: newKeywordTester("with"),
break: newKeywordTester("break"),
case: newKeywordTester("case"),
class: newKeywordTester("class"),
const: newKeywordTester("const"),
continue: newKeywordTester("continue"),
debugger: newKeywordTester("debugger"),
default: newKeywordTester("default"),
do: newKeywordTester("do"),
export: newKeywordTester("export"),
for: newKeywordTester("for"),
if: newKeywordTester("if"),
import: newKeywordTester("import"),
let: newKeywordTester("let"),
return: newKeywordTester("return"),
switch: newKeywordTester("switch"),
throw: newKeywordTester("throw"),
try: newKeywordTester("try"),
var: newKeywordTester("var"),
while: newKeywordTester("while"),
with: newKeywordTester("with")
};
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../types').Rule.RuleModule} */
/** @type {import('../shared/types').Rule} */
module.exports = {
meta: {
deprecated: {
message: "Formatting rules are being moved out of ESLint core.",
url: "https://eslint.org/blog/2023/10/deprecating-formatting-rules/",
deprecatedSince: "8.53.0",
availableUntil: "11.0.0",
replacedBy: [
{
message:
"ESLint Stylistic now maintains deprecated stylistic core rules.",
url: "https://eslint.style/guide/migration",
plugin: {
name: "@stylistic/eslint-plugin",
url: "https://eslint.style",
},
rule: {
name: "padding-line-between-statements",
url: "https://eslint.style/rules/padding-line-between-statements",
},
},
],
},
type: "layout",
meta: {
deprecated: true,
replacedBy: [],
type: "layout",
docs: {
description: "Require or disallow padding lines between statements",
recommended: false,
url: "https://eslint.org/docs/latest/rules/padding-line-between-statements",
},
docs: {
description: "Require or disallow padding lines between statements",
recommended: false,
url: "https://eslint.org/docs/latest/rules/padding-line-between-statements"
},
fixable: "whitespace",
fixable: "whitespace",
schema: {
definitions: {
paddingType: {
enum: Object.keys(PaddingTypes),
},
statementType: {
anyOf: [
{ enum: Object.keys(StatementTypes) },
{
type: "array",
items: { enum: Object.keys(StatementTypes) },
minItems: 1,
uniqueItems: true,
},
],
},
},
type: "array",
items: {
type: "object",
properties: {
blankLine: { $ref: "#/definitions/paddingType" },
prev: { $ref: "#/definitions/statementType" },
next: { $ref: "#/definitions/statementType" },
},
additionalProperties: false,
required: ["blankLine", "prev", "next"],
},
},
schema: {
definitions: {
paddingType: {
enum: Object.keys(PaddingTypes)
},
statementType: {
anyOf: [
{ enum: Object.keys(StatementTypes) },
{
type: "array",
items: { enum: Object.keys(StatementTypes) },
minItems: 1,
uniqueItems: true
}
]
}
},
type: "array",
items: {
type: "object",
properties: {
blankLine: { $ref: "#/definitions/paddingType" },
prev: { $ref: "#/definitions/statementType" },
next: { $ref: "#/definitions/statementType" }
},
additionalProperties: false,
required: ["blankLine", "prev", "next"]
}
},
messages: {
unexpectedBlankLine: "Unexpected blank line before this statement.",
expectedBlankLine: "Expected blank line before this statement.",
},
},
messages: {
unexpectedBlankLine: "Unexpected blank line before this statement.",
expectedBlankLine: "Expected blank line before this statement."
}
},
create(context) {
const sourceCode = context.sourceCode;
const configureList = context.options || [];
let scopeInfo = null;
create(context) {
const sourceCode = context.sourceCode;
const configureList = context.options || [];
let scopeInfo = null;
/**
* Processes to enter to new scope.
* This manages the current previous statement.
* @returns {void}
* @private
*/
function enterScope() {
scopeInfo = {
upper: scopeInfo,
prevNode: null,
};
}
/**
* Processes to enter to new scope.
* This manages the current previous statement.
* @returns {void}
* @private
*/
function enterScope() {
scopeInfo = {
upper: scopeInfo,
prevNode: null
};
}
/**
* Processes to exit from the current scope.
* @returns {void}
* @private
*/
function exitScope() {
scopeInfo = scopeInfo.upper;
}
/**
* Processes to exit from the current scope.
* @returns {void}
* @private
*/
function exitScope() {
scopeInfo = scopeInfo.upper;
}
/**
* Checks whether the given node matches the given type.
* @param {ASTNode} node The statement node to check.
* @param {string|string[]} type The statement type to check.
* @returns {boolean} `true` if the statement node matched the type.
* @private
*/
function match(node, type) {
let innerStatementNode = node;
/**
* Checks whether the given node matches the given type.
* @param {ASTNode} node The statement node to check.
* @param {string|string[]} type The statement type to check.
* @returns {boolean} `true` if the statement node matched the type.
* @private
*/
function match(node, type) {
let innerStatementNode = node;
while (innerStatementNode.type === "LabeledStatement") {
innerStatementNode = innerStatementNode.body;
}
if (Array.isArray(type)) {
return type.some(match.bind(null, innerStatementNode));
}
return StatementTypes[type].test(innerStatementNode, sourceCode);
}
while (innerStatementNode.type === "LabeledStatement") {
innerStatementNode = innerStatementNode.body;
}
if (Array.isArray(type)) {
return type.some(match.bind(null, innerStatementNode));
}
return StatementTypes[type].test(innerStatementNode, sourceCode);
}
/**
* Finds the last matched configure from configureList.
* @param {ASTNode} prevNode The previous statement to match.
* @param {ASTNode} nextNode The current statement to match.
* @returns {Object} The tester of the last matched configure.
* @private
*/
function getPaddingType(prevNode, nextNode) {
for (let i = configureList.length - 1; i >= 0; --i) {
const configure = configureList[i];
const matched =
match(prevNode, configure.prev) &&
match(nextNode, configure.next);
/**
* Finds the last matched configure from configureList.
* @param {ASTNode} prevNode The previous statement to match.
* @param {ASTNode} nextNode The current statement to match.
* @returns {Object} The tester of the last matched configure.
* @private
*/
function getPaddingType(prevNode, nextNode) {
for (let i = configureList.length - 1; i >= 0; --i) {
const configure = configureList[i];
const matched =
match(prevNode, configure.prev) &&
match(nextNode, configure.next);
if (matched) {
return PaddingTypes[configure.blankLine];
}
}
return PaddingTypes.any;
}
if (matched) {
return PaddingTypes[configure.blankLine];
}
}
return PaddingTypes.any;
}
/**
* Gets padding line sequences between the given 2 statements.
* Comments are separators of the padding line sequences.
* @param {ASTNode} prevNode The previous statement to count.
* @param {ASTNode} nextNode The current statement to count.
* @returns {Array<Token[]>} The array of token pairs.
* @private
*/
function getPaddingLineSequences(prevNode, nextNode) {
const pairs = [];
let prevToken = getActualLastToken(sourceCode, prevNode);
/**
* Gets padding line sequences between the given 2 statements.
* Comments are separators of the padding line sequences.
* @param {ASTNode} prevNode The previous statement to count.
* @param {ASTNode} nextNode The current statement to count.
* @returns {Array<Token[]>} The array of token pairs.
* @private
*/
function getPaddingLineSequences(prevNode, nextNode) {
const pairs = [];
let prevToken = getActualLastToken(sourceCode, prevNode);
if (nextNode.loc.start.line - prevToken.loc.end.line >= 2) {
do {
const token = sourceCode.getTokenAfter(prevToken, {
includeComments: true,
});
if (nextNode.loc.start.line - prevToken.loc.end.line >= 2) {
do {
const token = sourceCode.getTokenAfter(
prevToken,
{ includeComments: true }
);
if (token.loc.start.line - prevToken.loc.end.line >= 2) {
pairs.push([prevToken, token]);
}
prevToken = token;
} while (prevToken.range[0] < nextNode.range[0]);
}
if (token.loc.start.line - prevToken.loc.end.line >= 2) {
pairs.push([prevToken, token]);
}
prevToken = token;
return pairs;
}
} while (prevToken.range[0] < nextNode.range[0]);
}
/**
* Verify padding lines between the given node and the previous node.
* @param {ASTNode} node The node to verify.
* @returns {void}
* @private
*/
function verify(node) {
const parentType = node.parent.type;
const validParent =
astUtils.STATEMENT_LIST_PARENTS.has(parentType) ||
parentType === "SwitchStatement";
return pairs;
}
if (!validParent) {
return;
}
/**
* Verify padding lines between the given node and the previous node.
* @param {ASTNode} node The node to verify.
* @returns {void}
* @private
*/
function verify(node) {
const parentType = node.parent.type;
const validParent =
astUtils.STATEMENT_LIST_PARENTS.has(parentType) ||
parentType === "SwitchStatement";
// Save this node as the current previous statement.
const prevNode = scopeInfo.prevNode;
if (!validParent) {
return;
}
// Verify.
if (prevNode) {
const type = getPaddingType(prevNode, node);
const paddingLines = getPaddingLineSequences(prevNode, node);
// Save this node as the current previous statement.
const prevNode = scopeInfo.prevNode;
type.verify(context, prevNode, node, paddingLines);
}
// Verify.
if (prevNode) {
const type = getPaddingType(prevNode, node);
const paddingLines = getPaddingLineSequences(prevNode, node);
scopeInfo.prevNode = node;
}
type.verify(context, prevNode, node, paddingLines);
}
/**
* Verify padding lines between the given node and the previous node.
* Then process to enter to new scope.
* @param {ASTNode} node The node to verify.
* @returns {void}
* @private
*/
function verifyThenEnterScope(node) {
verify(node);
enterScope();
}
scopeInfo.prevNode = node;
}
return {
Program: enterScope,
BlockStatement: enterScope,
SwitchStatement: enterScope,
StaticBlock: enterScope,
"Program:exit": exitScope,
"BlockStatement:exit": exitScope,
"SwitchStatement:exit": exitScope,
"StaticBlock:exit": exitScope,
/**
* Verify padding lines between the given node and the previous node.
* Then process to enter to new scope.
* @param {ASTNode} node The node to verify.
* @returns {void}
* @private
*/
function verifyThenEnterScope(node) {
verify(node);
enterScope();
}
":statement": verify,
return {
Program: enterScope,
BlockStatement: enterScope,
SwitchStatement: enterScope,
StaticBlock: enterScope,
"Program:exit": exitScope,
"BlockStatement:exit": exitScope,
"SwitchStatement:exit": exitScope,
"StaticBlock:exit": exitScope,
SwitchCase: verifyThenEnterScope,
"SwitchCase:exit": exitScope,
};
},
":statement": verify,
SwitchCase: verifyThenEnterScope,
"SwitchCase:exit": exitScope
};
}
};