eslint-plugin-stylistic-compat
Version:
Compatibility version of @stylistic/eslint-plugin for Node.js >= 12 and ESLint v8
480 lines (476 loc) • 22.2 kB
JavaScript
'use strict';
var _Array$from = require('/runtime-corejs3/core-js/array/from');
var _Set = require('/runtime-corejs3/core-js/set');
var _String$raw = require('/runtime-corejs3/core-js/string/raw');
var _Array$isArray = require('/runtime-corejs3/core-js/array/is-array');
var _includesInstanceProperty = require('/runtime-corejs3/core-js/instance/includes');
var _sliceInstanceProperty = require('/runtime-corejs3/core-js/instance/slice');
var _Object$keys = require('/runtime-corejs3/core-js/object/keys');
var _someInstanceProperty = require('/runtime-corejs3/core-js/instance/some');
var _bindInstanceProperty = require('/runtime-corejs3/core-js/instance/bind');
var utils = require('../utils.js');
var vendor = require('../vendor.js');
require('/runtime-corejs3/core-js/object/from-entries');
require('/runtime-corejs3/core-js/instance/map');
require('/runtime-corejs3/core-js/instance/filter');
require('/runtime-corejs3/core-js/object/entries');
require('/runtime-corejs3/core-js/instance/flags');
require('/runtime-corejs3/core-js/instance/starts-with');
require('/runtime-corejs3/core-js/instance/concat');
require('/runtime-corejs3/core-js/instance/reduce');
require('/runtime-corejs3/core-js/object/assign');
require('/runtime-corejs3/core-js/instance/keys');
require('/runtime-corejs3/core-js/instance/find');
require('/runtime-corejs3/core-js/instance/reverse');
require('/runtime-corejs3/core-js/object/define-property');
require('/runtime-corejs3/core-js/object/create');
require('/runtime-corejs3/core-js/object/freeze');
require('/runtime-corejs3/core-js/instance/last-index-of');
require('/runtime-corejs3/core-js/object/define-properties');
require('/runtime-corejs3/core-js/instance/index-of');
require('/runtime-corejs3/core-js/instance/at');
require('/runtime-corejs3/core-js/symbol');
require('/runtime-corejs3/core-js/symbol/iterator');
require('/runtime-corejs3/core-js/parse-int');
require('/runtime-corejs3/core-js/parse-float');
require('/runtime-corejs3/core-js/weak-map');
require('/runtime-corejs3/core-js/global-this');
require('/runtime-corejs3/core-js/instance/for-each');
require('eslint/use-at-your-own-risk');
require('eslint');
require('/runtime-corejs3/core-js/object/get-own-property-descriptor');
require('/runtime-corejs3/core-js/map');
require('/runtime-corejs3/core-js/instance/every');
require('/runtime-corejs3/core-js/instance/sort');
require('/runtime-corejs3/core-js/array/of');
require('/runtime-corejs3/core-js/instance/entries');
require('/runtime-corejs3/core-js/instance/find-index');
require('/runtime-corejs3/core-js/instance/flat');
require('/runtime-corejs3/core-js/instance/values');
require('/runtime-corejs3/core-js/object/get-own-property-names');
require('/runtime-corejs3/core-js/number/is-finite');
require('/runtime-corejs3/core-js/number/is-nan');
require('/runtime-corejs3/core-js/number/parse-float');
require('/runtime-corejs3/core-js/number/parse-int');
require('/runtime-corejs3/core-js/object/is');
require('/runtime-corejs3/core-js/object/is-extensible');
require('/runtime-corejs3/core-js/object/is-frozen');
require('/runtime-corejs3/core-js/object/is-sealed');
require('/runtime-corejs3/core-js/object/values');
require('/runtime-corejs3/core-js/string/from-code-point');
require('/runtime-corejs3/core-js/instance/code-point-at');
require('/runtime-corejs3/core-js/instance/ends-with');
require('/runtime-corejs3/core-js/instance/pad-end');
require('/runtime-corejs3/core-js/instance/pad-start');
require('/runtime-corejs3/core-js/instance/trim');
require('/runtime-corejs3/core-js/instance/trim-end');
require('/runtime-corejs3/core-js/instance/trim-left');
require('/runtime-corejs3/core-js/instance/trim-right');
require('/runtime-corejs3/core-js/instance/trim-start');
require('/runtime-corejs3/core-js/symbol/for');
require('/runtime-corejs3/core-js/symbol/key-for');
require('/runtime-corejs3/core-js/object/prevent-extensions');
require('/runtime-corejs3/core-js/object/seal');
require('/runtime-corejs3/core-js/object/get-prototype-of');
require('/runtime-corejs3/core-js/symbol/replace');
require('/runtime-corejs3/core-js/instance/splice');
require('/runtime-corejs3/core-js/instance/repeat');
const CJS_EXPORT = /^(?:module\s*\.\s*)?exports(?:\s*\.|\s*\[|$)/u;
const CJS_IMPORT = /^require\(/u;
const LT = `[${_Array$from(/* @__PURE__ */new _Set(["\r\n", "\r", "\n", "\u2028", "\u2029"])).join("")}]`;
const PADDING_LINE_SEQUENCE = new RegExp(_String$raw`^(\s*?${LT})\s*${LT}(\s*;?)$`, "u");
function newKeywordTester(type, keyword) {
return {
test(node, sourceCode) {
var _sourceCode$getFirstT;
const isSameKeyword = ((_sourceCode$getFirstT = sourceCode.getFirstToken(node)) == null ? undefined : _sourceCode$getFirstT.value) === keyword;
const isSameType = _Array$isArray(type) ? _includesInstanceProperty(type).call(type, node.type) : type === node.type;
return isSameKeyword && isSameType;
}
};
}
function newSinglelineKeywordTester(keyword) {
return {
test(node, sourceCode) {
return node.loc.start.line === node.loc.end.line && sourceCode.getFirstToken(node).value === keyword;
}
};
}
function newMultilineKeywordTester(keyword) {
return {
test(node, sourceCode) {
return node.loc.start.line !== node.loc.end.line && sourceCode.getFirstToken(node).value === keyword;
}
};
}
function newNodeTypeTester(type) {
return {
test: node => node.type === type
};
}
function skipChainExpression(node) {
return node && node.type === vendor.distExports.AST_NODE_TYPES.ChainExpression ? node.expression : node;
}
function isIIFEStatement(node) {
if (node.type === vendor.distExports.AST_NODE_TYPES.ExpressionStatement) {
let expression = skipChainExpression(node.expression);
if (expression.type === vendor.distExports.AST_NODE_TYPES.UnaryExpression) expression = skipChainExpression(expression.argument);
if (expression.type === vendor.distExports.AST_NODE_TYPES.CallExpression) {
let node2 = expression.callee;
while (node2.type === vendor.distExports.AST_NODE_TYPES.SequenceExpression) node2 = node2.expressions[node2.expressions.length - 1];
return vendor.astUtilsExports.isFunction(node2);
}
}
return false;
}
function isCJSRequire(node) {
if (node.type === vendor.distExports.AST_NODE_TYPES.VariableDeclaration) {
const declaration = node.declarations[0];
if (declaration != null && declaration.init) {
let call = declaration == null ? undefined : declaration.init;
while (call.type === vendor.distExports.AST_NODE_TYPES.MemberExpression) call = call.object;
if (call.type === vendor.distExports.AST_NODE_TYPES.CallExpression && call.callee.type === vendor.distExports.AST_NODE_TYPES.Identifier) {
return call.callee.name === "require";
}
}
}
return false;
}
function isBlockLikeStatement(node, sourceCode) {
if (node.type === vendor.distExports.AST_NODE_TYPES.DoWhileStatement && node.body.type === vendor.distExports.AST_NODE_TYPES.BlockStatement) {
return true;
}
if (isIIFEStatement(node)) return true;
const lastToken = sourceCode.getLastToken(node, vendor.astUtilsExports.isNotSemicolonToken);
const belongingNode = lastToken && vendor.astUtilsExports.isClosingBraceToken(lastToken) ? sourceCode.getNodeByRangeIndex(lastToken.range[0]) : null;
return !!belongingNode && (belongingNode.type === vendor.distExports.AST_NODE_TYPES.BlockStatement || belongingNode.type === vendor.distExports.AST_NODE_TYPES.SwitchStatement);
}
function isDirective(node, sourceCode) {
var _node$parent, _node$parent2;
return node.type === vendor.distExports.AST_NODE_TYPES.ExpressionStatement && (((_node$parent = node.parent) == null ? undefined : _node$parent.type) === vendor.distExports.AST_NODE_TYPES.Program || ((_node$parent2 = node.parent) == null ? undefined : _node$parent2.type) === vendor.distExports.AST_NODE_TYPES.BlockStatement && vendor.astUtilsExports.isFunction(node.parent.parent)) && node.expression.type === vendor.distExports.AST_NODE_TYPES.Literal && typeof node.expression.value === "string" && !vendor.astUtilsExports.isParenthesized(node.expression, sourceCode);
}
function isDirectivePrologue(node, sourceCode) {
if (isDirective(node, sourceCode) && node.parent && "body" in node.parent && _Array$isArray(node.parent.body)) {
for (const sibling of node.parent.body) {
if (sibling === node) break;
if (!isDirective(sibling, sourceCode)) return false;
}
return true;
}
return false;
}
function isCJSExport(node) {
if (node.type === vendor.distExports.AST_NODE_TYPES.ExpressionStatement) {
const expression = node.expression;
if (expression.type === vendor.distExports.AST_NODE_TYPES.AssignmentExpression) {
let left = expression.left;
if (left.type === vendor.distExports.AST_NODE_TYPES.MemberExpression) {
while (left.object.type === vendor.distExports.AST_NODE_TYPES.MemberExpression) left = left.object;
return left.object.type === vendor.distExports.AST_NODE_TYPES.Identifier && (left.object.name === "exports" || left.object.name === "module" && left.property.type === vendor.distExports.AST_NODE_TYPES.Identifier && left.property.name === "exports");
}
}
}
return false;
}
function isExpression(node, sourceCode) {
return node.type === vendor.distExports.AST_NODE_TYPES.ExpressionStatement && !isDirectivePrologue(node, sourceCode);
}
function getActualLastToken(node, sourceCode) {
const semiToken = sourceCode.getLastToken(node);
const prevToken = sourceCode.getTokenBefore(semiToken);
const nextToken = sourceCode.getTokenAfter(semiToken);
const isSemicolonLessStyle = prevToken && nextToken && prevToken.range[0] >= node.range[0] && vendor.astUtilsExports.isSemicolonToken(semiToken) && semiToken.loc.start.line !== prevToken.loc.end.line && semiToken.loc.end.line === nextToken.loc.start.line;
return isSemicolonLessStyle ? prevToken : semiToken;
}
function replacerToRemovePaddingLines(_, trailingSpaces, indentSpaces) {
return trailingSpaces + indentSpaces;
}
function verifyForAny() {}
function verifyForNever(context, _, nextNode, paddingLines) {
if (paddingLines.length === 0) return;
context.report({
node: nextNode,
messageId: "unexpectedBlankLine",
fix(fixer) {
var _context;
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 = _sliceInstanceProperty(_context = context.getSourceCode().text).call(_context, start, end).replace(PADDING_LINE_SEQUENCE, replacerToRemovePaddingLines);
return fixer.replaceTextRange([start, end], text);
}
});
}
function verifyForAlways(context, prevNode, nextNode, paddingLines) {
if (paddingLines.length > 0) return;
context.report({
node: nextNode,
messageId: "expectedBlankLine",
fix(fixer) {
const sourceCode = context.sourceCode;
let prevToken = getActualLastToken(prevNode, sourceCode);
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 The token to check.
* @returns `true` if the token is not a trailing comment.
* @private
*/
filter(token) {
if (vendor.astUtilsExports.isTokenOnSameLine(prevToken, token)) {
prevToken = token;
return false;
}
return true;
}
}) || nextNode;
const insertText = vendor.astUtilsExports.isTokenOnSameLine(prevToken, nextToken) ? "\n\n" : "\n";
return fixer.insertTextAfter(prevToken, insertText);
}
});
}
const PaddingTypes = {
any: {
verify: verifyForAny
},
never: {
verify: verifyForNever
},
always: {
verify: verifyForAlways
}
};
const StatementTypes = {
"*": {
test: () => true
},
"block-like": {
test: isBlockLikeStatement
},
"exports": {
test: isCJSExport
},
"require": {
test: isCJSRequire
},
"directive": {
test: isDirectivePrologue
},
"expression": {
test: isExpression
},
"iife": {
test: isIIFEStatement
},
"multiline-block-like": {
test: (node, sourceCode) => node.loc.start.line !== node.loc.end.line && isBlockLikeStatement(node, sourceCode)
},
"multiline-expression": {
test: (node, sourceCode) => node.loc.start.line !== node.loc.end.line && node.type === vendor.distExports.AST_NODE_TYPES.ExpressionStatement && !isDirectivePrologue(node, sourceCode)
},
"multiline-const": newMultilineKeywordTester("const"),
"multiline-export": newMultilineKeywordTester("export"),
"multiline-let": newMultilineKeywordTester("let"),
"multiline-var": newMultilineKeywordTester("var"),
"singleline-const": newSinglelineKeywordTester("const"),
"singleline-export": newSinglelineKeywordTester("export"),
"singleline-let": newSinglelineKeywordTester("let"),
"singleline-var": newSinglelineKeywordTester("var"),
"block": newNodeTypeTester(vendor.distExports.AST_NODE_TYPES.BlockStatement),
"empty": newNodeTypeTester(vendor.distExports.AST_NODE_TYPES.EmptyStatement),
"function": newNodeTypeTester(vendor.distExports.AST_NODE_TYPES.FunctionDeclaration),
"ts-method": newNodeTypeTester(vendor.distExports.AST_NODE_TYPES.TSMethodSignature),
"break": newKeywordTester(vendor.distExports.AST_NODE_TYPES.BreakStatement, "break"),
"case": newKeywordTester(vendor.distExports.AST_NODE_TYPES.SwitchCase, "case"),
"class": newKeywordTester(vendor.distExports.AST_NODE_TYPES.ClassDeclaration, "class"),
"const": newKeywordTester(vendor.distExports.AST_NODE_TYPES.VariableDeclaration, "const"),
"continue": newKeywordTester(vendor.distExports.AST_NODE_TYPES.ContinueStatement, "continue"),
"debugger": newKeywordTester(vendor.distExports.AST_NODE_TYPES.DebuggerStatement, "debugger"),
"default": newKeywordTester([vendor.distExports.AST_NODE_TYPES.SwitchCase, vendor.distExports.AST_NODE_TYPES.ExportDefaultDeclaration], "default"),
"do": newKeywordTester(vendor.distExports.AST_NODE_TYPES.DoWhileStatement, "do"),
"export": newKeywordTester([vendor.distExports.AST_NODE_TYPES.ExportAllDeclaration, vendor.distExports.AST_NODE_TYPES.ExportDefaultDeclaration, vendor.distExports.AST_NODE_TYPES.ExportNamedDeclaration], "export"),
"for": newKeywordTester([vendor.distExports.AST_NODE_TYPES.ForStatement, vendor.distExports.AST_NODE_TYPES.ForInStatement, vendor.distExports.AST_NODE_TYPES.ForOfStatement], "for"),
"if": newKeywordTester(vendor.distExports.AST_NODE_TYPES.IfStatement, "if"),
"import": newKeywordTester(vendor.distExports.AST_NODE_TYPES.ImportDeclaration, "import"),
"let": newKeywordTester(vendor.distExports.AST_NODE_TYPES.VariableDeclaration, "let"),
"return": newKeywordTester(vendor.distExports.AST_NODE_TYPES.ReturnStatement, "return"),
"switch": newKeywordTester(vendor.distExports.AST_NODE_TYPES.SwitchStatement, "switch"),
"throw": newKeywordTester(vendor.distExports.AST_NODE_TYPES.ThrowStatement, "throw"),
"try": newKeywordTester(vendor.distExports.AST_NODE_TYPES.TryStatement, "try"),
"var": newKeywordTester(vendor.distExports.AST_NODE_TYPES.VariableDeclaration, "var"),
"while": newKeywordTester([vendor.distExports.AST_NODE_TYPES.WhileStatement, vendor.distExports.AST_NODE_TYPES.DoWhileStatement], "while"),
"with": newKeywordTester(vendor.distExports.AST_NODE_TYPES.WithStatement, "with"),
"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))
},
// Additional Typescript constructs
"enum": newKeywordTester(vendor.distExports.AST_NODE_TYPES.TSEnumDeclaration, "enum"),
"interface": newKeywordTester(vendor.distExports.AST_NODE_TYPES.TSInterfaceDeclaration, "interface"),
"type": newKeywordTester(vendor.distExports.AST_NODE_TYPES.TSTypeAliasDeclaration, "type"),
"function-overload": {
test: node => node.type === "TSDeclareFunction"
}
};
var paddingLineBetweenStatements = utils.createRule({
name: "padding-line-between-statements",
package: "ts",
meta: {
type: "layout",
docs: {
description: "Require or disallow padding lines between statements"
},
fixable: "whitespace",
hasSuggestions: false,
// This is intentionally an array schema as you can pass 0..n config objects
schema: {
$defs: {
paddingType: {
type: "string",
enum: _Object$keys(PaddingTypes)
},
statementType: {
anyOf: [{
type: "string",
enum: _Object$keys(StatementTypes)
}, {
type: "array",
items: {
type: "string",
enum: _Object$keys(StatementTypes)
},
minItems: 1,
uniqueItems: true,
additionalItems: false
}]
}
},
type: "array",
additionalItems: false,
items: {
type: "object",
properties: {
blankLine: {
$ref: "#/$defs/paddingType"
},
prev: {
$ref: "#/$defs/statementType"
},
next: {
$ref: "#/$defs/statementType"
}
},
additionalProperties: false,
required: ["blankLine", "prev", "next"]
}
},
messages: {
unexpectedBlankLine: "Unexpected blank line before this statement.",
expectedBlankLine: "Expected blank line before this statement."
}
},
defaultOptions: [],
create(context) {
const sourceCode = context.sourceCode;
const configureList = context.options || [];
let scopeInfo = null;
function enterScope() {
scopeInfo = {
upper: scopeInfo,
prevNode: null
};
}
function exitScope() {
if (scopeInfo) scopeInfo = scopeInfo.upper;
}
function match(node, type) {
let innerStatementNode = node;
while (innerStatementNode.type === vendor.distExports.AST_NODE_TYPES.LabeledStatement) innerStatementNode = innerStatementNode.body;
if (_Array$isArray(type)) return _someInstanceProperty(type).call(type, _bindInstanceProperty(match).call(match, null, innerStatementNode));
return StatementTypes[type].test(innerStatementNode, sourceCode);
}
function getPaddingType(prevNode, nextNode) {
for (let i = configureList.length - 1; i >= 0; --i) {
const configure = configureList[i];
if (match(prevNode, configure.prev) && match(nextNode, configure.next)) {
return PaddingTypes[configure.blankLine];
}
}
return PaddingTypes.any;
}
function getPaddingLineSequences(prevNode, nextNode) {
const pairs = [];
let prevToken = getActualLastToken(prevNode, sourceCode);
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]);
}
return pairs;
}
function verify(node) {
var _context2;
if (!node.parent || !_includesInstanceProperty(_context2 = [vendor.distExports.AST_NODE_TYPES.BlockStatement, vendor.distExports.AST_NODE_TYPES.Program, vendor.distExports.AST_NODE_TYPES.StaticBlock, vendor.distExports.AST_NODE_TYPES.SwitchCase, vendor.distExports.AST_NODE_TYPES.SwitchStatement, vendor.distExports.AST_NODE_TYPES.TSInterfaceBody, vendor.distExports.AST_NODE_TYPES.TSModuleBlock, vendor.distExports.AST_NODE_TYPES.TSTypeLiteral]).call(_context2, node.parent.type)) {
return;
}
const prevNode = scopeInfo.prevNode;
if (prevNode) {
const type = getPaddingType(prevNode, node);
const paddingLines = getPaddingLineSequences(prevNode, node);
type.verify(context, prevNode, node, paddingLines);
}
scopeInfo.prevNode = node;
}
function verifyThenEnterScope(node) {
verify(node);
enterScope();
}
return {
"Program": enterScope,
"BlockStatement": enterScope,
"SwitchStatement": enterScope,
"StaticBlock": enterScope,
"TSInterfaceBody": enterScope,
"TSModuleBlock": enterScope,
"TSTypeLiteral": enterScope,
"Program:exit": exitScope,
"BlockStatement:exit": exitScope,
"SwitchStatement:exit": exitScope,
"StaticBlock:exit": exitScope,
"TSInterfaceBody:exit": exitScope,
"TSModuleBlock:exit": exitScope,
"TSTypeLiteral:exit": exitScope,
":statement": verify,
"SwitchCase": verifyThenEnterScope,
"TSDeclareFunction": verifyThenEnterScope,
"TSMethodSignature": verifyThenEnterScope,
"SwitchCase:exit": exitScope,
"TSDeclareFunction:exit": exitScope,
"TSMethodSignature:exit": exitScope
};
}
});
module.exports = paddingLineBetweenStatements;