trellis 2.0.13 → 2.1.2
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/cli/index.js +1 -1
- package/dist/embeddings/index.js +1 -1
- package/dist/{index-7gvjxt27.js → index-2917tjd8.js} +1 -1
- package/package.json +2 -10
- package/dist/transformers.node-bx3q9d7k.js +0 -33130
- package/src/cli/index.ts +0 -3356
- package/src/core/agents/harness.ts +0 -380
- package/src/core/agents/index.ts +0 -18
- package/src/core/agents/types.ts +0 -90
- package/src/core/index.ts +0 -118
- package/src/core/kernel/middleware.ts +0 -44
- package/src/core/kernel/trellis-kernel.ts +0 -593
- package/src/core/ontology/builtins.ts +0 -248
- package/src/core/ontology/index.ts +0 -34
- package/src/core/ontology/registry.ts +0 -209
- package/src/core/ontology/types.ts +0 -124
- package/src/core/ontology/validator.ts +0 -382
- package/src/core/persist/backend.ts +0 -74
- package/src/core/persist/sqlite-backend.ts +0 -298
- package/src/core/plugins/index.ts +0 -17
- package/src/core/plugins/registry.ts +0 -322
- package/src/core/plugins/types.ts +0 -126
- package/src/core/query/datalog.ts +0 -188
- package/src/core/query/engine.ts +0 -370
- package/src/core/query/index.ts +0 -34
- package/src/core/query/parser.ts +0 -481
- package/src/core/query/types.ts +0 -200
- package/src/core/store/eav-store.ts +0 -467
- package/src/decisions/auto-capture.ts +0 -136
- package/src/decisions/hooks.ts +0 -163
- package/src/decisions/index.ts +0 -261
- package/src/decisions/types.ts +0 -103
- package/src/embeddings/auto-embed.ts +0 -248
- package/src/embeddings/chunker.ts +0 -327
- package/src/embeddings/index.ts +0 -48
- package/src/embeddings/model.ts +0 -112
- package/src/embeddings/search.ts +0 -305
- package/src/embeddings/store.ts +0 -313
- package/src/embeddings/types.ts +0 -92
- package/src/engine.ts +0 -1125
- package/src/garden/cluster.ts +0 -330
- package/src/garden/garden.ts +0 -306
- package/src/garden/index.ts +0 -29
- package/src/git/git-exporter.ts +0 -286
- package/src/git/git-importer.ts +0 -329
- package/src/git/git-reader.ts +0 -189
- package/src/git/index.ts +0 -22
- package/src/identity/governance.ts +0 -211
- package/src/identity/identity.ts +0 -224
- package/src/identity/index.ts +0 -30
- package/src/identity/signing-middleware.ts +0 -97
- package/src/index.ts +0 -29
- package/src/links/index.ts +0 -49
- package/src/links/lifecycle.ts +0 -400
- package/src/links/parser.ts +0 -484
- package/src/links/ref-index.ts +0 -186
- package/src/links/resolver.ts +0 -314
- package/src/links/types.ts +0 -108
- package/src/mcp/index.ts +0 -22
- package/src/mcp/server.ts +0 -1278
- package/src/semantic/csharp-parser.ts +0 -493
- package/src/semantic/go-parser.ts +0 -585
- package/src/semantic/index.ts +0 -34
- package/src/semantic/java-parser.ts +0 -456
- package/src/semantic/python-parser.ts +0 -659
- package/src/semantic/ruby-parser.ts +0 -446
- package/src/semantic/rust-parser.ts +0 -784
- package/src/semantic/semantic-merge.ts +0 -210
- package/src/semantic/ts-parser.ts +0 -681
- package/src/semantic/types.ts +0 -175
- package/src/sync/http-transport.ts +0 -144
- package/src/sync/index.ts +0 -43
- package/src/sync/memory-transport.ts +0 -66
- package/src/sync/multi-repo.ts +0 -200
- package/src/sync/reconciler.ts +0 -237
- package/src/sync/sync-engine.ts +0 -258
- package/src/sync/types.ts +0 -104
- package/src/sync/ws-transport.ts +0 -145
- package/src/ui/client.html +0 -695
- package/src/ui/server.ts +0 -419
- package/src/vcs/blob-store.ts +0 -124
- package/src/vcs/branch.ts +0 -150
- package/src/vcs/checkpoint.ts +0 -64
- package/src/vcs/decompose.ts +0 -469
- package/src/vcs/diff.ts +0 -409
- package/src/vcs/engine-context.ts +0 -26
- package/src/vcs/index.ts +0 -23
- package/src/vcs/issue.ts +0 -800
- package/src/vcs/merge.ts +0 -425
- package/src/vcs/milestone.ts +0 -124
- package/src/vcs/ops.ts +0 -59
- package/src/vcs/types.ts +0 -213
- package/src/vcs/vcs-middleware.ts +0 -81
- package/src/watcher/fs-watcher.ts +0 -255
- package/src/watcher/index.ts +0 -9
- package/src/watcher/ingestion.ts +0 -116
|
@@ -1,585 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Go Parser Adapter
|
|
3
|
-
*
|
|
4
|
-
* Tier 1 regex-based parser for Go source files.
|
|
5
|
-
* Extracts structs, interfaces, functions, methods, type aliases,
|
|
6
|
-
* constants, variables, and imports.
|
|
7
|
-
*
|
|
8
|
-
* @see TRL-6
|
|
9
|
-
*/
|
|
10
|
-
|
|
11
|
-
import type {
|
|
12
|
-
ParserAdapter,
|
|
13
|
-
ParseResult,
|
|
14
|
-
ASTEntity,
|
|
15
|
-
ASTEntityKind,
|
|
16
|
-
ImportRelation,
|
|
17
|
-
ExportRelation,
|
|
18
|
-
SemanticPatch,
|
|
19
|
-
} from './types.js';
|
|
20
|
-
|
|
21
|
-
// ---------------------------------------------------------------------------
|
|
22
|
-
// Parser Adapter
|
|
23
|
-
// ---------------------------------------------------------------------------
|
|
24
|
-
|
|
25
|
-
export const goParser: ParserAdapter = {
|
|
26
|
-
languages: ['go'],
|
|
27
|
-
|
|
28
|
-
parse(content: string, filePath: string): ParseResult {
|
|
29
|
-
const fileEntityId = `file:${filePath}`;
|
|
30
|
-
|
|
31
|
-
return {
|
|
32
|
-
fileEntityId,
|
|
33
|
-
filePath,
|
|
34
|
-
language: 'go',
|
|
35
|
-
declarations: extractDeclarations(content, filePath),
|
|
36
|
-
imports: extractImports(content),
|
|
37
|
-
exports: extractExports(content, filePath),
|
|
38
|
-
};
|
|
39
|
-
},
|
|
40
|
-
|
|
41
|
-
diff(oldResult: ParseResult, newResult: ParseResult): SemanticPatch[] {
|
|
42
|
-
return computeSemanticDiff(oldResult, newResult);
|
|
43
|
-
},
|
|
44
|
-
};
|
|
45
|
-
|
|
46
|
-
// ---------------------------------------------------------------------------
|
|
47
|
-
// Declaration extraction
|
|
48
|
-
// ---------------------------------------------------------------------------
|
|
49
|
-
|
|
50
|
-
function extractDeclarations(content: string, filePath: string): ASTEntity[] {
|
|
51
|
-
const declarations: ASTEntity[] = [];
|
|
52
|
-
const lines = content.split('\n');
|
|
53
|
-
|
|
54
|
-
let i = 0;
|
|
55
|
-
while (i < lines.length) {
|
|
56
|
-
const line = lines[i];
|
|
57
|
-
const trimmed = line.trim();
|
|
58
|
-
|
|
59
|
-
// Skip empty lines, comments, package declaration
|
|
60
|
-
if (
|
|
61
|
-
!trimmed ||
|
|
62
|
-
trimmed.startsWith('//') ||
|
|
63
|
-
trimmed.startsWith('/*') ||
|
|
64
|
-
trimmed.startsWith('*') ||
|
|
65
|
-
trimmed.startsWith('package ') ||
|
|
66
|
-
trimmed.startsWith('import ')
|
|
67
|
-
) {
|
|
68
|
-
i++;
|
|
69
|
-
continue;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Skip import blocks
|
|
73
|
-
if (trimmed === 'import (') {
|
|
74
|
-
while (i < lines.length && !lines[i].trim().startsWith(')')) { i++; }
|
|
75
|
-
i++;
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Function declaration: func Name(...)
|
|
80
|
-
let match = trimmed.match(/^func\s+(\w+)\s*\(/);
|
|
81
|
-
if (match) {
|
|
82
|
-
const result = extractBraceBlock(match[1], 'FunctionDef', lines, i, filePath);
|
|
83
|
-
declarations.push(result.entity);
|
|
84
|
-
i = result.endLine + 1;
|
|
85
|
-
continue;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
// Method declaration: func (receiver) Name(...)
|
|
89
|
-
match = trimmed.match(/^func\s+\([^)]+\)\s+(\w+)\s*\(/);
|
|
90
|
-
if (match) {
|
|
91
|
-
const result = extractBraceBlock(match[1], 'MethodDef', lines, i, filePath);
|
|
92
|
-
declarations.push(result.entity);
|
|
93
|
-
i = result.endLine + 1;
|
|
94
|
-
continue;
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
// Type struct: type Name struct {
|
|
98
|
-
match = trimmed.match(/^type\s+(\w+)\s+struct\b/);
|
|
99
|
-
if (match) {
|
|
100
|
-
const result = extractBraceBlock(match[1], 'ClassDef', lines, i, filePath);
|
|
101
|
-
result.entity.children = extractStructFields(lines, i, result.endLine, match[1], filePath);
|
|
102
|
-
declarations.push(result.entity);
|
|
103
|
-
i = result.endLine + 1;
|
|
104
|
-
continue;
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Type interface: type Name interface {
|
|
108
|
-
match = trimmed.match(/^type\s+(\w+)\s+interface\b/);
|
|
109
|
-
if (match) {
|
|
110
|
-
const result = extractBraceBlock(match[1], 'InterfaceDef', lines, i, filePath);
|
|
111
|
-
result.entity.children = extractInterfaceMethods(lines, i, result.endLine, match[1], filePath);
|
|
112
|
-
declarations.push(result.entity);
|
|
113
|
-
i = result.endLine + 1;
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// Type alias: type Name = ... or type Name OtherType
|
|
118
|
-
match = trimmed.match(/^type\s+(\w+)\s+/);
|
|
119
|
-
if (match) {
|
|
120
|
-
const result = extractSingleOrBlock(match[1], 'TypeAlias', lines, i, filePath);
|
|
121
|
-
declarations.push(result.entity);
|
|
122
|
-
i = result.endLine + 1;
|
|
123
|
-
continue;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Const block or single: const ( ... ) or const Name = ...
|
|
127
|
-
if (trimmed.startsWith('const ') || trimmed === 'const (') {
|
|
128
|
-
if (trimmed === 'const (') {
|
|
129
|
-
// Block const
|
|
130
|
-
const endLine = findClosingParen(lines, i);
|
|
131
|
-
const rawText = lines.slice(i, endLine + 1).join('\n');
|
|
132
|
-
const consts = extractConstBlock(lines, i, endLine, filePath);
|
|
133
|
-
declarations.push(...consts);
|
|
134
|
-
i = endLine + 1;
|
|
135
|
-
} else {
|
|
136
|
-
match = trimmed.match(/^const\s+(\w+)/);
|
|
137
|
-
if (match) {
|
|
138
|
-
const result = extractSingleLine(match[1], 'VariableDecl', lines, i, filePath);
|
|
139
|
-
declarations.push(result.entity);
|
|
140
|
-
i = result.endLine + 1;
|
|
141
|
-
} else {
|
|
142
|
-
i++;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
continue;
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// Var block or single
|
|
149
|
-
if (trimmed.startsWith('var ') || trimmed === 'var (') {
|
|
150
|
-
if (trimmed === 'var (') {
|
|
151
|
-
const endLine = findClosingParen(lines, i);
|
|
152
|
-
const vars = extractVarBlock(lines, i, endLine, filePath);
|
|
153
|
-
declarations.push(...vars);
|
|
154
|
-
i = endLine + 1;
|
|
155
|
-
} else {
|
|
156
|
-
match = trimmed.match(/^var\s+(\w+)/);
|
|
157
|
-
if (match) {
|
|
158
|
-
const result = extractSingleLine(match[1], 'VariableDecl', lines, i, filePath);
|
|
159
|
-
declarations.push(result.entity);
|
|
160
|
-
i = result.endLine + 1;
|
|
161
|
-
} else {
|
|
162
|
-
i++;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
i++;
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
return declarations;
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// ---------------------------------------------------------------------------
|
|
175
|
-
// Block extraction helpers
|
|
176
|
-
// ---------------------------------------------------------------------------
|
|
177
|
-
|
|
178
|
-
interface ExtractionResult {
|
|
179
|
-
entity: ASTEntity;
|
|
180
|
-
endLine: number;
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
function extractBraceBlock(
|
|
184
|
-
name: string,
|
|
185
|
-
kind: ASTEntityKind,
|
|
186
|
-
lines: string[],
|
|
187
|
-
startLine: number,
|
|
188
|
-
filePath: string,
|
|
189
|
-
): ExtractionResult {
|
|
190
|
-
let depth = 0;
|
|
191
|
-
let foundOpen = false;
|
|
192
|
-
let endLine = startLine;
|
|
193
|
-
|
|
194
|
-
for (let i = startLine; i < lines.length; i++) {
|
|
195
|
-
for (const ch of lines[i]) {
|
|
196
|
-
if (ch === '{') { depth++; foundOpen = true; }
|
|
197
|
-
else if (ch === '}') { depth--; }
|
|
198
|
-
}
|
|
199
|
-
if (foundOpen && depth <= 0) { endLine = i; break; }
|
|
200
|
-
if (i > startLine + 200) { endLine = i; break; }
|
|
201
|
-
endLine = i;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const rawText = lines.slice(startLine, endLine + 1).join('\n');
|
|
205
|
-
const startOffset = lines.slice(0, startLine).join('\n').length + (startLine > 0 ? 1 : 0);
|
|
206
|
-
|
|
207
|
-
return {
|
|
208
|
-
entity: {
|
|
209
|
-
id: makeEntityId(filePath, kind, name),
|
|
210
|
-
kind,
|
|
211
|
-
name,
|
|
212
|
-
scopePath: name,
|
|
213
|
-
span: [startOffset, startOffset + rawText.length],
|
|
214
|
-
rawText,
|
|
215
|
-
signature: normalizeSignature(rawText),
|
|
216
|
-
children: [],
|
|
217
|
-
},
|
|
218
|
-
endLine,
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
function extractSingleOrBlock(
|
|
223
|
-
name: string,
|
|
224
|
-
kind: ASTEntityKind,
|
|
225
|
-
lines: string[],
|
|
226
|
-
startLine: number,
|
|
227
|
-
filePath: string,
|
|
228
|
-
): ExtractionResult {
|
|
229
|
-
const trimmed = lines[startLine].trim();
|
|
230
|
-
if (trimmed.includes('{')) {
|
|
231
|
-
return extractBraceBlock(name, kind, lines, startLine, filePath);
|
|
232
|
-
}
|
|
233
|
-
return extractSingleLine(name, kind, lines, startLine, filePath);
|
|
234
|
-
}
|
|
235
|
-
|
|
236
|
-
function extractSingleLine(
|
|
237
|
-
name: string,
|
|
238
|
-
kind: ASTEntityKind,
|
|
239
|
-
lines: string[],
|
|
240
|
-
startLine: number,
|
|
241
|
-
filePath: string,
|
|
242
|
-
): ExtractionResult {
|
|
243
|
-
const rawText = lines[startLine];
|
|
244
|
-
const startOffset = lines.slice(0, startLine).join('\n').length + (startLine > 0 ? 1 : 0);
|
|
245
|
-
|
|
246
|
-
return {
|
|
247
|
-
entity: {
|
|
248
|
-
id: makeEntityId(filePath, kind, name),
|
|
249
|
-
kind,
|
|
250
|
-
name,
|
|
251
|
-
scopePath: name,
|
|
252
|
-
span: [startOffset, startOffset + rawText.length],
|
|
253
|
-
rawText,
|
|
254
|
-
signature: normalizeSignature(rawText),
|
|
255
|
-
children: [],
|
|
256
|
-
},
|
|
257
|
-
endLine: startLine,
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
function findClosingParen(lines: string[], startLine: number): number {
|
|
262
|
-
for (let i = startLine + 1; i < lines.length; i++) {
|
|
263
|
-
if (lines[i].trim() === ')') return i;
|
|
264
|
-
}
|
|
265
|
-
return lines.length - 1;
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// ---------------------------------------------------------------------------
|
|
269
|
-
// Struct field + interface method extraction
|
|
270
|
-
// ---------------------------------------------------------------------------
|
|
271
|
-
|
|
272
|
-
function extractStructFields(
|
|
273
|
-
lines: string[],
|
|
274
|
-
startLine: number,
|
|
275
|
-
endLine: number,
|
|
276
|
-
structName: string,
|
|
277
|
-
filePath: string,
|
|
278
|
-
): ASTEntity[] {
|
|
279
|
-
const children: ASTEntity[] = [];
|
|
280
|
-
for (let i = startLine + 1; i < endLine; i++) {
|
|
281
|
-
const trimmed = lines[i].trim();
|
|
282
|
-
if (!trimmed || trimmed.startsWith('//') || trimmed === '{' || trimmed === '}') continue;
|
|
283
|
-
|
|
284
|
-
const match = trimmed.match(/^(\w+)\s+/);
|
|
285
|
-
if (match) {
|
|
286
|
-
children.push({
|
|
287
|
-
id: makeEntityId(filePath, 'PropertyDef', `${structName}.${match[1]}`),
|
|
288
|
-
kind: 'PropertyDef',
|
|
289
|
-
name: match[1],
|
|
290
|
-
scopePath: `${structName}.${match[1]}`,
|
|
291
|
-
span: [0, 0],
|
|
292
|
-
rawText: trimmed,
|
|
293
|
-
signature: normalizeSignature(trimmed),
|
|
294
|
-
children: [],
|
|
295
|
-
});
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
return children;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
function extractInterfaceMethods(
|
|
302
|
-
lines: string[],
|
|
303
|
-
startLine: number,
|
|
304
|
-
endLine: number,
|
|
305
|
-
ifaceName: string,
|
|
306
|
-
filePath: string,
|
|
307
|
-
): ASTEntity[] {
|
|
308
|
-
const children: ASTEntity[] = [];
|
|
309
|
-
for (let i = startLine + 1; i < endLine; i++) {
|
|
310
|
-
const trimmed = lines[i].trim();
|
|
311
|
-
if (!trimmed || trimmed.startsWith('//') || trimmed === '{' || trimmed === '}') continue;
|
|
312
|
-
|
|
313
|
-
const match = trimmed.match(/^(\w+)\s*\(/);
|
|
314
|
-
if (match) {
|
|
315
|
-
children.push({
|
|
316
|
-
id: makeEntityId(filePath, 'MethodDef', `${ifaceName}.${match[1]}`),
|
|
317
|
-
kind: 'MethodDef',
|
|
318
|
-
name: match[1],
|
|
319
|
-
scopePath: `${ifaceName}.${match[1]}`,
|
|
320
|
-
span: [0, 0],
|
|
321
|
-
rawText: trimmed,
|
|
322
|
-
signature: normalizeSignature(trimmed),
|
|
323
|
-
children: [],
|
|
324
|
-
});
|
|
325
|
-
}
|
|
326
|
-
}
|
|
327
|
-
return children;
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
// ---------------------------------------------------------------------------
|
|
331
|
-
// Const/var block extraction
|
|
332
|
-
// ---------------------------------------------------------------------------
|
|
333
|
-
|
|
334
|
-
function extractConstBlock(
|
|
335
|
-
lines: string[],
|
|
336
|
-
startLine: number,
|
|
337
|
-
endLine: number,
|
|
338
|
-
filePath: string,
|
|
339
|
-
): ASTEntity[] {
|
|
340
|
-
const entities: ASTEntity[] = [];
|
|
341
|
-
for (let i = startLine + 1; i < endLine; i++) {
|
|
342
|
-
const trimmed = lines[i].trim();
|
|
343
|
-
if (!trimmed || trimmed.startsWith('//')) continue;
|
|
344
|
-
const match = trimmed.match(/^(\w+)/);
|
|
345
|
-
if (match) {
|
|
346
|
-
entities.push({
|
|
347
|
-
id: makeEntityId(filePath, 'VariableDecl', match[1]),
|
|
348
|
-
kind: 'VariableDecl',
|
|
349
|
-
name: match[1],
|
|
350
|
-
scopePath: match[1],
|
|
351
|
-
span: [0, 0],
|
|
352
|
-
rawText: trimmed,
|
|
353
|
-
signature: normalizeSignature(trimmed),
|
|
354
|
-
children: [],
|
|
355
|
-
});
|
|
356
|
-
}
|
|
357
|
-
}
|
|
358
|
-
return entities;
|
|
359
|
-
}
|
|
360
|
-
|
|
361
|
-
function extractVarBlock(
|
|
362
|
-
lines: string[],
|
|
363
|
-
startLine: number,
|
|
364
|
-
endLine: number,
|
|
365
|
-
filePath: string,
|
|
366
|
-
): ASTEntity[] {
|
|
367
|
-
return extractConstBlock(lines, startLine, endLine, filePath);
|
|
368
|
-
}
|
|
369
|
-
|
|
370
|
-
// ---------------------------------------------------------------------------
|
|
371
|
-
// Import extraction
|
|
372
|
-
// ---------------------------------------------------------------------------
|
|
373
|
-
|
|
374
|
-
function extractImports(content: string): ImportRelation[] {
|
|
375
|
-
const imports: ImportRelation[] = [];
|
|
376
|
-
const lines = content.split('\n');
|
|
377
|
-
|
|
378
|
-
for (let i = 0; i < lines.length; i++) {
|
|
379
|
-
const trimmed = lines[i].trim();
|
|
380
|
-
|
|
381
|
-
// Single import: import "fmt"
|
|
382
|
-
let match = trimmed.match(/^import\s+"([^"]+)"/);
|
|
383
|
-
if (match) {
|
|
384
|
-
imports.push({
|
|
385
|
-
source: match[1],
|
|
386
|
-
specifiers: [match[1].split('/').pop()!],
|
|
387
|
-
isDefault: true,
|
|
388
|
-
isNamespace: false,
|
|
389
|
-
rawText: trimmed,
|
|
390
|
-
span: [0, trimmed.length],
|
|
391
|
-
});
|
|
392
|
-
continue;
|
|
393
|
-
}
|
|
394
|
-
|
|
395
|
-
// Import block: import ( ... )
|
|
396
|
-
if (trimmed === 'import (') {
|
|
397
|
-
for (let j = i + 1; j < lines.length; j++) {
|
|
398
|
-
const impLine = lines[j].trim();
|
|
399
|
-
if (impLine === ')') { i = j; break; }
|
|
400
|
-
if (!impLine || impLine.startsWith('//')) continue;
|
|
401
|
-
|
|
402
|
-
// Aliased: alias "path"
|
|
403
|
-
const aliasMatch = impLine.match(/^(\w+)\s+"([^"]+)"/);
|
|
404
|
-
if (aliasMatch) {
|
|
405
|
-
imports.push({
|
|
406
|
-
source: aliasMatch[2],
|
|
407
|
-
specifiers: [aliasMatch[1]],
|
|
408
|
-
isDefault: true,
|
|
409
|
-
isNamespace: false,
|
|
410
|
-
rawText: impLine,
|
|
411
|
-
span: [0, impLine.length],
|
|
412
|
-
});
|
|
413
|
-
continue;
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
// Dot import: . "path"
|
|
417
|
-
const dotMatch = impLine.match(/^\.\s+"([^"]+)"/);
|
|
418
|
-
if (dotMatch) {
|
|
419
|
-
imports.push({
|
|
420
|
-
source: dotMatch[1],
|
|
421
|
-
specifiers: ['*'],
|
|
422
|
-
isDefault: false,
|
|
423
|
-
isNamespace: true,
|
|
424
|
-
rawText: impLine,
|
|
425
|
-
span: [0, impLine.length],
|
|
426
|
-
});
|
|
427
|
-
continue;
|
|
428
|
-
}
|
|
429
|
-
|
|
430
|
-
// Standard: "path"
|
|
431
|
-
const stdMatch = impLine.match(/^"([^"]+)"/);
|
|
432
|
-
if (stdMatch) {
|
|
433
|
-
imports.push({
|
|
434
|
-
source: stdMatch[1],
|
|
435
|
-
specifiers: [stdMatch[1].split('/').pop()!],
|
|
436
|
-
isDefault: true,
|
|
437
|
-
isNamespace: false,
|
|
438
|
-
rawText: impLine,
|
|
439
|
-
span: [0, impLine.length],
|
|
440
|
-
});
|
|
441
|
-
}
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
return imports;
|
|
447
|
-
}
|
|
448
|
-
|
|
449
|
-
// ---------------------------------------------------------------------------
|
|
450
|
-
// Export extraction
|
|
451
|
-
// ---------------------------------------------------------------------------
|
|
452
|
-
|
|
453
|
-
/**
|
|
454
|
-
* In Go, exported names start with an uppercase letter.
|
|
455
|
-
* We derive exports from declarations.
|
|
456
|
-
*/
|
|
457
|
-
function extractExports(content: string, filePath: string): ExportRelation[] {
|
|
458
|
-
const exports: ExportRelation[] = [];
|
|
459
|
-
const decls = extractDeclarations(content, filePath);
|
|
460
|
-
|
|
461
|
-
for (const d of decls) {
|
|
462
|
-
if (d.name[0] >= 'A' && d.name[0] <= 'Z') {
|
|
463
|
-
exports.push({
|
|
464
|
-
name: d.name,
|
|
465
|
-
isDefault: false,
|
|
466
|
-
rawText: d.rawText.split('\n')[0],
|
|
467
|
-
span: d.span,
|
|
468
|
-
});
|
|
469
|
-
}
|
|
470
|
-
}
|
|
471
|
-
|
|
472
|
-
return exports;
|
|
473
|
-
}
|
|
474
|
-
|
|
475
|
-
// ---------------------------------------------------------------------------
|
|
476
|
-
// Semantic diff (same generic algorithm)
|
|
477
|
-
// ---------------------------------------------------------------------------
|
|
478
|
-
|
|
479
|
-
function computeSemanticDiff(
|
|
480
|
-
oldResult: ParseResult,
|
|
481
|
-
newResult: ParseResult,
|
|
482
|
-
): SemanticPatch[] {
|
|
483
|
-
const patches: SemanticPatch[] = [];
|
|
484
|
-
const fileId = newResult.fileEntityId;
|
|
485
|
-
|
|
486
|
-
const oldDecls = new Map(oldResult.declarations.map(d => [d.id, d]));
|
|
487
|
-
const newDecls = new Map(newResult.declarations.map(d => [d.id, d]));
|
|
488
|
-
|
|
489
|
-
for (const [id, entity] of newDecls) {
|
|
490
|
-
if (!oldDecls.has(id)) {
|
|
491
|
-
const oldEntity = findRenamedEntity(entity, oldResult.declarations, newDecls);
|
|
492
|
-
if (oldEntity) {
|
|
493
|
-
patches.push({ kind: 'symbolRename', entityId: oldEntity.id, oldName: oldEntity.name, newName: entity.name });
|
|
494
|
-
} else {
|
|
495
|
-
patches.push({ kind: 'symbolAdd', entity });
|
|
496
|
-
}
|
|
497
|
-
}
|
|
498
|
-
}
|
|
499
|
-
|
|
500
|
-
for (const [id, entity] of oldDecls) {
|
|
501
|
-
if (!newDecls.has(id)) {
|
|
502
|
-
const wasRenamed = findRenamedEntity(entity, newResult.declarations, oldDecls);
|
|
503
|
-
if (!wasRenamed) {
|
|
504
|
-
patches.push({ kind: 'symbolRemove', entityId: id, entityName: entity.name });
|
|
505
|
-
}
|
|
506
|
-
}
|
|
507
|
-
}
|
|
508
|
-
|
|
509
|
-
for (const [id, newEntity] of newDecls) {
|
|
510
|
-
const oldEntity = oldDecls.get(id);
|
|
511
|
-
if (oldEntity && oldEntity.signature !== newEntity.signature) {
|
|
512
|
-
patches.push({
|
|
513
|
-
kind: 'symbolModify', entityId: id, entityName: newEntity.name,
|
|
514
|
-
oldSignature: oldEntity.signature, newSignature: newEntity.signature,
|
|
515
|
-
oldRawText: oldEntity.rawText, newRawText: newEntity.rawText,
|
|
516
|
-
});
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
|
|
520
|
-
const oldImports = new Map(oldResult.imports.map(imp => [imp.source, imp]));
|
|
521
|
-
const newImports = new Map(newResult.imports.map(imp => [imp.source, imp]));
|
|
522
|
-
|
|
523
|
-
for (const [source, imp] of newImports) {
|
|
524
|
-
const oldImp = oldImports.get(source);
|
|
525
|
-
if (!oldImp) {
|
|
526
|
-
patches.push({ kind: 'importAdd', fileId, source, specifiers: imp.specifiers, rawText: imp.rawText });
|
|
527
|
-
} else if (JSON.stringify(oldImp.specifiers.sort()) !== JSON.stringify(imp.specifiers.sort())) {
|
|
528
|
-
patches.push({ kind: 'importModify', fileId, source, oldSpecifiers: oldImp.specifiers, newSpecifiers: imp.specifiers });
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
for (const [source] of oldImports) {
|
|
533
|
-
if (!newImports.has(source)) {
|
|
534
|
-
patches.push({ kind: 'importRemove', fileId, source });
|
|
535
|
-
}
|
|
536
|
-
}
|
|
537
|
-
|
|
538
|
-
const oldExports = new Map(oldResult.exports.map(exp => [exp.name, exp]));
|
|
539
|
-
const newExports = new Map(newResult.exports.map(exp => [exp.name, exp]));
|
|
540
|
-
|
|
541
|
-
for (const [name, exp] of newExports) {
|
|
542
|
-
if (!oldExports.has(name)) {
|
|
543
|
-
patches.push({ kind: 'exportAdd', fileId, name, rawText: exp.rawText });
|
|
544
|
-
}
|
|
545
|
-
}
|
|
546
|
-
for (const [name] of oldExports) {
|
|
547
|
-
if (!newExports.has(name)) {
|
|
548
|
-
patches.push({ kind: 'exportRemove', fileId, name });
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
|
|
552
|
-
return patches;
|
|
553
|
-
}
|
|
554
|
-
|
|
555
|
-
// ---------------------------------------------------------------------------
|
|
556
|
-
// Helpers
|
|
557
|
-
// ---------------------------------------------------------------------------
|
|
558
|
-
|
|
559
|
-
function findRenamedEntity(
|
|
560
|
-
entity: ASTEntity,
|
|
561
|
-
candidates: ASTEntity[],
|
|
562
|
-
existingIds: Map<string, ASTEntity>,
|
|
563
|
-
): ASTEntity | null {
|
|
564
|
-
for (const candidate of candidates) {
|
|
565
|
-
if (candidate.kind !== entity.kind) continue;
|
|
566
|
-
if (candidate.name === entity.name) continue;
|
|
567
|
-
if (existingIds.has(candidate.id)) continue;
|
|
568
|
-
const normalizedOld = candidate.signature.replace(new RegExp(candidate.name, 'g'), '___');
|
|
569
|
-
const normalizedNew = entity.signature.replace(new RegExp(entity.name, 'g'), '___');
|
|
570
|
-
if (normalizedOld === normalizedNew) return candidate;
|
|
571
|
-
}
|
|
572
|
-
return null;
|
|
573
|
-
}
|
|
574
|
-
|
|
575
|
-
function makeEntityId(filePath: string, kind: string, name: string): string {
|
|
576
|
-
return `${kind}:${filePath}:${name}`;
|
|
577
|
-
}
|
|
578
|
-
|
|
579
|
-
function normalizeSignature(text: string): string {
|
|
580
|
-
return text
|
|
581
|
-
.replace(/\/\/[^\n]*/g, '')
|
|
582
|
-
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
583
|
-
.replace(/\s+/g, ' ')
|
|
584
|
-
.trim();
|
|
585
|
-
}
|
package/src/semantic/index.ts
DELETED
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Semantic Patching — Public Surface
|
|
3
|
-
*
|
|
4
|
-
* @module semantic
|
|
5
|
-
*
|
|
6
|
-
* Re-exports the {@link ParserAdapter} interface, the built-in
|
|
7
|
-
* {@link typescriptParser} (Tier 1 regex-based TS/JS parser), and the
|
|
8
|
-
* {@link semanticMerge} engine that merges patch sets with commutativity
|
|
9
|
-
* analysis.
|
|
10
|
-
*
|
|
11
|
-
* @see DESIGN.md §4 for the full semantic patching specification.
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
export type {
|
|
15
|
-
ASTEntity,
|
|
16
|
-
ASTEntityKind,
|
|
17
|
-
ImportRelation,
|
|
18
|
-
ExportRelation,
|
|
19
|
-
ParseResult,
|
|
20
|
-
ParserAdapter,
|
|
21
|
-
SemanticPatch,
|
|
22
|
-
SemanticMergeConflict,
|
|
23
|
-
SemanticMergeResult,
|
|
24
|
-
} from './types.js';
|
|
25
|
-
|
|
26
|
-
export { typescriptParser } from './ts-parser.js';
|
|
27
|
-
export { pythonParser } from './python-parser.js';
|
|
28
|
-
export { goParser } from './go-parser.js';
|
|
29
|
-
export { rustParser } from './rust-parser.js';
|
|
30
|
-
export { rubyParser } from './ruby-parser.js';
|
|
31
|
-
export { javaParser } from './java-parser.js';
|
|
32
|
-
export { csharpParser } from './csharp-parser.js';
|
|
33
|
-
|
|
34
|
-
export { patchesCommute, semanticMerge } from './semantic-merge.js';
|