@mduenas/codegraph 0.5.6 → 0.6.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 (68) hide show
  1. package/README.md +1 -1
  2. package/dist/bin/codegraph.js +16 -15
  3. package/dist/bin/codegraph.js.map +1 -1
  4. package/dist/config.d.ts.map +1 -1
  5. package/dist/config.js +4 -1
  6. package/dist/config.js.map +1 -1
  7. package/dist/context/index.d.ts.map +1 -1
  8. package/dist/context/index.js +3 -3
  9. package/dist/context/index.js.map +1 -1
  10. package/dist/db/index.d.ts.map +1 -1
  11. package/dist/db/index.js +10 -0
  12. package/dist/db/index.js.map +1 -1
  13. package/dist/db/migrations.d.ts +1 -1
  14. package/dist/db/migrations.d.ts.map +1 -1
  15. package/dist/db/migrations.js +11 -12
  16. package/dist/db/migrations.js.map +1 -1
  17. package/dist/db/queries.d.ts +8 -0
  18. package/dist/db/queries.d.ts.map +1 -1
  19. package/dist/db/queries.js +51 -10
  20. package/dist/db/queries.js.map +1 -1
  21. package/dist/db/schema.sql +4 -0
  22. package/dist/extraction/index.d.ts.map +1 -1
  23. package/dist/extraction/index.js +104 -7
  24. package/dist/extraction/index.js.map +1 -1
  25. package/dist/extraction/tree-sitter.d.ts +76 -4
  26. package/dist/extraction/tree-sitter.d.ts.map +1 -1
  27. package/dist/extraction/tree-sitter.js +627 -20
  28. package/dist/extraction/tree-sitter.js.map +1 -1
  29. package/dist/graph/traversal.d.ts.map +1 -1
  30. package/dist/graph/traversal.js +6 -2
  31. package/dist/graph/traversal.js.map +1 -1
  32. package/dist/index.d.ts +2 -1
  33. package/dist/index.d.ts.map +1 -1
  34. package/dist/index.js +51 -18
  35. package/dist/index.js.map +1 -1
  36. package/dist/mcp/index.d.ts.map +1 -1
  37. package/dist/mcp/index.js +4 -0
  38. package/dist/mcp/index.js.map +1 -1
  39. package/dist/mcp/tools.d.ts +13 -0
  40. package/dist/mcp/tools.d.ts.map +1 -1
  41. package/dist/mcp/tools.js +70 -37
  42. package/dist/mcp/tools.js.map +1 -1
  43. package/dist/resolution/import-resolver.d.ts.map +1 -1
  44. package/dist/resolution/import-resolver.js +3 -4
  45. package/dist/resolution/import-resolver.js.map +1 -1
  46. package/dist/resolution/index.d.ts +21 -0
  47. package/dist/resolution/index.d.ts.map +1 -1
  48. package/dist/resolution/index.js +139 -24
  49. package/dist/resolution/index.js.map +1 -1
  50. package/dist/resolution/name-matcher.d.ts.map +1 -1
  51. package/dist/resolution/name-matcher.js +7 -20
  52. package/dist/resolution/name-matcher.js.map +1 -1
  53. package/dist/resolution/types.d.ts +4 -0
  54. package/dist/resolution/types.d.ts.map +1 -1
  55. package/dist/types.d.ts +4 -0
  56. package/dist/types.d.ts.map +1 -1
  57. package/dist/types.js +2 -0
  58. package/dist/types.js.map +1 -1
  59. package/dist/utils.d.ts +42 -0
  60. package/dist/utils.d.ts.map +1 -1
  61. package/dist/utils.js +111 -1
  62. package/dist/utils.js.map +1 -1
  63. package/dist/vectors/embedder.js +1 -1
  64. package/dist/vectors/embedder.js.map +1 -1
  65. package/dist/vectors/search.d.ts.map +1 -1
  66. package/dist/vectors/search.js +8 -7
  67. package/dist/vectors/search.js.map +1 -1
  68. package/package.json +1 -1
@@ -158,6 +158,116 @@ function isKotlinEnum(node) {
158
158
  function isKotlinAbstractClass(node) {
159
159
  return kotlinHasModifier(node, 'abstract');
160
160
  }
161
+ // =============================================================================
162
+ // Swift-specific Helper Functions
163
+ // =============================================================================
164
+ /**
165
+ * Check if a Swift node has a specific modifier
166
+ */
167
+ function swiftHasModifier(node, modifier) {
168
+ for (let i = 0; i < node.childCount; i++) {
169
+ const child = node.child(i);
170
+ if (child?.type === 'modifiers' && child.text.includes(modifier)) {
171
+ return true;
172
+ }
173
+ }
174
+ return false;
175
+ }
176
+ /**
177
+ * Get the declaration kind from a Swift class_declaration
178
+ * Returns: 'class' | 'struct' | 'actor' | 'extension' | 'enum' | null
179
+ */
180
+ function getSwiftDeclarationKind(node) {
181
+ for (let i = 0; i < node.childCount; i++) {
182
+ const child = node.child(i);
183
+ if (child) {
184
+ if (child.type === 'class')
185
+ return 'class';
186
+ if (child.type === 'struct')
187
+ return 'struct';
188
+ if (child.type === 'actor')
189
+ return 'actor';
190
+ if (child.type === 'extension')
191
+ return 'extension';
192
+ if (child.type === 'enum')
193
+ return 'enum';
194
+ }
195
+ }
196
+ return null;
197
+ }
198
+ /**
199
+ * Extract property wrapper attributes (e.g., @State, @Published)
200
+ */
201
+ function getSwiftPropertyWrappers(node, source) {
202
+ const wrappers = [];
203
+ for (let i = 0; i < node.childCount; i++) {
204
+ const child = node.child(i);
205
+ if (child?.type === 'attribute') {
206
+ const text = getNodeText(child, source);
207
+ wrappers.push(text);
208
+ }
209
+ }
210
+ return wrappers;
211
+ }
212
+ /**
213
+ * Get the name from a Swift class_declaration
214
+ * For extensions, returns the extended type name
215
+ */
216
+ function getSwiftClassName(node, source) {
217
+ let name = '<unknown>';
218
+ let constraints = '';
219
+ for (let i = 0; i < node.namedChildCount; i++) {
220
+ const child = node.namedChild(i);
221
+ if (child?.type === 'type_identifier') {
222
+ name = getNodeText(child, source);
223
+ }
224
+ // For extensions, the name is in a user_type
225
+ if (child?.type === 'user_type') {
226
+ name = getNodeText(child, source);
227
+ }
228
+ // Capture type_constraints for extensions with where clauses
229
+ if (child?.type === 'type_constraints') {
230
+ constraints = ' ' + getNodeText(child, source);
231
+ }
232
+ }
233
+ return name + constraints;
234
+ }
235
+ /**
236
+ * Get the name from a Swift property_declaration
237
+ */
238
+ function getSwiftPropertyName(node, source) {
239
+ for (let i = 0; i < node.namedChildCount; i++) {
240
+ const child = node.namedChild(i);
241
+ if (child?.type === 'pattern') {
242
+ // The simple_identifier is inside the pattern
243
+ for (let j = 0; j < child.namedChildCount; j++) {
244
+ const patternChild = child.namedChild(j);
245
+ if (patternChild?.type === 'simple_identifier') {
246
+ return getNodeText(patternChild, source);
247
+ }
248
+ }
249
+ }
250
+ }
251
+ return '<unknown>';
252
+ }
253
+ /**
254
+ * Check if a Swift property is a constant (let vs var)
255
+ */
256
+ function isSwiftConstant(node) {
257
+ for (let i = 0; i < node.namedChildCount; i++) {
258
+ const child = node.namedChild(i);
259
+ if (child?.type === 'value_binding_pattern') {
260
+ // Check for 'let' child
261
+ for (let j = 0; j < child.childCount; j++) {
262
+ const bindingChild = child.child(j);
263
+ if (bindingChild?.type === 'let') {
264
+ return true;
265
+ }
266
+ }
267
+ }
268
+ }
269
+ return false;
270
+ }
161
271
  /**
162
272
  * Language-specific extractors
163
273
  */
@@ -627,8 +737,13 @@ const EXTRACTORS = {
627
737
  return false;
628
738
  },
629
739
  isAsync: (node) => {
740
+ // In Swift, async is a direct child node, not inside modifiers
630
741
  for (let i = 0; i < node.childCount; i++) {
631
742
  const child = node.child(i);
743
+ if (child?.type === 'async') {
744
+ return true;
745
+ }
746
+ // Also check modifiers for cases where it might be there
632
747
  if (child?.type === 'modifiers' && child.text.includes('async')) {
633
748
  return true;
634
749
  }
@@ -821,13 +936,9 @@ class TreeSitterExtractor {
821
936
  }
822
937
  // Check for class declarations
823
938
  else if (this.extractor.classTypes.includes(nodeType)) {
824
- // Swift uses class_declaration for both classes and structs
825
- // Check for 'struct' child to differentiate
826
- if (this.language === 'swift' && this.hasChildOfType(node, 'struct')) {
827
- this.extractStruct(node);
828
- }
829
- else if (this.language === 'swift' && this.hasChildOfType(node, 'enum')) {
830
- this.extractEnum(node);
939
+ // Swift uses class_declaration for class, struct, actor, extension, enum
940
+ if (this.language === 'swift' && nodeType === 'class_declaration') {
941
+ this.extractSwiftClassDeclaration(node);
831
942
  }
832
943
  // Kotlin uses class_declaration for classes, interfaces, and enums
833
944
  else if (this.language === 'kotlin' && nodeType === 'class_declaration') {
@@ -863,6 +974,37 @@ class TreeSitterExtractor {
863
974
  else if (this.language === 'kotlin' && nodeType === 'type_alias') {
864
975
  this.extractKotlinTypeAlias(node);
865
976
  }
977
+ // Swift property_declaration (top-level or inside protocols)
978
+ else if (this.language === 'swift' && nodeType === 'property_declaration') {
979
+ this.extractSwiftProperty(node);
980
+ }
981
+ // Swift protocol_property_declaration
982
+ else if (this.language === 'swift' && nodeType === 'protocol_property_declaration') {
983
+ this.extractSwiftProperty(node);
984
+ }
985
+ // Swift subscript_declaration
986
+ else if (this.language === 'swift' && nodeType === 'subscript_declaration') {
987
+ this.extractSwiftSubscript(node);
988
+ skipChildren = true;
989
+ }
990
+ // Swift typealias_declaration
991
+ else if (this.language === 'swift' && nodeType === 'typealias_declaration') {
992
+ this.extractSwiftTypealias(node);
993
+ }
994
+ // Swift associatedtype_declaration
995
+ else if (this.language === 'swift' && nodeType === 'associatedtype_declaration') {
996
+ this.extractSwiftAssociatedType(node);
997
+ }
998
+ // Swift init_declaration
999
+ else if (this.language === 'swift' && nodeType === 'init_declaration') {
1000
+ this.extractSwiftInit(node);
1001
+ skipChildren = true;
1002
+ }
1003
+ // Swift deinit_declaration
1004
+ else if (this.language === 'swift' && nodeType === 'deinit_declaration') {
1005
+ this.extractSwiftDeinit(node);
1006
+ skipChildren = true;
1007
+ }
866
1008
  // Check for method declarations (only if not already handled by functionTypes)
867
1009
  else if (this.extractor.methodTypes.includes(nodeType)) {
868
1010
  this.extractMethod(node);
@@ -870,7 +1012,13 @@ class TreeSitterExtractor {
870
1012
  }
871
1013
  // Check for interface/protocol/trait declarations
872
1014
  else if (this.extractor.interfaceTypes.includes(nodeType)) {
873
- this.extractInterface(node);
1015
+ // Swift protocols need special handling for associated types
1016
+ if (this.language === 'swift' && nodeType === 'protocol_declaration') {
1017
+ this.extractSwiftProtocol(node);
1018
+ }
1019
+ else {
1020
+ this.extractInterface(node);
1021
+ }
874
1022
  skipChildren = true; // extractInterface visits body children
875
1023
  }
876
1024
  // Check for struct declarations
@@ -949,18 +1097,6 @@ class TreeSitterExtractor {
949
1097
  parts.push(name);
950
1098
  return parts.join('::');
951
1099
  }
952
- /**
953
- * Check if a node has a child of a specific type
954
- */
955
- hasChildOfType(node, type) {
956
- for (let i = 0; i < node.childCount; i++) {
957
- const child = node.child(i);
958
- if (child?.type === type) {
959
- return true;
960
- }
961
- }
962
- return false;
963
- }
964
1100
  /**
965
1101
  * Extract a function
966
1102
  */
@@ -1522,6 +1658,477 @@ class TreeSitterExtractor {
1522
1658
  }
1523
1659
  }
1524
1660
  }
1661
+ // =============================================================================
1662
+ // Swift-specific Extraction Methods
1663
+ // =============================================================================
1664
+ /**
1665
+ * Extract a Swift class declaration (handles class, struct, actor, extension, enum)
1666
+ */
1667
+ extractSwiftClassDeclaration(node) {
1668
+ const declKind = getSwiftDeclarationKind(node);
1669
+ switch (declKind) {
1670
+ case 'extension':
1671
+ this.extractSwiftExtension(node);
1672
+ break;
1673
+ case 'actor':
1674
+ this.extractSwiftActor(node);
1675
+ break;
1676
+ case 'enum':
1677
+ this.extractSwiftEnum(node);
1678
+ break;
1679
+ case 'struct':
1680
+ this.extractSwiftStruct(node);
1681
+ break;
1682
+ default:
1683
+ this.extractSwiftClass(node);
1684
+ }
1685
+ }
1686
+ /**
1687
+ * Extract a Swift class
1688
+ */
1689
+ extractSwiftClass(node) {
1690
+ if (!this.extractor)
1691
+ return;
1692
+ const name = getSwiftClassName(node, this.source);
1693
+ const docstring = getPrecedingDocstring(node, this.source);
1694
+ const visibility = this.extractor.getVisibility?.(node);
1695
+ const isAbstract = swiftHasModifier(node, 'abstract');
1696
+ const classNode = this.createNode('class', name, node, {
1697
+ docstring,
1698
+ visibility,
1699
+ isAbstract,
1700
+ });
1701
+ // Extract inheritance
1702
+ this.extractSwiftInheritance(node, classNode.id);
1703
+ // Push to stack and visit body
1704
+ this.nodeStack.push(classNode.id);
1705
+ this.visitSwiftClassBody(node);
1706
+ this.nodeStack.pop();
1707
+ }
1708
+ /**
1709
+ * Extract a Swift struct
1710
+ */
1711
+ extractSwiftStruct(node) {
1712
+ if (!this.extractor)
1713
+ return;
1714
+ const name = getSwiftClassName(node, this.source);
1715
+ const docstring = getPrecedingDocstring(node, this.source);
1716
+ const visibility = this.extractor.getVisibility?.(node);
1717
+ const structNode = this.createNode('struct', name, node, {
1718
+ docstring,
1719
+ visibility,
1720
+ });
1721
+ // Extract protocol conformance
1722
+ this.extractSwiftInheritance(node, structNode.id);
1723
+ // Push to stack and visit body
1724
+ this.nodeStack.push(structNode.id);
1725
+ this.visitSwiftClassBody(node);
1726
+ this.nodeStack.pop();
1727
+ }
1728
+ /**
1729
+ * Extract a Swift actor declaration
1730
+ */
1731
+ extractSwiftActor(node) {
1732
+ if (!this.extractor)
1733
+ return;
1734
+ const name = getSwiftClassName(node, this.source);
1735
+ const docstring = getPrecedingDocstring(node, this.source);
1736
+ const visibility = this.extractor.getVisibility?.(node);
1737
+ // Actors are similar to classes but with built-in synchronization
1738
+ const actorNode = this.createNode('class', name, node, {
1739
+ docstring,
1740
+ visibility,
1741
+ });
1742
+ // Extract protocol conformance
1743
+ this.extractSwiftInheritance(node, actorNode.id);
1744
+ // Push to stack and visit body
1745
+ this.nodeStack.push(actorNode.id);
1746
+ this.visitSwiftClassBody(node);
1747
+ this.nodeStack.pop();
1748
+ }
1749
+ /**
1750
+ * Extract a Swift extension declaration
1751
+ */
1752
+ extractSwiftExtension(node) {
1753
+ if (!this.extractor)
1754
+ return;
1755
+ // For extensions, the name is the extended type
1756
+ const name = getSwiftClassName(node, this.source);
1757
+ const docstring = getPrecedingDocstring(node, this.source);
1758
+ const visibility = this.extractor.getVisibility?.(node);
1759
+ // Extensions are treated as classes extending the original type
1760
+ const extNode = this.createNode('class', name, node, {
1761
+ docstring,
1762
+ visibility,
1763
+ });
1764
+ // Extract protocol conformance added by the extension
1765
+ this.extractSwiftInheritance(node, extNode.id);
1766
+ // Push to stack and visit body
1767
+ this.nodeStack.push(extNode.id);
1768
+ this.visitSwiftClassBody(node);
1769
+ this.nodeStack.pop();
1770
+ }
1771
+ /**
1772
+ * Extract a Swift enum
1773
+ */
1774
+ extractSwiftEnum(node) {
1775
+ if (!this.extractor)
1776
+ return;
1777
+ const name = getSwiftClassName(node, this.source);
1778
+ const docstring = getPrecedingDocstring(node, this.source);
1779
+ const visibility = this.extractor.getVisibility?.(node);
1780
+ const enumNode = this.createNode('enum', name, node, {
1781
+ docstring,
1782
+ visibility,
1783
+ });
1784
+ // Extract protocol conformance
1785
+ this.extractSwiftInheritance(node, enumNode.id);
1786
+ // Push to stack and visit body (enum_class_body)
1787
+ this.nodeStack.push(enumNode.id);
1788
+ for (let i = 0; i < node.namedChildCount; i++) {
1789
+ const child = node.namedChild(i);
1790
+ if (child?.type === 'enum_class_body') {
1791
+ for (let j = 0; j < child.namedChildCount; j++) {
1792
+ const bodyChild = child.namedChild(j);
1793
+ if (bodyChild) {
1794
+ if (bodyChild.type === 'enum_entry') {
1795
+ this.extractSwiftEnumCase(bodyChild);
1796
+ }
1797
+ else {
1798
+ this.visitNode(bodyChild);
1799
+ }
1800
+ }
1801
+ }
1802
+ }
1803
+ }
1804
+ this.nodeStack.pop();
1805
+ }
1806
+ /**
1807
+ * Extract a Swift enum case
1808
+ */
1809
+ extractSwiftEnumCase(node) {
1810
+ // Find the simple_identifier for the case name
1811
+ let name = '<unknown>';
1812
+ for (let i = 0; i < node.namedChildCount; i++) {
1813
+ const child = node.namedChild(i);
1814
+ if (child?.type === 'simple_identifier') {
1815
+ name = getNodeText(child, this.source);
1816
+ break;
1817
+ }
1818
+ }
1819
+ this.createNode('enum_member', name, node, {});
1820
+ }
1821
+ /**
1822
+ * Extract a Swift property (stored or computed)
1823
+ */
1824
+ extractSwiftProperty(node) {
1825
+ if (!this.extractor)
1826
+ return;
1827
+ const name = getSwiftPropertyName(node, this.source);
1828
+ const docstring = getPrecedingDocstring(node, this.source);
1829
+ const visibility = this.extractor.getVisibility?.(node);
1830
+ const isConst = isSwiftConstant(node);
1831
+ const isStatic = this.extractor.isStatic?.(node);
1832
+ // Get property wrappers (decorators)
1833
+ const wrappers = getSwiftPropertyWrappers(node, this.source);
1834
+ const decorators = wrappers.length > 0 ? wrappers : undefined;
1835
+ // Use 'constant' for let, 'property' for var
1836
+ const kind = isConst && this.nodeStack.length === 0 ? 'constant' : 'property';
1837
+ this.createNode(kind, name, node, {
1838
+ docstring,
1839
+ visibility,
1840
+ isStatic,
1841
+ decorators,
1842
+ });
1843
+ }
1844
+ /**
1845
+ * Extract a Swift subscript declaration
1846
+ */
1847
+ extractSwiftSubscript(node) {
1848
+ if (!this.extractor)
1849
+ return;
1850
+ // Subscripts are treated as methods
1851
+ const docstring = getPrecedingDocstring(node, this.source);
1852
+ const visibility = this.extractor.getVisibility?.(node);
1853
+ const isStatic = this.extractor.isStatic?.(node);
1854
+ // Build signature from parameters and return type
1855
+ let signature = '';
1856
+ for (let i = 0; i < node.namedChildCount; i++) {
1857
+ const child = node.namedChild(i);
1858
+ if (child?.type === 'parameter') {
1859
+ if (signature)
1860
+ signature += ', ';
1861
+ signature += getNodeText(child, this.source);
1862
+ }
1863
+ else if (child?.type === 'user_type') {
1864
+ signature += ' -> ' + getNodeText(child, this.source);
1865
+ }
1866
+ }
1867
+ this.createNode('method', 'subscript', node, {
1868
+ docstring,
1869
+ visibility,
1870
+ isStatic,
1871
+ signature: signature || undefined,
1872
+ });
1873
+ }
1874
+ /**
1875
+ * Extract a Swift typealias declaration
1876
+ */
1877
+ extractSwiftTypealias(node) {
1878
+ // Find the type_identifier for the alias name
1879
+ let name = '<unknown>';
1880
+ for (let i = 0; i < node.namedChildCount; i++) {
1881
+ const child = node.namedChild(i);
1882
+ if (child?.type === 'type_identifier') {
1883
+ name = getNodeText(child, this.source);
1884
+ break;
1885
+ }
1886
+ }
1887
+ const docstring = getPrecedingDocstring(node, this.source);
1888
+ const visibility = this.extractor?.getVisibility?.(node);
1889
+ this.createNode('type_alias', name, node, {
1890
+ docstring,
1891
+ visibility,
1892
+ });
1893
+ }
1894
+ /**
1895
+ * Extract a Swift associated type declaration (in protocols)
1896
+ */
1897
+ extractSwiftAssociatedType(node) {
1898
+ // Find the type_identifier for the associated type name
1899
+ let name = '<unknown>';
1900
+ for (let i = 0; i < node.namedChildCount; i++) {
1901
+ const child = node.namedChild(i);
1902
+ if (child?.type === 'type_identifier') {
1903
+ name = getNodeText(child, this.source);
1904
+ break;
1905
+ }
1906
+ }
1907
+ const docstring = getPrecedingDocstring(node, this.source);
1908
+ this.createNode('type_alias', name, node, {
1909
+ docstring,
1910
+ });
1911
+ }
1912
+ /**
1913
+ * Extract a Swift init declaration
1914
+ */
1915
+ extractSwiftInit(node) {
1916
+ if (!this.extractor)
1917
+ return;
1918
+ const docstring = getPrecedingDocstring(node, this.source);
1919
+ const visibility = this.extractor.getVisibility?.(node);
1920
+ const isAsync = this.extractor.isAsync?.(node);
1921
+ // Build signature from parameters
1922
+ let signature = '';
1923
+ for (let i = 0; i < node.namedChildCount; i++) {
1924
+ const child = node.namedChild(i);
1925
+ if (child?.type === 'parameter') {
1926
+ if (signature)
1927
+ signature += ', ';
1928
+ signature += getNodeText(child, this.source);
1929
+ }
1930
+ }
1931
+ const initNode = this.createNode('method', 'init', node, {
1932
+ docstring,
1933
+ visibility,
1934
+ isAsync,
1935
+ signature: signature ? `(${signature})` : '()',
1936
+ });
1937
+ // Visit function body for calls
1938
+ this.nodeStack.push(initNode.id);
1939
+ this.visitSwiftFunctionBody(node);
1940
+ this.nodeStack.pop();
1941
+ }
1942
+ /**
1943
+ * Extract a Swift deinit declaration
1944
+ */
1945
+ extractSwiftDeinit(node) {
1946
+ const docstring = getPrecedingDocstring(node, this.source);
1947
+ const deinitNode = this.createNode('method', 'deinit', node, {
1948
+ docstring,
1949
+ });
1950
+ // Visit function body for calls
1951
+ this.nodeStack.push(deinitNode.id);
1952
+ this.visitSwiftFunctionBody(node);
1953
+ this.nodeStack.pop();
1954
+ }
1955
+ /**
1956
+ * Extract Swift inheritance (protocol conformance, superclass)
1957
+ */
1958
+ extractSwiftInheritance(node, classId) {
1959
+ let isFirst = true;
1960
+ for (let i = 0; i < node.namedChildCount; i++) {
1961
+ const child = node.namedChild(i);
1962
+ if (child?.type === 'inheritance_specifier') {
1963
+ // Get the user_type inside inheritance_specifier
1964
+ for (let j = 0; j < child.namedChildCount; j++) {
1965
+ const specChild = child.namedChild(j);
1966
+ if (specChild?.type === 'user_type') {
1967
+ const typeName = getNodeText(specChild, this.source);
1968
+ // First inheritance is usually extends (for classes), rest are implements
1969
+ this.unresolvedReferences.push({
1970
+ fromNodeId: classId,
1971
+ referenceName: typeName,
1972
+ referenceKind: isFirst ? 'extends' : 'implements',
1973
+ line: specChild.startPosition.row + 1,
1974
+ column: specChild.startPosition.column,
1975
+ });
1976
+ isFirst = false;
1977
+ }
1978
+ }
1979
+ }
1980
+ }
1981
+ }
1982
+ /**
1983
+ * Extract a Swift protocol declaration
1984
+ */
1985
+ extractSwiftProtocol(node) {
1986
+ if (!this.extractor)
1987
+ return;
1988
+ // Get protocol name
1989
+ let name = '<unknown>';
1990
+ for (let i = 0; i < node.namedChildCount; i++) {
1991
+ const child = node.namedChild(i);
1992
+ if (child?.type === 'type_identifier') {
1993
+ name = getNodeText(child, this.source);
1994
+ break;
1995
+ }
1996
+ }
1997
+ const docstring = getPrecedingDocstring(node, this.source);
1998
+ const visibility = this.extractor.getVisibility?.(node);
1999
+ const protocolNode = this.createNode('interface', name, node, {
2000
+ docstring,
2001
+ visibility,
2002
+ });
2003
+ // Extract protocol inheritance
2004
+ this.extractSwiftInheritance(node, protocolNode.id);
2005
+ // Push to stack and visit protocol body
2006
+ this.nodeStack.push(protocolNode.id);
2007
+ for (let i = 0; i < node.namedChildCount; i++) {
2008
+ const child = node.namedChild(i);
2009
+ if (child?.type === 'protocol_body') {
2010
+ for (let j = 0; j < child.namedChildCount; j++) {
2011
+ const bodyChild = child.namedChild(j);
2012
+ if (bodyChild) {
2013
+ if (bodyChild.type === 'associatedtype_declaration') {
2014
+ this.extractSwiftAssociatedType(bodyChild);
2015
+ }
2016
+ else if (bodyChild.type === 'protocol_property_declaration') {
2017
+ this.extractSwiftProtocolProperty(bodyChild);
2018
+ }
2019
+ else if (bodyChild.type === 'protocol_function_declaration') {
2020
+ this.extractSwiftProtocolFunction(bodyChild);
2021
+ }
2022
+ else {
2023
+ this.visitNode(bodyChild);
2024
+ }
2025
+ }
2026
+ }
2027
+ }
2028
+ }
2029
+ this.nodeStack.pop();
2030
+ }
2031
+ /**
2032
+ * Extract a Swift protocol property declaration
2033
+ */
2034
+ extractSwiftProtocolProperty(node) {
2035
+ // Find the simple_identifier for the property name
2036
+ let name = '<unknown>';
2037
+ for (let i = 0; i < node.namedChildCount; i++) {
2038
+ const child = node.namedChild(i);
2039
+ if (child?.type === 'pattern') {
2040
+ for (let j = 0; j < child.namedChildCount; j++) {
2041
+ const patternChild = child.namedChild(j);
2042
+ if (patternChild?.type === 'simple_identifier') {
2043
+ name = getNodeText(patternChild, this.source);
2044
+ break;
2045
+ }
2046
+ }
2047
+ }
2048
+ }
2049
+ const docstring = getPrecedingDocstring(node, this.source);
2050
+ this.createNode('property', name, node, {
2051
+ docstring,
2052
+ });
2053
+ }
2054
+ /**
2055
+ * Extract a Swift protocol function declaration
2056
+ */
2057
+ extractSwiftProtocolFunction(node) {
2058
+ // Find the simple_identifier for the function name
2059
+ let name = '<unknown>';
2060
+ for (let i = 0; i < node.namedChildCount; i++) {
2061
+ const child = node.namedChild(i);
2062
+ if (child?.type === 'simple_identifier') {
2063
+ name = getNodeText(child, this.source);
2064
+ break;
2065
+ }
2066
+ }
2067
+ const docstring = getPrecedingDocstring(node, this.source);
2068
+ // Build signature
2069
+ let signature = '';
2070
+ for (let i = 0; i < node.namedChildCount; i++) {
2071
+ const child = node.namedChild(i);
2072
+ if (child?.type === 'user_type') {
2073
+ signature = ' -> ' + getNodeText(child, this.source);
2074
+ break;
2075
+ }
2076
+ }
2077
+ this.createNode('method', name, node, {
2078
+ docstring,
2079
+ signature: signature || undefined,
2080
+ });
2081
+ }
2082
+ /**
2083
+ * Visit a Swift class/struct/actor body and extract members
2084
+ */
2085
+ visitSwiftClassBody(node) {
2086
+ for (let i = 0; i < node.namedChildCount; i++) {
2087
+ const child = node.namedChild(i);
2088
+ if (child?.type === 'class_body') {
2089
+ for (let j = 0; j < child.namedChildCount; j++) {
2090
+ const bodyChild = child.namedChild(j);
2091
+ if (bodyChild) {
2092
+ // Handle Swift-specific node types
2093
+ if (bodyChild.type === 'property_declaration') {
2094
+ this.extractSwiftProperty(bodyChild);
2095
+ }
2096
+ else if (bodyChild.type === 'subscript_declaration') {
2097
+ this.extractSwiftSubscript(bodyChild);
2098
+ }
2099
+ else if (bodyChild.type === 'init_declaration') {
2100
+ this.extractSwiftInit(bodyChild);
2101
+ }
2102
+ else if (bodyChild.type === 'deinit_declaration') {
2103
+ this.extractSwiftDeinit(bodyChild);
2104
+ }
2105
+ else if (bodyChild.type === 'typealias_declaration') {
2106
+ this.extractSwiftTypealias(bodyChild);
2107
+ }
2108
+ else {
2109
+ this.visitNode(bodyChild);
2110
+ }
2111
+ }
2112
+ }
2113
+ }
2114
+ }
2115
+ }
2116
+ /**
2117
+ * Visit a Swift function body to extract calls
2118
+ */
2119
+ visitSwiftFunctionBody(node) {
2120
+ for (let i = 0; i < node.namedChildCount; i++) {
2121
+ const child = node.namedChild(i);
2122
+ if (child?.type === 'function_body') {
2123
+ for (let j = 0; j < child.namedChildCount; j++) {
2124
+ const bodyChild = child.namedChild(j);
2125
+ if (bodyChild) {
2126
+ this.visitNode(bodyChild);
2127
+ }
2128
+ }
2129
+ }
2130
+ }
2131
+ }
1525
2132
  }
1526
2133
  exports.TreeSitterExtractor = TreeSitterExtractor;
1527
2134
  /**