projscan 1.6.1 → 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 (85) hide show
  1. package/dist/core/applyFix.js +57 -4
  2. package/dist/core/applyFix.js.map +1 -1
  3. package/dist/core/codeGraph.js +6 -2
  4. package/dist/core/codeGraph.js.map +1 -1
  5. package/dist/core/fileInspector.js +42 -7
  6. package/dist/core/fileInspector.js.map +1 -1
  7. package/dist/core/languages/LanguageAdapter.d.ts +1 -1
  8. package/dist/core/languages/cppAdapter.d.ts +2 -0
  9. package/dist/core/languages/cppAdapter.js +145 -0
  10. package/dist/core/languages/cppAdapter.js.map +1 -0
  11. package/dist/core/languages/cppCallSites.d.ts +13 -0
  12. package/dist/core/languages/cppCallSites.js +62 -0
  13. package/dist/core/languages/cppCallSites.js.map +1 -0
  14. package/dist/core/languages/cppCyclomatic.d.ts +25 -0
  15. package/dist/core/languages/cppCyclomatic.js +82 -0
  16. package/dist/core/languages/cppCyclomatic.js.map +1 -0
  17. package/dist/core/languages/cppExports.d.ts +13 -0
  18. package/dist/core/languages/cppExports.js +120 -0
  19. package/dist/core/languages/cppExports.js.map +1 -0
  20. package/dist/core/languages/cppFunctions.d.ts +30 -0
  21. package/dist/core/languages/cppFunctions.js +242 -0
  22. package/dist/core/languages/cppFunctions.js.map +1 -0
  23. package/dist/core/languages/cppImports.d.ts +25 -0
  24. package/dist/core/languages/cppImports.js +77 -0
  25. package/dist/core/languages/cppImports.js.map +1 -0
  26. package/dist/core/languages/cppManifests.d.ts +18 -0
  27. package/dist/core/languages/cppManifests.js +41 -0
  28. package/dist/core/languages/cppManifests.js.map +1 -0
  29. package/dist/core/languages/kotlinAdapter.d.ts +2 -0
  30. package/dist/core/languages/kotlinAdapter.js +141 -0
  31. package/dist/core/languages/kotlinAdapter.js.map +1 -0
  32. package/dist/core/languages/kotlinCallSites.d.ts +15 -0
  33. package/dist/core/languages/kotlinCallSites.js +62 -0
  34. package/dist/core/languages/kotlinCallSites.js.map +1 -0
  35. package/dist/core/languages/kotlinCyclomatic.d.ts +24 -0
  36. package/dist/core/languages/kotlinCyclomatic.js +54 -0
  37. package/dist/core/languages/kotlinCyclomatic.js.map +1 -0
  38. package/dist/core/languages/kotlinExports.d.ts +13 -0
  39. package/dist/core/languages/kotlinExports.js +103 -0
  40. package/dist/core/languages/kotlinExports.js.map +1 -0
  41. package/dist/core/languages/kotlinFunctions.d.ts +27 -0
  42. package/dist/core/languages/kotlinFunctions.js +147 -0
  43. package/dist/core/languages/kotlinFunctions.js.map +1 -0
  44. package/dist/core/languages/kotlinImports.d.ts +25 -0
  45. package/dist/core/languages/kotlinImports.js +74 -0
  46. package/dist/core/languages/kotlinImports.js.map +1 -0
  47. package/dist/core/languages/kotlinManifests.d.ts +20 -0
  48. package/dist/core/languages/kotlinManifests.js +46 -0
  49. package/dist/core/languages/kotlinManifests.js.map +1 -0
  50. package/dist/core/languages/registry.js +14 -1
  51. package/dist/core/languages/registry.js.map +1 -1
  52. package/dist/core/languages/treeSitterLoader.js +19 -1
  53. package/dist/core/languages/treeSitterLoader.js.map +1 -1
  54. package/dist/core/memory.d.ts +30 -0
  55. package/dist/core/memory.js +42 -0
  56. package/dist/core/memory.js.map +1 -1
  57. package/dist/core/prDiff.js +3 -1
  58. package/dist/core/prDiff.js.map +1 -1
  59. package/dist/core/review.js +42 -6
  60. package/dist/core/review.js.map +1 -1
  61. package/dist/core/searchIndex.js +8 -4
  62. package/dist/core/searchIndex.js.map +1 -1
  63. package/dist/core/session.d.ts +5 -0
  64. package/dist/core/session.js +18 -8
  65. package/dist/core/session.js.map +1 -1
  66. package/dist/grammars/tree-sitter-cpp.wasm +0 -0
  67. package/dist/grammars/tree-sitter-kotlin.wasm +0 -0
  68. package/dist/mcp/server.js +57 -11
  69. package/dist/mcp/server.js.map +1 -1
  70. package/dist/mcp/sessionTouchScanner.js +8 -2
  71. package/dist/mcp/sessionTouchScanner.js.map +1 -1
  72. package/dist/mcp/tools/costSummary.d.ts +26 -0
  73. package/dist/mcp/tools/costSummary.js +143 -0
  74. package/dist/mcp/tools/costSummary.js.map +1 -0
  75. package/dist/mcp/tools/fixSuggest.js +23 -2
  76. package/dist/mcp/tools/fixSuggest.js.map +1 -1
  77. package/dist/mcp/tools/memory.js +37 -4
  78. package/dist/mcp/tools/memory.js.map +1 -1
  79. package/dist/mcp/tools.js +2 -0
  80. package/dist/mcp/tools.js.map +1 -1
  81. package/dist/tool-manifest.json +18 -4
  82. package/dist/utils/concurrency.d.ts +23 -0
  83. package/dist/utils/concurrency.js +37 -0
  84. package/dist/utils/concurrency.js.map +1 -0
  85. package/package.json +5 -2
@@ -0,0 +1,41 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ const COMMON_CPP_ROOTS = ['include', 'src', 'lib', '.'];
4
+ /**
5
+ * Detect C++ source roots. We don't parse CMakeLists / Make files; we
6
+ * survey .cpp/.cc/.cxx/.h/.hpp file paths and pick whichever conventional
7
+ * roots actually contain sources.
8
+ */
9
+ export async function detectCppProject(rootPath, files) {
10
+ const cppFiles = files.filter((f) => isCppExtension(f.relativePath));
11
+ if (cppFiles.length === 0)
12
+ return null;
13
+ const hasCMake = await fileExists(path.join(rootPath, 'CMakeLists.txt'));
14
+ const hasMakefile = await fileExists(path.join(rootPath, 'Makefile'));
15
+ const includeRoots = [];
16
+ for (const candidate of COMMON_CPP_ROOTS) {
17
+ if (candidate === '.') {
18
+ if (cppFiles.some((f) => !f.relativePath.includes('/')))
19
+ includeRoots.push('.');
20
+ }
21
+ else if (cppFiles.some((f) => f.relativePath.startsWith(candidate + '/'))) {
22
+ includeRoots.push(candidate);
23
+ }
24
+ }
25
+ if (includeRoots.length === 0)
26
+ includeRoots.push('.');
27
+ return { includeRoots, hasCMake, hasMakefile };
28
+ }
29
+ async function fileExists(p) {
30
+ try {
31
+ await fs.access(p);
32
+ return true;
33
+ }
34
+ catch {
35
+ return false;
36
+ }
37
+ }
38
+ function isCppExtension(p) {
39
+ return /\.(cpp|cc|cxx|c\+\+|c|h|hpp|hxx|h\+\+)$/.test(p);
40
+ }
41
+ //# sourceMappingURL=cppManifests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cppManifests.js","sourceRoot":"","sources":["../../../src/core/languages/cppManifests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAe7B,MAAM,gBAAgB,GAAG,CAAC,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,GAAG,CAAC,CAAC;AAExD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAAgB,EAChB,KAAkB;IAElB,MAAM,QAAQ,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IACrE,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvC,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACzE,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC,CAAC;IACtE,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,MAAM,SAAS,IAAI,gBAAgB,EAAE,CAAC;QACzC,IAAI,SAAS,KAAK,GAAG,EAAE,CAAC;YACtB,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;gBAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAClF,CAAC;aAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;YAC5E,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,WAAW,EAAE,CAAC;AACjD,CAAC;AAED,KAAK,UAAU,UAAU,CAAC,CAAS;IACjC,IAAI,CAAC;QACH,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,SAAS,cAAc,CAAC,CAAS;IAC/B,OAAO,yCAAyC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAC3D,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { LanguageAdapter } from './LanguageAdapter.js';
2
+ export declare const kotlinAdapter: LanguageAdapter;
@@ -0,0 +1,141 @@
1
+ import path from 'node:path';
2
+ import { createParserFor } from './treeSitterLoader.js';
3
+ import { extractKotlinImports } from './kotlinImports.js';
4
+ import { extractKotlinExports } from './kotlinExports.js';
5
+ import { extractKotlinCyclomatic } from './kotlinCyclomatic.js';
6
+ import { extractKotlinFunctions } from './kotlinFunctions.js';
7
+ import { extractKotlinCallSites } from './kotlinCallSites.js';
8
+ import { detectKotlinProject } from './kotlinManifests.js';
9
+ const KOTLIN_EXTENSIONS = new Set(['.kt', '.kts']);
10
+ const MAX_KOTLIN_FILE = 1024 * 1024;
11
+ let parserPromise = null;
12
+ async function getParser() {
13
+ if (!parserPromise)
14
+ parserPromise = createParserFor('tree-sitter-kotlin.wasm');
15
+ return parserPromise;
16
+ }
17
+ export const kotlinAdapter = {
18
+ id: 'kotlin',
19
+ extensions: KOTLIN_EXTENSIONS,
20
+ sourceExtensions: KOTLIN_EXTENSIONS,
21
+ // Kotlin has no "barrel-file" idiom; entry-points are .kt files with `fun main`.
22
+ barrelBasenames: new Set(),
23
+ maxFileSize: MAX_KOTLIN_FILE,
24
+ async parse(_filePath, content) {
25
+ try {
26
+ const parser = await getParser();
27
+ const tree = parser.parse(content);
28
+ if (!tree || !tree.rootNode) {
29
+ return {
30
+ ok: false,
31
+ reason: 'tree-sitter returned null tree',
32
+ imports: [],
33
+ exports: [],
34
+ callSites: [],
35
+ lineCount: content ? content.split('\n').length : 0,
36
+ cyclomaticComplexity: 0,
37
+ functions: [],
38
+ };
39
+ }
40
+ const root = tree.rootNode;
41
+ const imports = extractKotlinImports(root);
42
+ const exports = extractKotlinExports(root);
43
+ const cyclomaticComplexity = extractKotlinCyclomatic(root);
44
+ const callSites = extractKotlinCallSites(root);
45
+ const functions = extractKotlinFunctions(root);
46
+ return {
47
+ ok: true,
48
+ imports,
49
+ exports,
50
+ callSites,
51
+ lineCount: content ? content.split('\n').length : 0,
52
+ cyclomaticComplexity,
53
+ functions,
54
+ };
55
+ }
56
+ catch (err) {
57
+ const msg = err instanceof Error ? err.message : String(err);
58
+ return {
59
+ ok: false,
60
+ reason: `kotlin parse failure: ${msg.slice(0, 120)}`,
61
+ imports: [],
62
+ exports: [],
63
+ callSites: [],
64
+ lineCount: content ? content.split('\n').length : 0,
65
+ cyclomaticComplexity: 0,
66
+ functions: [],
67
+ };
68
+ }
69
+ },
70
+ resolveImport(importingFile, source, graphFiles, context) {
71
+ return resolveKotlinImport(importingFile, source, graphFiles, context);
72
+ },
73
+ toPackageName(source) {
74
+ if (!source)
75
+ return null;
76
+ // Heuristic: a Kotlin import that begins with the project's own
77
+ // detected source-root directory shouldn't be a "package" — but at
78
+ // graph-build time we don't have project info here. Defer to
79
+ // resolveImport: anything that resolveImport can't pin to a local
80
+ // file falls through as external.
81
+ return source.split('.')[0] || null;
82
+ },
83
+ async preparePackageRoots(rootPath, files) {
84
+ const info = await detectKotlinProject(rootPath, files);
85
+ return {
86
+ packageRoots: info ? info.packageRoots.map((r) => path.relative(rootPath, path.join(rootPath, r)) || '.') : [],
87
+ meta: info ? { kotlinProject: info } : undefined,
88
+ };
89
+ },
90
+ };
91
+ /**
92
+ * Resolve a Kotlin `import com.foo.Bar` to a repo-local file. The path
93
+ * `com.foo.Bar` becomes `com/foo/Bar.kt` under each known package root.
94
+ * Wildcard imports (`com.foo.*`) resolve to `com/foo/<any>.kt` and we
95
+ * pick the first match if any. Non-local (stdlib, third-party) imports
96
+ * return null.
97
+ */
98
+ function resolveKotlinImport(_importingFile, source, graphFiles, context) {
99
+ if (!source)
100
+ return null;
101
+ const project = context.meta?.kotlinProject;
102
+ const packageRoots = context.packageRoots ?? project?.packageRoots ?? [];
103
+ if (packageRoots.length === 0)
104
+ return null;
105
+ const isWildcard = source.endsWith('.*');
106
+ const cleanedSegments = (isWildcard ? source.slice(0, -2) : source).split('.').filter(Boolean);
107
+ if (cleanedSegments.length === 0)
108
+ return null;
109
+ for (const root of packageRoots) {
110
+ const rootSegs = root === '.' || root === '' ? [] : root.split('/').filter(Boolean);
111
+ if (isWildcard) {
112
+ const dirParts = [...rootSegs, ...cleanedSegments];
113
+ const prefix = dirParts.join('/') + '/';
114
+ // Pick any file under that package directory.
115
+ for (const key of graphFiles.keys()) {
116
+ if (key.startsWith(prefix) && (key.endsWith('.kt') || key.endsWith('.kts'))) {
117
+ return key;
118
+ }
119
+ }
120
+ continue;
121
+ }
122
+ // Non-wildcard: try each segment count from full → 1, since the last segment
123
+ // could be a class name OR a file name. Try `com/foo/Bar.kt`, then if not
124
+ // found try `com/foo.kt` (top-level decl in Foo.kt).
125
+ for (let drop = 0; drop <= 1; drop++) {
126
+ const segs = cleanedSegments.slice(0, cleanedSegments.length - drop);
127
+ if (segs.length === 0)
128
+ break;
129
+ const baseSegs = [...rootSegs, ...segs.slice(0, -1)];
130
+ const fileName = segs[segs.length - 1];
131
+ const asKt = [...baseSegs, `${fileName}.kt`].join('/');
132
+ if (graphFiles.has(asKt))
133
+ return asKt;
134
+ const asKts = [...baseSegs, `${fileName}.kts`].join('/');
135
+ if (graphFiles.has(asKts))
136
+ return asKts;
137
+ }
138
+ }
139
+ return null;
140
+ }
141
+ //# sourceMappingURL=kotlinAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kotlinAdapter.js","sourceRoot":"","sources":["../../../src/core/languages/kotlinAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ interface TsNode {
2
+ type: string;
3
+ text: string;
4
+ namedChildren: TsNode[];
5
+ childForFieldName?: (name: string) => TsNode | null;
6
+ }
7
+ /**
8
+ * Extract the called identifier from each `call_expression` in a
9
+ * tree-sitter-kotlin AST. Mirrors the existing adapter behaviour: we
10
+ * deduplicate names and strip qualification so that `foo.bar()` and `bar()`
11
+ * both produce `bar`. Constructor calls (`Foo()`) and infix-form calls are
12
+ * captured the same way.
13
+ */
14
+ export declare function extractKotlinCallSites(root: TsNode): string[];
15
+ export {};
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Extract the called identifier from each `call_expression` in a
3
+ * tree-sitter-kotlin AST. Mirrors the existing adapter behaviour: we
4
+ * deduplicate names and strip qualification so that `foo.bar()` and `bar()`
5
+ * both produce `bar`. Constructor calls (`Foo()`) and infix-form calls are
6
+ * captured the same way.
7
+ */
8
+ export function extractKotlinCallSites(root) {
9
+ const seen = new Set();
10
+ walk(root, (n) => {
11
+ if (n.type !== 'call_expression')
12
+ return;
13
+ const fn = pickCallee(n);
14
+ if (!fn)
15
+ return;
16
+ const name = bareName(fn);
17
+ if (name)
18
+ seen.add(name);
19
+ });
20
+ return [...seen];
21
+ }
22
+ function pickCallee(node) {
23
+ if (node.childForFieldName) {
24
+ const f = node.childForFieldName('function');
25
+ if (f)
26
+ return f;
27
+ }
28
+ return node.namedChildren[0] ?? null;
29
+ }
30
+ function bareName(node) {
31
+ switch (node.type) {
32
+ case 'simple_identifier':
33
+ case 'identifier':
34
+ case 'type_identifier':
35
+ return node.text;
36
+ case 'navigation_expression': {
37
+ const last = node.namedChildren[node.namedChildren.length - 1];
38
+ return last ? bareName(last) : null;
39
+ }
40
+ case 'navigation_suffix': {
41
+ for (const c of node.namedChildren) {
42
+ const n = bareName(c);
43
+ if (n)
44
+ return n;
45
+ }
46
+ return null;
47
+ }
48
+ case 'call_expression': {
49
+ // Foo()() — a chained invocation; recurse on the inner callee.
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=kotlinCallSites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kotlinCallSites.js","sourceRoot":"","sources":["../../../src/core/languages/kotlinCallSites.ts"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,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,mBAAmB,CAAC;QACzB,KAAK,YAAY,CAAC;QAClB,KAAK,iBAAiB;YACpB,OAAO,IAAI,CAAC,IAAI,CAAC;QACnB,KAAK,uBAAuB,CAAC,CAAC,CAAC;YAC7B,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,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACnC,MAAM,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;gBACtB,IAAI,CAAC;oBAAE,OAAO,CAAC,CAAC;YAClB,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QACD,KAAK,iBAAiB,CAAC,CAAC,CAAC;YACvB,+DAA+D;YAC/D,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,24 @@
1
+ interface TsNode {
2
+ type: string;
3
+ text: string;
4
+ namedChildren: TsNode[];
5
+ }
6
+ /**
7
+ * File-level McCabe cyclomatic complexity for a tree-sitter-kotlin AST.
8
+ *
9
+ * Decision points in Kotlin:
10
+ * if_expression +1 (the `if` itself; `else` does not count)
11
+ * for_statement +1
12
+ * while_statement +1
13
+ * do_while_statement +1
14
+ * try_expression +1 (success vs throw paths)
15
+ * catch_block +1 (each catch is a separate handler)
16
+ * when_entry (non-else) +1 (each non-else `when` arm is a branch)
17
+ * conjunction_expression +1 (Kotlin's `&&`)
18
+ * disjunction_expression +1 (Kotlin's `||`)
19
+ *
20
+ * The Elvis operator `?:` and safe-call `?.` do NOT count as branches —
21
+ * matches the convention used elsewhere in projscan and most analyzers.
22
+ */
23
+ export declare function extractKotlinCyclomatic(root: TsNode): number;
24
+ export {};
@@ -0,0 +1,54 @@
1
+ /**
2
+ * File-level McCabe cyclomatic complexity for a tree-sitter-kotlin AST.
3
+ *
4
+ * Decision points in Kotlin:
5
+ * if_expression +1 (the `if` itself; `else` does not count)
6
+ * for_statement +1
7
+ * while_statement +1
8
+ * do_while_statement +1
9
+ * try_expression +1 (success vs throw paths)
10
+ * catch_block +1 (each catch is a separate handler)
11
+ * when_entry (non-else) +1 (each non-else `when` arm is a branch)
12
+ * conjunction_expression +1 (Kotlin's `&&`)
13
+ * disjunction_expression +1 (Kotlin's `||`)
14
+ *
15
+ * The Elvis operator `?:` and safe-call `?.` do NOT count as branches —
16
+ * matches the convention used elsewhere in projscan and most analyzers.
17
+ */
18
+ export function extractKotlinCyclomatic(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_expression':
29
+ case 'for_statement':
30
+ case 'while_statement':
31
+ case 'do_while_statement':
32
+ case 'try_expression':
33
+ case 'catch_block':
34
+ case 'conjunction_expression':
35
+ case 'disjunction_expression':
36
+ return true;
37
+ case 'when_entry': {
38
+ // The `else` arm has no `when_condition` child — the `else` keyword is
39
+ // an anonymous token in tree-sitter-kotlin, so checking child text
40
+ // doesn't work reliably. Non-else arms always carry at least one
41
+ // `when_condition` (multi-value arms like `1, 2 ->` carry several).
42
+ const hasCondition = n.namedChildren.some((c) => c.type === 'when_condition');
43
+ return hasCondition;
44
+ }
45
+ default:
46
+ return false;
47
+ }
48
+ }
49
+ function walk(node, visit) {
50
+ visit(node);
51
+ for (const child of node.namedChildren)
52
+ walk(child, visit);
53
+ }
54
+ //# sourceMappingURL=kotlinCyclomatic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kotlinCyclomatic.js","sourceRoot":"","sources":["../../../src/core/languages/kotlinCyclomatic.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,uBAAuB,CAAC,IAAY;IAClD,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,eAAe,CAAC;QACrB,KAAK,eAAe,CAAC;QACrB,KAAK,iBAAiB,CAAC;QACvB,KAAK,oBAAoB,CAAC;QAC1B,KAAK,gBAAgB,CAAC;QACtB,KAAK,aAAa,CAAC;QACnB,KAAK,wBAAwB,CAAC;QAC9B,KAAK,wBAAwB;YAC3B,OAAO,IAAI,CAAC;QACd,KAAK,YAAY,CAAC,CAAC,CAAC;YAClB,uEAAuE;YACvE,mEAAmE;YACnE,iEAAiE;YACjE,oEAAoE;YACpE,MAAM,YAAY,GAAG,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC;YAC9E,OAAO,YAAY,CAAC;QACtB,CAAC;QACD;YACE,OAAO,KAAK,CAAC;IACjB,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,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 extractKotlinExports(root: TsNode): AstExport[];
13
+ export {};
@@ -0,0 +1,103 @@
1
+ /**
2
+ * Extract Kotlin top-level declarations as exports. Kotlin's default
3
+ * visibility is `public`; only declarations marked `private` or `internal`
4
+ * are excluded. `protected` only applies to class members and is treated
5
+ * as exported when on a top-level decl (which is unusual but valid in
6
+ * tree-sitter's grammar).
7
+ *
8
+ * Kinds:
9
+ * fun foo() → function
10
+ * class Foo → class
11
+ * interface Foo → interface
12
+ * object Foo → class (Kotlin singleton object, modeled as class)
13
+ * enum class Color → enum
14
+ * typealias Bar = ... → type
15
+ * val/const x → variable
16
+ */
17
+ const EXPORT_NODE_TO_KIND = {
18
+ function_declaration: 'function',
19
+ class_declaration: 'class',
20
+ object_declaration: 'class',
21
+ type_alias: 'type',
22
+ property_declaration: 'variable',
23
+ };
24
+ export function extractKotlinExports(root) {
25
+ const exports = [];
26
+ // Top-level only: descend into the source_file/file_node body but not into
27
+ // nested classes (their members aren't top-level exports for graph purposes).
28
+ for (const child of root.namedChildren) {
29
+ visitTopLevel(child, exports);
30
+ }
31
+ return exports;
32
+ }
33
+ function visitTopLevel(node, out) {
34
+ // Some grammars wrap top-level decls in `package_header` / `import_list` /
35
+ // an explicit `top_level_object` node. We descend through wrappers.
36
+ if (node.type === 'package_header' ||
37
+ node.type === 'import_list' ||
38
+ node.type === 'file_annotation') {
39
+ return;
40
+ }
41
+ if (node.type === 'class_declaration') {
42
+ const isInterface = /\binterface\b/.test(headerText(node));
43
+ const isEnum = /\benum\s+class\b/.test(headerText(node));
44
+ const kind = isEnum ? 'enum' : isInterface ? 'interface' : 'class';
45
+ if (!isPrivate(node)) {
46
+ const name = nameOf(node);
47
+ if (name)
48
+ out.push({ name, kind, typeOnly: false, line: node.startPosition.row + 1 });
49
+ }
50
+ return;
51
+ }
52
+ const kind = EXPORT_NODE_TO_KIND[node.type];
53
+ if (!kind) {
54
+ // Walk container nodes (e.g., source_file already iterated, but defensively descend).
55
+ for (const c of node.namedChildren)
56
+ visitTopLevel(c, out);
57
+ return;
58
+ }
59
+ if (isPrivate(node))
60
+ return;
61
+ const name = nameOf(node);
62
+ if (!name)
63
+ return;
64
+ out.push({ name, kind, typeOnly: false, line: node.startPosition.row + 1 });
65
+ }
66
+ function headerText(node) {
67
+ // Just the first line — the `class`/`interface`/`enum class` keyword
68
+ // appears in the header before the body opens.
69
+ const idx = node.text.indexOf('{');
70
+ return idx >= 0 ? node.text.slice(0, idx) : node.text;
71
+ }
72
+ function isPrivate(node) {
73
+ for (const c of node.namedChildren) {
74
+ if (c.type === 'modifiers' || c.type === 'modifier_list') {
75
+ for (const m of c.namedChildren) {
76
+ if (m.type === 'visibility_modifier') {
77
+ const t = m.text.trim();
78
+ if (t === 'private' || t === 'internal')
79
+ return true;
80
+ }
81
+ }
82
+ }
83
+ }
84
+ return false;
85
+ }
86
+ function nameOf(node) {
87
+ if (node.childForFieldName) {
88
+ const id = node.childForFieldName('name');
89
+ if (id && id.text)
90
+ return id.text;
91
+ }
92
+ for (const c of node.namedChildren) {
93
+ if (c.type === 'simple_identifier' || c.type === 'identifier' || c.type === 'type_identifier') {
94
+ return c.text;
95
+ }
96
+ }
97
+ // property_declaration: `val/var <name> = ...`
98
+ const m = /\b(val|var|const\s+val)\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(node.text);
99
+ if (m)
100
+ return m[2];
101
+ return null;
102
+ }
103
+ //# sourceMappingURL=kotlinExports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kotlinExports.js","sourceRoot":"","sources":["../../../src/core/languages/kotlinExports.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
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 Kotlin. Walks `function_declaration` nodes
18
+ * (top-level functions and class methods). Methods inside `class Foo { fun m() }`
19
+ * are named `Foo.m`; top-level functions stay bare. Anonymous functions and
20
+ * lambdas are not extracted as separate entries; their decision points fold
21
+ * into the enclosing function (analogous to JS arrow/closure handling
22
+ * elsewhere in projscan).
23
+ *
24
+ * `when` expressions count one branch per non-else arm.
25
+ */
26
+ export declare function extractKotlinFunctions(root: TsNode): FunctionInfo[];
27
+ export {};