@liendev/parser 0.46.0 → 0.48.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.
@@ -8,6 +8,8 @@ import { goDefinition } from './go.js';
8
8
  import { javaDefinition } from './java.js';
9
9
  import { csharpDefinition } from './csharp.js';
10
10
  import { rubyDefinition } from './ruby.js';
11
+ import { kotlinDefinition } from './kotlin.js';
12
+ import { swiftDefinition } from './swift.js';
11
13
  /**
12
14
  * All registered language definitions.
13
15
  * To add a new language, create a definition file and add it here.
@@ -22,6 +24,8 @@ const definitions = [
22
24
  javaDefinition,
23
25
  csharpDefinition,
24
26
  rubyDefinition,
27
+ kotlinDefinition,
28
+ swiftDefinition,
25
29
  ];
26
30
  /**
27
31
  * Canonical list of supported language IDs.
@@ -38,6 +42,8 @@ export const LANGUAGE_IDS = [
38
42
  'java',
39
43
  'csharp',
40
44
  'ruby',
45
+ 'kotlin',
46
+ 'swift',
41
47
  ];
42
48
  /**
43
49
  * Registry keyed by language id.
@@ -1 +1 @@
1
- {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/ast/languages/registry.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/ast/languages/registry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAE/B,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iBAAiB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAE7C;;;GAGG;AACH,MAAM,WAAW,GAAyB;IACxC,oBAAoB;IACpB,oBAAoB;IACpB,aAAa;IACb,gBAAgB;IAChB,cAAc;IACd,YAAY;IACZ,cAAc;IACd,gBAAgB;IAChB,cAAc;IACd,gBAAgB;IAChB,eAAe;CAChB,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,YAAY;IACZ,YAAY;IACZ,KAAK;IACL,QAAQ;IACR,MAAM;IACN,IAAI;IACJ,MAAM;IACN,QAAQ;IACR,MAAM;IACN,QAAQ;IACR,OAAO;CACC,CAAC;AAGX;;GAEG;AACH,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAA8B,CAAC;AAC/D,MAAM,YAAY,GAAG,IAAI,GAAG,EAA6B,CAAC;AAE1D,KAAK,MAAM,GAAG,IAAI,WAAW,EAAE,CAAC;IAC9B,IAAI,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,sCAAsC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,gBAAgB,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,EAAE,GAAG,CAAC,CAAC;IAElC,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,UAAU,EAAE,CAAC;QACjC,IAAI,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,KAAK,CACb,wBAAwB,GAAG,oBAAoB,GAAG,CAAC,EAAE,0BAA0B,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CACzG,CAAC;QACJ,CAAC;QACD,YAAY,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IAChC,CAAC;AACH,CAAC;AAED,wEAAwE;AACxE,IAAI,IAAI,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,MAAM,EAAE,CAAC;IACvD,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3F,MAAM,IAAI,KAAK,CAAC,4CAA4C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAClF,CAAC;AACD,KAAK,MAAM,EAAE,IAAI,YAAY,EAAE,CAAC;IAC9B,IAAI,CAAC,gBAAgB,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,aAAa,EAAE,4DAA4D,CAAC,CAAC;IAC/F,CAAC;AACH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,QAA2B;IACrD,MAAM,GAAG,GAAG,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAC3C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,MAAM,IAAI,KAAK,CAAC,0CAA0C,QAAQ,EAAE,CAAC,CAAC;IACxE,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,MAAM,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACrD,OAAO,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC;AACvC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,QAAgB;IAC7C,OAAO,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,WAAW,CAAC,KAAK,EAAE,CAAC;AAC7B,CAAC;AAED;;;GAGG;AACH,IAAI,cAAc,GAAoB,IAAI,CAAC;AAE3C,MAAM,UAAU,sBAAsB;IACpC,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,cAAc,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAC1D,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC"}
@@ -0,0 +1,98 @@
1
+ import type Parser from 'tree-sitter';
2
+ import type { SymbolInfo } from '../types.js';
3
+ import type { LanguageDefinition } from './types.js';
4
+ import type { LanguageTraverser, DeclarationFunctionInfo } from '../traversers/types.js';
5
+ import type { LanguageExportExtractor, LanguageImportExtractor, LanguageSymbolExtractor } from '../extractors/types.js';
6
+ /**
7
+ * Swift AST traverser.
8
+ *
9
+ * Functions/methods/initializers live inside `class_declaration` (which covers
10
+ * class / struct / actor / enum / extension) and `protocol_declaration` bodies
11
+ * (`class_body` / `enum_class_body` / `protocol_body`). Closures can appear as
12
+ * property initializers (`let handler = { … }`).
13
+ */
14
+ export declare class SwiftTraverser implements LanguageTraverser {
15
+ targetNodeTypes: string[];
16
+ containerTypes: string[];
17
+ declarationTypes: string[];
18
+ functionTypes: string[];
19
+ shouldExtractChildren(node: Parser.SyntaxNode): boolean;
20
+ isDeclarationWithFunction(node: Parser.SyntaxNode): boolean;
21
+ getContainerBody(node: Parser.SyntaxNode): Parser.SyntaxNode | null;
22
+ shouldTraverseChildren(node: Parser.SyntaxNode): boolean;
23
+ findParentContainerName(node: Parser.SyntaxNode): string | undefined;
24
+ findFunctionInDeclaration(node: Parser.SyntaxNode): DeclarationFunctionInfo;
25
+ }
26
+ /**
27
+ * Swift export extractor.
28
+ *
29
+ * Swift has no `export` keyword. Top-level declarations and (non-private/
30
+ * fileprivate) members form the file's API surface. Protocol members are
31
+ * implicitly part of the protocol's surface.
32
+ */
33
+ export declare class SwiftExportExtractor implements LanguageExportExtractor {
34
+ extractExports(rootNode: Parser.SyntaxNode): string[];
35
+ private extractFromNode;
36
+ private extractMembers;
37
+ }
38
+ /**
39
+ * Swift import extractor.
40
+ *
41
+ * Handles `import Foundation`, dotted `import Combine.Just`, and import-kind
42
+ * forms (`import struct Combine.Just` — the `struct`/`class`/… keyword is an
43
+ * anonymous token and is ignored; the module path is what matters). Only the
44
+ * `Swift` stdlib module is filtered out.
45
+ */
46
+ export declare class SwiftImportExtractor implements LanguageImportExtractor {
47
+ readonly importNodeTypes: string[];
48
+ extractImportPath(node: Parser.SyntaxNode): string | null;
49
+ processImportSymbols(node: Parser.SyntaxNode): {
50
+ importPath: string;
51
+ symbols: string[];
52
+ } | null;
53
+ private getImportPath;
54
+ }
55
+ /**
56
+ * Swift symbol extractor.
57
+ *
58
+ * Handles `function_declaration`, `init`/`deinit`/`subscript` declarations,
59
+ * `class_declaration` (class / struct / actor / enum / extension — distinguished
60
+ * by the `declaration_kind` keyword), and `protocol_declaration`. `SymbolInfo.type`
61
+ * only has `function|method|class|interface`, so struct/actor/enum/extension map
62
+ * to `class` (keeping the real keyword in the signature) and protocol maps to
63
+ * `interface`.
64
+ *
65
+ * Call sites: `call_expression` — `foo()` (simple_identifier callee) and
66
+ * `a.b.c()` (the member is the `simple_identifier` in the trailing
67
+ * `navigation_suffix`).
68
+ */
69
+ export declare class SwiftSymbolExtractor implements LanguageSymbolExtractor {
70
+ readonly symbolNodeTypes: string[];
71
+ extractSymbol(node: Parser.SyntaxNode, content: string, parentClass?: string): SymbolInfo | null;
72
+ /**
73
+ * Resolve a call site to the called symbol name. Dependency matching is by
74
+ * bare name (call.symbol === symbol.name), so the name we record determines
75
+ * which definition the call links to.
76
+ *
77
+ * Constructor calls are worth a note: Swift spells initialization `Foo(...)`
78
+ * (no `new`), so the callee is the type name and we record `Foo` — linking the
79
+ * call to the type's `class_declaration` symbol, exactly as JS records
80
+ * `new Foo()` against the class and Python records `Foo()`. So blast-radius for
81
+ * "who constructs Foo" is found via the TYPE symbol (a safe over-approximation),
82
+ * not the `init` method symbol. An explicit `Foo.init()` records `init` and
83
+ * links the initializer directly. The standalone `init`/`deinit`/`subscript`
84
+ * symbols are definitions for search/listing (as Java emits constructor
85
+ * symbols); they intentionally carry no implicit-`Foo()` caller edges.
86
+ */
87
+ extractCallSite(node: Parser.SyntaxNode): {
88
+ symbol: string;
89
+ line: number;
90
+ key: string;
91
+ } | null;
92
+ private extractFunctionInfo;
93
+ private extractClassInfo;
94
+ private extractProtocolInfo;
95
+ private makeSymbol;
96
+ }
97
+ export declare const swiftDefinition: LanguageDefinition;
98
+ //# sourceMappingURL=swift.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"swift.d.ts","sourceRoot":"","sources":["../../../src/ast/languages/swift.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,MAAM,aAAa,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AACrD,OAAO,KAAK,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,wBAAwB,CAAC;AACzF,OAAO,KAAK,EACV,uBAAuB,EACvB,uBAAuB,EACvB,uBAAuB,EACxB,MAAM,wBAAwB,CAAC;AA4GhC;;;;;;;GAOG;AACH,qBAAa,cAAe,YAAW,iBAAiB;IACtD,eAAe,WAMb;IAEF,cAAc,WAAiD;IAE/D,gBAAgB,WAA4B;IAE5C,aAAa,WAAsB;IAEnC,qBAAqB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO;IAIvD,yBAAyB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO;IAI3D,gBAAgB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,GAAG,IAAI;IAKnE,sBAAsB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,OAAO;IASxD,uBAAuB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,SAAS;IAWpE,yBAAyB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,uBAAuB;CAS5E;AAMD;;;;;;GAMG;AACH,qBAAa,oBAAqB,YAAW,uBAAuB;IAClE,cAAc,CAAC,QAAQ,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,EAAE;IAgBrD,OAAO,CAAC,eAAe;IAsBvB,OAAO,CAAC,cAAc;CA4BvB;AAcD;;;;;;;GAOG;AACH,qBAAa,oBAAqB,YAAW,uBAAuB;IAClE,QAAQ,CAAC,eAAe,WAA0B;IAElD,iBAAiB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG,MAAM,GAAG,IAAI;IAMzD,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI;IAS/F,OAAO,CAAC,aAAa;CAGtB;AAMD;;;;;;;;;;;;;GAaG;AACH,qBAAa,oBAAqB,YAAW,uBAAuB;IAClE,QAAQ,CAAC,eAAe,WAQtB;IAEF,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI;IAiBhG;;;;;;;;;;;;;;OAcG;IACH,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,UAAU,GAAG;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAqB9F,OAAO,CAAC,mBAAmB;IAqB3B,OAAO,CAAC,gBAAgB;IAOxB,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,UAAU;CAcnB;AAMD,eAAO,MAAM,eAAe,EAAE,kBA0I7B,CAAC"}
@@ -0,0 +1,529 @@
1
+ import Swift from 'tree-sitter-swift';
2
+ import { extractSignature, extractReturnType } from '../extractors/symbol-helpers.js';
3
+ import { calculateComplexity } from '../complexity/index.js';
4
+ // =============================================================================
5
+ // HELPERS
6
+ //
7
+ // The tree-sitter-swift grammar (alex-pinkus) DOES expose field names
8
+ // (`name`, `body`, `return_type`, `declaration_kind`, …), so — unlike Kotlin —
9
+ // we use `childForFieldName` like the Java definition. The Swift-specific
10
+ // wrinkles are: class/struct/actor/enum/extension all share the
11
+ // `class_declaration` node (distinguished by the `declaration_kind` keyword),
12
+ // parameters are bare `parameter` children (no `parameters` wrapper field), and
13
+ // visibility lives under a `modifiers` child.
14
+ // =============================================================================
15
+ /** First named child of a given type. */
16
+ function childByType(node, type) {
17
+ return node.namedChildren.find(child => child.type === type) ?? null;
18
+ }
19
+ /** First descendant of a given type (depth-first), or null. */
20
+ function findFirst(node, type) {
21
+ for (const child of node.namedChildren) {
22
+ if (child.type === type)
23
+ return child;
24
+ const found = findFirst(child, type);
25
+ if (found)
26
+ return found;
27
+ }
28
+ return null;
29
+ }
30
+ /**
31
+ * The `class_declaration` keyword (`class` / `struct` / `actor` / `enum` /
32
+ * `extension`), read from the `declaration_kind` field. Defaults to `class`.
33
+ */
34
+ function declarationKeyword(node) {
35
+ return node.childForFieldName('declaration_kind')?.text ?? 'class';
36
+ }
37
+ /** The declared name of a class/protocol declaration (handles `extension`'s `user_type`). */
38
+ function declarationName(node) {
39
+ return node.childForFieldName('name')?.text;
40
+ }
41
+ /**
42
+ * The name of a function-like node. Swift's `init`/`deinit`/`subscript`
43
+ * declarations have no `name` field — fall back to the keyword.
44
+ */
45
+ function functionLikeName(node) {
46
+ const name = node.childForFieldName('name')?.text;
47
+ if (name)
48
+ return name;
49
+ switch (node.type) {
50
+ case 'init_declaration':
51
+ return 'init';
52
+ case 'deinit_declaration':
53
+ return 'deinit';
54
+ case 'subscript_declaration':
55
+ return 'subscript';
56
+ default:
57
+ return undefined;
58
+ }
59
+ }
60
+ /** Parameter texts. Swift function params are bare `parameter` children (no field). */
61
+ function swiftParameters(node) {
62
+ return node.namedChildren.filter(c => c.type === 'parameter' && c.text.trim()).map(c => c.text);
63
+ }
64
+ /**
65
+ * The function-valued initializer of a property, if the property's value is
66
+ * *directly* a closure (`let handler = { … }`). Checks the `value` field rather
67
+ * than any descendant, so a closure passed as a call argument
68
+ * (`let n = xs.map { … }`) is NOT treated as a function-valued property.
69
+ */
70
+ function propertyInitializerFunction(node) {
71
+ const value = node.childForFieldName('value');
72
+ return value?.type === 'lambda_literal' ? value : null;
73
+ }
74
+ /** Visibility modifier text (`public` / `private` / `fileprivate` / `internal` / `open`), if any. */
75
+ function visibilityModifier(node) {
76
+ const modifiers = childByType(node, 'modifiers');
77
+ if (!modifiers)
78
+ return null;
79
+ return modifiers.namedChildren.find(c => c.type === 'visibility_modifier')?.text ?? null;
80
+ }
81
+ /**
82
+ * Swift declarations are `internal` (module-visible) by default. We treat a
83
+ * declaration as "exported" (part of the file's API surface) unless it is
84
+ * explicitly `private` or `fileprivate` — so default/`internal`/`public`/`open`
85
+ * are surfaced. (Analogous to Kotlin's "public unless private/internal".)
86
+ */
87
+ function isExported(node) {
88
+ const visibility = visibilityModifier(node);
89
+ return visibility !== 'private' && visibility !== 'fileprivate';
90
+ }
91
+ /** The property's bound identifier (`let foo = …` → `foo`). */
92
+ function propertyName(node) {
93
+ const pattern = node.childForFieldName('name');
94
+ if (!pattern)
95
+ return undefined;
96
+ return findFirst(pattern, 'simple_identifier')?.text ?? pattern.text;
97
+ }
98
+ // =============================================================================
99
+ // TRAVERSER
100
+ // =============================================================================
101
+ /**
102
+ * Swift AST traverser.
103
+ *
104
+ * Functions/methods/initializers live inside `class_declaration` (which covers
105
+ * class / struct / actor / enum / extension) and `protocol_declaration` bodies
106
+ * (`class_body` / `enum_class_body` / `protocol_body`). Closures can appear as
107
+ * property initializers (`let handler = { … }`).
108
+ */
109
+ export class SwiftTraverser {
110
+ targetNodeTypes = [
111
+ 'function_declaration',
112
+ 'protocol_function_declaration', // abstract method requirements inside a protocol
113
+ 'init_declaration',
114
+ 'deinit_declaration',
115
+ 'subscript_declaration',
116
+ ];
117
+ containerTypes = ['class_declaration', 'protocol_declaration'];
118
+ declarationTypes = ['property_declaration'];
119
+ functionTypes = ['lambda_literal'];
120
+ shouldExtractChildren(node) {
121
+ return this.containerTypes.includes(node.type);
122
+ }
123
+ isDeclarationWithFunction(node) {
124
+ return node.type === 'property_declaration' && propertyInitializerFunction(node) !== null;
125
+ }
126
+ getContainerBody(node) {
127
+ if (!this.containerTypes.includes(node.type))
128
+ return null;
129
+ return node.childForFieldName('body');
130
+ }
131
+ shouldTraverseChildren(node) {
132
+ return (node.type === 'source_file' ||
133
+ node.type === 'class_body' ||
134
+ node.type === 'enum_class_body' ||
135
+ node.type === 'protocol_body');
136
+ }
137
+ findParentContainerName(node) {
138
+ let current = node.parent;
139
+ while (current) {
140
+ if (current.type === 'class_declaration' || current.type === 'protocol_declaration') {
141
+ return declarationName(current);
142
+ }
143
+ current = current.parent;
144
+ }
145
+ return undefined;
146
+ }
147
+ findFunctionInDeclaration(node) {
148
+ if (node.type !== 'property_declaration') {
149
+ return { hasFunction: false, functionNode: null };
150
+ }
151
+ const fn = propertyInitializerFunction(node);
152
+ return fn
153
+ ? { hasFunction: true, functionNode: fn }
154
+ : { hasFunction: false, functionNode: null };
155
+ }
156
+ }
157
+ // =============================================================================
158
+ // EXPORT EXTRACTOR
159
+ // =============================================================================
160
+ /**
161
+ * Swift export extractor.
162
+ *
163
+ * Swift has no `export` keyword. Top-level declarations and (non-private/
164
+ * fileprivate) members form the file's API surface. Protocol members are
165
+ * implicitly part of the protocol's surface.
166
+ */
167
+ export class SwiftExportExtractor {
168
+ extractExports(rootNode) {
169
+ const exports = [];
170
+ const seen = new Set();
171
+ const addExport = (name) => {
172
+ if (name && !seen.has(name)) {
173
+ seen.add(name);
174
+ exports.push(name);
175
+ }
176
+ };
177
+ rootNode.namedChildren.forEach(child => this.extractFromNode(child, addExport));
178
+ return exports;
179
+ }
180
+ extractFromNode(node, addExport) {
181
+ switch (node.type) {
182
+ case 'function_declaration':
183
+ case 'init_declaration':
184
+ case 'deinit_declaration':
185
+ case 'subscript_declaration':
186
+ if (isExported(node))
187
+ addExport(functionLikeName(node));
188
+ break;
189
+ case 'property_declaration':
190
+ if (isExported(node))
191
+ addExport(propertyName(node));
192
+ break;
193
+ case 'class_declaration':
194
+ case 'protocol_declaration':
195
+ // A private/fileprivate container exposes nothing — skip it and its members.
196
+ if (isExported(node)) {
197
+ addExport(declarationName(node));
198
+ this.extractMembers(node, addExport);
199
+ }
200
+ break;
201
+ }
202
+ }
203
+ extractMembers(container, addExport) {
204
+ const body = container.childForFieldName('body');
205
+ if (!body)
206
+ return;
207
+ // Protocol members are implicitly part of the protocol's surface.
208
+ const isProtocol = container.type === 'protocol_declaration';
209
+ body.namedChildren.forEach(member => {
210
+ switch (member.type) {
211
+ case 'function_declaration':
212
+ case 'protocol_function_declaration':
213
+ case 'init_declaration':
214
+ case 'deinit_declaration':
215
+ case 'subscript_declaration':
216
+ if (isProtocol || isExported(member))
217
+ addExport(functionLikeName(member));
218
+ break;
219
+ case 'property_declaration':
220
+ case 'protocol_property_declaration':
221
+ if (isProtocol || isExported(member))
222
+ addExport(propertyName(member));
223
+ break;
224
+ case 'class_declaration':
225
+ case 'protocol_declaration':
226
+ // Nested types — recurse so their names/members are surfaced too.
227
+ this.extractFromNode(member, addExport);
228
+ break;
229
+ }
230
+ });
231
+ }
232
+ }
233
+ // =============================================================================
234
+ // IMPORT EXTRACTOR
235
+ // =============================================================================
236
+ /**
237
+ * The Swift standard library module. `Foundation`, `UIKit`, `SwiftUI`,
238
+ * `Combine`, etc. are real external frameworks and are kept as import edges.
239
+ */
240
+ function isSwiftStdLib(importPath) {
241
+ return importPath === 'Swift' || importPath.startsWith('Swift.');
242
+ }
243
+ /**
244
+ * Swift import extractor.
245
+ *
246
+ * Handles `import Foundation`, dotted `import Combine.Just`, and import-kind
247
+ * forms (`import struct Combine.Just` — the `struct`/`class`/… keyword is an
248
+ * anonymous token and is ignored; the module path is what matters). Only the
249
+ * `Swift` stdlib module is filtered out.
250
+ */
251
+ export class SwiftImportExtractor {
252
+ importNodeTypes = ['import_declaration'];
253
+ extractImportPath(node) {
254
+ const path = this.getImportPath(node);
255
+ if (!path || isSwiftStdLib(path))
256
+ return null;
257
+ return path;
258
+ }
259
+ processImportSymbols(node) {
260
+ const path = this.getImportPath(node);
261
+ if (!path || isSwiftStdLib(path))
262
+ return null;
263
+ const parts = path.split('.');
264
+ const lastPart = parts[parts.length - 1];
265
+ return { importPath: path, symbols: [lastPart] };
266
+ }
267
+ getImportPath(node) {
268
+ return childByType(node, 'identifier')?.text ?? null;
269
+ }
270
+ }
271
+ // =============================================================================
272
+ // SYMBOL EXTRACTOR
273
+ // =============================================================================
274
+ /**
275
+ * Swift symbol extractor.
276
+ *
277
+ * Handles `function_declaration`, `init`/`deinit`/`subscript` declarations,
278
+ * `class_declaration` (class / struct / actor / enum / extension — distinguished
279
+ * by the `declaration_kind` keyword), and `protocol_declaration`. `SymbolInfo.type`
280
+ * only has `function|method|class|interface`, so struct/actor/enum/extension map
281
+ * to `class` (keeping the real keyword in the signature) and protocol maps to
282
+ * `interface`.
283
+ *
284
+ * Call sites: `call_expression` — `foo()` (simple_identifier callee) and
285
+ * `a.b.c()` (the member is the `simple_identifier` in the trailing
286
+ * `navigation_suffix`).
287
+ */
288
+ export class SwiftSymbolExtractor {
289
+ symbolNodeTypes = [
290
+ 'function_declaration',
291
+ 'protocol_function_declaration',
292
+ 'init_declaration',
293
+ 'deinit_declaration',
294
+ 'subscript_declaration',
295
+ 'class_declaration',
296
+ 'protocol_declaration',
297
+ ];
298
+ extractSymbol(node, content, parentClass) {
299
+ switch (node.type) {
300
+ case 'function_declaration':
301
+ case 'protocol_function_declaration':
302
+ case 'init_declaration':
303
+ case 'deinit_declaration':
304
+ case 'subscript_declaration':
305
+ return this.extractFunctionInfo(node, content, parentClass);
306
+ case 'class_declaration':
307
+ return this.extractClassInfo(node);
308
+ case 'protocol_declaration':
309
+ return this.extractProtocolInfo(node);
310
+ default:
311
+ return null;
312
+ }
313
+ }
314
+ /**
315
+ * Resolve a call site to the called symbol name. Dependency matching is by
316
+ * bare name (call.symbol === symbol.name), so the name we record determines
317
+ * which definition the call links to.
318
+ *
319
+ * Constructor calls are worth a note: Swift spells initialization `Foo(...)`
320
+ * (no `new`), so the callee is the type name and we record `Foo` — linking the
321
+ * call to the type's `class_declaration` symbol, exactly as JS records
322
+ * `new Foo()` against the class and Python records `Foo()`. So blast-radius for
323
+ * "who constructs Foo" is found via the TYPE symbol (a safe over-approximation),
324
+ * not the `init` method symbol. An explicit `Foo.init()` records `init` and
325
+ * links the initializer directly. The standalone `init`/`deinit`/`subscript`
326
+ * symbols are definitions for search/listing (as Java emits constructor
327
+ * symbols); they intentionally carry no implicit-`Foo()` caller edges.
328
+ */
329
+ extractCallSite(node) {
330
+ if (node.type !== 'call_expression')
331
+ return null;
332
+ const line = node.startPosition.row + 1;
333
+ const callee = node.namedChild(0);
334
+ if (!callee)
335
+ return null;
336
+ let name;
337
+ if (callee.type === 'simple_identifier') {
338
+ name = callee.text; // foo() / Foo() constructor — links to the fn or type symbol
339
+ }
340
+ else if (callee.type === 'navigation_expression') {
341
+ // a.b.c() / Mod.Type() / Type.init() — the called member is the
342
+ // simple_identifier in the last navigation_suffix
343
+ const suffix = callee.namedChildren.filter(c => c.type === 'navigation_suffix').at(-1);
344
+ name = suffix ? (findFirst(suffix, 'simple_identifier')?.text ?? undefined) : undefined;
345
+ }
346
+ if (!name)
347
+ return null;
348
+ return { symbol: name, line, key: `${name}:${line}` };
349
+ }
350
+ extractFunctionInfo(node, content, parentClass) {
351
+ const name = functionLikeName(node);
352
+ if (!name)
353
+ return null;
354
+ return {
355
+ name,
356
+ type: parentClass ? 'method' : 'function',
357
+ startLine: node.startPosition.row + 1,
358
+ endLine: node.endPosition.row + 1,
359
+ parentClass,
360
+ signature: extractSignature(node, content),
361
+ parameters: swiftParameters(node),
362
+ returnType: extractReturnType(node, content),
363
+ complexity: calculateComplexity(node),
364
+ };
365
+ }
366
+ extractClassInfo(node) {
367
+ const name = declarationName(node);
368
+ if (!name)
369
+ return null;
370
+ const keyword = declarationKeyword(node);
371
+ return this.makeSymbol(node, name, 'class', `${keyword} ${name}`);
372
+ }
373
+ extractProtocolInfo(node) {
374
+ const name = declarationName(node);
375
+ if (!name)
376
+ return null;
377
+ return this.makeSymbol(node, name, 'interface', `protocol ${name}`);
378
+ }
379
+ makeSymbol(node, name, type, signature) {
380
+ return {
381
+ name,
382
+ type,
383
+ startLine: node.startPosition.row + 1,
384
+ endLine: node.endPosition.row + 1,
385
+ signature,
386
+ };
387
+ }
388
+ }
389
+ // =============================================================================
390
+ // LANGUAGE DEFINITION
391
+ // =============================================================================
392
+ export const swiftDefinition = {
393
+ id: 'swift',
394
+ extensions: ['swift'],
395
+ grammar: Swift,
396
+ traverser: new SwiftTraverser(),
397
+ exportExtractor: new SwiftExportExtractor(),
398
+ importExtractor: new SwiftImportExtractor(),
399
+ symbolExtractor: new SwiftSymbolExtractor(),
400
+ complexity: {
401
+ decisionPoints: [
402
+ 'if_statement',
403
+ 'guard_statement',
404
+ 'switch_entry', // each `case` / `default` branch
405
+ 'for_statement',
406
+ 'while_statement',
407
+ 'repeat_while_statement',
408
+ 'catch_block',
409
+ 'conjunction_expression', // &&
410
+ 'disjunction_expression', // ||
411
+ 'nil_coalescing_expression', // ??
412
+ 'ternary_expression',
413
+ ],
414
+ nestingTypes: [
415
+ 'if_statement',
416
+ 'guard_statement',
417
+ 'switch_statement',
418
+ 'for_statement',
419
+ 'while_statement',
420
+ 'repeat_while_statement',
421
+ 'do_statement',
422
+ 'catch_block',
423
+ 'lambda_literal',
424
+ ],
425
+ nonNestingTypes: [
426
+ 'switch_entry',
427
+ 'conjunction_expression',
428
+ 'disjunction_expression',
429
+ 'nil_coalescing_expression',
430
+ 'ternary_expression',
431
+ ],
432
+ lambdaTypes: ['lambda_literal'],
433
+ operatorSymbols: new Set([
434
+ '+',
435
+ '-',
436
+ '*',
437
+ '/',
438
+ '%',
439
+ '==',
440
+ '!=',
441
+ '===',
442
+ '!==',
443
+ '<',
444
+ '>',
445
+ '<=',
446
+ '>=',
447
+ '=',
448
+ '+=',
449
+ '-=',
450
+ '*=',
451
+ '/=',
452
+ '%=',
453
+ '&&',
454
+ '||',
455
+ '!',
456
+ '??',
457
+ '?.',
458
+ '.',
459
+ '->',
460
+ '..<',
461
+ '...',
462
+ '(',
463
+ ')',
464
+ '[',
465
+ ']',
466
+ '{',
467
+ '}',
468
+ ]),
469
+ operatorKeywords: new Set([
470
+ 'if',
471
+ 'else',
472
+ 'guard',
473
+ 'switch',
474
+ 'case',
475
+ 'default',
476
+ 'for',
477
+ 'while',
478
+ 'repeat',
479
+ 'do',
480
+ 'return',
481
+ 'break',
482
+ 'continue',
483
+ 'fallthrough',
484
+ 'throw',
485
+ 'throws',
486
+ 'try',
487
+ 'catch',
488
+ 'defer',
489
+ 'func',
490
+ 'class',
491
+ 'struct',
492
+ 'actor',
493
+ 'enum',
494
+ 'protocol',
495
+ 'extension',
496
+ 'init',
497
+ 'deinit',
498
+ 'subscript',
499
+ 'var',
500
+ 'let',
501
+ 'is',
502
+ 'as',
503
+ 'in',
504
+ 'where',
505
+ 'some',
506
+ 'any',
507
+ 'async',
508
+ 'await',
509
+ 'import',
510
+ 'static',
511
+ 'final',
512
+ 'lazy',
513
+ 'weak',
514
+ 'override',
515
+ 'private',
516
+ 'fileprivate',
517
+ 'internal',
518
+ 'public',
519
+ 'open',
520
+ 'self',
521
+ 'super',
522
+ 'nil',
523
+ ]),
524
+ },
525
+ symbols: {
526
+ callExpressionTypes: ['call_expression'],
527
+ },
528
+ };
529
+ //# sourceMappingURL=swift.js.map