Files
NapCatQQ/.pnpm-store/v3/files/78/1fb2bc607863b5c0d6fd9bbc51e1983a9efa305bb6d6071297fc34a258638ee26a51563294edac297c2af51a66e040e36d0cddea65417e7bed632ed35953f6
TanTan e311ca3275
Build NapCat Artifacts / Windows Loader Test (push) Canceled after 0s
Build NapCat Artifacts / Type Check & Test (push) Canceled after 0s
Build NapCat Artifacts / Build NapCat.Framework (push) Canceled after 0s
Build NapCat Artifacts / Build NapCat.Shell (push) Canceled after 0s
docs: 仓库链接指向本镜像仓库
2026-11-13 09:25:58 +08:00

236 lines
6.8 KiB
Plaintext

'use strict';
var utils = require('../utils.js');
var utils$1 = require('@typescript-eslint/utils');
require('eslint-visitor-keys');
require('espree');
require('estraverse');
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]) {
const sourceCode = context.sourceCode;
const baseOptions = options;
const overrides = baseOptions.overrides ?? {};
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?.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 === utils$1.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 === utils$1.AST_NODE_TYPES.TSInterfaceBody ? interfaceOptions : typeLiteralOptions;
const opts = isSingleLine ? { ...typeOpts.singleline, type: "single-line" } : { ...typeOpts.multiline, type: "multi-line" };
members.forEach((member, index) => {
checkLastToken(member, opts ?? {}, index === members.length - 1);
});
}
return {
TSInterfaceBody: checkMemberSeparatorStyle,
TSTypeLiteral: checkMemberSeparatorStyle
};
}
});
module.exports = memberDelimiterStyle;