@rigour-labs/core 5.0.1 → 5.1.1
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/README.md +9 -1
- package/dist/gates/agent-team.d.ts +0 -1
- package/dist/gates/agent-team.js +0 -1
- package/dist/gates/checkpoint.d.ts +0 -2
- package/dist/gates/checkpoint.js +0 -2
- package/dist/gates/context-window-artifacts.d.ts +6 -2
- package/dist/gates/context-window-artifacts.js +107 -31
- package/dist/gates/deep-analysis.d.ts +2 -0
- package/dist/gates/deep-analysis.js +41 -11
- package/dist/gates/dependency.d.ts +0 -2
- package/dist/gates/dependency.js +23 -5
- package/dist/gates/deprecated-apis.d.ts +0 -2
- package/dist/gates/deprecated-apis.js +33 -20
- package/dist/gates/duplication-drift/index.d.ts +61 -0
- package/dist/gates/duplication-drift/index.js +240 -0
- package/dist/gates/duplication-drift/similarity.d.ts +68 -0
- package/dist/gates/duplication-drift/similarity.js +177 -0
- package/dist/gates/duplication-drift/tokenizer.d.ts +55 -0
- package/dist/gates/duplication-drift/tokenizer.js +195 -0
- package/dist/gates/frontend-secret-exposure.d.ts +0 -3
- package/dist/gates/frontend-secret-exposure.js +1 -114
- package/dist/gates/frontend-secret-patterns.d.ts +33 -0
- package/dist/gates/frontend-secret-patterns.js +119 -0
- package/dist/gates/{hallucinated-imports.d.ts → hallucinated-imports/index.d.ts} +2 -29
- package/dist/gates/hallucinated-imports/index.js +174 -0
- package/dist/gates/hallucinated-imports/js-resolver.d.ts +45 -0
- package/dist/gates/hallucinated-imports/js-resolver.js +320 -0
- package/dist/gates/hallucinated-imports/manifest-discovery.d.ts +28 -0
- package/dist/gates/hallucinated-imports/manifest-discovery.js +114 -0
- package/dist/gates/hallucinated-imports/python-resolver.d.ts +24 -0
- package/dist/gates/hallucinated-imports/python-resolver.js +306 -0
- package/dist/gates/hallucinated-imports-lang.d.ts +2 -2
- package/dist/gates/hallucinated-imports-lang.js +269 -34
- package/dist/gates/hallucinated-imports.test.js +1 -2
- package/dist/gates/inconsistent-error-handling.d.ts +0 -5
- package/dist/gates/inconsistent-error-handling.js +15 -144
- package/dist/gates/language-adapters/csharp-adapter.d.ts +16 -0
- package/dist/gates/language-adapters/csharp-adapter.js +211 -0
- package/dist/gates/language-adapters/go-adapter.d.ts +26 -0
- package/dist/gates/language-adapters/go-adapter.js +195 -0
- package/dist/gates/language-adapters/index.d.ts +15 -0
- package/dist/gates/language-adapters/index.js +16 -0
- package/dist/gates/language-adapters/java-adapter.d.ts +16 -0
- package/dist/gates/language-adapters/java-adapter.js +237 -0
- package/dist/gates/language-adapters/js-adapter.d.ts +26 -0
- package/dist/gates/language-adapters/js-adapter.js +279 -0
- package/dist/gates/language-adapters/python-adapter.d.ts +25 -0
- package/dist/gates/language-adapters/python-adapter.js +183 -0
- package/dist/gates/language-adapters/registry.d.ts +26 -0
- package/dist/gates/language-adapters/registry.js +65 -0
- package/dist/gates/language-adapters/ruby-adapter.d.ts +25 -0
- package/dist/gates/language-adapters/ruby-adapter.js +217 -0
- package/dist/gates/language-adapters/rust-adapter.d.ts +27 -0
- package/dist/gates/language-adapters/rust-adapter.js +235 -0
- package/dist/gates/language-adapters/types.d.ts +60 -0
- package/dist/gates/language-adapters/types.js +22 -0
- package/dist/gates/logic-drift-extractors.d.ts +15 -0
- package/dist/gates/logic-drift-extractors.js +34 -0
- package/dist/gates/logic-drift.d.ts +0 -30
- package/dist/gates/logic-drift.js +39 -129
- package/dist/gates/phantom-apis.d.ts +0 -2
- package/dist/gates/phantom-apis.js +49 -20
- package/dist/gates/promise-safety.d.ts +0 -1
- package/dist/gates/promise-safety.js +14 -2
- package/dist/gates/runner.js +52 -23
- package/dist/gates/runner.test.js +1 -1
- package/dist/gates/security-patterns-data.d.ts +14 -0
- package/dist/gates/security-patterns-data.js +235 -0
- package/dist/gates/security-patterns.d.ts +17 -3
- package/dist/gates/security-patterns.js +80 -211
- package/dist/gates/side-effect-analysis/categorizer.d.ts +32 -0
- package/dist/gates/side-effect-analysis/categorizer.js +83 -0
- package/dist/gates/{side-effect-analysis.d.ts → side-effect-analysis/index.d.ts} +3 -5
- package/dist/gates/{side-effect-analysis.js → side-effect-analysis/index.js} +33 -45
- package/dist/gates/side-effect-analysis/scope-tracker.d.ts +37 -0
- package/dist/gates/side-effect-analysis/scope-tracker.js +40 -0
- package/dist/gates/side-effect-helpers/index.d.ts +4 -0
- package/dist/gates/side-effect-helpers/index.js +4 -0
- package/dist/gates/side-effect-helpers/pattern-detection.d.ts +123 -0
- package/dist/gates/{side-effect-helpers.js → side-effect-helpers/pattern-detection.js} +22 -468
- package/dist/gates/side-effect-helpers/resource-tracking.d.ts +80 -0
- package/dist/gates/side-effect-helpers/resource-tracking.js +281 -0
- package/dist/gates/side-effect-helpers/scope-analysis.d.ts +21 -0
- package/dist/gates/side-effect-helpers/scope-analysis.js +146 -0
- package/dist/gates/side-effect-helpers/types.d.ts +38 -0
- package/dist/gates/side-effect-helpers/types.js +41 -0
- package/dist/gates/side-effect-rules.d.ts +0 -1
- package/dist/gates/side-effect-rules.js +0 -1
- package/dist/gates/style-drift-rules.d.ts +86 -0
- package/dist/gates/style-drift-rules.js +103 -0
- package/dist/gates/style-drift.d.ts +7 -16
- package/dist/gates/style-drift.js +101 -119
- package/dist/gates/test-quality-matchers.d.ts +53 -0
- package/dist/gates/test-quality-matchers.js +86 -0
- package/dist/gates/test-quality.d.ts +0 -3
- package/dist/gates/test-quality.js +47 -44
- package/dist/hooks/checker.d.ts +0 -1
- package/dist/hooks/checker.js +0 -2
- package/dist/hooks/dlp-templates.d.ts +0 -1
- package/dist/hooks/dlp-templates.js +0 -4
- package/dist/hooks/index.d.ts +0 -2
- package/dist/hooks/index.js +0 -2
- package/dist/hooks/input-validator.d.ts +0 -1
- package/dist/hooks/input-validator.js +0 -1
- package/dist/hooks/input-validator.test.js +0 -1
- package/dist/hooks/standalone-checker.d.ts +0 -1
- package/dist/hooks/standalone-checker.js +0 -1
- package/dist/hooks/standalone-dlp-checker.d.ts +0 -1
- package/dist/hooks/standalone-dlp-checker.js +0 -1
- package/dist/hooks/templates.d.ts +0 -1
- package/dist/hooks/templates.js +0 -1
- package/dist/hooks/types.d.ts +0 -1
- package/dist/hooks/types.js +0 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/inference/index.js +1 -1
- package/dist/services/adaptive-thresholds.d.ts +0 -2
- package/dist/services/adaptive-thresholds.js +0 -2
- package/dist/services/filesystem-cache.d.ts +0 -1
- package/dist/services/filesystem-cache.js +0 -1
- package/dist/services/score-history.d.ts +0 -1
- package/dist/services/score-history.js +0 -1
- package/dist/services/temporal-drift.d.ts +1 -2
- package/dist/services/temporal-drift.js +7 -8
- package/dist/storage/db.d.ts +23 -7
- package/dist/storage/db.js +116 -55
- package/dist/storage/findings.d.ts +4 -3
- package/dist/storage/findings.js +13 -20
- package/dist/storage/local-memory.d.ts +4 -4
- package/dist/storage/local-memory.js +20 -22
- package/dist/storage/patterns.d.ts +5 -5
- package/dist/storage/patterns.js +20 -26
- package/dist/storage/scans.d.ts +6 -6
- package/dist/storage/scans.js +12 -21
- package/dist/types/index.d.ts +1 -0
- package/dist/utils/scanner.js +1 -1
- package/package.json +7 -8
- package/dist/gates/duplication-drift.d.ts +0 -128
- package/dist/gates/duplication-drift.js +0 -585
- package/dist/gates/hallucinated-imports.js +0 -641
- package/dist/gates/side-effect-helpers.d.ts +0 -260
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
import { classifyCasing } from './types.js';
|
|
2
|
+
class CSharpAdapter {
|
|
3
|
+
id = 'csharp';
|
|
4
|
+
name = 'C#';
|
|
5
|
+
extensions = ['.cs'];
|
|
6
|
+
extractFunctions(source) {
|
|
7
|
+
const lines = source.split('\n');
|
|
8
|
+
const functions = [];
|
|
9
|
+
// Match: public/private/protected/internal static? async? ReturnType MethodName(
|
|
10
|
+
const methodRegex = /^\s*(public|private|protected|internal)?\s*(static)?\s*(async)?\s*(\w+)\s+(\w+)\s*\(/;
|
|
11
|
+
let i = 0;
|
|
12
|
+
while (i < lines.length) {
|
|
13
|
+
const match = lines[i].match(methodRegex);
|
|
14
|
+
if (match) {
|
|
15
|
+
const isAsync = !!match[3];
|
|
16
|
+
const returnType = match[4];
|
|
17
|
+
const methodName = match[5];
|
|
18
|
+
const startLine = i + 1;
|
|
19
|
+
// Find closing brace
|
|
20
|
+
let braceCount = 0;
|
|
21
|
+
let foundOpening = false;
|
|
22
|
+
let j = i;
|
|
23
|
+
let body = '';
|
|
24
|
+
while (j < lines.length) {
|
|
25
|
+
const line = lines[j];
|
|
26
|
+
for (let k = 0; k < line.length; k++) {
|
|
27
|
+
if (line[k] === '{') {
|
|
28
|
+
braceCount++;
|
|
29
|
+
foundOpening = true;
|
|
30
|
+
}
|
|
31
|
+
else if (line[k] === '}') {
|
|
32
|
+
braceCount--;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
body += line + '\n';
|
|
36
|
+
if (foundOpening && braceCount === 0)
|
|
37
|
+
break;
|
|
38
|
+
j++;
|
|
39
|
+
}
|
|
40
|
+
functions.push({
|
|
41
|
+
name: methodName,
|
|
42
|
+
startLine,
|
|
43
|
+
endLine: j + 1,
|
|
44
|
+
body: body.trim(),
|
|
45
|
+
isAsync,
|
|
46
|
+
isExported: lines[i].includes('public'),
|
|
47
|
+
});
|
|
48
|
+
i = j + 1;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
i++;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return functions;
|
|
55
|
+
}
|
|
56
|
+
extractImports(source) {
|
|
57
|
+
const imports = [];
|
|
58
|
+
const lines = source.split('\n');
|
|
59
|
+
// Match: using Namespace; or using static Namespace;
|
|
60
|
+
const usingRegex = /^\s*using\s+(static\s+)?([^;]+);/;
|
|
61
|
+
lines.forEach((line, idx) => {
|
|
62
|
+
const match = line.match(usingRegex);
|
|
63
|
+
if (match) {
|
|
64
|
+
const module = match[2].trim();
|
|
65
|
+
imports.push({
|
|
66
|
+
module,
|
|
67
|
+
names: [],
|
|
68
|
+
line: idx + 1,
|
|
69
|
+
isDynamic: false,
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return imports;
|
|
74
|
+
}
|
|
75
|
+
extractErrorHandlers(source) {
|
|
76
|
+
const handlers = [];
|
|
77
|
+
const lines = source.split('\n');
|
|
78
|
+
// Match: catch (ExceptionType e) {
|
|
79
|
+
const catchRegex = /catch\s*\(\s*(\w+)\s+\w+\s*\)\s*{/;
|
|
80
|
+
let i = 0;
|
|
81
|
+
while (i < lines.length) {
|
|
82
|
+
const match = lines[i].match(catchRegex);
|
|
83
|
+
if (match) {
|
|
84
|
+
const exceptionType = match[1];
|
|
85
|
+
const startLine = i + 1;
|
|
86
|
+
// Extract catch block
|
|
87
|
+
let braceCount = 0;
|
|
88
|
+
let foundOpening = false;
|
|
89
|
+
let j = i;
|
|
90
|
+
let body = '';
|
|
91
|
+
while (j < lines.length) {
|
|
92
|
+
const line = lines[j];
|
|
93
|
+
for (let k = 0; k < line.length; k++) {
|
|
94
|
+
if (line[k] === '{') {
|
|
95
|
+
braceCount++;
|
|
96
|
+
foundOpening = true;
|
|
97
|
+
}
|
|
98
|
+
else if (line[k] === '}') {
|
|
99
|
+
braceCount--;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
body += line + '\n';
|
|
103
|
+
if (foundOpening && braceCount === 0)
|
|
104
|
+
break;
|
|
105
|
+
j++;
|
|
106
|
+
}
|
|
107
|
+
// Classify strategy
|
|
108
|
+
let strategy = 'swallow';
|
|
109
|
+
if (/\bthrow\s*;/.test(body)) {
|
|
110
|
+
strategy = 'rethrow';
|
|
111
|
+
}
|
|
112
|
+
else if (/\bthrow\s+new\s+/.test(body)) {
|
|
113
|
+
strategy = 'wrap';
|
|
114
|
+
}
|
|
115
|
+
else if (/Console\.(Write|WriteLine)/.test(body)) {
|
|
116
|
+
strategy = 'log';
|
|
117
|
+
}
|
|
118
|
+
handlers.push({
|
|
119
|
+
type: 'try-catch',
|
|
120
|
+
strategy,
|
|
121
|
+
startLine,
|
|
122
|
+
body: body.trim(),
|
|
123
|
+
});
|
|
124
|
+
i = j + 1;
|
|
125
|
+
}
|
|
126
|
+
else {
|
|
127
|
+
i++;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return handlers;
|
|
131
|
+
}
|
|
132
|
+
extractNamingPatterns(source) {
|
|
133
|
+
const patterns = [];
|
|
134
|
+
// Extract PascalCase methods
|
|
135
|
+
const methodRegex = /\b(public|private|protected|internal)?\s*(static)?\s*\w+\s+([A-Z]\w+)\s*\(/g;
|
|
136
|
+
let match;
|
|
137
|
+
while ((match = methodRegex.exec(source)) !== null) {
|
|
138
|
+
patterns.push({
|
|
139
|
+
name: match[3],
|
|
140
|
+
kind: 'method',
|
|
141
|
+
convention: classifyCasing(match[3]),
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
// Extract PascalCase class declarations
|
|
145
|
+
const classRegex = /\bclass\s+([A-Z]\w+)/g;
|
|
146
|
+
while ((match = classRegex.exec(source)) !== null) {
|
|
147
|
+
patterns.push({
|
|
148
|
+
name: match[1],
|
|
149
|
+
kind: 'class',
|
|
150
|
+
convention: classifyCasing(match[1]),
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
// Extract _camelCase private fields
|
|
154
|
+
const fieldRegex = /\b(_[a-z]\w+)\s*[=;]/g;
|
|
155
|
+
while ((match = fieldRegex.exec(source)) !== null) {
|
|
156
|
+
patterns.push({
|
|
157
|
+
name: match[1],
|
|
158
|
+
kind: 'variable',
|
|
159
|
+
convention: classifyCasing(match[1]),
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
// Extract SCREAMING_SNAKE constants
|
|
163
|
+
const constRegex = /\b(const\s+)?([A-Z][A-Z0-9_]*)\s*=/g;
|
|
164
|
+
while ((match = constRegex.exec(source)) !== null) {
|
|
165
|
+
const name = match[2];
|
|
166
|
+
if (/^[A-Z][A-Z0-9_]+$/.test(name)) {
|
|
167
|
+
patterns.push({
|
|
168
|
+
name,
|
|
169
|
+
kind: 'constant',
|
|
170
|
+
convention: classifyCasing(name),
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return patterns;
|
|
175
|
+
}
|
|
176
|
+
stripComments(source) {
|
|
177
|
+
// Remove // comments
|
|
178
|
+
let result = source.replace(/\/\/.*$/gm, '');
|
|
179
|
+
// Remove /* */ comments (handles multiline)
|
|
180
|
+
result = result.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
extractComparisonOps(source) {
|
|
184
|
+
const ops = new Set();
|
|
185
|
+
const opsRegex = /(>=|<=|==|!=|>|<)/g;
|
|
186
|
+
let match;
|
|
187
|
+
while ((match = opsRegex.exec(source)) !== null) {
|
|
188
|
+
ops.add(match[1]);
|
|
189
|
+
}
|
|
190
|
+
return Array.from(ops);
|
|
191
|
+
}
|
|
192
|
+
countBranches(source) {
|
|
193
|
+
const stripped = this.stripComments(source);
|
|
194
|
+
const ifMatches = stripped.match(/\bif\s*\(/g) || [];
|
|
195
|
+
const elseIfMatches = stripped.match(/\belse\s+if\s*\(/g) || [];
|
|
196
|
+
const elseMatches = stripped.match(/\belse\s*{/g) || [];
|
|
197
|
+
const switchMatches = stripped.match(/\bswitch\s*\(/g) || [];
|
|
198
|
+
const caseMatches = stripped.match(/\bcase\s+/g) || [];
|
|
199
|
+
return (ifMatches.length +
|
|
200
|
+
elseIfMatches.length +
|
|
201
|
+
elseMatches.length +
|
|
202
|
+
switchMatches.length +
|
|
203
|
+
caseMatches.length);
|
|
204
|
+
}
|
|
205
|
+
countReturns(source) {
|
|
206
|
+
const stripped = this.stripComments(source);
|
|
207
|
+
const returnMatches = stripped.match(/\breturn\b/g) || [];
|
|
208
|
+
return returnMatches.length;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
export const csharpAdapter = new CSharpAdapter();
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go Language Adapter
|
|
3
|
+
*
|
|
4
|
+
* Handles Go-specific code analysis:
|
|
5
|
+
* - Function extraction (func Name, func (r *Receiver) Name)
|
|
6
|
+
* - Import parsing (single and multiline blocks)
|
|
7
|
+
* - Error handling (if err != nil patterns)
|
|
8
|
+
* - Naming conventions (PascalCase exports, camelCase unexported)
|
|
9
|
+
*/
|
|
10
|
+
import { LanguageAdapter, FunctionFact, ImportFact, ErrorHandlerFact, NamingPattern } from './types.js';
|
|
11
|
+
export declare class GoAdapter implements LanguageAdapter {
|
|
12
|
+
readonly id = "go";
|
|
13
|
+
readonly name = "Go";
|
|
14
|
+
readonly extensions: string[];
|
|
15
|
+
extractFunctions(source: string, filePath?: string): FunctionFact[];
|
|
16
|
+
extractImports(source: string): ImportFact[];
|
|
17
|
+
extractErrorHandlers(source: string): ErrorHandlerFact[];
|
|
18
|
+
extractNamingPatterns(source: string): NamingPattern[];
|
|
19
|
+
stripComments(source: string): string;
|
|
20
|
+
extractComparisonOps(source: string): string[];
|
|
21
|
+
countBranches(source: string): number;
|
|
22
|
+
countReturns(source: string): number;
|
|
23
|
+
private extractBraceBody;
|
|
24
|
+
private classifyGoErrorStrategy;
|
|
25
|
+
}
|
|
26
|
+
export declare const goAdapter: GoAdapter;
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Go Language Adapter
|
|
3
|
+
*
|
|
4
|
+
* Handles Go-specific code analysis:
|
|
5
|
+
* - Function extraction (func Name, func (r *Receiver) Name)
|
|
6
|
+
* - Import parsing (single and multiline blocks)
|
|
7
|
+
* - Error handling (if err != nil patterns)
|
|
8
|
+
* - Naming conventions (PascalCase exports, camelCase unexported)
|
|
9
|
+
*/
|
|
10
|
+
import { classifyCasing } from './types.js';
|
|
11
|
+
export class GoAdapter {
|
|
12
|
+
id = 'go';
|
|
13
|
+
name = 'Go';
|
|
14
|
+
extensions = ['.go'];
|
|
15
|
+
extractFunctions(source, filePath) {
|
|
16
|
+
const functions = [];
|
|
17
|
+
const lines = source.split('\n');
|
|
18
|
+
// Match: func Name(...) or func (r *Receiver) Name(...)
|
|
19
|
+
const funcRegex = /^\s*func\s+(?:\([^)]+\)\s+)?(\w+)\s*\(/;
|
|
20
|
+
for (let i = 0; i < lines.length; i++) {
|
|
21
|
+
const match = lines[i].match(funcRegex);
|
|
22
|
+
if (!match)
|
|
23
|
+
continue;
|
|
24
|
+
const name = match[1];
|
|
25
|
+
const startLine = i + 1;
|
|
26
|
+
const body = this.extractBraceBody(lines, i);
|
|
27
|
+
const bodyStr = body.join('\n');
|
|
28
|
+
functions.push({
|
|
29
|
+
name,
|
|
30
|
+
startLine,
|
|
31
|
+
endLine: startLine + body.length,
|
|
32
|
+
body: bodyStr,
|
|
33
|
+
isAsync: false,
|
|
34
|
+
isExported: /^[A-Z]/.test(name),
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
return functions;
|
|
38
|
+
}
|
|
39
|
+
extractImports(source) {
|
|
40
|
+
const imports = [];
|
|
41
|
+
const lines = source.split('\n');
|
|
42
|
+
for (let i = 0; i < lines.length; i++) {
|
|
43
|
+
const line = lines[i].trim();
|
|
44
|
+
// Single import: import "pkg"
|
|
45
|
+
const singleMatch = line.match(/^\s*import\s+"([^"]+)"/);
|
|
46
|
+
if (singleMatch) {
|
|
47
|
+
imports.push({
|
|
48
|
+
module: singleMatch[1],
|
|
49
|
+
names: [],
|
|
50
|
+
line: i + 1,
|
|
51
|
+
isDynamic: false,
|
|
52
|
+
});
|
|
53
|
+
continue;
|
|
54
|
+
}
|
|
55
|
+
// Multiline import block: import ( "pkg1" "pkg2" )
|
|
56
|
+
if (line.startsWith('import') && line.includes('(')) {
|
|
57
|
+
let j = i;
|
|
58
|
+
while (j < lines.length && !lines[j].includes(')')) {
|
|
59
|
+
j++;
|
|
60
|
+
}
|
|
61
|
+
for (let k = i + 1; k < j; k++) {
|
|
62
|
+
const importLine = lines[k].trim();
|
|
63
|
+
if (importLine.startsWith('//'))
|
|
64
|
+
continue;
|
|
65
|
+
const pkgMatch = importLine.match(/"([^"]+)"/);
|
|
66
|
+
if (pkgMatch) {
|
|
67
|
+
imports.push({
|
|
68
|
+
module: pkgMatch[1],
|
|
69
|
+
names: [],
|
|
70
|
+
line: k + 1,
|
|
71
|
+
isDynamic: false,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
i = j;
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return imports;
|
|
79
|
+
}
|
|
80
|
+
extractErrorHandlers(source) {
|
|
81
|
+
const handlers = [];
|
|
82
|
+
const lines = source.split('\n');
|
|
83
|
+
for (let i = 0; i < lines.length; i++) {
|
|
84
|
+
const line = lines[i];
|
|
85
|
+
// Match: if err != nil {
|
|
86
|
+
if (/if\s+err\s*!=\s*nil\s*\{/.test(line)) {
|
|
87
|
+
const body = this.extractBraceBody(lines, i).join('\n');
|
|
88
|
+
const strategy = this.classifyGoErrorStrategy(body);
|
|
89
|
+
handlers.push({
|
|
90
|
+
type: 'if-err',
|
|
91
|
+
strategy,
|
|
92
|
+
startLine: i + 1,
|
|
93
|
+
body,
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return handlers;
|
|
98
|
+
}
|
|
99
|
+
extractNamingPatterns(source) {
|
|
100
|
+
const patterns = [];
|
|
101
|
+
const lines = source.split('\n');
|
|
102
|
+
for (let i = 0; i < lines.length; i++) {
|
|
103
|
+
const line = lines[i];
|
|
104
|
+
// Function definitions
|
|
105
|
+
const funcMatch = line.match(/^\s*func\s+(?:\([^)]+\)\s+)?(\w+)\s*\(/);
|
|
106
|
+
if (funcMatch) {
|
|
107
|
+
const name = funcMatch[1];
|
|
108
|
+
patterns.push({
|
|
109
|
+
name,
|
|
110
|
+
kind: 'function',
|
|
111
|
+
convention: classifyCasing(name),
|
|
112
|
+
});
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
// Const/var declarations
|
|
116
|
+
const varMatch = line.match(/^\s*(?:const|var)\s+(\w+)\s*=/);
|
|
117
|
+
if (varMatch) {
|
|
118
|
+
const name = varMatch[1];
|
|
119
|
+
const kind = line.includes('const') ? 'constant' : 'variable';
|
|
120
|
+
patterns.push({
|
|
121
|
+
name,
|
|
122
|
+
kind,
|
|
123
|
+
convention: classifyCasing(name),
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return patterns;
|
|
128
|
+
}
|
|
129
|
+
stripComments(source) {
|
|
130
|
+
// Remove line comments: //
|
|
131
|
+
let result = source.replace(/\/\/.*/g, '');
|
|
132
|
+
// Remove block comments: /* */
|
|
133
|
+
result = result.replace(/\/\*[\s\S]*?\*\//g, '');
|
|
134
|
+
return result;
|
|
135
|
+
}
|
|
136
|
+
extractComparisonOps(source) {
|
|
137
|
+
const ops = [];
|
|
138
|
+
const cleaned = this.stripComments(source);
|
|
139
|
+
const matches = cleaned.matchAll(/(===|!==|==|!=|>=|<=|>(?!=)|<(?!=))/g);
|
|
140
|
+
for (const m of matches) {
|
|
141
|
+
ops.push(m[1]);
|
|
142
|
+
}
|
|
143
|
+
return ops;
|
|
144
|
+
}
|
|
145
|
+
countBranches(source) {
|
|
146
|
+
let count = 0;
|
|
147
|
+
const cleaned = this.stripComments(source);
|
|
148
|
+
count += (cleaned.match(/\bif\s+/g) || []).length;
|
|
149
|
+
count += (cleaned.match(/\belse\s+if\s+/g) || []).length;
|
|
150
|
+
count += (cleaned.match(/\belse\s*\{/g) || []).length;
|
|
151
|
+
count += (cleaned.match(/\bswitch\s/g) || []).length;
|
|
152
|
+
count += (cleaned.match(/\bcase\s+/g) || []).length;
|
|
153
|
+
count += (cleaned.match(/\bselect\s*\{/g) || []).length;
|
|
154
|
+
return count;
|
|
155
|
+
}
|
|
156
|
+
countReturns(source) {
|
|
157
|
+
return (source.match(/\breturn\b/g) || []).length;
|
|
158
|
+
}
|
|
159
|
+
extractBraceBody(lines, startIndex) {
|
|
160
|
+
let braceDepth = 0;
|
|
161
|
+
let started = false;
|
|
162
|
+
const body = [];
|
|
163
|
+
for (let i = startIndex; i < lines.length; i++) {
|
|
164
|
+
const line = lines[i];
|
|
165
|
+
for (const ch of line) {
|
|
166
|
+
if (ch === '{') {
|
|
167
|
+
braceDepth++;
|
|
168
|
+
started = true;
|
|
169
|
+
}
|
|
170
|
+
if (ch === '}')
|
|
171
|
+
braceDepth--;
|
|
172
|
+
}
|
|
173
|
+
if (started)
|
|
174
|
+
body.push(line);
|
|
175
|
+
if (started && braceDepth === 0)
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
return body;
|
|
179
|
+
}
|
|
180
|
+
classifyGoErrorStrategy(body) {
|
|
181
|
+
const trimmed = body.trim();
|
|
182
|
+
if (!trimmed)
|
|
183
|
+
return 'swallow';
|
|
184
|
+
if (/\breturn\b.*\berr\b/.test(trimmed))
|
|
185
|
+
return 'return-error';
|
|
186
|
+
if (/\breturn\b.*fmt\.Errorf|errors\.Wrap/.test(trimmed))
|
|
187
|
+
return 'wrap';
|
|
188
|
+
if (/\bpanic\b/.test(trimmed))
|
|
189
|
+
return 'panic';
|
|
190
|
+
if (/\blog\b/.test(trimmed))
|
|
191
|
+
return 'log';
|
|
192
|
+
return 'other';
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
export const goAdapter = new GoAdapter();
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language Adapters — Barrel Export
|
|
3
|
+
*
|
|
4
|
+
* Single entry point for the language adapter layer.
|
|
5
|
+
* Gates import from here: `import { languageAdapters } from './language-adapters/index.js'`
|
|
6
|
+
*/
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
export * from './registry.js';
|
|
9
|
+
export { jsAdapter } from './js-adapter.js';
|
|
10
|
+
export { pythonAdapter } from './python-adapter.js';
|
|
11
|
+
export { goAdapter } from './go-adapter.js';
|
|
12
|
+
export { rubyAdapter } from './ruby-adapter.js';
|
|
13
|
+
export { rustAdapter } from './rust-adapter.js';
|
|
14
|
+
export { csharpAdapter } from './csharp-adapter.js';
|
|
15
|
+
export { javaAdapter } from './java-adapter.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language Adapters — Barrel Export
|
|
3
|
+
*
|
|
4
|
+
* Single entry point for the language adapter layer.
|
|
5
|
+
* Gates import from here: `import { languageAdapters } from './language-adapters/index.js'`
|
|
6
|
+
*/
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
export * from './registry.js';
|
|
9
|
+
// Individual adapters (for direct use if needed)
|
|
10
|
+
export { jsAdapter } from './js-adapter.js';
|
|
11
|
+
export { pythonAdapter } from './python-adapter.js';
|
|
12
|
+
export { goAdapter } from './go-adapter.js';
|
|
13
|
+
export { rubyAdapter } from './ruby-adapter.js';
|
|
14
|
+
export { rustAdapter } from './rust-adapter.js';
|
|
15
|
+
export { csharpAdapter } from './csharp-adapter.js';
|
|
16
|
+
export { javaAdapter } from './java-adapter.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { LanguageAdapter, FunctionFact, ImportFact, ErrorHandlerFact, NamingPattern } from './types.js';
|
|
2
|
+
declare class JavaAdapter implements LanguageAdapter {
|
|
3
|
+
readonly id = "java";
|
|
4
|
+
readonly name = "Java/Kotlin";
|
|
5
|
+
readonly extensions: string[];
|
|
6
|
+
extractFunctions(source: string): FunctionFact[];
|
|
7
|
+
extractImports(source: string): ImportFact[];
|
|
8
|
+
extractErrorHandlers(source: string): ErrorHandlerFact[];
|
|
9
|
+
extractNamingPatterns(source: string): NamingPattern[];
|
|
10
|
+
stripComments(source: string): string;
|
|
11
|
+
extractComparisonOps(source: string): string[];
|
|
12
|
+
countBranches(source: string): number;
|
|
13
|
+
countReturns(source: string): number;
|
|
14
|
+
}
|
|
15
|
+
export declare const javaAdapter: JavaAdapter;
|
|
16
|
+
export {};
|