sigmap 8.31.0 → 8.32.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +28 -0
- package/README.md +12 -12
- package/gen-context.js +247 -138
- package/llms-full.txt +8 -8
- package/llms.txt +6 -6
- package/package.json +1 -1
- package/packages/cli/package.json +1 -1
- package/packages/core/package.json +1 -1
- package/src/config/loader.js +53 -3
- package/src/eval/analyzer.js +0 -1
- package/src/extractors/cpp.js +10 -2
- package/src/extractors/csharp.js +11 -3
- package/src/extractors/css.js +7 -1
- package/src/extractors/dart.js +11 -3
- package/src/extractors/dispatch.js +0 -1
- package/src/extractors/dockerfile.js +7 -1
- package/src/extractors/gdscript.js +13 -3
- package/src/extractors/go.js +6 -1
- package/src/extractors/html.js +7 -1
- package/src/extractors/kotlin.js +11 -3
- package/src/extractors/markdown.js +6 -1
- package/src/extractors/php.js +11 -3
- package/src/extractors/properties.js +6 -1
- package/src/extractors/python.js +6 -1
- package/src/extractors/r.js +11 -9
- package/src/extractors/ruby.js +7 -1
- package/src/extractors/rust.js +6 -1
- package/src/extractors/scala.js +11 -3
- package/src/extractors/shell.js +7 -1
- package/src/extractors/svelte.js +7 -1
- package/src/extractors/swift.js +11 -3
- package/src/extractors/toml.js +6 -1
- package/src/extractors/typescript_react.js +6 -1
- package/src/extractors/yaml.js +7 -1
- package/src/mcp/server.js +1 -1
- package/src/extractors/vue.js +0 -80
package/llms-full.txt
CHANGED
|
@@ -11,21 +11,21 @@ ranking keeps the relevant context in scope (cutting tokens ~97% as a side
|
|
|
11
11
|
effect), with no LLM calls, embeddings, or vector database. Works with Claude,
|
|
12
12
|
Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
|
|
13
13
|
|
|
14
|
-
# Version: 8.
|
|
14
|
+
# Version: 8.32.1 | Benchmark: sigmap-v8.32-main (2026-09-12)
|
|
15
15
|
# Source: auto-generated from package.json, version.json, benchmarks/latest.json, src/mcp/tools.js, src/config/defaults.js
|
|
16
16
|
# Regenerate: npm run generate:llms | Validate: npm run validate:llms
|
|
17
17
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
|
-
## Core metrics (benchmark: sigmap-v8.
|
|
20
|
+
## Core metrics (benchmark: sigmap-v8.32-main, 2026-09-12)
|
|
21
21
|
|
|
22
22
|
| Metric | Without SigMap | With SigMap |
|
|
23
23
|
|--------|----------------|-------------|
|
|
24
|
-
| Retrieval hit@5 | 44.0% (single-shot grep) |
|
|
24
|
+
| Retrieval hit@5 | 44.0% (single-shot grep) | 78.9% (1.73× lift) |
|
|
25
25
|
| Token reduction | — | 96.8% average |
|
|
26
|
-
| Task-success proxy (modeled) | — |
|
|
27
|
-
| Prompts per task | 2.84 | 1.
|
|
28
|
-
| Supported languages | — |
|
|
26
|
+
| Task-success proxy (modeled) | — | 62.9% |
|
|
27
|
+
| Prompts per task | 2.84 | 1.58 (44.4% fewer) |
|
|
28
|
+
| Supported languages | — | 32 |
|
|
29
29
|
| MCP tools | — | 21 |
|
|
30
30
|
| npm runtime dependencies | — | 0 |
|
|
31
31
|
|
|
@@ -370,9 +370,9 @@ impact = {"depth":3,"includeSigs":true}
|
|
|
370
370
|
|
|
371
371
|
---
|
|
372
372
|
|
|
373
|
-
## Supported languages (
|
|
373
|
+
## Supported languages (32 extractors)
|
|
374
374
|
|
|
375
|
-
cpp, csharp, css, dart, dockerfile, gdscript, go, graphql, html, java, javascript, kotlin, markdown, php, properties, protobuf, python, r, ruby, rust, scala, shell, sql, svelte, swift, terraform, toml, typescript, typescript_react,
|
|
375
|
+
cpp, csharp, css, dart, dockerfile, gdscript, go, graphql, html, java, javascript, kotlin, markdown, php, properties, protobuf, python, r, ruby, rust, scala, shell, sql, svelte, swift, terraform, toml, typescript, typescript_react, vue_sfc, xml, yaml
|
|
376
376
|
|
|
377
377
|
---
|
|
378
378
|
|
package/llms.txt
CHANGED
|
@@ -11,7 +11,7 @@ ranking keeps the relevant context in scope (cutting tokens ~97% as a side
|
|
|
11
11
|
effect), with no LLM calls, embeddings, or vector database. Works with Claude,
|
|
12
12
|
Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
|
|
13
13
|
|
|
14
|
-
# Version: 8.
|
|
14
|
+
# Version: 8.32.1 | Benchmark: sigmap-v8.32-main (2026-09-12)
|
|
15
15
|
# Source: auto-generated from package.json, version.json, benchmarks/latest.json, src/mcp/tools.js, src/config/defaults.js
|
|
16
16
|
# Regenerate: npm run generate:llms | Validate: npm run validate:llms
|
|
17
17
|
|
|
@@ -23,13 +23,13 @@ Cursor, GitHub Copilot, Aider, Windsurf, local LLMs, and MCP.
|
|
|
23
23
|
- No blast-radius awareness before editing a hub file — `--impact` shows every file a change touches.
|
|
24
24
|
- Pasted stack traces, CI logs, and JSON bloat the prompt — `squeeze` minimizes them and enriches the top frame from the symbol index.
|
|
25
25
|
|
|
26
|
-
## Core metrics (benchmark: sigmap-v8.
|
|
26
|
+
## Core metrics (benchmark: sigmap-v8.32-main, 2026-09-12)
|
|
27
27
|
|
|
28
|
-
- hit@5 retrieval:
|
|
28
|
+
- hit@5 retrieval: 78.9% vs 44.0% single-shot grep baseline (1.73× lift)
|
|
29
29
|
- Token reduction: 96.8% average across benchmark repos
|
|
30
|
-
- Task-success proxy:
|
|
31
|
-
- Prompts per task: 1.
|
|
32
|
-
- Languages:
|
|
30
|
+
- Task-success proxy: 62.9% (modeled from retrieval tiers, not measured LLM sessions)
|
|
31
|
+
- Prompts per task: 1.58 vs 2.84 baseline (44.4% fewer, modeled)
|
|
32
|
+
- Languages: 32 supported · MCP tools: 21
|
|
33
33
|
- Dependencies: zero npm runtime dependencies · fully offline
|
|
34
34
|
|
|
35
35
|
## Quick start
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "sigmap",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.32.1",
|
|
4
4
|
"description": "The deterministic, verifiable grounding layer for AI code work — a zero-dependency signature-and-evidence map that grounds Claude, Cursor, Copilot, Aider, Windsurf, local LLMs & MCP agents against your real code (repo + installed libraries) so they stop hallucinating files, imports & APIs. Runs offline via npx; byte-stable output; ~97% token reduction as proof.",
|
|
5
5
|
"main": "packages/core/index.js",
|
|
6
6
|
"exports": {
|
package/src/config/loader.js
CHANGED
|
@@ -227,6 +227,55 @@ function _legacyDetectAutoSrcDirs(cwd, excludeList) {
|
|
|
227
227
|
});
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Directory depth needed to reach source under a JVM package layout.
|
|
232
|
+
*
|
|
233
|
+
* `maxDepth: 6` is right for the JS/Python-shaped trees it was tuned on, but a
|
|
234
|
+
* JVM project puts one directory per package segment — real code in
|
|
235
|
+
* `src/main/java/com/company/project/module/Class.java` sits 8-10 levels down.
|
|
236
|
+
* At depth 6 only the top-level package was indexed: on spring-petclinic, 6 of
|
|
237
|
+
* 47 Java files (#590).
|
|
238
|
+
*
|
|
239
|
+
* #561 already raised the dependency-graph walk to 12 for exactly this reason,
|
|
240
|
+
* so extraction was the shallower half of an inconsistent pair.
|
|
241
|
+
*
|
|
242
|
+
* Deepening globally is not free — it adds candidates to every repo and cost
|
|
243
|
+
* 2.2pp on the (filename-leaky) 105-task matrix corpus while the unbiased
|
|
244
|
+
* `mined` corpus stayed flat. So the depth is raised only where the layout
|
|
245
|
+
* demands it, leaving non-JVM repos byte-identical.
|
|
246
|
+
*
|
|
247
|
+
* @param {string} cwd
|
|
248
|
+
* @returns {boolean} true when the repo looks like a Maven/Gradle/sbt project
|
|
249
|
+
*/
|
|
250
|
+
function _isJvmLayout(cwd) {
|
|
251
|
+
const MARKERS = ['pom.xml', 'build.gradle', 'build.gradle.kts', 'build.sbt', 'settings.gradle', 'settings.gradle.kts'];
|
|
252
|
+
for (const m of MARKERS) {
|
|
253
|
+
try { if (fs.existsSync(path.join(cwd, m))) return true; } catch { /* unreadable cwd */ }
|
|
254
|
+
}
|
|
255
|
+
for (const d of ['src/main/java', 'src/main/kotlin', 'src/main/scala']) {
|
|
256
|
+
try { if (fs.existsSync(path.join(cwd, d))) return true; } catch { /* ignore */ }
|
|
257
|
+
}
|
|
258
|
+
return false;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/** Walk depth for a JVM package layout — matches the graph walk from #561. */
|
|
262
|
+
const JVM_MAX_DEPTH = 12;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Raise `maxDepth` to the JVM depth when the layout needs it (#590).
|
|
266
|
+
* An explicit user value always wins, including a deliberately shallow one.
|
|
267
|
+
* @param {object} cfg resolved config (mutated and returned)
|
|
268
|
+
* @param {string} cwd
|
|
269
|
+
* @param {boolean} userSetDepth
|
|
270
|
+
* @returns {object} cfg
|
|
271
|
+
*/
|
|
272
|
+
function _applyJvmDepth(cfg, cwd, userSetDepth) {
|
|
273
|
+
if (!userSetDepth && cfg.maxDepth < JVM_MAX_DEPTH && _isJvmLayout(cwd)) {
|
|
274
|
+
cfg.maxDepth = JVM_MAX_DEPTH;
|
|
275
|
+
}
|
|
276
|
+
return cfg;
|
|
277
|
+
}
|
|
278
|
+
|
|
230
279
|
/**
|
|
231
280
|
* Load and merge configuration for a given working directory.
|
|
232
281
|
*
|
|
@@ -239,7 +288,7 @@ function loadConfig(cwd) {
|
|
|
239
288
|
const cfg = deepClone(DEFAULTS);
|
|
240
289
|
const detected = detectAutoSrcDirs(cwd, cfg.exclude);
|
|
241
290
|
if (detected.length > 0) cfg.srcDirs = detected;
|
|
242
|
-
return cfg;
|
|
291
|
+
return _applyJvmDepth(cfg, cwd, false);
|
|
243
292
|
}
|
|
244
293
|
|
|
245
294
|
let userConfig;
|
|
@@ -251,7 +300,7 @@ function loadConfig(cwd) {
|
|
|
251
300
|
const cfg = deepClone(DEFAULTS);
|
|
252
301
|
const detected = detectAutoSrcDirs(cwd, cfg.exclude);
|
|
253
302
|
if (detected.length > 0) cfg.srcDirs = detected;
|
|
254
|
-
return cfg;
|
|
303
|
+
return _applyJvmDepth(cfg, cwd, false);
|
|
255
304
|
}
|
|
256
305
|
|
|
257
306
|
// Warn on unknown keys (helps catch typos)
|
|
@@ -303,7 +352,8 @@ function loadConfig(cwd) {
|
|
|
303
352
|
} else if (Array.isArray(merged.adapters) && !userConfig.outputs) {
|
|
304
353
|
merged.outputs = merged.adapters.filter((a) => ['copilot','claude','cursor','windsurf'].includes(a));
|
|
305
354
|
}
|
|
306
|
-
|
|
355
|
+
|
|
356
|
+
return _applyJvmDepth(merged, cwd, userConfig.maxDepth !== undefined);
|
|
307
357
|
}
|
|
308
358
|
|
|
309
359
|
function deepClone(obj) {
|
package/src/eval/analyzer.js
CHANGED
package/src/extractors/cpp.js
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
|
|
4
|
+
|
|
5
|
+
// Ceilings sit above the default `maxSigsPerFile` so the configured budget
|
|
6
|
+
// governs output rather than a literal buried here, and omissions are disclosed
|
|
7
|
+
// — an undisclosed cap looks like a class that simply has eight methods (#576).
|
|
8
|
+
const MEMBER_LIMIT = 8;
|
|
9
|
+
const PER_FILE_LIMIT = 25;
|
|
10
|
+
|
|
3
11
|
/**
|
|
4
12
|
* Extract signatures from C/C++ source code.
|
|
5
13
|
* @param {string} src - Raw file content
|
|
@@ -30,7 +38,7 @@ function extract(src) {
|
|
|
30
38
|
sigs.push(`${m[2]}(${normalizeParams(m[3])})${retStr}`);
|
|
31
39
|
}
|
|
32
40
|
|
|
33
|
-
return sigs
|
|
41
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
34
42
|
}
|
|
35
43
|
|
|
36
44
|
function extractBlock(src, startIndex) {
|
|
@@ -53,7 +61,7 @@ function extractMembers(block) {
|
|
|
53
61
|
const retStr = ret ? ` → ${ret}` : '';
|
|
54
62
|
members.push(`${m[2]}(${normalizeParams(m[3])})${retStr}`);
|
|
55
63
|
}
|
|
56
|
-
return members
|
|
64
|
+
return capWithNotice(members, MEMBER_LIMIT, 'members');
|
|
57
65
|
}
|
|
58
66
|
|
|
59
67
|
function normalizeParams(params) {
|
package/src/extractors/csharp.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { lineAt, withAnchor } = require('./line-anchor');
|
|
4
|
+
const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
|
|
5
|
+
|
|
6
|
+
// Ceilings sit above the default `maxSigsPerFile` so the configured budget
|
|
7
|
+
// governs output rather than a literal buried here, and omissions are disclosed
|
|
8
|
+
// — an undisclosed cap looks like a class that simply has eight methods (#576).
|
|
9
|
+
const MEMBER_LIMIT = 8;
|
|
10
|
+
const PER_FILE_LIMIT = 25;
|
|
4
11
|
|
|
5
12
|
/**
|
|
6
13
|
* Extract signatures from C# source code.
|
|
@@ -25,11 +32,12 @@ function extract(src) {
|
|
|
25
32
|
const block = extractBlock(stripped, bodyStart);
|
|
26
33
|
sigs.push(withAnchor(`${m[1]} ${m[2]}`, lineAt(stripped, declIdx), lineAt(stripped, bodyStart + block.length)));
|
|
27
34
|
for (const meth of extractMembers(block)) {
|
|
28
|
-
|
|
35
|
+
// The disclosure marker carries no offsets; anchor it at the class body.
|
|
36
|
+
sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + (meth.declIdx || 0)), lineAt(stripped, bodyStart + (meth.endIdx || 0))));
|
|
29
37
|
}
|
|
30
38
|
}
|
|
31
39
|
|
|
32
|
-
return sigs
|
|
40
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
33
41
|
}
|
|
34
42
|
|
|
35
43
|
function extractBlock(src, startIndex) {
|
|
@@ -55,7 +63,7 @@ function extractMembers(block) {
|
|
|
55
63
|
endIdx: m.index + m[0].length,
|
|
56
64
|
});
|
|
57
65
|
}
|
|
58
|
-
return members
|
|
66
|
+
return capMembersWithNotice(members, MEMBER_LIMIT);
|
|
59
67
|
}
|
|
60
68
|
|
|
61
69
|
function normalizeParams(params) {
|
package/src/extractors/css.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { capWithNotice } = require('../util/truncate');
|
|
4
|
+
|
|
5
|
+
// Ceiling sits above the default `maxSigsPerFile` so the configured budget
|
|
6
|
+
// governs output rather than a literal buried here, and omissions are disclosed (#576).
|
|
7
|
+
const PER_FILE_LIMIT = 25;
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
10
|
* Extract signatures from CSS/SCSS/SASS/Less source code.
|
|
5
11
|
* @param {string} src - Raw file content
|
|
@@ -63,7 +69,7 @@ function extract(src) {
|
|
|
63
69
|
for (const name of selected) sigs.push(`.${name}`);
|
|
64
70
|
}
|
|
65
71
|
|
|
66
|
-
return sigs
|
|
72
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
67
73
|
}
|
|
68
74
|
|
|
69
75
|
module.exports = { extract };
|
package/src/extractors/dart.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { lineAt, withAnchor } = require('./line-anchor');
|
|
4
|
+
const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
|
|
5
|
+
|
|
6
|
+
// Ceilings sit above the default `maxSigsPerFile` so the configured budget
|
|
7
|
+
// governs output rather than a literal buried here, and omissions are disclosed
|
|
8
|
+
// — an undisclosed cap looks like a class that simply has eight methods (#576).
|
|
9
|
+
const MEMBER_LIMIT = 8;
|
|
10
|
+
const PER_FILE_LIMIT = 25;
|
|
4
11
|
|
|
5
12
|
/**
|
|
6
13
|
* Extract signatures from Dart source code.
|
|
@@ -36,7 +43,8 @@ function extract(src) {
|
|
|
36
43
|
const block = extractBlock(stripped, bodyStart);
|
|
37
44
|
sigs.push(withAnchor(`${abs}class ${m[1]}`, lineAt(stripped, m.index), lineAt(stripped, bodyStart + block.length)));
|
|
38
45
|
for (const meth of extractMembers(block)) {
|
|
39
|
-
|
|
46
|
+
// The disclosure marker carries no offsets; anchor it at the class body.
|
|
47
|
+
sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + (meth.declIdx || 0)), lineAt(stripped, bodyStart + (meth.endIdx || 0))));
|
|
40
48
|
}
|
|
41
49
|
}
|
|
42
50
|
|
|
@@ -48,7 +56,7 @@ function extract(src) {
|
|
|
48
56
|
sigs.push(withAnchor(`${m[2]}(${normalizeParams(m[3])})${retStr}`, s, e));
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
return sigs
|
|
59
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
function extractBlock(src, startIndex) {
|
|
@@ -73,7 +81,7 @@ function extractMembers(block) {
|
|
|
73
81
|
endIdx: m.index + m[0].length,
|
|
74
82
|
});
|
|
75
83
|
}
|
|
76
|
-
return members
|
|
84
|
+
return capMembersWithNotice(members, MEMBER_LIMIT);
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
function normalizeParams(params) {
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { capWithNotice } = require('../util/truncate');
|
|
4
|
+
|
|
5
|
+
// Ceiling sits above the default `maxSigsPerFile` so the configured budget
|
|
6
|
+
// governs output rather than a literal buried here, and omissions are disclosed (#576).
|
|
7
|
+
const PER_FILE_LIMIT = 25;
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
10
|
* Extract signatures from Dockerfiles.
|
|
5
11
|
* @param {string} src - Raw file content
|
|
@@ -43,7 +49,7 @@ function extract(src) {
|
|
|
43
49
|
if (m) sigs.push(`ARG ${m[1]}`);
|
|
44
50
|
}
|
|
45
51
|
|
|
46
|
-
return sigs
|
|
52
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
47
53
|
}
|
|
48
54
|
|
|
49
55
|
module.exports = { extract };
|
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { capWithNotice } = require('../util/truncate');
|
|
4
|
+
|
|
5
|
+
// Ceiling sits above the default `maxSigsPerFile` so the configured budget
|
|
6
|
+
// governs output rather than a literal buried here, and omissions are disclosed (#576).
|
|
7
|
+
const PER_FILE_LIMIT = 25;
|
|
8
|
+
|
|
9
|
+
// Ceilings disclose what they drop rather than truncating silently (#576).
|
|
10
|
+
const MEMBER_LIMIT = 6;
|
|
11
|
+
const ENUM_LIMIT = 24;
|
|
12
|
+
|
|
3
13
|
/**
|
|
4
14
|
* Extract signatures from Godot GDScript source code.
|
|
5
15
|
* @param {string} src - Raw file content
|
|
@@ -44,7 +54,7 @@ function extract(src) {
|
|
|
44
54
|
.split(',')
|
|
45
55
|
.map((s) => s.trim().split(/\s*=/)[0].trim())
|
|
46
56
|
.filter(Boolean);
|
|
47
|
-
sigs.push(`${indent}enum ${m[1]} { ${members
|
|
57
|
+
sigs.push(`${indent}enum ${m[1]} { ${capWithNotice(members, ENUM_LIMIT, 'values').join(', ')} }`);
|
|
48
58
|
}
|
|
49
59
|
|
|
50
60
|
let constCount = 0;
|
|
@@ -92,7 +102,7 @@ function extract(src) {
|
|
|
92
102
|
}
|
|
93
103
|
}
|
|
94
104
|
|
|
95
|
-
return sigs
|
|
105
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
96
106
|
}
|
|
97
107
|
|
|
98
108
|
function extractInnerMembers(stripped, startIndex) {
|
|
@@ -110,7 +120,7 @@ function extractInnerMembers(stripped, startIndex) {
|
|
|
110
120
|
members.push(`${staticKw}func ${fm[2]}(${params})${retStr}`);
|
|
111
121
|
}
|
|
112
122
|
}
|
|
113
|
-
return members
|
|
123
|
+
return capWithNotice(members, MEMBER_LIMIT, 'members');
|
|
114
124
|
}
|
|
115
125
|
|
|
116
126
|
function normalizeParams(params) {
|
package/src/extractors/go.js
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { lineAt, withAnchor } = require('./line-anchor');
|
|
4
|
+
const { capWithNotice } = require('../util/truncate');
|
|
5
|
+
|
|
6
|
+
// Ceiling sits above the default `maxSigsPerFile` so the configured budget
|
|
7
|
+
// governs output rather than a literal buried here, and omissions are disclosed (#576).
|
|
8
|
+
const PER_FILE_LIMIT = 25;
|
|
4
9
|
|
|
5
10
|
/**
|
|
6
11
|
* Extract signatures from Go source code.
|
|
@@ -49,7 +54,7 @@ function extract(src) {
|
|
|
49
54
|
sigs.push(hinted(withAnchor(`func ${receiver}${m[2]}(${normalizeParams(m[3])})${retStr}`, lineAt(stripped, m.index), lineAt(stripped, end)), m[2]));
|
|
50
55
|
}
|
|
51
56
|
|
|
52
|
-
return sigs
|
|
57
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
53
58
|
}
|
|
54
59
|
|
|
55
60
|
function extractBlock(src, startIndex) {
|
package/src/extractors/html.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { capWithNotice } = require('../util/truncate');
|
|
4
|
+
|
|
5
|
+
// Ceiling sits above the default `maxSigsPerFile` so the configured budget
|
|
6
|
+
// governs output rather than a literal buried here, and omissions are disclosed (#576).
|
|
7
|
+
const PER_FILE_LIMIT = 25;
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
10
|
* Extract signatures from HTML files.
|
|
5
11
|
* Focuses on id/class attributes, forms, and script tags.
|
|
@@ -33,7 +39,7 @@ function extract(src) {
|
|
|
33
39
|
sigs.push(`data-${m[0].match(/data-(\w[\w-]*)/i)[1]}: ${m[1]}`);
|
|
34
40
|
}
|
|
35
41
|
|
|
36
|
-
return sigs
|
|
42
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
37
43
|
}
|
|
38
44
|
|
|
39
45
|
module.exports = { extract };
|
package/src/extractors/kotlin.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { lineAt, withAnchor } = require('./line-anchor');
|
|
4
|
+
const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
|
|
5
|
+
|
|
6
|
+
// Ceilings sit above the default `maxSigsPerFile` so the configured budget
|
|
7
|
+
// governs output rather than a literal buried here, and omissions are disclosed
|
|
8
|
+
// — an undisclosed cap looks like a class that simply has eight methods (#576).
|
|
9
|
+
const MEMBER_LIMIT = 8;
|
|
10
|
+
const PER_FILE_LIMIT = 25;
|
|
4
11
|
|
|
5
12
|
/**
|
|
6
13
|
* Extract signatures from Kotlin source code.
|
|
@@ -35,7 +42,8 @@ function extract(src) {
|
|
|
35
42
|
const block = extractBlock(stripped, bodyStart);
|
|
36
43
|
sigs.push(withAnchor(`${m[1]} ${m[2]}`, lineAt(stripped, m.index), lineAt(stripped, bodyStart + block.length)));
|
|
37
44
|
for (const meth of extractMembers(block)) {
|
|
38
|
-
|
|
45
|
+
// The disclosure marker carries no offsets; anchor it at the class body.
|
|
46
|
+
sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + (meth.declIdx || 0)), lineAt(stripped, bodyStart + (meth.endIdx || 0))));
|
|
39
47
|
}
|
|
40
48
|
}
|
|
41
49
|
|
|
@@ -48,7 +56,7 @@ function extract(src) {
|
|
|
48
56
|
sigs.push(withAnchor(`${suspend}fun ${m[1]}(${normalizeParams(m[2])})${retStr}`, s, e));
|
|
49
57
|
}
|
|
50
58
|
|
|
51
|
-
return sigs
|
|
59
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
52
60
|
}
|
|
53
61
|
|
|
54
62
|
function extractBlock(src, startIndex) {
|
|
@@ -75,7 +83,7 @@ function extractMembers(block) {
|
|
|
75
83
|
endIdx: m.index + m[0].length,
|
|
76
84
|
});
|
|
77
85
|
}
|
|
78
|
-
return members
|
|
86
|
+
return capMembersWithNotice(members, MEMBER_LIMIT);
|
|
79
87
|
}
|
|
80
88
|
|
|
81
89
|
function normalizeParams(params) {
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { capWithNotice } = require('../util/truncate');
|
|
4
|
+
|
|
5
|
+
// Ceiling discloses what it drops rather than truncating silently (#583).
|
|
6
|
+
const PER_FILE_LIMIT = 40;
|
|
7
|
+
|
|
3
8
|
/**
|
|
4
9
|
* Lightweight markdown technical indexer.
|
|
5
10
|
* Captures headings and fenced code block language hints only.
|
|
@@ -24,7 +29,7 @@ function extract(src) {
|
|
|
24
29
|
sigs.push(`code-fence ${lang}`);
|
|
25
30
|
}
|
|
26
31
|
|
|
27
|
-
return Array.from(new Set(sigs))
|
|
32
|
+
return capWithNotice(Array.from(new Set(sigs)), PER_FILE_LIMIT, 'headings');
|
|
28
33
|
}
|
|
29
34
|
|
|
30
35
|
module.exports = { extract };
|
package/src/extractors/php.js
CHANGED
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const { lineAt, withAnchor } = require('./line-anchor');
|
|
4
|
+
const { capWithNotice, capMembersWithNotice } = require('../util/truncate');
|
|
5
|
+
|
|
6
|
+
// Ceilings sit above the default `maxSigsPerFile` so the configured budget
|
|
7
|
+
// governs output rather than a literal buried here, and omissions are disclosed
|
|
8
|
+
// — an undisclosed cap looks like a class that simply has eight methods (#576).
|
|
9
|
+
const MEMBER_LIMIT = 8;
|
|
10
|
+
const PER_FILE_LIMIT = 25;
|
|
4
11
|
|
|
5
12
|
/**
|
|
6
13
|
* Extract signatures from PHP source code.
|
|
@@ -40,7 +47,8 @@ function extract(src) {
|
|
|
40
47
|
const block = extractBlock(stripped, bodyStart);
|
|
41
48
|
sigs.push(withAnchor(`${kind} ${m[1]}`, lineAt(stripped, m.index), lineAt(stripped, bodyStart + block.length)));
|
|
42
49
|
for (const meth of extractMembers(block)) {
|
|
43
|
-
|
|
50
|
+
// The disclosure marker carries no offsets; anchor it at the class body.
|
|
51
|
+
sigs.push(withAnchor(` ${meth.text}`, lineAt(stripped, bodyStart + (meth.declIdx || 0)), lineAt(stripped, bodyStart + (meth.endIdx || 0))));
|
|
44
52
|
}
|
|
45
53
|
}
|
|
46
54
|
|
|
@@ -52,7 +60,7 @@ function extract(src) {
|
|
|
52
60
|
sigs.push(withAnchor(`function ${m[1]}(${normalizeParams(m[2])})${retStr}`, s, e));
|
|
53
61
|
}
|
|
54
62
|
|
|
55
|
-
return sigs
|
|
63
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
56
64
|
}
|
|
57
65
|
|
|
58
66
|
function extractBlock(src, startIndex) {
|
|
@@ -80,7 +88,7 @@ function extractMembers(block) {
|
|
|
80
88
|
endIdx: m.index + m[0].length,
|
|
81
89
|
});
|
|
82
90
|
}
|
|
83
|
-
return members
|
|
91
|
+
return capMembersWithNotice(members, MEMBER_LIMIT);
|
|
84
92
|
}
|
|
85
93
|
|
|
86
94
|
function normalizeParams(params) {
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { capWithNotice } = require('../util/truncate');
|
|
4
|
+
|
|
5
|
+
// Ceiling discloses what it drops rather than truncating silently (#583).
|
|
6
|
+
const PER_FILE_LIMIT = 50;
|
|
7
|
+
|
|
3
8
|
/**
|
|
4
9
|
* Extract signatures from .properties configuration files.
|
|
5
10
|
* Captures key names, grouped by prefixes where possible.
|
|
@@ -31,7 +36,7 @@ function extract(src) {
|
|
|
31
36
|
sigs.push(`key ${key}`);
|
|
32
37
|
}
|
|
33
38
|
|
|
34
|
-
return Array.from(new Set(sigs))
|
|
39
|
+
return capWithNotice(Array.from(new Set(sigs)), PER_FILE_LIMIT, 'keys');
|
|
35
40
|
}
|
|
36
41
|
|
|
37
42
|
module.exports = { extract };
|
package/src/extractors/python.js
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const { lineAt } = require('./line-anchor');
|
|
5
|
+
const { capWithNotice } = require('../util/truncate');
|
|
6
|
+
|
|
7
|
+
// Ceiling sits above the default `maxSigsPerFile` so the configured budget
|
|
8
|
+
// governs output rather than a literal buried here, and omissions are disclosed (#576).
|
|
9
|
+
const PER_FILE_LIMIT = 30;
|
|
5
10
|
|
|
6
11
|
/**
|
|
7
12
|
* 1-based line of the last source line belonging to a top-level (indent 0)
|
|
@@ -136,7 +141,7 @@ function extract(src, filePath) {
|
|
|
136
141
|
}
|
|
137
142
|
}
|
|
138
143
|
|
|
139
|
-
return sigs
|
|
144
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
140
145
|
}
|
|
141
146
|
|
|
142
147
|
function extractClassMethods(stripped, startIndex) {
|
package/src/extractors/r.js
CHANGED
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
const { capWithNotice } = require('../util/truncate');
|
|
4
|
+
|
|
5
|
+
// Ceiling sits above the default `maxSigsPerFile` so the configured budget
|
|
6
|
+
// governs output rather than a literal buried here, and omissions are disclosed (#576).
|
|
7
|
+
const PER_FILE_LIMIT = 30;
|
|
8
|
+
|
|
3
9
|
/**
|
|
4
10
|
* Extract signatures from R source code.
|
|
5
11
|
*
|
|
@@ -38,7 +44,7 @@ function extract(src) {
|
|
|
38
44
|
// ClassName <- R6::R6Class(...)
|
|
39
45
|
const r6Re = /([\w.]+)\s*(?:<<-|<-|=)\s*(?:R6::)?R6Class\s*\(/g;
|
|
40
46
|
let m;
|
|
41
|
-
while ((m = r6Re.exec(stripped)) !== null
|
|
47
|
+
while ((m = r6Re.exec(stripped)) !== null) {
|
|
42
48
|
const name = m[1];
|
|
43
49
|
if (name.startsWith('.')) continue;
|
|
44
50
|
const openIdx = r6Re.lastIndex - 1;
|
|
@@ -49,7 +55,6 @@ function extract(src) {
|
|
|
49
55
|
sigs.push(`${name} <- R6Class("${classNameLit}")` + applyHint(docHints, name));
|
|
50
56
|
for (const memberSig of extractListMethods(body, 8)) {
|
|
51
57
|
sigs.push(' ' + memberSig);
|
|
52
|
-
if (sigs.length >= 30) break;
|
|
53
58
|
}
|
|
54
59
|
consumedRanges.push([m.index, closeIdx]);
|
|
55
60
|
r6Re.lastIndex = closeIdx;
|
|
@@ -59,7 +64,7 @@ function extract(src) {
|
|
|
59
64
|
// ClassName <- new_class("ClassName", properties = list(...))
|
|
60
65
|
const s7Classes = new Set();
|
|
61
66
|
const s7Re = /([\w.]+)\s*(?:<<-|<-|=)\s*(?:S7::)?new_class\s*\(/g;
|
|
62
|
-
while ((m = s7Re.exec(stripped)) !== null
|
|
67
|
+
while ((m = s7Re.exec(stripped)) !== null) {
|
|
63
68
|
const name = m[1];
|
|
64
69
|
if (name.startsWith('.')) continue;
|
|
65
70
|
const openIdx = s7Re.lastIndex - 1;
|
|
@@ -76,7 +81,7 @@ function extract(src) {
|
|
|
76
81
|
|
|
77
82
|
// S7 method dispatch: `method(generic, ClassName) <- function(args)`
|
|
78
83
|
const s7MethodRe = /^[ \t]*method\s*\(\s*([\w.]+)\s*,\s*([\w.]+)\s*\)\s*(?:<<-|<-|=)\s*function\s*\(/gm;
|
|
79
|
-
while ((m = s7MethodRe.exec(stripped)) !== null
|
|
84
|
+
while ((m = s7MethodRe.exec(stripped)) !== null) {
|
|
80
85
|
if (!s7Classes.has(m[2])) continue;
|
|
81
86
|
const argsStart = s7MethodRe.lastIndex - 1;
|
|
82
87
|
const args = readBalancedParens(stripped, argsStart);
|
|
@@ -89,7 +94,7 @@ function extract(src) {
|
|
|
89
94
|
// Skip matches whose position falls inside an R6/S7 class body — those have
|
|
90
95
|
// already been emitted as indented members.
|
|
91
96
|
const funcRe = /^(?:[ \t]*)([\w.]+)\s*(?:<<-|<-|=)\s*function\s*\(/gm;
|
|
92
|
-
while ((m = funcRe.exec(stripped)) !== null
|
|
97
|
+
while ((m = funcRe.exec(stripped)) !== null) {
|
|
93
98
|
const name = m[1];
|
|
94
99
|
if (name.startsWith('.')) continue;
|
|
95
100
|
if (inAnyRange(m.index, consumedRanges)) continue;
|
|
@@ -101,19 +106,16 @@ function extract(src) {
|
|
|
101
106
|
|
|
102
107
|
// ── S4 ────────────────────────────────────────────────────────────────────
|
|
103
108
|
for (const sm of stripped.matchAll(/^[ \t]*setGeneric\s*\(\s*["']([\w.]+)["']/gm)) {
|
|
104
|
-
if (sigs.length >= 30) break;
|
|
105
109
|
sigs.push(`setGeneric("${sm[1]}")`);
|
|
106
110
|
}
|
|
107
111
|
for (const sm of stripped.matchAll(/^[ \t]*setMethod\s*\(\s*["']([\w.]+)["']\s*,\s*["']([\w.]+)["']/gm)) {
|
|
108
|
-
if (sigs.length >= 30) break;
|
|
109
112
|
sigs.push(`setMethod("${sm[1]}", "${sm[2]}")`);
|
|
110
113
|
}
|
|
111
114
|
for (const sm of stripped.matchAll(/^[ \t]*setClass\s*\(\s*["']([\w.]+)["']/gm)) {
|
|
112
|
-
if (sigs.length >= 30) break;
|
|
113
115
|
sigs.push(`setClass("${sm[1]}")`);
|
|
114
116
|
}
|
|
115
117
|
|
|
116
|
-
return sigs
|
|
118
|
+
return capWithNotice(sigs, PER_FILE_LIMIT, 'signatures');
|
|
117
119
|
}
|
|
118
120
|
|
|
119
121
|
/**
|