Files
SnowLuma/.pnpm-store/v11/files/2b/cedd186edfca14f3284da859b0df9d01db899a49f9103a32c798ab66782afde2707095b233214d2d3abe5f5b797bc25b71e946f83aedf23cb32f4b34aa473c
T
TanTan 2a69b23b47
Dev Build / cleanup (push) Waiting to run
Dev Build / typecheck (push) Waiting to run
docs: 仓库链接指向本镜像仓库
2026-11-13 09:27:07 +08:00

187 lines
5.5 KiB
Plaintext

import { K as isSingleLine, f as createRule, m as AST_NODE_TYPES, p as deepMerge } from "../utils.js";
function isLastTokenEndOfLine(token, line) {
return token.loc.start.column === line.length - 1;
}
function isCommentsEndOfLine(token, comments, line) {
if (!comments) return false;
if (comments.loc.end.line > token.loc.end.line) return true;
return comments.loc.end.column === line.length;
}
function makeFixFunction({ optsNone, optsSemi, lastToken, commentsAfterLastToken, missingDelimiter, lastTokenLine, isSingleLine }) {
if (optsNone && !isLastTokenEndOfLine(lastToken, lastTokenLine) && !isCommentsEndOfLine(lastToken, commentsAfterLastToken, lastTokenLine) && !isSingleLine) return;
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 member_delimiter_style_default = createRule({
name: "member-delimiter-style",
meta: {
type: "layout",
docs: { description: "Require a specific member delimiter style for interfaces and type literals" },
fixable: "whitespace",
schema: [{
$defs: {
multiLineOption: {
type: "string",
enum: [
"none",
"semi",
"comma"
]
},
singleLineOption: {
type: "string",
enum: ["semi", "comma"]
},
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"
}],
messages: {
unexpectedComma: "Unexpected separator (,).",
unexpectedSemi: "Unexpected separator (;).",
expectedComma: "Expected a comma.",
expectedSemi: "Expected a semicolon."
}
},
create(context, [options]) {
const sourceCode = context.sourceCode;
const baseOptions = options;
const overrides = baseOptions.overrides ?? {};
const interfaceOptions = deepMerge(baseOptions, overrides.interface);
const typeLiteralOptions = 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 lastTokenLine = sourceCode.getLines()[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 === AST_NODE_TYPES.TSInterfaceBody ? node.body : node.members;
let _isSingleLine = isSingleLine(node);
if (options.multilineDetection === "last-member" && !_isSingleLine && members.length > 0) {
if (members[members.length - 1].loc.end.line === node.loc.end.line) _isSingleLine = true;
}
const typeOpts = node.type === 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
};
}
});
export { member_delimiter_style_default as t };