@bugsbunnycodes1998/cartographer-core 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/__tests__/pipeline.test.d.ts +2 -0
- package/dist/__tests__/pipeline.test.d.ts.map +1 -0
- package/dist/__tests__/pipeline.test.js +58 -0
- package/dist/__tests__/pipeline.test.js.map +1 -0
- package/dist/analysis/call-graph.d.ts +13 -0
- package/dist/analysis/call-graph.d.ts.map +1 -0
- package/dist/analysis/call-graph.js +133 -0
- package/dist/analysis/call-graph.js.map +1 -0
- package/dist/analysis/dependency-graph.d.ts +8 -0
- package/dist/analysis/dependency-graph.d.ts.map +1 -0
- package/dist/analysis/dependency-graph.js +101 -0
- package/dist/analysis/dependency-graph.js.map +1 -0
- package/dist/analysis/git/archaeology.d.ts +20 -0
- package/dist/analysis/git/archaeology.d.ts.map +1 -0
- package/dist/analysis/git/archaeology.js +61 -0
- package/dist/analysis/git/archaeology.js.map +1 -0
- package/dist/analysis/git/bus-factor.d.ts +17 -0
- package/dist/analysis/git/bus-factor.d.ts.map +1 -0
- package/dist/analysis/git/bus-factor.js +90 -0
- package/dist/analysis/git/bus-factor.js.map +1 -0
- package/dist/analysis/git/churn.d.ts +26 -0
- package/dist/analysis/git/churn.d.ts.map +1 -0
- package/dist/analysis/git/churn.js +127 -0
- package/dist/analysis/git/churn.js.map +1 -0
- package/dist/analysis/git/contributors.d.ts +14 -0
- package/dist/analysis/git/contributors.d.ts.map +1 -0
- package/dist/analysis/git/contributors.js +60 -0
- package/dist/analysis/git/contributors.js.map +1 -0
- package/dist/analysis/git/evolution.d.ts +10 -0
- package/dist/analysis/git/evolution.d.ts.map +1 -0
- package/dist/analysis/git/evolution.js +127 -0
- package/dist/analysis/git/evolution.js.map +1 -0
- package/dist/analysis/git/index.d.ts +6 -0
- package/dist/analysis/git/index.d.ts.map +1 -0
- package/dist/analysis/git/index.js +6 -0
- package/dist/analysis/git/index.js.map +1 -0
- package/dist/analysis/go-visitor.d.ts +4 -0
- package/dist/analysis/go-visitor.d.ts.map +1 -0
- package/dist/analysis/go-visitor.js +295 -0
- package/dist/analysis/go-visitor.js.map +1 -0
- package/dist/analysis/health/indicators.d.ts +25 -0
- package/dist/analysis/health/indicators.d.ts.map +1 -0
- package/dist/analysis/health/indicators.js +53 -0
- package/dist/analysis/health/indicators.js.map +1 -0
- package/dist/analysis/health/scorer.d.ts +26 -0
- package/dist/analysis/health/scorer.d.ts.map +1 -0
- package/dist/analysis/health/scorer.js +97 -0
- package/dist/analysis/health/scorer.js.map +1 -0
- package/dist/analysis/health/test-coverage.d.ts +19 -0
- package/dist/analysis/health/test-coverage.d.ts.map +1 -0
- package/dist/analysis/health/test-coverage.js +67 -0
- package/dist/analysis/health/test-coverage.js.map +1 -0
- package/dist/analysis/import-resolver.d.ts +10 -0
- package/dist/analysis/import-resolver.d.ts.map +1 -0
- package/dist/analysis/import-resolver.js +353 -0
- package/dist/analysis/import-resolver.js.map +1 -0
- package/dist/analysis/index.d.ts +22 -0
- package/dist/analysis/index.d.ts.map +1 -0
- package/dist/analysis/index.js +24 -0
- package/dist/analysis/index.js.map +1 -0
- package/dist/analysis/java-visitor.d.ts +4 -0
- package/dist/analysis/java-visitor.d.ts.map +1 -0
- package/dist/analysis/java-visitor.js +257 -0
- package/dist/analysis/java-visitor.js.map +1 -0
- package/dist/analysis/metrics.d.ts +19 -0
- package/dist/analysis/metrics.d.ts.map +1 -0
- package/dist/analysis/metrics.js +70 -0
- package/dist/analysis/metrics.js.map +1 -0
- package/dist/analysis/module-detector.d.ts +3 -0
- package/dist/analysis/module-detector.d.ts.map +1 -0
- package/dist/analysis/module-detector.js +257 -0
- package/dist/analysis/module-detector.js.map +1 -0
- package/dist/analysis/parser.d.ts +13 -0
- package/dist/analysis/parser.d.ts.map +1 -0
- package/dist/analysis/parser.js +92 -0
- package/dist/analysis/parser.js.map +1 -0
- package/dist/analysis/python-visitor.d.ts +4 -0
- package/dist/analysis/python-visitor.d.ts.map +1 -0
- package/dist/analysis/python-visitor.js +306 -0
- package/dist/analysis/python-visitor.js.map +1 -0
- package/dist/analysis/rust-visitor.d.ts +4 -0
- package/dist/analysis/rust-visitor.d.ts.map +1 -0
- package/dist/analysis/rust-visitor.js +318 -0
- package/dist/analysis/rust-visitor.js.map +1 -0
- package/dist/analysis/semantic/cache.d.ts +16 -0
- package/dist/analysis/semantic/cache.d.ts.map +1 -0
- package/dist/analysis/semantic/cache.js +26 -0
- package/dist/analysis/semantic/cache.js.map +1 -0
- package/dist/analysis/semantic/openai-client.d.ts +21 -0
- package/dist/analysis/semantic/openai-client.d.ts.map +1 -0
- package/dist/analysis/semantic/openai-client.js +73 -0
- package/dist/analysis/semantic/openai-client.js.map +1 -0
- package/dist/analysis/semantic/prompts.d.ts +32 -0
- package/dist/analysis/semantic/prompts.d.ts.map +1 -0
- package/dist/analysis/semantic/prompts.js +134 -0
- package/dist/analysis/semantic/prompts.js.map +1 -0
- package/dist/analysis/semantic/summarizer.d.ts +36 -0
- package/dist/analysis/semantic/summarizer.d.ts.map +1 -0
- package/dist/analysis/semantic/summarizer.js +229 -0
- package/dist/analysis/semantic/summarizer.js.map +1 -0
- package/dist/analysis/ts-js-visitor.d.ts +4 -0
- package/dist/analysis/ts-js-visitor.d.ts.map +1 -0
- package/dist/analysis/ts-js-visitor.js +390 -0
- package/dist/analysis/ts-js-visitor.js.map +1 -0
- package/dist/analysis/visitor-registry.d.ts +5 -0
- package/dist/analysis/visitor-registry.d.ts.map +1 -0
- package/dist/analysis/visitor-registry.js +17 -0
- package/dist/analysis/visitor-registry.js.map +1 -0
- package/dist/analysis/visitor-utils.d.ts +38 -0
- package/dist/analysis/visitor-utils.d.ts.map +1 -0
- package/dist/analysis/visitor-utils.js +110 -0
- package/dist/analysis/visitor-utils.js.map +1 -0
- package/dist/errors.d.ts +20 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +39 -0
- package/dist/errors.js.map +1 -0
- package/dist/expeditions/custom.d.ts +11 -0
- package/dist/expeditions/custom.d.ts.map +1 -0
- package/dist/expeditions/custom.js +61 -0
- package/dist/expeditions/custom.js.map +1 -0
- package/dist/expeditions/danger-zones.d.ts +9 -0
- package/dist/expeditions/danger-zones.d.ts.map +1 -0
- package/dist/expeditions/danger-zones.js +42 -0
- package/dist/expeditions/danger-zones.js.map +1 -0
- package/dist/expeditions/generator.d.ts +21 -0
- package/dist/expeditions/generator.d.ts.map +1 -0
- package/dist/expeditions/generator.js +78 -0
- package/dist/expeditions/generator.js.map +1 -0
- package/dist/expeditions/grand-tour.d.ts +10 -0
- package/dist/expeditions/grand-tour.d.ts.map +1 -0
- package/dist/expeditions/grand-tour.js +96 -0
- package/dist/expeditions/grand-tour.js.map +1 -0
- package/dist/expeditions/request-flow.d.ts +11 -0
- package/dist/expeditions/request-flow.d.ts.map +1 -0
- package/dist/expeditions/request-flow.js +138 -0
- package/dist/expeditions/request-flow.js.map +1 -0
- package/dist/grammars/tree-sitter-go.wasm +0 -0
- package/dist/grammars/tree-sitter-java.wasm +0 -0
- package/dist/grammars/tree-sitter-javascript.wasm +0 -0
- package/dist/grammars/tree-sitter-python.wasm +0 -0
- package/dist/grammars/tree-sitter-rust.wasm +0 -0
- package/dist/grammars/tree-sitter-tsx.wasm +0 -0
- package/dist/grammars/tree-sitter-typescript.wasm +0 -0
- package/dist/graph/builder.d.ts +23 -0
- package/dist/graph/builder.d.ts.map +1 -0
- package/dist/graph/builder.js +131 -0
- package/dist/graph/builder.js.map +1 -0
- package/dist/graph/exporter.d.ts +5 -0
- package/dist/graph/exporter.d.ts.map +1 -0
- package/dist/graph/exporter.js +20 -0
- package/dist/graph/exporter.js.map +1 -0
- package/dist/graph/layout.d.ts +3 -0
- package/dist/graph/layout.d.ts.map +1 -0
- package/dist/graph/layout.js +257 -0
- package/dist/graph/layout.js.map +1 -0
- package/dist/graph/store.d.ts +13 -0
- package/dist/graph/store.d.ts.map +1 -0
- package/dist/graph/store.js +145 -0
- package/dist/graph/store.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/index.js.map +1 -0
- package/dist/ingestion/cloner.d.ts +18 -0
- package/dist/ingestion/cloner.d.ts.map +1 -0
- package/dist/ingestion/cloner.js +62 -0
- package/dist/ingestion/cloner.js.map +1 -0
- package/dist/ingestion/file-tree.d.ts +3 -0
- package/dist/ingestion/file-tree.d.ts.map +1 -0
- package/dist/ingestion/file-tree.js +85 -0
- package/dist/ingestion/file-tree.js.map +1 -0
- package/dist/ingestion/index.d.ts +5 -0
- package/dist/ingestion/index.d.ts.map +1 -0
- package/dist/ingestion/index.js +5 -0
- package/dist/ingestion/index.js.map +1 -0
- package/dist/ingestion/language-detector.d.ts +8 -0
- package/dist/ingestion/language-detector.d.ts.map +1 -0
- package/dist/ingestion/language-detector.js +37 -0
- package/dist/ingestion/language-detector.js.map +1 -0
- package/dist/ingestion/path-resolver.d.ts +7 -0
- package/dist/ingestion/path-resolver.d.ts.map +1 -0
- package/dist/ingestion/path-resolver.js +30 -0
- package/dist/ingestion/path-resolver.js.map +1 -0
- package/dist/logger.d.ts +3 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +11 -0
- package/dist/logger.js.map +1 -0
- package/dist/pipeline.d.ts +3 -0
- package/dist/pipeline.d.ts.map +1 -0
- package/dist/pipeline.js +223 -0
- package/dist/pipeline.js.map +1 -0
- package/dist/types/analysis.d.ts +51 -0
- package/dist/types/analysis.d.ts.map +1 -0
- package/dist/types/analysis.js +2 -0
- package/dist/types/analysis.js.map +1 -0
- package/dist/types/config.d.ts +19 -0
- package/dist/types/config.d.ts.map +1 -0
- package/dist/types/config.js +2 -0
- package/dist/types/config.js.map +1 -0
- package/dist/types/edges.d.ts +8 -0
- package/dist/types/edges.d.ts.map +1 -0
- package/dist/types/edges.js +2 -0
- package/dist/types/edges.js.map +1 -0
- package/dist/types/expeditions.d.ts +19 -0
- package/dist/types/expeditions.d.ts.map +1 -0
- package/dist/types/expeditions.js +2 -0
- package/dist/types/expeditions.js.map +1 -0
- package/dist/types/graph.d.ts +29 -0
- package/dist/types/graph.d.ts.map +1 -0
- package/dist/types/graph.js +2 -0
- package/dist/types/graph.js.map +1 -0
- package/dist/types/index.d.ts +7 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/nodes.d.ts +35 -0
- package/dist/types/nodes.d.ts.map +1 -0
- package/dist/types/nodes.js +2 -0
- package/dist/types/nodes.js.map +1 -0
- package/package.json +36 -0
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
import { countLOC, truncateBody, extractStringLiteral, findDescendantByType, extractCallSitesGeneric, computeComplexityGeneric } from "./visitor-utils.js";
|
|
2
|
+
// --- Complexity ---
|
|
3
|
+
const GO_COMPLEXITY_TYPES = new Set([
|
|
4
|
+
"if_statement",
|
|
5
|
+
"for_statement",
|
|
6
|
+
"select_statement",
|
|
7
|
+
"type_switch_statement",
|
|
8
|
+
"expression_switch_statement",
|
|
9
|
+
]);
|
|
10
|
+
function computeComplexity(node) {
|
|
11
|
+
return computeComplexityGeneric(node, GO_COMPLEXITY_TYPES, (n) => {
|
|
12
|
+
// Count individual case clauses in switch/select
|
|
13
|
+
if (n.type === "expression_case" || n.type === "type_case" || n.type === "communication_case") {
|
|
14
|
+
return 1;
|
|
15
|
+
}
|
|
16
|
+
// Count logical && and || in binary expressions
|
|
17
|
+
if (n.type === "binary_expression") {
|
|
18
|
+
const op = n.children.find((c) => c.type === "&&" || c.type === "||");
|
|
19
|
+
if (op)
|
|
20
|
+
return 1;
|
|
21
|
+
}
|
|
22
|
+
return 0;
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
// --- Call sites ---
|
|
26
|
+
function extractCallSites(node) {
|
|
27
|
+
return extractCallSitesGeneric(node, "call_expression", (callNode) => {
|
|
28
|
+
const fnNode = callNode.childForFieldName("function") ?? callNode.children[0];
|
|
29
|
+
if (!fnNode)
|
|
30
|
+
return null;
|
|
31
|
+
if (fnNode.type === "identifier") {
|
|
32
|
+
return fnNode.text;
|
|
33
|
+
}
|
|
34
|
+
if (fnNode.type === "selector_expression") {
|
|
35
|
+
// pkg.Func() or obj.Method() -> extract the field (right-hand side)
|
|
36
|
+
const field = fnNode.childForFieldName("field");
|
|
37
|
+
if (field)
|
|
38
|
+
return field.text;
|
|
39
|
+
}
|
|
40
|
+
return null;
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
// --- Imports ---
|
|
44
|
+
function extractImports(root) {
|
|
45
|
+
const imports = [];
|
|
46
|
+
for (const child of root.children) {
|
|
47
|
+
if (child.type === "import_declaration") {
|
|
48
|
+
// Single import: import "fmt"
|
|
49
|
+
// Grouped import: import ( "fmt"\n "os" )
|
|
50
|
+
const specList = child.children.find((c) => c.type === "import_spec_list");
|
|
51
|
+
if (specList) {
|
|
52
|
+
for (const spec of specList.children) {
|
|
53
|
+
if (spec.type === "import_spec") {
|
|
54
|
+
const imp = extractImportSpec(spec);
|
|
55
|
+
if (imp)
|
|
56
|
+
imports.push(imp);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
// Single import_spec directly under import_declaration
|
|
62
|
+
const spec = child.children.find((c) => c.type === "import_spec");
|
|
63
|
+
if (spec) {
|
|
64
|
+
const imp = extractImportSpec(spec);
|
|
65
|
+
if (imp)
|
|
66
|
+
imports.push(imp);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
return imports;
|
|
72
|
+
}
|
|
73
|
+
function extractImportSpec(spec) {
|
|
74
|
+
const pathNode = spec.childForFieldName("path") ?? spec.children.find((c) => c.type === "interpreted_string_literal");
|
|
75
|
+
if (!pathNode)
|
|
76
|
+
return null;
|
|
77
|
+
const source = extractStringLiteral(pathNode);
|
|
78
|
+
const nameNode = spec.childForFieldName("name");
|
|
79
|
+
const alias = nameNode?.text;
|
|
80
|
+
// If there's a dot import (. "pkg"), import all names
|
|
81
|
+
const isDotImport = alias === ".";
|
|
82
|
+
// If there's a blank import (_ "pkg"), side-effect only
|
|
83
|
+
const isBlankImport = alias === "_";
|
|
84
|
+
const names = [];
|
|
85
|
+
if (isDotImport) {
|
|
86
|
+
names.push("*");
|
|
87
|
+
}
|
|
88
|
+
else if (isBlankImport) {
|
|
89
|
+
names.push("_");
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
// Normal import: the package name is the last segment of the path
|
|
93
|
+
const pkgName = alias ?? source.split("/").pop() ?? source;
|
|
94
|
+
names.push(pkgName);
|
|
95
|
+
}
|
|
96
|
+
return {
|
|
97
|
+
source,
|
|
98
|
+
resolvedPath: null,
|
|
99
|
+
names,
|
|
100
|
+
isTypeOnly: false,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// --- Exports ---
|
|
104
|
+
// In Go, exported identifiers start with an uppercase letter.
|
|
105
|
+
function extractExports(root) {
|
|
106
|
+
const exports = [];
|
|
107
|
+
for (const child of root.children) {
|
|
108
|
+
if (child.type === "function_declaration") {
|
|
109
|
+
const nameNode = child.childForFieldName("name");
|
|
110
|
+
if (nameNode && isExportedName(nameNode.text)) {
|
|
111
|
+
exports.push({
|
|
112
|
+
name: nameNode.text,
|
|
113
|
+
kind: "function",
|
|
114
|
+
isTypeOnly: false,
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
else if (child.type === "method_declaration") {
|
|
119
|
+
const nameNode = child.childForFieldName("name");
|
|
120
|
+
if (nameNode && isExportedName(nameNode.text)) {
|
|
121
|
+
exports.push({
|
|
122
|
+
name: nameNode.text,
|
|
123
|
+
kind: "function",
|
|
124
|
+
isTypeOnly: false,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else if (child.type === "type_declaration") {
|
|
129
|
+
// type Foo struct { ... } or type Bar interface { ... }
|
|
130
|
+
for (const spec of child.children) {
|
|
131
|
+
if (spec.type === "type_spec") {
|
|
132
|
+
const nameNode = spec.childForFieldName("name");
|
|
133
|
+
if (nameNode && isExportedName(nameNode.text)) {
|
|
134
|
+
const typeNode = spec.childForFieldName("type");
|
|
135
|
+
const kind = typeNode?.type === "interface_type" ? "interface" : "class";
|
|
136
|
+
exports.push({
|
|
137
|
+
name: nameNode.text,
|
|
138
|
+
kind,
|
|
139
|
+
isTypeOnly: kind === "interface",
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
else if (child.type === "var_declaration" || child.type === "const_declaration") {
|
|
146
|
+
for (const spec of child.children) {
|
|
147
|
+
if (spec.type === "var_spec" || spec.type === "const_spec") {
|
|
148
|
+
const nameNode = spec.childForFieldName("name");
|
|
149
|
+
if (nameNode && isExportedName(nameNode.text)) {
|
|
150
|
+
exports.push({
|
|
151
|
+
name: nameNode.text,
|
|
152
|
+
kind: "variable",
|
|
153
|
+
isTypeOnly: false,
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
// Also check for multiple names in a single spec
|
|
157
|
+
for (const c of spec.children) {
|
|
158
|
+
if (c.type === "identifier" && c !== nameNode && isExportedName(c.text)) {
|
|
159
|
+
exports.push({
|
|
160
|
+
name: c.text,
|
|
161
|
+
kind: "variable",
|
|
162
|
+
isTypeOnly: false,
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return exports;
|
|
171
|
+
}
|
|
172
|
+
function isExportedName(name) {
|
|
173
|
+
if (name.length === 0)
|
|
174
|
+
return false;
|
|
175
|
+
const firstChar = name.charAt(0);
|
|
176
|
+
return firstChar === firstChar.toUpperCase() && firstChar !== firstChar.toLowerCase();
|
|
177
|
+
}
|
|
178
|
+
// --- Package ---
|
|
179
|
+
function extractPackageName(root) {
|
|
180
|
+
for (const child of root.children) {
|
|
181
|
+
if (child.type === "package_clause") {
|
|
182
|
+
const nameNode = child.children.find((c) => c.type === "package_identifier");
|
|
183
|
+
if (nameNode)
|
|
184
|
+
return nameNode.text;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
// --- Functions ---
|
|
190
|
+
function extractFunctions(root, content) {
|
|
191
|
+
const functions = [];
|
|
192
|
+
for (const child of root.children) {
|
|
193
|
+
if (child.type === "function_declaration") {
|
|
194
|
+
const nameNode = child.childForFieldName("name");
|
|
195
|
+
if (nameNode) {
|
|
196
|
+
const params = extractGoParams(child);
|
|
197
|
+
const returnType = extractGoReturnType(child);
|
|
198
|
+
const bodyNode = child.childForFieldName("body") ?? child;
|
|
199
|
+
const isExported = isExportedName(nameNode.text);
|
|
200
|
+
functions.push({
|
|
201
|
+
name: nameNode.text,
|
|
202
|
+
startLine: child.startPosition.row + 1,
|
|
203
|
+
endLine: child.endPosition.row + 1,
|
|
204
|
+
params,
|
|
205
|
+
returnType,
|
|
206
|
+
isExported,
|
|
207
|
+
isAsync: false, // Go doesn't have async functions
|
|
208
|
+
body: truncateBody(child.text, 200),
|
|
209
|
+
complexity: computeComplexity(bodyNode),
|
|
210
|
+
calls: extractCallSites(bodyNode),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
else if (child.type === "method_declaration") {
|
|
215
|
+
const nameNode = child.childForFieldName("name");
|
|
216
|
+
if (nameNode) {
|
|
217
|
+
const params = extractGoParams(child);
|
|
218
|
+
const returnType = extractGoReturnType(child);
|
|
219
|
+
const bodyNode = child.childForFieldName("body") ?? child;
|
|
220
|
+
const isExported = isExportedName(nameNode.text);
|
|
221
|
+
// Include receiver type in name for disambiguation
|
|
222
|
+
const receiver = child.childForFieldName("receiver");
|
|
223
|
+
const receiverType = receiver ? extractReceiverType(receiver) : null;
|
|
224
|
+
const fullName = receiverType ? `${receiverType}.${nameNode.text}` : nameNode.text;
|
|
225
|
+
functions.push({
|
|
226
|
+
name: fullName,
|
|
227
|
+
startLine: child.startPosition.row + 1,
|
|
228
|
+
endLine: child.endPosition.row + 1,
|
|
229
|
+
params,
|
|
230
|
+
returnType,
|
|
231
|
+
isExported,
|
|
232
|
+
isAsync: false,
|
|
233
|
+
body: truncateBody(child.text, 200),
|
|
234
|
+
complexity: computeComplexity(bodyNode),
|
|
235
|
+
calls: extractCallSites(bodyNode),
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return functions;
|
|
241
|
+
}
|
|
242
|
+
function extractGoParams(funcNode) {
|
|
243
|
+
const params = funcNode.childForFieldName("parameters");
|
|
244
|
+
if (!params)
|
|
245
|
+
return [];
|
|
246
|
+
return params.children
|
|
247
|
+
.filter((c) => c.type === "parameter_declaration")
|
|
248
|
+
.flatMap((c) => {
|
|
249
|
+
// A parameter_declaration can have multiple names: a, b int
|
|
250
|
+
const names = [];
|
|
251
|
+
for (const n of c.children) {
|
|
252
|
+
if (n.type === "identifier") {
|
|
253
|
+
names.push(n.text);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return names.length > 0 ? names : [c.text];
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
function extractGoReturnType(funcNode) {
|
|
260
|
+
const result = funcNode.childForFieldName("result");
|
|
261
|
+
if (!result)
|
|
262
|
+
return null;
|
|
263
|
+
return result.text;
|
|
264
|
+
}
|
|
265
|
+
function extractReceiverType(receiver) {
|
|
266
|
+
// Receiver: (r *Router) or (r Router)
|
|
267
|
+
const paramDecl = receiver.children.find((c) => c.type === "parameter_declaration");
|
|
268
|
+
if (!paramDecl)
|
|
269
|
+
return null;
|
|
270
|
+
const typeNode = paramDecl.childForFieldName("type");
|
|
271
|
+
if (typeNode) {
|
|
272
|
+
// Strip pointer: *Router -> Router
|
|
273
|
+
const text = typeNode.text;
|
|
274
|
+
return text.startsWith("*") ? text.slice(1) : text;
|
|
275
|
+
}
|
|
276
|
+
return null;
|
|
277
|
+
}
|
|
278
|
+
// --- Main visitor ---
|
|
279
|
+
export function visitFile(content, tree, filePath) {
|
|
280
|
+
const root = tree.rootNode;
|
|
281
|
+
const imports = extractImports(root);
|
|
282
|
+
const exports = extractExports(root);
|
|
283
|
+
const loc = countLOC(content, tree);
|
|
284
|
+
const functions = extractFunctions(root, content);
|
|
285
|
+
return {
|
|
286
|
+
filePath,
|
|
287
|
+
language: "go",
|
|
288
|
+
content,
|
|
289
|
+
loc,
|
|
290
|
+
imports,
|
|
291
|
+
exports,
|
|
292
|
+
functions,
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
//# sourceMappingURL=go-visitor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"go-visitor.js","sourceRoot":"","sources":["../../src/analysis/go-visitor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Individual health indicator functions.
|
|
3
|
+
* Each returns a score from 0 to 100, where higher is better.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Compute an inverted TODO/FIXME/HACK/XXX density score.
|
|
7
|
+
* 0 occurrences = 100. >5 per 100 LOC = 0.
|
|
8
|
+
*/
|
|
9
|
+
export declare function computeTodoDensity(content: string, loc: number): number;
|
|
10
|
+
/**
|
|
11
|
+
* Compute a type safety score based on file extension.
|
|
12
|
+
* TypeScript files get full score; JavaScript gets partial; others get 0.
|
|
13
|
+
*/
|
|
14
|
+
export declare function computeTypeSafety(filePath: string): number;
|
|
15
|
+
/**
|
|
16
|
+
* Pass through the doc coverage percentage computed from FileMetrics.
|
|
17
|
+
* Clamps to 0-100 range.
|
|
18
|
+
*/
|
|
19
|
+
export declare function computeDocCoverage(docCoveragePercent: number): number;
|
|
20
|
+
/**
|
|
21
|
+
* Dependency health score. Currently returns a default value.
|
|
22
|
+
* Proper implementation (checking outdated deps) is deferred.
|
|
23
|
+
*/
|
|
24
|
+
export declare function computeDepHealth(): number;
|
|
25
|
+
//# sourceMappingURL=indicators.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indicators.d.ts","sourceRoot":"","sources":["../../../src/analysis/health/indicators.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAavE;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAa1D;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,kBAAkB,EAAE,MAAM,GAAG,MAAM,CAErE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Individual health indicator functions.
|
|
3
|
+
* Each returns a score from 0 to 100, where higher is better.
|
|
4
|
+
*/
|
|
5
|
+
const TODO_REGEX = /\b(TODO|FIXME|HACK|XXX)\b/gi;
|
|
6
|
+
/**
|
|
7
|
+
* Compute an inverted TODO/FIXME/HACK/XXX density score.
|
|
8
|
+
* 0 occurrences = 100. >5 per 100 LOC = 0.
|
|
9
|
+
*/
|
|
10
|
+
export function computeTodoDensity(content, loc) {
|
|
11
|
+
if (loc <= 0)
|
|
12
|
+
return 100;
|
|
13
|
+
const matches = content.match(TODO_REGEX);
|
|
14
|
+
const count = matches ? matches.length : 0;
|
|
15
|
+
if (count === 0)
|
|
16
|
+
return 100;
|
|
17
|
+
const densityPer100 = (count / loc) * 100;
|
|
18
|
+
// Linear scale: 0 density = 100, >= 5 per 100 LOC = 0
|
|
19
|
+
const score = Math.max(0, 100 - (densityPer100 / 5) * 100);
|
|
20
|
+
return Math.round(score);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Compute a type safety score based on file extension.
|
|
24
|
+
* TypeScript files get full score; JavaScript gets partial; others get 0.
|
|
25
|
+
*/
|
|
26
|
+
export function computeTypeSafety(filePath) {
|
|
27
|
+
const ext = filePath.slice(filePath.lastIndexOf(".")).toLowerCase();
|
|
28
|
+
switch (ext) {
|
|
29
|
+
case ".ts":
|
|
30
|
+
case ".tsx":
|
|
31
|
+
return 100;
|
|
32
|
+
case ".js":
|
|
33
|
+
case ".jsx":
|
|
34
|
+
return 30;
|
|
35
|
+
default:
|
|
36
|
+
return 0;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Pass through the doc coverage percentage computed from FileMetrics.
|
|
41
|
+
* Clamps to 0-100 range.
|
|
42
|
+
*/
|
|
43
|
+
export function computeDocCoverage(docCoveragePercent) {
|
|
44
|
+
return Math.round(Math.max(0, Math.min(100, docCoveragePercent)));
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Dependency health score. Currently returns a default value.
|
|
48
|
+
* Proper implementation (checking outdated deps) is deferred.
|
|
49
|
+
*/
|
|
50
|
+
export function computeDepHealth() {
|
|
51
|
+
return 80;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=indicators.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"indicators.js","sourceRoot":"","sources":["../../../src/analysis/health/indicators.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,UAAU,GAAG,6BAA6B,CAAC;AAEjD;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAAe,EAAE,GAAW;IAC7D,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC;IAEzB,MAAM,OAAO,GAAG,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;IAC1C,MAAM,KAAK,GAAG,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;IAE3C,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,GAAG,CAAC;IAE5B,MAAM,aAAa,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC;IAE1C,sDAAsD;IACtD,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,aAAa,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC3B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,iBAAiB,CAAC,QAAgB;IAChD,MAAM,GAAG,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IAEpE,QAAQ,GAAG,EAAE,CAAC;QACZ,KAAK,KAAK,CAAC;QACX,KAAK,MAAM;YACT,OAAO,GAAG,CAAC;QACb,KAAK,KAAK,CAAC;QACX,KAAK,MAAM;YACT,OAAO,EAAE,CAAC;QACZ;YACE,OAAO,CAAC,CAAC;IACb,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,kBAAkB,CAAC,kBAA0B;IAC3D,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;AACpE,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO,EAAE,CAAC;AACZ,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { FileAnalysis, FileEntry } from "../../types/index.js";
|
|
2
|
+
import type { FileMetrics } from "../metrics.js";
|
|
3
|
+
export interface HealthInputs {
|
|
4
|
+
testScore: number;
|
|
5
|
+
complexityInv: number;
|
|
6
|
+
churnStability: number;
|
|
7
|
+
todoDensityInv: number;
|
|
8
|
+
typeSafety: number;
|
|
9
|
+
docCoverage: number;
|
|
10
|
+
depHealth: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Compute a composite health score from individual indicator scores.
|
|
14
|
+
* Result is clamped to 0-100.
|
|
15
|
+
*/
|
|
16
|
+
export declare function computeHealthScore(inputs: HealthInputs): number;
|
|
17
|
+
/**
|
|
18
|
+
* Entry point that computes health scores for all analyzed files.
|
|
19
|
+
*
|
|
20
|
+
* When churnMap is absent (e.g. --skip-git), a neutral default of 75 is used.
|
|
21
|
+
* When allFiles is provided, test file detection uses all file paths for matching.
|
|
22
|
+
*/
|
|
23
|
+
export declare function computeAllHealthScores(analyses: FileAnalysis[], fileMetrics: Map<string, FileMetrics>, churnMap?: Map<string, {
|
|
24
|
+
churnScore: number;
|
|
25
|
+
}>, allFiles?: FileEntry[]): Map<string, number>;
|
|
26
|
+
//# sourceMappingURL=scorer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scorer.d.ts","sourceRoot":"","sources":["../../../src/analysis/health/scorer.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAIjD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;CACnB;AAYD;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAW/D;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,QAAQ,EAAE,YAAY,EAAE,EACxB,WAAW,EAAE,GAAG,CAAC,MAAM,EAAE,WAAW,CAAC,EACrC,QAAQ,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE;IAAE,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,EAC9C,QAAQ,CAAC,EAAE,SAAS,EAAE,GACrB,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA+ErB"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { logger } from "../../logger.js";
|
|
2
|
+
import { computeTodoDensity, computeTypeSafety, computeDocCoverage, computeDepHealth } from "./indicators.js";
|
|
3
|
+
import { detectTestFiles, computeTestScore } from "./test-coverage.js";
|
|
4
|
+
const WEIGHTS = {
|
|
5
|
+
testScore: 0.25,
|
|
6
|
+
complexityInv: 0.20,
|
|
7
|
+
churnStability: 0.15,
|
|
8
|
+
todoDensityInv: 0.10,
|
|
9
|
+
typeSafety: 0.10,
|
|
10
|
+
docCoverage: 0.10,
|
|
11
|
+
depHealth: 0.10,
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Compute a composite health score from individual indicator scores.
|
|
15
|
+
* Result is clamped to 0-100.
|
|
16
|
+
*/
|
|
17
|
+
export function computeHealthScore(inputs) {
|
|
18
|
+
const raw = inputs.testScore * WEIGHTS.testScore +
|
|
19
|
+
inputs.complexityInv * WEIGHTS.complexityInv +
|
|
20
|
+
inputs.churnStability * WEIGHTS.churnStability +
|
|
21
|
+
inputs.todoDensityInv * WEIGHTS.todoDensityInv +
|
|
22
|
+
inputs.typeSafety * WEIGHTS.typeSafety +
|
|
23
|
+
inputs.docCoverage * WEIGHTS.docCoverage +
|
|
24
|
+
inputs.depHealth * WEIGHTS.depHealth;
|
|
25
|
+
return Math.round(Math.max(0, Math.min(100, raw)));
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Entry point that computes health scores for all analyzed files.
|
|
29
|
+
*
|
|
30
|
+
* When churnMap is absent (e.g. --skip-git), a neutral default of 75 is used.
|
|
31
|
+
* When allFiles is provided, test file detection uses all file paths for matching.
|
|
32
|
+
*/
|
|
33
|
+
export function computeAllHealthScores(analyses, fileMetrics, churnMap, allFiles) {
|
|
34
|
+
const healthScores = new Map();
|
|
35
|
+
// Gather all file paths for test detection
|
|
36
|
+
const allFilePaths = allFiles
|
|
37
|
+
? allFiles.map((f) => f.relativePath)
|
|
38
|
+
: [...fileMetrics.keys()];
|
|
39
|
+
// Detect test file mappings
|
|
40
|
+
const testMap = detectTestFiles(allFilePaths);
|
|
41
|
+
// Build a quick lookup: normalized path -> FileAnalysis for test LOC
|
|
42
|
+
const analysisMap = new Map();
|
|
43
|
+
for (const a of analyses) {
|
|
44
|
+
analysisMap.set(a.filePath.replace(/\\/g, "/"), a);
|
|
45
|
+
}
|
|
46
|
+
// Determine max complexity across all files for normalization
|
|
47
|
+
let maxComplexity = 0;
|
|
48
|
+
for (const fm of fileMetrics.values()) {
|
|
49
|
+
if (fm.complexity > maxComplexity) {
|
|
50
|
+
maxComplexity = fm.complexity;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
logger.debug(`Health scoring: ${fileMetrics.size} files, maxComplexity=${maxComplexity}`);
|
|
54
|
+
for (const [filePath, fm] of fileMetrics) {
|
|
55
|
+
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
56
|
+
// Test score
|
|
57
|
+
const testPath = testMap.get(normalizedPath) ?? null;
|
|
58
|
+
let testLoc = 0;
|
|
59
|
+
if (testPath) {
|
|
60
|
+
const testAnalysis = analysisMap.get(testPath);
|
|
61
|
+
testLoc = testAnalysis?.loc ?? 0;
|
|
62
|
+
}
|
|
63
|
+
const testScore = computeTestScore(normalizedPath, testPath, testLoc, fm.loc);
|
|
64
|
+
// Complexity inverse: 100 means zero complexity, 0 means at-or-above max
|
|
65
|
+
const complexityInv = maxComplexity > 0
|
|
66
|
+
? Math.round(100 - Math.min((fm.complexity / maxComplexity) * 100, 100))
|
|
67
|
+
: 100;
|
|
68
|
+
// Churn stability: invert the churn score (high churn = low stability)
|
|
69
|
+
const churnData = churnMap?.get(normalizedPath);
|
|
70
|
+
const churnStability = churnData
|
|
71
|
+
? Math.round((1 - churnData.churnScore) * 100)
|
|
72
|
+
: 75; // neutral default when git data unavailable
|
|
73
|
+
// TODO density inverse
|
|
74
|
+
const analysis = analysisMap.get(normalizedPath);
|
|
75
|
+
const content = analysis?.content ?? "";
|
|
76
|
+
const todoDensityInv = computeTodoDensity(content, fm.loc);
|
|
77
|
+
// Type safety
|
|
78
|
+
const typeSafety = computeTypeSafety(normalizedPath);
|
|
79
|
+
// Doc coverage
|
|
80
|
+
const docCoverage = computeDocCoverage(fm.docCoverage);
|
|
81
|
+
// Dependency health
|
|
82
|
+
const depHealth = computeDepHealth();
|
|
83
|
+
const score = computeHealthScore({
|
|
84
|
+
testScore,
|
|
85
|
+
complexityInv,
|
|
86
|
+
churnStability,
|
|
87
|
+
todoDensityInv,
|
|
88
|
+
typeSafety,
|
|
89
|
+
docCoverage,
|
|
90
|
+
depHealth,
|
|
91
|
+
});
|
|
92
|
+
healthScores.set(normalizedPath, score);
|
|
93
|
+
}
|
|
94
|
+
logger.debug(`Health scoring complete: ${healthScores.size} files scored`);
|
|
95
|
+
return healthScores;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=scorer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scorer.js","sourceRoot":"","sources":["../../../src/analysis/health/scorer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Detect test files and map source files to their corresponding test files.
|
|
3
|
+
*
|
|
4
|
+
* Convention matching:
|
|
5
|
+
* - foo.ts -> foo.test.ts, foo.spec.ts
|
|
6
|
+
* - foo.ts -> __tests__/foo.test.ts, __tests__/foo.spec.ts
|
|
7
|
+
*
|
|
8
|
+
* Returns a map from source file path to its test file path (or null if none found).
|
|
9
|
+
*/
|
|
10
|
+
export declare function detectTestFiles(allFilePaths: string[]): Map<string, string | null>;
|
|
11
|
+
/**
|
|
12
|
+
* Compute a test score for a single source file.
|
|
13
|
+
*
|
|
14
|
+
* - No test file: 0
|
|
15
|
+
* - Test file exists but small (LOC ratio < 0.3): 50
|
|
16
|
+
* - Test file with good ratio (>= 0.3): 100
|
|
17
|
+
*/
|
|
18
|
+
export declare function computeTestScore(_sourcePath: string, testPath: string | null, testLoc: number, sourceLoc: number): number;
|
|
19
|
+
//# sourceMappingURL=test-coverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-coverage.d.ts","sourceRoot":"","sources":["../../../src/analysis/health/test-coverage.ts"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,YAAY,EAAE,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CA+ClF;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,GAChB,MAAM,CAOR"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
/**
|
|
3
|
+
* Detect test files and map source files to their corresponding test files.
|
|
4
|
+
*
|
|
5
|
+
* Convention matching:
|
|
6
|
+
* - foo.ts -> foo.test.ts, foo.spec.ts
|
|
7
|
+
* - foo.ts -> __tests__/foo.test.ts, __tests__/foo.spec.ts
|
|
8
|
+
*
|
|
9
|
+
* Returns a map from source file path to its test file path (or null if none found).
|
|
10
|
+
*/
|
|
11
|
+
export function detectTestFiles(allFilePaths) {
|
|
12
|
+
const testFilePattern = /\.(test|spec)\.[^.]+$/;
|
|
13
|
+
const testDirPattern = /[/\\]__tests__[/\\]/;
|
|
14
|
+
// Collect all test file paths into a Set for fast lookup
|
|
15
|
+
const testFiles = new Set();
|
|
16
|
+
const sourceFiles = [];
|
|
17
|
+
for (const fp of allFilePaths) {
|
|
18
|
+
const normalized = fp.replace(/\\/g, "/");
|
|
19
|
+
if (testFilePattern.test(normalized) || testDirPattern.test(normalized)) {
|
|
20
|
+
testFiles.add(normalized);
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
sourceFiles.push(normalized);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const result = new Map();
|
|
27
|
+
for (const sourcePath of sourceFiles) {
|
|
28
|
+
const normalized = sourcePath.replace(/\\/g, "/");
|
|
29
|
+
const dir = path.posix.dirname(normalized);
|
|
30
|
+
const ext = path.posix.extname(normalized);
|
|
31
|
+
const baseName = path.posix.basename(normalized, ext);
|
|
32
|
+
// Candidates to check, in priority order
|
|
33
|
+
const candidates = [
|
|
34
|
+
// Same directory: foo.test.ext, foo.spec.ext
|
|
35
|
+
`${dir}/${baseName}.test${ext}`,
|
|
36
|
+
`${dir}/${baseName}.spec${ext}`,
|
|
37
|
+
// __tests__ subdirectory: __tests__/foo.test.ext, __tests__/foo.spec.ext
|
|
38
|
+
`${dir}/__tests__/${baseName}.test${ext}`,
|
|
39
|
+
`${dir}/__tests__/${baseName}.spec${ext}`,
|
|
40
|
+
];
|
|
41
|
+
let matched = null;
|
|
42
|
+
for (const candidate of candidates) {
|
|
43
|
+
if (testFiles.has(candidate)) {
|
|
44
|
+
matched = candidate;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
result.set(normalized, matched);
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Compute a test score for a single source file.
|
|
54
|
+
*
|
|
55
|
+
* - No test file: 0
|
|
56
|
+
* - Test file exists but small (LOC ratio < 0.3): 50
|
|
57
|
+
* - Test file with good ratio (>= 0.3): 100
|
|
58
|
+
*/
|
|
59
|
+
export function computeTestScore(_sourcePath, testPath, testLoc, sourceLoc) {
|
|
60
|
+
if (testPath === null)
|
|
61
|
+
return 0;
|
|
62
|
+
if (sourceLoc <= 0)
|
|
63
|
+
return 100; // Trivial source file with a test
|
|
64
|
+
const ratio = testLoc / sourceLoc;
|
|
65
|
+
return ratio >= 0.3 ? 100 : 50;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=test-coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"test-coverage.js","sourceRoot":"","sources":["../../../src/analysis/health/test-coverage.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B;;;;;;;;GAQG;AACH,MAAM,UAAU,eAAe,CAAC,YAAsB;IACpD,MAAM,eAAe,GAAG,uBAAuB,CAAC;IAChD,MAAM,cAAc,GAAG,qBAAqB,CAAC;IAE7C,yDAAyD;IACzD,MAAM,SAAS,GAAG,IAAI,GAAG,EAAU,CAAC;IACpC,MAAM,WAAW,GAAa,EAAE,CAAC;IAEjC,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;QAC9B,MAAM,UAAU,GAAG,EAAE,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAC1C,IAAI,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAAC;YACxE,SAAS,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,GAAG,EAAyB,CAAC;IAEhD,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;QAClD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC3C,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC;QAEtD,yCAAyC;QACzC,MAAM,UAAU,GAAG;YACjB,6CAA6C;YAC7C,GAAG,GAAG,IAAI,QAAQ,QAAQ,GAAG,EAAE;YAC/B,GAAG,GAAG,IAAI,QAAQ,QAAQ,GAAG,EAAE;YAC/B,yEAAyE;YACzE,GAAG,GAAG,cAAc,QAAQ,QAAQ,GAAG,EAAE;YACzC,GAAG,GAAG,cAAc,QAAQ,QAAQ,GAAG,EAAE;SAC1C,CAAC;QAEF,IAAI,OAAO,GAAkB,IAAI,CAAC;QAClC,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,IAAI,SAAS,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7B,OAAO,GAAG,SAAS,CAAC;gBACpB,MAAM;YACR,CAAC;QACH,CAAC;QAED,MAAM,CAAC,GAAG,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;IAClC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAmB,EACnB,QAAuB,EACvB,OAAe,EACf,SAAiB;IAEjB,IAAI,QAAQ,KAAK,IAAI;QAAE,OAAO,CAAC,CAAC;IAEhC,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,GAAG,CAAC,CAAC,kCAAkC;IAElE,MAAM,KAAK,GAAG,OAAO,GAAG,SAAS,CAAC;IAClC,OAAO,KAAK,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;AACjC,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { FileAnalysis, SupportedLanguage } from "../types/index.js";
|
|
2
|
+
interface TsConfigPaths {
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
paths: Record<string, string[]>;
|
|
5
|
+
}
|
|
6
|
+
export declare function loadTsConfigPaths(rootDir: string): TsConfigPaths | null;
|
|
7
|
+
export declare function resolveImport(source: string, importingFile: string, rootDir: string, tsConfig: TsConfigPaths | null, language?: SupportedLanguage): string | null;
|
|
8
|
+
export declare function resolveAllImports(analyses: FileAnalysis[], rootDir: string, tsConfig: TsConfigPaths | null): FileAnalysis[];
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=import-resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"import-resolver.d.ts","sourceRoot":"","sources":["../../src/analysis/import-resolver.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAOzE,UAAU,aAAa;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;CACjC;AAED,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAuBvE;AA2DD,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,aAAa,GAAG,IAAI,EAC9B,QAAQ,CAAC,EAAE,iBAAiB,GAC3B,MAAM,GAAG,IAAI,CAyDf;AA+OD,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,YAAY,EAAE,EACxB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,aAAa,GAAG,IAAI,GAC7B,YAAY,EAAE,CAuBhB"}
|