UNPKG

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
'use strict'; var _endsWithInstanceProperty = require('@babel/runtime-corejs3/core-js/instance/ends-with'); var utils = require('../utils.js'); var vendor = require('../vendor.js'); var _Object$freeze = require('@babel/runtime-corejs3/core-js/object/freeze'); var _includesInstanceProperty = require('@babel/runtime-corejs3/core-js/instance/includes'); require('@babel/runtime-corejs3/core-js/object/from-entries'); require('@babel/runtime-corejs3/core-js/instance/map'); require('@babel/runtime-corejs3/core-js/instance/filter'); require('@babel/runtime-corejs3/core-js/object/entries'); require('@babel/runtime-corejs3/core-js/set'); require('@babel/runtime-corejs3/core-js/instance/flags'); require('@babel/runtime-corejs3/core-js/instance/starts-with'); require('@babel/runtime-corejs3/core-js/array/from'); require('@babel/runtime-corejs3/core-js/array/is-array'); require('@babel/runtime-corejs3/core-js/instance/concat'); require('@babel/runtime-corejs3/core-js/object/keys'); require('@babel/runtime-corejs3/core-js/instance/reduce'); require('@babel/runtime-corejs3/core-js/object/assign'); require('@babel/runtime-corejs3/core-js/instance/keys'); require('@babel/runtime-corejs3/core-js/instance/find'); require('@babel/runtime-corejs3/core-js/instance/reverse'); require('@babel/runtime-corejs3/core-js/object/define-property'); require('@babel/runtime-corejs3/core-js/instance/slice'); require('@babel/runtime-corejs3/core-js/object/create'); require('@babel/runtime-corejs3/core-js/instance/last-index-of'); require('@babel/runtime-corejs3/core-js/object/define-properties'); require('@babel/runtime-corejs3/core-js/instance/index-of'); require('@babel/runtime-corejs3/core-js/instance/at'); require('@babel/runtime-corejs3/core-js/symbol'); require('@babel/runtime-corejs3/core-js/symbol/iterator'); require('@babel/runtime-corejs3/core-js/parse-int'); require('@babel/runtime-corejs3/core-js/parse-float'); require('@babel/runtime-corejs3/core-js/weak-map'); require('@babel/runtime-corejs3/core-js/global-this'); require('@babel/runtime-corejs3/core-js/instance/for-each'); require('eslint/use-at-your-own-risk'); require('eslint'); require('@babel/runtime-corejs3/core-js/object/get-own-property-descriptor'); require('@babel/runtime-corejs3/core-js/map'); require('@babel/runtime-corejs3/core-js/instance/some'); require('@babel/runtime-corejs3/core-js/instance/every'); require('@babel/runtime-corejs3/core-js/instance/sort'); require('@babel/runtime-corejs3/core-js/array/of'); require('@babel/runtime-corejs3/core-js/instance/entries'); require('@babel/runtime-corejs3/core-js/instance/find-index'); require('@babel/runtime-corejs3/core-js/instance/flat'); require('@babel/runtime-corejs3/core-js/instance/values'); require('@babel/runtime-corejs3/core-js/object/get-own-property-names'); require('@babel/runtime-corejs3/core-js/number/is-finite'); require('@babel/runtime-corejs3/core-js/number/is-nan'); require('@babel/runtime-corejs3/core-js/number/parse-float'); require('@babel/runtime-corejs3/core-js/number/parse-int'); require('@babel/runtime-corejs3/core-js/object/is'); require('@babel/runtime-corejs3/core-js/object/is-extensible'); require('@babel/runtime-corejs3/core-js/object/is-frozen'); require('@babel/runtime-corejs3/core-js/object/is-sealed'); require('@babel/runtime-corejs3/core-js/object/values'); require('@babel/runtime-corejs3/core-js/string/from-code-point'); require('@babel/runtime-corejs3/core-js/string/raw'); require('@babel/runtime-corejs3/core-js/instance/code-point-at'); require('@babel/runtime-corejs3/core-js/instance/pad-end'); require('@babel/runtime-corejs3/core-js/instance/pad-start'); require('@babel/runtime-corejs3/core-js/instance/trim'); require('@babel/runtime-corejs3/core-js/instance/trim-end'); require('@babel/runtime-corejs3/core-js/instance/trim-left'); require('@babel/runtime-corejs3/core-js/instance/trim-right'); require('@babel/runtime-corejs3/core-js/instance/trim-start'); require('@babel/runtime-corejs3/core-js/symbol/for'); require('@babel/runtime-corejs3/core-js/symbol/key-for'); require('@babel/runtime-corejs3/core-js/object/prevent-extensions'); require('@babel/runtime-corejs3/core-js/object/seal'); require('@babel/runtime-corejs3/core-js/object/get-prototype-of'); require('@babel/runtime-corejs3/core-js/symbol/replace'); require('@babel/runtime-corejs3/core-js/instance/bind'); require('@babel/runtime-corejs3/core-js/instance/splice'); require('@babel/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;