@longzai-intelligence-oxlint/tsdoc-plugin 0.1.13 → 0.1.15

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.
Files changed (2) hide show
  1. package/dist/index.js +1 -1
  2. package/package.json +2 -2
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@ import{defineRule as e,eslintCompatPlugin as t}from"@oxlint/plugins";import*as n
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
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 w(e,t,n,r,i){let a=t.range[0]+2,o=t.range[1]-2,s=n[0].replace(/\s+$/,``).length,c=a+(n.index??0)+s,l=`${r}\n${i} `;return e.replaceTextRange([c,o],l)}function we(e,t,n,r){let i=`\n${r} * @param ${n} - ${x.paramDescription}`,a=t.value.match(/@param[^@]*$/);return a&&a.index!==void 0?w(e,t,a,i,r):C(e,t,i,r)}function Te(e,t,n){let r=`\n${n} * @returns ${x.returnsDescription}`,i=t.value.match(/@\w+[^@]*$/);return i&&i.index!==void 0?w(e,t,i,r,n):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)return w(e,t,o,i,r);let s=a.match(/@param[^@]*$/);return s&&s.index!==void 0?w(e,t,s,i,r):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 T(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+${E(n)}\\s*$`,`m`),o=a.exec(i);if(o){let s=T(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=T(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 E(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const D=n.object({name:n.optional(n.string())}),Ae=n.object({type:n.string(),name:n.optional(n.string()),left:n.optional(D),argument:n.optional(D),parameter:n.optional(D)});function je(e){return _e.safeParse(e).success}function O(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=O(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+${E(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(`
7
+ `)?``:`\n${n} `}function Oe(e,t,n,r){let i=t.value,a=RegExp(`@param\\s+${E(n)}\\s*$`,`m`),o=a.exec(i);if(o){let s=T(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=T(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 E(e){return e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`)}const D=n.object({type:n.optional(n.string()),name:n.optional(n.string()),left:n.optional(n.object({name:n.optional(n.string())}))}),Ae=n.object({type:n.string(),name:n.optional(n.string()),left:n.optional(D),argument:n.optional(D),parameter:n.optional(D)});function je(e){return _e.safeParse(e).success}function O(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??n.parameter?.left?.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=O(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+${E(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 k(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=k(e);return t?`禁止使用占位描述 "${t}",请提供有意义的描述`:null}function Be(e){let t=[],n=f(e);for(let e of n){let n=k(e.description);n&&t.push(`@param 标签禁止使用占位描述 "${n}",请提供有意义的描述`)}let r=p(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 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+${E(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
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(/([ \t]*)(\* [^\n@]+)\n([ \t]*)(\* @)/g,(e,t,n,r,i)=>`${t}${n}\n${t||r}*\n${r}${i}`);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 A(e){return pe.safeParse(e).success}function j(e){return me.safeParse(e).success}function M(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(!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 $e(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 et(e);default:return null}}const tt={FunctionDeclaration:`函数`,MethodDefinition:`方法`,ClassDeclaration:`类`,VariableDeclaration:`变量`,TSInterfaceDeclaration:`接口`,TSTypeAliasDeclaration:`类型别名`,TSEnumDeclaration:`枚举`,PropertyDefinition:`类属性`,TSPropertySignature:`接口属性`,TSEnumMember:`枚举成员`};function P(e){return tt[e]||e}function F(e){return ge.safeParse(e).success}function nt(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 rt(e){return!e.trim().includes(`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@longzai-intelligence-oxlint/tsdoc-plugin",
3
- "version": "0.1.13",
3
+ "version": "0.1.15",
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.13",
40
+ "@longzai-intelligence-oxlint/core": "0.1.15",
41
41
  "@oxlint/plugins": "^1.74.0",
42
42
  "zod": "^4.4.3"
43
43
  },