mcp-code-context 2.5.1 → 3.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +92 -236
- package/README.md +304 -298
- package/dist/src/core/engine.d.ts +21 -0
- package/dist/src/core/engine.js +68 -0
- package/dist/src/core/engine.js.map +1 -0
- package/dist/src/core/validator.d.ts +15 -0
- package/dist/src/core/validator.js +44 -0
- package/dist/src/core/validator.js.map +1 -0
- package/dist/src/index.d.ts +7 -11
- package/dist/src/index.js +182 -397
- package/dist/src/index.js.map +1 -1
- package/dist/src/operations/write.d.ts +51 -0
- package/dist/src/operations/write.js +169 -0
- package/dist/src/operations/write.js.map +1 -0
- package/dist/src/parsers/base.d.ts +28 -0
- package/dist/src/parsers/base.js +27 -0
- package/dist/src/parsers/base.js.map +1 -0
- package/dist/src/parsers/dartTreeSitter.d.ts +13 -0
- package/dist/src/parsers/dartTreeSitter.js +91 -0
- package/dist/src/parsers/dartTreeSitter.js.map +1 -0
- package/dist/src/parsers/php.d.ts +12 -0
- package/dist/src/parsers/php.js +86 -0
- package/dist/src/parsers/php.js.map +1 -0
- package/dist/src/parsers/python.d.ts +12 -0
- package/dist/src/parsers/python.js +86 -0
- package/dist/src/parsers/python.js.map +1 -0
- package/dist/src/parsers/registry.d.ts +15 -0
- package/dist/src/parsers/registry.js +70 -0
- package/dist/src/parsers/registry.js.map +1 -0
- package/dist/src/parsers/typescript.d.ts +13 -0
- package/dist/src/parsers/typescript.js +98 -0
- package/dist/src/parsers/typescript.js.map +1 -0
- package/llms.txt +246 -234
- package/mcp-code-context-3.0.2.tgz +0 -0
- package/package.json +59 -57
- package/tsconfig.tests.json +27 -0
- package/.io/RULES.md +0 -12
- package/CONTRIBUTING.md +0 -243
- package/PLAN_v2.5.0.md +0 -407
- package/TROUBLESHOOTING.md +0 -38
- package/dist/src/ast/dartCompressor.d.ts +0 -27
- package/dist/src/ast/dartCompressor.js +0 -859
- package/dist/src/ast/dartCompressor.js.map +0 -1
- package/dist/src/ast/phpCompressor.d.ts +0 -24
- package/dist/src/ast/phpCompressor.js +0 -634
- package/dist/src/ast/phpCompressor.js.map +0 -1
- package/dist/src/ast/semanticCompressor.d.ts +0 -22
- package/dist/src/ast/semanticCompressor.js +0 -677
- package/dist/src/ast/semanticCompressor.js.map +0 -1
- package/dist/src/ast/writers/dartWriter.d.ts +0 -37
- package/dist/src/ast/writers/dartWriter.js +0 -544
- package/dist/src/ast/writers/dartWriter.js.map +0 -1
- package/dist/src/ast/writers/phpWriter.d.ts +0 -37
- package/dist/src/ast/writers/phpWriter.js +0 -411
- package/dist/src/ast/writers/phpWriter.js.map +0 -1
- package/dist/src/ast/writers/pyWriter.d.ts +0 -37
- package/dist/src/ast/writers/pyWriter.js +0 -355
- package/dist/src/ast/writers/pyWriter.js.map +0 -1
- package/dist/src/ast/writers/safeRename.d.ts +0 -14
- package/dist/src/ast/writers/safeRename.js +0 -258
- package/dist/src/ast/writers/safeRename.js.map +0 -1
- package/dist/src/ast/writers/symbolWriter.d.ts +0 -64
- package/dist/src/ast/writers/symbolWriter.js +0 -174
- package/dist/src/ast/writers/symbolWriter.js.map +0 -1
- package/dist/src/ast/writers/tsWriter.d.ts +0 -38
- package/dist/src/ast/writers/tsWriter.js +0 -344
- package/dist/src/ast/writers/tsWriter.js.map +0 -1
- package/dist/src/cache/astCache.d.ts +0 -39
- package/dist/src/cache/astCache.js +0 -169
- package/dist/src/cache/astCache.js.map +0 -1
- package/dist/src/handlers/readHandlers.d.ts +0 -70
- package/dist/src/handlers/readHandlers.js +0 -455
- package/dist/src/handlers/readHandlers.js.map +0 -1
- package/dist/src/handlers/utilHandlers.d.ts +0 -31
- package/dist/src/handlers/utilHandlers.js +0 -69
- package/dist/src/handlers/utilHandlers.js.map +0 -1
- package/dist/src/handlers/writeHandlers.d.ts +0 -57
- package/dist/src/handlers/writeHandlers.js +0 -499
- package/dist/src/handlers/writeHandlers.js.map +0 -1
- package/dist/src/tools/readFileLines.d.ts +0 -26
- package/dist/src/tools/readFileLines.js +0 -77
- package/dist/src/tools/readFileLines.js.map +0 -1
- package/dist/src/tools/searchCodePattern.d.ts +0 -37
- package/dist/src/tools/searchCodePattern.js +0 -144
- package/dist/src/tools/searchCodePattern.js.map +0 -1
- package/dist/src/utils/arrayUtils.d.ts +0 -12
- package/dist/src/utils/arrayUtils.js +0 -27
- package/dist/src/utils/arrayUtils.js.map +0 -1
- package/dist/src/utils/backupManager.d.ts +0 -31
- package/dist/src/utils/backupManager.js +0 -124
- package/dist/src/utils/backupManager.js.map +0 -1
- package/dist/src/utils/confirmationCache.d.ts +0 -16
- package/dist/src/utils/confirmationCache.js +0 -40
- package/dist/src/utils/confirmationCache.js.map +0 -1
- package/dist/src/utils/constants.d.ts +0 -46
- package/dist/src/utils/constants.js +0 -112
- package/dist/src/utils/constants.js.map +0 -1
- package/dist/src/utils/dependencyChecker.d.ts +0 -1
- package/dist/src/utils/dependencyChecker.js +0 -55
- package/dist/src/utils/dependencyChecker.js.map +0 -1
- package/dist/src/utils/diffEngine.d.ts +0 -21
- package/dist/src/utils/diffEngine.js +0 -163
- package/dist/src/utils/diffEngine.js.map +0 -1
- package/dist/src/utils/fuzzyMatch.d.ts +0 -8
- package/dist/src/utils/fuzzyMatch.js +0 -69
- package/dist/src/utils/fuzzyMatch.js.map +0 -1
- package/dist/src/utils/ignoreManager.d.ts +0 -30
- package/dist/src/utils/ignoreManager.js +0 -186
- package/dist/src/utils/ignoreManager.js.map +0 -1
- package/dist/src/utils/normalization.d.ts +0 -49
- package/dist/src/utils/normalization.js +0 -173
- package/dist/src/utils/normalization.js.map +0 -1
- package/dist/src/utils/projectRoot.d.ts +0 -17
- package/dist/src/utils/projectRoot.js +0 -42
- package/dist/src/utils/projectRoot.js.map +0 -1
- package/dist/src/utils/secureValidation.d.ts +0 -15
- package/dist/src/utils/secureValidation.js +0 -41
- package/dist/src/utils/secureValidation.js.map +0 -1
- package/dist/src/utils/syntaxValidator.d.ts +0 -15
- package/dist/src/utils/syntaxValidator.js +0 -218
- package/dist/src/utils/syntaxValidator.js.map +0 -1
- package/dist/src/utils/transactionManager.d.ts +0 -46
- package/dist/src/utils/transactionManager.js +0 -123
- package/dist/src/utils/transactionManager.js.map +0 -1
- package/dist/src/utils/validation.d.ts +0 -87
- package/dist/src/utils/validation.js +0 -231
- package/dist/src/utils/validation.js.map +0 -1
- package/docs/ARCHITECTURE.md +0 -300
- package/docs/architecture/ADR-001-modular-handlers.md +0 -119
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SemanticCompressor — The AST engine that extracts structural signatures
|
|
3
|
-
* from source files, stripping implementation bodies to save tokens.
|
|
4
|
-
*
|
|
5
|
-
* Supports:
|
|
6
|
-
* - TypeScript / JavaScript (via ts-morph AST)
|
|
7
|
-
* - PHP (via php-parser AST — Glayzzle)
|
|
8
|
-
* - Dart (via regex + brace-counting)
|
|
9
|
-
* - Python (via regex-based extraction)
|
|
10
|
-
* - Generic files (passthrough for small configs, summary for large files)
|
|
11
|
-
*/
|
|
12
|
-
/**
|
|
13
|
-
* Compress a source file into its semantic skeleton.
|
|
14
|
-
* Returns only structural signatures — no function bodies.
|
|
15
|
-
*/
|
|
16
|
-
export declare function compressFile(filePath: string, content: string): string;
|
|
17
|
-
/**
|
|
18
|
-
* Extract the full source code of a named symbol from a file.
|
|
19
|
-
* When className is provided, scopes method search to within that class only.
|
|
20
|
-
* Returns null if the symbol is not found.
|
|
21
|
-
*/
|
|
22
|
-
export declare function extractSymbol(content: string, symbolName: string, filePath: string, className?: string): string | null;
|
|
@@ -1,677 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SemanticCompressor — The AST engine that extracts structural signatures
|
|
3
|
-
* from source files, stripping implementation bodies to save tokens.
|
|
4
|
-
*
|
|
5
|
-
* Supports:
|
|
6
|
-
* - TypeScript / JavaScript (via ts-morph AST)
|
|
7
|
-
* - PHP (via php-parser AST — Glayzzle)
|
|
8
|
-
* - Dart (via regex + brace-counting)
|
|
9
|
-
* - Python (via regex-based extraction)
|
|
10
|
-
* - Generic files (passthrough for small configs, summary for large files)
|
|
11
|
-
*/
|
|
12
|
-
import { Project, SyntaxKind, ts, } from "ts-morph";
|
|
13
|
-
import * as path from "node:path";
|
|
14
|
-
import { compressPHP, extractPHPSymbol } from "./phpCompressor.js";
|
|
15
|
-
import { compressDart, extractDartSymbol } from "./dartCompressor.js";
|
|
16
|
-
// ─── Supported extensions ───────────────────────────────────────────
|
|
17
|
-
const TS_EXTENSIONS = new Set([
|
|
18
|
-
".ts", ".tsx", ".js", ".jsx", ".mts", ".mjs", ".cts", ".cjs",
|
|
19
|
-
]);
|
|
20
|
-
const PY_EXTENSIONS = new Set([".py", ".pyi"]);
|
|
21
|
-
const PHP_EXTENSIONS = new Set([".php", ".phtml"]);
|
|
22
|
-
const DART_EXTENSIONS = new Set([".dart"]);
|
|
23
|
-
const CONFIG_EXTENSIONS = new Set([
|
|
24
|
-
".json", ".yaml", ".yml", ".toml", ".ini", ".env",
|
|
25
|
-
".xml", ".html", ".css", ".scss", ".less",
|
|
26
|
-
".md", ".txt", ".svg",
|
|
27
|
-
]);
|
|
28
|
-
// ─── Singleton ts-morph Project (reusable, in-memory) ───────────────
|
|
29
|
-
let _project = null;
|
|
30
|
-
function getProject() {
|
|
31
|
-
if (!_project) {
|
|
32
|
-
_project = new Project({
|
|
33
|
-
useInMemoryFileSystem: true,
|
|
34
|
-
compilerOptions: {
|
|
35
|
-
target: ts.ScriptTarget.ESNext,
|
|
36
|
-
module: ts.ModuleKind.ESNext,
|
|
37
|
-
jsx: ts.JsxEmit.ReactJSX,
|
|
38
|
-
allowJs: true,
|
|
39
|
-
strict: false,
|
|
40
|
-
noEmit: true,
|
|
41
|
-
skipLibCheck: true,
|
|
42
|
-
},
|
|
43
|
-
});
|
|
44
|
-
}
|
|
45
|
-
return _project;
|
|
46
|
-
}
|
|
47
|
-
// ─── Public API ─────────────────────────────────────────────────────
|
|
48
|
-
/**
|
|
49
|
-
* Compress a source file into its semantic skeleton.
|
|
50
|
-
* Returns only structural signatures — no function bodies.
|
|
51
|
-
*/
|
|
52
|
-
export function compressFile(filePath, content) {
|
|
53
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
54
|
-
if (TS_EXTENSIONS.has(ext)) {
|
|
55
|
-
return compressTypeScript(content, filePath);
|
|
56
|
-
}
|
|
57
|
-
if (PHP_EXTENSIONS.has(ext)) {
|
|
58
|
-
return compressPHP(content);
|
|
59
|
-
}
|
|
60
|
-
if (DART_EXTENSIONS.has(ext)) {
|
|
61
|
-
return compressDart(content);
|
|
62
|
-
}
|
|
63
|
-
if (PY_EXTENSIONS.has(ext)) {
|
|
64
|
-
return compressPython(content);
|
|
65
|
-
}
|
|
66
|
-
return compressGeneric(content, filePath);
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Extract the full source code of a named symbol from a file.
|
|
70
|
-
* When className is provided, scopes method search to within that class only.
|
|
71
|
-
* Returns null if the symbol is not found.
|
|
72
|
-
*/
|
|
73
|
-
export function extractSymbol(content, symbolName, filePath, className) {
|
|
74
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
75
|
-
if (TS_EXTENSIONS.has(ext)) {
|
|
76
|
-
return extractTSSymbol(content, symbolName, filePath, className);
|
|
77
|
-
}
|
|
78
|
-
if (PHP_EXTENSIONS.has(ext)) {
|
|
79
|
-
return extractPHPSymbol(content, symbolName, className);
|
|
80
|
-
}
|
|
81
|
-
if (DART_EXTENSIONS.has(ext)) {
|
|
82
|
-
return extractDartSymbol(content, symbolName, className);
|
|
83
|
-
}
|
|
84
|
-
if (PY_EXTENSIONS.has(ext)) {
|
|
85
|
-
return extractPySymbol(content, symbolName, className);
|
|
86
|
-
}
|
|
87
|
-
return null;
|
|
88
|
-
}
|
|
89
|
-
// ─── TypeScript / JavaScript Compression ────────────────────────────
|
|
90
|
-
function compressTypeScript(content, filePath) {
|
|
91
|
-
const project = getProject();
|
|
92
|
-
const ext = path.extname(filePath);
|
|
93
|
-
const tempName = `temp_${Date.now()}${ext}`;
|
|
94
|
-
let sourceFile;
|
|
95
|
-
try {
|
|
96
|
-
sourceFile = project.createSourceFile(tempName, content, {
|
|
97
|
-
overwrite: true,
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
catch {
|
|
101
|
-
return compressGeneric(content, filePath);
|
|
102
|
-
}
|
|
103
|
-
try {
|
|
104
|
-
const chunks = [];
|
|
105
|
-
// 1) Imports — keep for dependency context
|
|
106
|
-
const imports = sourceFile.getImportDeclarations();
|
|
107
|
-
if (imports.length > 0) {
|
|
108
|
-
chunks.push("// ── Imports ──");
|
|
109
|
-
for (const imp of imports) {
|
|
110
|
-
chunks.push(imp.getText());
|
|
111
|
-
}
|
|
112
|
-
chunks.push("");
|
|
113
|
-
}
|
|
114
|
-
// 2) Type aliases
|
|
115
|
-
for (const ta of sourceFile.getTypeAliases()) {
|
|
116
|
-
chunks.push(ta.getText());
|
|
117
|
-
}
|
|
118
|
-
// 3) Interfaces (already just signatures)
|
|
119
|
-
for (const iface of sourceFile.getInterfaces()) {
|
|
120
|
-
chunks.push(iface.getText());
|
|
121
|
-
}
|
|
122
|
-
// 4) Enums
|
|
123
|
-
for (const enumDecl of sourceFile.getEnums()) {
|
|
124
|
-
chunks.push(enumDecl.getText());
|
|
125
|
-
}
|
|
126
|
-
// 5) Function declarations (signature only, body stripped)
|
|
127
|
-
for (const func of sourceFile.getFunctions()) {
|
|
128
|
-
chunks.push(buildFunctionSignature(func));
|
|
129
|
-
}
|
|
130
|
-
// 6) Class declarations (signatures only)
|
|
131
|
-
for (const cls of sourceFile.getClasses()) {
|
|
132
|
-
chunks.push(buildClassSignature(cls));
|
|
133
|
-
}
|
|
134
|
-
// 7) Exported variable statements (arrow fns, consts, etc.)
|
|
135
|
-
for (const varStmt of sourceFile.getVariableStatements()) {
|
|
136
|
-
if (!varStmt.isExported())
|
|
137
|
-
continue;
|
|
138
|
-
for (const decl of varStmt.getDeclarations()) {
|
|
139
|
-
const init = decl.getInitializer();
|
|
140
|
-
if (!init)
|
|
141
|
-
continue;
|
|
142
|
-
const kind = init.getKind();
|
|
143
|
-
if (kind === SyntaxKind.ArrowFunction ||
|
|
144
|
-
kind === SyntaxKind.FunctionExpression) {
|
|
145
|
-
const fn = init;
|
|
146
|
-
const params = fn
|
|
147
|
-
.getParameters()
|
|
148
|
-
.map((p) => p.getText())
|
|
149
|
-
.join(", ");
|
|
150
|
-
const retNode = fn.getReturnTypeNode();
|
|
151
|
-
const retType = retNode ? `: ${retNode.getText()}` : "";
|
|
152
|
-
const asyncMod = fn.isAsync() ? "async " : "";
|
|
153
|
-
const declKind = varStmt.getDeclarationKind();
|
|
154
|
-
chunks.push(`export ${declKind} ${asyncMod}${decl.getName()} = (${params})${retType} => { /* ... */ };`);
|
|
155
|
-
}
|
|
156
|
-
else {
|
|
157
|
-
const declKind = varStmt.getDeclarationKind();
|
|
158
|
-
const typeNode = decl.getTypeNode();
|
|
159
|
-
const typeStr = typeNode ? `: ${typeNode.getText()}` : "";
|
|
160
|
-
chunks.push(`export ${declKind} ${decl.getName()}${typeStr};`);
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
// 8) Re-export declarations
|
|
165
|
-
for (const exp of sourceFile.getExportDeclarations()) {
|
|
166
|
-
chunks.push(exp.getText());
|
|
167
|
-
}
|
|
168
|
-
// 9) Export assignments (export default ...)
|
|
169
|
-
const exportAssignment = sourceFile.getExportAssignment((ea) => !ea.isExportEquals());
|
|
170
|
-
if (exportAssignment) {
|
|
171
|
-
chunks.push(exportAssignment.getText());
|
|
172
|
-
}
|
|
173
|
-
return chunks.filter((c) => c.trim()).join("\n\n");
|
|
174
|
-
}
|
|
175
|
-
finally {
|
|
176
|
-
// Clean up the in-memory source file to avoid memory leaks
|
|
177
|
-
try {
|
|
178
|
-
project.removeSourceFile(sourceFile);
|
|
179
|
-
}
|
|
180
|
-
catch {
|
|
181
|
-
// Ignore cleanup errors
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
}
|
|
185
|
-
function buildFunctionSignature(func) {
|
|
186
|
-
const name = func.getName() || "anonymous";
|
|
187
|
-
const params = func
|
|
188
|
-
.getParameters()
|
|
189
|
-
.map((p) => p.getText())
|
|
190
|
-
.join(", ");
|
|
191
|
-
const retNode = func.getReturnTypeNode();
|
|
192
|
-
const retType = retNode ? `: ${retNode.getText()}` : "";
|
|
193
|
-
const exported = func.isExported() ? "export " : "";
|
|
194
|
-
const isDefault = func.isDefaultExport() ? "default " : "";
|
|
195
|
-
const asyncMod = func.isAsync() ? "async " : "";
|
|
196
|
-
const generics = func
|
|
197
|
-
.getTypeParameters()
|
|
198
|
-
.map((tp) => tp.getText())
|
|
199
|
-
.join(", ");
|
|
200
|
-
const genericStr = generics ? `<${generics}>` : "";
|
|
201
|
-
const overloads = func.getOverloads();
|
|
202
|
-
const parts = [];
|
|
203
|
-
for (const overload of overloads) {
|
|
204
|
-
parts.push(overload.getText());
|
|
205
|
-
}
|
|
206
|
-
parts.push(`${exported}${isDefault}${asyncMod}function ${name}${genericStr}(${params})${retType} { /* ... */ }`);
|
|
207
|
-
return parts.join("\n");
|
|
208
|
-
}
|
|
209
|
-
function buildClassSignature(cls) {
|
|
210
|
-
const lines = [];
|
|
211
|
-
const name = cls.getName() || "AnonymousClass";
|
|
212
|
-
const exported = cls.isExported() ? "export " : "";
|
|
213
|
-
const isDefault = cls.isDefaultExport() ? "default " : "";
|
|
214
|
-
const isAbstract = cls.isAbstract() ? "abstract " : "";
|
|
215
|
-
const extendsExpr = cls.getExtends();
|
|
216
|
-
const implementsClauses = cls.getImplements();
|
|
217
|
-
const generics = cls
|
|
218
|
-
.getTypeParameters()
|
|
219
|
-
.map((tp) => tp.getText())
|
|
220
|
-
.join(", ");
|
|
221
|
-
const genericStr = generics ? `<${generics}>` : "";
|
|
222
|
-
let header = `${exported}${isDefault}${isAbstract}class ${name}${genericStr}`;
|
|
223
|
-
if (extendsExpr)
|
|
224
|
-
header += ` extends ${extendsExpr.getText()}`;
|
|
225
|
-
if (implementsClauses.length > 0) {
|
|
226
|
-
header += ` implements ${implementsClauses.map((i) => i.getText()).join(", ")}`;
|
|
227
|
-
}
|
|
228
|
-
header += " {";
|
|
229
|
-
lines.push(header);
|
|
230
|
-
// Constructor
|
|
231
|
-
for (const ctor of cls.getConstructors()) {
|
|
232
|
-
const params = ctor
|
|
233
|
-
.getParameters()
|
|
234
|
-
.map((p) => p.getText())
|
|
235
|
-
.join(", ");
|
|
236
|
-
lines.push(` constructor(${params}) { /* ... */ }`);
|
|
237
|
-
}
|
|
238
|
-
// Properties
|
|
239
|
-
for (const prop of cls.getProperties()) {
|
|
240
|
-
const mods = prop
|
|
241
|
-
.getModifiers()
|
|
242
|
-
.map((m) => m.getText())
|
|
243
|
-
.join(" ");
|
|
244
|
-
const modStr = mods ? `${mods} ` : "";
|
|
245
|
-
const typeNode = prop.getTypeNode();
|
|
246
|
-
const typeStr = typeNode ? `: ${typeNode.getText()}` : "";
|
|
247
|
-
const optional = prop.hasQuestionToken() ? "?" : "";
|
|
248
|
-
const isReadonly = prop.isReadonly() ? "readonly " : "";
|
|
249
|
-
lines.push(` ${modStr}${isReadonly}${prop.getName()}${optional}${typeStr};`);
|
|
250
|
-
}
|
|
251
|
-
// Methods (signature only)
|
|
252
|
-
for (const method of cls.getMethods()) {
|
|
253
|
-
lines.push(` ${buildMethodSignature(method)}`);
|
|
254
|
-
}
|
|
255
|
-
// Getters
|
|
256
|
-
for (const getter of cls.getGetAccessors()) {
|
|
257
|
-
const retNode = getter.getReturnTypeNode();
|
|
258
|
-
const retType = retNode ? `: ${retNode.getText()}` : "";
|
|
259
|
-
lines.push(` get ${getter.getName()}()${retType} { /* ... */ }`);
|
|
260
|
-
}
|
|
261
|
-
// Setters
|
|
262
|
-
for (const setter of cls.getSetAccessors()) {
|
|
263
|
-
const params = setter
|
|
264
|
-
.getParameters()
|
|
265
|
-
.map((p) => p.getText())
|
|
266
|
-
.join(", ");
|
|
267
|
-
lines.push(` set ${setter.getName()}(${params}) { /* ... */ }`);
|
|
268
|
-
}
|
|
269
|
-
lines.push("}");
|
|
270
|
-
return lines.join("\n");
|
|
271
|
-
}
|
|
272
|
-
function buildMethodSignature(method) {
|
|
273
|
-
const mods = method
|
|
274
|
-
.getModifiers()
|
|
275
|
-
.map((m) => m.getText())
|
|
276
|
-
.join(" ");
|
|
277
|
-
const modStr = mods ? `${mods} ` : "";
|
|
278
|
-
const asyncMod = method.isAsync() ? "async " : "";
|
|
279
|
-
const name = method.getName();
|
|
280
|
-
const params = method
|
|
281
|
-
.getParameters()
|
|
282
|
-
.map((p) => p.getText())
|
|
283
|
-
.join(", ");
|
|
284
|
-
const retNode = method.getReturnTypeNode();
|
|
285
|
-
const retType = retNode ? `: ${retNode.getText()}` : "";
|
|
286
|
-
const generics = method
|
|
287
|
-
.getTypeParameters()
|
|
288
|
-
.map((tp) => tp.getText())
|
|
289
|
-
.join(", ");
|
|
290
|
-
const genericStr = generics ? `<${generics}>` : "";
|
|
291
|
-
return `${modStr}${asyncMod}${name}${genericStr}(${params})${retType} { /* ... */ }`;
|
|
292
|
-
}
|
|
293
|
-
// ─── Python Compression ─────────────────────────────────────────────
|
|
294
|
-
function compressPython(content) {
|
|
295
|
-
const lines = content.split("\n");
|
|
296
|
-
const result = [];
|
|
297
|
-
let i = 0;
|
|
298
|
-
// Phase 1: Collect imports at the top
|
|
299
|
-
const importBlock = [];
|
|
300
|
-
for (const line of lines) {
|
|
301
|
-
const t = line.trim();
|
|
302
|
-
if (t.startsWith("import ") || t.startsWith("from ")) {
|
|
303
|
-
importBlock.push(line);
|
|
304
|
-
}
|
|
305
|
-
}
|
|
306
|
-
if (importBlock.length > 0) {
|
|
307
|
-
result.push("# ── Imports ──");
|
|
308
|
-
result.push(...importBlock);
|
|
309
|
-
result.push("");
|
|
310
|
-
}
|
|
311
|
-
// Phase 2: Walk the file extracting signatures
|
|
312
|
-
while (i < lines.length) {
|
|
313
|
-
const line = lines[i];
|
|
314
|
-
const trimmed = line.trim();
|
|
315
|
-
const indent = measureIndent(line);
|
|
316
|
-
// Skip import lines (already captured)
|
|
317
|
-
if (trimmed.startsWith("import ") || trimmed.startsWith("from ")) {
|
|
318
|
-
i++;
|
|
319
|
-
continue;
|
|
320
|
-
}
|
|
321
|
-
// Decorators — pass through
|
|
322
|
-
if (trimmed.startsWith("@")) {
|
|
323
|
-
result.push(line);
|
|
324
|
-
i++;
|
|
325
|
-
continue;
|
|
326
|
-
}
|
|
327
|
-
// Class definition
|
|
328
|
-
if (/^class\s+\w+/.test(trimmed)) {
|
|
329
|
-
// Capture the full class signature (may span multiple lines)
|
|
330
|
-
let signature = line;
|
|
331
|
-
i++;
|
|
332
|
-
while (i < lines.length && !signature.trimEnd().endsWith(":")) {
|
|
333
|
-
signature += "\n" + lines[i];
|
|
334
|
-
i++;
|
|
335
|
-
}
|
|
336
|
-
result.push(signature);
|
|
337
|
-
// Capture docstring
|
|
338
|
-
i = captureDocstring(lines, i, result);
|
|
339
|
-
// Now extract methods within this class
|
|
340
|
-
while (i < lines.length) {
|
|
341
|
-
const innerLine = lines[i];
|
|
342
|
-
const innerTrimmed = innerLine.trim();
|
|
343
|
-
// Empty line within class is OK
|
|
344
|
-
if (innerTrimmed === "") {
|
|
345
|
-
i++;
|
|
346
|
-
continue;
|
|
347
|
-
}
|
|
348
|
-
// Exited the class (non-indented non-empty line)
|
|
349
|
-
if (measureIndent(innerLine) <= indent && innerTrimmed !== "") {
|
|
350
|
-
break;
|
|
351
|
-
}
|
|
352
|
-
// Decorator before method
|
|
353
|
-
if (innerTrimmed.startsWith("@")) {
|
|
354
|
-
result.push(innerLine);
|
|
355
|
-
i++;
|
|
356
|
-
continue;
|
|
357
|
-
}
|
|
358
|
-
// Method definition
|
|
359
|
-
if (/^\s*(async\s+)?def\s+\w+/.test(innerLine)) {
|
|
360
|
-
let methodSig = innerLine;
|
|
361
|
-
i++;
|
|
362
|
-
while (i < lines.length && !methodSig.trimEnd().endsWith(":")) {
|
|
363
|
-
methodSig += "\n" + lines[i];
|
|
364
|
-
i++;
|
|
365
|
-
}
|
|
366
|
-
result.push(methodSig);
|
|
367
|
-
// Capture method docstring
|
|
368
|
-
i = captureDocstring(lines, i, result);
|
|
369
|
-
// Placeholder for body
|
|
370
|
-
const methodIndent = measureIndent(innerLine);
|
|
371
|
-
result.push(" ".repeat(methodIndent + 4) + "...");
|
|
372
|
-
result.push("");
|
|
373
|
-
// Skip method body
|
|
374
|
-
while (i < lines.length) {
|
|
375
|
-
const bodyLine = lines[i];
|
|
376
|
-
if (bodyLine.trim() === "") {
|
|
377
|
-
i++;
|
|
378
|
-
continue;
|
|
379
|
-
}
|
|
380
|
-
if (measureIndent(bodyLine) > methodIndent) {
|
|
381
|
-
i++;
|
|
382
|
-
}
|
|
383
|
-
else {
|
|
384
|
-
break;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
continue;
|
|
388
|
-
}
|
|
389
|
-
// Class-level attribute with type hint
|
|
390
|
-
if (/^\s+\w+\s*:/.test(innerLine) && !innerTrimmed.startsWith("#")) {
|
|
391
|
-
result.push(innerLine);
|
|
392
|
-
}
|
|
393
|
-
i++;
|
|
394
|
-
}
|
|
395
|
-
result.push("");
|
|
396
|
-
continue;
|
|
397
|
-
}
|
|
398
|
-
// Top-level function definition
|
|
399
|
-
if (/^(async\s+)?def\s+\w+/.test(trimmed)) {
|
|
400
|
-
let signature = line;
|
|
401
|
-
i++;
|
|
402
|
-
while (i < lines.length && !signature.trimEnd().endsWith(":")) {
|
|
403
|
-
signature += "\n" + lines[i];
|
|
404
|
-
i++;
|
|
405
|
-
}
|
|
406
|
-
result.push(signature);
|
|
407
|
-
// Capture docstring
|
|
408
|
-
i = captureDocstring(lines, i, result);
|
|
409
|
-
// Placeholder
|
|
410
|
-
result.push(" ...");
|
|
411
|
-
result.push("");
|
|
412
|
-
// Skip body
|
|
413
|
-
while (i < lines.length) {
|
|
414
|
-
const bodyLine = lines[i];
|
|
415
|
-
if (bodyLine.trim() === "") {
|
|
416
|
-
i++;
|
|
417
|
-
continue;
|
|
418
|
-
}
|
|
419
|
-
if (bodyLine.startsWith(" ") || bodyLine.startsWith("\t")) {
|
|
420
|
-
i++;
|
|
421
|
-
}
|
|
422
|
-
else {
|
|
423
|
-
break;
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
continue;
|
|
427
|
-
}
|
|
428
|
-
// Top-level typed variable
|
|
429
|
-
if (indent === 0 && /^\w+\s*:/.test(trimmed) && !trimmed.startsWith("#")) {
|
|
430
|
-
result.push(line);
|
|
431
|
-
i++;
|
|
432
|
-
continue;
|
|
433
|
-
}
|
|
434
|
-
// Top-level assignment of special objects
|
|
435
|
-
if (indent === 0 &&
|
|
436
|
-
/^\w+\s*=/.test(trimmed) &&
|
|
437
|
-
!trimmed.startsWith("#")) {
|
|
438
|
-
// Keep only single-line assignments to constants, named tuples, etc.
|
|
439
|
-
if (!trimmed.includes("(") || trimmed.endsWith(")")) {
|
|
440
|
-
result.push(line);
|
|
441
|
-
}
|
|
442
|
-
i++;
|
|
443
|
-
continue;
|
|
444
|
-
}
|
|
445
|
-
i++;
|
|
446
|
-
}
|
|
447
|
-
return result.join("\n");
|
|
448
|
-
}
|
|
449
|
-
function captureDocstring(lines, i, result) {
|
|
450
|
-
if (i >= lines.length)
|
|
451
|
-
return i;
|
|
452
|
-
const trimmed = lines[i].trim();
|
|
453
|
-
if (!trimmed.startsWith('"""') && !trimmed.startsWith("'''")) {
|
|
454
|
-
return i;
|
|
455
|
-
}
|
|
456
|
-
const quoteType = trimmed.substring(0, 3);
|
|
457
|
-
result.push(lines[i]);
|
|
458
|
-
// Single-line docstring: """Something."""
|
|
459
|
-
if (trimmed.length > 6 && trimmed.endsWith(quoteType)) {
|
|
460
|
-
return i + 1;
|
|
461
|
-
}
|
|
462
|
-
// Multi-line docstring
|
|
463
|
-
i++;
|
|
464
|
-
while (i < lines.length) {
|
|
465
|
-
result.push(lines[i]);
|
|
466
|
-
if (lines[i].trim().endsWith(quoteType)) {
|
|
467
|
-
return i + 1;
|
|
468
|
-
}
|
|
469
|
-
i++;
|
|
470
|
-
}
|
|
471
|
-
return i;
|
|
472
|
-
}
|
|
473
|
-
function measureIndent(line) {
|
|
474
|
-
const match = line.match(/^(\s*)/);
|
|
475
|
-
return match ? match[1].length : 0;
|
|
476
|
-
}
|
|
477
|
-
// ─── Generic Compression ────────────────────────────────────────────
|
|
478
|
-
function compressGeneric(content, filePath) {
|
|
479
|
-
const ext = path.extname(filePath).toLowerCase();
|
|
480
|
-
const lines = content.split("\n");
|
|
481
|
-
const lineCount = lines.length;
|
|
482
|
-
// Small config/data files: return as-is
|
|
483
|
-
if (CONFIG_EXTENSIONS.has(ext) && lineCount <= 150) {
|
|
484
|
-
return content;
|
|
485
|
-
}
|
|
486
|
-
// Larger files: provide a summary + head
|
|
487
|
-
if (lineCount > 150) {
|
|
488
|
-
const head = lines.slice(0, 60).join("\n");
|
|
489
|
-
return [
|
|
490
|
-
`// File: ${path.basename(filePath)} (${lineCount} lines)`,
|
|
491
|
-
`// Language not supported for semantic compression.`,
|
|
492
|
-
`// Showing first 60 lines:`,
|
|
493
|
-
``,
|
|
494
|
-
head,
|
|
495
|
-
``,
|
|
496
|
-
`// ... (${lineCount - 60} more lines truncated)`,
|
|
497
|
-
].join("\n");
|
|
498
|
-
}
|
|
499
|
-
return content;
|
|
500
|
-
}
|
|
501
|
-
// ─── Symbol Extraction (Full Source) ────────────────────────────────
|
|
502
|
-
function extractTSSymbol(content, symbolName, filePath, className) {
|
|
503
|
-
const project = getProject();
|
|
504
|
-
const ext = path.extname(filePath);
|
|
505
|
-
const tempName = `extract_${Date.now()}${ext}`;
|
|
506
|
-
let sourceFile;
|
|
507
|
-
try {
|
|
508
|
-
sourceFile = project.createSourceFile(tempName, content, {
|
|
509
|
-
overwrite: true,
|
|
510
|
-
});
|
|
511
|
-
}
|
|
512
|
-
catch {
|
|
513
|
-
return null;
|
|
514
|
-
}
|
|
515
|
-
try {
|
|
516
|
-
// If className is provided, scope search to within that class
|
|
517
|
-
if (className) {
|
|
518
|
-
const cls = sourceFile.getClass(className);
|
|
519
|
-
if (!cls)
|
|
520
|
-
return null;
|
|
521
|
-
const method = cls.getMethod(symbolName);
|
|
522
|
-
if (method)
|
|
523
|
-
return method.getFullText().trim();
|
|
524
|
-
const getter = cls.getGetAccessor(symbolName);
|
|
525
|
-
if (getter)
|
|
526
|
-
return getter.getFullText().trim();
|
|
527
|
-
const setter = cls.getSetAccessor(symbolName);
|
|
528
|
-
if (setter)
|
|
529
|
-
return setter.getFullText().trim();
|
|
530
|
-
const prop = cls.getProperty(symbolName);
|
|
531
|
-
if (prop)
|
|
532
|
-
return prop.getFullText().trim();
|
|
533
|
-
return null;
|
|
534
|
-
}
|
|
535
|
-
// Search top-level functions
|
|
536
|
-
const func = sourceFile.getFunction(symbolName);
|
|
537
|
-
if (func)
|
|
538
|
-
return func.getFullText().trim();
|
|
539
|
-
// Search classes
|
|
540
|
-
const cls = sourceFile.getClass(symbolName);
|
|
541
|
-
if (cls)
|
|
542
|
-
return cls.getFullText().trim();
|
|
543
|
-
// Search interfaces
|
|
544
|
-
const iface = sourceFile.getInterface(symbolName);
|
|
545
|
-
if (iface)
|
|
546
|
-
return iface.getFullText().trim();
|
|
547
|
-
// Search type aliases
|
|
548
|
-
const typeAlias = sourceFile.getTypeAlias(symbolName);
|
|
549
|
-
if (typeAlias)
|
|
550
|
-
return typeAlias.getFullText().trim();
|
|
551
|
-
// Search enums
|
|
552
|
-
const enumDecl = sourceFile.getEnum(symbolName);
|
|
553
|
-
if (enumDecl)
|
|
554
|
-
return enumDecl.getFullText().trim();
|
|
555
|
-
// Search methods inside classes
|
|
556
|
-
for (const c of sourceFile.getClasses()) {
|
|
557
|
-
const method = c.getMethod(symbolName);
|
|
558
|
-
if (method)
|
|
559
|
-
return method.getFullText().trim();
|
|
560
|
-
const getter = c.getGetAccessor(symbolName);
|
|
561
|
-
if (getter)
|
|
562
|
-
return getter.getFullText().trim();
|
|
563
|
-
const setter = c.getSetAccessor(symbolName);
|
|
564
|
-
if (setter)
|
|
565
|
-
return setter.getFullText().trim();
|
|
566
|
-
}
|
|
567
|
-
// Search variable declarations (arrow functions, consts)
|
|
568
|
-
for (const varStmt of sourceFile.getVariableStatements()) {
|
|
569
|
-
for (const decl of varStmt.getDeclarations()) {
|
|
570
|
-
if (decl.getName() === symbolName) {
|
|
571
|
-
return varStmt.getFullText().trim();
|
|
572
|
-
}
|
|
573
|
-
}
|
|
574
|
-
}
|
|
575
|
-
return null;
|
|
576
|
-
}
|
|
577
|
-
finally {
|
|
578
|
-
try {
|
|
579
|
-
project.removeSourceFile(sourceFile);
|
|
580
|
-
}
|
|
581
|
-
catch {
|
|
582
|
-
// Ignore
|
|
583
|
-
}
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
function extractPySymbol(content, symbolName, className) {
|
|
587
|
-
const lines = content.split("\n");
|
|
588
|
-
const escapedName = symbolName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
589
|
-
// If className is provided, find the class first, then search within it
|
|
590
|
-
if (className) {
|
|
591
|
-
const escapedClass = className.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
592
|
-
for (let i = 0; i < lines.length; i++) {
|
|
593
|
-
const trimmed = lines[i].trim();
|
|
594
|
-
if (!new RegExp(`^class\\s+${escapedClass}[\\s(:]`).test(trimmed))
|
|
595
|
-
continue;
|
|
596
|
-
// Found the class — now search for the method within it
|
|
597
|
-
const classIndent = measureIndent(lines[i]);
|
|
598
|
-
let j = i + 1;
|
|
599
|
-
while (j < lines.length) {
|
|
600
|
-
const bodyLine = lines[j];
|
|
601
|
-
if (bodyLine.trim() === "") {
|
|
602
|
-
j++;
|
|
603
|
-
continue;
|
|
604
|
-
}
|
|
605
|
-
if (measureIndent(bodyLine) <= classIndent && bodyLine.trim() !== "")
|
|
606
|
-
break;
|
|
607
|
-
const bodyTrimmed = bodyLine.trim();
|
|
608
|
-
const isFunc = new RegExp(`^(?:async\\s+)?def\\s+${escapedName}\\s*\\(`).test(bodyTrimmed);
|
|
609
|
-
if (isFunc) {
|
|
610
|
-
const startLine = j;
|
|
611
|
-
const baseIndent = measureIndent(bodyLine);
|
|
612
|
-
const blockLines = [bodyLine];
|
|
613
|
-
j++;
|
|
614
|
-
while (j < lines.length) {
|
|
615
|
-
const innerLine = lines[j];
|
|
616
|
-
if (innerLine.trim() === "") {
|
|
617
|
-
blockLines.push(innerLine);
|
|
618
|
-
j++;
|
|
619
|
-
continue;
|
|
620
|
-
}
|
|
621
|
-
if (measureIndent(innerLine) > baseIndent) {
|
|
622
|
-
blockLines.push(innerLine);
|
|
623
|
-
j++;
|
|
624
|
-
}
|
|
625
|
-
else
|
|
626
|
-
break;
|
|
627
|
-
}
|
|
628
|
-
while (blockLines.length > 0 && blockLines[blockLines.length - 1].trim() === "") {
|
|
629
|
-
blockLines.pop();
|
|
630
|
-
}
|
|
631
|
-
return blockLines.join("\n");
|
|
632
|
-
}
|
|
633
|
-
j++;
|
|
634
|
-
}
|
|
635
|
-
return null; // Method not found within class
|
|
636
|
-
}
|
|
637
|
-
return null; // Class not found
|
|
638
|
-
}
|
|
639
|
-
// Original behavior when no className is provided
|
|
640
|
-
for (let i = 0; i < lines.length; i++) {
|
|
641
|
-
const line = lines[i];
|
|
642
|
-
const trimmed = line.trim();
|
|
643
|
-
// Match class or function by exact name
|
|
644
|
-
const isClass = new RegExp(`^class\\s+${escapedName}[\\s(:]`).test(trimmed);
|
|
645
|
-
const isFunc = new RegExp(`^(?:async\\s+)?def\\s+${escapedName}\\s*\\(`).test(trimmed);
|
|
646
|
-
if (!isClass && !isFunc)
|
|
647
|
-
continue;
|
|
648
|
-
const startLine = i;
|
|
649
|
-
const baseIndent = measureIndent(line);
|
|
650
|
-
const blockLines = [line];
|
|
651
|
-
i++;
|
|
652
|
-
// Capture the entire block (including body)
|
|
653
|
-
while (i < lines.length) {
|
|
654
|
-
const bodyLine = lines[i];
|
|
655
|
-
if (bodyLine.trim() === "") {
|
|
656
|
-
blockLines.push(bodyLine);
|
|
657
|
-
i++;
|
|
658
|
-
continue;
|
|
659
|
-
}
|
|
660
|
-
if (measureIndent(bodyLine) > baseIndent) {
|
|
661
|
-
blockLines.push(bodyLine);
|
|
662
|
-
i++;
|
|
663
|
-
}
|
|
664
|
-
else {
|
|
665
|
-
break;
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
// Trim trailing empty lines
|
|
669
|
-
while (blockLines.length > 0 &&
|
|
670
|
-
blockLines[blockLines.length - 1].trim() === "") {
|
|
671
|
-
blockLines.pop();
|
|
672
|
-
}
|
|
673
|
-
return blockLines.join("\n");
|
|
674
|
-
}
|
|
675
|
-
return null;
|
|
676
|
-
}
|
|
677
|
-
//# sourceMappingURL=semanticCompressor.js.map
|