@longzai-intelligence-oxlint/tsdoc-plugin 0.1.8 → 0.1.10
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.js +8 -10
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3,14 +3,12 @@ import{defineRule as e,eslintCompatPlugin as t}from"@oxlint/plugins";import*as n
|
|
|
3
3
|
`),r=[],i=[],a=null,o=!0;for(let e=0;e<n.length;e++){let t=n[e];if(t)if(t=t.trim(),t.startsWith(`*`)&&(t=t.slice(1).trim()),t.startsWith(`@`)){o=!1,a&&i.push(a);let e=t.match(/^@(\w+)\s*(.*)/);if(e){let t=e[1];if(!t)continue;a=ne(t,e[2]??``)}}else o?(t||r.length>0)&&r.push(t):a&&(a.description+=(a.description?`
|
|
4
4
|
`:``)+t)}return a&&i.push(a),{description:r.join(`
|
|
5
5
|
`).trim(),tags:i}}function f(e){return e.tags.filter(e=>e.tag===`param`)}function p(e){return e.tags.find(e=>e.tag===`returns`||e.tag===`return`)}function m(e){return e.description.trim().length>0}function h(e){let t=e.description.trim();return!(t.length===0||t===`-`||t===`--`)}function g(e){return f(e).map(e=>e.name.split(`.`)[0]).filter(e=>typeof e==`string`)}const ae=e({meta:{type:`suggestion`,docs:{description:`禁止使用 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.some(e=>e.tag===`description`)&&e.report({node:t,message:`请勿使用 description 标签,直接书写描述文本即可`})}}}}});n.object({type:n.string(),range:n.tuple([n.number(),n.number()])});const oe=n.object({init:n.unknown()}),se=n.object({type:n.string()});n.object({name:n.unknown()}),n.object({left:n.unknown(),right:n.unknown()}),n.object({id:n.object({name:n.string()})}),n.object({key:n.object({name:n.string()})}),n.object({declarations:n.array(n.object({id:n.optional(n.object({name:n.optional(n.string())}))}))}),n.object({type:n.literal(`ThrowStatement`),argument:n.unknown()}),n.object({type:n.literal(`NewExpression`),callee:n.unknown()}),n.object({type:n.literal(`Identifier`),name:n.unknown()}),n.object({consequent:n.array(n.unknown())}),n.object({consequent:n.unknown(),alternate:n.unknown()}),n.object({block:n.unknown(),handler:n.unknown()}),n.object({cases:n.unknown()}),n.object({body:n.array(n.unknown())});const ce=n.record(n.string(),n.unknown()),le=n.object({type:n.enum([`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`])});n.object({type:n.string(),params:n.array(n.unknown())});const ue=n.object({range:n.tuple([n.number(),n.number()])}),de=n.object({range:n.tuple([n.number(),n.number()])}),fe=n.object({range:n.tuple([n.number(),n.number()])}),pe=n.object({id:n.object({name:n.string()})}),me=n.object({key:n.object({name:n.string()})}),he=n.object({declarations:n.array(n.unknown())}),ge=n.object({typeParameters:n.object({params:n.array(n.record(n.string(),n.unknown()))})}),_e=n.object({params:n.array(n.unknown())}),ve=n.object({value:n.unknown()}),ye=n.object({declarations:n.array(n.unknown())});function _(e){return ue.safeParse(e).success}function be(e){return de.safeParse(e).success}function v(e){return fe.safeParse(e).success}function y(e){if(!_(e))return-1;if(`decorators`in e&&Array.isArray(e.decorators)&&e.decorators.length>0){let t=e.decorators[0];if(v(t))return t.range[0]}if(`parent`in e&&e.parent&&typeof e.parent==`object`){let t=e.parent;if(_(t)&&`type`in t&&typeof t.type==`string`){if(t.type===`MethodDefinition`){if(`decorators`in t&&Array.isArray(t.decorators)&&t.decorators.length>0){let e=t.decorators[0];if(v(e))return e.range[0]}return t.range[0]}if(t.type===`Property`)return t.range[0];if(t.type===`VariableDeclarator`){let e=`parent`in t?t.parent:void 0;if(_(e)&&`type`in e&&typeof e.type==`string`&&e.type===`VariableDeclaration`){if(`parent`in e&&e.parent){let t=e.parent;if(_(t)&&`type`in t&&typeof t.type==`string`&&[`ExportNamedDeclaration`,`ExportDefaultDeclaration`].includes(t.type))return t.range[0]}return e.range[0]}}if([`ExportNamedDeclaration`,`ExportDefaultDeclaration`].includes(t.type))return t.range[0]}}return e.range[0]}function xe(e,t,n,r){let i=e.range[1],a=y(t);if(a<0)return!1;let o=n.filter(e=>e.range[0]>=i&&e.range[1]<=a),s=[];if(_(t)&&`decorators`in t){let e=t.decorators;if(Array.isArray(e))for(let t of e)v(t)&&s.push(t.range)}let c=[...o.map(e=>e.range),...s].sort((e,t)=>e[0]-t[0]),l=[],u=i;for(let e of c)e[0]>u&&l.push(r.slice(u,e[0])),u=Math.max(u,e[1]);u<a&&l.push(r.slice(u,a));for(let e of l)if(e.trim().length>0)return!1;return!0}function b(e,t,n){if(!be(t))return null;let r=y(t),i=r>=0?r:t.range[0],a=null;for(let t of e)t.type===`Block`&&t.value.startsWith(`*`)&&t.range[1]<=i&&(a===null||t.range[1]>a.range[1])&&(a={value:t.value,range:t.range});return a&&n&&!xe(a,t,e,n)?null:a}const x={description:`[待填写描述]`,functionDescription:`[待填写函数描述]`,methodDescription:`[待填写方法描述]`,classDescription:`[待填写类描述]`,variableDescription:`[待填写变量描述]`,paramDescription:`[待填写参数描述]`,returnsDescription:`[待填写返回值描述]`,typeParamDescription:`[待填写类型参数描述]`},Se=[/^\s*\*\s*描述\s*$/m,/^\s*\*\s*函数描述\s*$/m,/^\s*\*\s*方法描述\s*$/m,/^\s*\*\s*类描述\s*$/m,/^\s*\*\s*变量描述\s*$/m,/@param\s+\w+\s*-\s*参数描述/,/@returns\s+返回值描述/,/@typeParam\s+\w+\s*-\s*类型参数描述/];function Ce(e){return Object.values(x).some(t=>e.includes(t))?!0:Se.some(t=>t.test(e))}function S(e,t){let n=t[0];for(;n>0&&e[n-1]!==`
|
|
6
|
-
`;)n--;return e.slice(n,t[0])}function we(e,t,n,r){let i=`\n${r} * @param ${n} - ${x.paramDescription}`,a=t.value.match(/@param[^@]*$/);if(a&&a.index!==void 0){let n=t.range[0]+2+a.index+a[0].length;return e.insertTextAfterRange([t.range[0],n],i)}
|
|
7
|
-
|
|
8
|
-
`)?``:`
|
|
9
|
-
`}function Oe(e,t,n){let r=t.value,i=RegExp(`@param\\s+${w(n)}\\s*$`,`m`),a=i.exec(r);if(a){let o=C(r,a.index+a[0].length),s=r.replace(i,`@param ${n} - ${x.paramDescription}${o}`);return e.replaceTextRange(t.range,`/*${s}*/`)}return e.replaceTextRange(t.range,`/*${r}*/`)}function ke(e,t){let n=t.value,r=/@returns\s*$/m,i=r.exec(n);if(i){let a=C(n,i.index+i[0].length),o=n.replace(r,`@returns ${x.returnsDescription}${a}`);return e.replaceTextRange(t.range,`/*${o}*/`)}return e.replaceTextRange(t.range,`/*${n}*/`)}function w(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const T=n.object({name:n.optional(n.string())}),Ae=n.object({type:n.string(),name:n.optional(n.string()),left:n.optional(T),argument:n.optional(T),parameter:n.optional(T)});function je(e){return _e.safeParse(e).success}function E(e){return je(e)?e.params.map(e=>{let t=Ae.safeParse(e);if(!t.success)return``;let n=t.data;switch(n.type){case`Identifier`:return n.name??``;case`AssignmentPattern`:return n.left?.name??``;case`RestElement`:return n.argument?.name??``;case`ObjectPattern`:return Me(n)??`options`;case`ArrayPattern`:return`args`;case`TSParameterProperty`:return n.parameter?.name??``;default:return``}}).filter(e=>!!e):[]}function Me(e){return null}const Ne=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=d(r.value);if(!i)return;let a=E(n),o=g(i).filter(e=>!a.includes(e));for(let t of o)e.report({node:n,message:`@param "${t}" 在函数签名中不存在`,fix:e=>{let n=r.value,i=RegExp(`\\n\\s*\\*\\s*@param\\s+${w(t)}\\b[^\\n]*`),a=n.replace(i,``);return e.replaceTextRange(r.range,`/*${a}*/`)}})}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)}}}}),Pe=[`file`,`module`,`author`,`since`];function Fe(e){return Pe.includes(e)}function Ie(e,t,n,r){let i=e.split(`
|
|
6
|
+
`;)n--;return e.slice(n,t[0])}function C(e,t,n,r){let i=t.range[1]-2,a=t.range[0]+2+t.value.replace(/\s+$/,``).length,o=`${n}\n${r} `;return e.replaceTextRange([a,i],o)}function we(e,t,n,r){let i=`\n${r} * @param ${n} - ${x.paramDescription}`,a=t.value.match(/@param[^@]*$/);if(a&&a.index!==void 0){let n=t.range[0]+2+a.index+a[0].length;return e.insertTextAfterRange([t.range[0],n],i)}return C(e,t,i,r)}function Te(e,t,n){let r=`\n${n} * @returns ${x.returnsDescription}`,i=t.value.match(/@\w+[^@]*$/);if(i&&i.index!==void 0){let n=t.range[0]+2+i.index+i[0].length;return e.insertTextAfterRange([t.range[0],n],r)}return C(e,t,r,n)}function Ee(e,t,n,r){let i=`\n${r} * @typeParam ${n} - ${x.typeParamDescription}`,a=t.value,o=a.match(/@typeParam[^@]*$/);if(o&&o.index!==void 0){let n=t.range[0]+2+o.index+o[0].length;return e.insertTextAfterRange([t.range[0],n],i)}let s=a.match(/@param[^@]*$/);if(s&&s.index!==void 0){let n=t.range[0]+2+s.index+s[0].length;return e.insertTextAfterRange([t.range[0],n],i)}return C(e,t,i,r)}function De(e,t,n){let r=t.value;return r.trim()===`*`?e.replaceTextRange(t.range,`/**\n${n} * ${x.description}\n${n} */`):e.replaceTextRange(t.range,`/*${r}*/`)}function w(e,t,n){return e.slice(t).includes(`
|
|
7
|
+
`)?``:`\n${n} `}function Oe(e,t,n,r){let i=t.value,a=RegExp(`@param\\s+${T(n)}\\s*$`,`m`),o=a.exec(i);if(o){let s=w(i,o.index+o[0].length,r),c=i.replace(a,`@param ${n} - ${x.paramDescription}${s}`);return e.replaceTextRange(t.range,`/*${c}*/`)}return e.replaceTextRange(t.range,`/*${i}*/`)}function ke(e,t,n){let r=t.value,i=/@returns\s*$/m,a=i.exec(r);if(a){let o=w(r,a.index+a[0].length,n),s=r.replace(i,`@returns ${x.returnsDescription}${o}`);return e.replaceTextRange(t.range,`/*${s}*/`)}return e.replaceTextRange(t.range,`/*${r}*/`)}function T(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const E=n.object({name:n.optional(n.string())}),Ae=n.object({type:n.string(),name:n.optional(n.string()),left:n.optional(E),argument:n.optional(E),parameter:n.optional(E)});function je(e){return _e.safeParse(e).success}function D(e){return je(e)?e.params.map(e=>{let t=Ae.safeParse(e);if(!t.success)return``;let n=t.data;switch(n.type){case`Identifier`:return n.name??``;case`AssignmentPattern`:return n.left?.name??``;case`RestElement`:return n.argument?.name??``;case`ObjectPattern`:return Me(n)??`options`;case`ArrayPattern`:return`args`;case`TSParameterProperty`:return n.parameter?.name??``;default:return``}}).filter(e=>!!e):[]}function Me(e){return null}const Ne=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=d(r.value);if(!i)return;let a=D(n),o=g(i).filter(e=>!a.includes(e));for(let t of o)e.report({node:n,message:`@param "${t}" 在函数签名中不存在`,fix:e=>{let n=r.value,i=RegExp(`\\n\\s*\\*\\s*@param\\s+${T(t)}\\b[^\\n]*`),a=n.replace(i,``);return e.replaceTextRange(r.range,`/*${a}*/`)}})}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)}}}}),Pe=[`file`,`module`,`author`,`since`];function Fe(e){return Pe.includes(e)}function Ie(e,t,n,r){let i=e.split(`
|
|
10
8
|
`),a=-1;for(let e=0;e<i.length;e++){let n=i[e];if(n&&n.trim().startsWith(`* @${t}`)){a=e;break}}if(a===-1)return n.replaceTextRange(r,`/*${e}*/`);let o=i.filter((e,t)=>t!==a).join(`
|
|
11
|
-
`);return n.replaceTextRange(r,`/*${o}*/`)}const Le=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)Fe(a.tag)&&e.report({node:t,message:`禁止使用旧版 JSDoc 标签 @${a.tag},该标签在 TSDoc 中已不推荐使用`,fix:e=>Ie(n,a.tag,e,r.range)})}}}}}),Re=[...Object.values(x),`参数描述`,`返回值描述`,`函数描述`,`方法描述`,`类描述`,`变量描述`,`类型参数描述`,`描述`];function
|
|
12
|
-
`),n=-1;for(let e=0;e<t.length;e++){let r=t[e];if(!r)continue;let i=r.trim();if(i.startsWith(`*`)&&i.slice(1).trim().startsWith(`@`)){n=e;break}}if(n===-1||n===0)return!0;let r=t[n-1];if(!r)return!0;let i=r.trim();return i===`*`||i===``}const Ge=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&&m(i)&&(We(n)||e.report({node:t,message:`标签前应有一个空行`,fix:e=>{let t=n.replace(/(\* [^\n@]+)\n(\s
|
|
13
|
-
|
|
14
|
-
$2`);return e.replaceTextRange(r.range,`/*${t}*/`)}}))}}}}}),Ke=[/使用\s+\S+\s+代替/,/请使用\s+\S+/,/use\s+\S+\s+instead/i,/replaced\s+by\s+\S+/i];function qe(e){if(!e)return!1;let t=e.trim();if(t.length===0)return!1;for(let e of Ke)if(e.test(t))return!0;return t.length>10}const Je=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&&(qe(a.description)||e.report({node:t,message:`@deprecated 标签应该包含替代方案说明,例如:@deprecated 使用 newMethod 代替`}))}}}}}),Ye=[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`,`ClassDeclaration`,`VariableDeclaration`,`MethodDefinition`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSPropertySignature`,`TSEnumMember`],Xe=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&&(m(i)||e.report({node:n,message:`TSDoc 注释缺少描述`,fix:t=>{let n=S(e.sourceCode.text,r.range);return De(t,r,n)}}))}let r={Program(){t=e.sourceCode.getAllComments()}};for(let e of Ye)r[e]=e=>n(e);return r}});function
|
|
15
|
-
`)}function it(e){return k(e)?e.key.name:O(e)?e.id.name:`(匿名)`}const at=e({meta:{type:`suggestion`,docs:{description:`要求接口属性、类属性、枚举成员使用多行 TSDoc 注释格式`}},createOnce(e){return{TSPropertySignature(t){P(t,e)},PropertyDefinition(t){P(t,e)},TSEnumMember(t){P(t,e)}}}});function P(e,t){let n=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!n)return;let r=n.value;if(rt(r)){let n=it(e);t.report({node:e,message:`"${n}"的注释应使用多行 TSDoc 格式,当前为单行格式`})}}const ot=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=f(i);for(let n of a)h(n)||e.report({node:t,message:`参数 "${n.name}" 缺少描述`,fix:e=>Oe(e,r,n.name)})}}}}}),st=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=E(n);if(i.length===0)return;let a=d(r.value);if(!a)return;let o=g(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 we(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)}}}}),ct=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=p(i);a&&!h(a)&&e.report({node:t,message:`@returns 标签缺少描述`,fix:e=>ke(e,r)})}}}}});function F(e){return typeof e!=`object`||!e||!(`type`in e)?!1:typeof e.type==`string`}function lt(e){return F(e)&&e.type===`ReturnStatement`&&`argument`in e}function ut(e){return typeof e==`object`&&!!e&&`body`in e}function dt(e){return typeof e==`object`&&!!e&&`returnType`in e}function ft(e){return F(e)?[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`].includes(e.type):!1}function I(e,t){if(!e||typeof e!=`object`)return!1;let n=e;if(t.has(n))return!1;if(t.add(n),lt(n))return!0;if(ft(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(I(e,t))return!0}else if(`type`in i&&I(i,t))return!0}}return!1}function L(e){if(typeof e!=`object`||!e||!ut(e)||!e.body)return!1;let t=e.body;return typeof t!=`object`||!t?!1:!(`type`in t)||t.type!==`BlockStatement`||I(t,new WeakSet)}function R(e){if(typeof e!=`object`||!e||!dt(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(F(t))return t.type===`TSVoidKeyword`}}}return!1}function pt(e){return L(e)?!R(e):!1}const mt=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求有返回值的函数有 @returns 标签`}},createOnce(e){return{FunctionDeclaration(t){z(t,e)},FunctionExpression(t){z(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}z(t,e)}}}});function z(e,t){if(!pt(e))return;let n=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!n)return;let r=d(n.value);r&&(p(r)||t.report({node:e,message:`缺少 @returns 文档`,fix:e=>{let r=S(t.sourceCode.text,n.range);return Te(e,n,r)}}))}function ht(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&`range`in t&&Array.isArray(t.range)}const gt=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&&ht(t)&&e.report({node:t,message:`@throws 标签应使用 {@link Type} 格式声明异常类型,例如:@throws {@link Error} 描述`})}}}}});function B(e){if(typeof e!=`object`||!e)return!1;let t=e;return`body`in t&&Array.isArray(t.body)}function _t(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`ThrowStatement`&&`argument`in t}function vt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`NewExpression`&&`callee`in t}function V(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`Identifier`&&`name`in t}function yt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`consequent`in t&&`alternate`in t}function bt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`block`in t&&`handler`in t}function xt(e){return typeof e!=`object`||!e?!1:`cases`in e}function St(e){if(typeof e!=`object`||!e||!(`consequent`in e))return!1;let t=e;return Array.isArray(t.consequent)}function Ct(e){let t=e.argument;if(vt(t)){let e=t.callee;if(V(e))return e.name}return V(t)?t.name:`Error`}function H(e,t){if(!B(e))return;let n=e;if(Array.isArray(n.body))for(let e of n.body)U(e,t)}function U(e,t){if(!e||typeof e!=`object`)return;let n=e;if(`type`in n&&n.type===`ThrowStatement`&&_t(n)){let e=Ct(n);t.push({typeName:e});return}if(`type`in n&&n.type===`IfStatement`&&yt(n)){U(n.consequent,t),n.alternate&&U(n.alternate,t);return}if(`type`in n&&n.type===`TryStatement`&&bt(n)){wt(n,t);return}if(`type`in n&&n.type===`SwitchStatement`&&xt(n)){Tt(n,t);return}`type`in n&&n.type===`BlockStatement`&&B(n)&&H(n,t)}function wt(e,t){B(e.block)&&H(e.block,t),e.handler&&typeof e.handler==`object`&&`body`in e.handler&&e.handler.body&&B(e.handler.body)&&H(e.handler.body,t)}function Tt(e,t){for(let n of e.cases)if(St(n))for(let e of n.consequent)U(e,t)}function Et(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 H(t,n),n}const Dt=e({meta:{type:`suggestion`,docs:{description:`要求抛出异常的函数有 @throws 标签`}},createOnce(e){return{FunctionDeclaration(t){W(t,e)},FunctionExpression(t){W(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}W(t,e)}}}});function W(e,t){let n=Et(e);if(n.length===0)return;let r=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!r){G(e,t,n);return}let i=d(r.value);if(!i){G(e,t,n);return}i.tags.filter(e=>e.tag===`throws`||e.tag===`throw`).length===0&&G(e,t,n)}function G(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 Ot(e){return le.safeParse(e).success}function kt(e){return ce.safeParse(e).success}function At(e){return oe.safeParse(e).success}function jt(e){return se.safeParse(e).success}function Mt(e){return ve.safeParse(e).success}function Nt(e){return ye.safeParse(e).success}function Pt(e,t){return e.type===`FunctionDeclaration`||e.type===`FunctionExpression`||e.type===`ArrowFunctionExpression`?Ft(e,t):e.type===`MethodDefinition`&&Mt(e)&&e.value?It(e.value,t):e.type===`ClassDeclaration`?Lt(t):e.type===`VariableDeclaration`&&Nt(e)?Rt(e.declarations,t):K(t)}function Ft(e,t){let n=E(e),r=L(e),i=R(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 It(e,t){if(!e||typeof e!=`object`||!Ot(e))return K(t);let n=e,r=E(n),i=L(n),a=R(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 Lt(e){let t=[];return t.push(`/**`),t.push(` * ${x.classDescription}`),t.push(` */`),`\n${e}`+t.join(`\n${e}`)+`\n${e}`}function Rt(e,t){let n=e[0];if(!n||!kt(n))return K(t);let r=At(n)?n.init:void 0;if(r&&typeof r==`object`&&jt(r)){let e=r.type;if(e===`ArrowFunctionExpression`||e===`FunctionExpression`)return K(t)}let i=[];return i.push(`/**`),i.push(` * ${x.variableDescription}`),i.push(` */`),`\n${t}`+i.join(`\n${t}`)+`\n${t}`}function K(e){let t=[];return t.push(`/**`),t.push(` * ${x.description}`),t.push(` */`),`\n${e}`+t.join(`\n${e}`)+`\n${e}`}function q(e){return typeof e==`object`&&!!e&&`type`in e&&typeof e.type==`string`}function J(e){return typeof e==`object`&&!!e&&`parent`in e}function zt(e){return typeof e==`object`&&!!e&&`init`in e}function Y(e){return typeof e==`object`&&!!e}const Bt=[`FunctionDeclaration`,`MethodDefinition`,`ClassDeclaration`,`VariableDeclaration`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSEnumMember`];function Vt(e){if(!Y(e)||e.type!==`TSPropertySignature`)return!1;let t=e.key;return Y(t)&&t.type===`Identifier`&&`name`in t&&typeof t.name==`string`?t.name===`null`||t.name===`undefined`:!1}function Ht(e,t){if(J(e)&&e.parent&&typeof e.parent==`object`&&q(e.parent)&&[`ForStatement`,`ForInStatement`,`ForOfStatement`].includes(e.parent.type))return!0;if(e.type===`VariableDeclaration`){if(t)return!1;if(A(e)&&e.declarations.length>0){let t=e.declarations[0];if(!t)return!0;if(zt(t)&&t.init&&typeof t.init==`object`&&q(t.init)&&(t.init.type===`ArrowFunctionExpression`||t.init.type===`FunctionExpression`))return!1}return!0}return!!Vt(e)}function Ut(e){return e.includes(`/**`)}function Wt(e){if(`decorators`in e&&Array.isArray(e.decorators)&&e.decorators.length>0){let t=e.decorators[0];if(Y(t)){let e=t.range;if(Array.isArray(e)&&e.length>=1&&typeof e[0]==`number`)return[e[0],e[0]]}}if(J(e)&&e.parent&&typeof e.parent==`object`){let t=e.parent;if(q(t)&&Y(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 Gt(e,t){if(!e)return``;let n=t;for(;n>0&&e[n-1]!==`
|
|
16
|
-
`;)n--;return e.slice(n,t)}function Kt(e,t,n){if(t.skipFile||Ht(e,t.checkAllVariables))return;let r=b(t.commentsCache,e,n.sourceCode.text);if(!r){let t=
|
|
9
|
+
`);return n.replaceTextRange(r,`/*${o}*/`)}const Le=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)Fe(a.tag)&&e.report({node:t,message:`禁止使用旧版 JSDoc 标签 @${a.tag},该标签在 TSDoc 中已不推荐使用`,fix:e=>Ie(n,a.tag,e,r.range)})}}}}}),Re=[...Object.values(x),`参数描述`,`返回值描述`,`函数描述`,`方法描述`,`类描述`,`变量描述`,`类型参数描述`,`描述`];function O(e){let t=e.trim();t.startsWith(`-`)&&(t=t.slice(1).trim());for(let e of Re)if(t===e)return e;return null}function ze(e){let t=O(e);return t?`禁止使用占位描述 "${t}",请提供有意义的描述`:null}function Be(e){let t=[],n=f(e);for(let e of n){let n=O(e.description);n&&t.push(`@param 标签禁止使用占位描述 "${n}",请提供有意义的描述`)}let r=p(e);if(r){let e=O(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=O(e.description);n&&t.push(`@typeParam 标签禁止使用占位描述 "${n}",请提供有意义的描述`)}return t}const Ve=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=ze(i.description);a&&e.report({node:t,message:a});let o=Be(i);for(let n of o)e.report({node:t,message:n})}}}}});function He(e){return e?e.trim().startsWith(`-`):!1}const Ue=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=f(i);for(let i of a)He(i.description)||e.report({node:t,message:`参数 "${i.name}" 的描述应该使用 \`-\` 分隔,格式:@param ${i.name} - 描述`,fix:e=>{let t=RegExp(`(@param\\s+${T(i.name)}\\s+)([^\\-\\s].*?)(\\n|$)`,`g`),a=n.replace(t,`$1- $2$3`);return e.replaceTextRange(r.range,`/*${a}*/`)}})}}}}});function We(e){let t=e.split(`
|
|
10
|
+
`),n=-1;for(let e=0;e<t.length;e++){let r=t[e];if(!r)continue;let i=r.trim();if(i.startsWith(`*`)&&i.slice(1).trim().startsWith(`@`)){n=e;break}}if(n===-1||n===0)return!0;let r=t[n-1];if(!r)return!0;let i=r.trim();return i===`*`||i===``}const Ge=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&&m(i)&&(We(n)||e.report({node:t,message:`标签前应有一个空行`,fix:e=>{let t=n.replace(/(\* [^\n@]+)\n(\s*)(\* @)/g,`$1
|
|
11
|
+
$2*
|
|
12
|
+
$2$3`);return e.replaceTextRange(r.range,`/*${t}*/`)}}))}}}}}),Ke=[/使用\s+\S+\s+代替/,/请使用\s+\S+/,/use\s+\S+\s+instead/i,/replaced\s+by\s+\S+/i];function qe(e){if(!e)return!1;let t=e.trim();if(t.length===0)return!1;for(let e of Ke)if(e.test(t))return!0;return t.length>10}const Je=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&&(qe(a.description)||e.report({node:t,message:`@deprecated 标签应该包含替代方案说明,例如:@deprecated 使用 newMethod 代替`}))}}}}}),Ye=[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`,`ClassDeclaration`,`VariableDeclaration`,`MethodDefinition`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSPropertySignature`,`TSEnumMember`],Xe=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&&(m(i)||e.report({node:n,message:`TSDoc 注释缺少描述`,fix:t=>{let n=S(e.sourceCode.text,r.range);return De(t,r,n)}}))}let r={Program(){t=e.sourceCode.getAllComments()}};for(let e of Ye)r[e]=e=>n(e);return r}});function k(e){return pe.safeParse(e).success}function A(e){return me.safeParse(e).success}function j(e){return he.safeParse(e).success}function Ze(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 Qe(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 $e(e){if(!e||typeof e!=`object`)return null;let t=e;return`type`in t&&t.type===`ObjectPattern`&&`properties`in t?Ze(t.properties):`type`in t&&t.type===`ArrayPattern`&&`elements`in t?Qe(t.elements):null}function et(e){if(!j(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 $e(n)}return k(t)?t.id?.name??null:null}function M(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 k(e)?e.id?.name??null:null;case`MethodDefinition`:case`PropertyDefinition`:case`TSPropertySignature`:return A(e)?e.key?.name??null:null;case`VariableDeclaration`:return et(e);default:return null}}const tt={FunctionDeclaration:`函数`,MethodDefinition:`方法`,ClassDeclaration:`类`,VariableDeclaration:`变量`,TSInterfaceDeclaration:`接口`,TSTypeAliasDeclaration:`类型别名`,TSEnumDeclaration:`枚举`,PropertyDefinition:`类属性`,TSPropertySignature:`接口属性`,TSEnumMember:`枚举成员`};function N(e){return tt[e]||e}function P(e){return ge.safeParse(e).success}function nt(e){return P(e)?e.typeParameters.params.map(e=>e.name&&typeof e.name==`object`&&`name`in e.name?String(e.name.name):``).filter(Boolean):[]}function rt(e){return!e.trim().includes(`
|
|
13
|
+
`)}function it(e){return A(e)?e.key.name:k(e)?e.id.name:`(匿名)`}const at=e({meta:{type:`suggestion`,docs:{description:`要求接口属性、类属性、枚举成员使用多行 TSDoc 注释格式`}},createOnce(e){return{TSPropertySignature(t){F(t,e)},PropertyDefinition(t){F(t,e)},TSEnumMember(t){F(t,e)}}}});function F(e,t){let n=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!n)return;let r=n.value;if(rt(r)){let n=it(e);t.report({node:e,message:`"${n}"的注释应使用多行 TSDoc 格式,当前为单行格式`})}}const ot=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=f(i);for(let n of a)h(n)||e.report({node:t,message:`参数 "${n.name}" 缺少描述`,fix:t=>Oe(t,r,n.name,S(e.sourceCode.text,r.range))})}}}}}),st=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=D(n);if(i.length===0)return;let a=d(r.value);if(!a)return;let o=g(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 we(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)}}}}),ct=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=p(i);a&&!h(a)&&e.report({node:t,message:`@returns 标签缺少描述`,fix:t=>ke(t,r,S(e.sourceCode.text,r.range))})}}}}});function I(e){return typeof e!=`object`||!e||!(`type`in e)?!1:typeof e.type==`string`}function lt(e){return I(e)&&e.type===`ReturnStatement`&&`argument`in e}function ut(e){return typeof e==`object`&&!!e&&`body`in e}function dt(e){return typeof e==`object`&&!!e&&`returnType`in e}function ft(e){return I(e)?[`FunctionDeclaration`,`FunctionExpression`,`ArrowFunctionExpression`].includes(e.type):!1}function L(e,t){if(!e||typeof e!=`object`)return!1;let n=e;if(t.has(n))return!1;if(t.add(n),lt(n))return!0;if(ft(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(L(e,t))return!0}else if(`type`in i&&L(i,t))return!0}}return!1}function R(e){if(typeof e!=`object`||!e||!ut(e)||!e.body)return!1;let t=e.body;return typeof t!=`object`||!t?!1:!(`type`in t)||t.type!==`BlockStatement`||L(t,new WeakSet)}function z(e){if(typeof e!=`object`||!e||!dt(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(I(t))return t.type===`TSVoidKeyword`}}}return!1}function pt(e){return R(e)?!z(e):!1}const mt=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求有返回值的函数有 @returns 标签`}},createOnce(e){return{FunctionDeclaration(t){B(t,e)},FunctionExpression(t){B(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}B(t,e)}}}});function B(e,t){if(!pt(e))return;let n=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!n)return;let r=d(n.value);r&&(p(r)||t.report({node:e,message:`缺少 @returns 文档`,fix:e=>{let r=S(t.sourceCode.text,n.range);return Te(e,n,r)}}))}function ht(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&`range`in t&&Array.isArray(t.range)}const gt=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&&ht(t)&&e.report({node:t,message:`@throws 标签应使用 {@link Type} 格式声明异常类型,例如:@throws {@link Error} 描述`})}}}}});function V(e){if(typeof e!=`object`||!e)return!1;let t=e;return`body`in t&&Array.isArray(t.body)}function _t(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`ThrowStatement`&&`argument`in t}function vt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`NewExpression`&&`callee`in t}function H(e){if(typeof e!=`object`||!e)return!1;let t=e;return`type`in t&&t.type===`Identifier`&&`name`in t}function yt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`consequent`in t&&`alternate`in t}function bt(e){if(typeof e!=`object`||!e)return!1;let t=e;return`block`in t&&`handler`in t}function xt(e){return typeof e!=`object`||!e?!1:`cases`in e}function St(e){if(typeof e!=`object`||!e||!(`consequent`in e))return!1;let t=e;return Array.isArray(t.consequent)}function Ct(e){let t=e.argument;if(vt(t)){let e=t.callee;if(H(e))return e.name}return H(t)?t.name:`Error`}function U(e,t){if(!V(e))return;let n=e;if(Array.isArray(n.body))for(let e of n.body)W(e,t)}function W(e,t){if(!e||typeof e!=`object`)return;let n=e;if(`type`in n&&n.type===`ThrowStatement`&&_t(n)){let e=Ct(n);t.push({typeName:e});return}if(`type`in n&&n.type===`IfStatement`&&yt(n)){W(n.consequent,t),n.alternate&&W(n.alternate,t);return}if(`type`in n&&n.type===`TryStatement`&&bt(n)){wt(n,t);return}if(`type`in n&&n.type===`SwitchStatement`&&xt(n)){Tt(n,t);return}`type`in n&&n.type===`BlockStatement`&&V(n)&&U(n,t)}function wt(e,t){V(e.block)&&U(e.block,t),e.handler&&typeof e.handler==`object`&&`body`in e.handler&&e.handler.body&&V(e.handler.body)&&U(e.handler.body,t)}function Tt(e,t){for(let n of e.cases)if(St(n))for(let e of n.consequent)W(e,t)}function Et(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 U(t,n),n}const Dt=e({meta:{type:`suggestion`,docs:{description:`要求抛出异常的函数有 @throws 标签`}},createOnce(e){return{FunctionDeclaration(t){G(t,e)},FunctionExpression(t){G(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}G(t,e)}}}});function G(e,t){let n=Et(e);if(n.length===0)return;let r=b(t.sourceCode.getAllComments(),e,t.sourceCode.text);if(!r){K(e,t,n);return}let i=d(r.value);if(!i){K(e,t,n);return}i.tags.filter(e=>e.tag===`throws`||e.tag===`throw`).length===0&&K(e,t,n)}function K(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 Ot(e){return le.safeParse(e).success}function kt(e){return ce.safeParse(e).success}function At(e){return oe.safeParse(e).success}function jt(e){return se.safeParse(e).success}function Mt(e){return ve.safeParse(e).success}function Nt(e){return ye.safeParse(e).success}function Pt(e,t){return e.type===`FunctionDeclaration`||e.type===`FunctionExpression`||e.type===`ArrowFunctionExpression`?Ft(e,t):e.type===`MethodDefinition`&&Mt(e)&&e.value?It(e.value,t):e.type===`ClassDeclaration`?Lt(t):e.type===`VariableDeclaration`&&Nt(e)?Rt(e.declarations,t):q(t)}function Ft(e,t){let n=D(e),r=R(e),i=z(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 It(e,t){if(!e||typeof e!=`object`||!Ot(e))return q(t);let n=e,r=D(n),i=R(n),a=z(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 Lt(e){let t=[];return t.push(`/**`),t.push(` * ${x.classDescription}`),t.push(` */`),`\n${e}`+t.join(`\n${e}`)+`\n${e}`}function Rt(e,t){let n=e[0];if(!n||!kt(n))return q(t);let r=At(n)?n.init:void 0;if(r&&typeof r==`object`&&jt(r)){let e=r.type;if(e===`ArrowFunctionExpression`||e===`FunctionExpression`)return q(t)}let i=[];return i.push(`/**`),i.push(` * ${x.variableDescription}`),i.push(` */`),`\n${t}`+i.join(`\n${t}`)+`\n${t}`}function q(e){let t=[];return t.push(`/**`),t.push(` * ${x.description}`),t.push(` */`),`\n${e}`+t.join(`\n${e}`)+`\n${e}`}function J(e){return typeof e==`object`&&!!e&&`type`in e&&typeof e.type==`string`}function Y(e){return typeof e==`object`&&!!e&&`parent`in e}function zt(e){return typeof e==`object`&&!!e&&`init`in e}function X(e){return typeof e==`object`&&!!e}const Bt=[`FunctionDeclaration`,`MethodDefinition`,`ClassDeclaration`,`VariableDeclaration`,`TSInterfaceDeclaration`,`TSTypeAliasDeclaration`,`TSEnumDeclaration`,`PropertyDefinition`,`TSEnumMember`];function Vt(e){if(!X(e)||e.type!==`TSPropertySignature`)return!1;let t=e.key;return X(t)&&t.type===`Identifier`&&`name`in t&&typeof t.name==`string`?t.name===`null`||t.name===`undefined`:!1}function Ht(e,t){if(Y(e)&&e.parent&&typeof e.parent==`object`&&J(e.parent)&&[`ForStatement`,`ForInStatement`,`ForOfStatement`].includes(e.parent.type))return!0;if(e.type===`VariableDeclaration`){if(t)return!1;if(j(e)&&e.declarations.length>0){let t=e.declarations[0];if(!t)return!0;if(zt(t)&&t.init&&typeof t.init==`object`&&J(t.init)&&(t.init.type===`ArrowFunctionExpression`||t.init.type===`FunctionExpression`))return!1}return!0}return!!Vt(e)}function Ut(e){return e.includes(`/**`)}function Wt(e){if(`decorators`in e&&Array.isArray(e.decorators)&&e.decorators.length>0){let t=e.decorators[0];if(X(t)){let e=t.range;if(Array.isArray(e)&&e.length>=1&&typeof e[0]==`number`)return[e[0],e[0]]}}if(Y(e)&&e.parent&&typeof e.parent==`object`){let t=e.parent;if(J(t)&&X(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 Gt(e,t){if(!e)return``;let n=t;for(;n>0&&e[n-1]!==`
|
|
14
|
+
`;)n--;return e.slice(n,t)}function Kt(e,t,n){if(t.skipFile||Ht(e,t.checkAllVariables))return;let r=b(t.commentsCache,e,n.sourceCode.text);if(!r){let t=N(e.type),r=M(e);n.report({node:e,message:`${t}"${r}"缺少 TSDoc 注释`,fix:t=>{let r=Wt(e),i=Pt(e,Gt(n.sourceCode.text,r[0]));return t.insertTextBeforeRange(r,i)}});return}let i=r.value;if(Ce(i)){let t=N(e.type),r=M(e);n.report({node:e,message:`${t}"${r}"的 TSDoc 注释包含占位描述,请填写实际描述`})}}function qt(e,t){let n=e.getAllComments(),r=e.text;if(r!=null){if(!Ut(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 Jt(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 Yt=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=qt(e.sourceCode,t);let r=e.options?.[0];t.checkAllVariables=Jt(r)}};for(let r of Bt)n[r]=n=>Kt(n,t,e);return n}});function Xt(e){return e.tags.filter(e=>e.tag===`typeParam`||e.tag===`template`).map(e=>e.name)}const Zt=e({meta:{type:`suggestion`,fixable:`code`,docs:{description:`要求泛型有 @typeParam 标签`}},createOnce(e){return{FunctionDeclaration(t){Z(t,e)},FunctionExpression(t){Z(t,e)},ArrowFunctionExpression(t){if(`parent`in t&&t.parent){let e=t.parent.type;if(e===`CallExpression`||e===`Property`)return}Z(t,e)},ClassDeclaration(t){Z(t,e)},TSInterfaceDeclaration(t){Z(t,e)},TSTypeAliasDeclaration(t){Z(t,e)}}}});function Z(e,t){if(!P(e))return;let n=nt(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=Xt(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 Ee(e,r,n,i)}})}const Qt=/^(=+)\s+(.+?)\s+(=+)$/;function $t(e){let t=e.trim().match(Qt);return t?{leadingEquals:t[1]??``,text:t[2]??``,trailingEquals:t[3]??``}:null}const en=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=$t(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)}})}}}}}}),tn=/\bTODO(?:\(([^)]+)\))?:?\s*(.*)/i;function nn(e){return typeof e==`object`&&!!e&&!Array.isArray(e)}const rn={requireAuthor:!1,requireDescription:!0};function an(e){return/\bTODO\b/i.test(e)}function on(e){let t={...rn};if(nn(e)){let n=e;typeof n.requireAuthor==`boolean`&&(t.requireAuthor=n.requireAuthor),typeof n.requireDescription==`boolean`&&(t.requireDescription=n.requireDescription)}return t}function sn(e){let t=e.match(tn);return t?{author:t[1]??``,description:(t[2]??``).trim()}:null}const Q={"no-commented-code":s,"no-description-tag":ae,"no-extra-param":Ne,"no-legacy-jsdoc-tags":Le,"no-placeholder-description":Ve,"param-hyphen-format":Ue,"require-blank-line-before-tags":Ge,"require-deprecated-alternative":Je,"require-description":Xe,"require-multiline-property-comment":at,"require-param":st,"require-param-description":ot,"require-returns":mt,"require-returns-description":ct,"require-throws":Dt,"require-throws-type":gt,"require-tsdoc":Yt,"require-type-param":Zt,"separator-format":en,"todo-format":e({meta:{type:`suggestion`,docs:{description:`要求 TODO 注释有描述和作者`}},createOnce(e){let t=on(e.options?.[0]);return{Program(n){let r=e.sourceCode.getAllComments();for(let i of r){let r=i.value;if(!an(r))continue;let a=sn(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:Q});export{$ as default,$ as tsdocPlugin,Q 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.10",
|
|
4
4
|
"description": "Oxlint TSDoc 插件,提供 TSDoc 注释规范检查规则",
|
|
5
5
|
"license": "UNLICENSED",
|
|
6
6
|
"files": [
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
39
|
"@longzai-intelligence-logger/node": "^0.1.1",
|
|
40
|
-
"@longzai-intelligence-oxlint/core": "0.1.
|
|
40
|
+
"@longzai-intelligence-oxlint/core": "0.1.10",
|
|
41
41
|
"@oxlint/plugins": "^1.74.0",
|
|
42
42
|
"zod": "^4.4.3"
|
|
43
43
|
},
|