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.
- package/dist/core/applyFix.js +5 -46
- package/dist/core/applyFix.js.map +1 -1
- package/dist/core/embeddings.d.ts +9 -0
- package/dist/core/embeddings.js +45 -5
- package/dist/core/embeddings.js.map +1 -1
- package/dist/core/languages/LanguageAdapter.d.ts +1 -1
- package/dist/core/languages/cppAdapter.d.ts +2 -0
- package/dist/core/languages/cppAdapter.js +145 -0
- package/dist/core/languages/cppAdapter.js.map +1 -0
- package/dist/core/languages/cppCallSites.d.ts +13 -0
- package/dist/core/languages/cppCallSites.js +62 -0
- package/dist/core/languages/cppCallSites.js.map +1 -0
- package/dist/core/languages/cppCyclomatic.d.ts +25 -0
- package/dist/core/languages/cppCyclomatic.js +82 -0
- package/dist/core/languages/cppCyclomatic.js.map +1 -0
- package/dist/core/languages/cppExports.d.ts +13 -0
- package/dist/core/languages/cppExports.js +120 -0
- package/dist/core/languages/cppExports.js.map +1 -0
- package/dist/core/languages/cppFunctions.d.ts +30 -0
- package/dist/core/languages/cppFunctions.js +281 -0
- package/dist/core/languages/cppFunctions.js.map +1 -0
- package/dist/core/languages/cppImports.d.ts +25 -0
- package/dist/core/languages/cppImports.js +77 -0
- package/dist/core/languages/cppImports.js.map +1 -0
- package/dist/core/languages/cppManifests.d.ts +18 -0
- package/dist/core/languages/cppManifests.js +41 -0
- package/dist/core/languages/cppManifests.js.map +1 -0
- package/dist/core/languages/kotlinAdapter.d.ts +2 -0
- package/dist/core/languages/kotlinAdapter.js +141 -0
- package/dist/core/languages/kotlinAdapter.js.map +1 -0
- package/dist/core/languages/kotlinCallSites.d.ts +15 -0
- package/dist/core/languages/kotlinCallSites.js +62 -0
- package/dist/core/languages/kotlinCallSites.js.map +1 -0
- package/dist/core/languages/kotlinCyclomatic.d.ts +24 -0
- package/dist/core/languages/kotlinCyclomatic.js +54 -0
- package/dist/core/languages/kotlinCyclomatic.js.map +1 -0
- package/dist/core/languages/kotlinExports.d.ts +13 -0
- package/dist/core/languages/kotlinExports.js +103 -0
- package/dist/core/languages/kotlinExports.js.map +1 -0
- package/dist/core/languages/kotlinFunctions.d.ts +27 -0
- package/dist/core/languages/kotlinFunctions.js +147 -0
- package/dist/core/languages/kotlinFunctions.js.map +1 -0
- package/dist/core/languages/kotlinImports.d.ts +25 -0
- package/dist/core/languages/kotlinImports.js +74 -0
- package/dist/core/languages/kotlinImports.js.map +1 -0
- package/dist/core/languages/kotlinManifests.d.ts +20 -0
- package/dist/core/languages/kotlinManifests.js +46 -0
- package/dist/core/languages/kotlinManifests.js.map +1 -0
- package/dist/core/languages/registry.js +16 -1
- package/dist/core/languages/registry.js.map +1 -1
- package/dist/core/languages/swiftAdapter.d.ts +2 -0
- package/dist/core/languages/swiftAdapter.js +130 -0
- package/dist/core/languages/swiftAdapter.js.map +1 -0
- package/dist/core/languages/swiftCallSites.d.ts +14 -0
- package/dist/core/languages/swiftCallSites.js +60 -0
- package/dist/core/languages/swiftCallSites.js.map +1 -0
- package/dist/core/languages/swiftCyclomatic.d.ts +24 -0
- package/dist/core/languages/swiftCyclomatic.js +54 -0
- package/dist/core/languages/swiftCyclomatic.js.map +1 -0
- package/dist/core/languages/swiftExports.d.ts +13 -0
- package/dist/core/languages/swiftExports.js +95 -0
- package/dist/core/languages/swiftExports.js.map +1 -0
- package/dist/core/languages/swiftFunctions.d.ts +28 -0
- package/dist/core/languages/swiftFunctions.js +162 -0
- package/dist/core/languages/swiftFunctions.js.map +1 -0
- package/dist/core/languages/swiftImports.d.ts +26 -0
- package/dist/core/languages/swiftImports.js +45 -0
- package/dist/core/languages/swiftImports.js.map +1 -0
- package/dist/core/languages/swiftManifests.d.ts +17 -0
- package/dist/core/languages/swiftManifests.js +49 -0
- package/dist/core/languages/swiftManifests.js.map +1 -0
- package/dist/core/languages/treeSitterLoader.js +21 -1
- package/dist/core/languages/treeSitterLoader.js.map +1 -1
- package/dist/core/memory.d.ts +30 -0
- package/dist/core/memory.js +42 -0
- package/dist/core/memory.js.map +1 -1
- package/dist/core/session.d.ts +23 -4
- package/dist/core/session.js +28 -8
- package/dist/core/session.js.map +1 -1
- package/dist/core/taint.d.ts +17 -0
- package/dist/core/taint.js +19 -1
- package/dist/core/taint.js.map +1 -1
- package/dist/grammars/tree-sitter-cpp.wasm +0 -0
- package/dist/grammars/tree-sitter-kotlin.wasm +0 -0
- package/dist/grammars/tree-sitter-swift.wasm +0 -0
- package/dist/mcp/server.js +107 -11
- package/dist/mcp/server.js.map +1 -1
- package/dist/mcp/sessionTouchScanner.js +8 -2
- package/dist/mcp/sessionTouchScanner.js.map +1 -1
- package/dist/mcp/tools/_shared.d.ts +25 -1
- package/dist/mcp/tools/_shared.js.map +1 -1
- package/dist/mcp/tools/costSummary.d.ts +26 -0
- package/dist/mcp/tools/costSummary.js +152 -0
- package/dist/mcp/tools/costSummary.js.map +1 -0
- package/dist/mcp/tools/fixSuggest.js +23 -2
- package/dist/mcp/tools/fixSuggest.js.map +1 -1
- package/dist/mcp/tools/memory.js +37 -4
- package/dist/mcp/tools/memory.js.map +1 -1
- package/dist/mcp/tools/reviewWatch.d.ts +7 -0
- package/dist/mcp/tools/reviewWatch.js +228 -0
- package/dist/mcp/tools/reviewWatch.js.map +1 -0
- package/dist/mcp/tools.js +4 -0
- package/dist/mcp/tools.js.map +1 -1
- package/dist/tool-manifest.json +52 -4
- package/dist/utils/atomicWrite.d.ts +26 -0
- package/dist/utils/atomicWrite.js +69 -0
- package/dist/utils/atomicWrite.js.map +1 -0
- 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
|
-
|
|
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;
|
|
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,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 {};
|