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.
Files changed (129) hide show
  1. package/CHANGELOG.md +92 -236
  2. package/README.md +304 -298
  3. package/dist/src/core/engine.d.ts +21 -0
  4. package/dist/src/core/engine.js +68 -0
  5. package/dist/src/core/engine.js.map +1 -0
  6. package/dist/src/core/validator.d.ts +15 -0
  7. package/dist/src/core/validator.js +44 -0
  8. package/dist/src/core/validator.js.map +1 -0
  9. package/dist/src/index.d.ts +7 -11
  10. package/dist/src/index.js +182 -397
  11. package/dist/src/index.js.map +1 -1
  12. package/dist/src/operations/write.d.ts +51 -0
  13. package/dist/src/operations/write.js +169 -0
  14. package/dist/src/operations/write.js.map +1 -0
  15. package/dist/src/parsers/base.d.ts +28 -0
  16. package/dist/src/parsers/base.js +27 -0
  17. package/dist/src/parsers/base.js.map +1 -0
  18. package/dist/src/parsers/dartTreeSitter.d.ts +13 -0
  19. package/dist/src/parsers/dartTreeSitter.js +91 -0
  20. package/dist/src/parsers/dartTreeSitter.js.map +1 -0
  21. package/dist/src/parsers/php.d.ts +12 -0
  22. package/dist/src/parsers/php.js +86 -0
  23. package/dist/src/parsers/php.js.map +1 -0
  24. package/dist/src/parsers/python.d.ts +12 -0
  25. package/dist/src/parsers/python.js +86 -0
  26. package/dist/src/parsers/python.js.map +1 -0
  27. package/dist/src/parsers/registry.d.ts +15 -0
  28. package/dist/src/parsers/registry.js +70 -0
  29. package/dist/src/parsers/registry.js.map +1 -0
  30. package/dist/src/parsers/typescript.d.ts +13 -0
  31. package/dist/src/parsers/typescript.js +98 -0
  32. package/dist/src/parsers/typescript.js.map +1 -0
  33. package/llms.txt +246 -234
  34. package/mcp-code-context-3.0.2.tgz +0 -0
  35. package/package.json +59 -57
  36. package/tsconfig.tests.json +27 -0
  37. package/.io/RULES.md +0 -12
  38. package/CONTRIBUTING.md +0 -243
  39. package/PLAN_v2.5.0.md +0 -407
  40. package/TROUBLESHOOTING.md +0 -38
  41. package/dist/src/ast/dartCompressor.d.ts +0 -27
  42. package/dist/src/ast/dartCompressor.js +0 -859
  43. package/dist/src/ast/dartCompressor.js.map +0 -1
  44. package/dist/src/ast/phpCompressor.d.ts +0 -24
  45. package/dist/src/ast/phpCompressor.js +0 -634
  46. package/dist/src/ast/phpCompressor.js.map +0 -1
  47. package/dist/src/ast/semanticCompressor.d.ts +0 -22
  48. package/dist/src/ast/semanticCompressor.js +0 -677
  49. package/dist/src/ast/semanticCompressor.js.map +0 -1
  50. package/dist/src/ast/writers/dartWriter.d.ts +0 -37
  51. package/dist/src/ast/writers/dartWriter.js +0 -544
  52. package/dist/src/ast/writers/dartWriter.js.map +0 -1
  53. package/dist/src/ast/writers/phpWriter.d.ts +0 -37
  54. package/dist/src/ast/writers/phpWriter.js +0 -411
  55. package/dist/src/ast/writers/phpWriter.js.map +0 -1
  56. package/dist/src/ast/writers/pyWriter.d.ts +0 -37
  57. package/dist/src/ast/writers/pyWriter.js +0 -355
  58. package/dist/src/ast/writers/pyWriter.js.map +0 -1
  59. package/dist/src/ast/writers/safeRename.d.ts +0 -14
  60. package/dist/src/ast/writers/safeRename.js +0 -258
  61. package/dist/src/ast/writers/safeRename.js.map +0 -1
  62. package/dist/src/ast/writers/symbolWriter.d.ts +0 -64
  63. package/dist/src/ast/writers/symbolWriter.js +0 -174
  64. package/dist/src/ast/writers/symbolWriter.js.map +0 -1
  65. package/dist/src/ast/writers/tsWriter.d.ts +0 -38
  66. package/dist/src/ast/writers/tsWriter.js +0 -344
  67. package/dist/src/ast/writers/tsWriter.js.map +0 -1
  68. package/dist/src/cache/astCache.d.ts +0 -39
  69. package/dist/src/cache/astCache.js +0 -169
  70. package/dist/src/cache/astCache.js.map +0 -1
  71. package/dist/src/handlers/readHandlers.d.ts +0 -70
  72. package/dist/src/handlers/readHandlers.js +0 -455
  73. package/dist/src/handlers/readHandlers.js.map +0 -1
  74. package/dist/src/handlers/utilHandlers.d.ts +0 -31
  75. package/dist/src/handlers/utilHandlers.js +0 -69
  76. package/dist/src/handlers/utilHandlers.js.map +0 -1
  77. package/dist/src/handlers/writeHandlers.d.ts +0 -57
  78. package/dist/src/handlers/writeHandlers.js +0 -499
  79. package/dist/src/handlers/writeHandlers.js.map +0 -1
  80. package/dist/src/tools/readFileLines.d.ts +0 -26
  81. package/dist/src/tools/readFileLines.js +0 -77
  82. package/dist/src/tools/readFileLines.js.map +0 -1
  83. package/dist/src/tools/searchCodePattern.d.ts +0 -37
  84. package/dist/src/tools/searchCodePattern.js +0 -144
  85. package/dist/src/tools/searchCodePattern.js.map +0 -1
  86. package/dist/src/utils/arrayUtils.d.ts +0 -12
  87. package/dist/src/utils/arrayUtils.js +0 -27
  88. package/dist/src/utils/arrayUtils.js.map +0 -1
  89. package/dist/src/utils/backupManager.d.ts +0 -31
  90. package/dist/src/utils/backupManager.js +0 -124
  91. package/dist/src/utils/backupManager.js.map +0 -1
  92. package/dist/src/utils/confirmationCache.d.ts +0 -16
  93. package/dist/src/utils/confirmationCache.js +0 -40
  94. package/dist/src/utils/confirmationCache.js.map +0 -1
  95. package/dist/src/utils/constants.d.ts +0 -46
  96. package/dist/src/utils/constants.js +0 -112
  97. package/dist/src/utils/constants.js.map +0 -1
  98. package/dist/src/utils/dependencyChecker.d.ts +0 -1
  99. package/dist/src/utils/dependencyChecker.js +0 -55
  100. package/dist/src/utils/dependencyChecker.js.map +0 -1
  101. package/dist/src/utils/diffEngine.d.ts +0 -21
  102. package/dist/src/utils/diffEngine.js +0 -163
  103. package/dist/src/utils/diffEngine.js.map +0 -1
  104. package/dist/src/utils/fuzzyMatch.d.ts +0 -8
  105. package/dist/src/utils/fuzzyMatch.js +0 -69
  106. package/dist/src/utils/fuzzyMatch.js.map +0 -1
  107. package/dist/src/utils/ignoreManager.d.ts +0 -30
  108. package/dist/src/utils/ignoreManager.js +0 -186
  109. package/dist/src/utils/ignoreManager.js.map +0 -1
  110. package/dist/src/utils/normalization.d.ts +0 -49
  111. package/dist/src/utils/normalization.js +0 -173
  112. package/dist/src/utils/normalization.js.map +0 -1
  113. package/dist/src/utils/projectRoot.d.ts +0 -17
  114. package/dist/src/utils/projectRoot.js +0 -42
  115. package/dist/src/utils/projectRoot.js.map +0 -1
  116. package/dist/src/utils/secureValidation.d.ts +0 -15
  117. package/dist/src/utils/secureValidation.js +0 -41
  118. package/dist/src/utils/secureValidation.js.map +0 -1
  119. package/dist/src/utils/syntaxValidator.d.ts +0 -15
  120. package/dist/src/utils/syntaxValidator.js +0 -218
  121. package/dist/src/utils/syntaxValidator.js.map +0 -1
  122. package/dist/src/utils/transactionManager.d.ts +0 -46
  123. package/dist/src/utils/transactionManager.js +0 -123
  124. package/dist/src/utils/transactionManager.js.map +0 -1
  125. package/dist/src/utils/validation.d.ts +0 -87
  126. package/dist/src/utils/validation.js +0 -231
  127. package/dist/src/utils/validation.js.map +0 -1
  128. package/docs/ARCHITECTURE.md +0 -300
  129. package/docs/architecture/ADR-001-modular-handlers.md +0 -119
@@ -1,859 +0,0 @@
1
- /**
2
- * dartCompressor — Regex + brace-counting Dart semantic compressor.
3
- *
4
- * Dart has no npm AST parser, so we use a high-fidelity regex engine combined
5
- * with precise brace-counting to extract structural signatures from Dart source.
6
- * This approach handles all real-world Flutter/Dart patterns including generics,
7
- * factory constructors, mixins, extensions, and enum members.
8
- *
9
- * Design principles:
10
- * 1. Brace-counting for block boundaries — never fails on nested blocks
11
- * 2. Regex for signature detection — generics-aware, handles multi-line
12
- * 3. Preserve doc comments (///) for semantic context
13
- * 4. Preserve annotations (@override, @visibleForTesting, etc.)
14
- * 5. Preserve field declarations (they ARE the structural contract)
15
- */
16
- // ─── Constants ──────────────────────────────────────────────────────
17
- /**
18
- * Regex patterns for Dart structural elements.
19
- * These MUST handle generics (e.g., `Map<String, List<int>>`) which
20
- * contain `>` characters that could confuse naive parsers.
21
- */
22
- // Top-level and class declarations
23
- const DECLARATION_REGEX = /^(\s*)((?:abstract\s+|sealed\s+|base\s+|final\s+|interface\s+)*)(class|mixin|extension(?:\s+type)?|enum)\s+(\w+)/;
24
- // Function/method declarations — handles generics, async, arrow syntax
25
- // Matches: `Type? name<T>(params) async => ...` or `Type? name<T>(params) { ... }`
26
- const METHOD_REGEX = /^(\s*)((?:static\s+|abstract\s+|external\s+|@\w+\s+)*)([\w<>,?\s[\]]+?\s+)?(\w+)\s*(<[^>]*>)?\s*\(([^)]*(?:\([^)]*\)[^)]*)*)\)\s*(async\*?|sync\*?)?\s*(=>\s*.+;|\{)/;
27
- // Constructor regex — `ClassName(`, `ClassName.named(`, `factory ClassName(`
28
- const CONSTRUCTOR_REGEX = /^(\s*)(const\s+|factory\s+)?((\w+)(\.\w+)?)\s*\(([^)]*(?:\([^)]*\)[^)]*)*)\)\s*(:\s*[^{;]+)?\s*([{;]|=>)/;
29
- // Field/property declaration
30
- const FIELD_REGEX = /^(\s*)((?:static\s+|late\s+|final\s+|const\s+|covariant\s+)*)([\w<>,?\s[\].]+?\s+)(\w+)\s*(=\s*[^;]+)?;/;
31
- // Getter/setter
32
- const GETTER_REGEX = /^(\s*)((?:static\s+)?)([\w<>,?\s[\].]*?\s+)?get\s+(\w+)\b/;
33
- const SETTER_REGEX = /^(\s*)((?:static\s+)?)set\s+(\w+)\s*\(([^)]*)\)\s*([{]|=>)/;
34
- // Import / export / part statements
35
- const IMPORT_REGEX = /^(import|export|part\s+of|part)\s+['"]([^'"]+)['"]/;
36
- // Typedef
37
- const TYPEDEF_REGEX = /^(\s*)typedef\s+(.+);/;
38
- // Enum case (inside an enum body)
39
- const ENUM_CASE_REGEX = /^(\s*)(\w+)(\([^)]*\))?\s*[,;]/;
40
- // ─── Public API ────────────────────────────────────────────────────
41
- /**
42
- * Compress a Dart file into its semantic skeleton.
43
- * Returns only structural signatures — no function/method bodies.
44
- */
45
- export function compressDart(content) {
46
- const lines = content.split("\n");
47
- const result = [];
48
- let i = 0;
49
- // Phase 1: Collect imports
50
- const importBlock = [];
51
- for (const line of lines) {
52
- const t = line.trim();
53
- if (IMPORT_REGEX.test(t)) {
54
- importBlock.push(line);
55
- }
56
- }
57
- if (importBlock.length > 0) {
58
- result.push("// ── Imports ──");
59
- result.push(...importBlock);
60
- result.push("");
61
- }
62
- // Phase 2: Walk the file extracting structural signatures
63
- while (i < lines.length) {
64
- const line = lines[i];
65
- const trimmed = line.trim();
66
- // Skip blank lines
67
- if (trimmed === "") {
68
- i++;
69
- continue;
70
- }
71
- // Skip already-collected imports
72
- if (IMPORT_REGEX.test(trimmed)) {
73
- i++;
74
- continue;
75
- }
76
- // Skip single-line comments (not doc comments)
77
- if (trimmed.startsWith("//") && !trimmed.startsWith("///")) {
78
- i++;
79
- continue;
80
- }
81
- // Preserve doc comments (///) — collect them
82
- if (trimmed.startsWith("///")) {
83
- const docLines = collectDocComments(lines, i);
84
- result.push(...docLines.lines);
85
- i = docLines.nextIndex;
86
- continue;
87
- }
88
- // Preserve annotations (@override, @visibleForTesting, etc.)
89
- if (trimmed.startsWith("@") && !trimmed.startsWith("@override")) {
90
- result.push(line);
91
- i++;
92
- continue;
93
- }
94
- // @override — attach to next item, don't emit standalone
95
- if (trimmed === "@override") {
96
- result.push(line);
97
- i++;
98
- continue;
99
- }
100
- // Typedefs — pass through
101
- const typedefMatch = TYPEDEF_REGEX.exec(trimmed);
102
- if (typedefMatch) {
103
- result.push(line);
104
- i++;
105
- continue;
106
- }
107
- // Top-level constants and variables
108
- if (isTopLevelField(lines, i)) {
109
- const field = processFieldDeclaration(lines, i);
110
- result.push(...field.lines);
111
- i = field.nextIndex;
112
- continue;
113
- }
114
- // Class / Mixin / Extension / Enum declarations
115
- const declMatch = DECLARATION_REGEX.exec(trimmed);
116
- if (declMatch) {
117
- const classResult = processClassDeclaration(lines, i);
118
- result.push(...classResult.lines);
119
- i = classResult.nextIndex;
120
- continue;
121
- }
122
- // Top-level functions
123
- if (isTopLevelFunction(trimmed)) {
124
- const funcResult = processTopLevelFunction(lines, i);
125
- result.push(...funcResult.lines);
126
- i = funcResult.nextIndex;
127
- continue;
128
- }
129
- i++;
130
- }
131
- return result.join("\n");
132
- }
133
- /**
134
- * Extract the full source code of a named symbol from a Dart file.
135
- * Supports classes, mixins, extensions, enums, functions, and methods.
136
- * When className is provided, scopes method search to within that class only.
137
- * Returns null if the symbol is not found.
138
- */
139
- export function extractDartSymbol(content, symbolName, className) {
140
- const lines = content.split("\n");
141
- // If className is provided, scope the search to within that class
142
- if (className) {
143
- for (let i = 0; i < lines.length; i++) {
144
- const trimmed = lines[i].trim();
145
- const declMatch = DECLARATION_REGEX.exec(trimmed);
146
- if (declMatch && declMatch[4] === className) {
147
- // Found the class — determine body boundaries
148
- let braceLineIdx = i;
149
- while (braceLineIdx < lines.length && !lines[braceLineIdx].includes("{")) {
150
- braceLineIdx++;
151
- }
152
- const bodyEnd = findMatchingBrace(lines, braceLineIdx + 1, 1);
153
- // Search only within the class body for the method
154
- for (let j = braceLineIdx + 1; j < bodyEnd; j++) {
155
- const bodyTrimmed = lines[j].trim();
156
- const methodMatch = bodyTrimmed.match(new RegExp(`\\b${escapeRegex(symbolName)}\\s*[<(]`));
157
- if (methodMatch &&
158
- !DECLARATION_REGEX.test(bodyTrimmed) &&
159
- !IMPORT_REGEX.test(bodyTrimmed) &&
160
- (bodyTrimmed.includes("(") || bodyTrimmed.includes("<"))) {
161
- if (isMethodOrConstructor(bodyTrimmed) ||
162
- isTopLevelFunction(bodyTrimmed)) {
163
- return extractFullBlock(lines, j);
164
- }
165
- }
166
- }
167
- return null; // Method not found within the specified class
168
- }
169
- }
170
- return null; // Class not found
171
- }
172
- // Original behavior when no className is provided
173
- for (let i = 0; i < lines.length; i++) {
174
- const trimmed = lines[i].trim();
175
- // Match class-level declarations (class, mixin, extension, enum)
176
- const declMatch = DECLARATION_REGEX.exec(trimmed);
177
- if (declMatch && declMatch[4] === symbolName) {
178
- return extractFullBlock(lines, i);
179
- }
180
- // Match top-level functions
181
- if (isTopLevelFunction(trimmed)) {
182
- const funcName = extractFunctionName(trimmed);
183
- if (funcName === symbolName) {
184
- return extractFullBlock(lines, i);
185
- }
186
- }
187
- // Match methods inside classes (search inside class bodies)
188
- // Look for `methodName(` pattern
189
- const methodMatch = trimmed.match(new RegExp(`\\b${escapeRegex(symbolName)}\\s*[<(]`));
190
- if (methodMatch &&
191
- !DECLARATION_REGEX.test(trimmed) &&
192
- !IMPORT_REGEX.test(trimmed) &&
193
- (trimmed.includes("(") || trimmed.includes("<"))) {
194
- // Verify this is actually a method/function definition
195
- if (isMethodOrConstructor(trimmed) ||
196
- isTopLevelFunction(trimmed)) {
197
- return extractFullBlock(lines, i);
198
- }
199
- }
200
- }
201
- return null;
202
- }
203
- function processClassDeclaration(lines, startIndex) {
204
- const result = [];
205
- let i = startIndex;
206
- // Collect leading doc comments that precede this declaration
207
- // (they may already have been emitted, so check if we need to go backwards)
208
- // Collect the full declaration header (may span multiple lines)
209
- let header = "";
210
- while (i < lines.length) {
211
- header += (header ? " " : "") + lines[i].trim();
212
- if (header.includes("{")) {
213
- break;
214
- }
215
- i++;
216
- }
217
- // Emit the header up to (and including) the opening brace
218
- const bracePos = header.indexOf("{");
219
- if (bracePos >= 0) {
220
- result.push(header.substring(0, bracePos + 1));
221
- }
222
- else {
223
- result.push(header);
224
- return { lines: result, nextIndex: i + 1 };
225
- }
226
- // Determine if this is an enum (special handling for cases)
227
- const isEnum = /\benum\s+/.test(header);
228
- // Find the matching closing brace
229
- i++;
230
- let braceDepth = 1;
231
- const bodyStart = i;
232
- const bodyEnd = findMatchingBrace(lines, i, braceDepth);
233
- // Process the body
234
- const bodyLines = lines.slice(bodyStart, bodyEnd);
235
- let j = 0;
236
- while (j < bodyLines.length) {
237
- const bodyLine = bodyLines[j];
238
- const bodyTrimmed = bodyLine.trim();
239
- // Skip blank lines
240
- if (bodyTrimmed === "") {
241
- j++;
242
- continue;
243
- }
244
- // Doc comments — preserve
245
- if (bodyTrimmed.startsWith("///")) {
246
- const docs = collectDocCommentsRelative(bodyLines, j);
247
- result.push(...docs.lines);
248
- j = docs.nextIndex;
249
- continue;
250
- }
251
- // Annotations — preserve
252
- if (bodyTrimmed.startsWith("@")) {
253
- result.push(bodyLine.replace(/\r$/, ""));
254
- j++;
255
- continue;
256
- }
257
- // Enum cases (before the semicolon or methods)
258
- if (isEnum && isEnumCase(bodyTrimmed)) {
259
- result.push(bodyLine.replace(/\r$/, ""));
260
- j++;
261
- continue;
262
- }
263
- // Enum semicolon separator (between cases and methods/fields)
264
- if (isEnum && bodyTrimmed === ";") {
265
- result.push(bodyLine.replace(/\r$/, ""));
266
- j++;
267
- continue;
268
- }
269
- // Field declarations
270
- if (isFieldDeclaration(bodyLines, j)) {
271
- const field = processFieldDeclaration(bodyLines, j);
272
- result.push(...field.lines);
273
- j = field.nextIndex;
274
- continue;
275
- }
276
- // Getter
277
- if (GETTER_REGEX.test(bodyTrimmed)) {
278
- const getter = processGetterSetter(bodyLines, j);
279
- result.push(...getter.lines);
280
- j = getter.nextIndex;
281
- continue;
282
- }
283
- // Setter
284
- if (bodyTrimmed.includes(" set ") && bodyTrimmed.includes("(")) {
285
- const setter = processGetterSetter(bodyLines, j);
286
- result.push(...setter.lines);
287
- j = setter.nextIndex;
288
- continue;
289
- }
290
- // Constructor or method
291
- if (isMethodOrConstructor(bodyTrimmed)) {
292
- const method = processMethodSignature(bodyLines, j);
293
- result.push(...method.lines);
294
- j = method.nextIndex;
295
- continue;
296
- }
297
- j++;
298
- }
299
- result.push("}");
300
- result.push("");
301
- return { lines: result, nextIndex: bodyEnd + 1 };
302
- }
303
- // ─── Top-level Functions ───────────────────────────────────────────
304
- function processTopLevelFunction(lines, startIndex) {
305
- const result = [];
306
- let i = startIndex;
307
- // Collect the full signature
308
- let signature = "";
309
- while (i < lines.length) {
310
- signature += (signature ? " " : "") + lines[i].trim();
311
- // Stop when we find `{` or `=> ...;`
312
- if (findBlockBraceIndex(signature) >= 0 || (signature.includes("=>") && signature.endsWith(";"))) {
313
- break;
314
- }
315
- i++;
316
- }
317
- const indent = getIndent(lines[startIndex]);
318
- if (signature.includes("=>") && signature.endsWith(";")) {
319
- const arrowPos = signature.indexOf("=>");
320
- result.push(`${indent}${signature.substring(0, arrowPos).trim()} => /* ... */;`);
321
- }
322
- else if (findBlockBraceIndex(signature) >= 0) {
323
- const bracePos = findBlockBraceIndex(signature);
324
- result.push(`${indent}${signature.substring(0, bracePos).trim()} { /* ... */ }`);
325
- // Skip the body
326
- i = findMatchingBrace(lines, i + 1, 1);
327
- }
328
- result.push("");
329
- return { lines: result, nextIndex: i + 1 };
330
- }
331
- // ─── Method/Constructor Signature Processing ───────────────────────
332
- function processMethodSignature(bodyLines, startIndex) {
333
- const result = [];
334
- let j = startIndex;
335
- // Collect the full signature (may span multiple lines until { or ; or =>)
336
- let signature = "";
337
- let foundEnd = false;
338
- while (j < bodyLines.length) {
339
- const lineContent = bodyLines[j].trim();
340
- signature += (signature ? " " : "") + lineContent;
341
- // Check if we have the complete signature
342
- if (findBlockBraceIndex(signature) >= 0) {
343
- foundEnd = true;
344
- break;
345
- }
346
- if (signature.includes("=>")) {
347
- // Arrow body — find the semicolon
348
- if (signature.endsWith(";")) {
349
- foundEnd = true;
350
- break;
351
- }
352
- // Multi-line arrow — keep collecting until ;
353
- j++;
354
- while (j < bodyLines.length) {
355
- const arrowLine = bodyLines[j].trim();
356
- signature += " " + arrowLine;
357
- if (arrowLine.endsWith(";")) {
358
- break;
359
- }
360
- j++;
361
- }
362
- foundEnd = true;
363
- break;
364
- }
365
- if (lineContent.endsWith(";")) {
366
- // Abstract method or similar
367
- foundEnd = true;
368
- break;
369
- }
370
- j++;
371
- }
372
- const indent = getIndent(bodyLines[startIndex]);
373
- if (!foundEnd) {
374
- result.push(bodyLines[startIndex].replace(/\r$/, ""));
375
- return { lines: result, nextIndex: j + 1 };
376
- }
377
- if (signature.includes("=>")) {
378
- const arrowPos = signature.indexOf("=>");
379
- result.push(`${indent}${signature.substring(0, arrowPos).trim()} => /* ... */;`);
380
- }
381
- else if (findBlockBraceIndex(signature) >= 0) {
382
- const bracePos = findBlockBraceIndex(signature);
383
- const sigPart = signature.substring(0, bracePos).trim();
384
- result.push(`${indent}${sigPart} { /* ... */ }`);
385
- j = findMatchingBraceRelative(bodyLines, j + 1, 1);
386
- }
387
- else if (signature.endsWith(";")) {
388
- result.push(`${indent}${signature}`);
389
- }
390
- return { lines: result, nextIndex: j + 1 };
391
- }
392
- function processFieldDeclaration(bodyLines, startIndex) {
393
- const result = [];
394
- let j = startIndex;
395
- let signature = "";
396
- while (j < bodyLines.length) {
397
- signature += (signature ? " " : "") + bodyLines[j].trim();
398
- if (signature.endsWith(";"))
399
- break;
400
- j++;
401
- }
402
- const indent = getIndent(bodyLines[startIndex]);
403
- result.push(`${indent}${signature}`);
404
- return { lines: result, nextIndex: j + 1 };
405
- }
406
- // ─── Getter/Setter Processing ──────────────────────────────────────
407
- function processGetterSetter(bodyLines, startIndex) {
408
- const result = [];
409
- let j = startIndex;
410
- let signature = "";
411
- while (j < bodyLines.length) {
412
- signature += (signature ? " " : "") + bodyLines[j].trim();
413
- if (signature.includes("=>")) {
414
- if (signature.endsWith(";"))
415
- break;
416
- j++;
417
- while (j < bodyLines.length) {
418
- signature += " " + bodyLines[j].trim();
419
- if (bodyLines[j].trim().endsWith(";"))
420
- break;
421
- j++;
422
- }
423
- break;
424
- }
425
- if (findBlockBraceIndex(signature) >= 0)
426
- break;
427
- if (signature.endsWith(";"))
428
- break;
429
- j++;
430
- }
431
- const indent = getIndent(bodyLines[startIndex]);
432
- if (signature.includes("=>")) {
433
- const arrowPos = signature.indexOf("=>");
434
- result.push(`${indent}${signature.substring(0, arrowPos).trim()} => /* ... */;`);
435
- }
436
- else if (findBlockBraceIndex(signature) >= 0) {
437
- const bracePos = findBlockBraceIndex(signature);
438
- result.push(`${indent}${signature.substring(0, bracePos).trim()} { /* ... */ }`);
439
- j = findMatchingBraceRelative(bodyLines, j + 1, 1);
440
- }
441
- else {
442
- result.push(`${indent}${signature}`);
443
- }
444
- return { lines: result, nextIndex: j + 1 };
445
- }
446
- // ─── Utility Functions ─────────────────────────────────────────────
447
- function collectDocComments(lines, startIndex) {
448
- const result = [];
449
- let i = startIndex;
450
- while (i < lines.length && lines[i].trim().startsWith("///")) {
451
- result.push(lines[i].replace(/\r$/, ""));
452
- i++;
453
- }
454
- return { lines: result, nextIndex: i };
455
- }
456
- function collectDocCommentsRelative(lines, startIndex) {
457
- return collectDocComments(lines, startIndex);
458
- }
459
- function isTopLevelField(lines, startIndex) {
460
- const line = lines[startIndex];
461
- const trimmed = line.trim();
462
- // Must be at indentation 0
463
- if (line.length > 0 && (line[0] === " " || line[0] === "\t"))
464
- return false;
465
- let signature = "";
466
- let j = startIndex;
467
- while (j < lines.length) {
468
- const t = lines[j].trim();
469
- if (t.startsWith("//") || t.startsWith("@"))
470
- break;
471
- signature += (signature ? " " : "") + t;
472
- if (signature.includes("{") || signature.includes("=>") || signature.includes("("))
473
- return false;
474
- if (signature.endsWith(";"))
475
- break;
476
- j++;
477
- }
478
- if (!signature.endsWith(";"))
479
- return false;
480
- // Must look like a field: starts with const, final, var, type + name
481
- if (/^(const|final|var)\s+/.test(signature)) {
482
- return true;
483
- }
484
- // Typed top-level: `String name = ...;` or `Type name;`
485
- if (/^[A-Z]\w*[<?\s]/.test(signature)) {
486
- return true;
487
- }
488
- return false;
489
- }
490
- function isTopLevelFunction(trimmed) {
491
- // Top-level function: async? returnType? functionName<T>(params) {
492
- // Exclude class/mixin/etc declarations
493
- if (DECLARATION_REGEX.test(trimmed))
494
- return false;
495
- if (IMPORT_REGEX.test(trimmed))
496
- return false;
497
- if (trimmed.startsWith("//"))
498
- return false;
499
- if (trimmed.startsWith("@"))
500
- return false;
501
- // Must contain `(` for parameter list
502
- if (!trimmed.includes("("))
503
- return false;
504
- // Must not start with common non-function keywords
505
- if (/^(return|if|for|while|switch|try|catch|throw|assert|yield)\b/.test(trimmed)) {
506
- return false;
507
- }
508
- // Check common patterns:
509
- // `void main() {`
510
- // `Future<void> loadSections({bool forceRefresh = false}) async {`
511
- // `static Widget buildSection(Map<String, dynamic> section) {`
512
- if (/^([\w<>,?\s[\].]+?\s+)?(\w+)\s*(<[^>]*>)?\s*\(/.test(trimmed) &&
513
- (trimmed.includes("{") || trimmed.includes("=>") || trimmed.endsWith(")") || trimmed.includes(") async") || trimmed.includes(") sync"))) {
514
- return true;
515
- }
516
- return false;
517
- }
518
- function extractFunctionName(trimmed) {
519
- // Extract function name before the `(`
520
- const match = trimmed.match(/(\w+)\s*[<(]/);
521
- if (match) {
522
- // Filter out keywords that aren't actual function names
523
- const name = match[1];
524
- const keywords = new Set([
525
- "if", "for", "while", "switch", "try", "catch", "return",
526
- "class", "mixin", "enum", "extension", "import", "export",
527
- "void", "int", "double", "String", "bool", "List", "Map",
528
- "Set", "Future", "Stream", "const", "final", "var",
529
- "static", "abstract", "factory", "async", "await",
530
- ]);
531
- if (!keywords.has(name))
532
- return name;
533
- }
534
- return "";
535
- }
536
- function isMethodOrConstructor(trimmed) {
537
- if (trimmed.startsWith("//"))
538
- return false;
539
- if (trimmed.startsWith("@"))
540
- return false;
541
- if (!trimmed.includes("("))
542
- return false;
543
- // Skip non-method statements
544
- if (/^(return|if|for|while|switch|try|catch|throw|assert|yield|super|this)\b/.test(trimmed)) {
545
- return false;
546
- }
547
- // Skip field declarations
548
- if (!trimmed.includes("(") ||
549
- (trimmed.endsWith(";") && !trimmed.includes(")") && !trimmed.includes("=>"))) {
550
- return false;
551
- }
552
- // Factory constructors
553
- if (/^(const\s+|factory\s+)/.test(trimmed))
554
- return true;
555
- // Regular methods/constructors: `Type? name(` or `name(`
556
- if (/^([\w<>,?\s[\].]*?\s*)?(\w+)(\.\w+)?\s*[<(]/.test(trimmed)) {
557
- return true;
558
- }
559
- return false;
560
- }
561
- function isFieldDeclaration(lines, startIndex) {
562
- const firstTrimmed = lines[startIndex].trim();
563
- if (firstTrimmed.startsWith("//"))
564
- return false;
565
- if (firstTrimmed.startsWith("@"))
566
- return false;
567
- let signature = "";
568
- let j = startIndex;
569
- while (j < lines.length) {
570
- const t = lines[j].trim();
571
- if (t.startsWith("//") || t.startsWith("@"))
572
- break;
573
- signature += (signature ? " " : "") + t;
574
- // Check for block braces OUTSIDE string literals
575
- // This prevents `'${...}'` Dart interpolation from being misidentified as block openers
576
- if (containsBlockBraceOutsideStrings(signature) || containsArrowOutsideStrings(signature)) {
577
- return false;
578
- }
579
- if (signature.endsWith(";"))
580
- break;
581
- j++;
582
- }
583
- // Field must end with a semicolon
584
- if (!signature.endsWith(";")) {
585
- return false;
586
- }
587
- // Contains `(` before `=` — probably a method or constructor, not a field
588
- // Exception: default values with constructors like `= SomeClass()`
589
- const parenIdx = signature.indexOf("(");
590
- const equalsIdx = signature.indexOf("=");
591
- if (parenIdx >= 0 && (equalsIdx < 0 || parenIdx < equalsIdx)) {
592
- return false;
593
- }
594
- // Looks like: modifiers type name [= value];
595
- return /^(static\s+|late\s+|final\s+|const\s+|covariant\s+)*([\w<>,?\s[\].]*?\s+)(\w+)/.test(signature);
596
- }
597
- function isEnumCase(trimmed) {
598
- // Enum case: `caseName,` or `caseName;` or `caseName(args),`
599
- if (trimmed.startsWith("//") || trimmed.startsWith("@"))
600
- return false;
601
- // Must not look like a method or field with a type
602
- if (/^(static|final|const|late|void|int|double|String|bool|Future|Stream|List|Map|Set|var)\b/.test(trimmed)) {
603
- return false;
604
- }
605
- // Enum case pattern: identifier optionally followed by (args), then , or ;
606
- if (/^\w+(\([^)]*\))?\s*[,;]?\s*$/.test(trimmed)) {
607
- return true;
608
- }
609
- return false;
610
- }
611
- function findMatchingBrace(lines, startIndex, initialDepth) {
612
- let depth = initialDepth;
613
- let i = startIndex;
614
- while (i < lines.length && depth > 0) {
615
- const line = lines[i];
616
- for (const ch of line) {
617
- if (ch === "{")
618
- depth++;
619
- else if (ch === "}") {
620
- depth--;
621
- if (depth === 0)
622
- return i;
623
- }
624
- }
625
- i++;
626
- }
627
- return i;
628
- }
629
- function findMatchingBraceRelative(lines, startIndex, initialDepth) {
630
- return findMatchingBrace(lines, startIndex, initialDepth);
631
- }
632
- function extractFullBlock(lines, startIndex) {
633
- // Walk backwards to capture doc comments and annotations
634
- let actualStart = startIndex;
635
- for (let k = startIndex - 1; k >= 0; k--) {
636
- const t = lines[k].trim();
637
- if (t.startsWith("///") ||
638
- t.startsWith("@") ||
639
- t === "") {
640
- if (t !== "")
641
- actualStart = k;
642
- }
643
- else {
644
- break;
645
- }
646
- }
647
- // Determine block end
648
- const line = lines[startIndex].trim();
649
- // Check if this is a single-line declaration (no body)
650
- if (line.endsWith(";") && !line.includes("{")) {
651
- const block = lines.slice(actualStart, startIndex + 1);
652
- while (block.length > 0 && block[block.length - 1].trim() === "") {
653
- block.pop();
654
- }
655
- return block.map((l) => l.replace(/\r$/, "")).join("\n");
656
- }
657
- // Find the matching closing brace using a combined approach
658
- // We skip all braces until we find the real '{' that opens the block,
659
- // which is the first '{' encountered when parens are balanced.
660
- let parenDepth = 0;
661
- let blockDepth = 0;
662
- let startedCounting = false;
663
- let endIdx = startIndex;
664
- let inString = false;
665
- let stringDelim = "";
666
- let inTripleQuote = false;
667
- let inComment = false;
668
- let inMultiLineComment = false;
669
- for (let k = startIndex; k < lines.length; k++) {
670
- const lineStr = lines[k];
671
- if (!startedCounting && lineStr.includes("=>")) {
672
- let arrowEndIdx = k;
673
- while (arrowEndIdx < lines.length && !lines[arrowEndIdx].trim().endsWith(";")) {
674
- arrowEndIdx++;
675
- }
676
- const block = lines.slice(actualStart, arrowEndIdx + 1);
677
- return block.map((l) => l.replace(/\r$/, "")).join("\n");
678
- }
679
- for (let j = 0; j < lineStr.length; j++) {
680
- const ch = lineStr[j];
681
- const prev = j > 0 ? lineStr[j - 1] : "";
682
- const next = j < lineStr.length - 1 ? lineStr[j + 1] : "";
683
- if (prev === "\\" && (inString || inTripleQuote))
684
- continue;
685
- if (!inString && !inTripleQuote) {
686
- if (!inMultiLineComment && ch === "/" && next === "/") {
687
- inComment = true;
688
- break;
689
- }
690
- if (!inMultiLineComment && ch === "/" && next === "*") {
691
- inMultiLineComment = true;
692
- j++;
693
- continue;
694
- }
695
- if (inMultiLineComment && ch === "*" && next === "/") {
696
- inMultiLineComment = false;
697
- j++;
698
- continue;
699
- }
700
- }
701
- if (inComment || inMultiLineComment)
702
- continue;
703
- if (!inString && !inMultiLineComment) {
704
- const isTriple = lineStr.slice(j, j + 3) === "'''" || lineStr.slice(j, j + 3) === '"""';
705
- if (isTriple) {
706
- if (!inTripleQuote) {
707
- inTripleQuote = true;
708
- stringDelim = lineStr.slice(j, j + 3);
709
- j += 2;
710
- continue;
711
- }
712
- else if (lineStr.slice(j, j + 3) === stringDelim) {
713
- inTripleQuote = false;
714
- stringDelim = "";
715
- j += 2;
716
- continue;
717
- }
718
- }
719
- }
720
- if (inTripleQuote)
721
- continue;
722
- if (!inMultiLineComment && (ch === "'" || ch === '"')) {
723
- if (!inString) {
724
- inString = true;
725
- stringDelim = ch;
726
- }
727
- else if (ch === stringDelim) {
728
- inString = false;
729
- stringDelim = "";
730
- }
731
- continue;
732
- }
733
- if (inString)
734
- continue;
735
- if (!startedCounting) {
736
- if (ch === "(")
737
- parenDepth++;
738
- else if (ch === ")")
739
- parenDepth--;
740
- else if (ch === "{" && parenDepth === 0) {
741
- startedCounting = true;
742
- blockDepth = 1;
743
- }
744
- }
745
- else {
746
- if (ch === "{") {
747
- blockDepth++;
748
- }
749
- else if (ch === "}") {
750
- blockDepth--;
751
- if (blockDepth === 0) {
752
- endIdx = k;
753
- break;
754
- }
755
- }
756
- }
757
- }
758
- inComment = false;
759
- if (startedCounting && blockDepth === 0)
760
- break;
761
- }
762
- // If we never started counting, it's probably an abstract method or just a field
763
- if (!startedCounting) {
764
- return lines.slice(actualStart, startIndex + 1).map((l) => l.replace(/\r$/, "")).join("\n");
765
- }
766
- const block = lines.slice(actualStart, endIdx + 1);
767
- while (block.length > 0 && block[block.length - 1].trim() === "") {
768
- block.pop();
769
- }
770
- return block.map((l) => l.replace(/\r$/, "")).join("\n");
771
- }
772
- function getIndent(line) {
773
- const match = line.match(/^(\s*)/);
774
- return match ? match[1] : "";
775
- }
776
- function escapeRegex(str) {
777
- return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
778
- }
779
- function findBlockBraceIndex(signature) {
780
- let parenDepth = 0;
781
- for (let i = 0; i < signature.length; i++) {
782
- const ch = signature[i];
783
- if (ch === "(")
784
- parenDepth++;
785
- else if (ch === ")")
786
- parenDepth--;
787
- else if (ch === "{" && parenDepth === 0) {
788
- return i;
789
- }
790
- }
791
- return -1;
792
- }
793
- /**
794
- * Check if a signature contains `{` outside of string literals.
795
- * This is critical for Dart where string interpolation `'${expr}'`
796
- * contains braces that are NOT block openers.
797
- */
798
- function containsBlockBraceOutsideStrings(signature) {
799
- let inSingleQuote = false;
800
- let inDoubleQuote = false;
801
- let parenDepth = 0;
802
- for (let i = 0; i < signature.length; i++) {
803
- const ch = signature[i];
804
- // Handle escape sequences
805
- if ((inSingleQuote || inDoubleQuote) && ch === "\\" && i + 1 < signature.length) {
806
- i++; // skip escaped character
807
- continue;
808
- }
809
- // Toggle string state
810
- if (ch === "'" && !inDoubleQuote) {
811
- inSingleQuote = !inSingleQuote;
812
- continue;
813
- }
814
- if (ch === '"' && !inSingleQuote) {
815
- inDoubleQuote = !inDoubleQuote;
816
- continue;
817
- }
818
- // Skip characters inside strings
819
- if (inSingleQuote || inDoubleQuote)
820
- continue;
821
- if (ch === "(")
822
- parenDepth++;
823
- else if (ch === ")")
824
- parenDepth--;
825
- else if (ch === "{" && parenDepth === 0) {
826
- return true;
827
- }
828
- }
829
- return false;
830
- }
831
- /**
832
- * Check if a signature contains `=>` outside of string literals.
833
- */
834
- function containsArrowOutsideStrings(signature) {
835
- let inSingleQuote = false;
836
- let inDoubleQuote = false;
837
- for (let i = 0; i < signature.length; i++) {
838
- const ch = signature[i];
839
- if ((inSingleQuote || inDoubleQuote) && ch === "\\" && i + 1 < signature.length) {
840
- i++;
841
- continue;
842
- }
843
- if (ch === "'" && !inDoubleQuote) {
844
- inSingleQuote = !inSingleQuote;
845
- continue;
846
- }
847
- if (ch === '"' && !inSingleQuote) {
848
- inDoubleQuote = !inDoubleQuote;
849
- continue;
850
- }
851
- if (inSingleQuote || inDoubleQuote)
852
- continue;
853
- if (ch === "=" && i + 1 < signature.length && signature[i + 1] === ">") {
854
- return true;
855
- }
856
- }
857
- return false;
858
- }
859
- //# sourceMappingURL=dartCompressor.js.map