mustflow 2.75.0 → 2.75.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -11,6 +11,7 @@ const DEFAULT_MAX_FILE_BYTES = 1024 * 1024;
|
|
|
11
11
|
const DEFAULT_MAX_FILES = 200;
|
|
12
12
|
const DEFAULT_CONTEXT_LINES = 0;
|
|
13
13
|
const DEFAULT_MAX_SNIPPET_LINES = 250;
|
|
14
|
+
const RETURN_PREVIEW_MAX_CHARS = 120;
|
|
14
15
|
const CODE_FILE_EXTENSIONS = ['.ts', '.tsx', '.mts', '.cts', '.js', '.jsx', '.mjs', '.cjs'];
|
|
15
16
|
const IGNORED_DIRECTORIES = [
|
|
16
17
|
'.git',
|
|
@@ -261,6 +262,169 @@ function buildSignature(lines, startLine, endLine) {
|
|
|
261
262
|
const signature = parts.join(' ').replace(/\s+/gu, ' ');
|
|
262
263
|
return signature.length > 240 ? `${signature.slice(0, 237)}...` : signature;
|
|
263
264
|
}
|
|
265
|
+
function normalizeReturnType(value) {
|
|
266
|
+
return value.replace(/\s+/gu, ' ').replace(/[;{]\s*$/u, '').trim();
|
|
267
|
+
}
|
|
268
|
+
function extractExplicitReturnType(signature, match) {
|
|
269
|
+
if (match.kind !== 'function') {
|
|
270
|
+
return null;
|
|
271
|
+
}
|
|
272
|
+
const functionReturnMatch = /\bfunction(?:\s+[$A-Z_a-z][$\w]*)?\s*\([^)]*\)\s*:\s*(?<returnType>[^={;]+?)(?=\s*(?:\{|$))/u.exec(signature);
|
|
273
|
+
if (functionReturnMatch?.groups?.returnType) {
|
|
274
|
+
return normalizeReturnType(functionReturnMatch.groups.returnType);
|
|
275
|
+
}
|
|
276
|
+
const arrowReturnMatch = /\)\s*:\s*(?<returnType>[^=]+?)\s*=>/u.exec(signature);
|
|
277
|
+
if (arrowReturnMatch?.groups?.returnType) {
|
|
278
|
+
return normalizeReturnType(arrowReturnMatch.groups.returnType);
|
|
279
|
+
}
|
|
280
|
+
const arrowTypeAnnotationMatch = /:\s*(?:async\s*)?\([^)]*\)\s*=>\s*(?<returnType>[^=;]+?)\s*=/u.exec(signature);
|
|
281
|
+
if (arrowTypeAnnotationMatch?.groups?.returnType) {
|
|
282
|
+
return normalizeReturnType(arrowTypeAnnotationMatch.groups.returnType);
|
|
283
|
+
}
|
|
284
|
+
return null;
|
|
285
|
+
}
|
|
286
|
+
function truncateReturnPreview(value) {
|
|
287
|
+
const preview = value.replace(/\s+/gu, ' ').trim();
|
|
288
|
+
return preview.length > RETURN_PREVIEW_MAX_CHARS
|
|
289
|
+
? `${preview.slice(0, RETURN_PREVIEW_MAX_CHARS - 3)}...`
|
|
290
|
+
: preview;
|
|
291
|
+
}
|
|
292
|
+
function extractArrowExpressionReturnPreview(signature) {
|
|
293
|
+
const arrowIndex = signature.lastIndexOf('=>');
|
|
294
|
+
if (arrowIndex < 0) {
|
|
295
|
+
return null;
|
|
296
|
+
}
|
|
297
|
+
const expression = signature.slice(arrowIndex + 2).trim().replace(/;\s*$/u, '');
|
|
298
|
+
if (expression.length === 0 || expression.startsWith('{')) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
return truncateReturnPreview(expression);
|
|
302
|
+
}
|
|
303
|
+
function isIdentifierCharacter(value) {
|
|
304
|
+
return typeof value === 'string' && /[$\w]/u.test(value);
|
|
305
|
+
}
|
|
306
|
+
function findReturnKeywordIndex(line) {
|
|
307
|
+
let quote = null;
|
|
308
|
+
let escaped = false;
|
|
309
|
+
for (let index = 0; index < line.length; index += 1) {
|
|
310
|
+
const character = line[index];
|
|
311
|
+
const nextCharacter = line[index + 1];
|
|
312
|
+
if (quote !== null) {
|
|
313
|
+
if (escaped) {
|
|
314
|
+
escaped = false;
|
|
315
|
+
continue;
|
|
316
|
+
}
|
|
317
|
+
if (character === '\\') {
|
|
318
|
+
escaped = true;
|
|
319
|
+
continue;
|
|
320
|
+
}
|
|
321
|
+
if (character === quote) {
|
|
322
|
+
quote = null;
|
|
323
|
+
}
|
|
324
|
+
continue;
|
|
325
|
+
}
|
|
326
|
+
if (character === '/' && nextCharacter === '/') {
|
|
327
|
+
return -1;
|
|
328
|
+
}
|
|
329
|
+
if (character === '"' || character === "'" || character === '`') {
|
|
330
|
+
quote = character;
|
|
331
|
+
continue;
|
|
332
|
+
}
|
|
333
|
+
if (line.startsWith('return', index) &&
|
|
334
|
+
!isIdentifierCharacter(line[index - 1]) &&
|
|
335
|
+
!isIdentifierCharacter(line[index + 'return'.length])) {
|
|
336
|
+
return index;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
return -1;
|
|
340
|
+
}
|
|
341
|
+
function extractReturnExpressionPreview(line) {
|
|
342
|
+
const returnIndex = findReturnKeywordIndex(line);
|
|
343
|
+
if (returnIndex < 0) {
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
const expression = line
|
|
347
|
+
.slice(returnIndex + 'return'.length)
|
|
348
|
+
.replace(/\/\/.*$/u, '')
|
|
349
|
+
.trim()
|
|
350
|
+
.replace(/;\s*$/u, '')
|
|
351
|
+
.trim();
|
|
352
|
+
return expression.length === 0 ? null : truncateReturnPreview(expression);
|
|
353
|
+
}
|
|
354
|
+
function hasReturnStatement(line) {
|
|
355
|
+
return findReturnKeywordIndex(line) >= 0;
|
|
356
|
+
}
|
|
357
|
+
function simpleBodyThrowsOnly(lines, startLine, endLine, returnType) {
|
|
358
|
+
let sawThrow = false;
|
|
359
|
+
let sawOtherExecutableLine = false;
|
|
360
|
+
for (let index = startLine; index < endLine - 1; index += 1) {
|
|
361
|
+
const bodyLine = stripLineForBraceScan(lines[index] ?? '')
|
|
362
|
+
.replace(/[{};]/gu, '')
|
|
363
|
+
.trim();
|
|
364
|
+
if (bodyLine.length === 0) {
|
|
365
|
+
continue;
|
|
366
|
+
}
|
|
367
|
+
if (/^throw\b/u.test(bodyLine)) {
|
|
368
|
+
sawThrow = true;
|
|
369
|
+
continue;
|
|
370
|
+
}
|
|
371
|
+
sawOtherExecutableLine = true;
|
|
372
|
+
}
|
|
373
|
+
return sawThrow && (!sawOtherExecutableLine || returnType === 'never');
|
|
374
|
+
}
|
|
375
|
+
function extractReturnMetadata(lines, startLine, endLine, signature, match) {
|
|
376
|
+
const returnType = extractExplicitReturnType(signature, match);
|
|
377
|
+
if (match.kind !== 'function') {
|
|
378
|
+
return {
|
|
379
|
+
return_type: null,
|
|
380
|
+
return_behavior: 'unknown',
|
|
381
|
+
return_count: 0,
|
|
382
|
+
return_lines: [],
|
|
383
|
+
return_preview: null,
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
const returnLines = [];
|
|
387
|
+
const valueReturnPreviews = [];
|
|
388
|
+
let voidReturnCount = 0;
|
|
389
|
+
for (let index = startLine - 1; index < endLine; index += 1) {
|
|
390
|
+
const line = lines[index] ?? '';
|
|
391
|
+
if (!hasReturnStatement(line)) {
|
|
392
|
+
continue;
|
|
393
|
+
}
|
|
394
|
+
returnLines.push(index + 1);
|
|
395
|
+
const preview = extractReturnExpressionPreview(line);
|
|
396
|
+
if (preview === null) {
|
|
397
|
+
voidReturnCount += 1;
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
valueReturnPreviews.push(preview);
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
const arrowExpressionPreview = returnLines.length === 0 ? extractArrowExpressionReturnPreview(signature) : null;
|
|
404
|
+
let returnBehavior;
|
|
405
|
+
if (valueReturnPreviews.length > 0 && voidReturnCount > 0) {
|
|
406
|
+
returnBehavior = 'mixed';
|
|
407
|
+
}
|
|
408
|
+
else if (valueReturnPreviews.length > 0 || arrowExpressionPreview !== null) {
|
|
409
|
+
returnBehavior = 'value';
|
|
410
|
+
}
|
|
411
|
+
else if (voidReturnCount > 0) {
|
|
412
|
+
returnBehavior = 'void';
|
|
413
|
+
}
|
|
414
|
+
else if (simpleBodyThrowsOnly(lines, startLine, endLine, returnType)) {
|
|
415
|
+
returnBehavior = 'throws_only';
|
|
416
|
+
}
|
|
417
|
+
else {
|
|
418
|
+
returnBehavior = 'implicit_undefined';
|
|
419
|
+
}
|
|
420
|
+
return {
|
|
421
|
+
return_type: returnType,
|
|
422
|
+
return_behavior: returnBehavior,
|
|
423
|
+
return_count: returnLines.length,
|
|
424
|
+
return_lines: returnLines,
|
|
425
|
+
return_preview: valueReturnPreviews[0] ?? arrowExpressionPreview,
|
|
426
|
+
};
|
|
427
|
+
}
|
|
264
428
|
function extractSymbols(relativePath, language, contentSha256, text) {
|
|
265
429
|
const lines = text.split(/\r\n|\r|\n/u);
|
|
266
430
|
const symbols = [];
|
|
@@ -271,6 +435,8 @@ function extractSymbols(relativePath, language, contentSha256, text) {
|
|
|
271
435
|
}
|
|
272
436
|
const startLine = index + 1;
|
|
273
437
|
const endLine = findDeclarationEndLine(lines, index);
|
|
438
|
+
const signature = buildSignature(lines, startLine, endLine);
|
|
439
|
+
const returnMetadata = extractReturnMetadata(lines, startLine, endLine, signature, match);
|
|
274
440
|
symbols.push({
|
|
275
441
|
id: `${relativePath}:${startLine}:${match.kind}:${match.name}`,
|
|
276
442
|
path: relativePath,
|
|
@@ -279,9 +445,10 @@ function extractSymbols(relativePath, language, contentSha256, text) {
|
|
|
279
445
|
name: match.name,
|
|
280
446
|
start_line: startLine,
|
|
281
447
|
end_line: endLine,
|
|
282
|
-
signature
|
|
448
|
+
signature,
|
|
283
449
|
exported: match.exported,
|
|
284
450
|
async: match.async,
|
|
451
|
+
...returnMetadata,
|
|
285
452
|
parent: null,
|
|
286
453
|
content_sha256: contentSha256,
|
|
287
454
|
});
|
package/package.json
CHANGED
package/schemas/README.md
CHANGED
|
@@ -67,11 +67,11 @@ Current schemas:
|
|
|
67
67
|
- `code-outline-report.schema.json`: output of
|
|
68
68
|
`mf script-pack run code/outline scan <path...> --json`, containing a bounded TypeScript and
|
|
69
69
|
JavaScript source outline with file hashes, symbol names, declaration kinds, line ranges,
|
|
70
|
-
signatures, export flags, and stable input-limit finding codes
|
|
70
|
+
signatures, export flags, static return metadata, and stable input-limit finding codes
|
|
71
71
|
- `code-symbol-read-report.schema.json`: output of
|
|
72
72
|
`mf script-pack run code/symbol-read read <path> --start-line <line> --json`, containing a
|
|
73
73
|
focused source snippet selected by outline symbol line or explicit line range with file hash,
|
|
74
|
-
resolved line metadata, optional symbol metadata, and stable range/read finding codes
|
|
74
|
+
resolved line metadata, optional symbol and static return metadata, and stable range/read finding codes
|
|
75
75
|
- `text-budget-report.schema.json`: output of
|
|
76
76
|
`mf script-pack run core/text-budget check <path...> --json`, containing
|
|
77
77
|
exact text-budget metrics, input content hashes, policy metadata, findings, and JSON Pointer field
|
|
@@ -104,6 +104,11 @@
|
|
|
104
104
|
"signature",
|
|
105
105
|
"exported",
|
|
106
106
|
"async",
|
|
107
|
+
"return_type",
|
|
108
|
+
"return_behavior",
|
|
109
|
+
"return_count",
|
|
110
|
+
"return_lines",
|
|
111
|
+
"return_preview",
|
|
107
112
|
"parent",
|
|
108
113
|
"content_sha256"
|
|
109
114
|
],
|
|
@@ -118,6 +123,16 @@
|
|
|
118
123
|
"signature": { "type": "string" },
|
|
119
124
|
"exported": { "type": "boolean" },
|
|
120
125
|
"async": { "type": "boolean" },
|
|
126
|
+
"return_type": { "type": ["string", "null"] },
|
|
127
|
+
"return_behavior": {
|
|
128
|
+
"enum": ["value", "void", "implicit_undefined", "mixed", "throws_only", "unknown"]
|
|
129
|
+
},
|
|
130
|
+
"return_count": { "type": "integer", "minimum": 0 },
|
|
131
|
+
"return_lines": {
|
|
132
|
+
"type": "array",
|
|
133
|
+
"items": { "type": "integer", "minimum": 1 }
|
|
134
|
+
},
|
|
135
|
+
"return_preview": { "type": ["string", "null"] },
|
|
121
136
|
"parent": { "type": ["string", "null"] },
|
|
122
137
|
"content_sha256": { "$ref": "#/$defs/sha256" }
|
|
123
138
|
}
|
|
@@ -91,6 +91,11 @@
|
|
|
91
91
|
"signature",
|
|
92
92
|
"exported",
|
|
93
93
|
"async",
|
|
94
|
+
"return_type",
|
|
95
|
+
"return_behavior",
|
|
96
|
+
"return_count",
|
|
97
|
+
"return_lines",
|
|
98
|
+
"return_preview",
|
|
94
99
|
"parent",
|
|
95
100
|
"content_sha256"
|
|
96
101
|
],
|
|
@@ -105,6 +110,16 @@
|
|
|
105
110
|
"signature": { "type": "string" },
|
|
106
111
|
"exported": { "type": "boolean" },
|
|
107
112
|
"async": { "type": "boolean" },
|
|
113
|
+
"return_type": { "type": ["string", "null"] },
|
|
114
|
+
"return_behavior": {
|
|
115
|
+
"enum": ["value", "void", "implicit_undefined", "mixed", "throws_only", "unknown"]
|
|
116
|
+
},
|
|
117
|
+
"return_count": { "type": "integer", "minimum": 0 },
|
|
118
|
+
"return_lines": {
|
|
119
|
+
"type": "array",
|
|
120
|
+
"items": { "type": "integer", "minimum": 1 }
|
|
121
|
+
},
|
|
122
|
+
"return_preview": { "type": ["string", "null"] },
|
|
108
123
|
"parent": { "type": ["string", "null"] },
|
|
109
124
|
"content_sha256": { "$ref": "#/$defs/sha256" }
|
|
110
125
|
}
|