projscan 1.6.2 → 1.8.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 (108) hide show
  1. package/dist/core/applyFix.js +5 -46
  2. package/dist/core/applyFix.js.map +1 -1
  3. package/dist/core/embeddings.d.ts +9 -0
  4. package/dist/core/embeddings.js +45 -5
  5. package/dist/core/embeddings.js.map +1 -1
  6. package/dist/core/languages/LanguageAdapter.d.ts +1 -1
  7. package/dist/core/languages/cppAdapter.d.ts +2 -0
  8. package/dist/core/languages/cppAdapter.js +145 -0
  9. package/dist/core/languages/cppAdapter.js.map +1 -0
  10. package/dist/core/languages/cppCallSites.d.ts +13 -0
  11. package/dist/core/languages/cppCallSites.js +62 -0
  12. package/dist/core/languages/cppCallSites.js.map +1 -0
  13. package/dist/core/languages/cppCyclomatic.d.ts +25 -0
  14. package/dist/core/languages/cppCyclomatic.js +82 -0
  15. package/dist/core/languages/cppCyclomatic.js.map +1 -0
  16. package/dist/core/languages/cppExports.d.ts +13 -0
  17. package/dist/core/languages/cppExports.js +120 -0
  18. package/dist/core/languages/cppExports.js.map +1 -0
  19. package/dist/core/languages/cppFunctions.d.ts +30 -0
  20. package/dist/core/languages/cppFunctions.js +281 -0
  21. package/dist/core/languages/cppFunctions.js.map +1 -0
  22. package/dist/core/languages/cppImports.d.ts +25 -0
  23. package/dist/core/languages/cppImports.js +77 -0
  24. package/dist/core/languages/cppImports.js.map +1 -0
  25. package/dist/core/languages/cppManifests.d.ts +18 -0
  26. package/dist/core/languages/cppManifests.js +41 -0
  27. package/dist/core/languages/cppManifests.js.map +1 -0
  28. package/dist/core/languages/kotlinAdapter.d.ts +2 -0
  29. package/dist/core/languages/kotlinAdapter.js +141 -0
  30. package/dist/core/languages/kotlinAdapter.js.map +1 -0
  31. package/dist/core/languages/kotlinCallSites.d.ts +15 -0
  32. package/dist/core/languages/kotlinCallSites.js +62 -0
  33. package/dist/core/languages/kotlinCallSites.js.map +1 -0
  34. package/dist/core/languages/kotlinCyclomatic.d.ts +24 -0
  35. package/dist/core/languages/kotlinCyclomatic.js +54 -0
  36. package/dist/core/languages/kotlinCyclomatic.js.map +1 -0
  37. package/dist/core/languages/kotlinExports.d.ts +13 -0
  38. package/dist/core/languages/kotlinExports.js +103 -0
  39. package/dist/core/languages/kotlinExports.js.map +1 -0
  40. package/dist/core/languages/kotlinFunctions.d.ts +27 -0
  41. package/dist/core/languages/kotlinFunctions.js +147 -0
  42. package/dist/core/languages/kotlinFunctions.js.map +1 -0
  43. package/dist/core/languages/kotlinImports.d.ts +25 -0
  44. package/dist/core/languages/kotlinImports.js +74 -0
  45. package/dist/core/languages/kotlinImports.js.map +1 -0
  46. package/dist/core/languages/kotlinManifests.d.ts +20 -0
  47. package/dist/core/languages/kotlinManifests.js +46 -0
  48. package/dist/core/languages/kotlinManifests.js.map +1 -0
  49. package/dist/core/languages/registry.js +16 -1
  50. package/dist/core/languages/registry.js.map +1 -1
  51. package/dist/core/languages/swiftAdapter.d.ts +2 -0
  52. package/dist/core/languages/swiftAdapter.js +130 -0
  53. package/dist/core/languages/swiftAdapter.js.map +1 -0
  54. package/dist/core/languages/swiftCallSites.d.ts +14 -0
  55. package/dist/core/languages/swiftCallSites.js +60 -0
  56. package/dist/core/languages/swiftCallSites.js.map +1 -0
  57. package/dist/core/languages/swiftCyclomatic.d.ts +24 -0
  58. package/dist/core/languages/swiftCyclomatic.js +54 -0
  59. package/dist/core/languages/swiftCyclomatic.js.map +1 -0
  60. package/dist/core/languages/swiftExports.d.ts +13 -0
  61. package/dist/core/languages/swiftExports.js +95 -0
  62. package/dist/core/languages/swiftExports.js.map +1 -0
  63. package/dist/core/languages/swiftFunctions.d.ts +28 -0
  64. package/dist/core/languages/swiftFunctions.js +162 -0
  65. package/dist/core/languages/swiftFunctions.js.map +1 -0
  66. package/dist/core/languages/swiftImports.d.ts +26 -0
  67. package/dist/core/languages/swiftImports.js +45 -0
  68. package/dist/core/languages/swiftImports.js.map +1 -0
  69. package/dist/core/languages/swiftManifests.d.ts +17 -0
  70. package/dist/core/languages/swiftManifests.js +49 -0
  71. package/dist/core/languages/swiftManifests.js.map +1 -0
  72. package/dist/core/languages/treeSitterLoader.js +21 -1
  73. package/dist/core/languages/treeSitterLoader.js.map +1 -1
  74. package/dist/core/memory.d.ts +30 -0
  75. package/dist/core/memory.js +42 -0
  76. package/dist/core/memory.js.map +1 -1
  77. package/dist/core/session.d.ts +23 -4
  78. package/dist/core/session.js +28 -8
  79. package/dist/core/session.js.map +1 -1
  80. package/dist/core/taint.d.ts +17 -0
  81. package/dist/core/taint.js +19 -1
  82. package/dist/core/taint.js.map +1 -1
  83. package/dist/grammars/tree-sitter-cpp.wasm +0 -0
  84. package/dist/grammars/tree-sitter-kotlin.wasm +0 -0
  85. package/dist/grammars/tree-sitter-swift.wasm +0 -0
  86. package/dist/mcp/server.js +107 -11
  87. package/dist/mcp/server.js.map +1 -1
  88. package/dist/mcp/sessionTouchScanner.js +8 -2
  89. package/dist/mcp/sessionTouchScanner.js.map +1 -1
  90. package/dist/mcp/tools/_shared.d.ts +25 -1
  91. package/dist/mcp/tools/_shared.js.map +1 -1
  92. package/dist/mcp/tools/costSummary.d.ts +26 -0
  93. package/dist/mcp/tools/costSummary.js +152 -0
  94. package/dist/mcp/tools/costSummary.js.map +1 -0
  95. package/dist/mcp/tools/fixSuggest.js +23 -2
  96. package/dist/mcp/tools/fixSuggest.js.map +1 -1
  97. package/dist/mcp/tools/memory.js +37 -4
  98. package/dist/mcp/tools/memory.js.map +1 -1
  99. package/dist/mcp/tools/reviewWatch.d.ts +7 -0
  100. package/dist/mcp/tools/reviewWatch.js +228 -0
  101. package/dist/mcp/tools/reviewWatch.js.map +1 -0
  102. package/dist/mcp/tools.js +4 -0
  103. package/dist/mcp/tools.js.map +1 -1
  104. package/dist/tool-manifest.json +52 -4
  105. package/dist/utils/atomicWrite.d.ts +26 -0
  106. package/dist/utils/atomicWrite.js +69 -0
  107. package/dist/utils/atomicWrite.js.map +1 -0
  108. package/package.json +6 -2
@@ -0,0 +1,74 @@
1
+ /**
2
+ * Extract Kotlin `import` statements from a tree-sitter-kotlin AST.
3
+ *
4
+ * Handled forms:
5
+ * import com.foo.Bar → source = "com.foo.Bar"
6
+ * import com.foo.* → source = "com.foo.*"
7
+ * import com.foo.Bar as Baz → source = "com.foo.Bar", alias = "Baz"
8
+ *
9
+ * Kotlin doesn't have an explicit "re-export" notion at the import site
10
+ * (re-exports are done via top-level `typealias` / `val` exposing imported
11
+ * symbols). All imports are flagged as `static`.
12
+ */
13
+ export function extractKotlinImports(root) {
14
+ const imports = [];
15
+ walk(root, (n) => {
16
+ if (n.type !== 'import_header')
17
+ return;
18
+ const source = readImportPath(n);
19
+ if (!source)
20
+ return;
21
+ const alias = readAlias(n);
22
+ imports.push({
23
+ source,
24
+ kind: 'static',
25
+ specifiers: alias ? [alias] : [],
26
+ typeOnly: false,
27
+ line: n.startPosition.row + 1,
28
+ });
29
+ });
30
+ return imports;
31
+ }
32
+ function readImportPath(node) {
33
+ const segments = [];
34
+ collectIdentifiers(node, segments, false);
35
+ if (node.text.includes('.*'))
36
+ segments.push('*');
37
+ return segments.join('.');
38
+ }
39
+ function collectIdentifiers(node, out, insideAlias) {
40
+ if (insideAlias)
41
+ return;
42
+ if (node.type === 'import_alias')
43
+ return;
44
+ if (node.type === 'identifier' ||
45
+ node.type === 'simple_identifier' ||
46
+ node.type === 'type_identifier') {
47
+ out.push(node.text);
48
+ return;
49
+ }
50
+ for (const c of node.namedChildren)
51
+ collectIdentifiers(c, out, insideAlias);
52
+ }
53
+ function readAlias(node) {
54
+ for (const c of node.namedChildren) {
55
+ if (c.type !== 'import_alias')
56
+ continue;
57
+ for (const sub of c.namedChildren) {
58
+ if (sub.type === 'type_identifier' || sub.type === 'identifier' || sub.type === 'simple_identifier') {
59
+ return sub.text;
60
+ }
61
+ }
62
+ // Fallback: last token of `as <name>` text
63
+ const m = /\bas\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(c.text);
64
+ if (m)
65
+ return m[1];
66
+ }
67
+ return null;
68
+ }
69
+ function walk(node, visit) {
70
+ visit(node);
71
+ for (const child of node.namedChildren)
72
+ walk(child, visit);
73
+ }
74
+ //# sourceMappingURL=kotlinImports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kotlinImports.js","sourceRoot":"","sources":["../../../src/core/languages/kotlinImports.ts"],"names":[],"mappings":"AAUA;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,OAAO,GAAgB,EAAE,CAAC;IAChC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE;QACf,IAAI,CAAC,CAAC,IAAI,KAAK,eAAe;YAAE,OAAO;QACvC,MAAM,MAAM,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC;QACjC,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,CAAC;QAC3B,OAAO,CAAC,IAAI,CAAC;YACX,MAAM;YACN,IAAI,EAAE,QAAQ;YACd,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;YAChC,QAAQ,EAAE,KAAK;YACf,IAAI,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,GAAG,CAAC;SAC9B,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,cAAc,CAAC,IAAY;IAClC,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,kBAAkB,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC;IAC1C,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACjD,OAAO,QAAQ,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,SAAS,kBAAkB,CAAC,IAAY,EAAE,GAAa,EAAE,WAAoB;IAC3E,IAAI,WAAW;QAAE,OAAO;IACxB,IAAI,IAAI,CAAC,IAAI,KAAK,cAAc;QAAE,OAAO;IACzC,IACE,IAAI,CAAC,IAAI,KAAK,YAAY;QAC1B,IAAI,CAAC,IAAI,KAAK,mBAAmB;QACjC,IAAI,CAAC,IAAI,KAAK,iBAAiB,EAC/B,CAAC;QACD,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpB,OAAO;IACT,CAAC;IACD,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa;QAAE,kBAAkB,CAAC,CAAC,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,SAAS,CAAC,IAAY;IAC7B,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,IAAI,CAAC,CAAC,IAAI,KAAK,cAAc;YAAE,SAAS;QACxC,KAAK,MAAM,GAAG,IAAI,CAAC,CAAC,aAAa,EAAE,CAAC;YAClC,IAAI,GAAG,CAAC,IAAI,KAAK,iBAAiB,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,IAAI,GAAG,CAAC,IAAI,KAAK,mBAAmB,EAAE,CAAC;gBACpG,OAAO,GAAG,CAAC,IAAI,CAAC;YAClB,CAAC;QACH,CAAC;QACD,2CAA2C;QAC3C,MAAM,CAAC,GAAG,iCAAiC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;QACzD,IAAI,CAAC;YAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,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,20 @@
1
+ import type { FileEntry } from '../../types.js';
2
+ export interface KotlinProjectInfo {
3
+ /**
4
+ * Detected package roots — directories under which Kotlin source files
5
+ * live. For Gradle / Maven projects this is typically `src/main/kotlin`
6
+ * and / or `src/test/kotlin`. Imports like `import com.foo.Bar` resolve
7
+ * against each root.
8
+ */
9
+ packageRoots: string[];
10
+ /** Did we see a Gradle build file? Used for diagnostics only. */
11
+ hasGradle: boolean;
12
+ }
13
+ /**
14
+ * Detect Kotlin source roots. We don't parse Gradle / Maven manifests; we
15
+ * just check for the conventional `src/main/kotlin` layout and fall back
16
+ * to surveying the .kt file paths to find any prefix that looks like a
17
+ * package root (a directory whose first .kt file's `package` declaration
18
+ * matches its sub-path).
19
+ */
20
+ export declare function detectKotlinProject(rootPath: string, files: FileEntry[]): Promise<KotlinProjectInfo | null>;
@@ -0,0 +1,46 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ const COMMON_KOTLIN_ROOTS = [
4
+ 'src/main/kotlin',
5
+ 'src/test/kotlin',
6
+ 'src/main/java', // Kotlin / Java mixed projects
7
+ 'src/test/java',
8
+ 'src',
9
+ ];
10
+ /**
11
+ * Detect Kotlin source roots. We don't parse Gradle / Maven manifests; we
12
+ * just check for the conventional `src/main/kotlin` layout and fall back
13
+ * to surveying the .kt file paths to find any prefix that looks like a
14
+ * package root (a directory whose first .kt file's `package` declaration
15
+ * matches its sub-path).
16
+ */
17
+ export async function detectKotlinProject(rootPath, files) {
18
+ const ktFiles = files.filter((f) => f.relativePath.endsWith('.kt') || f.relativePath.endsWith('.kts'));
19
+ if (ktFiles.length === 0)
20
+ return null;
21
+ const hasGradle = await hasGradleManifest(rootPath);
22
+ const packageRoots = [];
23
+ for (const candidate of COMMON_KOTLIN_ROOTS) {
24
+ if (ktFiles.some((f) => f.relativePath.startsWith(candidate + '/'))) {
25
+ packageRoots.push(candidate);
26
+ }
27
+ }
28
+ // Fallback: bare repo with .kt files at the root.
29
+ if (packageRoots.length === 0)
30
+ packageRoots.push('.');
31
+ return { packageRoots, hasGradle };
32
+ }
33
+ async function hasGradleManifest(rootPath) {
34
+ const candidates = ['build.gradle', 'build.gradle.kts', 'settings.gradle', 'settings.gradle.kts', 'pom.xml'];
35
+ for (const c of candidates) {
36
+ try {
37
+ await fs.access(path.join(rootPath, c));
38
+ return true;
39
+ }
40
+ catch {
41
+ // try next
42
+ }
43
+ }
44
+ return false;
45
+ }
46
+ //# sourceMappingURL=kotlinManifests.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kotlinManifests.js","sourceRoot":"","sources":["../../../src/core/languages/kotlinManifests.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAe7B,MAAM,mBAAmB,GAAG;IAC1B,iBAAiB;IACjB,iBAAiB;IACjB,eAAe,EAAE,+BAA+B;IAChD,eAAe;IACf,KAAK;CACN,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,QAAgB,EAChB,KAAkB;IAElB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CACzE,CAAC;IACF,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IAEtC,MAAM,SAAS,GAAG,MAAM,iBAAiB,CAAC,QAAQ,CAAC,CAAC;IACpD,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,MAAM,SAAS,IAAI,mBAAmB,EAAE,CAAC;QAC5C,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,UAAU,CAAC,SAAS,GAAG,GAAG,CAAC,CAAC,EAAE,CAAC;YACpE,YAAY,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;IACH,CAAC;IACD,kDAAkD;IAClD,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACtD,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC;AACrC,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,QAAgB;IAC/C,MAAM,UAAU,GAAG,CAAC,cAAc,EAAE,kBAAkB,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,SAAS,CAAC,CAAC;IAC7G,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC;YACxC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,WAAW;QACb,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
@@ -7,7 +7,22 @@ import { rubyAdapter } from './rubyAdapter.js';
7
7
  import { rustAdapter } from './rustAdapter.js';
8
8
  import { phpAdapter } from './phpAdapter.js';
9
9
  import { csharpAdapter } from './csharpAdapter.js';
10
- const adapters = [javascriptAdapter, pythonAdapter, goAdapter, javaAdapter, rubyAdapter, rustAdapter, phpAdapter, csharpAdapter];
10
+ import { kotlinAdapter } from './kotlinAdapter.js';
11
+ import { swiftAdapter } from './swiftAdapter.js';
12
+ import { cppAdapter } from './cppAdapter.js';
13
+ const adapters = [
14
+ javascriptAdapter,
15
+ pythonAdapter,
16
+ goAdapter,
17
+ javaAdapter,
18
+ rubyAdapter,
19
+ rustAdapter,
20
+ phpAdapter,
21
+ csharpAdapter,
22
+ kotlinAdapter,
23
+ swiftAdapter,
24
+ cppAdapter,
25
+ ];
11
26
  const byExtension = new Map();
12
27
  function rebuildIndex() {
13
28
  byExtension.clear();
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/core/languages/registry.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGnD,MAAM,QAAQ,GAAsB,CAAC,iBAAiB,EAAE,aAAa,EAAE,SAAS,EAAE,WAAW,EAAE,WAAW,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,CAAC,CAAC;AACpJ,MAAM,WAAW,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEvD,SAAS,YAAY;IACnB,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACrC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;AACH,CAAC;AACD,YAAY,EAAE,CAAC;AAEf,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,YAAY,EAAE,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,QAAQ,CAAC;AAClB,CAAC"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/core/languages/registry.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,OAAO,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAG7C,MAAM,QAAQ,GAAsB;IAClC,iBAAiB;IACjB,aAAa;IACb,SAAS;IACT,WAAW;IACX,WAAW;IACX,WAAW;IACX,UAAU;IACV,aAAa;IACb,aAAa;IACb,YAAY;IACZ,UAAU;CACX,CAAC;AACF,MAAM,WAAW,GAAG,IAAI,GAAG,EAA2B,CAAC;AAEvD,SAAS,YAAY;IACnB,WAAW,CAAC,KAAK,EAAE,CAAC;IACpB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACrC,WAAW,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;AACH,CAAC;AACD,YAAY,EAAE,CAAC;AAEf,MAAM,UAAU,eAAe,CAAC,OAAwB;IACtD,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;QAChC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACvB,YAAY,EAAE,CAAC;IACjB,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,QAAgB;IAC5C,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,QAAgB;IACjD,OAAO,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -0,0 +1,2 @@
1
+ import type { LanguageAdapter } from './LanguageAdapter.js';
2
+ export declare const swiftAdapter: LanguageAdapter;
@@ -0,0 +1,130 @@
1
+ import path from 'node:path';
2
+ import { createParserFor } from './treeSitterLoader.js';
3
+ import { extractSwiftImports } from './swiftImports.js';
4
+ import { extractSwiftExports } from './swiftExports.js';
5
+ import { extractSwiftCyclomatic } from './swiftCyclomatic.js';
6
+ import { extractSwiftFunctions } from './swiftFunctions.js';
7
+ import { extractSwiftCallSites } from './swiftCallSites.js';
8
+ import { detectSwiftProject } from './swiftManifests.js';
9
+ const SWIFT_EXTENSIONS = new Set(['.swift']);
10
+ const MAX_SWIFT_FILE = 1024 * 1024;
11
+ let parserPromise = null;
12
+ async function getParser() {
13
+ if (!parserPromise)
14
+ parserPromise = createParserFor('tree-sitter-swift.wasm');
15
+ return parserPromise;
16
+ }
17
+ export const swiftAdapter = {
18
+ id: 'swift',
19
+ extensions: SWIFT_EXTENSIONS,
20
+ sourceExtensions: SWIFT_EXTENSIONS,
21
+ barrelBasenames: new Set(),
22
+ maxFileSize: MAX_SWIFT_FILE,
23
+ async parse(_filePath, content) {
24
+ try {
25
+ const parser = await getParser();
26
+ const tree = parser.parse(content);
27
+ if (!tree || !tree.rootNode) {
28
+ return {
29
+ ok: false,
30
+ reason: 'tree-sitter returned null tree',
31
+ imports: [],
32
+ exports: [],
33
+ callSites: [],
34
+ lineCount: content ? content.split('\n').length : 0,
35
+ cyclomaticComplexity: 0,
36
+ functions: [],
37
+ };
38
+ }
39
+ const root = tree.rootNode;
40
+ const imports = extractSwiftImports(root);
41
+ const exports = extractSwiftExports(root);
42
+ const cyclomaticComplexity = extractSwiftCyclomatic(root);
43
+ const callSites = extractSwiftCallSites(root);
44
+ const functions = extractSwiftFunctions(root);
45
+ return {
46
+ ok: true,
47
+ imports,
48
+ exports,
49
+ callSites,
50
+ lineCount: content ? content.split('\n').length : 0,
51
+ cyclomaticComplexity,
52
+ functions,
53
+ };
54
+ }
55
+ catch (err) {
56
+ const msg = err instanceof Error ? err.message : String(err);
57
+ return {
58
+ ok: false,
59
+ reason: `swift parse failure: ${msg.slice(0, 120)}`,
60
+ imports: [],
61
+ exports: [],
62
+ callSites: [],
63
+ lineCount: content ? content.split('\n').length : 0,
64
+ cyclomaticComplexity: 0,
65
+ functions: [],
66
+ };
67
+ }
68
+ },
69
+ resolveImport(_importingFile, source, graphFiles, context) {
70
+ return resolveSwiftImport(source, graphFiles, context);
71
+ },
72
+ toPackageName(source) {
73
+ if (!source)
74
+ return null;
75
+ return source.split('.')[0] || null;
76
+ },
77
+ async preparePackageRoots(rootPath, files) {
78
+ const info = await detectSwiftProject(rootPath, files);
79
+ return {
80
+ packageRoots: info ? info.packageRoots.map((r) => path.relative(rootPath, path.join(rootPath, r)) || '.') : [],
81
+ meta: info ? { swiftProject: info } : undefined,
82
+ };
83
+ },
84
+ };
85
+ /**
86
+ * Resolve a Swift `import Foo` to a repo-local file. Swift imports bind a
87
+ * module name, not a file path; for SwiftPM-style projects the convention
88
+ * is one Sources/<ModuleName>/ directory per module. We probe for any
89
+ * .swift file under <root>/<source-root>/<ModuleName>/ that exists in the
90
+ * graph and pick the first match (typically <ModuleName>.swift if present,
91
+ * otherwise the lexicographically first file). For sub-module imports
92
+ * (`import Foo.Bar`) we look for Bar.swift inside Foo's directory.
93
+ */
94
+ function resolveSwiftImport(source, graphFiles, context) {
95
+ if (!source)
96
+ return null;
97
+ const project = context.meta?.swiftProject;
98
+ const packageRoots = context.packageRoots ?? project?.packageRoots ?? [];
99
+ if (packageRoots.length === 0)
100
+ return null;
101
+ const segments = source.split('.').filter(Boolean);
102
+ if (segments.length === 0)
103
+ return null;
104
+ for (const root of packageRoots) {
105
+ const rootSegs = root === '.' || root === '' ? [] : root.split('/').filter(Boolean);
106
+ if (segments.length >= 2) {
107
+ const fileName = segments[segments.length - 1];
108
+ const dirSegs = [...rootSegs, ...segments.slice(0, -1)];
109
+ const asFile = [...dirSegs, `${fileName}.swift`].join('/');
110
+ if (graphFiles.has(asFile))
111
+ return asFile;
112
+ }
113
+ const moduleDir = [...rootSegs, ...segments].join('/');
114
+ const preferred = [...rootSegs, ...segments, `${segments[segments.length - 1]}.swift`].join('/');
115
+ if (graphFiles.has(preferred))
116
+ return preferred;
117
+ const prefix = moduleDir + '/';
118
+ let firstHit = null;
119
+ for (const key of graphFiles.keys()) {
120
+ if (key.startsWith(prefix) && key.endsWith('.swift')) {
121
+ if (firstHit === null || key < firstHit)
122
+ firstHit = key;
123
+ }
124
+ }
125
+ if (firstHit)
126
+ return firstHit;
127
+ }
128
+ return null;
129
+ }
130
+ //# sourceMappingURL=swiftAdapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swiftAdapter.js","sourceRoot":"","sources":["../../../src/core/languages/swiftAdapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,14 @@
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-swift AST. Mirrors the existing adapter behaviour: dedupe
10
+ * names, strip qualification so `obj.foo()` and `foo()` both produce
11
+ * `foo`. Initialiser calls (`Foo()`) surface as `Foo`.
12
+ */
13
+ export declare function extractSwiftCallSites(root: TsNode): string[];
14
+ export {};
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Extract the called identifier from each `call_expression` in a
3
+ * tree-sitter-swift AST. Mirrors the existing adapter behaviour: dedupe
4
+ * names, strip qualification so `obj.foo()` and `foo()` both produce
5
+ * `foo`. Initialiser calls (`Foo()`) surface as `Foo`.
6
+ */
7
+ export function extractSwiftCallSites(root) {
8
+ const seen = new Set();
9
+ walk(root, (n) => {
10
+ if (n.type !== 'call_expression')
11
+ return;
12
+ const fn = pickCallee(n);
13
+ if (!fn)
14
+ return;
15
+ const name = bareName(fn);
16
+ if (name)
17
+ seen.add(name);
18
+ });
19
+ return [...seen];
20
+ }
21
+ function pickCallee(node) {
22
+ if (node.childForFieldName) {
23
+ const f = node.childForFieldName('function');
24
+ if (f)
25
+ return f;
26
+ }
27
+ return node.namedChildren[0] ?? null;
28
+ }
29
+ function bareName(node) {
30
+ switch (node.type) {
31
+ case 'simple_identifier':
32
+ case 'identifier':
33
+ case 'type_identifier':
34
+ return node.text;
35
+ case 'navigation_expression': {
36
+ const last = node.namedChildren[node.namedChildren.length - 1];
37
+ return last ? bareName(last) : null;
38
+ }
39
+ case 'navigation_suffix': {
40
+ for (const c of node.namedChildren) {
41
+ const n = bareName(c);
42
+ if (n)
43
+ return n;
44
+ }
45
+ return null;
46
+ }
47
+ case 'call_expression': {
48
+ const inner = pickCallee(node);
49
+ return inner ? bareName(inner) : null;
50
+ }
51
+ default:
52
+ return null;
53
+ }
54
+ }
55
+ function walk(node, visit) {
56
+ visit(node);
57
+ for (const child of node.namedChildren)
58
+ walk(child, visit);
59
+ }
60
+ //# sourceMappingURL=swiftCallSites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swiftCallSites.js","sourceRoot":"","sources":["../../../src/core/languages/swiftCallSites.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,IAAY;IAChD,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,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-swift AST.
8
+ *
9
+ * Decision points in Swift:
10
+ * if_statement +1
11
+ * guard_statement +1 (short-circuits to its `else`)
12
+ * for_statement +1
13
+ * while_statement +1
14
+ * repeat_while_statement +1
15
+ * do_statement +1
16
+ * catch_block / catch_clause +1 each
17
+ * switch_entry (non-default) +1
18
+ * conjunction_expression +1 (Swift's `&&`)
19
+ * disjunction_expression +1 (Swift's `||`)
20
+ *
21
+ * The optional-chaining `?.` and nil-coalescing `??` operators do NOT count.
22
+ */
23
+ export declare function extractSwiftCyclomatic(root: TsNode): number;
24
+ export {};
@@ -0,0 +1,54 @@
1
+ /**
2
+ * File-level McCabe cyclomatic complexity for a tree-sitter-swift AST.
3
+ *
4
+ * Decision points in Swift:
5
+ * if_statement +1
6
+ * guard_statement +1 (short-circuits to its `else`)
7
+ * for_statement +1
8
+ * while_statement +1
9
+ * repeat_while_statement +1
10
+ * do_statement +1
11
+ * catch_block / catch_clause +1 each
12
+ * switch_entry (non-default) +1
13
+ * conjunction_expression +1 (Swift's `&&`)
14
+ * disjunction_expression +1 (Swift's `||`)
15
+ *
16
+ * The optional-chaining `?.` and nil-coalescing `??` operators do NOT count.
17
+ */
18
+ export function extractSwiftCyclomatic(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 'guard_statement':
30
+ case 'for_statement':
31
+ case 'while_statement':
32
+ case 'repeat_while_statement':
33
+ case 'do_statement':
34
+ case 'catch_block':
35
+ case 'catch_clause':
36
+ case 'conjunction_expression':
37
+ case 'disjunction_expression':
38
+ return true;
39
+ case 'switch_entry': {
40
+ // Default arm has no `switch_pattern` / `case_label` child; non-default
41
+ // always does. Structural detection is more reliable than text-regex.
42
+ const isDefault = !n.namedChildren.some((c) => c.type === 'switch_pattern' || c.type === 'case_label');
43
+ return !isDefault;
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=swiftCyclomatic.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swiftCyclomatic.js","sourceRoot":"","sources":["../../../src/core/languages/swiftCyclomatic.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,sBAAsB,CAAC,IAAY;IACjD,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,iBAAiB,CAAC;QACvB,KAAK,eAAe,CAAC;QACrB,KAAK,iBAAiB,CAAC;QACvB,KAAK,wBAAwB,CAAC;QAC9B,KAAK,cAAc,CAAC;QACpB,KAAK,aAAa,CAAC;QACnB,KAAK,cAAc,CAAC;QACpB,KAAK,wBAAwB,CAAC;QAC9B,KAAK,wBAAwB;YAC3B,OAAO,IAAI,CAAC;QACd,KAAK,cAAc,CAAC,CAAC,CAAC;YACpB,wEAAwE;YACxE,sEAAsE;YACtE,MAAM,SAAS,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,IAAI,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;YACvG,OAAO,CAAC,SAAS,CAAC;QACpB,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 extractSwiftExports(root: TsNode): AstExport[];
13
+ export {};
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Extract Swift top-level declarations as exports. Swift's default
3
+ * visibility is `internal` (visible within the module). For graph
4
+ * purposes we treat everything that is NOT explicitly `private` or
5
+ * `fileprivate` as exported — module-internal symbols still participate
6
+ * in cross-file resolution within the module.
7
+ *
8
+ * Kinds:
9
+ * func foo() → function
10
+ * class Foo / struct Foo → class
11
+ * protocol Foo → interface
12
+ * enum Color → enum
13
+ * typealias Bar = ... → type
14
+ * let / var x → variable
15
+ * actor Foo → class
16
+ */
17
+ const EXPORT_NODE_TO_KIND = {
18
+ function_declaration: 'function',
19
+ class_declaration: 'class',
20
+ protocol_declaration: 'interface',
21
+ typealias_declaration: 'type',
22
+ property_declaration: 'variable',
23
+ };
24
+ export function extractSwiftExports(root) {
25
+ const exports = [];
26
+ for (const child of root.namedChildren) {
27
+ visitTopLevel(child, exports);
28
+ }
29
+ return exports;
30
+ }
31
+ function visitTopLevel(node, out) {
32
+ if (node.type === 'class_declaration') {
33
+ if (isHidden(node))
34
+ return;
35
+ const name = nameOf(node);
36
+ if (!name)
37
+ return;
38
+ const head = headerText(node);
39
+ let kind = 'class';
40
+ if (/\benum\b/.test(head))
41
+ kind = 'enum';
42
+ out.push({ name, kind, typeOnly: false, line: node.startPosition.row + 1 });
43
+ return;
44
+ }
45
+ const kind = EXPORT_NODE_TO_KIND[node.type];
46
+ if (!kind) {
47
+ for (const c of node.namedChildren)
48
+ visitTopLevel(c, out);
49
+ return;
50
+ }
51
+ if (isHidden(node))
52
+ return;
53
+ const name = nameOf(node);
54
+ if (!name)
55
+ return;
56
+ out.push({ name, kind, typeOnly: false, line: node.startPosition.row + 1 });
57
+ }
58
+ function headerText(node) {
59
+ const idx = node.text.indexOf('{');
60
+ return idx >= 0 ? node.text.slice(0, idx) : node.text;
61
+ }
62
+ function isHidden(node) {
63
+ for (const c of node.namedChildren) {
64
+ if (c.type === 'modifiers' || c.type === 'modifier_list') {
65
+ for (const m of c.namedChildren) {
66
+ const t = m.text.trim();
67
+ if (t === 'private' || t === 'fileprivate')
68
+ return true;
69
+ }
70
+ }
71
+ if (c.type === 'visibility_modifier') {
72
+ const t = c.text.trim();
73
+ if (t === 'private' || t === 'fileprivate')
74
+ return true;
75
+ }
76
+ }
77
+ return false;
78
+ }
79
+ function nameOf(node) {
80
+ if (node.childForFieldName) {
81
+ const id = node.childForFieldName('name');
82
+ if (id && id.text)
83
+ return id.text;
84
+ }
85
+ for (const c of node.namedChildren) {
86
+ if (c.type === 'simple_identifier' || c.type === 'identifier' || c.type === 'type_identifier') {
87
+ return c.text;
88
+ }
89
+ }
90
+ const m = /\b(let|var)\s+([A-Za-z_][A-Za-z0-9_]*)/.exec(node.text);
91
+ if (m)
92
+ return m[2];
93
+ return null;
94
+ }
95
+ //# sourceMappingURL=swiftExports.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swiftExports.js","sourceRoot":"","sources":["../../../src/core/languages/swiftExports.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,28 @@
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 Swift. Walks `function_declaration` nodes
18
+ * (top-level + class/struct/protocol/extension methods). Methods inside
19
+ * `class Foo { func m() }` are named `Foo.m`. Closures and trailing-closure
20
+ * blocks aren't extracted as separate functions; their decision points
21
+ * fold into the enclosing function (matches projscan's convention for
22
+ * Rust closures and Go func literals).
23
+ *
24
+ * `switch` cases each count as +1; the `default` arm does not. Optional
25
+ * chaining (`?.`) and nil-coalescing (`??`) are NOT counted.
26
+ */
27
+ export declare function extractSwiftFunctions(root: TsNode): FunctionInfo[];
28
+ export {};