@longzai-intelligence-oxlint/tsdoc-plugin 0.1.9 → 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 +3 -3
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -7,8 +7,8 @@ import{defineRule as e,eslintCompatPlugin as t}from"@oxlint/plugins";import*as n
|
|
|
7
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(`
|
|
8
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(`
|
|
9
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
|
|
11
|
-
|
|
12
|
-
$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 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(`
|
|
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
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
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
|
},
|