@defai.digital/ax-cli 3.4.6 → 3.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +2 -6
- package/README.md +109 -2
- package/dist/analyzers/ast/index.d.ts +9 -0
- package/dist/analyzers/ast/index.js +10 -0
- package/dist/analyzers/ast/index.js.map +1 -0
- package/dist/analyzers/ast/node-helpers.d.ts +81 -0
- package/dist/analyzers/ast/node-helpers.js +128 -0
- package/dist/analyzers/ast/node-helpers.js.map +1 -0
- package/dist/analyzers/ast/parser.d.ts +59 -0
- package/dist/analyzers/ast/parser.js +293 -0
- package/dist/analyzers/ast/parser.js.map +1 -0
- package/dist/analyzers/ast/traverser.d.ts +67 -0
- package/dist/analyzers/ast/traverser.js +156 -0
- package/dist/analyzers/ast/traverser.js.map +1 -0
- package/dist/analyzers/ast/types.d.ts +107 -0
- package/dist/analyzers/ast/types.js +7 -0
- package/dist/analyzers/ast/types.js.map +1 -0
- package/dist/analyzers/best-practices/index.d.ts +10 -0
- package/dist/analyzers/best-practices/index.js +11 -0
- package/dist/analyzers/best-practices/index.js.map +1 -0
- package/dist/analyzers/code-smells/base-smell-detector.d.ts +30 -0
- package/dist/analyzers/code-smells/base-smell-detector.js +44 -0
- package/dist/analyzers/code-smells/base-smell-detector.js.map +1 -0
- package/dist/analyzers/code-smells/code-smell-analyzer.d.ts +30 -0
- package/dist/analyzers/code-smells/code-smell-analyzer.js +167 -0
- package/dist/analyzers/code-smells/code-smell-analyzer.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/data-clumps-detector.d.ts +11 -0
- package/dist/analyzers/code-smells/detectors/data-clumps-detector.js +66 -0
- package/dist/analyzers/code-smells/detectors/data-clumps-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/dead-code-detector.d.ts +11 -0
- package/dist/analyzers/code-smells/detectors/dead-code-detector.js +53 -0
- package/dist/analyzers/code-smells/detectors/dead-code-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/duplicate-code-detector.d.ts +11 -0
- package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js +51 -0
- package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/feature-envy-detector.d.ts +11 -0
- package/dist/analyzers/code-smells/detectors/feature-envy-detector.js +64 -0
- package/dist/analyzers/code-smells/detectors/feature-envy-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.d.ts +11 -0
- package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js +56 -0
- package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/large-class-detector.d.ts +13 -0
- package/dist/analyzers/code-smells/detectors/large-class-detector.js +58 -0
- package/dist/analyzers/code-smells/detectors/large-class-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/long-method-detector.d.ts +12 -0
- package/dist/analyzers/code-smells/detectors/long-method-detector.js +52 -0
- package/dist/analyzers/code-smells/detectors/long-method-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.d.ts +12 -0
- package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js +50 -0
- package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/magic-numbers-detector.d.ts +12 -0
- package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js +54 -0
- package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js.map +1 -0
- package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.d.ts +13 -0
- package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js +71 -0
- package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js.map +1 -0
- package/dist/analyzers/code-smells/index.d.ts +16 -0
- package/dist/analyzers/code-smells/index.js +19 -0
- package/dist/analyzers/code-smells/index.js.map +1 -0
- package/dist/analyzers/code-smells/types.d.ts +82 -0
- package/dist/analyzers/code-smells/types.js +30 -0
- package/dist/analyzers/code-smells/types.js.map +1 -0
- package/dist/analyzers/dependency/circular-detector.d.ts +17 -0
- package/dist/analyzers/dependency/circular-detector.js +71 -0
- package/dist/analyzers/dependency/circular-detector.js.map +1 -0
- package/dist/analyzers/dependency/coupling-calculator.d.ts +24 -0
- package/dist/analyzers/dependency/coupling-calculator.js +86 -0
- package/dist/analyzers/dependency/coupling-calculator.js.map +1 -0
- package/dist/analyzers/dependency/dependency-analyzer.d.ts +40 -0
- package/dist/analyzers/dependency/dependency-analyzer.js +214 -0
- package/dist/analyzers/dependency/dependency-analyzer.js.map +1 -0
- package/dist/analyzers/dependency/dependency-graph.d.ts +57 -0
- package/dist/analyzers/dependency/dependency-graph.js +186 -0
- package/dist/analyzers/dependency/dependency-graph.js.map +1 -0
- package/dist/analyzers/dependency/index.d.ts +8 -0
- package/dist/analyzers/dependency/index.js +8 -0
- package/dist/analyzers/dependency/index.js.map +1 -0
- package/dist/analyzers/dependency/types.d.ts +105 -0
- package/dist/analyzers/dependency/types.js +5 -0
- package/dist/analyzers/dependency/types.js.map +1 -0
- package/dist/analyzers/git/churn-calculator.d.ts +34 -0
- package/dist/analyzers/git/churn-calculator.js +214 -0
- package/dist/analyzers/git/churn-calculator.js.map +1 -0
- package/dist/analyzers/git/git-analyzer.d.ts +19 -0
- package/dist/analyzers/git/git-analyzer.js +71 -0
- package/dist/analyzers/git/git-analyzer.js.map +1 -0
- package/dist/analyzers/git/hotspot-detector.d.ts +34 -0
- package/dist/analyzers/git/hotspot-detector.js +170 -0
- package/dist/analyzers/git/hotspot-detector.js.map +1 -0
- package/dist/analyzers/git/index.d.ts +7 -0
- package/dist/analyzers/git/index.js +7 -0
- package/dist/analyzers/git/index.js.map +1 -0
- package/dist/analyzers/git/types.d.ts +88 -0
- package/dist/analyzers/git/types.js +5 -0
- package/dist/analyzers/git/types.js.map +1 -0
- package/dist/analyzers/metrics/halstead-calculator.d.ts +30 -0
- package/dist/analyzers/metrics/halstead-calculator.js +150 -0
- package/dist/analyzers/metrics/halstead-calculator.js.map +1 -0
- package/dist/analyzers/metrics/index.d.ts +9 -0
- package/dist/analyzers/metrics/index.js +9 -0
- package/dist/analyzers/metrics/index.js.map +1 -0
- package/dist/analyzers/metrics/maintainability-calculator.d.ts +17 -0
- package/dist/analyzers/metrics/maintainability-calculator.js +46 -0
- package/dist/analyzers/metrics/maintainability-calculator.js.map +1 -0
- package/dist/analyzers/metrics/metrics-analyzer.d.ts +32 -0
- package/dist/analyzers/metrics/metrics-analyzer.js +140 -0
- package/dist/analyzers/metrics/metrics-analyzer.js.map +1 -0
- package/dist/analyzers/metrics/types.d.ts +67 -0
- package/dist/analyzers/metrics/types.js +5 -0
- package/dist/analyzers/metrics/types.js.map +1 -0
- package/dist/analyzers/security/base-detector.d.ts +58 -0
- package/dist/analyzers/security/base-detector.js +104 -0
- package/dist/analyzers/security/base-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/command-injection-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/command-injection-detector.js +84 -0
- package/dist/analyzers/security/detectors/command-injection-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/hardcoded-secrets-detector.d.ts +16 -0
- package/dist/analyzers/security/detectors/hardcoded-secrets-detector.js +140 -0
- package/dist/analyzers/security/detectors/hardcoded-secrets-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/insecure-deserialization-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/insecure-deserialization-detector.js +109 -0
- package/dist/analyzers/security/detectors/insecure-deserialization-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/insecure-random-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/insecure-random-detector.js +61 -0
- package/dist/analyzers/security/detectors/insecure-random-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/path-traversal-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/path-traversal-detector.js +82 -0
- package/dist/analyzers/security/detectors/path-traversal-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/sql-injection-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/sql-injection-detector.js +88 -0
- package/dist/analyzers/security/detectors/sql-injection-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/weak-crypto-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/weak-crypto-detector.js +104 -0
- package/dist/analyzers/security/detectors/weak-crypto-detector.js.map +1 -0
- package/dist/analyzers/security/detectors/xss-detector.d.ts +12 -0
- package/dist/analyzers/security/detectors/xss-detector.js +90 -0
- package/dist/analyzers/security/detectors/xss-detector.js.map +1 -0
- package/dist/analyzers/security/index.d.ts +16 -0
- package/dist/analyzers/security/index.js +18 -0
- package/dist/analyzers/security/index.js.map +1 -0
- package/dist/analyzers/security/security-analyzer.d.ts +38 -0
- package/dist/analyzers/security/security-analyzer.js +215 -0
- package/dist/analyzers/security/security-analyzer.js.map +1 -0
- package/dist/analyzers/security/types.d.ts +95 -0
- package/dist/analyzers/security/types.js +7 -0
- package/dist/analyzers/security/types.js.map +1 -0
- package/dist/hooks/use-enhanced-input.d.ts +0 -1
- package/dist/hooks/use-enhanced-input.js.map +1 -1
- package/dist/index.js +0 -0
- package/dist/mcp/validation.js +12 -6
- package/dist/mcp/validation.js.map +1 -1
- package/dist/tools/analysis-tools.d.ts +73 -0
- package/dist/tools/analysis-tools.js +422 -0
- package/dist/tools/analysis-tools.js.map +1 -0
- package/dist/tools/bash.js +2 -1
- package/dist/tools/bash.js.map +1 -1
- package/dist/ui/components/toast-notification.js +0 -1
- package/dist/ui/components/toast-notification.js.map +1 -1
- package/dist/ui/components/welcome-panel.js +1 -1
- package/dist/ui/components/welcome-panel.js.map +1 -1
- package/dist/ui/hooks/use-input-history.d.ts +9 -0
- package/dist/ui/hooks/use-input-history.js +117 -0
- package/dist/ui/hooks/use-input-history.js.map +1 -0
- package/dist/utils/parallel-analyzer.js +30 -17
- package/dist/utils/parallel-analyzer.js.map +1 -1
- package/eslint.config.js +3 -0
- package/package.json +5 -5
- package/vitest.config.ts +1 -0
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-11e9e0ba-c39d-4fd2-aa77-bc818811c921.json +0 -69
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-2b260b98-b418-4c7c-9694-e2b94967e662.json +0 -24
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-7e03601e-e8ab-4cd7-9841-a74b66adf78f.json +0 -69
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-7f9c6562-771f-4fd0-adcf-9e7e9ac34ae8.json +0 -44
- package/.ax-cli/checkpoints/2025-11-20/checkpoint-e1ebe666-4c3a-4367-ba5c-27fe512a9c70.json +0 -24
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-15743e7d-430c-4d76-b6fc-955d7a5c250c.json +0 -44
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-25cf7679-0b3f-4988-83d7-704548fbba91.json +0 -69
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-54aedbac-6db0-464e-8ebb-dbb3979e6dca.json +0 -24
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-7658aed8-fe5d-4222-903f-1a7c63717ea7.json +0 -24
- package/.ax-cli/checkpoints/2025-11-21/checkpoint-c9c13497-40dc-4294-a327-6a5fc854eaa1.json +0 -69
- package/automatosx.config.json +0 -333
- package/config/messages.yaml +0 -75
- package/config/models.yaml +0 -66
- package/config/prompts.yaml +0 -156
- package/config/settings.yaml +0 -86
- package/dist/commands/weather.d.ts +0 -8
- package/dist/commands/weather.js +0 -160
- package/dist/commands/weather.js.map +0 -1
- package/dist/grok/client.d.ts +0 -144
- package/dist/grok/client.js +0 -237
- package/dist/grok/client.js.map +0 -1
- package/dist/grok/tools.d.ts +0 -8
- package/dist/grok/tools.js +0 -318
- package/dist/grok/tools.js.map +0 -1
- package/dist/grok/types.d.ts +0 -291
- package/dist/grok/types.js +0 -127
- package/dist/grok/types.js.map +0 -1
- package/dist/tools/morph-editor.d.ts +0 -36
- package/dist/tools/morph-editor.js +0 -308
- package/dist/tools/morph-editor.js.map +0 -1
- package/dist/ui/components/session-recovery.d.ts +0 -12
- package/dist/ui/components/session-recovery.js +0 -93
- package/dist/ui/components/session-recovery.js.map +0 -1
- package/dist/utils/model-config.d.ts +0 -28
- package/dist/utils/model-config.js +0 -43
- package/dist/utils/model-config.js.map +0 -1
- package/dist/utils/tool-helpers.d.ts +0 -25
- package/dist/utils/tool-helpers.js +0 -79
- package/dist/utils/tool-helpers.js.map +0 -1
- package/packages/schemas/dist/index.d.ts +0 -14
- package/packages/schemas/dist/index.d.ts.map +0 -1
- package/packages/schemas/dist/index.js +0 -19
- package/packages/schemas/dist/index.js.map +0 -1
- package/packages/schemas/dist/public/core/brand-types.d.ts +0 -308
- package/packages/schemas/dist/public/core/brand-types.d.ts.map +0 -1
- package/packages/schemas/dist/public/core/brand-types.js +0 -243
- package/packages/schemas/dist/public/core/brand-types.js.map +0 -1
- package/packages/schemas/dist/public/core/enums.d.ts +0 -227
- package/packages/schemas/dist/public/core/enums.d.ts.map +0 -1
- package/packages/schemas/dist/public/core/enums.js +0 -222
- package/packages/schemas/dist/public/core/enums.js.map +0 -1
- package/packages/schemas/dist/public/core/id-types.d.ts +0 -286
- package/packages/schemas/dist/public/core/id-types.d.ts.map +0 -1
- package/packages/schemas/dist/public/core/id-types.js +0 -136
- package/packages/schemas/dist/public/core/id-types.js.map +0 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Main orchestrator for Git history analysis
|
|
5
|
+
*/
|
|
6
|
+
import { ChurnCalculator } from './churn-calculator.js';
|
|
7
|
+
import { HotspotDetector } from './hotspot-detector.js';
|
|
8
|
+
export class GitAnalyzer {
|
|
9
|
+
churnCalculator;
|
|
10
|
+
hotspotDetector;
|
|
11
|
+
constructor(repositoryPath) {
|
|
12
|
+
this.churnCalculator = new ChurnCalculator(repositoryPath);
|
|
13
|
+
this.hotspotDetector = new HotspotDetector();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Perform complete Git analysis
|
|
17
|
+
*/
|
|
18
|
+
async analyze(options = {}) {
|
|
19
|
+
const timestamp = new Date();
|
|
20
|
+
// Calculate churn metrics
|
|
21
|
+
const churnMetrics = await this.churnCalculator.calculateChurn(options);
|
|
22
|
+
// Calculate contributor statistics
|
|
23
|
+
const contributors = await this.churnCalculator.calculateContributorStats(options);
|
|
24
|
+
// Detect hotspots
|
|
25
|
+
const hotspots = await this.hotspotDetector.detectHotspots(churnMetrics, options);
|
|
26
|
+
// Calculate summary
|
|
27
|
+
const summary = this.calculateSummary(churnMetrics, hotspots, contributors);
|
|
28
|
+
return Object.freeze({
|
|
29
|
+
hotspots: Object.freeze(hotspots),
|
|
30
|
+
churnMetrics: Object.freeze(churnMetrics),
|
|
31
|
+
contributors: Object.freeze(contributors),
|
|
32
|
+
summary: Object.freeze(summary),
|
|
33
|
+
timestamp,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Calculate summary statistics
|
|
38
|
+
*/
|
|
39
|
+
calculateSummary(churnMetrics, hotspots, contributors) {
|
|
40
|
+
const totalCommits = contributors.reduce((sum, c) => sum + c.commitCount, 0);
|
|
41
|
+
const averageChurn = churnMetrics.length > 0
|
|
42
|
+
? churnMetrics.reduce((sum, c) => sum + c.totalChurn, 0) / churnMetrics.length
|
|
43
|
+
: 0;
|
|
44
|
+
const topContributor = contributors.length > 0
|
|
45
|
+
? contributors[0].author
|
|
46
|
+
: 'Unknown';
|
|
47
|
+
// Determine date range
|
|
48
|
+
let earliestDate = new Date();
|
|
49
|
+
let latestDate = new Date(0);
|
|
50
|
+
for (const contributor of contributors) {
|
|
51
|
+
if (contributor.firstCommit < earliestDate) {
|
|
52
|
+
earliestDate = contributor.firstCommit;
|
|
53
|
+
}
|
|
54
|
+
if (contributor.lastCommit > latestDate) {
|
|
55
|
+
latestDate = contributor.lastCommit;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return {
|
|
59
|
+
totalCommits,
|
|
60
|
+
filesAnalyzed: churnMetrics.length,
|
|
61
|
+
hotspotCount: hotspots.length,
|
|
62
|
+
averageChurn: Math.round(averageChurn),
|
|
63
|
+
topContributor,
|
|
64
|
+
dateRange: {
|
|
65
|
+
from: earliestDate,
|
|
66
|
+
to: latestDate,
|
|
67
|
+
},
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=git-analyzer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-analyzer.js","sourceRoot":"","sources":["../../../src/analyzers/git/git-analyzer.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAGxD,MAAM,OAAO,WAAW;IACd,eAAe,CAAkB;IACjC,eAAe,CAAkB;IAEzC,YAAY,cAAsB;QAChC,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,CAAC,cAAc,CAAC,CAAC;QAC3D,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,EAAE,CAAC;IAC/C,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,UAA8B,EAAE;QAC5C,MAAM,SAAS,GAAG,IAAI,IAAI,EAAE,CAAC;QAE7B,0BAA0B;QAC1B,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,OAAO,CAAC,CAAC;QAExE,mCAAmC;QACnC,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,yBAAyB,CAAC,OAAO,CAAC,CAAC;QAEnF,kBAAkB;QAClB,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,cAAc,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QAElF,oBAAoB;QACpB,MAAM,OAAO,GAAG,IAAI,CAAC,gBAAgB,CAAC,YAAY,EAAE,QAAQ,EAAE,YAAY,CAAC,CAAC;QAE5E,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;YACjC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;YACzC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC;YACzC,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;YAC/B,SAAS;SACV,CAAC,CAAC;IACL,CAAC;IAED;;OAEG;IACK,gBAAgB,CACtB,YAA4B,EAC5B,QAAwB,EACxB,YAA4B;QAE5B,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAC7E,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC;YAC1C,CAAC,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,GAAG,YAAY,CAAC,MAAM;YAC9E,CAAC,CAAC,CAAC,CAAC;QAEN,MAAM,cAAc,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC;YAC5C,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,MAAM;YACxB,CAAC,CAAC,SAAS,CAAC;QAEd,uBAAuB;QACvB,IAAI,YAAY,GAAG,IAAI,IAAI,EAAE,CAAC;QAC9B,IAAI,UAAU,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;QAE7B,KAAK,MAAM,WAAW,IAAI,YAAY,EAAE,CAAC;YACvC,IAAI,WAAW,CAAC,WAAW,GAAG,YAAY,EAAE,CAAC;gBAC3C,YAAY,GAAG,WAAW,CAAC,WAAW,CAAC;YACzC,CAAC;YACD,IAAI,WAAW,CAAC,UAAU,GAAG,UAAU,EAAE,CAAC;gBACxC,UAAU,GAAG,WAAW,CAAC,UAAU,CAAC;YACtC,CAAC;QACH,CAAC;QAED,OAAO;YACL,YAAY;YACZ,aAAa,EAAE,YAAY,CAAC,MAAM;YAClC,YAAY,EAAE,QAAQ,CAAC,MAAM;YAC7B,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;YACtC,cAAc;YACd,SAAS,EAAE;gBACT,IAAI,EAAE,YAAY;gBAClB,EAAE,EAAE,UAAU;aACf;SACF,CAAC;IACJ,CAAC;CACF"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hotspot Detector
|
|
3
|
+
*
|
|
4
|
+
* Identifies code hotspots using churn × complexity formula
|
|
5
|
+
*/
|
|
6
|
+
import type { FileChurn, CodeHotspot, GitAnalysisOptions } from './types.js';
|
|
7
|
+
export declare class HotspotDetector {
|
|
8
|
+
private astParser;
|
|
9
|
+
constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Detect hotspots from churn metrics
|
|
12
|
+
*/
|
|
13
|
+
detectHotspots(churnMetrics: readonly FileChurn[], options?: GitAnalysisOptions): Promise<CodeHotspot[]>;
|
|
14
|
+
/**
|
|
15
|
+
* Get complexity metrics from file
|
|
16
|
+
*/
|
|
17
|
+
private getComplexityMetrics;
|
|
18
|
+
/**
|
|
19
|
+
* Normalize complexity to 0-100 scale
|
|
20
|
+
*/
|
|
21
|
+
private normalizeComplexity;
|
|
22
|
+
/**
|
|
23
|
+
* Calculate severity based on hotspot score
|
|
24
|
+
*/
|
|
25
|
+
private calculateSeverity;
|
|
26
|
+
/**
|
|
27
|
+
* Generate reason for hotspot
|
|
28
|
+
*/
|
|
29
|
+
private generateReason;
|
|
30
|
+
/**
|
|
31
|
+
* Generate recommendation
|
|
32
|
+
*/
|
|
33
|
+
private generateRecommendation;
|
|
34
|
+
}
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hotspot Detector
|
|
3
|
+
*
|
|
4
|
+
* Identifies code hotspots using churn × complexity formula
|
|
5
|
+
*/
|
|
6
|
+
import { ASTParser } from '../ast/parser.js';
|
|
7
|
+
export class HotspotDetector {
|
|
8
|
+
astParser;
|
|
9
|
+
constructor() {
|
|
10
|
+
this.astParser = new ASTParser();
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Detect hotspots from churn metrics
|
|
14
|
+
*/
|
|
15
|
+
async detectHotspots(churnMetrics, options = {}) {
|
|
16
|
+
const threshold = options.hotspotThreshold ?? 70;
|
|
17
|
+
const hotspots = [];
|
|
18
|
+
// Calculate max values for normalization
|
|
19
|
+
const maxChurn = Math.max(...churnMetrics.map(c => c.totalChurn), 1);
|
|
20
|
+
const maxCommits = Math.max(...churnMetrics.map(c => c.commitCount), 1);
|
|
21
|
+
for (const churn of churnMetrics) {
|
|
22
|
+
try {
|
|
23
|
+
// Get complexity metrics from AST
|
|
24
|
+
const complexity = await this.getComplexityMetrics(churn.filePath);
|
|
25
|
+
if (!complexity)
|
|
26
|
+
continue;
|
|
27
|
+
// Normalize churn (0-100)
|
|
28
|
+
const normalizedChurn = (churn.totalChurn / maxChurn) * 100;
|
|
29
|
+
const normalizedCommits = (churn.commitCount / maxCommits) * 100;
|
|
30
|
+
const churnScore = (normalizedChurn * 0.6 + normalizedCommits * 0.4);
|
|
31
|
+
// Normalize complexity (0-100)
|
|
32
|
+
const complexityScore = this.normalizeComplexity(complexity.average, complexity.max);
|
|
33
|
+
// Calculate hotspot score using weighted formula
|
|
34
|
+
// Churn: 40%, Complexity: 30%, Commit Frequency: 30%
|
|
35
|
+
const hotspotScore = Math.round(churnScore * 0.4 +
|
|
36
|
+
complexityScore * 0.3 +
|
|
37
|
+
normalizedCommits * 0.3);
|
|
38
|
+
// Only include if above threshold
|
|
39
|
+
if (hotspotScore >= threshold) {
|
|
40
|
+
const severity = this.calculateSeverity(hotspotScore);
|
|
41
|
+
const reason = this.generateReason(churn, complexity, hotspotScore);
|
|
42
|
+
const recommendation = this.generateRecommendation(churn, complexity, severity);
|
|
43
|
+
hotspots.push(Object.freeze({
|
|
44
|
+
filePath: churn.filePath,
|
|
45
|
+
hotspotScore,
|
|
46
|
+
churnScore: Math.round(churnScore),
|
|
47
|
+
complexityScore: Math.round(complexityScore),
|
|
48
|
+
commitCount: churn.commitCount,
|
|
49
|
+
totalChurn: churn.totalChurn,
|
|
50
|
+
averageComplexity: complexity.average,
|
|
51
|
+
maxComplexity: complexity.max,
|
|
52
|
+
severity,
|
|
53
|
+
reason,
|
|
54
|
+
recommendation,
|
|
55
|
+
}));
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
catch (error) {
|
|
59
|
+
// Skip files that can't be analyzed
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
// Sort by hotspot score (descending)
|
|
64
|
+
return hotspots.sort((a, b) => b.hotspotScore - a.hotspotScore);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Get complexity metrics from file
|
|
68
|
+
*/
|
|
69
|
+
async getComplexityMetrics(filePath) {
|
|
70
|
+
try {
|
|
71
|
+
const ast = this.astParser.parseFile(filePath);
|
|
72
|
+
const complexities = [];
|
|
73
|
+
// Collect function complexities
|
|
74
|
+
for (const func of ast.functions) {
|
|
75
|
+
complexities.push(func.complexity);
|
|
76
|
+
}
|
|
77
|
+
// Collect method complexities
|
|
78
|
+
for (const cls of ast.classes) {
|
|
79
|
+
for (const method of cls.methods) {
|
|
80
|
+
complexities.push(method.complexity);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
if (complexities.length === 0) {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
const average = complexities.reduce((sum, c) => sum + c, 0) / complexities.length;
|
|
87
|
+
const max = Math.max(...complexities);
|
|
88
|
+
return { average, max };
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Normalize complexity to 0-100 scale
|
|
96
|
+
*/
|
|
97
|
+
normalizeComplexity(average, max) {
|
|
98
|
+
// McCabe complexity thresholds:
|
|
99
|
+
// 1-10: Simple
|
|
100
|
+
// 11-20: Moderate
|
|
101
|
+
// 21-50: Complex
|
|
102
|
+
// 50+: Very complex
|
|
103
|
+
const avgScore = Math.min(100, (average / 20) * 100);
|
|
104
|
+
const maxScore = Math.min(100, (max / 50) * 100);
|
|
105
|
+
// Weight average more than max
|
|
106
|
+
return avgScore * 0.7 + maxScore * 0.3;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Calculate severity based on hotspot score
|
|
110
|
+
*/
|
|
111
|
+
calculateSeverity(score) {
|
|
112
|
+
if (score >= 90)
|
|
113
|
+
return 'CRITICAL';
|
|
114
|
+
if (score >= 80)
|
|
115
|
+
return 'HIGH';
|
|
116
|
+
if (score >= 70)
|
|
117
|
+
return 'MEDIUM';
|
|
118
|
+
return 'LOW';
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Generate reason for hotspot
|
|
122
|
+
*/
|
|
123
|
+
generateReason(churn, complexity, score) {
|
|
124
|
+
const reasons = [];
|
|
125
|
+
if (churn.commitCount > 20) {
|
|
126
|
+
reasons.push(`high change frequency (${churn.commitCount} commits)`);
|
|
127
|
+
}
|
|
128
|
+
if (churn.totalChurn > 500) {
|
|
129
|
+
reasons.push(`high churn (${churn.totalChurn} lines changed)`);
|
|
130
|
+
}
|
|
131
|
+
if (complexity.average > 10) {
|
|
132
|
+
reasons.push(`high average complexity (${complexity.average.toFixed(1)})`);
|
|
133
|
+
}
|
|
134
|
+
if (complexity.max > 20) {
|
|
135
|
+
reasons.push(`very complex functions (max: ${complexity.max})`);
|
|
136
|
+
}
|
|
137
|
+
if (churn.authors.length > 5) {
|
|
138
|
+
reasons.push(`many contributors (${churn.authors.length})`);
|
|
139
|
+
}
|
|
140
|
+
return `Hotspot (score: ${score}/100): ${reasons.join(', ')}`;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Generate recommendation
|
|
144
|
+
*/
|
|
145
|
+
generateRecommendation(churn, complexity, severity) {
|
|
146
|
+
const recommendations = [];
|
|
147
|
+
if (complexity.max > 20) {
|
|
148
|
+
recommendations.push('Reduce complexity by breaking down complex functions');
|
|
149
|
+
}
|
|
150
|
+
if (churn.commitCount > 30) {
|
|
151
|
+
recommendations.push('Stabilize this file - consider refactoring to reduce change frequency');
|
|
152
|
+
}
|
|
153
|
+
if (churn.authors.length > 8) {
|
|
154
|
+
recommendations.push('Establish clear ownership and coding standards');
|
|
155
|
+
}
|
|
156
|
+
if (complexity.average > 15) {
|
|
157
|
+
recommendations.push('Simplify logic and improve code structure');
|
|
158
|
+
}
|
|
159
|
+
if (recommendations.length === 0) {
|
|
160
|
+
recommendations.push('Monitor this file for further changes and consider refactoring');
|
|
161
|
+
}
|
|
162
|
+
const prefix = severity === 'CRITICAL' || severity === 'HIGH'
|
|
163
|
+
? 'URGENT: '
|
|
164
|
+
: severity === 'MEDIUM'
|
|
165
|
+
? 'Important: '
|
|
166
|
+
: '';
|
|
167
|
+
return prefix + recommendations.join('. ') + '.';
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=hotspot-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hotspot-detector.js","sourceRoot":"","sources":["../../../src/analyzers/git/hotspot-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Integration Module
|
|
3
|
+
*/
|
|
4
|
+
export { GitAnalyzer } from './git-analyzer.js';
|
|
5
|
+
export { ChurnCalculator } from './churn-calculator.js';
|
|
6
|
+
export { HotspotDetector } from './hotspot-detector.js';
|
|
7
|
+
export type { GitCommit, FileChurn, CodeHotspot, ContributorStats, GitAnalysisResult, GitAnalysisSummary, GitAnalysisOptions, } from './types.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/git/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Git Integration Types
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Git commit information
|
|
6
|
+
*/
|
|
7
|
+
export interface GitCommit {
|
|
8
|
+
readonly hash: string;
|
|
9
|
+
readonly author: string;
|
|
10
|
+
readonly date: Date;
|
|
11
|
+
readonly message: string;
|
|
12
|
+
readonly filesChanged: ReadonlyArray<string>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* File churn metrics
|
|
16
|
+
*/
|
|
17
|
+
export interface FileChurn {
|
|
18
|
+
readonly filePath: string;
|
|
19
|
+
readonly commitCount: number;
|
|
20
|
+
readonly additions: number;
|
|
21
|
+
readonly deletions: number;
|
|
22
|
+
readonly totalChurn: number;
|
|
23
|
+
readonly lastModified: Date;
|
|
24
|
+
readonly authors: ReadonlyArray<string>;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Code hotspot (high churn + high complexity)
|
|
28
|
+
*/
|
|
29
|
+
export interface CodeHotspot {
|
|
30
|
+
readonly filePath: string;
|
|
31
|
+
readonly hotspotScore: number;
|
|
32
|
+
readonly churnScore: number;
|
|
33
|
+
readonly complexityScore: number;
|
|
34
|
+
readonly commitCount: number;
|
|
35
|
+
readonly totalChurn: number;
|
|
36
|
+
readonly averageComplexity: number;
|
|
37
|
+
readonly maxComplexity: number;
|
|
38
|
+
readonly severity: 'LOW' | 'MEDIUM' | 'HIGH' | 'CRITICAL';
|
|
39
|
+
readonly reason: string;
|
|
40
|
+
readonly recommendation: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Contributor statistics
|
|
44
|
+
*/
|
|
45
|
+
export interface ContributorStats {
|
|
46
|
+
readonly author: string;
|
|
47
|
+
readonly commitCount: number;
|
|
48
|
+
readonly filesChanged: number;
|
|
49
|
+
readonly linesAdded: number;
|
|
50
|
+
readonly linesDeleted: number;
|
|
51
|
+
readonly firstCommit: Date;
|
|
52
|
+
readonly lastCommit: Date;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Git analysis result
|
|
56
|
+
*/
|
|
57
|
+
export interface GitAnalysisResult {
|
|
58
|
+
readonly hotspots: ReadonlyArray<CodeHotspot>;
|
|
59
|
+
readonly churnMetrics: ReadonlyArray<FileChurn>;
|
|
60
|
+
readonly contributors: ReadonlyArray<ContributorStats>;
|
|
61
|
+
readonly summary: GitAnalysisSummary;
|
|
62
|
+
readonly timestamp: Date;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Analysis summary
|
|
66
|
+
*/
|
|
67
|
+
export interface GitAnalysisSummary {
|
|
68
|
+
readonly totalCommits: number;
|
|
69
|
+
readonly filesAnalyzed: number;
|
|
70
|
+
readonly hotspotCount: number;
|
|
71
|
+
readonly averageChurn: number;
|
|
72
|
+
readonly topContributor: string;
|
|
73
|
+
readonly dateRange: {
|
|
74
|
+
readonly from: Date;
|
|
75
|
+
readonly to: Date;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Analysis options
|
|
80
|
+
*/
|
|
81
|
+
export interface GitAnalysisOptions {
|
|
82
|
+
readonly since?: string;
|
|
83
|
+
readonly until?: string;
|
|
84
|
+
readonly branch?: string;
|
|
85
|
+
readonly includePatterns?: readonly string[];
|
|
86
|
+
readonly excludePatterns?: readonly string[];
|
|
87
|
+
readonly hotspotThreshold?: number;
|
|
88
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/analyzers/git/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Halstead Complexity Calculator
|
|
3
|
+
*
|
|
4
|
+
* Calculates Halstead metrics from source code tokens
|
|
5
|
+
*/
|
|
6
|
+
import type { HalsteadMetrics } from './types.js';
|
|
7
|
+
export declare class HalsteadCalculator {
|
|
8
|
+
private astParser;
|
|
9
|
+
constructor();
|
|
10
|
+
/**
|
|
11
|
+
* Calculate Halstead metrics for a file
|
|
12
|
+
*/
|
|
13
|
+
calculateMetrics(filePath: string): HalsteadMetrics;
|
|
14
|
+
/**
|
|
15
|
+
* Compute Halstead metrics from counts
|
|
16
|
+
*/
|
|
17
|
+
private computeMetrics;
|
|
18
|
+
/**
|
|
19
|
+
* Check if node is an operator
|
|
20
|
+
*/
|
|
21
|
+
private isOperator;
|
|
22
|
+
/**
|
|
23
|
+
* Check if node is an operand
|
|
24
|
+
*/
|
|
25
|
+
private isOperand;
|
|
26
|
+
/**
|
|
27
|
+
* Get operator symbol for syntax kind
|
|
28
|
+
*/
|
|
29
|
+
private getOperatorSymbol;
|
|
30
|
+
}
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Halstead Complexity Calculator
|
|
3
|
+
*
|
|
4
|
+
* Calculates Halstead metrics from source code tokens
|
|
5
|
+
*/
|
|
6
|
+
import { SyntaxKind } from 'ts-morph';
|
|
7
|
+
import { ASTParser } from '../ast/parser.js';
|
|
8
|
+
export class HalsteadCalculator {
|
|
9
|
+
astParser;
|
|
10
|
+
constructor() {
|
|
11
|
+
this.astParser = new ASTParser();
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Calculate Halstead metrics for a file
|
|
15
|
+
*/
|
|
16
|
+
calculateMetrics(filePath) {
|
|
17
|
+
const sourceFile = this.astParser.getSourceFile(filePath);
|
|
18
|
+
const operators = new Set();
|
|
19
|
+
const operands = new Set();
|
|
20
|
+
let operatorCount = 0;
|
|
21
|
+
let operandCount = 0;
|
|
22
|
+
// Traverse AST and count operators/operands
|
|
23
|
+
sourceFile.forEachDescendant((node) => {
|
|
24
|
+
const kind = node.getKind();
|
|
25
|
+
const text = node.getText();
|
|
26
|
+
// Operators
|
|
27
|
+
if (this.isOperator(kind)) {
|
|
28
|
+
operators.add(this.getOperatorSymbol(kind));
|
|
29
|
+
operatorCount++;
|
|
30
|
+
}
|
|
31
|
+
// Operands (identifiers, literals)
|
|
32
|
+
else if (this.isOperand(kind)) {
|
|
33
|
+
operands.add(text);
|
|
34
|
+
operandCount++;
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
const n1 = operators.size;
|
|
38
|
+
const n2 = operands.size;
|
|
39
|
+
const N1 = operatorCount;
|
|
40
|
+
const N2 = operandCount;
|
|
41
|
+
return this.computeMetrics(n1, n2, N1, N2);
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Compute Halstead metrics from counts
|
|
45
|
+
*/
|
|
46
|
+
computeMetrics(n1, n2, N1, N2) {
|
|
47
|
+
const vocabulary = n1 + n2;
|
|
48
|
+
const length = N1 + N2;
|
|
49
|
+
const calculatedLength = n1 > 0 && n2 > 0
|
|
50
|
+
? n1 * Math.log2(n1) + n2 * Math.log2(n2)
|
|
51
|
+
: 0;
|
|
52
|
+
const volume = length > 0 && vocabulary > 0
|
|
53
|
+
? length * Math.log2(vocabulary)
|
|
54
|
+
: 0;
|
|
55
|
+
const difficulty = n1 > 0 && n2 > 0 && N2 > 0
|
|
56
|
+
? (n1 / 2) * (N2 / n2)
|
|
57
|
+
: 0;
|
|
58
|
+
const effort = difficulty * volume;
|
|
59
|
+
const time = effort / 18; // Seconds to program
|
|
60
|
+
const bugs = volume / 3000; // Estimated delivered bugs
|
|
61
|
+
return Object.freeze({
|
|
62
|
+
n1,
|
|
63
|
+
n2,
|
|
64
|
+
N1,
|
|
65
|
+
N2,
|
|
66
|
+
vocabulary,
|
|
67
|
+
length,
|
|
68
|
+
calculatedLength: Math.round(calculatedLength * 100) / 100,
|
|
69
|
+
volume: Math.round(volume * 100) / 100,
|
|
70
|
+
difficulty: Math.round(difficulty * 100) / 100,
|
|
71
|
+
effort: Math.round(effort * 100) / 100,
|
|
72
|
+
time: Math.round(time * 100) / 100,
|
|
73
|
+
bugs: Math.round(bugs * 1000) / 1000,
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Check if node is an operator
|
|
78
|
+
*/
|
|
79
|
+
isOperator(kind) {
|
|
80
|
+
const operators = [
|
|
81
|
+
SyntaxKind.PlusToken,
|
|
82
|
+
SyntaxKind.MinusToken,
|
|
83
|
+
SyntaxKind.AsteriskToken,
|
|
84
|
+
SyntaxKind.SlashToken,
|
|
85
|
+
SyntaxKind.PercentToken,
|
|
86
|
+
SyntaxKind.EqualsToken,
|
|
87
|
+
SyntaxKind.EqualsEqualsToken,
|
|
88
|
+
SyntaxKind.EqualsEqualsEqualsToken,
|
|
89
|
+
SyntaxKind.ExclamationEqualsToken,
|
|
90
|
+
SyntaxKind.ExclamationEqualsEqualsToken,
|
|
91
|
+
SyntaxKind.LessThanToken,
|
|
92
|
+
SyntaxKind.GreaterThanToken,
|
|
93
|
+
SyntaxKind.LessThanEqualsToken,
|
|
94
|
+
SyntaxKind.GreaterThanEqualsToken,
|
|
95
|
+
SyntaxKind.AmpersandAmpersandToken,
|
|
96
|
+
SyntaxKind.BarBarToken,
|
|
97
|
+
SyntaxKind.ExclamationToken,
|
|
98
|
+
SyntaxKind.QuestionToken,
|
|
99
|
+
SyntaxKind.PlusPlusToken,
|
|
100
|
+
SyntaxKind.MinusMinusToken,
|
|
101
|
+
SyntaxKind.AmpersandToken,
|
|
102
|
+
SyntaxKind.BarToken,
|
|
103
|
+
SyntaxKind.CaretToken,
|
|
104
|
+
SyntaxKind.TildeToken,
|
|
105
|
+
SyntaxKind.LessThanLessThanToken,
|
|
106
|
+
SyntaxKind.GreaterThanGreaterThanToken,
|
|
107
|
+
];
|
|
108
|
+
return operators.includes(kind);
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Check if node is an operand
|
|
112
|
+
*/
|
|
113
|
+
isOperand(kind) {
|
|
114
|
+
return (kind === SyntaxKind.Identifier ||
|
|
115
|
+
kind === SyntaxKind.NumericLiteral ||
|
|
116
|
+
kind === SyntaxKind.StringLiteral ||
|
|
117
|
+
kind === SyntaxKind.TrueKeyword ||
|
|
118
|
+
kind === SyntaxKind.FalseKeyword ||
|
|
119
|
+
kind === SyntaxKind.NullKeyword);
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Get operator symbol for syntax kind
|
|
123
|
+
*/
|
|
124
|
+
getOperatorSymbol(kind) {
|
|
125
|
+
const symbols = {
|
|
126
|
+
[SyntaxKind.PlusToken]: '+',
|
|
127
|
+
[SyntaxKind.MinusToken]: '-',
|
|
128
|
+
[SyntaxKind.AsteriskToken]: '*',
|
|
129
|
+
[SyntaxKind.SlashToken]: '/',
|
|
130
|
+
[SyntaxKind.PercentToken]: '%',
|
|
131
|
+
[SyntaxKind.EqualsToken]: '=',
|
|
132
|
+
[SyntaxKind.EqualsEqualsToken]: '==',
|
|
133
|
+
[SyntaxKind.EqualsEqualsEqualsToken]: '===',
|
|
134
|
+
[SyntaxKind.ExclamationEqualsToken]: '!=',
|
|
135
|
+
[SyntaxKind.ExclamationEqualsEqualsToken]: '!==',
|
|
136
|
+
[SyntaxKind.LessThanToken]: '<',
|
|
137
|
+
[SyntaxKind.GreaterThanToken]: '>',
|
|
138
|
+
[SyntaxKind.LessThanEqualsToken]: '<=',
|
|
139
|
+
[SyntaxKind.GreaterThanEqualsToken]: '>=',
|
|
140
|
+
[SyntaxKind.AmpersandAmpersandToken]: '&&',
|
|
141
|
+
[SyntaxKind.BarBarToken]: '||',
|
|
142
|
+
[SyntaxKind.ExclamationToken]: '!',
|
|
143
|
+
[SyntaxKind.QuestionToken]: '?',
|
|
144
|
+
[SyntaxKind.PlusPlusToken]: '++',
|
|
145
|
+
[SyntaxKind.MinusMinusToken]: '--',
|
|
146
|
+
};
|
|
147
|
+
return symbols[kind] || kind.toString();
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
//# sourceMappingURL=halstead-calculator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"halstead-calculator.js","sourceRoot":"","sources":["../../../src/analyzers/metrics/halstead-calculator.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Advanced Metrics Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Calculates Halstead metrics and Maintainability Index
|
|
5
|
+
*/
|
|
6
|
+
export { MetricsAnalyzer } from './metrics-analyzer.js';
|
|
7
|
+
export { HalsteadCalculator } from './halstead-calculator.js';
|
|
8
|
+
export { MaintainabilityCalculator } from './maintainability-calculator.js';
|
|
9
|
+
export type { HalsteadMetrics, MaintainabilityIndex, FileMetrics, MetricsAnalysisResult, MetricsAnalysisOptions, MetricsSummary, } from './types.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Advanced Metrics Analyzer
|
|
3
|
+
*
|
|
4
|
+
* Calculates Halstead metrics and Maintainability Index
|
|
5
|
+
*/
|
|
6
|
+
export { MetricsAnalyzer } from './metrics-analyzer.js';
|
|
7
|
+
export { HalsteadCalculator } from './halstead-calculator.js';
|
|
8
|
+
export { MaintainabilityCalculator } from './maintainability-calculator.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/metrics/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,yBAAyB,EAAE,MAAM,iCAAiC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maintainability Index Calculator
|
|
3
|
+
*
|
|
4
|
+
* Calculates MI = 171 - 5.2*ln(V) - 0.23*CC - 16.2*ln(LOC)
|
|
5
|
+
* Normalized to 0-100 scale
|
|
6
|
+
*/
|
|
7
|
+
import type { MaintainabilityIndex } from './types.js';
|
|
8
|
+
export declare class MaintainabilityCalculator {
|
|
9
|
+
/**
|
|
10
|
+
* Calculate Maintainability Index
|
|
11
|
+
*/
|
|
12
|
+
calculateIndex(halsteadVolume: number, cyclomaticComplexity: number, linesOfCode: number): MaintainabilityIndex;
|
|
13
|
+
/**
|
|
14
|
+
* Get letter rating from MI score
|
|
15
|
+
*/
|
|
16
|
+
private getRating;
|
|
17
|
+
}
|