@longzai-intelligence-oxlint/tsdoc-plugin 0.1.27 → 0.1.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +33 -1
- package/dist/index.js +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,36 @@
|
|
|
1
1
|
import { Rule } from "@oxlint/plugins";
|
|
2
|
+
//#region src/rules/separator-format.rule.d.ts
|
|
3
|
+
/**
|
|
4
|
+
* 分隔符正则表达式
|
|
5
|
+
* 匹配格式:===...=== 文本 ===...===
|
|
6
|
+
* 注意:注释 value 不包含 // 前缀
|
|
7
|
+
*/
|
|
8
|
+
declare const SEPARATOR_PATTERN: RegExp;
|
|
9
|
+
/**
|
|
10
|
+
* 解析后的分隔符注释类型
|
|
11
|
+
*/
|
|
12
|
+
type ParsedSeparatorComment = {
|
|
13
|
+
/**
|
|
14
|
+
* 前导等号
|
|
15
|
+
*/
|
|
16
|
+
leadingEquals: string;
|
|
17
|
+
/**
|
|
18
|
+
* 分隔符文本
|
|
19
|
+
*/
|
|
20
|
+
text: string;
|
|
21
|
+
/**
|
|
22
|
+
* 后导等号
|
|
23
|
+
*/
|
|
24
|
+
trailingEquals: string;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* 解析分隔符注释
|
|
28
|
+
*
|
|
29
|
+
* @param commentText - 注释文本
|
|
30
|
+
* @returns 解析结果,包含前导等号、文本和后导等号
|
|
31
|
+
*/
|
|
32
|
+
declare function parseSeparatorComment(commentText: string): ParsedSeparatorComment | null;
|
|
33
|
+
//#endregion
|
|
2
34
|
//#region src/index.d.ts
|
|
3
35
|
/**
|
|
4
36
|
* tsdoc 规则集合
|
|
@@ -9,4 +41,4 @@ declare const tsdocRules: Record<string, Rule>;
|
|
|
9
41
|
*/
|
|
10
42
|
declare const tsdocPlugin: import("@oxlint/plugins").Plugin;
|
|
11
43
|
//#endregion
|
|
12
|
-
export { tsdocPlugin as default, tsdocPlugin, tsdocRules };
|
|
44
|
+
export { type ParsedSeparatorComment, SEPARATOR_PATTERN, tsdocPlugin as default, tsdocPlugin, parseSeparatorComment, tsdocRules };
|
package/dist/index.js
CHANGED
|
@@ -10,4 +10,4 @@ import{defineRule as e,eslintCompatPlugin as t}from"@oxlint/plugins";import*as n
|
|
|
10
10
|
`);return n.replaceTextRange(r,`/*${o}*/`)}const Re=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`禁止使用旧版 JSDoc 标签`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(i)for(let a of i.tags)Ie(a.tag)&&e.report({node:t,message:`禁止使用旧版 JSDoc 标签 @${a.tag},该标签在 TSDoc 中已不推荐使用`,fix:e=>Le(n,a.tag,e,r.range)})}}}}}),ze=[...Object.values(x),`参数描述`,`返回值描述`,`函数描述`,`方法描述`,`类描述`,`变量描述`,`类型参数描述`,`描述`];function k(e){let t=e.trim();t.startsWith(`-`)&&(t=t.slice(1).trim());for(let e of ze)if(t===e)return e;return null}function Be(e){let t=k(e);return t?`禁止使用占位描述 "${t}",请提供有意义的描述`:null}function Ve(e){let t=[],n=p(e);for(let e of n){let n=k(e.description);n&&t.push(`@param 标签禁止使用占位描述 "${n}",请提供有意义的描述`)}let r=m(e);if(r){let e=k(r.description);e&&t.push(`@returns 标签禁止使用占位描述 "${e}",请提供有意义的描述`)}let i=e.tags.filter(e=>e.tag===`typeParam`||e.tag===`template`);for(let e of i){let n=k(e.description);n&&t.push(`@typeParam 标签禁止使用占位描述 "${n}",请提供有意义的描述`)}return t}const He=e({meta:{type:`suggestion`,docs:{description:`禁止使用占位描述文本`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(!i)continue;let a=Be(i.description);a&&e.report({node:t,message:a});let o=Ve(i);for(let n of o)e.report({node:t,message:n})}}}}});function Ue(e){return e?e.trim().startsWith(`-`):!1}const We=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:"要求参数描述使用 `-` 分隔"}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(!i)continue;let a=p(i);for(let i of a)Ue(i.description)||e.report({node:t,message:`参数 "${i.name}" 的描述应该使用 \`-\` 分隔,格式:@param ${i.name} - 描述`,fix:e=>{let t=RegExp(`(@param\\s+${E(i.name)}\\s+)([^\\-\\s].*?)(\\n|$)`,`g`),a=n.replace(t,`$1- $2$3`);return e.replaceTextRange(r.range,`/*${a}*/`)}})}}}}});function Ge(e){let t=e.split(`
|
|
11
11
|
`),n=-1,r=!1;for(let e=0;e<t.length;e++){let i=t[e];if(!i)continue;let a=i.trim();if(f(a.startsWith(`*`)?a.slice(1).trim():a)){r=!r;continue}if(!r&&a.startsWith(`*`)&&a.slice(1).trim().startsWith(`@`)){n=e;break}}if(n===-1||n===0)return!0;let i=t[n-1];if(!i)return!0;let a=i.trim();return a===`*`||a===``}const Ke=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求标签前有空行`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);i&&i.tags.length>0&&h(i)&&(Ge(n)||e.report({node:t,message:`标签前应有一个空行`,fix:e=>{let t=n.replace(/([ \t]*)(\* [^\n@]+)\n([ \t]*)(\* @)/g,(e,t,n,r,i)=>`${t}${n}\n${t||r}*\n${r}${i}`);return e.replaceTextRange(r.range,`/*${t}*/`)}}))}}}}}),qe=[/使用\s+\S+\s+代替/,/请使用\s+\S+/,/use\s+\S+\s+instead/i,/replaced\s+by\s+\S+/i];function Je(e){if(!e)return!1;let t=e.trim();if(t.length===0)return!1;for(let e of qe)if(e.test(t))return!0;return t.length>10}const Ye=e({meta:{type:`suggestion`,docs:{description:`要求 @deprecated 标签有替代方案说明`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(!i)continue;let a=i.tags.find(e=>e.tag===`deprecated`);a&&(Je(a.description)||e.report({node:t,message:`@deprecated 标签应该包含替代方案说明,例如:@deprecated 使用 newMethod 代替`}))}}}}}),Xe=[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`,`ClassDeclaration`,`VariableDeclaration`,`MethodDefinition`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSPropertySignature`,`TSEnumMember`],Ze=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求 TSDoc 注释有描述文本`}},createOnce(e){let t=[];function n(n){let r=b(t,n,e.sourceCode.text);if(!r)return;let i=d(r.value);i&&(h(i)||e.report({node:n,message:`TSDoc 注释缺少描述`,fix:t=>{let n=S(e.sourceCode.text,r.range);return Oe(t,r,n)}}))}let r={Program(){t=e.sourceCode.getAllComments()}};for(let e of Xe)r[e]=e=>n(e);return r}});function A(e){return pe.safeParse(e).success}function j(e){return me.safeParse(e).success}function M(e){return he.safeParse(e).success}function Qe(e){if(!Array.isArray(e)||e.length===0)return null;let t=e[0];if(!t||typeof t!=`object`)return null;let n=t;if(`type`in n&&n.type===`Property`&&`key`in n){let e=n.key;if(e&&typeof e==`object`&&`name`in e&&typeof e.name==`string`)return e.name}if(`type`in n&&n.type===`RestElement`&&`argument`in n){let e=n.argument;if(e&&typeof e==`object`&&`name`in e&&typeof e.name==`string`)return e.name}return null}function $e(e){if(!Array.isArray(e)||e.length===0)return null;let t=e[0];return t&&typeof t==`object`&&`name`in t&&typeof t.name==`string`?t.name:null}function et(e){if(!e||typeof e!=`object`)return null;let t=e;return`type`in t&&t.type===`ObjectPattern`&&`properties`in t?Qe(t.properties):`type`in t&&t.type===`ArrayPattern`&&`elements`in t?$e(t.elements):null}function tt(e){if(!M(e)||e.declarations.length===0)return null;let t=e.declarations[0];if(!t||typeof t!=`object`||!t||!(`id`in t)||!t.id)return null;let n=t.id;if(typeof n==`object`&&`type`in n){let e=n;if(e.type===`Identifier`&&`name`in e)return typeof e.name==`string`?e.name:null;if(e.type===`ObjectPattern`||e.type===`ArrayPattern`)return et(n)}return A(t)?t.id?.name??null:null}function N(e){if(!e||typeof e!=`object`||!(`type`in e))return null;let t=e.type;if(typeof t!=`string`)return null;switch(t){case`FunctionDeclaration`:case`ClassDeclaration`:case`TSInterfaceDeclaration`:case`TSTypeAliasDeclaration`:case`TSEnumDeclaration`:case`TSEnumMember`:return A(e)?e.id?.name??null:null;case`MethodDefinition`:case`PropertyDefinition`:case`TSPropertySignature`:return j(e)?e.key?.name??null:null;case`VariableDeclaration`:return tt(e);default:return null}}const nt={FunctionDeclaration:`函数`,MethodDefinition:`方法`,ClassDeclaration:`类`,VariableDeclaration:`变量`,TSInterfaceDeclaration:`接口`,TSTypeAliasDeclaration:`类型别名`,TSEnumDeclaration:`枚举`,PropertyDefinition:`类属性`,TSPropertySignature:`接口属性`,TSEnumMember:`枚举成员`};function P(e){return nt[e]||e}function F(e){return ge.safeParse(e).success}function rt(e){return F(e)?e.typeParameters.params.map(e=>e.name&&typeof e.name==`object`&&`name`in e.name?String(e.name.name):``).filter(Boolean):[]}function it(e){return!e.trim().includes(`
|
|
12
12
|
`)}function at(e){return j(e)?e.key.name:A(e)?e.id.name:`(匿名)`}const ot=e({meta:{type:`suggestion`,docs:{description:`要求接口属性、类属性、枚举成员使用多行 TSDoc 注释格式`}},createOnce(e){return{TSPropertySignature(t){I(t,e)},PropertyDefinition(t){I(t,e)},TSEnumMember(t){I(t,e)}}}});function I(e,t){let n=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!n)return;let r=n.value;if(it(r)){let n=at(e);t.report({node:e,message:`"${n}"的注释应使用多行 TSDoc 格式,当前为单行格式`})}}const st=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求 @param 标签有描述`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(!i)continue;let a=p(i);for(let n of a)g(n)||e.report({node:t,message:`参数 "${n.name}" 缺少描述`,fix:t=>ke(t,r,n.name,S(e.sourceCode.text,r.range))})}}}}}),ct=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求函数参数有 @param 标签`}},createOnce(e){let t=[];function n(n){let r=b(t,n,e.sourceCode.text);if(!r)return;let i=O(n);if(i.length===0)return;let a=d(r.value);if(!a)return;let o=_(a),s=i.filter(e=>!o.includes(e));for(let t of s)e.report({node:n,message:`参数 "${t}" 缺少 @param 标签`,fix:n=>{let i=S(e.sourceCode.text,r.range);return Te(n,r,t,i)}})}return{Program(){t=e.sourceCode.getAllComments()},FunctionDeclaration(e){n(e)},FunctionExpression(e){n(e)},ArrowFunctionExpression(e){if(`parent`in e&&e.parent){let t=e.parent.type;if(t===`CallExpression`||t===`Property`)return}n(e)}}}}),lt=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求 @returns 标签有描述`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Block`)continue;let n=r.value;if(!n.startsWith(`*`))continue;let i=d(n);if(!i)continue;let a=m(i);a&&!g(a)&&e.report({node:t,message:`@returns 标签缺少描述`,fix:t=>Ae(t,r,S(e.sourceCode.text,r.range))})}}}}});function L(e){return typeof e!=`object`||!e||!(`type`in e)?!1:typeof e.type==`string`}function ut(e){return L(e)&&e.type===`ReturnStatement`&&`argument`in e}function dt(e){return typeof e==`object`&&!!e&&`body`in e}function ft(e){return typeof e==`object`&&!!e&&`returnType`in e}function pt(e){return L(e)?[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`].includes(e.type):!1}function R(e,t){if(!e||typeof e!=`object`)return!1;let n=e;if(t.has(n))return!1;if(t.add(n),ut(n))return!0;if(pt(n))return!1;for(let e of Object.keys(n)){let r=Object.getOwnPropertyDescriptor(n,e);if(!r||!(`value`in r))continue;let i=r.value;if(i&&typeof i==`object`){if(Array.isArray(i)){for(let e of i)if(R(e,t))return!0}else if(`type`in i&&R(i,t))return!0}}return!1}function z(e){if(typeof e!=`object`||!e||!dt(e)||!e.body)return!1;let t=e.body;return typeof t!=`object`||!t?!1:!(`type`in t)||t.type!==`BlockStatement`||R(t,/* @__PURE__ */ new WeakSet)}function B(e){if(typeof e!=`object`||!e||!ft(e)||!e.returnType)return!1;let t=e.returnType;if(!t||typeof t!=`object`||!(`typeAnnotation`in t)||!t.typeAnnotation)return!1;let n=t.typeAnnotation;if(typeof n!=`object`||!(`type`in n))return!1;if(n.type===`TSVoidKeyword`)return!0;if(n.type===`TSTypeReference`){let e=`typeName`in n?n.typeName:null;if(e&&typeof e==`object`&&`name`in e&&e.name===`Promise`){let e=`typeArguments`in n?n.typeArguments:null;if(e&&typeof e==`object`&&`params`in e&&Array.isArray(e.params)&&e.params.length>0){let t=e.params[0];if(L(t))return t.type===`TSVoidKeyword`}}}return!1}function mt(e){return z(e)?!B(e):!1}const ht=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求有返回值的函数有 @returns 标签`}},createOnce(e){return{FunctionDeclaration(t){V(t,e)},FunctionExpression(t){V(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}V(t,e)}}}});function V(e,t){if(!mt(e))return;let n=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!n)return;let r=d(n.value);r&&(m(r)||t.report({node:e,message:`缺少 @returns 文档`,fix:e=>{let r=S(t.sourceCode.text,n.range);return Ee(e,n,r)}}))}function gt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&`range`in t&&Array.isArray(t.range)}const _t=e({meta:{type:`suggestion`,docs:{description:`要求 @throws 标签有异常类型`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let t of n){if(t.type!==`Block`)continue;let n=t.value;if(!n.startsWith(`*`))continue;let r=d(n);if(!r)continue;let i=r.tags.filter(e=>e.tag===`throws`||e.tag===`throw`);for(let n of i)!n.type&>(t)&&e.report({node:t,message:`@throws 标签应使用 {@link Type} 格式声明异常类型,例如:@throws {@link Error} 描述`})}}}}});function H(e){if(typeof e!=`object`||!e)return!1;let t=e;return`body`in t&&Array.isArray(t.body)}function vt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`ThrowStatement`&&`argument`in t}function yt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`NewExpression`&&`callee`in t}function U(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`Identifier`&&`name`in t}function bt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`consequent`in t&&`alternate`in t}function xt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`block`in t&&`handler`in t}function St(e){return typeof e!=`object`||!e?!1:`cases`in e}function Ct(e){if(typeof e!=`object`||!e||!(`consequent`in e))return!1;let t=e;return Array.isArray(t.consequent)}function wt(e){let t=e.argument;if(yt(t)){let e=t.callee;if(U(e))return e.name}return U(t)?t.name:`Error`}function W(e,t){if(!H(e))return;let n=e;if(Array.isArray(n.body))for(let e of n.body)G(e,t)}function G(e,t){if(!e||typeof e!=`object`)return;let n=e;if(`type`in n&&n.type===`ThrowStatement`&&vt(n)){let e=wt(n);t.push({typeName:e});return}if(`type`in n&&n.type===`IfStatement`&&bt(n)){G(n.consequent,t),n.alternate&&G(n.alternate,t);return}if(`type`in n&&n.type===`TryStatement`&&xt(n)){Tt(n,t);return}if(`type`in n&&n.type===`SwitchStatement`&&St(n)){Et(n,t);return}`type`in n&&n.type===`BlockStatement`&&H(n)&&W(n,t)}function Tt(e,t){H(e.block)&&W(e.block,t),e.handler&&typeof e.handler==`object`&&`body`in e.handler&&e.handler.body&&H(e.handler.body)&&W(e.handler.body,t)}function Et(e,t){for(let n of e.cases)if(Ct(n))for(let e of n.consequent)G(e,t)}function Dt(e){if(!e||typeof e!=`object`||!(`body`in e)||!e.body)return[];let t=e.body;if(typeof t!=`object`||!t||!(`type`in t)||t.type!==`BlockStatement`)return[];let n=[];return W(t,n),n}const Ot=e({meta:{type:`suggestion`,docs:{description:`要求抛出异常的函数有 @throws 标签`}},createOnce(e){return{FunctionDeclaration(t){K(t,e)},FunctionExpression(t){K(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}K(t,e)}}}});function K(e,t){let n=Dt(e);if(n.length===0)return;let r=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!r){q(e,t,n);return}let i=d(r.value);if(!i){q(e,t,n);return}i.tags.filter(e=>e.tag===`throws`||e.tag===`throw`).length===0&&q(e,t,n)}function q(e,t,n){let r=[...new Set(n.map(e=>e.typeName))],i=r[0]||`Error`;t.report({node:e,message:`函数抛出异常但没有 @throws 标签。抛出的异常类型: ${r.join(`, `)}。正确用法: @throws {@link ${i}} 异常描述`})}function kt(e){return le.safeParse(e).success}function At(e){return ce.safeParse(e).success}function jt(e){return oe.safeParse(e).success}function Mt(e){return se.safeParse(e).success}function Nt(e){return ve.safeParse(e).success}function Pt(e){return ye.safeParse(e).success}function Ft(e,t){return e.type===`FunctionDeclaration`||e.type===`FunctionExpression`||e.type===`ArrowFunctionExpression`?It(e,t):e.type===`MethodDefinition`&&Nt(e)&&e.value?Lt(e.value,t):e.type===`ClassDeclaration`?Rt(t):e.type===`VariableDeclaration`&&Pt(e)?zt(e.declarations,t):J(t)}function It(e,t){let n=O(e),r=z(e),i=B(e),a=[];a.push(`/**`),a.push(` * ${x.functionDescription}`);for(let e of n)a.push(` * @param ${e} - ${x.paramDescription}`);return r&&!i&&a.push(` * @returns ${x.returnsDescription}`),a.push(` */`),`\n${t}`+a.join(`\n${t}`)+`\n${t}`}function Lt(e,t){if(!e||typeof e!=`object`||!kt(e))return J(t);let n=e,r=O(n),i=z(n),a=B(n),o=[];o.push(`/**`),o.push(` * ${x.methodDescription}`);for(let e of r)o.push(` * @param ${e} - ${x.paramDescription}`);return i&&!a&&o.push(` * @returns ${x.returnsDescription}`),o.push(` */`),`\n${t}`+o.join(`\n${t}`)+`\n${t}`}function Rt(e){let t=[];return t.push(`/**`),t.push(` * ${x.classDescription}`),t.push(` */`),`\n${e}`+t.join(`\n${e}`)+`\n${e}`}function zt(e,t){let n=e[0];if(!n||!At(n))return J(t);let r=jt(n)?n.init:void 0;if(r&&typeof r==`object`&&Mt(r)){let e=r.type;if(e===`ArrowFunctionExpression`||e===`FunctionExpression`)return J(t)}let i=[];return i.push(`/**`),i.push(` * ${x.variableDescription}`),i.push(` */`),`\n${t}`+i.join(`\n${t}`)+`\n${t}`}function J(e){let t=[];return t.push(`/**`),t.push(` * ${x.description}`),t.push(` */`),`\n${e}`+t.join(`\n${e}`)+`\n${e}`}function Y(e){return typeof e==`object`&&!!e&&`type`in e&&typeof e.type==`string`}function X(e){return typeof e==`object`&&!!e&&`parent`in e}function Bt(e){return typeof e==`object`&&!!e&&`init`in e}function Z(e){return typeof e==`object`&&!!e}const Vt=[`FunctionDeclaration`,`MethodDefinition`,`ClassDeclaration`,`VariableDeclaration`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSEnumMember`];function Ht(e){if(!Z(e)||e.type!==`TSPropertySignature`)return!1;let t=e.key;return Z(t)&&t.type===`Identifier`&&`name`in t&&typeof t.name==`string`?t.name===`null`||t.name===`undefined`:!1}function Ut(e,t){if(X(e)&&e.parent&&typeof e.parent==`object`&&Y(e.parent)&&[`ForStatement`,`ForInStatement`,`ForOfStatement`].includes(e.parent.type))return!0;if(e.type===`VariableDeclaration`){if(t)return!1;if(M(e)&&e.declarations.length>0){let t=e.declarations[0];if(!t)return!0;if(Bt(t)&&t.init&&typeof t.init==`object`&&Y(t.init)&&(t.init.type===`ArrowFunctionExpression`||t.init.type===`FunctionExpression`))return!1}return!0}return!!Ht(e)}function Wt(e){return e.includes(`/**`)}function Gt(e){if(`decorators`in e&&Array.isArray(e.decorators)&&e.decorators.length>0){let t=e.decorators[0];if(Z(t)){let e=t.range;if(Array.isArray(e)&&e.length>=1&&typeof e[0]==`number`)return[e[0],e[0]]}}if(X(e)&&e.parent&&typeof e.parent==`object`){let t=e.parent;if(Y(t)&&Z(t)&&[`ExportNamedDeclaration`,`ExportDefaultDeclaration`].includes(t.type)){let e=t.range;if(Array.isArray(e)&&e.length>=1&&typeof e[0]==`number`)return[e[0],e[0]]}}return[e.range[0],e.range[0]]}function Kt(e,t){if(!e)return``;let n=t;for(;n>0&&e[n-1]!==`
|
|
13
|
-
`;)n--;return e.slice(n,t)}function qt(e,t,n){if(t.skipFile||Ut(e,t.checkAllVariables))return;let r=b(t.commentsCache,e,n.sourceCode.text);if(!r){let t=P(e.type),r=N(e);n.report({node:e,message:`${t}"${r}"缺少 TSDoc 注释`,fix:t=>{let r=Gt(e),i=Ft(e,Kt(n.sourceCode.text,r[0]));return t.insertTextBeforeRange(r,i)}});return}let i=r.value;if(we(i)){let t=P(e.type),r=N(e);n.report({node:e,message:`${t}"${r}"的 TSDoc 注释包含占位描述,请填写实际描述`})}}function Jt(e,t){let n=e.getAllComments(),r=e.text;if(r!=null){if(!Wt(r))return t.skipFile=!0,n}else if(!n.some(e=>e.type===`Block`&&e.value.startsWith(`*`)))return t.skipFile=!0,n;return n}function Yt(e){if(typeof e==`object`&&e&&!Array.isArray(e)){let t=e;if(`checkAllVariables`in t&&typeof t.checkAllVariables==`boolean`)return t.checkAllVariables}return!1}const Xt=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求 TSDoc 注释存在`},schema:[{type:`object`,properties:{contexts:{type:`array`,items:{type:`string`}},checkAllVariables:{type:`boolean`}},additionalProperties:!1}]},createOnce(e){let t={commentsCache:[],checkAllVariables:!1,skipFile:!1},n={Program(n){t.skipFile=!1,t.checkAllVariables=!1,t.commentsCache=Jt(e.sourceCode,t);let r=e.options?.[0];t.checkAllVariables=Yt(r)}};for(let r of Vt)n[r]=n=>qt(n,t,e);return n}});function Zt(e){return e.tags.filter(e=>e.tag===`typeParam`||e.tag===`template`).map(e=>e.name)}const Qt=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求泛型有 @typeParam 标签`}},createOnce(e){return{FunctionDeclaration(t){Q(t,e)},FunctionExpression(t){Q(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}Q(t,e)},ClassDeclaration(t){Q(t,e)},TSInterfaceDeclaration(t){Q(t,e)},TSTypeAliasDeclaration(t){Q(t,e)}}}});function Q(e,t){if(!F(e))return;let n=rt(e);if(n.length===0)return;let r=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!r)return;let i=d(r.value);if(!i)return;let a=Zt(i),o=n.filter(e=>!a.includes(e));for(let n of o)t.report({node:e,message:`缺少类型参数 "${n}" 的 @typeParam 文档`,fix:e=>{let i=S(t.sourceCode.text,r.range);return De(e,r,n,i)}})}const $t=/^(=+)\s+(.+?)\s+(=+)$/;function en(e){let t=e.trim().match($t);return t?{leadingEquals:t[1]??``,text:t[2]??``,trailingEquals:t[3]??``}:null}const tn=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求代码块分隔符使用规范格式`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Line`)continue;let n=en(r.value.trim());if(n&&(n.leadingEquals.length!==20||n.trailingEquals.length!==20)){let i=`=`.repeat(20);e.report({node:t,message:`代码块分隔符格式不正确,应为:// ${i} ${n.text} ${i}`,fix:e=>{let t=`// ${i} ${n.text} ${i}`;return e.replaceTextRange(r.range,t)}})}}}}}}),nn=/\bTODO(?:\(([^)]+)\))?:?\s*(.*)/i;function rn(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const an={requireAuthor:!1,requireDescription:!0};function on(e){return/\bTODO\b/i.test(e)}function sn(e){let t={...an};if(rn(e)){let n=e;typeof n.requireAuthor==`boolean`&&(t.requireAuthor=n.requireAuthor),typeof n.requireDescription==`boolean`&&(t.requireDescription=n.requireDescription)}return t}function cn(e){let t=e.match(nn);return t?{author:t[1]??``,description:(t[2]??``).trim()}:null}const ln={"no-commented-code":s,"no-description-tag":ae,"no-extra-param":Pe,"no-legacy-jsdoc-tags":Re,"no-placeholder-description":He,"param-hyphen-format":We,"require-blank-line-before-tags":Ke,"require-deprecated-alternative":Ye,"require-description":Ze,"require-multiline-property-comment":ot,"require-param":ct,"require-param-description":st,"require-returns":ht,"require-returns-description":lt,"require-throws":Ot,"require-throws-type":_t,"require-tsdoc":Xt,"require-type-param":Qt,"separator-format":tn,"todo-format":e({meta:{type:`suggestion`,docs:{description:`要求 TODO 注释有描述和作者`}},createOnce(e){let t=sn(e.options?.[0]);return{Program(n){let r=e.sourceCode.getAllComments();for(let i of r){let r=i.value;if(!on(r))continue;let a=cn(r);a&&(t.requireAuthor&&!a.author&&e.report({node:n,message:`TODO 注释缺少作者信息,格式:TODO(author): 描述`}),t.requireDescription&&!a.description&&e.report({node:n,message:`TODO 注释缺少描述说明`}))}}}}})},$=t({meta:{name:`@longzai-intelligence-oxlint/tsdoc-plugin`},rules:ln});export{$ as default,$ as tsdocPlugin,ln as tsdocRules};
|
|
13
|
+
`;)n--;return e.slice(n,t)}function qt(e,t,n){if(t.skipFile||Ut(e,t.checkAllVariables))return;let r=b(t.commentsCache,e,n.sourceCode.text);if(!r){let t=P(e.type),r=N(e);n.report({node:e,message:`${t}"${r}"缺少 TSDoc 注释`,fix:t=>{let r=Gt(e),i=Ft(e,Kt(n.sourceCode.text,r[0]));return t.insertTextBeforeRange(r,i)}});return}let i=r.value;if(we(i)){let t=P(e.type),r=N(e);n.report({node:e,message:`${t}"${r}"的 TSDoc 注释包含占位描述,请填写实际描述`})}}function Jt(e,t){let n=e.getAllComments(),r=e.text;if(r!=null){if(!Wt(r))return t.skipFile=!0,n}else if(!n.some(e=>e.type===`Block`&&e.value.startsWith(`*`)))return t.skipFile=!0,n;return n}function Yt(e){if(typeof e==`object`&&e&&!Array.isArray(e)){let t=e;if(`checkAllVariables`in t&&typeof t.checkAllVariables==`boolean`)return t.checkAllVariables}return!1}const Xt=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求 TSDoc 注释存在`},schema:[{type:`object`,properties:{contexts:{type:`array`,items:{type:`string`}},checkAllVariables:{type:`boolean`}},additionalProperties:!1}]},createOnce(e){let t={commentsCache:[],checkAllVariables:!1,skipFile:!1},n={Program(n){t.skipFile=!1,t.checkAllVariables=!1,t.commentsCache=Jt(e.sourceCode,t);let r=e.options?.[0];t.checkAllVariables=Yt(r)}};for(let r of Vt)n[r]=n=>qt(n,t,e);return n}});function Zt(e){return e.tags.filter(e=>e.tag===`typeParam`||e.tag===`template`).map(e=>e.name)}const Qt=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求泛型有 @typeParam 标签`}},createOnce(e){return{FunctionDeclaration(t){Q(t,e)},FunctionExpression(t){Q(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}Q(t,e)},ClassDeclaration(t){Q(t,e)},TSInterfaceDeclaration(t){Q(t,e)},TSTypeAliasDeclaration(t){Q(t,e)}}}});function Q(e,t){if(!F(e))return;let n=rt(e);if(n.length===0)return;let r=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!r)return;let i=d(r.value);if(!i)return;let a=Zt(i),o=n.filter(e=>!a.includes(e));for(let n of o)t.report({node:e,message:`缺少类型参数 "${n}" 的 @typeParam 文档`,fix:e=>{let i=S(t.sourceCode.text,r.range);return De(e,r,n,i)}})}const $t=/^(=+)\s+(.+?)\s+(=+)$/;function en(e){let t=e.trim().match($t);return t?{leadingEquals:t[1]??``,text:t[2]??``,trailingEquals:t[3]??``}:null}const tn=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求代码块分隔符使用规范格式`}},createOnce(e){return{Program(t){let n=e.sourceCode.getAllComments();for(let r of n){if(r.type!==`Line`)continue;let n=en(r.value.trim());if(n&&(n.leadingEquals.length!==20||n.trailingEquals.length!==20)){let i=`=`.repeat(20);e.report({node:t,message:`代码块分隔符格式不正确,应为:// ${i} ${n.text} ${i}`,fix:e=>{let t=`// ${i} ${n.text} ${i}`;return e.replaceTextRange(r.range,t)}})}}}}}}),nn=/\bTODO(?:\(([^)]+)\))?:?\s*(.*)/i;function rn(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const an={requireAuthor:!1,requireDescription:!0};function on(e){return/\bTODO\b/i.test(e)}function sn(e){let t={...an};if(rn(e)){let n=e;typeof n.requireAuthor==`boolean`&&(t.requireAuthor=n.requireAuthor),typeof n.requireDescription==`boolean`&&(t.requireDescription=n.requireDescription)}return t}function cn(e){let t=e.match(nn);return t?{author:t[1]??``,description:(t[2]??``).trim()}:null}const ln={"no-commented-code":s,"no-description-tag":ae,"no-extra-param":Pe,"no-legacy-jsdoc-tags":Re,"no-placeholder-description":He,"param-hyphen-format":We,"require-blank-line-before-tags":Ke,"require-deprecated-alternative":Ye,"require-description":Ze,"require-multiline-property-comment":ot,"require-param":ct,"require-param-description":st,"require-returns":ht,"require-returns-description":lt,"require-throws":Ot,"require-throws-type":_t,"require-tsdoc":Xt,"require-type-param":Qt,"separator-format":tn,"todo-format":e({meta:{type:`suggestion`,docs:{description:`要求 TODO 注释有描述和作者`}},createOnce(e){let t=sn(e.options?.[0]);return{Program(n){let r=e.sourceCode.getAllComments();for(let i of r){let r=i.value;if(!on(r))continue;let a=cn(r);a&&(t.requireAuthor&&!a.author&&e.report({node:n,message:`TODO 注释缺少作者信息,格式:TODO(author): 描述`}),t.requireDescription&&!a.description&&e.report({node:n,message:`TODO 注释缺少描述说明`}))}}}}})},$=t({meta:{name:`@longzai-intelligence-oxlint/tsdoc-plugin`},rules:ln});export{$t as SEPARATOR_PATTERN,$ as default,$ as tsdocPlugin,en as parseSeparatorComment,ln as tsdocRules};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@longzai-intelligence-oxlint/tsdoc-plugin",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.29",
|
|
4
4
|
"description": "Longzai Intelligence oxlint TSDoc 规则插件",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"comments",
|
|
@@ -44,7 +44,7 @@
|
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
46
|
"@longzai-intelligence-logger/node": "^0.1.1",
|
|
47
|
-
"@longzai-intelligence-oxlint/core": "0.1.
|
|
47
|
+
"@longzai-intelligence-oxlint/core": "0.1.29",
|
|
48
48
|
"@oxlint/plugins": "^1.74.0",
|
|
49
49
|
"zod": "^4.4.3"
|
|
50
50
|
},
|