eslint-plugin-stylistic-compat
Version:
Compatibility version of @stylistic/eslint-plugin for Node.js >= 12 and ESLint v8
533 lines (528 loc) • 19.3 kB
JavaScript
'use strict';
var _endsWithInstanceProperty = require('/runtime-corejs3/core-js/instance/ends-with');
var utils = require('../utils.js');
var vendor = require('../vendor.js');
var _Object$freeze = require('/runtime-corejs3/core-js/object/freeze');
var _includesInstanceProperty = require('/runtime-corejs3/core-js/instance/includes');
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/set');
require('/runtime-corejs3/core-js/instance/flags');
require('/runtime-corejs3/core-js/instance/starts-with');
require('/runtime-corejs3/core-js/array/from');
require('/runtime-corejs3/core-js/array/is-array');
require('/runtime-corejs3/core-js/instance/concat');
require('/runtime-corejs3/core-js/object/keys');
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/instance/slice');
require('/runtime-corejs3/core-js/object/create');
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/some');
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/string/raw');
require('/runtime-corejs3/core-js/instance/code-point-at');
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/bind');
require('/runtime-corejs3/core-js/instance/splice');
require('/runtime-corejs3/core-js/instance/repeat');
const DEFAULT_OPTIONS = _Object$freeze({
arrays: "never",
objects: "never",
imports: "never",
exports: "never",
functions: "never",
importAttributes: "never",
dynamicImports: "never"
});
const closeBraces = ["}", "]", ")", ">"];
function isTrailingCommaAllowed(lastItem) {
return lastItem.type !== "RestElement";
}
function normalizeOptions$1(optionValue, ecmaVersion) {
if (typeof optionValue === "string") {
return {
arrays: optionValue,
objects: optionValue,
imports: optionValue,
exports: optionValue,
functions: !ecmaVersion || ecmaVersion === "latest" ? optionValue : ecmaVersion < 2017 ? "ignore" : optionValue,
importAttributes: optionValue,
dynamicImports: !ecmaVersion || ecmaVersion === "latest" ? optionValue : ecmaVersion < 2025 ? "ignore" : optionValue
};
}
if (typeof optionValue === "object" && optionValue !== null) {
return {
arrays: optionValue.arrays || DEFAULT_OPTIONS.arrays,
objects: optionValue.objects || DEFAULT_OPTIONS.objects,
imports: optionValue.imports || DEFAULT_OPTIONS.imports,
exports: optionValue.exports || DEFAULT_OPTIONS.exports,
functions: optionValue.functions || DEFAULT_OPTIONS.functions,
importAttributes: optionValue.importAttributes || DEFAULT_OPTIONS.importAttributes,
dynamicImports: optionValue.dynamicImports || DEFAULT_OPTIONS.dynamicImports
};
}
return DEFAULT_OPTIONS;
}
var _baseRule = utils.createRule({
name: "comma-dangle",
package: "js",
meta: {
type: "layout",
docs: {
description: "Require or disallow trailing commas"
},
fixable: "code",
schema: {
definitions: {
value: {
type: "string",
enum: ["always-multiline", "always", "never", "only-multiline"]
},
valueWithIgnore: {
type: "string",
enum: ["always-multiline", "always", "ignore", "never", "only-multiline"]
}
},
type: "array",
items: [{
oneOf: [{
$ref: "#/definitions/value"
}, {
type: "object",
properties: {
arrays: {
$ref: "#/definitions/valueWithIgnore"
},
objects: {
$ref: "#/definitions/valueWithIgnore"
},
imports: {
$ref: "#/definitions/valueWithIgnore"
},
exports: {
$ref: "#/definitions/valueWithIgnore"
},
functions: {
$ref: "#/definitions/valueWithIgnore"
},
importAttributes: {
$ref: "#/definitions/valueWithIgnore"
},
dynamicImports: {
$ref: "#/definitions/valueWithIgnore"
}
},
additionalProperties: false
}]
}],
additionalItems: false
},
messages: {
unexpected: "Unexpected trailing comma.",
missing: "Missing trailing comma."
}
},
create(context) {
var _context$languageOpti, _context$languageOpti2;
const ecmaVersion = (_context$languageOpti = context == null || (_context$languageOpti2 = context.languageOptions) == null ? undefined : _context$languageOpti2.ecmaVersion) != null ? _context$languageOpti : context.parserOptions.ecmaVersion;
const options = normalizeOptions$1(context.options[0], ecmaVersion);
const sourceCode = context.sourceCode;
function last(array) {
var _array;
if (!array) return null;
return (_array = array[array.length - 1]) != null ? _array : null;
}
function getTrailingToken(info) {
switch (info.node.type) {
case "ObjectExpression":
case "ArrayExpression":
case "CallExpression":
case "NewExpression":
case "ImportExpression":
return sourceCode.getLastToken(info.node, 1);
default:
{
const lastItem = info.lastItem;
if (!lastItem) return null;
const nextToken = sourceCode.getTokenAfter(lastItem);
if (utils.isCommaToken(nextToken)) return nextToken;
return sourceCode.getLastToken(lastItem);
}
}
}
function isMultiline(info) {
const lastItem = info.lastItem;
if (!lastItem) return false;
const penultimateToken = getTrailingToken(info);
if (!penultimateToken) return false;
const lastToken = sourceCode.getTokenAfter(penultimateToken);
if (!lastToken) return false;
return lastToken.loc.end.line !== penultimateToken.loc.end.line;
}
function forbidTrailingComma(info) {
const lastItem = info.lastItem;
if (!lastItem) return;
const trailingToken = getTrailingToken(info);
if (trailingToken && utils.isCommaToken(trailingToken)) {
context.report({
node: lastItem,
loc: trailingToken.loc,
messageId: "unexpected",
*fix(fixer) {
yield fixer.remove(trailingToken);
yield fixer.insertTextBefore(sourceCode.getTokenBefore(trailingToken), "");
yield fixer.insertTextAfter(sourceCode.getTokenAfter(trailingToken), "");
}
});
}
}
function forceTrailingComma(info) {
const lastItem = info.lastItem;
if (!lastItem) return;
if (!isTrailingCommaAllowed(lastItem)) {
forbidTrailingComma(info);
return;
}
const trailingToken = getTrailingToken(info);
if (!trailingToken || trailingToken.value === ",") return;
const nextToken = sourceCode.getTokenAfter(trailingToken);
if (!nextToken || !_includesInstanceProperty(closeBraces).call(closeBraces, nextToken.value)) return;
context.report({
node: lastItem,
loc: {
start: trailingToken.loc.end,
end: utils.getNextLocation(sourceCode, trailingToken.loc.end)
},
messageId: "missing",
*fix(fixer) {
yield fixer.insertTextAfter(trailingToken, ",");
yield fixer.insertTextBefore(trailingToken, "");
yield fixer.insertTextAfter(sourceCode.getTokenAfter(trailingToken), "");
}
});
}
function forceTrailingCommaIfMultiline(info) {
if (isMultiline(info)) forceTrailingComma(info);else forbidTrailingComma(info);
}
function allowTrailingCommaIfMultiline(info) {
if (!isMultiline(info)) forbidTrailingComma(info);
}
const predicate = {
"always": forceTrailingComma,
"always-multiline": forceTrailingCommaIfMultiline,
"only-multiline": allowTrailingCommaIfMultiline,
"never": forbidTrailingComma,
ignore() {}
};
return {
ObjectExpression: node => {
predicate[options.objects]({
node,
lastItem: last(node.properties)
});
},
ObjectPattern: node => {
predicate[options.objects]({
node,
lastItem: last(node.properties)
});
},
ArrayExpression: node => {
predicate[options.arrays]({
node,
lastItem: last(node.elements)
});
},
ArrayPattern: node => {
predicate[options.arrays]({
node,
lastItem: last(node.elements)
});
},
ImportDeclaration: node => {
const lastSpecifier = last(node.specifiers);
if ((lastSpecifier == null ? undefined : lastSpecifier.type) === "ImportSpecifier") {
predicate[options.imports]({
node,
lastItem: lastSpecifier
});
}
predicate[options.importAttributes]({
node,
lastItem: last(node.attributes)
});
},
ExportNamedDeclaration: node => {
predicate[options.exports]({
node,
lastItem: last(node.specifiers)
});
predicate[options.importAttributes]({
node,
lastItem: last(node.attributes)
});
},
ExportAllDeclaration: node => {
predicate[options.importAttributes]({
node,
lastItem: last(node.attributes)
});
},
FunctionDeclaration: node => {
predicate[options.functions]({
node,
lastItem: last(node.params)
});
},
FunctionExpression: node => {
predicate[options.functions]({
node,
lastItem: last(node.params)
});
},
ArrowFunctionExpression: node => {
predicate[options.functions]({
node,
lastItem: last(node.params)
});
},
CallExpression: node => {
predicate[options.functions]({
node,
lastItem: last(node.arguments)
});
},
NewExpression: node => {
predicate[options.functions]({
node,
lastItem: last(node.arguments)
});
},
ImportExpression: node => {
var _node$options;
predicate[options.dynamicImports]({
node,
lastItem: (_node$options = node.options) != null ? _node$options : node.source
});
}
};
}
});
const baseRule = /* @__PURE__ */utils.castRuleModule(_baseRule);
const OPTION_VALUE_SCHEME = ["always-multiline", "always", "never", "only-multiline"];
const DEFAULT_OPTION_VALUE = "never";
function normalizeOptions(options = {}) {
var _options$enums, _options$generics, _options$tuples;
if (typeof options === "string") {
return {
enums: options,
generics: options,
tuples: options
};
}
return {
enums: (_options$enums = options.enums) != null ? _options$enums : DEFAULT_OPTION_VALUE,
generics: (_options$generics = options.generics) != null ? _options$generics : DEFAULT_OPTION_VALUE,
tuples: (_options$tuples = options.tuples) != null ? _options$tuples : DEFAULT_OPTION_VALUE
};
}
var commaDangle = utils.createRule({
name: "comma-dangle",
package: "ts",
meta: {
type: "layout",
docs: {
description: "Require or disallow trailing commas"
},
schema: {
$defs: {
value: {
type: "string",
enum: OPTION_VALUE_SCHEME
},
valueWithIgnore: {
type: "string",
enum: [...OPTION_VALUE_SCHEME, "ignore"]
}
},
type: "array",
items: [{
oneOf: [{
$ref: "#/$defs/value"
}, {
type: "object",
properties: {
arrays: {
$ref: "#/$defs/valueWithIgnore"
},
objects: {
$ref: "#/$defs/valueWithIgnore"
},
imports: {
$ref: "#/$defs/valueWithIgnore"
},
exports: {
$ref: "#/$defs/valueWithIgnore"
},
functions: {
$ref: "#/$defs/valueWithIgnore"
},
importAttributes: {
$ref: "#/$defs/valueWithIgnore"
},
dynamicImports: {
$ref: "#/$defs/valueWithIgnore"
},
enums: {
$ref: "#/$defs/valueWithIgnore"
},
generics: {
$ref: "#/$defs/valueWithIgnore"
},
tuples: {
$ref: "#/$defs/valueWithIgnore"
}
},
additionalProperties: false
}]
}],
additionalItems: false
},
fixable: "code",
hasSuggestions: baseRule.meta.hasSuggestions,
messages: baseRule.meta.messages
},
defaultOptions: ["never"],
create(context, [options]) {
var _context$parserOption, _context$filename;
const rules = baseRule.create(context);
const sourceCode = context.sourceCode;
const normalizedOptions = normalizeOptions(options);
const isTSX = ((_context$parserOption = context.parserOptions) == null || (_context$parserOption = _context$parserOption.ecmaFeatures) == null ? undefined : _context$parserOption.jsx) && ((_context$filename = context.filename) == null ? undefined : _endsWithInstanceProperty(_context$filename).call(_context$filename, ".tsx"));
const predicate = {
"always": forceComma,
"always-multiline": forceCommaIfMultiline,
"only-multiline": allowCommaIfMultiline,
"never": forbidComma,
// https://github.com/typescript-eslint/typescript-eslint/issues/7220
"ignore": () => {}
};
function last(nodes) {
var _nodes;
return (_nodes = nodes[nodes.length - 1]) != null ? _nodes : null;
}
function getLastItem(node) {
var _node$body;
switch (node.type) {
case vendor.distExports.AST_NODE_TYPES.TSEnumDeclaration:
return last(((_node$body = node.body) == null ? undefined : _node$body.members) || node.members);
case vendor.distExports.AST_NODE_TYPES.TSTypeParameterDeclaration:
return last(node.params);
case vendor.distExports.AST_NODE_TYPES.TSTupleType:
return last(node.elementTypes);
default:
return null;
}
}
function getTrailingToken(node) {
const last2 = getLastItem(node);
const trailing = last2 && sourceCode.getTokenAfter(last2);
return trailing;
}
function isMultiline(node) {
const last2 = getLastItem(node);
const lastToken = sourceCode.getLastToken(node);
return (last2 == null ? undefined : last2.loc.end.line) !== (lastToken == null ? undefined : lastToken.loc.end.line);
}
function forbidComma(node) {
if (isTSX && node.type === vendor.distExports.AST_NODE_TYPES.TSTypeParameterDeclaration && node.params.length === 1) return;
const last2 = getLastItem(node);
const trailing = getTrailingToken(node);
if (last2 && trailing && vendor.astUtilsExports.isCommaToken(trailing)) {
context.report({
node,
messageId: "unexpected",
fix(fixer) {
return fixer.remove(trailing);
}
});
}
}
function forceComma(node) {
const last2 = getLastItem(node);
const trailing = getTrailingToken(node);
if (last2 && trailing && !vendor.astUtilsExports.isCommaToken(trailing)) {
context.report({
node,
messageId: "missing",
fix(fixer) {
return fixer.insertTextAfter(last2, ",");
}
});
}
}
function allowCommaIfMultiline(node) {
if (!isMultiline(node)) forbidComma(node);
}
function forceCommaIfMultiline(node) {
if (isMultiline(node)) forceComma(node);else forbidComma(node);
}
return {
...rules,
TSEnumDeclaration: predicate[normalizedOptions.enums],
TSTypeParameterDeclaration: predicate[normalizedOptions.generics],
TSTupleType: predicate[normalizedOptions.tuples]
};
}
});
module.exports = commaDangle;