projscan 1.6.2 → 1.7.0

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 (70) hide show
  1. package/dist/core/languages/LanguageAdapter.d.ts +1 -1
  2. package/dist/core/languages/cppAdapter.d.ts +2 -0
  3. package/dist/core/languages/cppAdapter.js +145 -0
  4. package/dist/core/languages/cppAdapter.js.map +1 -0
  5. package/dist/core/languages/cppCallSites.d.ts +13 -0
  6. package/dist/core/languages/cppCallSites.js +62 -0
  7. package/dist/core/languages/cppCallSites.js.map +1 -0
  8. package/dist/core/languages/cppCyclomatic.d.ts +25 -0
  9. package/dist/core/languages/cppCyclomatic.js +82 -0
  10. package/dist/core/languages/cppCyclomatic.js.map +1 -0
  11. package/dist/core/languages/cppExports.d.ts +13 -0
  12. package/dist/core/languages/cppExports.js +120 -0
  13. package/dist/core/languages/cppExports.js.map +1 -0
  14. package/dist/core/languages/cppFunctions.d.ts +30 -0
  15. package/dist/core/languages/cppFunctions.js +242 -0
  16. package/dist/core/languages/cppFunctions.js.map +1 -0
  17. package/dist/core/languages/cppImports.d.ts +25 -0
  18. package/dist/core/languages/cppImports.js +77 -0
  19. package/dist/core/languages/cppImports.js.map +1 -0
  20. package/dist/core/languages/cppManifests.d.ts +18 -0
  21. package/dist/core/languages/cppManifests.js +41 -0
  22. package/dist/core/languages/cppManifests.js.map +1 -0
  23. package/dist/core/languages/kotlinAdapter.d.ts +2 -0
  24. package/dist/core/languages/kotlinAdapter.js +141 -0
  25. package/dist/core/languages/kotlinAdapter.js.map +1 -0
  26. package/dist/core/languages/kotlinCallSites.d.ts +15 -0
  27. package/dist/core/languages/kotlinCallSites.js +62 -0
  28. package/dist/core/languages/kotlinCallSites.js.map +1 -0
  29. package/dist/core/languages/kotlinCyclomatic.d.ts +24 -0
  30. package/dist/core/languages/kotlinCyclomatic.js +54 -0
  31. package/dist/core/languages/kotlinCyclomatic.js.map +1 -0
  32. package/dist/core/languages/kotlinExports.d.ts +13 -0
  33. package/dist/core/languages/kotlinExports.js +103 -0
  34. package/dist/core/languages/kotlinExports.js.map +1 -0
  35. package/dist/core/languages/kotlinFunctions.d.ts +27 -0
  36. package/dist/core/languages/kotlinFunctions.js +147 -0
  37. package/dist/core/languages/kotlinFunctions.js.map +1 -0
  38. package/dist/core/languages/kotlinImports.d.ts +25 -0
  39. package/dist/core/languages/kotlinImports.js +74 -0
  40. package/dist/core/languages/kotlinImports.js.map +1 -0
  41. package/dist/core/languages/kotlinManifests.d.ts +20 -0
  42. package/dist/core/languages/kotlinManifests.js +46 -0
  43. package/dist/core/languages/kotlinManifests.js.map +1 -0
  44. package/dist/core/languages/registry.js +14 -1
  45. package/dist/core/languages/registry.js.map +1 -1
  46. package/dist/core/languages/treeSitterLoader.js +19 -1
  47. package/dist/core/languages/treeSitterLoader.js.map +1 -1
  48. package/dist/core/memory.d.ts +30 -0
  49. package/dist/core/memory.js +42 -0
  50. package/dist/core/memory.js.map +1 -1
  51. package/dist/core/session.d.ts +5 -0
  52. package/dist/core/session.js +8 -3
  53. package/dist/core/session.js.map +1 -1
  54. package/dist/grammars/tree-sitter-cpp.wasm +0 -0
  55. package/dist/grammars/tree-sitter-kotlin.wasm +0 -0
  56. package/dist/mcp/server.js +47 -10
  57. package/dist/mcp/server.js.map +1 -1
  58. package/dist/mcp/sessionTouchScanner.js +8 -2
  59. package/dist/mcp/sessionTouchScanner.js.map +1 -1
  60. package/dist/mcp/tools/costSummary.d.ts +26 -0
  61. package/dist/mcp/tools/costSummary.js +143 -0
  62. package/dist/mcp/tools/costSummary.js.map +1 -0
  63. package/dist/mcp/tools/fixSuggest.js +23 -2
  64. package/dist/mcp/tools/fixSuggest.js.map +1 -1
  65. package/dist/mcp/tools/memory.js +37 -4
  66. package/dist/mcp/tools/memory.js.map +1 -1
  67. package/dist/mcp/tools.js +2 -0
  68. package/dist/mcp/tools.js.map +1 -1
  69. package/dist/tool-manifest.json +18 -4
  70. package/package.json +5 -2
@@ -1,6 +1,6 @@
1
1
  import type { FileEntry } from '../../types.js';
2
2
  import type { AstResult } from '../ast.js';
3
- export type LanguageId = 'javascript' | 'python' | 'go' | 'java' | 'ruby' | 'rust' | 'php' | 'csharp';
3
+ export type LanguageId = 'javascript' | 'python' | 'go' | 'java' | 'ruby' | 'rust' | 'php' | 'csharp' | 'kotlin' | 'cpp';
4
4
  export interface LanguageResolveContext {
5
5
  /** Language-specific root dirs used during import resolution. */
6
6
  packageRoots?: string[];
@@ -0,0 +1,2 @@
1
+ import type { LanguageAdapter } from './LanguageAdapter.js';
2
+ export declare const cppAdapter: LanguageAdapter;
@@ -0,0 +1,145 @@
1
+ import path from 'node:path';
2
+ import { createParserFor } from './treeSitterLoader.js';
3
+ import { extractCppImports } from './cppImports.js';
4
+ import { extractCppExports } from './cppExports.js';
5
+ import { extractCppCyclomatic } from './cppCyclomatic.js';
6
+ import { extractCppFunctions } from './cppFunctions.js';
7
+ import { extractCppCallSites } from './cppCallSites.js';
8
+ import { detectCppProject } from './cppManifests.js';
9
+ const CPP_EXTENSIONS = new Set(['.cpp', '.cc', '.cxx', '.c', '.h', '.hpp', '.hxx']);
10
+ const SOURCE_EXTENSIONS = new Set(['.cpp', '.cc', '.cxx', '.c']);
11
+ const MAX_CPP_FILE = 1024 * 1024;
12
+ let parserPromise = null;
13
+ async function getParser() {
14
+ if (!parserPromise)
15
+ parserPromise = createParserFor('tree-sitter-cpp.wasm');
16
+ return parserPromise;
17
+ }
18
+ export const cppAdapter = {
19
+ id: 'cpp',
20
+ extensions: CPP_EXTENSIONS,
21
+ // Only .cpp/.cc/.cxx/.c are "source" for dead-code purposes; headers
22
+ // hold the declarations they consume.
23
+ sourceExtensions: SOURCE_EXTENSIONS,
24
+ barrelBasenames: new Set(),
25
+ maxFileSize: MAX_CPP_FILE,
26
+ async parse(_filePath, content) {
27
+ try {
28
+ const parser = await getParser();
29
+ const tree = parser.parse(content);
30
+ if (!tree || !tree.rootNode) {
31
+ return {
32
+ ok: false,
33
+ reason: 'tree-sitter returned null tree',
34
+ imports: [],
35
+ exports: [],
36
+ callSites: [],
37
+ lineCount: content ? content.split('\n').length : 0,
38
+ cyclomaticComplexity: 0,
39
+ functions: [],
40
+ };
41
+ }
42
+ const root = tree.rootNode;
43
+ const imports = extractCppImports(root);
44
+ const exports = extractCppExports(root);
45
+ const cyclomaticComplexity = extractCppCyclomatic(root);
46
+ const callSites = extractCppCallSites(root);
47
+ const functions = extractCppFunctions(root);
48
+ return {
49
+ ok: true,
50
+ imports,
51
+ exports,
52
+ callSites,
53
+ lineCount: content ? content.split('\n').length : 0,
54
+ cyclomaticComplexity,
55
+ functions,
56
+ };
57
+ }
58
+ catch (err) {
59
+ const msg = err instanceof Error ? err.message : String(err);
60
+ return {
61
+ ok: false,
62
+ reason: `cpp parse failure: ${msg.slice(0, 120)}`,
63
+ imports: [],
64
+ exports: [],
65
+ callSites: [],
66
+ lineCount: content ? content.split('\n').length : 0,
67
+ cyclomaticComplexity: 0,
68
+ functions: [],
69
+ };
70
+ }
71
+ },
72
+ resolveImport(importingFile, source, graphFiles, context) {
73
+ return resolveCppImport(importingFile, source, graphFiles, context);
74
+ },
75
+ toPackageName(source) {
76
+ if (!source)
77
+ return null;
78
+ // For #include, the "package" is the system header name (`vector`,
79
+ // `iostream`) when angle-bracketed. Quoted includes are project-local
80
+ // and should resolve via resolveImport — but we don't know quoting
81
+ // at this layer, so we conservatively return null for paths that
82
+ // look relative (`./`, `../`, contain `/`) and the bare leaf for
83
+ // angle-bracket-style names.
84
+ if (source.startsWith('./') || source.startsWith('../'))
85
+ return null;
86
+ if (source.includes('/'))
87
+ return source.split('/')[0];
88
+ return source;
89
+ },
90
+ async preparePackageRoots(rootPath, files) {
91
+ const info = await detectCppProject(rootPath, files);
92
+ return {
93
+ packageRoots: info ? info.includeRoots.map((r) => path.relative(rootPath, path.join(rootPath, r)) || '.') : [],
94
+ meta: info ? { cppProject: info } : undefined,
95
+ };
96
+ },
97
+ };
98
+ /**
99
+ * Resolve a C++ `#include` source to a repo-local file. We try, in order:
100
+ *
101
+ * 1. Relative to the importing file's directory (quoted-include semantics).
102
+ * 2. Each detected include root (e.g., `include/`, `src/`, `lib/`).
103
+ *
104
+ * We return the first hit. Standard-library / third-party headers (e.g.,
105
+ * `<vector>`, `<boost/optional.hpp>`) won't match anything in the graph
106
+ * and resolve to null, which is correct — they're external.
107
+ */
108
+ function resolveCppImport(importingFile, source, graphFiles, context) {
109
+ if (!source)
110
+ return null;
111
+ const project = context.meta?.cppProject;
112
+ const includeRoots = context.packageRoots ?? project?.includeRoots ?? [];
113
+ // 1) Relative to the importing file. tree-sitter doesn't tell us whether
114
+ // the source was quoted or angle-bracketed, but the resolver works the
115
+ // same way for either: we try the importing file's directory first.
116
+ const importingDir = path.posix.dirname(importingFile);
117
+ const relative = normalizeRelative(importingDir, source);
118
+ if (relative && graphFiles.has(relative))
119
+ return relative;
120
+ // 2) Each include root.
121
+ for (const root of includeRoots) {
122
+ const rootSegs = root === '.' || root === '' ? [] : root.split('/').filter(Boolean);
123
+ const candidate = [...rootSegs, ...source.split('/').filter(Boolean)].join('/');
124
+ if (graphFiles.has(candidate))
125
+ return candidate;
126
+ }
127
+ return null;
128
+ }
129
+ function normalizeRelative(baseDir, source) {
130
+ // Strip any leading `./`. For `../foo`, walk up the baseDir.
131
+ let dir = baseDir === '.' ? '' : baseDir;
132
+ let rest = source;
133
+ while (rest.startsWith('./'))
134
+ rest = rest.slice(2);
135
+ while (rest.startsWith('../')) {
136
+ if (!dir)
137
+ return null;
138
+ dir = path.posix.dirname(dir);
139
+ if (dir === '.')
140
+ dir = '';
141
+ rest = rest.slice(3);
142
+ }
143
+ return dir ? `${dir}/${rest}` : rest;
144
+ }
145
+ //# sourceMappingURL=cppAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cppAdapter.js","sourceRoot":"","sources":["../../../src/core/languages/cppAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ interface TsNode {
2
+ type: string;
3
+ text: string;
4
+ namedChildren: TsNode[];
5
+ childForFieldName?: (name: string) => TsNode | null;
6
+ }
7
+ /**
8
+ * Extract called-name from each `call_expression` in a tree-sitter-cpp AST.
9
+ * Mirrors the existing adapter behaviour: dedupe names, strip qualification,
10
+ * so `obj.foo()`, `Foo::bar()`, and `bar()` all surface as just the leaf.
11
+ */
12
+ export declare function extractCppCallSites(root: TsNode): string[];
13
+ export {};
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Extract called-name from each `call_expression` in a tree-sitter-cpp AST.
3
+ * Mirrors the existing adapter behaviour: dedupe names, strip qualification,
4
+ * so `obj.foo()`, `Foo::bar()`, and `bar()` all surface as just the leaf.
5
+ */
6
+ export function extractCppCallSites(root) {
7
+ const seen = new Set();
8
+ walk(root, (n) => {
9
+ if (n.type !== 'call_expression')
10
+ return;
11
+ const fn = pickCallee(n);
12
+ if (!fn)
13
+ return;
14
+ const name = bareName(fn);
15
+ if (name)
16
+ seen.add(name);
17
+ });
18
+ return [...seen];
19
+ }
20
+ function pickCallee(node) {
21
+ if (node.childForFieldName) {
22
+ const f = node.childForFieldName('function');
23
+ if (f)
24
+ return f;
25
+ }
26
+ return node.namedChildren[0] ?? null;
27
+ }
28
+ function bareName(node) {
29
+ switch (node.type) {
30
+ case 'identifier':
31
+ case 'field_identifier':
32
+ case 'type_identifier':
33
+ return node.text;
34
+ case 'qualified_identifier': {
35
+ const last = node.namedChildren[node.namedChildren.length - 1];
36
+ return last ? bareName(last) : null;
37
+ }
38
+ case 'field_expression': {
39
+ const f = node.childForFieldName ? node.childForFieldName('field') : null;
40
+ if (f)
41
+ return bareName(f);
42
+ const last = node.namedChildren[node.namedChildren.length - 1];
43
+ return last ? bareName(last) : null;
44
+ }
45
+ case 'template_function': {
46
+ const f = node.childForFieldName ? node.childForFieldName('name') : null;
47
+ return f ? bareName(f) : null;
48
+ }
49
+ case 'call_expression': {
50
+ const inner = pickCallee(node);
51
+ return inner ? bareName(inner) : null;
52
+ }
53
+ default:
54
+ return null;
55
+ }
56
+ }
57
+ function walk(node, visit) {
58
+ visit(node);
59
+ for (const child of node.namedChildren)
60
+ walk(child, visit);
61
+ }
62
+ //# sourceMappingURL=cppCallSites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cppCallSites.js","sourceRoot":"","sources":["../../../src/core/languages/cppCallSites.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,IAAY;IAC9C,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;QACf,IAAI,CAAC,CAAC,IAAI,KAAK,iBAAiB;YAAE,OAAO;QACzC,MAAM,EAAE,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACzB,IAAI,CAAC,EAAE;YAAE,OAAO;QAChB,MAAM,IAAI,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;QAC1B,IAAI,IAAI;YAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC,CAAC,CAAC;IACH,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;AACnB,CAAC;AAED,SAAS,UAAU,CAAC,IAAY;IAC9B,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAC3B,MAAM,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,CAAC;QAC7C,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AACvC,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,YAAY,CAAC;QAClB,KAAK,kBAAkB,CAAC;QACxB,KAAK,iBAAiB;YACpB,OAAO,IAAI,CAAC,IAAI,CAAC;QACnB,KAAK,sBAAsB,CAAC,CAAC,CAAC;YAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/D,OAAO,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACtC,CAAC;QACD,KAAK,kBAAkB,CAAC,CAAC,CAAC;YACxB,MAAM,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YAC1E,IAAI,CAAC;gBAAE,OAAO,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC1B,MAAM,IAAI,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/D,OAAO,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACtC,CAAC;QACD,KAAK,mBAAmB,CAAC,CAAC,CAAC;YACzB,MAAM,CAAC,GAAG,IAAI,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;YACzE,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QAChC,CAAC;QACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC;YAC/B,OAAO,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxC,CAAC;QACD;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED,SAAS,IAAI,CAAC,IAAY,EAAE,KAA0B;IACpD,KAAK,CAAC,IAAI,CAAC,CAAC;IACZ,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa;QAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,25 @@
1
+ interface TsNode {
2
+ type: string;
3
+ text: string;
4
+ namedChildren: TsNode[];
5
+ childForFieldName?: (name: string) => TsNode | null;
6
+ }
7
+ /**
8
+ * File-level McCabe cyclomatic complexity for a tree-sitter-cpp AST.
9
+ *
10
+ * Decision points in C++:
11
+ * if_statement +1
12
+ * for_statement +1
13
+ * for_range_loop +1
14
+ * while_statement +1
15
+ * do_statement +1
16
+ * try_statement +1
17
+ * catch_clause +1 each
18
+ * case_statement (non-default) +1
19
+ * conditional_expression (`?:`) +1
20
+ * binary_expression `&&` / `||` +1 each
21
+ *
22
+ * `case 1:` and `case 2:` count individually; `default:` does not.
23
+ */
24
+ export declare function extractCppCyclomatic(root: TsNode): number;
25
+ export {};
@@ -0,0 +1,82 @@
1
+ /**
2
+ * File-level McCabe cyclomatic complexity for a tree-sitter-cpp AST.
3
+ *
4
+ * Decision points in C++:
5
+ * if_statement +1
6
+ * for_statement +1
7
+ * for_range_loop +1
8
+ * while_statement +1
9
+ * do_statement +1
10
+ * try_statement +1
11
+ * catch_clause +1 each
12
+ * case_statement (non-default) +1
13
+ * conditional_expression (`?:`) +1
14
+ * binary_expression `&&` / `||` +1 each
15
+ *
16
+ * `case 1:` and `case 2:` count individually; `default:` does not.
17
+ */
18
+ export function extractCppCyclomatic(root) {
19
+ let decisions = 0;
20
+ walk(root, (n) => {
21
+ if (isDecisionPoint(n))
22
+ decisions++;
23
+ });
24
+ return decisions + 1;
25
+ }
26
+ function isDecisionPoint(n) {
27
+ switch (n.type) {
28
+ case 'if_statement':
29
+ case 'for_statement':
30
+ case 'for_range_loop':
31
+ case 'while_statement':
32
+ case 'do_statement':
33
+ case 'try_statement':
34
+ case 'catch_clause':
35
+ case 'conditional_expression':
36
+ return true;
37
+ case 'case_statement': {
38
+ // tree-sitter-cpp exposes a `value` field for `case X:` and leaves it
39
+ // null for `default:`. Field-based detection is more reliable than
40
+ // text inspection, which can misbehave when comments / whitespace
41
+ // sit between the keyword and the colon.
42
+ if (n.childForFieldName) {
43
+ const value = n.childForFieldName('value');
44
+ if (value)
45
+ return true;
46
+ }
47
+ // Fallback for grammar versions without the `value` field: a regular
48
+ // `case` has its label value as the first named child (literal /
49
+ // identifier / expression). The `default` form's first named child
50
+ // is whatever statement follows the colon.
51
+ const first = n.namedChildren[0];
52
+ if (!first)
53
+ return false;
54
+ return !STATEMENT_NODES.has(first.type);
55
+ }
56
+ case 'binary_expression':
57
+ return /(\s|^)(\|\||&&)(\s|$)/.test(n.text);
58
+ default:
59
+ return false;
60
+ }
61
+ }
62
+ const STATEMENT_NODES = new Set([
63
+ 'return_statement',
64
+ 'break_statement',
65
+ 'continue_statement',
66
+ 'expression_statement',
67
+ 'compound_statement',
68
+ 'if_statement',
69
+ 'for_statement',
70
+ 'while_statement',
71
+ 'do_statement',
72
+ 'switch_statement',
73
+ 'goto_statement',
74
+ 'declaration',
75
+ 'labeled_statement',
76
+ ]);
77
+ function walk(node, visit) {
78
+ visit(node);
79
+ for (const child of node.namedChildren)
80
+ walk(child, visit);
81
+ }
82
+ //# sourceMappingURL=cppCyclomatic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cppCyclomatic.js","sourceRoot":"","sources":["../../../src/core/languages/cppCyclomatic.ts"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;QACf,IAAI,eAAe,CAAC,CAAC,CAAC;YAAE,SAAS,EAAE,CAAC;IACtC,CAAC,CAAC,CAAC;IACH,OAAO,SAAS,GAAG,CAAC,CAAC;AACvB,CAAC;AAED,SAAS,eAAe,CAAC,CAAS;IAChC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC;QACf,KAAK,cAAc,CAAC;QACpB,KAAK,eAAe,CAAC;QACrB,KAAK,gBAAgB,CAAC;QACtB,KAAK,iBAAiB,CAAC;QACvB,KAAK,cAAc,CAAC;QACpB,KAAK,eAAe,CAAC;QACrB,KAAK,cAAc,CAAC;QACpB,KAAK,wBAAwB;YAC3B,OAAO,IAAI,CAAC;QACd,KAAK,gBAAgB,CAAC,CAAC,CAAC;YACtB,sEAAsE;YACtE,mEAAmE;YACnE,kEAAkE;YAClE,yCAAyC;YACzC,IAAI,CAAC,CAAC,iBAAiB,EAAE,CAAC;gBACxB,MAAM,KAAK,GAAG,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;gBAC3C,IAAI,KAAK;oBAAE,OAAO,IAAI,CAAC;YACzB,CAAC;YACD,qEAAqE;YACrE,iEAAiE;YACjE,mEAAmE;YACnE,2CAA2C;YAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC;YACjC,IAAI,CAAC,KAAK;gBAAE,OAAO,KAAK,CAAC;YACzB,OAAO,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC1C,CAAC;QACD,KAAK,mBAAmB;YACtB,OAAO,uBAAuB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QAC9C;YACE,OAAO,KAAK,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC;IAC9B,kBAAkB;IAClB,iBAAiB;IACjB,oBAAoB;IACpB,sBAAsB;IACtB,oBAAoB;IACpB,cAAc;IACd,eAAe;IACf,iBAAiB;IACjB,cAAc;IACd,kBAAkB;IAClB,gBAAgB;IAChB,aAAa;IACb,mBAAmB;CACpB,CAAC,CAAC;AAEH,SAAS,IAAI,CAAC,IAAY,EAAE,KAA0B;IACpD,KAAK,CAAC,IAAI,CAAC,CAAC;IACZ,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa;QAAE,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;AAC7D,CAAC"}
@@ -0,0 +1,13 @@
1
+ import type { AstExport } from '../ast.js';
2
+ interface TsNode {
3
+ type: string;
4
+ text: string;
5
+ startPosition: {
6
+ row: number;
7
+ column: number;
8
+ };
9
+ namedChildren: TsNode[];
10
+ childForFieldName?: (name: string) => TsNode | null;
11
+ }
12
+ export declare function extractCppExports(root: TsNode): AstExport[];
13
+ export {};
@@ -0,0 +1,120 @@
1
+ /**
2
+ * Extract top-level C++ declarations as exports.
3
+ *
4
+ * C++ has no first-class export model the way Rust / Kotlin do; "exports"
5
+ * for graph purposes are top-level declarations that are visible to other
6
+ * translation units. We surface:
7
+ *
8
+ * function_definition → function (free functions and methods)
9
+ * class_specifier → class
10
+ * struct_specifier → class (structs are classes with default-public)
11
+ * union_specifier → class
12
+ * enum_specifier → enum
13
+ * alias_declaration → type (`using Foo = Bar;`)
14
+ * type_definition → type (`typedef ... Foo;`)
15
+ * declaration (var/const) → variable (top-level globals)
16
+ *
17
+ * `static` at file scope marks a translation-unit-internal symbol; we
18
+ * still surface it (the graph treats it as a local definition).
19
+ *
20
+ * Member declarations inside class bodies are NOT extracted (they're
21
+ * reachable via the class export). Anonymous namespaces are descended.
22
+ */
23
+ const EXPORT_NODE_TO_KIND = {
24
+ function_definition: 'function',
25
+ class_specifier: 'class',
26
+ struct_specifier: 'class',
27
+ union_specifier: 'class',
28
+ enum_specifier: 'enum',
29
+ alias_declaration: 'type',
30
+ type_definition: 'type',
31
+ };
32
+ export function extractCppExports(root) {
33
+ const exports = [];
34
+ visitTopLevel(root, exports);
35
+ return exports;
36
+ }
37
+ function visitTopLevel(node, out) {
38
+ // Descend through namespace and linkage_specification (`extern "C" { ... }`)
39
+ // wrappers — top-level declarations inside them are still file-scope.
40
+ if (node.type === 'translation_unit' ||
41
+ node.type === 'namespace_definition' ||
42
+ node.type === 'linkage_specification' ||
43
+ node.type === 'declaration_list') {
44
+ for (const c of node.namedChildren)
45
+ visitTopLevel(c, out);
46
+ return;
47
+ }
48
+ const kind = EXPORT_NODE_TO_KIND[node.type];
49
+ if (kind) {
50
+ const name = nameOf(node);
51
+ if (name)
52
+ out.push({ name, kind, typeOnly: false, line: node.startPosition.row + 1 });
53
+ return;
54
+ }
55
+ // Top-level variable / constant declarations: tree-sitter-cpp uses
56
+ // `declaration` for these. A declaration at translation-unit scope with
57
+ // a single declarator is a variable export.
58
+ if (node.type === 'declaration') {
59
+ const declarators = collectDeclarators(node);
60
+ for (const d of declarators) {
61
+ out.push({ name: d.name, kind: 'variable', typeOnly: false, line: node.startPosition.row + 1 });
62
+ }
63
+ return;
64
+ }
65
+ // Don't recurse into anything else — class bodies and function bodies
66
+ // hold non-top-level declarations.
67
+ }
68
+ function collectDeclarators(declaration) {
69
+ const out = [];
70
+ for (const c of declaration.namedChildren) {
71
+ // function_declarator / init_declarator / array_declarator are wrappers
72
+ // around an identifier. Drill through them.
73
+ const id = innerIdentifier(c);
74
+ if (id)
75
+ out.push({ name: id });
76
+ }
77
+ return out;
78
+ }
79
+ function innerIdentifier(node) {
80
+ if (node.type === 'identifier' ||
81
+ node.type === 'field_identifier' ||
82
+ node.type === 'type_identifier') {
83
+ return node.text;
84
+ }
85
+ if (node.type === 'init_declarator' ||
86
+ node.type === 'array_declarator' ||
87
+ node.type === 'pointer_declarator' ||
88
+ node.type === 'reference_declarator' ||
89
+ node.type === 'parenthesized_declarator' ||
90
+ node.type === 'function_declarator') {
91
+ if (node.childForFieldName) {
92
+ const dec = node.childForFieldName('declarator');
93
+ if (dec)
94
+ return innerIdentifier(dec);
95
+ }
96
+ for (const c of node.namedChildren) {
97
+ const r = innerIdentifier(c);
98
+ if (r)
99
+ return r;
100
+ }
101
+ }
102
+ return null;
103
+ }
104
+ function nameOf(node) {
105
+ if (node.childForFieldName) {
106
+ const id = node.childForFieldName('name');
107
+ if (id && id.text)
108
+ return id.text;
109
+ const dec = node.childForFieldName('declarator');
110
+ if (dec)
111
+ return innerIdentifier(dec);
112
+ }
113
+ for (const c of node.namedChildren) {
114
+ if (c.type === 'identifier' || c.type === 'field_identifier' || c.type === 'type_identifier') {
115
+ return c.text;
116
+ }
117
+ }
118
+ return innerIdentifier(node);
119
+ }
120
+ //# sourceMappingURL=cppExports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cppExports.js","sourceRoot":"","sources":["../../../src/core/languages/cppExports.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ import type { FunctionInfo } from '../ast.js';
2
+ interface TsNode {
3
+ type: string;
4
+ text: string;
5
+ startPosition: {
6
+ row: number;
7
+ column: number;
8
+ };
9
+ endPosition: {
10
+ row: number;
11
+ column: number;
12
+ };
13
+ namedChildren: TsNode[];
14
+ childForFieldName?: (name: string) => TsNode | null;
15
+ }
16
+ /**
17
+ * Per-function McCabe CC for C++. Walks `function_definition` nodes
18
+ * (free functions, methods defined out-of-line, lambdas are NOT
19
+ * extracted as separate entries; their decisions fold into the
20
+ * enclosing function — matches the convention used elsewhere).
21
+ *
22
+ * Member functions defined inside a class body are named `Class.method`.
23
+ * Out-of-line definitions (`void Foo::bar() { ... }`) are also named
24
+ * `Foo.bar` based on the qualified declarator.
25
+ *
26
+ * `case` labels each contribute +1; `default:` does not. Ternaries (`?:`)
27
+ * count as +1. Logical `&&` and `||` each count.
28
+ */
29
+ export declare function extractCppFunctions(root: TsNode): FunctionInfo[];
30
+ export {};