oxlint-plugin-complexity
Advanced tools
| import { type ModuleAnalysisResult, type ModuleComplexityOptions } from './module/visitor.js'; | ||
| /** Standalone module complexity analysis (no linting context required). */ | ||
| export declare function analyzeModule(code: string, filename?: string, options?: ModuleComplexityOptions): ModuleAnalysisResult; | ||
| //# sourceMappingURL=analyze.d.ts.map |
| {"version":3,"file":"analyze.d.ts","sourceRoot":"","sources":["../src/analyze.ts"],"names":[],"mappings":"AAIA,OAAO,EAEL,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC7B,MAAM,qBAAqB,CAAC;AA6E7B,2EAA2E;AAC3E,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAAoB,EAC9B,OAAO,CAAC,EAAE,uBAAuB,GAChC,oBAAoB,CA4BtB"} |
| import { parseSync } from 'oxc-parser'; | ||
| import { walk } from 'estree-walker'; | ||
| import { createModuleAnalysisVisitor, } from './module/visitor.js'; | ||
| function createLineOffsetTable(code) { | ||
| const lineOffsets = [0]; | ||
| for (let i = 0; i < code.length; i++) { | ||
| if (code[i] === '\n') { | ||
| lineOffsets.push(i + 1); | ||
| } | ||
| } | ||
| return lineOffsets; | ||
| } | ||
| function offsetToLineCol(offset, lineOffsets) { | ||
| let lo = 0; | ||
| let hi = lineOffsets.length - 1; | ||
| while (lo < hi) { | ||
| const mid = (lo + hi + 1) >>> 1; | ||
| if (lineOffsets[mid] <= offset) | ||
| lo = mid; | ||
| else | ||
| hi = mid - 1; | ||
| } | ||
| return { line: lo + 1, column: offset - lineOffsets[lo] }; | ||
| } | ||
| /** Single-pass AST walk: adds parent/loc references and dispatches visitor handlers. */ | ||
| function walkAndDispatch(ast, code, visitor) { | ||
| const lineOffsets = createLineOffsetTable(code); | ||
| walk(ast, { | ||
| enter(node, parent) { | ||
| const esNode = node; | ||
| const raw = node; | ||
| if (typeof raw.start === 'number' && typeof raw.end === 'number') { | ||
| Object.defineProperty(esNode, 'loc', { | ||
| value: { | ||
| start: offsetToLineCol(raw.start, lineOffsets), | ||
| end: offsetToLineCol(raw.end, lineOffsets), | ||
| }, | ||
| writable: true, | ||
| enumerable: false, | ||
| configurable: true, | ||
| }); | ||
| } | ||
| Object.defineProperty(esNode, 'parent', { | ||
| value: parent, | ||
| writable: true, | ||
| enumerable: false, | ||
| configurable: true, | ||
| }); | ||
| visitor[esNode.type]?.(esNode); | ||
| visitor['*']?.(esNode); | ||
| }, | ||
| leave(node) { | ||
| const esNode = node; | ||
| visitor[`${esNode.type}:exit`]?.(esNode); | ||
| visitor['*:exit']?.(esNode); | ||
| }, | ||
| }); | ||
| } | ||
| function createLibraryContext(code) { | ||
| return { | ||
| sourceCode: { | ||
| text: code, | ||
| getText: () => code, | ||
| scopeManager: null, | ||
| getScope: () => null, | ||
| }, | ||
| options: [], | ||
| report: () => { }, | ||
| }; | ||
| } | ||
| /** Standalone module complexity analysis (no linting context required). */ | ||
| export function analyzeModule(code, filename = 'module.js', options) { | ||
| const { program, errors } = parseSync(filename, code); | ||
| if (errors.length > 0) { | ||
| throw new Error(`Parse errors in "${filename}": ${errors.map((e) => e.message).join(', ')}`); | ||
| } | ||
| const ast = program; | ||
| let result; | ||
| const visitor = createModuleAnalysisVisitor(createLibraryContext(code), (r) => { | ||
| result = r; | ||
| }, undefined, options); | ||
| walkAndDispatch(ast, code, visitor); | ||
| if (!result) { | ||
| throw new Error('Module analysis did not produce a result'); | ||
| } | ||
| return result; | ||
| } | ||
| //# sourceMappingURL=analyze.js.map |
| {"version":3,"file":"analyze.js","sourceRoot":"","sources":["../src/analyze.ts"],"names":[],"mappings":"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"} |
| /** | ||
| * Raw operator/operand frequency maps collected during AST traversal. | ||
| */ | ||
| export interface HalsteadCounts { | ||
| /** Operator identifier -> occurrence count */ | ||
| operators: Map<string, number>; | ||
| /** Operand identifier -> occurrence count */ | ||
| operands: Map<string, number>; | ||
| } | ||
| /** | ||
| * Computed Halstead complexity metrics derived from operator/operand counts. | ||
| * | ||
| * Formulas (Halstead, 1977): | ||
| * length = N1 + N2 | ||
| * vocabulary = n1 + n2 | ||
| * volume = length * log2(vocabulary) | ||
| * difficulty = (n1 / 2) * (N2 / n2) | ||
| * effort = difficulty * volume | ||
| * bugs = volume / 3000 | ||
| * time = effort / 18 (seconds) | ||
| */ | ||
| export interface HalsteadMetrics { | ||
| /** Unique operator count */ | ||
| n1: number; | ||
| /** Unique operand count */ | ||
| n2: number; | ||
| /** Total operator occurrences */ | ||
| N1: number; | ||
| /** Total operand occurrences */ | ||
| N2: number; | ||
| /** Program length: N1 + N2 */ | ||
| length: number; | ||
| /** Program vocabulary: n1 + n2 */ | ||
| vocabulary: number; | ||
| /** Program volume: length * log2(vocabulary) */ | ||
| volume: number; | ||
| /** Difficulty: (n1/2) * (N2/n2) */ | ||
| difficulty: number; | ||
| /** Effort: difficulty * volume */ | ||
| effort: number; | ||
| /** Estimated bugs: volume / 3000 */ | ||
| bugs: number; | ||
| /** Estimated time to understand (seconds): effort / 18 */ | ||
| time: number; | ||
| } | ||
| /** Increment a count in a Map by a given amount. */ | ||
| export declare function incrementCount(map: Map<string, number>, key: string, amount?: number): void; | ||
| /** | ||
| * Calculate Halstead metrics from raw operator/operand counts. | ||
| * Pure math -- no AST dependency. | ||
| */ | ||
| export declare function calculateHalsteadMetrics(counts: HalsteadCounts): HalsteadMetrics; | ||
| export declare function createHalsteadCounts(): HalsteadCounts; | ||
| /** Merge source counts into target (mutates target). */ | ||
| export declare function mergeHalsteadCounts(target: HalsteadCounts, source: HalsteadCounts): void; | ||
| //# sourceMappingURL=calculate.d.ts.map |
| {"version":3,"file":"calculate.d.ts","sourceRoot":"","sources":["../../src/halstead/calculate.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,8CAA8C;IAC9C,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,6CAA6C;IAC7C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;CACd;AAED,oDAAoD;AACpD,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI,CAE9F;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,cAAc,GAAG,eAAe,CAehF;AAED,wBAAgB,oBAAoB,IAAI,cAAc,CAErD;AAED,wDAAwD;AACxD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAOxF"} |
| /** Increment a count in a Map by a given amount. */ | ||
| export function incrementCount(map, key, amount = 1) { | ||
| map.set(key, (map.get(key) ?? 0) + amount); | ||
| } | ||
| /** | ||
| * Calculate Halstead metrics from raw operator/operand counts. | ||
| * Pure math -- no AST dependency. | ||
| */ | ||
| export function calculateHalsteadMetrics(counts) { | ||
| const n1 = counts.operators.size; | ||
| const n2 = counts.operands.size; | ||
| const N1 = sumValues(counts.operators); | ||
| const N2 = sumValues(counts.operands); | ||
| const length = N1 + N2; | ||
| const vocabulary = n1 + n2; | ||
| const volume = vocabulary > 0 ? length * Math.log2(vocabulary) : 0; | ||
| const difficulty = n2 > 0 ? (n1 / 2) * (N2 / n2) : 0; | ||
| const effort = difficulty * volume; | ||
| const bugs = volume / 3000; | ||
| const time = effort / 18; | ||
| return { n1, n2, N1, N2, length, vocabulary, volume, difficulty, effort, bugs, time }; | ||
| } | ||
| export function createHalsteadCounts() { | ||
| return { operators: new Map(), operands: new Map() }; | ||
| } | ||
| /** Merge source counts into target (mutates target). */ | ||
| export function mergeHalsteadCounts(target, source) { | ||
| for (const [key, count] of source.operators) { | ||
| incrementCount(target.operators, key, count); | ||
| } | ||
| for (const [key, count] of source.operands) { | ||
| incrementCount(target.operands, key, count); | ||
| } | ||
| } | ||
| function sumValues(map) { | ||
| let total = 0; | ||
| for (const count of map.values()) { | ||
| total += count; | ||
| } | ||
| return total; | ||
| } | ||
| //# sourceMappingURL=calculate.js.map |
| {"version":3,"file":"calculate.js","sourceRoot":"","sources":["../../src/halstead/calculate.ts"],"names":[],"mappings":"AA+CA,oDAAoD;AACpD,MAAM,UAAU,cAAc,CAAC,GAAwB,EAAE,GAAW,EAAE,SAAiB,CAAC;IACtF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CAAC,MAAsB;IAC7D,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;IACjC,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;IAChC,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,CAAC;IACvB,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,IAAI,GAAG,MAAM,GAAG,EAAE,CAAC;IAEzB,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxF,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;AACvD,CAAC;AAED,wDAAwD;AACxD,MAAM,UAAU,mBAAmB,CAAC,MAAsB,EAAE,MAAsB;IAChF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QAC5C,cAAc,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC3C,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAwB;IACzC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;QACjC,KAAK,IAAI,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"} |
| export type { HalsteadCounts, HalsteadMetrics } from './types.js'; | ||
| export { calculateHalsteadMetrics, createHalsteadCounts, incrementCount, mergeHalsteadCounts, } from './calculate.js'; | ||
| export { createHalsteadVisitorHandlers } from './visitor.js'; | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/halstead/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAClE,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC"} |
| export { calculateHalsteadMetrics, createHalsteadCounts, incrementCount, mergeHalsteadCounts, } from './calculate.js'; | ||
| export { createHalsteadVisitorHandlers } from './visitor.js'; | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/halstead/index.ts"],"names":[],"mappings":"AACA,OAAO,EACL,wBAAwB,EACxB,oBAAoB,EACpB,cAAc,EACd,mBAAmB,GACpB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,6BAA6B,EAAE,MAAM,cAAc,CAAC"} |
| /** | ||
| * Raw operator/operand frequency maps collected during AST traversal. | ||
| */ | ||
| export interface HalsteadCounts { | ||
| /** Operator identifier -> occurrence count */ | ||
| operators: Map<string, number>; | ||
| /** Operand identifier -> occurrence count */ | ||
| operands: Map<string, number>; | ||
| } | ||
| /** | ||
| * Computed Halstead complexity metrics derived from operator/operand counts. | ||
| * | ||
| * Formulas (Halstead, 1977): | ||
| * length = N1 + N2 | ||
| * vocabulary = n1 + n2 | ||
| * volume = length * log2(vocabulary) | ||
| * difficulty = (n1 / 2) * (N2 / n2) | ||
| * effort = difficulty * volume | ||
| * bugs = volume / 3000 | ||
| * time = effort / 18 (seconds) | ||
| */ | ||
| export interface HalsteadMetrics { | ||
| /** Unique operator count */ | ||
| n1: number; | ||
| /** Unique operand count */ | ||
| n2: number; | ||
| /** Total operator occurrences */ | ||
| N1: number; | ||
| /** Total operand occurrences */ | ||
| N2: number; | ||
| /** Program length: N1 + N2 */ | ||
| length: number; | ||
| /** Program vocabulary: n1 + n2 */ | ||
| vocabulary: number; | ||
| /** Program volume: length * log2(vocabulary) */ | ||
| volume: number; | ||
| /** Difficulty: (n1/2) * (N2/n2) */ | ||
| difficulty: number; | ||
| /** Effort: difficulty * volume */ | ||
| effort: number; | ||
| /** Estimated bugs: volume / 3000 */ | ||
| bugs: number; | ||
| /** Estimated time to understand (seconds): effort / 18 */ | ||
| time: number; | ||
| } | ||
| //# sourceMappingURL=types.d.ts.map |
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/halstead/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,8CAA8C;IAC9C,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,6CAA6C;IAC7C,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B,4BAA4B;IAC5B,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,EAAE,EAAE,MAAM,CAAC;IACX,iCAAiC;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,gCAAgC;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,8BAA8B;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,kCAAkC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,gDAAgD;IAChD,MAAM,EAAE,MAAM,CAAC;IACf,mCAAmC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,0DAA0D;IAC1D,IAAI,EAAE,MAAM,CAAC;CACd"} |
| export {}; | ||
| //# sourceMappingURL=types.js.map |
| {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/halstead/types.ts"],"names":[],"mappings":""} |
| /** | ||
| * Halstead operator/operand classification for JavaScript/TypeScript AST nodes. | ||
| * | ||
| * Classification based on escomplex's es5.js (MIT), extended for modern JS/TS. | ||
| */ | ||
| import type { ESTreeNode } from '../types.js'; | ||
| import type { HalsteadCounts } from './calculate.js'; | ||
| export interface HalsteadVisitorCallbacks { | ||
| onFunctionEnter?: () => void; | ||
| onFunctionExit?: (counts: HalsteadCounts) => void; | ||
| } | ||
| /** | ||
| * Create visitor handlers that classify AST nodes into Halstead operators and operands. | ||
| * | ||
| * Maintains a scope stack mirroring function boundaries, plus a module-level accumulator | ||
| * that always receives every operator/operand. | ||
| */ | ||
| export declare function createHalsteadVisitorHandlers(callbacks?: HalsteadVisitorCallbacks): { | ||
| handlers: Record<string, (node: ESTreeNode) => void>; | ||
| moduleCounts: HalsteadCounts; | ||
| }; | ||
| //# sourceMappingURL=visitor.d.ts.map |
| {"version":3,"file":"visitor.d.ts","sourceRoot":"","sources":["../../src/halstead/visitor.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,MAAM,WAAW,wBAAwB;IACvC,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAgED;;;;;GAKG;AAEH,wBAAgB,6BAA6B,CAAC,SAAS,CAAC,EAAE,wBAAwB,GAAG;IACnF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC,CAAC;IACrD,YAAY,EAAE,cAAc,CAAC;CAC9B,CAuKA"} |
| import { createHalsteadCounts, incrementCount } from './calculate.js'; | ||
| /** Extract the operator string from a node with an `operator` property. */ | ||
| function getNodeOperator(node) { | ||
| return node.operator; | ||
| } | ||
| /** Check if a node is a non-computed key/property of its parent. */ | ||
| function isNonComputedKeyOf(node, parentType) { | ||
| const parent = node.parent; | ||
| if (parent?.type !== parentType) | ||
| return false; | ||
| const keyed = parent; | ||
| if (keyed.computed) | ||
| return false; | ||
| return keyed.key === node || keyed.property === node; | ||
| } | ||
| /** Declaration-site parent types mapped to their identifier-holding property. */ | ||
| const DECLARATION_PARENTS = [ | ||
| { type: 'VariableDeclarator', prop: 'id' }, | ||
| { type: 'ImportSpecifier', prop: 'local' }, | ||
| { type: 'ImportDefaultSpecifier', prop: 'local' }, | ||
| { type: 'ImportNamespaceSpecifier', prop: 'local' }, | ||
| { type: 'CatchClause', prop: 'param' }, | ||
| { type: 'LabeledStatement', prop: 'label' }, | ||
| ]; | ||
| /** | ||
| * Check if an Identifier is at a declaration site (should be skipped as operand). | ||
| */ | ||
| // eslint-disable-next-line complexity/complexity -- Type-dispatch across many AST parent types | ||
| function isDeclarationIdentifier(node) { | ||
| const parent = node.parent; | ||
| if (!parent) | ||
| return false; | ||
| const n = node; | ||
| // Function declaration/expression: check id and params | ||
| if (parent.type === 'FunctionDeclaration' || parent.type === 'FunctionExpression') { | ||
| const fn = parent; | ||
| return fn.id?.name === n.name || (fn.params?.includes(node) ?? false); | ||
| } | ||
| // Arrow function: check params | ||
| if (parent.type === 'ArrowFunctionExpression') { | ||
| const arrow = parent; | ||
| return arrow.params?.includes(node) ?? false; | ||
| } | ||
| // Class declaration/expression: check id | ||
| if (parent.type === 'ClassDeclaration' || parent.type === 'ClassExpression') { | ||
| const cls = parent; | ||
| return cls.id?.name === n.name; | ||
| } | ||
| // Table-driven check for simple "is node === parent.prop" patterns | ||
| for (const { type, prop } of DECLARATION_PARENTS) { | ||
| if (parent.type === type) { | ||
| return parent[prop] === node; | ||
| } | ||
| } | ||
| return false; | ||
| } | ||
| /** | ||
| * Create visitor handlers that classify AST nodes into Halstead operators and operands. | ||
| * | ||
| * Maintains a scope stack mirroring function boundaries, plus a module-level accumulator | ||
| * that always receives every operator/operand. | ||
| */ | ||
| // eslint-disable-next-line complexity/complexity -- Visitor factory pattern requires many nested handlers | ||
| export function createHalsteadVisitorHandlers(callbacks) { | ||
| const moduleCounts = createHalsteadCounts(); | ||
| const scopeStack = []; | ||
| function currentScope() { | ||
| return scopeStack[scopeStack.length - 1]; | ||
| } | ||
| function addOperator(name) { | ||
| incrementCount(moduleCounts.operators, name); | ||
| const scope = currentScope(); | ||
| if (scope) { | ||
| incrementCount(scope.operators, name); | ||
| } | ||
| } | ||
| function addOperand(name) { | ||
| incrementCount(moduleCounts.operands, name); | ||
| const scope = currentScope(); | ||
| if (scope) { | ||
| incrementCount(scope.operands, name); | ||
| } | ||
| } | ||
| function enterFunction() { | ||
| scopeStack.push(createHalsteadCounts()); | ||
| callbacks?.onFunctionEnter?.(); | ||
| } | ||
| function exitFunction() { | ||
| const scope = scopeStack.pop(); | ||
| if (scope) { | ||
| callbacks?.onFunctionExit?.(scope); | ||
| } | ||
| } | ||
| /** Helper to create a simple handler that adds a fixed operator. */ | ||
| function operatorHandler(name) { | ||
| return () => addOperator(name); | ||
| } | ||
| /** Helper to create a handler that reads the operator from the node. */ | ||
| function nodeOperatorHandler() { | ||
| return (node) => addOperator(getNodeOperator(node)); | ||
| } | ||
| const handlers = { | ||
| // --- Function boundaries --- | ||
| FunctionDeclaration(node) { | ||
| enterFunction(); | ||
| addOperator('function'); | ||
| const fn = node; | ||
| if (fn.id?.name) | ||
| addOperand(fn.id.name); | ||
| }, | ||
| 'FunctionDeclaration:exit': () => exitFunction(), | ||
| FunctionExpression(node) { | ||
| enterFunction(); | ||
| addOperator('function'); | ||
| const fn = node; | ||
| if (fn.id?.name) | ||
| addOperand(fn.id.name); | ||
| }, | ||
| 'FunctionExpression:exit': () => exitFunction(), | ||
| ArrowFunctionExpression() { | ||
| enterFunction(); | ||
| addOperator('=>'); | ||
| }, | ||
| 'ArrowFunctionExpression:exit': () => exitFunction(), | ||
| // --- Control flow operators --- | ||
| IfStatement: operatorHandler('if'), | ||
| 'IfStatement:exit'(node) { | ||
| const ifNode = node; | ||
| if (ifNode.alternate) | ||
| addOperator('else'); | ||
| }, | ||
| ForStatement: operatorHandler('for'), | ||
| ForInStatement: operatorHandler('forin'), | ||
| ForOfStatement: operatorHandler('forof'), | ||
| WhileStatement: operatorHandler('while'), | ||
| DoWhileStatement: operatorHandler('dowhile'), | ||
| SwitchStatement: operatorHandler('switch'), | ||
| SwitchCase(node) { | ||
| const sc = node; | ||
| addOperator(sc.test !== null ? 'case' : 'default'); | ||
| }, | ||
| CatchClause: operatorHandler('catch'), | ||
| BreakStatement: operatorHandler('break'), | ||
| ContinueStatement: operatorHandler('continue'), | ||
| ReturnStatement: operatorHandler('return'), | ||
| ThrowStatement: operatorHandler('throw'), | ||
| // --- Expressions --- | ||
| NewExpression: operatorHandler('new'), | ||
| ClassDeclaration: operatorHandler('class'), | ||
| ClassExpression: operatorHandler('class'), | ||
| ImportDeclaration: operatorHandler('import'), | ||
| ExportNamedDeclaration: operatorHandler('export'), | ||
| ExportDefaultDeclaration: operatorHandler('export'), | ||
| AwaitExpression: operatorHandler('await'), | ||
| YieldExpression: operatorHandler('yield'), | ||
| // Binary, logical, assignment, unary, update -- use the node's operator string | ||
| BinaryExpression: nodeOperatorHandler(), | ||
| LogicalExpression: nodeOperatorHandler(), | ||
| AssignmentExpression: nodeOperatorHandler(), | ||
| UnaryExpression: nodeOperatorHandler(), | ||
| UpdateExpression: nodeOperatorHandler(), | ||
| CallExpression: operatorHandler('()'), | ||
| ArrayExpression: operatorHandler('[]'), | ||
| ObjectExpression: operatorHandler('{}'), | ||
| MemberExpression(node) { | ||
| const member = node; | ||
| addOperator(member.computed ? '[]' : member.optional ? '?.' : '.'); | ||
| }, | ||
| Property: operatorHandler(':'), | ||
| ConditionalExpression: operatorHandler('?:'), | ||
| VariableDeclaration(node) { | ||
| const decl = node; | ||
| addOperator(decl.kind); | ||
| }, | ||
| VariableDeclarator(node) { | ||
| const declarator = node; | ||
| if (declarator.init !== null && declarator.init !== undefined) { | ||
| addOperator('='); | ||
| } | ||
| const id = declarator.id; | ||
| if (id.type === 'Identifier' && id.name) { | ||
| addOperand(id.name); | ||
| } | ||
| }, | ||
| TemplateLiteral: operatorHandler('`'), | ||
| SpreadElement: operatorHandler('...'), | ||
| RestElement: operatorHandler('...'), | ||
| // --- Operands --- | ||
| Identifier(node) { | ||
| if (isDeclarationIdentifier(node)) | ||
| return; | ||
| if (isNonComputedKeyOf(node, 'MemberExpression')) | ||
| return; | ||
| if (isNonComputedKeyOf(node, 'Property')) | ||
| return; | ||
| if (isNonComputedKeyOf(node, 'MethodDefinition')) | ||
| return; | ||
| addOperand(node.name); | ||
| }, | ||
| Literal(node) { | ||
| const lit = node; | ||
| addOperand(lit.raw ?? String(lit.value)); | ||
| }, | ||
| ThisExpression() { | ||
| addOperand('this'); | ||
| }, | ||
| TemplateElement(node) { | ||
| const elem = node; | ||
| if (elem.value.raw) { | ||
| addOperand(elem.value.raw); | ||
| } | ||
| }, | ||
| }; | ||
| return { handlers, moduleCounts }; | ||
| } | ||
| //# sourceMappingURL=visitor.js.map |
| {"version":3,"file":"visitor.js","sourceRoot":"","sources":["../../src/halstead/visitor.ts"],"names":[],"mappings":"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"} |
| /** | ||
| * Halstead operator/operand classification for JavaScript/TypeScript AST nodes. | ||
| * Based on escomplex's es5.js (MIT), extended for modern JS/TS. | ||
| */ | ||
| import type { ESTreeNode } from '../types.js'; | ||
| import type { HalsteadCounts } from './halstead.js'; | ||
| export interface HalsteadVisitorCallbacks { | ||
| onFunctionEnter?: () => void; | ||
| onFunctionExit?: (counts: HalsteadCounts) => void; | ||
| } | ||
| export declare function createHalsteadVisitorHandlers(callbacks?: HalsteadVisitorCallbacks): { | ||
| handlers: Record<string, (node: ESTreeNode) => void>; | ||
| moduleCounts: HalsteadCounts; | ||
| }; | ||
| //# sourceMappingURL=halstead-visitor.d.ts.map |
| {"version":3,"file":"halstead-visitor.d.ts","sourceRoot":"","sources":["../../src/module/halstead-visitor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAGpD,MAAM,WAAW,wBAAwB;IACvC,eAAe,CAAC,EAAE,MAAM,IAAI,CAAC;IAC7B,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,cAAc,KAAK,IAAI,CAAC;CACnD;AAwDD,wBAAgB,6BAA6B,CAAC,SAAS,CAAC,EAAE,wBAAwB,GAAG;IACnF,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,IAAI,CAAC,CAAC;IACrD,YAAY,EAAE,cAAc,CAAC;CAC9B,CA4JA"} |
| import { createHalsteadCounts, incrementCount } from './halstead.js'; | ||
| function getNodeOperator(node) { | ||
| return node.operator; | ||
| } | ||
| /** Caller must pre-check that parent type is MemberExpression, Property, or MethodDefinition. */ | ||
| function isNonComputedKeyOf(node) { | ||
| const parent = node.parent; | ||
| if (!parent) | ||
| return false; | ||
| const keyed = parent; | ||
| if (keyed.computed) | ||
| return false; | ||
| return keyed.key === node || keyed.property === node; | ||
| } | ||
| const DECLARATION_PARENTS = new Map([ | ||
| ['VariableDeclarator', 'id'], | ||
| ['ImportSpecifier', 'local'], | ||
| ['ImportDefaultSpecifier', 'local'], | ||
| ['ImportNamespaceSpecifier', 'local'], | ||
| ['CatchClause', 'param'], | ||
| ['LabeledStatement', 'label'], | ||
| ]); | ||
| /** Skip identifiers at declaration sites (they are not operands). */ | ||
| // eslint-disable-next-line complexity/complexity -- Type-dispatch across many AST parent types | ||
| function isDeclarationIdentifier(node) { | ||
| const parent = node.parent; | ||
| if (!parent) | ||
| return false; | ||
| const n = node; | ||
| if (parent.type === 'FunctionDeclaration' || parent.type === 'FunctionExpression') { | ||
| const fn = parent; | ||
| return fn.id?.name === n.name || (fn.params?.includes(node) ?? false); | ||
| } | ||
| if (parent.type === 'ArrowFunctionExpression') { | ||
| const arrow = parent; | ||
| return arrow.params?.includes(node) ?? false; | ||
| } | ||
| if (parent.type === 'ClassDeclaration' || parent.type === 'ClassExpression') { | ||
| const cls = parent; | ||
| return cls.id?.name === n.name; | ||
| } | ||
| const prop = DECLARATION_PARENTS.get(parent.type); | ||
| if (prop) { | ||
| return parent[prop] === node; | ||
| } | ||
| return false; | ||
| } | ||
| // eslint-disable-next-line complexity/complexity -- Visitor factory pattern requires many nested handlers | ||
| export function createHalsteadVisitorHandlers(callbacks) { | ||
| const moduleCounts = createHalsteadCounts(); | ||
| const scopeStack = []; | ||
| function currentScope() { | ||
| return scopeStack[scopeStack.length - 1]; | ||
| } | ||
| function addCount(kind, name) { | ||
| incrementCount(moduleCounts[kind], name); | ||
| const scope = currentScope(); | ||
| if (scope) { | ||
| incrementCount(scope[kind], name); | ||
| } | ||
| } | ||
| function addOperator(name) { | ||
| addCount('operators', name); | ||
| } | ||
| function addOperand(name) { | ||
| addCount('operands', name); | ||
| } | ||
| function enterFunction() { | ||
| scopeStack.push(createHalsteadCounts()); | ||
| callbacks?.onFunctionEnter?.(); | ||
| } | ||
| function exitFunction() { | ||
| const scope = scopeStack.pop(); | ||
| if (scope) { | ||
| callbacks?.onFunctionExit?.(scope); | ||
| } | ||
| } | ||
| function operatorHandler(name) { | ||
| return () => addOperator(name); | ||
| } | ||
| function nodeOperatorHandler() { | ||
| return (node) => addOperator(getNodeOperator(node)); | ||
| } | ||
| function handleNamedFunction(node) { | ||
| enterFunction(); | ||
| addOperator('function'); | ||
| const fn = node; | ||
| if (fn.id?.name) | ||
| addOperand(fn.id.name); | ||
| } | ||
| const handlers = { | ||
| FunctionDeclaration: handleNamedFunction, | ||
| 'FunctionDeclaration:exit': () => exitFunction(), | ||
| FunctionExpression: handleNamedFunction, | ||
| 'FunctionExpression:exit': () => exitFunction(), | ||
| ArrowFunctionExpression() { | ||
| enterFunction(); | ||
| addOperator('=>'); | ||
| }, | ||
| 'ArrowFunctionExpression:exit': () => exitFunction(), | ||
| IfStatement: operatorHandler('if'), | ||
| 'IfStatement:exit'(node) { | ||
| const ifNode = node; | ||
| if (ifNode.alternate) | ||
| addOperator('else'); | ||
| }, | ||
| ForStatement: operatorHandler('for'), | ||
| ForInStatement: operatorHandler('forin'), | ||
| ForOfStatement: operatorHandler('forof'), | ||
| WhileStatement: operatorHandler('while'), | ||
| DoWhileStatement: operatorHandler('dowhile'), | ||
| SwitchStatement: operatorHandler('switch'), | ||
| SwitchCase(node) { | ||
| const sc = node; | ||
| addOperator(sc.test !== null ? 'case' : 'default'); | ||
| }, | ||
| CatchClause: operatorHandler('catch'), | ||
| BreakStatement: operatorHandler('break'), | ||
| ContinueStatement: operatorHandler('continue'), | ||
| ReturnStatement: operatorHandler('return'), | ||
| ThrowStatement: operatorHandler('throw'), | ||
| NewExpression: operatorHandler('new'), | ||
| ClassDeclaration: operatorHandler('class'), | ||
| ClassExpression: operatorHandler('class'), | ||
| ImportDeclaration: operatorHandler('import'), | ||
| ExportNamedDeclaration: operatorHandler('export'), | ||
| ExportDefaultDeclaration: operatorHandler('export'), | ||
| AwaitExpression: operatorHandler('await'), | ||
| YieldExpression: operatorHandler('yield'), | ||
| BinaryExpression: nodeOperatorHandler(), | ||
| LogicalExpression: nodeOperatorHandler(), | ||
| AssignmentExpression: nodeOperatorHandler(), | ||
| UnaryExpression: nodeOperatorHandler(), | ||
| UpdateExpression: nodeOperatorHandler(), | ||
| CallExpression: operatorHandler('()'), | ||
| ArrayExpression: operatorHandler('[]'), | ||
| ObjectExpression: operatorHandler('{}'), | ||
| MemberExpression(node) { | ||
| const member = node; | ||
| addOperator(member.computed ? '[]' : member.optional ? '?.' : '.'); | ||
| }, | ||
| Property: operatorHandler(':'), | ||
| ConditionalExpression: operatorHandler('?:'), | ||
| VariableDeclaration(node) { | ||
| const decl = node; | ||
| addOperator(decl.kind); | ||
| }, | ||
| VariableDeclarator(node) { | ||
| const declarator = node; | ||
| if (declarator.init !== null && declarator.init !== undefined) { | ||
| addOperator('='); | ||
| } | ||
| const id = declarator.id; | ||
| if (id.type === 'Identifier' && id.name) { | ||
| addOperand(id.name); | ||
| } | ||
| }, | ||
| TemplateLiteral: operatorHandler('`'), | ||
| SpreadElement: operatorHandler('...'), | ||
| RestElement: operatorHandler('...'), | ||
| Identifier(node) { | ||
| if (isDeclarationIdentifier(node)) | ||
| return; | ||
| const pt = node.parent?.type; | ||
| if (pt === 'MemberExpression' || pt === 'Property' || pt === 'MethodDefinition') { | ||
| if (isNonComputedKeyOf(node)) | ||
| return; | ||
| } | ||
| addOperand(node.name); | ||
| }, | ||
| Literal(node) { | ||
| const lit = node; | ||
| addOperand(lit.raw ?? String(lit.value)); | ||
| }, | ||
| ThisExpression() { | ||
| addOperand('this'); | ||
| }, | ||
| TemplateElement(node) { | ||
| const elem = node; | ||
| if (elem.value.raw) { | ||
| addOperand(elem.value.raw); | ||
| } | ||
| }, | ||
| }; | ||
| return { handlers, moduleCounts }; | ||
| } | ||
| //# sourceMappingURL=halstead-visitor.js.map |
| {"version":3,"file":"halstead-visitor.js","sourceRoot":"","sources":["../../src/module/halstead-visitor.ts"],"names":[],"mappings":"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"} |
| export interface HalsteadCounts { | ||
| operators: Map<string, number>; | ||
| operands: Map<string, number>; | ||
| } | ||
| /** | ||
| * Halstead metrics derived from operator/operand counts. | ||
| * | ||
| * Formulas (Halstead, 1977): | ||
| * length = N1 + N2 | ||
| * vocabulary = n1 + n2 | ||
| * volume = length * log2(vocabulary) | ||
| * difficulty = (n1 / 2) * (N2 / n2) | ||
| * effort = difficulty * volume | ||
| * bugs = volume / 3000 | ||
| * time = effort / 18 (seconds) | ||
| */ | ||
| export interface HalsteadMetrics { | ||
| n1: number; | ||
| n2: number; | ||
| N1: number; | ||
| N2: number; | ||
| length: number; | ||
| vocabulary: number; | ||
| volume: number; | ||
| difficulty: number; | ||
| effort: number; | ||
| bugs: number; | ||
| time: number; | ||
| } | ||
| export declare function incrementCount(map: Map<string, number>, key: string, amount?: number): void; | ||
| export declare function calculateHalsteadMetrics(counts: HalsteadCounts): HalsteadMetrics; | ||
| export declare function createHalsteadCounts(): HalsteadCounts; | ||
| export declare function mergeHalsteadCounts(target: HalsteadCounts, source: HalsteadCounts): void; | ||
| //# sourceMappingURL=halstead.d.ts.map |
| {"version":3,"file":"halstead.d.ts","sourceRoot":"","sources":["../../src/module/halstead.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC/B,QAAQ,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;CACd;AAED,wBAAgB,cAAc,CAAC,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,GAAE,MAAU,GAAG,IAAI,CAE9F;AAED,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,cAAc,GAAG,eAAe,CAehF;AAED,wBAAgB,oBAAoB,IAAI,cAAc,CAErD;AAED,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,cAAc,EAAE,MAAM,EAAE,cAAc,GAAG,IAAI,CAOxF"} |
| export function incrementCount(map, key, amount = 1) { | ||
| map.set(key, (map.get(key) ?? 0) + amount); | ||
| } | ||
| export function calculateHalsteadMetrics(counts) { | ||
| const n1 = counts.operators.size; | ||
| const n2 = counts.operands.size; | ||
| const N1 = sumValues(counts.operators); | ||
| const N2 = sumValues(counts.operands); | ||
| const length = N1 + N2; | ||
| const vocabulary = n1 + n2; | ||
| const volume = vocabulary > 0 ? length * Math.log2(vocabulary) : 0; | ||
| const difficulty = n2 > 0 ? (n1 / 2) * (N2 / n2) : 0; | ||
| const effort = difficulty * volume; | ||
| const bugs = volume / 3000; | ||
| const time = effort / 18; | ||
| return { n1, n2, N1, N2, length, vocabulary, volume, difficulty, effort, bugs, time }; | ||
| } | ||
| export function createHalsteadCounts() { | ||
| return { operators: new Map(), operands: new Map() }; | ||
| } | ||
| export function mergeHalsteadCounts(target, source) { | ||
| for (const [key, count] of source.operators) { | ||
| incrementCount(target.operators, key, count); | ||
| } | ||
| for (const [key, count] of source.operands) { | ||
| incrementCount(target.operands, key, count); | ||
| } | ||
| } | ||
| function sumValues(map) { | ||
| let total = 0; | ||
| for (const count of map.values()) { | ||
| total += count; | ||
| } | ||
| return total; | ||
| } | ||
| //# sourceMappingURL=halstead.js.map |
| {"version":3,"file":"halstead.js","sourceRoot":"","sources":["../../src/module/halstead.ts"],"names":[],"mappings":"AA+BA,MAAM,UAAU,cAAc,CAAC,GAAwB,EAAE,GAAW,EAAE,SAAiB,CAAC;IACtF,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;AAC7C,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,MAAsB;IAC7D,MAAM,EAAE,GAAG,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC;IACjC,MAAM,EAAE,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC;IAChC,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;IACvC,MAAM,EAAE,GAAG,SAAS,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IAEtC,MAAM,MAAM,GAAG,EAAE,GAAG,EAAE,CAAC;IACvB,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,CAAC;IAC3B,MAAM,MAAM,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,MAAM,UAAU,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,MAAM,GAAG,UAAU,GAAG,MAAM,CAAC;IACnC,MAAM,IAAI,GAAG,MAAM,GAAG,IAAI,CAAC;IAC3B,MAAM,IAAI,GAAG,MAAM,GAAG,EAAE,CAAC;IAEzB,OAAO,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;AACxF,CAAC;AAED,MAAM,UAAU,oBAAoB;IAClC,OAAO,EAAE,SAAS,EAAE,IAAI,GAAG,EAAE,EAAE,QAAQ,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC;AACvD,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,MAAsB,EAAE,MAAsB;IAChF,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;QAC5C,cAAc,CAAC,MAAM,CAAC,SAAS,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC/C,CAAC;IACD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QAC3C,cAAc,CAAC,MAAM,CAAC,QAAQ,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;IAC9C,CAAC;AACH,CAAC;AAED,SAAS,SAAS,CAAC,GAAwB;IACzC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,KAAK,IAAI,GAAG,CAAC,MAAM,EAAE,EAAE,CAAC;QACjC,KAAK,IAAI,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"} |
| export type { FunctionMetrics, AggregateComplexity, ModuleAnalysisResult, ModuleComplexityOptions, } from './types.js'; | ||
| export { calculateMaintainabilityIndex, computeMIInputs } from './maintainability.js'; | ||
| export { createModuleAnalysisVisitor } from './visitor.js'; | ||
| //# sourceMappingURL=index.d.ts.map |
| {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/module/index.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,eAAe,EACf,mBAAmB,EACnB,oBAAoB,EACpB,uBAAuB,GACxB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,6BAA6B,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC"} |
| export { calculateMaintainabilityIndex, computeMIInputs } from './maintainability.js'; | ||
| export { createModuleAnalysisVisitor } from './visitor.js'; | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/module/index.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,6BAA6B,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACtF,OAAO,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC"} |
| import type { HalsteadMetrics } from '../halstead/types.js'; | ||
| /** | ||
| * Calculate the Maintainability Index using the formula from escomplex (SIG model): | ||
| * | ||
| * MI = 171 - 3.42 * ln(avgEffort) - 0.23 * ln(avgCyclomatic) - 16.2 * ln(avgLOC) | ||
| * MI_scaled = max(0, MI * 100 / 171) | ||
| * | ||
| * If there are zero functions, the module is treated as one "function" using | ||
| * module-level Halstead metrics and total LOC. | ||
| */ | ||
| export declare function calculateMaintainabilityIndex(avgEffort: number, avgCyclomatic: number, avgLOC: number): { | ||
| raw: number; | ||
| scaled: number; | ||
| }; | ||
| /** | ||
| * Compute average function metrics for MI calculation. | ||
| * If no functions, treats the whole module as one function. | ||
| */ | ||
| export declare function computeMIInputs(functionCount: number, totalCyclomatic: number, totalLOC: number, moduleHalstead: HalsteadMetrics, functionEffortSum: number): { | ||
| avgEffort: number; | ||
| avgCyclomatic: number; | ||
| avgLOC: number; | ||
| }; | ||
| //# sourceMappingURL=maintainability.d.ts.map |
| {"version":3,"file":"maintainability.d.ts","sourceRoot":"","sources":["../../src/module/maintainability.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D;;;;;;;;GAQG;AACH,wBAAgB,6BAA6B,CAC3C,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,GACb;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAUjC;AAED;;;GAGG;AACH,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,eAAe,EAC/B,iBAAiB,EAAE,MAAM,GACxB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAc9D"} |
| /** | ||
| * Calculate the Maintainability Index using the formula from escomplex (SIG model): | ||
| * | ||
| * MI = 171 - 3.42 * ln(avgEffort) - 0.23 * ln(avgCyclomatic) - 16.2 * ln(avgLOC) | ||
| * MI_scaled = max(0, MI * 100 / 171) | ||
| * | ||
| * If there are zero functions, the module is treated as one "function" using | ||
| * module-level Halstead metrics and total LOC. | ||
| */ | ||
| export function calculateMaintainabilityIndex(avgEffort, avgCyclomatic, avgLOC) { | ||
| // Guard against log(0) — use 1 as minimum for ln arguments | ||
| const lnEffort = Math.log(Math.max(avgEffort, 1)); | ||
| const lnCyclomatic = Math.log(Math.max(avgCyclomatic, 1)); | ||
| const lnLOC = Math.log(Math.max(avgLOC, 1)); | ||
| const raw = 171 - 3.42 * lnEffort - 0.23 * lnCyclomatic - 16.2 * lnLOC; | ||
| const scaled = Math.max(0, (raw * 100) / 171); | ||
| return { raw, scaled }; | ||
| } | ||
| /** | ||
| * Compute average function metrics for MI calculation. | ||
| * If no functions, treats the whole module as one function. | ||
| */ | ||
| export function computeMIInputs(functionCount, totalCyclomatic, totalLOC, moduleHalstead, functionEffortSum) { | ||
| if (functionCount === 0) { | ||
| return { | ||
| avgEffort: moduleHalstead.effort, | ||
| avgCyclomatic: 1, | ||
| avgLOC: Math.max(totalLOC, 1), | ||
| }; | ||
| } | ||
| return { | ||
| avgEffort: functionEffortSum / functionCount, | ||
| avgCyclomatic: totalCyclomatic / functionCount, | ||
| avgLOC: totalLOC / functionCount, | ||
| }; | ||
| } | ||
| //# sourceMappingURL=maintainability.js.map |
| {"version":3,"file":"maintainability.js","sourceRoot":"","sources":["../../src/module/maintainability.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,MAAM,UAAU,6BAA6B,CAC3C,SAAiB,EACjB,aAAqB,EACrB,MAAc;IAEd,2DAA2D;IAC3D,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC,CAAC,CAAC;IAClD,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,CAAC;IAC1D,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC;IAE5C,MAAM,GAAG,GAAG,GAAG,GAAG,IAAI,GAAG,QAAQ,GAAG,IAAI,GAAG,YAAY,GAAG,IAAI,GAAG,KAAK,CAAC;IACvE,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,GAAG,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,CAAC;IAE9C,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC;AACzB,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe,CAC7B,aAAqB,EACrB,eAAuB,EACvB,QAAgB,EAChB,cAA+B,EAC/B,iBAAyB;IAEzB,IAAI,aAAa,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO;YACL,SAAS,EAAE,cAAc,CAAC,MAAM;YAChC,aAAa,EAAE,CAAC;YAChB,MAAM,EAAE,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC;SAC9B,CAAC;IACJ,CAAC;IAED,OAAO;QACL,SAAS,EAAE,iBAAiB,GAAG,aAAa;QAC5C,aAAa,EAAE,eAAe,GAAG,aAAa;QAC9C,MAAM,EAAE,QAAQ,GAAG,aAAa;KACjC,CAAC;AACJ,CAAC"} |
| import type { HalsteadMetrics } from '../halstead/types.js'; | ||
| import type { ComplexityPoint } from '../types.js'; | ||
| export interface FunctionMetrics { | ||
| name: string; | ||
| lineStart: number; | ||
| lineEnd: number; | ||
| loc: number; | ||
| cyclomatic: number; | ||
| cognitive: number; | ||
| halstead: HalsteadMetrics; | ||
| cyclomaticPoints: ComplexityPoint[]; | ||
| cognitivePoints: ComplexityPoint[]; | ||
| } | ||
| export interface AggregateComplexity { | ||
| /** WMC-style total (sum of all function complexities) */ | ||
| sum: number; | ||
| /** Worst hotspot */ | ||
| max: number; | ||
| /** Average across functions */ | ||
| average: number; | ||
| /** Number of functions above the threshold */ | ||
| countAboveThreshold: number; | ||
| } | ||
| export interface ModuleAnalysisResult { | ||
| functions: FunctionMetrics[]; | ||
| /** Module-wide Halstead metrics (all operators/operands across the file) */ | ||
| halstead: HalsteadMetrics; | ||
| cyclomatic: AggregateComplexity; | ||
| cognitive: AggregateComplexity; | ||
| /** Raw Maintainability Index (0-171 scale) */ | ||
| maintainabilityIndex: number; | ||
| /** Scaled Maintainability Index (0-100 scale) */ | ||
| maintainabilityIndexScaled: number; | ||
| totalLOC: number; | ||
| functionCount: number; | ||
| } | ||
| export interface ModuleComplexityOptions { | ||
| /** Minimum MI (scaled 0-100). Default: 20 */ | ||
| maintainabilityIndex?: number; | ||
| /** Maximum aggregate cyclomatic. Default: 0 (disabled) */ | ||
| maxCyclomaticSum?: number; | ||
| /** Maximum aggregate cognitive. Default: 0 (disabled) */ | ||
| maxCognitiveSum?: number; | ||
| /** Threshold for countAboveThreshold (cyclomatic). Default: 10 */ | ||
| cyclomaticThreshold?: number; | ||
| /** Threshold for countAboveThreshold (cognitive). Default: 10 */ | ||
| cognitiveThreshold?: number; | ||
| /** How many hotspot functions to show in diagnostics. Default: 3 */ | ||
| topHotspots?: number; | ||
| } | ||
| //# sourceMappingURL=types.d.ts.map |
| {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/module/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,eAAe,CAAC;IAC1B,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,eAAe,EAAE,eAAe,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB;IAClC,yDAAyD;IACzD,GAAG,EAAE,MAAM,CAAC;IACZ,oBAAoB;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAC;IAChB,8CAA8C;IAC9C,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,4EAA4E;IAC5E,QAAQ,EAAE,eAAe,CAAC;IAC1B,UAAU,EAAE,mBAAmB,CAAC;IAChC,SAAS,EAAE,mBAAmB,CAAC;IAC/B,8CAA8C;IAC9C,oBAAoB,EAAE,MAAM,CAAC;IAC7B,iDAAiD;IACjD,0BAA0B,EAAE,MAAM,CAAC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,6CAA6C;IAC7C,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,0DAA0D;IAC1D,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yDAAyD;IACzD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kEAAkE;IAClE,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B,oEAAoE;IACpE,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB"} |
| export {}; | ||
| //# sourceMappingURL=types.js.map |
| {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/module/types.ts"],"names":[],"mappings":""} |
| import type { Context, ESTreeNode, Visitor, ComplexityPoint } from '../types.js'; | ||
| import { type CombinedComplexityResult } from '../combined-visitor.js'; | ||
| import { type HalsteadMetrics } from './halstead.js'; | ||
| export interface FunctionMetrics { | ||
| name: string; | ||
| lineStart: number; | ||
| lineEnd: number; | ||
| loc: number; | ||
| cyclomatic: number; | ||
| cognitive: number; | ||
| halstead: HalsteadMetrics; | ||
| cyclomaticPoints: ComplexityPoint[]; | ||
| cognitivePoints: ComplexityPoint[]; | ||
| } | ||
| export interface AggregateComplexity { | ||
| sum: number; | ||
| max: number; | ||
| average: number; | ||
| countAboveThreshold: number; | ||
| } | ||
| export interface MIDecomposition { | ||
| /** 3.42 * ln(avgEffort) — how much expression complexity lowers MI */ | ||
| effortTerm: number; | ||
| /** 0.23 * ln(avgCyclomatic) — how much branching lowers MI */ | ||
| cyclomaticTerm: number; | ||
| /** 16.2 * ln(avgLOC) — how much code length lowers MI */ | ||
| locTerm: number; | ||
| /** Which factor contributes the most to lowering MI */ | ||
| mainContributor: 'effort' | 'cyclomatic' | 'loc'; | ||
| } | ||
| export interface ModuleAnalysisResult { | ||
| functions: FunctionMetrics[]; | ||
| halstead: HalsteadMetrics; | ||
| cyclomatic: AggregateComplexity; | ||
| cognitive: AggregateComplexity; | ||
| /** Module complexity score (0-100, higher = more complex). Inverted Maintainability Index. */ | ||
| moduleComplexity: number; | ||
| complexityDecomposition: MIDecomposition; | ||
| totalLOC: number; | ||
| functionCount: number; | ||
| } | ||
| export interface ModuleComplexityOptions { | ||
| moduleComplexity?: number; | ||
| maxCyclomaticSum?: number; | ||
| maxCognitiveSum?: number; | ||
| cyclomaticThreshold?: number; | ||
| cognitiveThreshold?: number; | ||
| } | ||
| /** | ||
| * Module complexity = 100 - scaled Maintainability Index. | ||
| * | ||
| * MI = 171 - 3.42 * ln(avgEffort) - 0.23 * ln(avgCyclomatic) - 16.2 * ln(avgLOC) | ||
| * Scaled MI = max(0, MI * 100 / 171) | ||
| * Module complexity = 100 - Scaled MI (0 = trivial, 100 = maximally complex) | ||
| */ | ||
| export declare function calculateModuleComplexity(avgEffort: number, avgCyclomatic: number, avgLOC: number): { | ||
| score: number; | ||
| decomposition: MIDecomposition; | ||
| }; | ||
| /** If no functions, treats the whole module as one function. */ | ||
| export declare function computeMIInputs(functionCount: number, totalCyclomatic: number, totalLOC: number, moduleHalstead: HalsteadMetrics, functionEffortSum: number): { | ||
| avgEffort: number; | ||
| avgCyclomatic: number; | ||
| avgLOC: number; | ||
| }; | ||
| /** | ||
| * Creates a visitor that computes cyclomatic + cognitive + Halstead per function, | ||
| * then aggregates into module-level metrics with Maintainability Index on Program:exit. | ||
| */ | ||
| export declare function createModuleAnalysisVisitor(context: Context, onModuleAnalyzed: (result: ModuleAnalysisResult) => void, onFunctionAnalyzed?: (result: CombinedComplexityResult, node: ESTreeNode) => void, options?: ModuleComplexityOptions): Visitor; | ||
| //# sourceMappingURL=visitor.d.ts.map |
| {"version":3,"file":"visitor.d.ts","sourceRoot":"","sources":["../../src/module/visitor.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,UAAU,EAAgB,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE/F,OAAO,EAEL,KAAK,wBAAwB,EAC9B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EAIL,KAAK,eAAe,EACrB,MAAM,eAAe,CAAC;AAEvB,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,eAAe,CAAC;IAC1B,gBAAgB,EAAE,eAAe,EAAE,CAAC;IACpC,eAAe,EAAE,eAAe,EAAE,CAAC;CACpC;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,UAAU,EAAE,MAAM,CAAC;IACnB,8DAA8D;IAC9D,cAAc,EAAE,MAAM,CAAC;IACvB,yDAAyD;IACzD,OAAO,EAAE,MAAM,CAAC;IAChB,uDAAuD;IACvD,eAAe,EAAE,QAAQ,GAAG,YAAY,GAAG,KAAK,CAAC;CAClD;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,eAAe,EAAE,CAAC;IAC7B,QAAQ,EAAE,eAAe,CAAC;IAC1B,UAAU,EAAE,mBAAmB,CAAC;IAChC,SAAS,EAAE,mBAAmB,CAAC;IAC/B,8FAA8F;IAC9F,gBAAgB,EAAE,MAAM,CAAC;IACzB,uBAAuB,EAAE,eAAe,CAAC;IACzC,QAAQ,EAAE,MAAM,CAAC;IACjB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,uBAAuB;IACtC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,aAAa,EAAE,MAAM,EACrB,MAAM,EAAE,MAAM,GACb;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,eAAe,CAAA;CAAE,CAwBnD;AAED,gEAAgE;AAChE,wBAAgB,eAAe,CAC7B,aAAa,EAAE,MAAM,EACrB,eAAe,EAAE,MAAM,EACvB,QAAQ,EAAE,MAAM,EAChB,cAAc,EAAE,eAAe,EAC/B,iBAAiB,EAAE,MAAM,GACxB;IAAE,SAAS,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAc9D;AASD;;;GAGG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,OAAO,EAChB,gBAAgB,EAAE,CAAC,MAAM,EAAE,oBAAoB,KAAK,IAAI,EACxD,kBAAkB,CAAC,EAAE,CAAC,MAAM,EAAE,wBAAwB,EAAE,IAAI,EAAE,UAAU,KAAK,IAAI,EACjF,OAAO,CAAC,EAAE,uBAAuB,GAChC,OAAO,CAsHT"} |
| import { getFunctionName } from '../utils.js'; | ||
| import { createCombinedComplexityVisitor, } from '../combined-visitor.js'; | ||
| import { createHalsteadVisitorHandlers } from './halstead-visitor.js'; | ||
| import { calculateHalsteadMetrics, createHalsteadCounts, } from './halstead.js'; | ||
| /** | ||
| * Module complexity = 100 - scaled Maintainability Index. | ||
| * | ||
| * MI = 171 - 3.42 * ln(avgEffort) - 0.23 * ln(avgCyclomatic) - 16.2 * ln(avgLOC) | ||
| * Scaled MI = max(0, MI * 100 / 171) | ||
| * Module complexity = 100 - Scaled MI (0 = trivial, 100 = maximally complex) | ||
| */ | ||
| export function calculateModuleComplexity(avgEffort, avgCyclomatic, avgLOC) { | ||
| const lnEffort = Math.log(Math.max(avgEffort, 1)); | ||
| const lnCyclomatic = Math.log(Math.max(avgCyclomatic, 1)); | ||
| const lnLOC = Math.log(Math.max(avgLOC, 1)); | ||
| const effortTerm = 3.42 * lnEffort; | ||
| const cyclomaticTerm = 0.23 * lnCyclomatic; | ||
| const locTerm = 16.2 * lnLOC; | ||
| const rawMI = 171 - effortTerm - cyclomaticTerm - locTerm; | ||
| const scaledMI = Math.max(0, (rawMI * 100) / 171); | ||
| const score = Math.min(100, 100 - scaledMI); | ||
| let mainContributor = 'effort'; | ||
| if (locTerm >= effortTerm && locTerm >= cyclomaticTerm) { | ||
| mainContributor = 'loc'; | ||
| } | ||
| else if (cyclomaticTerm >= effortTerm) { | ||
| mainContributor = 'cyclomatic'; | ||
| } | ||
| return { | ||
| score, | ||
| decomposition: { effortTerm, cyclomaticTerm, locTerm, mainContributor }, | ||
| }; | ||
| } | ||
| /** If no functions, treats the whole module as one function. */ | ||
| export function computeMIInputs(functionCount, totalCyclomatic, totalLOC, moduleHalstead, functionEffortSum) { | ||
| if (functionCount === 0) { | ||
| return { | ||
| avgEffort: moduleHalstead.effort, | ||
| avgCyclomatic: 1, | ||
| avgLOC: Math.max(totalLOC, 1), | ||
| }; | ||
| } | ||
| return { | ||
| avgEffort: functionEffortSum / functionCount, | ||
| avgCyclomatic: totalCyclomatic / functionCount, | ||
| avgLOC: totalLOC / functionCount, | ||
| }; | ||
| } | ||
| /** | ||
| * Creates a visitor that computes cyclomatic + cognitive + Halstead per function, | ||
| * then aggregates into module-level metrics with Maintainability Index on Program:exit. | ||
| */ | ||
| export function createModuleAnalysisVisitor(context, onModuleAnalyzed, onFunctionAnalyzed, options) { | ||
| const opts = options ?? {}; | ||
| const cyclomaticThreshold = opts.cyclomaticThreshold ?? 10; | ||
| const cognitiveThreshold = opts.cognitiveThreshold ?? 10; | ||
| const pendingFunctions = []; | ||
| const combinedVisitor = createCombinedComplexityVisitor(context, (result, node) => { | ||
| const funcNode = node; | ||
| const name = getFunctionName(funcNode, funcNode.parent); | ||
| pendingFunctions.push({ node, name, result, halsteadCounts: createHalsteadCounts() }); | ||
| onFunctionAnalyzed?.(result, node); | ||
| }); | ||
| const { handlers: halsteadHandlers, moduleCounts } = createHalsteadVisitorHandlers({ | ||
| onFunctionExit(counts) { | ||
| const last = pendingFunctions[pendingFunctions.length - 1]; | ||
| if (last) | ||
| last.halsteadCounts = counts; | ||
| }, | ||
| }); | ||
| // Merge both visitors: for overlapping keys, call both handlers | ||
| const combinedHandlerMap = combinedVisitor; | ||
| const allKeys = new Set([...Object.keys(combinedVisitor), ...Object.keys(halsteadHandlers)]); | ||
| const mergedVisitor = {}; | ||
| for (const key of allKeys) { | ||
| const a = combinedHandlerMap[key]; | ||
| const b = halsteadHandlers[key]; | ||
| const handler = a && b | ||
| ? (node) => { | ||
| a(node); | ||
| b(node); | ||
| } | ||
| : (a ?? b); | ||
| if (handler) | ||
| mergedVisitor[key] = handler; | ||
| } | ||
| // Reset per-file state when entering a new Program (prevents accumulation across files) | ||
| const originalProgramEnter = mergedVisitor['Program']; | ||
| mergedVisitor['Program'] = (node) => { | ||
| pendingFunctions.length = 0; | ||
| moduleCounts.operators.clear(); | ||
| moduleCounts.operands.clear(); | ||
| originalProgramEnter?.(node); | ||
| }; | ||
| const originalProgramExit = mergedVisitor['Program:exit']; | ||
| mergedVisitor['Program:exit'] = (node) => { | ||
| originalProgramExit?.(node); | ||
| const totalLOC = node.loc ? node.loc.end.line : 0; | ||
| const functions = pendingFunctions.map((pf) => { | ||
| const halstead = calculateHalsteadMetrics(pf.halsteadCounts); | ||
| const lineStart = pf.node.loc?.start.line ?? 0; | ||
| const lineEnd = pf.node.loc?.end.line ?? 0; | ||
| const loc = Math.max(lineEnd - lineStart + 1, 1); | ||
| return { | ||
| name: pf.name, | ||
| lineStart, | ||
| lineEnd, | ||
| loc, | ||
| cyclomatic: pf.result.cyclomatic, | ||
| cognitive: pf.result.cognitive, | ||
| halstead, | ||
| cyclomaticPoints: pf.result.cyclomaticPoints, | ||
| cognitivePoints: pf.result.cognitivePoints, | ||
| }; | ||
| }); | ||
| const moduleHalstead = calculateHalsteadMetrics(moduleCounts); | ||
| const cyclomatic = aggregateComplexity(functions.map((f) => f.cyclomatic), cyclomaticThreshold); | ||
| const cognitive = aggregateComplexity(functions.map((f) => f.cognitive), cognitiveThreshold); | ||
| const functionEffortSum = functions.reduce((sum, f) => sum + f.halstead.effort, 0); | ||
| const miInputs = computeMIInputs(functions.length, cyclomatic.sum, totalLOC, moduleHalstead, functionEffortSum); | ||
| const mc = calculateModuleComplexity(miInputs.avgEffort, miInputs.avgCyclomatic, miInputs.avgLOC); | ||
| onModuleAnalyzed({ | ||
| functions, | ||
| halstead: moduleHalstead, | ||
| cyclomatic, | ||
| cognitive, | ||
| moduleComplexity: mc.score, | ||
| complexityDecomposition: mc.decomposition, | ||
| totalLOC, | ||
| functionCount: functions.length, | ||
| }); | ||
| }; | ||
| return mergedVisitor; | ||
| } | ||
| function aggregateComplexity(values, threshold) { | ||
| if (values.length === 0) { | ||
| return { sum: 0, max: 0, average: 0, countAboveThreshold: 0 }; | ||
| } | ||
| let sum = 0; | ||
| let max = 0; | ||
| let countAboveThreshold = 0; | ||
| for (const v of values) { | ||
| sum += v; | ||
| if (v > max) | ||
| max = v; | ||
| if (v > threshold) | ||
| countAboveThreshold++; | ||
| } | ||
| return { sum, max, average: sum / values.length, countAboveThreshold }; | ||
| } | ||
| //# sourceMappingURL=visitor.js.map |
| {"version":3,"file":"visitor.js","sourceRoot":"","sources":["../../src/module/visitor.ts"],"names":[],"mappings":"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"} |
+2
-2
| { | ||
| "name": "oxlint-plugin-complexity", | ||
| "version": "2.0.1", | ||
| "version": "2.0.2", | ||
| "description": "Cyclomatic and cognitive complexity rules for oxlint", | ||
@@ -44,3 +44,3 @@ "keywords": [ | ||
| "husky": "^9.1.7", | ||
| "oxc-parser": "^0.115.0", | ||
| "oxc-parser": "^0.116.0", | ||
| "@oxlint/plugins": "^1.48.0", | ||
@@ -47,0 +47,0 @@ "oxlint": "^1.48.0", |
244080
45.68%119
58.67%3276
48.91%