eslint-plugin-stylistic-compat
Version:
Compatibility version of @stylistic/eslint-plugin for Node.js >= 12 and ESLint v8
308 lines (304 loc) • 11.4 kB
JavaScript
'use strict';
var _forEachInstanceProperty = require('/runtime-corejs3/core-js/instance/for-each');
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/set');
require('/runtime-corejs3/core-js/instance/flags');
require('/runtime-corejs3/core-js/instance/includes');
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/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('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/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/bind');
require('/runtime-corejs3/core-js/instance/splice');
require('/runtime-corejs3/core-js/instance/repeat');
function isLastTokenEndOfLine(token, line) {
const positionInLine = token.loc.start.column;
return positionInLine === line.length - 1;
}
function isCommentsEndOfLine(token, comments, line) {
if (!comments) return false;
if (comments.loc.end.line > token.loc.end.line) return true;
const positionInLine = comments.loc.end.column;
return positionInLine === line.length;
}
function makeFixFunction({
optsNone,
optsSemi,
lastToken,
commentsAfterLastToken,
missingDelimiter,
lastTokenLine,
isSingleLine
}) {
if (optsNone && !isLastTokenEndOfLine(lastToken, lastTokenLine) && !isCommentsEndOfLine(lastToken, commentsAfterLastToken, lastTokenLine) && !isSingleLine) {
return null;
}
return fixer => {
if (optsNone) {
return fixer.remove(lastToken);
}
const token = optsSemi ? ";" : ",";
if (missingDelimiter) {
return fixer.insertTextAfter(lastToken, token);
}
return fixer.replaceText(lastToken, token);
};
}
const BASE_SCHEMA = {
type: "object",
properties: {
multiline: {
type: "object",
properties: {
delimiter: {
$ref: "#/items/0/$defs/multiLineOption"
},
requireLast: {
type: "boolean"
}
},
additionalProperties: false
},
singleline: {
type: "object",
properties: {
delimiter: {
$ref: "#/items/0/$defs/singleLineOption"
},
requireLast: {
type: "boolean"
}
},
additionalProperties: false
}
},
additionalProperties: false
};
var memberDelimiterStyle = utils.createRule({
name: "member-delimiter-style",
package: "ts",
meta: {
type: "layout",
docs: {
description: "Require a specific member delimiter style for interfaces and type literals"
},
fixable: "whitespace",
messages: {
unexpectedComma: "Unexpected separator (,).",
unexpectedSemi: "Unexpected separator (;).",
expectedComma: "Expected a comma.",
expectedSemi: "Expected a semicolon."
},
schema: [{
$defs: {
multiLineOption: {
type: "string",
enum: ["none", "semi", "comma"]
},
// note can't have "none" for single line delimiter as it's invalid syntax
singleLineOption: {
type: "string",
enum: ["semi", "comma"]
},
// note - need to define this last as it references the enums
delimiterConfig: BASE_SCHEMA
},
type: "object",
properties: {
...BASE_SCHEMA.properties,
overrides: {
type: "object",
properties: {
interface: {
$ref: "#/items/0/$defs/delimiterConfig"
},
typeLiteral: {
$ref: "#/items/0/$defs/delimiterConfig"
}
},
additionalProperties: false
},
multilineDetection: {
type: "string",
enum: ["brackets", "last-member"]
}
},
additionalProperties: false
}]
},
defaultOptions: [{
multiline: {
delimiter: "semi",
requireLast: true
},
singleline: {
delimiter: "semi",
requireLast: false
},
multilineDetection: "brackets"
}],
create(context, [options]) {
var _baseOptions$override;
const sourceCode = context.sourceCode;
const baseOptions = options;
const overrides = (_baseOptions$override = baseOptions.overrides) != null ? _baseOptions$override : {};
const interfaceOptions = utils.deepMerge(baseOptions, overrides.interface);
const typeLiteralOptions = utils.deepMerge(baseOptions, overrides.typeLiteral);
function checkLastToken(member, opts, isLast) {
function getOption(type) {
if (isLast && !opts.requireLast) {
return type === "none";
}
return opts.delimiter === type;
}
let messageId = null;
let missingDelimiter = false;
const lastToken = sourceCode.getLastToken(member, {
includeComments: false
});
if (!lastToken) return;
const commentsAfterLastToken = sourceCode.getCommentsAfter(lastToken).pop();
const sourceCodeLines = sourceCode.getLines();
const lastTokenLine = sourceCodeLines[(lastToken == null ? undefined : lastToken.loc.start.line) - 1];
const optsSemi = getOption("semi");
const optsComma = getOption("comma");
const optsNone = getOption("none");
if (lastToken.value === ";") {
if (optsComma) {
messageId = "expectedComma";
} else if (optsNone) {
missingDelimiter = true;
messageId = "unexpectedSemi";
}
} else if (lastToken.value === ",") {
if (optsSemi) {
messageId = "expectedSemi";
} else if (optsNone) {
missingDelimiter = true;
messageId = "unexpectedComma";
}
} else {
if (optsSemi) {
missingDelimiter = true;
messageId = "expectedSemi";
} else if (optsComma) {
missingDelimiter = true;
messageId = "expectedComma";
}
}
if (messageId) {
context.report({
node: lastToken,
loc: {
start: {
line: lastToken.loc.end.line,
column: lastToken.loc.end.column
},
end: {
line: lastToken.loc.end.line,
column: lastToken.loc.end.column
}
},
messageId,
fix: makeFixFunction({
optsNone,
optsSemi,
lastToken,
commentsAfterLastToken,
missingDelimiter,
lastTokenLine,
isSingleLine: opts.type === "single-line"
})
});
}
}
function checkMemberSeparatorStyle(node) {
const members = node.type === vendor.distExports.AST_NODE_TYPES.TSInterfaceBody ? node.body : node.members;
let isSingleLine = node.loc.start.line === node.loc.end.line;
if (options.multilineDetection === "last-member" && !isSingleLine && members.length > 0) {
const lastMember = members[members.length - 1];
if (lastMember.loc.end.line === node.loc.end.line) isSingleLine = true;
}
const typeOpts = node.type === vendor.distExports.AST_NODE_TYPES.TSInterfaceBody ? interfaceOptions : typeLiteralOptions;
const opts = isSingleLine ? {
...typeOpts.singleline,
type: "single-line"
} : {
...typeOpts.multiline,
type: "multi-line"
};
_forEachInstanceProperty(members).call(members, (member, index) => {
checkLastToken(member, opts != null ? opts : {}, index === members.length - 1);
});
}
return {
TSInterfaceBody: checkMemberSeparatorStyle,
TSTypeLiteral: checkMemberSeparatorStyle
};
}
});
module.exports = memberDelimiterStyle;