productive-eslint
Version:
Mildly strict and sufficiently practical ESLint config based on Evgeny Orekhov's eslint-config-hardcore
6 lines • 66.6 kB
JavaScript
#!/usr/bin/env node
import{_ as e,h as t,i as n,n as r,r as i,t as a,u as o}from"./model-DGP73Lve.js";import s from"node:path";import c from"node:process";import{createJiti as l}from"jiti";import{access as u,readFile as d}from"node:fs/promises";import f from"@typescript-eslint/eslint-plugin";import p from"@typescript-eslint/parser";import m from"eslint-plugin-import";import{ESLint as h}from"eslint";import g from"typescript";import _ from"@smarttools/eslint-plugin-rxjs";const ee=e=>{let t=[`# ${e.title}`,``,`## Summary`,``,`- Files scanned: \`${e.fileCount}\``,`- Findings: \`${e.findingsCount}\``,`- Hotspots shown: \`${e.summaries.length}\``];if(e.summaryLines&&e.summaryLines.length>0)for(let n of e.summaryLines)t.push(`- ${n}`);if(t.push(``),e.summaries.length>0){if(e.topGroups&&e.topGroups.length>0){t.push(`## Top Directions`,``);for(let n of e.topGroups)t.push(`- ${n.label}: \`${n.count}\``);t.push(``)}t.push(`## Highest Risk`,``);for(let n of e.summaries){if(t.push(`### \`${n.file}\``,``),t.push(`- Score: \`${n.score}\``),n.labels&&n.labels.length>0&&t.push(`- Labels: ${n.labels.map(e=>`\`${e}\``).join(`, `)}`),n.reasons&&n.reasons.length>0){t.push(`- Why this file is prioritized:`);for(let e of n.reasons)t.push(` - ${e}`)}let e=n.findings.slice(0,10),r=n.findings.length-e.length;for(let r of e){let e=r.symbol?`${n.file} :: ${r.symbol}`:n.file,i=r.line?`${e}:${r.line}${r.column?`:${r.column}`:``}`:e;t.push(`- ${r.ruleId??`unknown-rule`} (${r.severity}, score ${r.score}) at \`${i}\``),r.labels&&r.labels.length>0&&t.push(` - Labels: ${r.labels.map(e=>`\`${e}\``).join(`, `)}`);for(let e of r.reasons)t.push(` - ${e}`)}r>0&&t.push(`- ${r} more findings in this hotspot are omitted from the Markdown report.`),t.push(``)}}return e.suggestedOrder.length>0&&(t.push(`## Suggested Order`,``),e.suggestedOrder.forEach((e,n)=>{t.push(`${n+1}. \`${e}\``)}),t.push(``)),t.push(`## Next Step`,``,e.nextStep),`${t.join(`
`).trim()}\n`};var v=class extends Error{constructor(e){super(e),this.name=`CliError`}};const te=[`eslint.config.ts`,`eslint.config.mts`],ne=async e=>{for(let t of te){let n=s.join(e,t);try{return await u(n),n}catch{continue}}return null},re=t=>{if(!e(t))throw new v(`The selected project does not export a supported productive-eslint composer pipeline.`);return t},ie=e=>!e||typeof e!=`object`||!(`default`in e)?e:e.default??e,ae=async e=>{let t=await ne(e);if(!t)throw new v(`No supported eslint.config.ts or eslint.config.mts file was found in "${e}".`);let n=l(import.meta.url,{fsCache:!1,moduleCache:!1}),r=c.cwd();try{return c.chdir(e),{composer:re(ie(n(t))),configPath:t}}finally{c.chdir(r)}},y=async({config:e,context:t,ruleIds:n})=>{let r=new h({cwd:t.cwd,errorOnUnmatchedPattern:!1,ignore:!0,ignorePatterns:t.exclude,overrideConfig:e,overrideConfigFile:!0,passOnNoPatterns:!0,ruleFilter:({ruleId:e})=>n.includes(e)}),i=t.include.length>0?t.include:[`.`];return(await r.lintFiles(i)).map(e=>({...e,filePath:s.relative(t.cwd,e.filePath)||e.filePath}))},oe=e=>e.labels?.includes(`test-only`)??!1,se=e=>{let t=e.reduce((e,t)=>e+t.score,0);return e.length>0&&e.every(oe)?Math.min(t,10):t},b=(e,t)=>{let n=new Map;for(let t of e){let e=n.get(t.file)??[];e.push(t),n.set(t.file,e)}return[...n.entries()].map(([e,t])=>({file:e,findings:t.sort((e,t)=>t.score-e.score),labels:[...new Set(t.flatMap(e=>e.labels??[]))],reasons:[...new Set(t.flatMap(e=>e.reasons.slice(0,1)))],score:se(t)})).sort((e,t)=>t.score-e.score||e.file.localeCompare(t.file)).slice(0,t)},ce={"@typescript-eslint/explicit-module-boundary-types":`error`,"@typescript-eslint/no-explicit-any":`error`,"@typescript-eslint/no-unsafe-return":`error`,"import/no-mutable-exports":`error`,"no-restricted-syntax":[`error`,{message:`Default exports make public API naming less explicit and harder to refactor.`,selector:`ExportDefaultDeclaration`}]},le=m,ue=f,x=Object.keys(ce),de={"@typescript-eslint/explicit-module-boundary-types":{category:`public-signature`,labels:[`public-signature`,`missing-return-type`],reason:`An exported boundary should make its return contract explicit.`,score:5,severity:`medium`},"@typescript-eslint/no-explicit-any":{category:`public-type-safety`,labels:[`public-type-safety`,`explicit-any`],reason:`Explicit any in public-facing code weakens downstream contracts.`,score:6,severity:`high`},"@typescript-eslint/no-unsafe-return":{category:`public-type-safety`,labels:[`public-type-safety`,`unsafe-return`],reason:`Unsafe returns can leak unknown runtime shape through an API boundary.`,score:6,severity:`high`},"import/no-mutable-exports":{category:`public-mutability`,labels:[`public-mutability`,`mutable-export`],reason:`Mutable exports make public module state difficult to reason about.`,score:5,severity:`medium`},"no-restricted-syntax":{category:`export-policy`,labels:[`export-policy`,`default-export`],reason:`Default exports make public API naming less explicit and harder to refactor.`,score:2,severity:`low`}},fe=/(^|\/)(index|public-api)\.(c|m)?[jt]sx?$/u,pe=/(^|\/)(api|public|shared|lib|components)\//u,me=/\.vue$/u,he=(e,t)=>{let n=[],r=[],i=t;return fe.test(e)&&(n.push(`public-entry`),r.push(`This file looks like a public entrypoint.`),i+=3),pe.test(e)&&(n.push(`shared-surface`),r.push(`The file sits in a shared or API-facing surface.`),i+=2),me.test(e)&&(n.push(`vue-component-contract`),r.push(`A Vue component file can expose props, emits, slots, or bindings.`),i+=2),{labels:n,reasons:r,score:i}},ge=e=>e.clone().append({files:[t],languageOptions:{parserOptions:{extraFileExtensions:[`.vue`],parser:p,projectService:!0,sourceType:`module`}},name:`productive-eslint/analyze-api-vue-parser`}).append({files:[o,t],name:`productive-eslint/analyze-api`,plugins:{"@typescript-eslint":ue,import:le},rules:ce,settings:{"import/resolver":{typescript:!0}}}),_e=(e,t)=>{if(!t.ruleId||!x.includes(t.ruleId))return null;let n=de[t.ruleId];if(!n)return null;let r=he(e,n.score);return{category:n.category,column:t.column,confidence:`high`,file:e,labels:[...n.labels,...r.labels],line:t.line,reasons:[n.reason,t.message,...r.reasons],ruleId:t.ruleId,score:r.score,severity:n.severity}},S=async(e,t)=>{if(t.top<1)throw new v(`--top must be at least 1.`);let n=await y({config:await ge(e).toConfigs(),context:t,ruleIds:x}),r=n.flatMap(e=>e.messages.flatMap(t=>{let n=_e(e.filePath,t);return n?[n]:[]})),i=b(r,t.top),a=i[0],o=r.filter(e=>e.category===`public-type-safety`).length,s=r.filter(e=>e.category===`public-signature`).length,c=r.filter(e=>e.category===`export-policy`).length;return{fileCount:n.length,findingsCount:r.length,nextStep:a?`Start with \`${a.file}\` and make exported contracts explicit before changing internal implementation details.`:`No public API contract findings were reported by the current analyzer ruleset.`,suggestedOrder:i.map(e=>e.file),summaries:i,summaryLines:[`Public type-safety findings: \`${o}\``,`Public signature findings: \`${s}\``,`Export policy findings: \`${c}\``],title:`API Analysis`}},C=[`boundaries/dependencies`],ve=/\b(?:import|export)\b[\s\S]*?\bfrom\s*['"]([^'"]+)['"]|import\s*\(\s*['"]([^'"]+)['"]\s*\)/u,ye=(e,n)=>e.clone().append({files:[o,t],name:`productive-eslint/analyze-architecture`,rules:{"boundaries/dependencies":a},settings:{"boundaries/root-path":n}}),be=e=>e.some(e=>e.plugins?.boundaries?e.files?Array.isArray(e.files)&&e.files.includes(`**/*.vue`):!0:!1),w=e=>{let t=e.match(ve);return t?.[1]??t?.[2]??null},T=(e,t,n)=>{if(n.startsWith(`.`)){let r=s.resolve(s.dirname(s.join(e,t)),n);return s.relative(e,r)}return n},xe=async(e,t)=>{let r=n(t.file);if(!r)return{labels:[`unknown-source`],reason:`Could not map the source file to a known architecture element.`,scoreDelta:0};if(t.category===`private-entry`){let a=w((await d(s.join(e,t.file),`utf8`)).split(`
`)[Math.max(0,(t.line??1)-1)]??``);if(!a)return{category:`private-entry`,labels:[`private-entry`],reason:`A private entry import was reported, but the exact target import could not be recovered.`,scoreDelta:4};let o=n(T(e,t.file,a));return{category:`private-entry`,labels:[`private-entry`],reason:`This import bypasses the public entry point of the target architecture element.`,scoreDelta:4,...o?{directionLabel:i(r,o)}:{}}}let a=w((await d(s.join(e,t.file),`utf8`)).split(`
`)[Math.max(0,(t.line??1)-1)]??``);if(!a)return{category:`layer-direction`,labels:[`layer-direction`],reason:`An architecture direction violation was reported, but the target dependency could not be recovered.`,scoreDelta:3};let o=n(T(e,t.file,a));return o?{category:r.type===o.type?`slice-direction`:`layer-direction`,directionLabel:i(r,o),labels:[r.type===o.type?`slice-direction`:`layer-direction`],reason:r.type===o.type?`This import crosses into another slice of the same architecture layer.`:`This import violates the allowed dependency direction between architecture layers.`,scoreDelta:3}:{category:`layer-direction`,labels:[`layer-direction`],reason:`The target dependency could not be mapped to a known architecture element.`,scoreDelta:3}},Se=(e,t)=>!t.ruleId||!C.includes(t.ruleId)?null:{category:t.message.includes(`private-entry`)?`private-entry`:`layer-direction`,column:t.column,confidence:`high`,file:e.filePath,labels:[],line:t.line,reasons:[t.message],ruleId:t.ruleId,score:t.message.includes(`private-entry`)?5:4,severity:`high`},Ce=e=>{let t=new Map;for(let n of e){let e=n.category===`private-entry`?`private entry imports`:n.labels?.find(e=>e.includes(`->`));e&&t.set(e,(t.get(e)??0)+1)}return[...t.entries()].map(([e,t])=>({count:t,label:e})).sort((e,t)=>t.count-e.count||e.label.localeCompare(t.label)).slice(0,5)},E=async(e,n)=>{if(n.top<1)throw new v(`--top must be at least 1.`);let i=await ye(e,n.cwd).toConfigs();be(i)||i.push({files:[t],name:`productive-eslint/analyze-architecture-vue-plugin`,plugins:r.plugins});let a=await y({config:i,context:n,ruleIds:[...C]}),o=[];for(let e of a)for(let t of e.messages){let r=Se(e,t);if(!r)continue;let i=await xe(n.cwd,r);o.push({...r,...i.category?{category:i.category}:{},labels:[...new Set([...r.labels??[],...i.labels,...i.directionLabel?[i.directionLabel]:[]])],reasons:[...r.reasons,i.reason],score:r.score+i.scoreDelta})}let s=b(o,n.top),c=s[0],l=Ce(o),u=o.filter(e=>e.category===`private-entry`).length,d=o.filter(e=>e.category===`layer-direction`).length,f=o.filter(e=>e.category===`slice-direction`).length;return{fileCount:a.length,findingsCount:o.length,nextStep:c?`Start with \`${c.file}\` and remove the repeated architecture violations there first.`:`No architecture boundary violations were reported by the current analyzer ruleset.`,suggestedOrder:s.map(e=>e.file),summaries:s,summaryLines:[`Layer-direction violations: \`${d}\``,`Slice-direction violations: \`${f}\``,`Private-entry violations: \`${u}\``],title:`Architecture Analysis`,topGroups:l}},D={"@typescript-eslint/await-thenable":`error`,"@typescript-eslint/no-floating-promises":`error`,"@typescript-eslint/no-misused-promises":`error`,"@typescript-eslint/require-await":`error`,"@typescript-eslint/return-await":[`error`,`error-handling-correctness-only`],"no-async-promise-executor":`error`,"promise/always-return":`error`,"promise/catch-or-return":`error`,"promise/no-multiple-resolved":`error`,"promise/no-return-in-finally":`error`,"promise/valid-params":`error`},we=f,O=Object.keys(D),Te={"@typescript-eslint/await-thenable":{category:`likely-bug`,labels:[`likely-bug`,`await-non-thenable`],reason:`Awaiting a non-thenable value usually means async intent drifted.`,score:5,severity:`high`},"@typescript-eslint/no-floating-promises":{category:`likely-bug`,labels:[`likely-bug`,`floating-promise`],reason:`A promise can reject without any handling path.`,score:6,severity:`high`},"@typescript-eslint/no-misused-promises":{category:`likely-bug`,labels:[`likely-bug`,`misused-promise`],reason:`Async behavior is flowing through an API shape that is usually not promise-safe.`,score:6,severity:`high`},"@typescript-eslint/require-await":{category:`suspicious-flow`,labels:[`suspicious-flow`,`unneeded-async`],reason:`An async function without await can make callers assume async work or error boundaries that are not present.`,score:3,severity:`medium`},"@typescript-eslint/return-await":{category:`suspicious-flow`,labels:[`suspicious-flow`,`return-await-error-boundary`],reason:`Returning a promise without await can bypass the local async error boundary.`,score:4,severity:`medium`},"no-async-promise-executor":{category:`likely-bug`,labels:[`likely-bug`,`async-executor`],reason:`Async promise executors often hide rejected work and double-resolution hazards.`,score:5,severity:`high`},"promise/always-return":{category:`suspicious-flow`,labels:[`suspicious-flow`,`incomplete-chain`],reason:`A promise callback does not consistently return its async result.`,score:3,severity:`medium`},"promise/catch-or-return":{category:`suspicious-flow`,labels:[`suspicious-flow`,`missing-catch`],reason:`The promise chain does not make error handling explicit.`,score:4,severity:`medium`},"promise/no-multiple-resolved":{category:`lifecycle-hazard`,labels:[`lifecycle-hazard`,`multiple-resolve`],reason:`The same promise can resolve or reject more than once.`,score:5,severity:`high`},"promise/no-return-in-finally":{category:`lifecycle-hazard`,labels:[`lifecycle-hazard`,`finally-control-flow`],reason:`Returning from finally can suppress or replace earlier async outcomes.`,score:4,severity:`high`},"promise/valid-params":{category:`likely-bug`,labels:[`likely-bug`,`invalid-promise-api`],reason:`Promise APIs are being called with invalid argument shapes.`,score:4,severity:`medium`}},Ee=/(^|\/)(test|tests|__tests__|__mocks__)\//u,De=/\.(spec|test)\.(c|m)?[jt]sx?$/u,Oe=/(^|\/)(shared|lib|libs|utils|helpers|api)\//u,ke=e=>Ee.test(e)||De.test(e),Ae=e=>Oe.test(e),je=e=>e.clone().append({files:[t],languageOptions:{parserOptions:{extraFileExtensions:[`.vue`],parser:p,projectService:!0,sourceType:`module`}},name:`productive-eslint/analyze-async-vue-parser`}).append({files:[o,t],name:`productive-eslint/analyze-async`,plugins:{"@typescript-eslint":we},rules:D}),Me=(e,t)=>{if(!t.ruleId||!O.includes(t.ruleId))return null;let n=Te[t.ruleId];if(!n)return null;let r=ke(e),i=!r&&Ae(e),a=Math.max(1,n.score+(i?2:0)-(r?2:0)),o=[...n.labels,...i?[`shared-surface`]:[],...r?[`test-only`]:[]],s=[n.reason,t.message,...i?[`The finding sits in a shared async surface that can affect multiple callers.`]:[],...r?[`The finding is test-only, so urgency is usually lower than production code.`]:[]];return{category:n.category,column:t.column,confidence:`high`,file:e,labels:o,line:t.line,reasons:s,ruleId:t.ruleId,score:a,severity:n.severity}},k=async(e,t)=>{if(t.top<1)throw new v(`--top must be at least 1.`);let n=await y({config:await je(e).toConfigs(),context:t,ruleIds:O}),r=n.flatMap(e=>e.messages.flatMap(t=>{let n=Me(e.filePath,t);return n?[n]:[]})),i=b(r,t.top),a=i[0],o=r.filter(e=>e.category===`likely-bug`).length,s=r.filter(e=>e.category===`suspicious-flow`).length,c=r.filter(e=>e.category===`lifecycle-hazard`).length;return{fileCount:n.length,findingsCount:r.length,nextStep:a?`Start with \`${a.file}\` and make the async control flow explicit there first.`:`No async reliability findings were reported by the current analyzer ruleset.`,suggestedOrder:i.map(e=>e.file),summaries:i,summaryLines:[`Likely bug findings: \`${o}\``,`Suspicious flow findings: \`${s}\``,`Lifecycle hazard findings: \`${c}\``],title:`Async Analysis`}},A={complexity:[`error`,10],"max-depth":[`error`,3],"no-nested-ternary":`error`,"productive/no-abusive-nested-if":[`error`,3],"sonarjs/cognitive-complexity":[`error`,15],"sonarjs/no-all-duplicated-branches":`error`,"sonarjs/no-duplicated-branches":`error`,"sonarjs/no-gratuitous-expressions":`error`,"sonarjs/no-identical-conditions":`error`,"sonarjs/no-identical-expressions":`error`,"sonarjs/no-invariant-returns":`error`,"sonarjs/no-nested-conditional":`error`},j=Object.keys(A),Ne={complexity:3,"max-depth":3,"no-nested-ternary":2,"productive/no-abusive-nested-if":2,"sonarjs/cognitive-complexity":4,"sonarjs/no-all-duplicated-branches":3,"sonarjs/no-duplicated-branches":3,"sonarjs/no-gratuitous-expressions":2,"sonarjs/no-identical-conditions":3,"sonarjs/no-identical-expressions":3,"sonarjs/no-invariant-returns":3,"sonarjs/no-nested-conditional":2},Pe={complexity:`Cyclomatic complexity already crossed the analyzer threshold.`,"max-depth":`Branch nesting is above the safe editing threshold.`,"no-nested-ternary":`Nested ternaries make branch intent harder to preserve.`,"productive/no-abusive-nested-if":`Nested if chains are dense enough to deserve structural attention.`,"sonarjs/cognitive-complexity":`Cognitive complexity is already high before additional risk scoring.`,"sonarjs/no-all-duplicated-branches":`Every branch has the same implementation, so the control flow is likely misleading.`,"sonarjs/no-duplicated-branches":`Duplicated branch implementations make it harder to infer the intended behavior.`,"sonarjs/no-gratuitous-expressions":`A condition or expression is structurally unnecessary and can obscure intent.`,"sonarjs/no-identical-conditions":`Repeated branch conditions usually point to stale or unreachable logic.`,"sonarjs/no-identical-expressions":`Identical expressions in a comparison can turn branching into dead intent.`,"sonarjs/no-invariant-returns":`A function returns the same value through different branches, making the branching suspect.`,"sonarjs/no-nested-conditional":`Nested conditionals compress multiple branches into a hard-to-edit expression.`},Fe=e=>e.endsWith(`.tsx`)?g.ScriptKind.TSX:g.ScriptKind.TS,M=e=>g.isArrowFunction(e)||g.isConstructorDeclaration(e)||g.isFunctionDeclaration(e)||g.isFunctionExpression(e)||g.isGetAccessor(e)||g.isMethodDeclaration(e)||g.isSetAccessor(e),Ie=e=>{if(g.isConstructorDeclaration(e))return`constructor`;if(`name`in e&&e.name)return g.isIdentifier(e.name)||g.isStringLiteral(e.name)?e.name.text:e.name.getText();let t=e.parent;return t&&g.isVariableDeclaration(t)&&g.isIdentifier(t.name)||t&&g.isPropertyAssignment(t)&&(g.isIdentifier(t.name)||g.isStringLiteral(t.name)||g.isNumericLiteral(t.name))?t.name.text:t&&g.isBinaryExpression(t)&&t.operatorToken.kind===g.SyntaxKind.EqualsToken?t.left.getText():`<anonymous>`},Le=e=>e?g.isObjectLiteralExpression(e)?`object`:g.isArrayLiteralExpression(e)?`array`:g.isStringLiteralLike(e)||g.isNumericLiteral(e)?`literal`:e.kind===g.SyntaxKind.TrueKeyword||e.kind===g.SyntaxKind.FalseKeyword?`boolean`:g.isIdentifier(e)?`identifier`:g.isCallExpression(e)?`call`:g.isAwaitExpression(e)?`await`:g.isConditionalExpression(e)?`conditional`:g.SyntaxKind[e.kind]??`other`:`void`,N=e=>{let t=0,n=e=>{g.isBinaryExpression(e)&&(e.operatorToken.kind===g.SyntaxKind.AmpersandAmpersandToken||e.operatorToken.kind===g.SyntaxKind.BarBarToken)&&(t+=1),e.forEachChild(n)};return n(e),t},P=e=>g.isIdentifier(e)?e.text:e.getText(),Re=e=>e===g.SyntaxKind.EqualsToken||e===g.SyntaxKind.PlusEqualsToken||e===g.SyntaxKind.MinusEqualsToken||e===g.SyntaxKind.AsteriskEqualsToken||e===g.SyntaxKind.AsteriskAsteriskEqualsToken||e===g.SyntaxKind.SlashEqualsToken||e===g.SyntaxKind.PercentEqualsToken||e===g.SyntaxKind.AmpersandEqualsToken||e===g.SyntaxKind.BarEqualsToken||e===g.SyntaxKind.CaretEqualsToken||e===g.SyntaxKind.LessThanLessThanEqualsToken||e===g.SyntaxKind.GreaterThanGreaterThanEqualsToken||e===g.SyntaxKind.GreaterThanGreaterThanGreaterThanEqualsToken||e===g.SyntaxKind.AmpersandAmpersandEqualsToken||e===g.SyntaxKind.BarBarEqualsToken||e===g.SyntaxKind.QuestionQuestionEqualsToken,ze=(e,t)=>{let n=0,r=[],i=new Map,a=new Set,o=new Set,s=new Set,c=0,l=0,u=0,d=0,f=e=>{let t=n;n+=1,r.push(t),c=Math.max(c,r.length),h(e),r.pop()},p=e=>{let t=r.at(-1);if(t===void 0)return;let n=i.get(t)??new Set;n.add(e),i.set(t,n),a.add(t)},m=()=>{let e=r.at(-1);e!==void 0&&o.add(e)},h=t=>{if(!(t!==e&&M(t))){if(g.isIfStatement(t)){d+=N(t.expression),f(t.thenStatement),t.elseStatement&&f(t.elseStatement);return}if(g.isForStatement(t)||g.isForInStatement(t)||g.isForOfStatement(t)||g.isWhileStatement(t)||g.isDoStatement(t)){`expression`in t&&t.expression&&(d+=N(t.expression)),f(t.statement);return}if(g.isSwitchStatement(t)){for(let e of t.caseBlock.clauses)f(e);return}if(g.isTryStatement(t)&&r.length>0&&(u+=1),g.isAwaitExpression(t)&&r.length>0&&(l+=1),g.isBinaryExpression(t)&&Re(t.operatorToken.kind)&&(g.isIdentifier(t.left)||g.isPropertyAccessExpression(t.left)||g.isElementAccessExpression(t.left)||g.isArrayLiteralExpression(t.left)||g.isObjectLiteralExpression(t.left))&&p(P(t.left)),(g.isPrefixUnaryExpression(t)||g.isPostfixUnaryExpression(t))&&(t.operator===g.SyntaxKind.PlusPlusToken||t.operator===g.SyntaxKind.MinusMinusToken)){let e=t.operand;(g.isIdentifier(e)||g.isPropertyAccessExpression(e)||g.isElementAccessExpression(e))&&p(P(e))}(g.isCallExpression(t)||g.isNewExpression(t))&&r.length>0&&m(),g.isReturnStatement(t)&&s.add(Le(t.expression)),t.forEachChild(h)}};e.body&&h(e.body);let _=new Map;for(let e of i.values())for(let t of e)_.set(t,(_.get(t)??0)+1);let ee=t.getLineAndCharacterOfPosition(e.getStart(t)).line+1,v=t.getLineAndCharacterOfPosition(e.end).line+1;return{asyncInsideBranches:l,booleanGuardComplexity:d,branchMutations:a.size,functionLines:v-ee+1,maxDepth:c,mixedReturnShapes:s.size>1?s.size:0,sharedMutableAcrossBranches:[..._.values()].filter(e=>e>1).length,sideEffectBranches:o.size,tryCatchInsideBranches:u}},Be=(e,t)=>{let n=[],r=i=>{if(M(i)){let r=t.getLineAndCharacterOfPosition(i.getStart(t)).line+1,a=t.getLineAndCharacterOfPosition(i.end).line+1;n.push({displayName:Ie(i),endLine:a,file:e,metrics:ze(i,t),startLine:r})}i.forEachChild(r)};return r(t),n},F=(e,t)=>t===void 0?null:e.filter(e=>t>=e.startLine&&t<=e.endLine).sort((e,t)=>e.endLine-e.startLine-(t.endLine-t.startLine))[0]??null,Ve=(e,t,n)=>{if(n&&n.displayName!==`<anonymous>`)return n;let r=e.filter(e=>e.displayName!==`<anonymous>`);for(let e of t){let t=F(r,e.line);if(t)return t}return n},He=e=>Math.max(0,e.maxDepth-2)+e.branchMutations*2+e.asyncInsideBranches*2+e.tryCatchInsideBranches*2+(e.mixedReturnShapes>0?2:0)+e.sharedMutableAcrossBranches*3+Math.max(0,e.sideEffectBranches-1)*3+ +(e.functionLines>40)+e.booleanGuardComplexity,Ue=e=>{let t=[];return e.maxDepth>2&&t.push(`Nested branch depth reaches ${e.maxDepth}.`),e.branchMutations>0&&t.push(`Branches mutate state in ${e.branchMutations} places.`),e.sharedMutableAcrossBranches>0&&t.push(`Mutable state is shared across ${e.sharedMutableAcrossBranches} branch paths.`),e.asyncInsideBranches>0&&t.push(`Async work appears inside ${e.asyncInsideBranches} branch paths.`),e.sideEffectBranches>1&&t.push(`Side effects appear in ${e.sideEffectBranches} different branches.`),e.tryCatchInsideBranches>0&&t.push(`Try/catch handling is nested inside branching logic.`),e.mixedReturnShapes>0&&t.push(`The function returns more than one structural shape.`),e.functionLines>40&&t.push(`Function spans ${e.functionLines} lines.`),e.booleanGuardComplexity>0&&t.push(`Boolean guards contain multiple logical operators.`),t},We=e=>e>=12?`high`:e>=7?`medium`:`low`,Ge=e=>e.clone().append({files:[o],name:`productive-eslint/analyze-complexity`,rules:A}),Ke=(e,t)=>e.sort((e,t)=>t.score-e.score||e.file.localeCompare(t.file)).slice(0,t).map(e=>({file:e.file,findings:[e],...e.labels?{labels:e.labels}:{},reasons:e.reasons.slice(0,3),score:e.score})),I=e=>e.symbol?`${e.file} :: ${e.symbol}`:e.file,L=async(e,t)=>{if(t.top<1)throw new v(`--top must be at least 1.`);let n=await y({config:await Ge(e).toConfigs(),context:t,ruleIds:j}),r=[];for(let e of n){if(e.messages.length===0)continue;let n=s.join(t.cwd,e.filePath),i=await d(n,`utf8`),a=g.createSourceFile(n,i,g.ScriptTarget.Latest,!0,Fe(n)),o=Be(e.filePath,a),c=new Map;for(let t of e.messages){if(!t.ruleId||!j.includes(t.ruleId))continue;let n=F(o,t.line),r=n?`${e.filePath} :: ${n.displayName}:${n.startLine}`:`${e.filePath} :: <module>:0`,i=c.get(r)??{context:n,hits:[]};i.hits.push({line:t.line,message:t.message,ruleId:t.ruleId}),c.set(r,i)}for(let[,t]of c){let n=Ve(o,t.hits,t.context),i=n?.metrics??{asyncInsideBranches:0,booleanGuardComplexity:0,branchMutations:0,functionLines:0,maxDepth:0,mixedReturnShapes:0,sharedMutableAcrossBranches:0,sideEffectBranches:0,tryCatchInsideBranches:0},a=t.hits.reduce((e,t)=>e+(Ne[t.ruleId]??1),0)+He(i),s=We(a),c=n?.displayName??`<module>`,l=[...t.hits.map(e=>`${Pe[e.ruleId]??e.message} (${e.ruleId} at line ${e.line})`),...Ue(i)];r.push({category:`semantic-change-risk`,confidence:`medium`,file:e.filePath,labels:[s,...n?[`function:${c}`]:[`module-scope`]],...n?{line:n.startLine}:{},reasons:l,ruleId:`complexity/hotspot`,score:a,severity:s,symbol:c})}}let i=Ke(r,t.top),a=r.filter(e=>e.severity===`high`).length,o=r.filter(e=>e.severity===`medium`).length,c=r.filter(e=>e.severity===`low`).length,l=i[0],u=l?.findings[0];return{fileCount:n.length,findingsCount:r.length,nextStep:l?`Start with \`${u?I(u):l.file}\` and reduce the branch and side-effect risk there first.`:`No complexity hotspots were reported by the current analyzer ruleset.`,suggestedOrder:i.flatMap(e=>e.findings.map(I)),summaries:i,summaryLines:[`High-risk hotspots: \`${a}\``,`Medium-risk hotspots: \`${o}\``,`Low-risk hotspots: \`${c}\``],title:`Complexity Analysis`}},R={"@typescript-eslint/no-unused-private-class-members":`error`,"@typescript-eslint/no-unused-vars":[`error`,{args:`after-used`,argsIgnorePattern:`^_`,caughtErrors:`all`,caughtErrorsIgnorePattern:`^_`,ignoreRestSiblings:!0,varsIgnorePattern:`^_`}],"@typescript-eslint/no-useless-constructor":`error`,"no-unreachable":`error`,"no-useless-catch":`error`,"unicorn/no-empty-file":`error`,"unicorn/no-static-only-class":`error`,"unicorn/no-useless-undefined":`error`,"unused-imports/no-unused-imports":`error`},qe=f,z=Object.keys(R),Je={"@typescript-eslint/no-unused-private-class-members":{category:`safe-delete-candidate`,labels:[`safe-delete-candidate`,`private-member`],reason:`A private class member appears unused and is usually safe to delete.`,score:4,severity:`medium`},"@typescript-eslint/no-unused-vars":{category:`safe-delete-candidate`,labels:[`safe-delete-candidate`,`unused-symbol`],reason:`An unused local symbol adds maintenance noise.`,score:3,severity:`medium`},"@typescript-eslint/no-useless-constructor":{category:`safe-delete-candidate`,labels:[`safe-delete-candidate`,`useless-constructor`],reason:`A constructor does not add behavior beyond the inherited default.`,score:3,severity:`low`},"no-unreachable":{category:`likely-bug-or-delete`,labels:[`likely-bug-or-delete`,`unreachable`],reason:`Unreachable code is either dead or hides a control-flow mistake.`,score:6,severity:`high`},"no-useless-catch":{category:`safe-delete-candidate`,labels:[`safe-delete-candidate`,`useless-catch`],reason:`A catch block only rethrows and can usually be removed.`,score:3,severity:`low`},"unicorn/no-empty-file":{category:`safe-delete-candidate`,labels:[`safe-delete-candidate`,`empty-file`],reason:`An empty source file is usually leftover migration or scaffolding debt.`,score:4,severity:`medium`},"unicorn/no-static-only-class":{category:`requires-judgment`,labels:[`requires-judgment`,`static-only-class`],reason:`A static-only class may be a namespace-shaped leftover rather than useful API.`,score:2,severity:`low`},"unicorn/no-useless-undefined":{category:`safe-delete-candidate`,labels:[`safe-delete-candidate`,`redundant-undefined`],reason:`A redundant undefined usually has no semantic value.`,score:1,severity:`low`},"unused-imports/no-unused-imports":{category:`mechanical-delete`,labels:[`mechanical-delete`,`unused-import`],reason:`An unused import can be removed mechanically.`,score:2,severity:`low`}},Ye=/(^|\/)(test|tests|__tests__|__mocks__)\//u,Xe=/\.(spec|test)\.(c|m)?[jt]sx?$/u,Ze=e=>Ye.test(e)||Xe.test(e),Qe=e=>e.clone().append({files:[t],languageOptions:{parserOptions:{extraFileExtensions:[`.vue`],parser:p,projectService:!0,sourceType:`module`}},name:`productive-eslint/analyze-dead-code-vue-parser`}).append({files:[o,t],name:`productive-eslint/analyze-dead-code`,plugins:{"@typescript-eslint":qe},rules:R}),$e=(e,t)=>{if(!t.ruleId||!z.includes(t.ruleId))return null;let n=Je[t.ruleId];if(!n)return null;let r=Ze(e);return{category:r?`test-only`:n.category,column:t.column,confidence:n.category===`requires-judgment`?`medium`:`high`,file:e,labels:[...n.labels,...r?[`test-only`]:[]],line:t.line,reasons:[n.reason,t.message,...r?[`The finding is test-only, so deletion priority is usually lower.`]:[]],ruleId:t.ruleId,score:Math.max(1,n.score-(r?2:0)),severity:r?`low`:n.severity}},B=async(e,t)=>{if(t.top<1)throw new v(`--top must be at least 1.`);let n=await y({config:await Qe(e).toConfigs(),context:t,ruleIds:z}),r=n.flatMap(e=>e.messages.flatMap(t=>{let n=$e(e.filePath,t);return n?[n]:[]})),i=b(r,t.top),a=i[0],o=r.filter(e=>e.labels?.includes(`mechanical-delete`)).length,s=r.filter(e=>e.labels?.includes(`safe-delete-candidate`)).length,c=r.filter(e=>e.category===`requires-judgment`).length;return{fileCount:n.length,findingsCount:r.length,nextStep:a?`Start with \`${a.file}\` and remove the mechanical dead-code findings before touching judgment-heavy cleanup.`:`No dead-code findings were reported by the current analyzer ruleset.`,suggestedOrder:i.map(e=>e.file),summaries:i,summaryLines:[`Mechanical deletion findings: \`${o}\``,`Safe-delete candidates: \`${s}\``,`Requires judgment findings: \`${c}\``],title:`Dead Code Analysis`}},et={"@typescript-eslint/consistent-type-imports":[`error`,{disallowTypeAnnotations:!1,fixStyle:`separate-type-imports`,prefer:`type-imports`}],"import/consistent-type-specifier-style":[`error`,`prefer-top-level`],"import/no-cycle":[`error`,{ignoreExternal:!0,maxDepth:10}],"import/no-duplicates":`error`,"import/no-mutable-exports":`error`,"import/no-namespace":`error`,"import/no-relative-packages":`error`,"import/no-self-import":`error`,"import/no-useless-path-segments":`error`},tt=m,nt=f,V=Object.keys(et),rt={"@typescript-eslint/consistent-type-imports":{category:`type-value-boundary`,labels:[`type-value-boundary`,`mechanical-fix`],reason:`Mixed type and value imports make dependency intent harder to scan.`,score:2,severity:`low`},"import/consistent-type-specifier-style":{category:`type-value-boundary`,labels:[`type-value-boundary`,`mechanical-fix`],reason:`Inline type specifiers make import shape less consistent.`,score:1,severity:`low`},"import/no-cycle":{category:`dependency-graph`,labels:[`dependency-graph`,`cycle`],reason:`Import cycles increase coupling and can create initialization hazards.`,score:7,severity:`high`},"import/no-duplicates":{category:`local-import-hygiene`,labels:[`local-import-hygiene`,`mechanical-fix`],reason:`Duplicate imports are local dependency noise and are usually mechanical to merge.`,score:2,severity:`low`},"import/no-mutable-exports":{category:`public-contract-risk`,labels:[`public-contract-risk`,`mutable-export`],reason:`Mutable exports make module contracts harder to reason about.`,score:5,severity:`medium`},"import/no-namespace":{category:`dependency-shape`,labels:[`dependency-shape`,`namespace-import`],reason:`Namespace imports can hide which dependency surface is actually used.`,score:2,severity:`low`},"import/no-relative-packages":{category:`package-boundary`,labels:[`package-boundary`,`relative-package-import`],reason:`Relative package imports bypass package boundaries and published entrypoints.`,score:6,severity:`high`},"import/no-self-import":{category:`dependency-graph`,labels:[`dependency-graph`,`self-import`],reason:`A module importing itself indicates broken dependency shape.`,score:6,severity:`high`},"import/no-useless-path-segments":{category:`local-import-hygiene`,labels:[`local-import-hygiene`,`mechanical-fix`],reason:`Useless path segments make imports harder to compare and maintain.`,score:1,severity:`low`}},it=e=>e.clone().append({files:[o,t],name:`productive-eslint/analyze-imports`,plugins:{"@typescript-eslint":nt,import:tt},rules:et,settings:{"import/resolver":{typescript:!0}}}),at=(e,t)=>{if(!t.ruleId||!V.includes(t.ruleId))return null;let n=rt[t.ruleId];return n?{category:n.category,column:t.column,confidence:`high`,file:e,labels:n.labels,line:t.line,reasons:[n.reason,t.message],ruleId:t.ruleId,score:n.score,severity:n.severity}:null},ot=e=>[...e.reduce((e,t)=>{let n=t.category??`uncategorized`;return e.set(n,(e.get(n)??0)+1),e},new Map)].map(([e,t])=>({count:t,label:e})).sort((e,t)=>t.count-e.count||e.label.localeCompare(t.label)),H=async(e,t)=>{if(t.top<1)throw new v(`--top must be at least 1.`);let n=await y({config:await it(e).toConfigs(),context:t,ruleIds:V}),r=n.flatMap(e=>e.messages.flatMap(t=>{let n=at(e.filePath,t);return n?[n]:[]})),i=b(r,t.top),a=i[0],o=r.filter(e=>e.labels?.includes(`cycle`)).length,s=r.filter(e=>e.category===`package-boundary`).length,c=r.filter(e=>e.labels?.includes(`mechanical-fix`)).length;return{fileCount:n.length,findingsCount:r.length,nextStep:a?`Start with \`${a.file}\`; fix cycles and package-boundary findings before mechanical import cleanup.`:`No import-shape findings were reported by the current analyzer ruleset.`,suggestedOrder:i.map(e=>e.file),summaries:i,summaryLines:[`Import cycle findings: \`${o}\``,`Package-boundary findings: \`${s}\``,`Mechanical import fixes: \`${c}\``],title:`Imports Analysis`,topGroups:ot(r)}},U={"@typescript-eslint/no-deprecated":`error`,"import/no-deprecated":`error`,"n/no-deprecated-api":`error`},W={"productive-rxjs/no-compat":`error`,"productive-rxjs/no-create":`error`,"productive-rxjs/no-topromise":`error`},G={"vue/no-deprecated-data-object-declaration":`error`,"vue/no-deprecated-delete-set":`error`,"vue/no-deprecated-destroyed-lifecycle":`error`,"vue/no-deprecated-dollar-listeners-api":`error`,"vue/no-deprecated-dollar-scopedslots-api":`error`,"vue/no-deprecated-events-api":`error`,"vue/no-deprecated-filter":`error`,"vue/no-deprecated-functional-template":`error`,"vue/no-deprecated-html-element-is":`error`,"vue/no-deprecated-inline-template":`error`,"vue/no-deprecated-model-definition":`error`,"vue/no-deprecated-props-default-this":`error`,"vue/no-deprecated-router-link-tag-prop":`error`,"vue/no-deprecated-scope-attribute":`error`,"vue/no-deprecated-slot-attribute":`error`,"vue/no-deprecated-slot-scope-attribute":`error`,"vue/no-deprecated-v-bind-sync":`error`,"vue/no-deprecated-v-is":`error`,"vue/no-deprecated-v-on-native-modifier":`error`,"vue/no-deprecated-v-on-number-modifiers":`error`,"vue/no-deprecated-vue-config-keycodes":`error`},K=[...Object.keys(U),...Object.keys(W),...Object.keys(G)],st=_,ct={"productive-rxjs/no-compat":`rxjs/no-compat`,"productive-rxjs/no-create":`rxjs/no-create`,"productive-rxjs/no-topromise":`rxjs/no-topromise`},lt=e=>e.startsWith(`vue/no-deprecated-`)?{category:`vue-migration`,labels:[`vue-migration`,`deprecated-api`],reason:`Deprecated Vue API usage should be removed before framework upgrades.`,score:4,severity:`medium`}:e.startsWith(`@typescript-eslint/`)?{category:`typescript-migration`,labels:[`typescript-migration`,`deprecated-api`],reason:`Deprecated TypeScript symbols should be migrated before they become harder to trace.`,score:4,severity:`medium`}:e.startsWith(`import/`)?{category:`dependency-migration`,labels:[`dependency-migration`,`deprecated-api`],reason:`Deprecated imported APIs should be removed before dependency upgrades.`,score:4,severity:`medium`}:e.startsWith(`rxjs/`)?{category:`rxjs-migration`,labels:[`rxjs-migration`,`deprecated-api`],reason:`RxJS toPromise is deprecated and blocks clean reactive upgrades.`,score:4,severity:`medium`}:{category:`node-migration`,labels:[`node-migration`,`deprecated-api`],reason:`Deprecated Node APIs should be removed before runtime upgrades.`,score:4,severity:`medium`},ut=e=>e.clone().append({files:[o],name:`productive-eslint/analyze-migrations-source`,rules:U}).append({files:[o],name:`productive-eslint/analyze-migrations-rxjs`,plugins:{"productive-rxjs":st},rules:W}).append({files:[t],name:`productive-eslint/analyze-migrations-vue`,rules:G}),dt=(e,t)=>{if(!t.ruleId||!K.includes(t.ruleId))return null;let n=ct[t.ruleId]??t.ruleId,r=lt(n);return{category:r.category,column:t.column,confidence:`high`,file:e,labels:r.labels,line:t.line,reasons:[r.reason,t.message],ruleId:n,score:r.score,severity:r.severity}},ft=async(e,t)=>{if(t.top<1)throw new v(`--top must be at least 1.`);let n=await y({config:await ut(e).toConfigs(),context:t,ruleIds:K}),r=n.flatMap(e=>e.messages.flatMap(t=>{let n=dt(e.filePath,t);return n?[n]:[]})),i=b(r,t.top),a=i[0],o=r.filter(e=>e.category===`vue-migration`).length,s=r.filter(e=>e.category===`rxjs-migration`).length,c=r.filter(e=>e.category===`node-migration`).length,l=r.filter(e=>e.category===`typescript-migration`).length,u=r.filter(e=>e.category===`dependency-migration`).length;return{fileCount:n.length,findingsCount:r.length,nextStep:a?`Start with \`${a.file}\` and remove deprecated APIs before planning larger framework upgrades.`:`No migration-tail findings were reported by the current analyzer ruleset.`,suggestedOrder:i.map(e=>e.file),summaries:i,summaryLines:[`Vue migration findings: \`${o}\``,`RxJS migration findings: \`${s}\``,`Node migration findings: \`${c}\``,`TypeScript migration findings: \`${l}\``,`Dependency migration findings: \`${u}\``],title:`Migrations Analysis`}},q={"@typescript-eslint/ban-ts-comment":[`error`,{minimumDescriptionLength:10,"ts-check":!1,"ts-expect-error":`allow-with-description`,"ts-ignore":!0,"ts-nocheck":!0}],"eslint-comments/no-aggregating-enable":`error`,"eslint-comments/no-duplicate-disable":`error`,"eslint-comments/no-unlimited-disable":`error`,"eslint-comments/no-unused-enable":`error`},pt=f,J=Object.keys(q),mt=/(^|\/)(test|tests|__tests__|__mocks__)\//u,ht=/\.(spec|test)\.(c|m)?[jt]sx?$/u,gt=/(^|\/)(shared|lib|libs|utils|helpers|api)\//u,_t=/eslint-disable|eslint-enable|@ts-(?:ignore|expect-error|nocheck|check)/gu,Y=/^Unused eslint-disable directive/u,vt={category:`unused-disable`,labels:[`unused-disable`,`stale-suppression`],reason:`The disable directive no longer suppresses anything and should be removed.`,score:4,severity:`medium`},X={"@typescript-eslint/ban-ts-comment":{category:`ts-directive`,labels:[`ts-directive`,`compiler-suppression`],reason:`A TypeScript compiler directive is muting or weakening type feedback.`,score:4,severity:`medium`},"eslint-comments/no-aggregating-enable":{category:`aggregated-enable`,labels:[`aggregated-enable`,`scope-confusion`],reason:`One eslint-enable is reopening multiple disables, which makes suppression scope harder to reason about.`,score:3,severity:`medium`},"eslint-comments/no-duplicate-disable":{category:`duplicate-disable`,labels:[`duplicate-disable`,`redundant-suppression`],reason:`The same rule is being disabled more than once in the same area.`,score:3,severity:`medium`},"eslint-comments/no-unlimited-disable":{category:`broad-disable`,labels:[`broad-disable`,`wide-suppression`],reason:`An eslint-disable comment is muting every rule instead of naming the specific exception.`,score:6,severity:`high`},"eslint-comments/no-unused-enable":{category:`unused-enable`,labels:[`unused-enable`,`stale-suppression`],reason:`The eslint-enable directive is not paired with an active disable and should be cleaned up.`,score:2,severity:`low`}},yt=e=>mt.test(e)||ht.test(e),bt=e=>gt.test(e),xt=async(e,t)=>{let n=(await d(s.join(e,t),`utf8`)).match(_t)?.length??0;return{isSharedSurface:bt(t),isTest:yt(t),suppressionCount:n}},St=e=>e.clone().append({linterOptions:{reportUnusedDisableDirectives:`error`},name:`productive-eslint/analyze-suppressions-options`}).append({files:[t],languageOptions:{parserOptions:{extraFileExtensions:[`.vue`],parser:p,projectService:!0,sourceType:`module`}},name:`productive-eslint/analyze-suppressions-vue-parser`}).append({files:[o,t],name:`productive-eslint/analyze-suppressions`,plugins:{"@typescript-eslint":pt},rules:q}),Ct=e=>e.message.includes(`@ts-ignore`)?{category:`ts-ignore`,labels:[`ts-ignore`,`compiler-suppression`],reason:`ts-ignore suppresses the next compiler error even when the code stops failing later.`,score:6,severity:`high`}:e.message.includes(`@ts-nocheck`)?{category:`ts-nocheck`,labels:[`ts-nocheck`,`file-wide-suppression`],reason:`ts-nocheck suppresses type checking for the whole file and tends to hide deeper debt.`,score:7,severity:`high`}:e.message.includes(`@ts-expect-error`)?{category:`weak-ts-expect-error`,labels:[`ts-expect-error`,`weak-description`],reason:`ts-expect-error without a useful explanation makes the suppressed type debt harder to revisit safely.`,score:4,severity:`medium`}:X[`@typescript-eslint/ban-ts-comment`]??{category:`ts-directive`,labels:[`ts-directive`,`compiler-suppression`],reason:`A TypeScript compiler directive is muting or weakening type feedback.`,score:4,severity:`medium`},wt=(e,t,n)=>{let r=!t.ruleId&&Y.test(t.message)?vt:t.ruleId===`@typescript-eslint/ban-ts-comment`?Ct(t):t.ruleId?X[t.ruleId]:null;if(!r)return null;let i=[...r.labels,...n.isSharedSurface?[`shared-surface`]:[],...n.isTest?[`test-only`]:[],...n.suppressionCount>=3?[`dense-suppressions`]:[]],a=[r.reason,t.message,...n.isSharedSurface?[`The suppression sits in a shared surface, so it can hide issues for multiple callers.`]:[],...n.isTest?[`The suppression is test-only, so cleanup urgency is usually lower than production code.`]:[],...n.suppressionCount>=3?[`This file already contains ${n.suppressionCount} suppression directives, which usually points to accumulated local debt.`]:[]],o=Math.max(1,r.score+(n.isSharedSurface?2:0)+(n.isTest?-2:0)+ +(n.suppressionCount>=3));return{category:r.category,column:t.column,confidence:t.ruleId?`high`:`medium`,file:e,labels:i,line:t.line,reasons:a,ruleId:t.ruleId??`eslint/unused-disable-directive`,score:o,severity:r.severity}},Z=async(e,t)=>{if(t.top<1)throw new v(`--top must be at least 1.`);let n=await y({config:await St(e).toConfigs(),context:t,ruleIds:J}),r=n.filter(e=>e.messages.some(e=>!e.ruleId&&Y.test(e.message)||(e.ruleId?J.includes(e.ruleId):!1))),i=new Map;await Promise.all(r.map(async e=>{i.set(e.filePath,await xt(t.cwd,e.filePath))}));let a=r.flatMap(e=>e.messages.flatMap(t=>{let n=i.get(e.filePath);if(!n)return[];let r=wt(e.filePath,t,n);return r?[r]:[]})),o=b(a,t.top),s=o[0],c=a.filter(e=>e.category===`unused-disable`||e.category===`unused-enable`).length,l=a.filter(e=>e.category===`broad-disable`).length,u=a.filter(e=>e.labels?.includes(`compiler-suppression`)).length,d=o.filter(e=>e.labels?.includes(`dense-suppressions`)).length;return{fileCount:n.length,findingsCount:a.length,nextStep:s?`Start with \`${s.file}\` and remove stale or broad suppressions there before touching lower-risk files.`:`No suppression findings were reported by the current analyzer ruleset.`,suggestedOrder:o.map(e=>e.file),summaries:o,summaryLines:[`Unused directive findings: \`${c}\``,`Broad disable findings: \`${l}\``,`TypeScript directive findings: \`${u}\``,`Dense suppression files: \`${d}\``],title:`Suppressions Analysis`}},Q={"@typescript-eslint/ban-ts-comment":`error`,"@typescript-eslint/no-base-to-string":`error`,"@typescript-eslint/no-explicit-any":`error`,"@typescript-eslint/no-unnecessary-condition":`error`,"@typescript-eslint/no-unsafe-argument":`error`,"@typescript-eslint/no-unsafe-assignment":`error`,"@typescript-eslint/no-unsafe-call":`error`,"@typescript-eslint/no-unsafe-enum-comparison":`error`,"@typescript-eslint/no-unsafe-member-access":`error`,"@typescript-eslint/no-unsafe-return":`error`,"@typescript-eslint/no-unsafe-unary-minus":`error`,"@typescript-eslint/switch-exhaustiveness-check":`error`,"@typescript-eslint/unbound-method":`error`},Tt=f,Et=Object.keys(Q),Dt={"@typescript-eslint/ban-ts-comment":`Type suppression hides an actual type-system signal.`,"@typescript-eslint/no-base-to-string":`Implicit object stringification often hides an unexpected runtime representation.`,"@typescript-eslint/no-explicit-any":`Explicit any weakens the local type boundary.`,"@typescript-eslint/no-unnecessary-condition":`A condition is unnecessary according to TypeScript and can mislead control-flow analysis.`,"@typescript-eslint/no-unsafe-argument":`Unsafe argument passes an untyped value across a typed boundary.`,"@typescript-eslint/no-unsafe-assignment":`Unsafe assignment can spread an untyped value further.`,"@typescript-eslint/no-unsafe-call":`Unsafe call means runtime behavior depends on an untyped value.`,"@typescript-eslint/no-unsafe-enum-comparison":`Unsafe enum comparison can make a branch look valid while comparing incompatible domains.`,"@typescript-eslint/no-unsafe-member-access":`Unsafe member access depends on unchecked runtime shape.`,"@typescript-eslint/no-unsafe-return":`Unsafe return leaks a weakly typed value through an API boundary.`,"@typescript-eslint/no-unsafe-unary-minus":`Unsafe unary minus depends on unchecked numeric coercion.`,"@typescript-eslint/switch-exhaustiveness-check":`A switch over a union or enum is not exhaustive.`,"@typescript-eslint/unbound-method":`An unbound method reference can lose its receiver at runtime.`},Ot={"@typescript-eslint/ban-ts-comment":5,"@typescript-eslint/no-base-to-string":2,"@typescript-eslint/no-explicit-any":4,"@typescript-eslint/no-unnecessary-condition":2,"@typescript-eslint/no-unsafe-argument":4,"@typescript-eslint/no-unsafe-assignment":3,"@typescript-eslint/no-unsafe-call":3,"@typescript-eslint/no-unsafe-enum-comparison":3,"@typescript-eslint/no-unsafe-member-access":3,"@typescript-eslint/no-unsafe-return":4,"@typescript-eslint/no-unsafe-unary-minus":3,"@typescript-eslint/switch-exhaustiveness-check":4,"@typescript-eslint/unbound-method":4},kt={"@typescript-eslint/ban-ts-comment":`high`,"@typescript-eslint/no-base-to-string":`low`,"@typescript-eslint/no-explicit-any":`high`,"@typescript-eslint/no-unnecessary-condition":`low`,"@typescript-eslint/no-unsafe-argument":`high`,"@typescript-eslint/no-unsafe-assignment":`medium`,"@typescript-eslint/no-unsafe-call":`medium`,"@typescript-eslint/no-unsafe-enum-comparison":`medium`,"@typescript-eslint/no-unsafe-member-access":`medium`,"@typescript-eslint/no-unsafe-return":`high`,"@typescript-eslint/no-unsafe-unary-minus":`medium`,"@typescript-eslint/switch-exhaustiveness-check":`high`,"@typescript-eslint/unbound-method":`medium`},At=/(^|\/)(test|tests|__tests__|__mocks__)\//u,jt=/\.(spec|test)\.(mts|ts|tsx)$/u,Mt=/(^|\/)(shared|lib|libs|utils|helpers)\//u,Nt=/\.vue$/u,Pt=/(^|\/)(components|ui)\//u,Ft=[/\bdefineProps\s*</u,/\bdefineProps\s*\(/u,/\bdefineEmits\s*</u,/\bdefineEmits\s*\(/u,/\bdefineSlots\s*</u,/\bdefineSlots\s*\(/u,/\bdefineExpose\s*\(/u,/\bdefineModel\s*</u,/\bdefineModel\s*\(/u,/\bdefineComponent\s*\(/u],It=new Set([`@typescript-eslint/no-explicit-any`,`@typescript-eslint/no-unsafe-return`]),Lt=new Set([`@typescript-eslint/no-unnecessary-condition`,`@typescript-eslint/switch-exhaustiveness-check`]),Rt=new Set([`@typescript-eslint/unbound-method`]),zt=e=>e.endsWith(`.tsx`)?g.ScriptKind.TSX:g.ScriptKind.TS,Bt=e=>(g.getCombinedModifierFlags(e)&g.ModifierFlags.Export)!==0,Vt=e=>e.statements.flatMap(t=>{if(g.isExportAssignment(t)||g.isExportDeclaration(t)||Bt(t)){let n=e.getLineAndCharacterOfPosition(t.getStart(e)).line+1;return[{endLine:e.getLineAndCharacterOfPosition(t.getEnd()).line+1,startLine:n}]}return[]}),Ht=e=>e.split(`
`).flatMap((e,t)=>Ft.some(t=>t.test(e))?[t+1]:[]),Ut=async(e,t)=>{let n=s.join(e,t),r=await d(n,`utf8`);if(Nt.test(t)){let e=Ht(r);return{exportedRanges:[],hasExports:e.length>0,isSharedUtility:Mt.test(t)||Pt.test(t),isTest:At.test(t)||jt.test(t),isVueComponent:!0,vueContractLines:e}}let i=Vt(g.createSourceFile(n,r,g.ScriptTarget.Latest,!0,zt(n)));return{exportedRanges:i,hasExports:i.length>0,isSharedUtility:Mt.test(t),isTest:At.test(t)||jt.test(t),isVueComponent:!1,vueContractLines:[]}},Wt=(e,t)=>e!==void 0&&t.some(t=>e>=t.startLine&&e<=t.endLine),Gt=(e,t)=>e!==void 0&&t.some(t=>Math.abs(t-e)<=2),Kt=(e,t)=>{if(Lt.has(t.ruleId??``)){let e=t.ruleId===`@typescript-eslint/switch-exhaustiveness-check`;return{category:`control-flow-signal`,labels:[`control-flow-signal`,e?`non-exhaustive-switch`:`unnecessary-condition`],reason:e?`The switch does not cover every known TypeScript branch.`:`The condition is impossible or redundant according to the current TypeScript model.`,scoreDelta:0}}return Rt.has(t.ruleId??``)?{category:`method-binding-signal`,labels:[`method-binding-signal`,`unbound-method`],reason:`The method reference may run without the object instance it depends on.`,scoreDelta:1}:e.isTest?{category:`test-only`,labels:[`test-only`],reason:`Test-only type holes usually have lower migration urgency.`,scoreDelta:-2}:It.has(t.ruleId??``)&&Wt(t.line,e.exportedRanges)?{category:`exported-api`,labels:[`exported-api`],reason:`The finding sits inside an exported declaration and can leak outward.`,scoreDelta:4}:e.isVueComponent&&It.has(t.ruleId??``)&&Gt(t.line,e.vueContractLines)?{category:`vue-component-contract`,labels:[`vue-component-contract`],reason:`The finding appears near a Vue component contract and can leak through props, emits, or exposed bindings.`,scoreDelta:4}:e.isVueComponent&&e.isSharedUtility?{category:`shared-vue-component`,labels:[`shared-vue-component`],reason:`Shared Vue components can spread weak typing through reusable props and emits contracts.`,scoreDelta:2}:e.hasExports&&s.basename(t.file)===`index.ts`?{category:`public-entry`,labels:[`public-entry`],reason:`The file looks like a public entrypoint, so weak typing spreads quickly.`,scoreDelta:3}:e.isSharedUtility?{category:`shared-utility`,labels:[`shared-utility`],reason:`Shared utilities tend to amplify weak typing across multiple callers.`,scoreDelta:2}:{category:`internal`,labels:[`internal`],reason:`The finding appears to be internal implementation detail.`,scoreDelta:0}},qt=e=>e.clone().append({files:[`**/*.vue`],languageOptions:{parserOptions:{extraFileExtensions:[`.vue`],parser:p,projectService:!0,sourceType:`module`}},name:`productive-eslint/analyze-types-vue-parser`}).append({files:[`**/*.ts`,`**/*.tsx`,