@shapeshift-labs/frontier-lang-compiler 0.2.103 → 0.2.104

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 (124) hide show
  1. package/README.md +13 -0
  2. package/dist/declarations/bidirectional-target-change-source-edit.d.ts +30 -0
  3. package/dist/declarations/bidirectional-target-change.d.ts +10 -0
  4. package/dist/declarations/js-ts-safe-member-merge.d.ts +58 -0
  5. package/dist/declarations/js-ts-safe-merge.d.ts +120 -0
  6. package/dist/declarations/js-ts-semantic-conflict-sidecars.d.ts +235 -0
  7. package/dist/declarations/js-ts-semantic-merge-contracts.d.ts +287 -0
  8. package/dist/declarations/js-ts-semantic-merge.d.ts +4 -0
  9. package/dist/declarations/native-import-losses.d.ts +3 -0
  10. package/dist/declarations/semantic-edit-replay-diagnostics.d.ts +12 -0
  11. package/dist/declarations/semantic-edit-script.d.ts +7 -4
  12. package/dist/declarations/semantic-patch-bundle-index.d.ts +45 -0
  13. package/dist/declarations/semantic-patch-bundle.d.ts +6 -4
  14. package/dist/declarations/semantic-sidecar-example.d.ts +18 -0
  15. package/dist/declarations/semantic-transform-identity.d.ts +3 -0
  16. package/dist/declarations/source-preservation.d.ts +72 -0
  17. package/dist/declarations/universal-capability.d.ts +4 -0
  18. package/dist/declarations/universal-conversion-artifacts.d.ts +61 -1
  19. package/dist/declarations/universal-conversion-compact-counts.d.ts +51 -0
  20. package/dist/declarations/universal-conversion-plan.d.ts +6 -1
  21. package/dist/declarations/universal-representation-coverage.d.ts +90 -0
  22. package/dist/index.d.ts +4 -0
  23. package/dist/index.js +3 -0
  24. package/dist/internal/index-impl/bidirectionalExactSourceBackprojection.js +199 -0
  25. package/dist/internal/index-impl/bidirectionalSameLanguageSourceProjection.js +112 -0
  26. package/dist/internal/index-impl/bidirectionalSourceEditProjection.js +319 -0
  27. package/dist/internal/index-impl/bidirectionalSourceEditProjectionArtifacts.js +67 -0
  28. package/dist/internal/index-impl/bidirectionalTargetChangeRecordInternals.js +17 -5
  29. package/dist/internal/index-impl/bidirectionalTargetRoundtripEvidence.js +58 -20
  30. package/dist/internal/index-impl/createBidirectionalTargetChangeRecord.js +60 -7
  31. package/dist/internal/index-impl/createLightweightNativeImport.js +1 -0
  32. package/dist/internal/index-impl/createNativeSourcePreservation.js +28 -2
  33. package/dist/internal/index-impl/diffNativeSymbols.js +3 -3
  34. package/dist/internal/index-impl/nativeChangeProjectionSourceMapLinks.js +2 -0
  35. package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +43 -8
  36. package/dist/internal/index-impl/replaySemanticEditLineEndings.js +34 -0
  37. package/dist/internal/index-impl/replaySemanticEditProjection.js +39 -19
  38. package/dist/internal/index-impl/semanticEditBundleAdmission.js +7 -3
  39. package/dist/internal/index-impl/semanticEditBundleIndex.js +47 -1
  40. package/dist/internal/index-impl/semanticEditExplicitSourceReplacement.js +40 -0
  41. package/dist/internal/index-impl/semanticEditOperationCoverage.js +33 -3
  42. package/dist/internal/index-impl/semanticEditProjectionRecord.js +29 -0
  43. package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +39 -0
  44. package/dist/internal/index-impl/semanticEditReplaySourceReplacement.js +85 -0
  45. package/dist/internal/index-impl/semanticEditScripts.js +4 -0
  46. package/dist/internal/index-impl/semanticEditSourceRanges.js +27 -0
  47. package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +1 -0
  48. package/dist/internal/index-impl/semanticPatchBundleAdmission.js +41 -7
  49. package/dist/internal/index-impl/semanticPatchBundleRecords.js +16 -0
  50. package/dist/internal/index-impl/semanticPatchBundleSourceRecords.js +2 -0
  51. package/dist/internal/index-impl/semanticSidecarQuality.js +111 -0
  52. package/dist/internal/index-impl/semanticSourceEditDedupe.js +69 -9
  53. package/dist/internal/index-impl/semanticTransformIdentityRecords.js +85 -9
  54. package/dist/js-ts-safe-member-merge-result.js +158 -0
  55. package/dist/js-ts-safe-member-merge.js +202 -0
  56. package/dist/js-ts-safe-merge-analyze.js +279 -0
  57. package/dist/js-ts-safe-merge-constants.js +50 -0
  58. package/dist/js-ts-safe-merge-context.js +118 -0
  59. package/dist/js-ts-safe-merge-ledger-validation.js +92 -0
  60. package/dist/js-ts-safe-merge-ledger.js +85 -0
  61. package/dist/js-ts-safe-merge-parse-declarations.js +210 -0
  62. package/dist/js-ts-safe-merge-parse-statements.js +155 -0
  63. package/dist/js-ts-safe-merge-plan.js +190 -0
  64. package/dist/js-ts-safe-merge.js +175 -0
  65. package/dist/js-ts-semantic-conflict-sidecar-constants.js +77 -0
  66. package/dist/js-ts-semantic-conflict-sidecar-detectors.js +195 -0
  67. package/dist/js-ts-semantic-conflict-sidecar-normalize.js +203 -0
  68. package/dist/js-ts-semantic-conflict-sidecar-utils.js +190 -0
  69. package/dist/js-ts-semantic-conflict-sidecars.js +81 -0
  70. package/dist/js-ts-semantic-merge-contract-helpers.js +128 -0
  71. package/dist/js-ts-semantic-merge-contracts.js +217 -0
  72. package/dist/js-ts-semantic-merge-member-containers.js +100 -0
  73. package/dist/js-ts-semantic-merge-member-keys.js +142 -0
  74. package/dist/js-ts-semantic-merge-member-segments.js +185 -0
  75. package/dist/js-ts-semantic-merge-member-source.js +64 -0
  76. package/dist/js-ts-semantic-merge-member-utils.js +18 -0
  77. package/dist/js-ts-semantic-merge-parse.js +15 -0
  78. package/dist/js-ts-semantic-merge.js +21 -0
  79. package/dist/lightweight-dependency-effects.js +51 -0
  80. package/dist/lightweight-dependency-language.js +12 -1
  81. package/dist/lightweight-dependency-relations.js +14 -27
  82. package/dist/native-region-scanner-core.js +33 -1
  83. package/dist/native-region-scanner-csharp.js +151 -0
  84. package/dist/native-region-scanner-dart.js +91 -0
  85. package/dist/native-region-scanner-dynamic.js +21 -151
  86. package/dist/native-region-scanner-functional.js +40 -13
  87. package/dist/native-region-scanner-java.js +97 -0
  88. package/dist/native-region-scanner-js-class.js +100 -0
  89. package/dist/native-region-scanner-js-helpers.js +28 -86
  90. package/dist/native-region-scanner-js-imports.js +121 -1
  91. package/dist/native-region-scanner-js-nested.js +96 -8
  92. package/dist/native-region-scanner-js-structure.js +27 -0
  93. package/dist/native-region-scanner-js-types.js +99 -0
  94. package/dist/native-region-scanner-js.js +70 -118
  95. package/dist/native-region-scanner-kotlin.js +94 -0
  96. package/dist/native-region-scanner-main.js +15 -181
  97. package/dist/native-region-scanner-php.js +80 -0
  98. package/dist/native-region-scanner-python.js +62 -0
  99. package/dist/native-region-scanner-ruby.js +72 -0
  100. package/dist/native-region-scanner-scala.js +91 -0
  101. package/dist/native-region-scanner-spans.js +74 -0
  102. package/dist/native-region-scanner-swift.js +155 -0
  103. package/dist/native-region-scanner.js +14 -10
  104. package/dist/native-source-ledger-helpers.js +195 -0
  105. package/dist/native-source-ledger.js +306 -0
  106. package/dist/native-source-preservation-scanner.js +4 -0
  107. package/dist/semantic-import-callsite-regions.js +136 -0
  108. package/dist/semantic-import-effect-regions.js +283 -0
  109. package/dist/semantic-import-regions.js +11 -2
  110. package/dist/semantic-import-sidecar-entry.js +16 -2
  111. package/dist/semantic-import-sidecar-types.d.ts +2 -0
  112. package/dist/semantic-sidecar-example.js +68 -0
  113. package/dist/universal-capability-matrix.js +23 -0
  114. package/dist/universal-conversion-artifact-query.js +79 -2
  115. package/dist/universal-conversion-artifact-semantic-edit.js +103 -0
  116. package/dist/universal-conversion-artifact-summary.js +33 -1
  117. package/dist/universal-conversion-artifacts.js +13 -48
  118. package/dist/universal-conversion-plan-scoring.js +21 -1
  119. package/dist/universal-conversion-plan-summary.js +30 -0
  120. package/dist/universal-conversion-plan.js +25 -9
  121. package/dist/universal-conversion-route-metadata.js +96 -0
  122. package/dist/universal-conversion-route-operations.js +7 -0
  123. package/dist/universal-representation-coverage.js +193 -0
  124. package/package.json +1 -1
@@ -1,40 +1,49 @@
1
1
  import {
2
2
  braceDelta,
3
- jsControlKeyword,
4
- nativeDeclaration,
5
- nativeImportDeclaration,
3
+ nativeDeclaration, nativeImportDeclaration, nativeSignatureDeclaration,
6
4
  sourceLines,
7
5
  splitParameters
8
6
  } from './native-region-scanner-core.js';
9
7
  import {
10
8
  jsCommentOnlyLine,
11
- jsContainerDelta,
12
9
  jsDeclarationScanLine,
13
- jsExportAliasDeclaration,
10
+ jsExportAliasDeclaration, jsExportDeclarations,
14
11
  jsExportedContainerDeclaration,
15
12
  jsExportedFunctionWrapperDeclaration,
16
13
  jsInitializerKind,
17
14
  jsImportDeclarations,
18
- jsObjectPropertyDeclaration,
19
15
  jsObjectRegionContext,
20
16
  jsRegionKindForDeclarationName,
21
- jsRouteRecordDeclaration,
22
17
  jsVariableHasBody,
23
18
  jsVariableSymbolKind
24
19
  } from './native-region-scanner-js-helpers.js';
20
+ import { jsStructureDelta } from './native-region-scanner-js-structure.js';
25
21
  import {
26
- jsContextAllowsPropertyScan,
27
- jsCurrentObjectContext,
28
- jsInlineNestedObjectDeclarations,
29
- jsNestedObjectContextFromDeclaration,
30
- updateJsObjectContextStack
22
+ jsCurrentTypeMemberContext,
23
+ jsNestedTypeMemberContextFromDeclaration,
24
+ jsTypeMemberDeclaration,
25
+ jsTypeRegionContext,
26
+ updateJsTypeRegionContext
27
+ } from './native-region-scanner-js-types.js';
28
+ import {
29
+ jsArrayObjectContextFromLine, jsContextAllowsPropertyScan, jsCurrentObjectContext,
30
+ jsInlineNestedObjectDeclarations, jsNestedObjectContextFromDeclaration,
31
+ jsObjectPropertyDeclaration, jsRouteRecordDeclaration,
32
+ updateJsArrayObjectContextName, updateJsObjectContextStack
31
33
  } from './native-region-scanner-js-nested.js';
34
+ import {
35
+ jsClassMemberDeclaration,
36
+ jsInlineClassMemberDeclarations
37
+ } from './native-region-scanner-js-class.js';
32
38
 
33
39
  function scanJavaScriptLike(input) {
34
40
  const declarations = [];
35
41
  const lines = sourceLines(input.sourceText);
36
42
  const pushDeclaration = (declaration) => {
37
- if (declaration) declarations.push(jsDeclarationWithSourceSpan(input, declaration, lines));
43
+ if (!declaration) return undefined;
44
+ const declarationWithSpan = jsDeclarationWithSourceSpan(input, declaration, lines);
45
+ declarations.push(declarationWithSpan);
46
+ return declarationWithSpan;
38
47
  };
39
48
  const pushDeclarations = (items) => {
40
49
  for (const declaration of items ?? []) pushDeclaration(declaration);
@@ -51,14 +60,22 @@ function scanJavaScriptLike(input) {
51
60
  const declarationLine = trimmed.replace(/^(?:export\s+)?(?:declare\s+)?/, '');
52
61
  let match;
53
62
  if (currentType && number !== currentType.startLine) {
54
- pushDeclaration(jsTypeMemberDeclaration(input, number, declarationLine, currentType));
63
+ const typeContext = jsCurrentTypeMemberContext(currentType);
64
+ if (!typeContext.suppressMembers) {
65
+ const typeMember = pushDeclaration(jsTypeMemberDeclaration(input, number, declarationLine, typeContext));
66
+ const nestedTypeContext = jsNestedTypeMemberContextFromDeclaration(typeMember, number, declarationLine, typeContext);
67
+ if (nestedTypeContext) currentType.memberStack.push(nestedTypeContext);
68
+ }
55
69
  }
56
70
  const currentObject = jsCurrentObjectContext(objectStack);
57
71
  if (currentObject) {
72
+ const arrayItemContext = jsArrayObjectContextFromLine(currentObject, number, trimmed);
73
+ if (arrayItemContext) objectStack.push(arrayItemContext);
58
74
  const routeRecord = jsRouteRecordDeclaration(input, number, trimmed, currentObject);
59
75
  if (routeRecord) {
60
76
  pushDeclaration(routeRecord);
61
77
  } else if (jsContextAllowsPropertyScan(currentObject)) {
78
+ updateJsArrayObjectContextName(currentObject, trimmed);
62
79
  const property = jsObjectPropertyDeclaration(input, number, trimmed, currentObject);
63
80
  if (property) {
64
81
  pushDeclaration(property);
@@ -74,9 +91,15 @@ function scanJavaScriptLike(input) {
74
91
  } else if ((match = trimmed.match(/^import\s*\(\s*['"]([^'"]+)['"]\s*\)/))) {
75
92
  pushDeclaration(nativeImportDeclaration(input, number, match[1], 'DynamicImportExpression', 'module'));
76
93
  } else if ((match = declarationLine.match(/^(?:async\s+)?function\*?\s+([A-Za-z_$][\w$]*)\s*(?:<[^({;]+>)?\s*\(([^)]*)\)\s*(?::\s*[^={]+)?/))) {
77
- pushDeclaration(nativeDeclaration(input, number, 'FunctionDeclaration', 'function', match[1], { parameters: splitParameters(match[2]) }, declarationLine.includes('{')));
94
+ const hasBody = declarationLine.includes('{');
95
+ pushDeclaration((hasBody ? nativeDeclaration : nativeSignatureDeclaration)(input, number, 'FunctionDeclaration', 'function', match[1], { parameters: splitParameters(match[2]) }, hasBody));
78
96
  } else if ((match = trimmed.match(/^export\s+default\s+(?:async\s+)?function\*?\s*([A-Za-z_$][\w$]*)?\s*(?:<[^({;]+>)?\s*\(([^)]*)\)\s*(?::\s*[^={]+)?/))) {
79
97
  pushDeclaration(nativeDeclaration(input, number, 'ExportDefaultFunctionDeclaration', 'function', match[1] ?? 'default', { parameters: splitParameters(match[2]), exportDefault: true }, trimmed.includes('{')));
98
+ } else if ((match = trimmed.match(/^export\s+default\s+(?:async\s*)?(?:<[^=]+>\s*)?(?:\(([^)]*)\)|([A-Za-z_$][\w$]*))\s*(?::\s*[^=]+)?=>/))) {
99
+ pushDeclaration(nativeDeclaration(input, number, 'ExportDefaultArrowFunctionDeclaration', 'function', 'default', {
100
+ parameters: splitParameters(match[1] ?? match[2]),
101
+ exportDefault: true
102
+ }, true));
80
103
  } else if ((match = declarationLine.match(/^(default\s+)?(?:abstract\s+)?class\b(?:\s+(?!(?:extends|implements)\b)([A-Za-z_$][\w$]*))?/)) && (match[1] || match[2])) {
81
104
  const className = match[2] ?? 'default';
82
105
  const exportDefault = Boolean(match[1]);
@@ -121,24 +144,43 @@ function scanJavaScriptLike(input) {
121
144
  if (match.context) objectStack.push(match.context);
122
145
  } else if ((match = jsExportAliasDeclaration(input, number, trimmed))) {
123
146
  pushDeclaration(match);
147
+ } else if ((match = trimmed.match(/^module\.exports\s*=\s*(?:async\s+)?function\*?\s*([A-Za-z_$][\w$]*)?\s*(?:<[^({;]+>)?\s*\(([^)]*)\)/))) {
148
+ pushDeclaration(nativeDeclaration(input, number, 'CommonJsDefaultFunctionExport', 'function', match[1] ?? 'module.exports', {
149
+ export: 'commonjs',
150
+ parameters: splitParameters(match[2])
151
+ }, true));
152
+ } else if ((match = trimmed.match(/^module\.exports\s*=\s*(?:async\s*)?(?:<[^=]+>\s*)?(?:\(([^)]*)\)|([A-Za-z_$][\w$]*))\s*(?::\s*[^=]+)?=>/))) {
153
+ pushDeclaration(nativeDeclaration(input, number, 'CommonJsDefaultArrowFunctionExport', 'function', 'module.exports', {
154
+ export: 'commonjs',
155
+ parameters: splitParameters(match[1] ?? match[2])
156
+ }, true));
157
+ } else if ((match = trimmed.match(/^module\.exports\s*=\s*(?:abstract\s+)?class\b(?:\s+(?!(?:extends|implements)\b)([A-Za-z_$][\w$]*))?/))) {
158
+ const className = match[1] ?? 'module.exports';
159
+ pushDeclaration(nativeDeclaration(input, number, 'CommonJsDefaultClassExport', 'class', className, { export: 'commonjs' }, trimmed.includes('{')));
160
+ pushDeclarations(jsInlineClassMemberDeclarations(input, number, trimmed, className));
161
+ if (jsStructureDelta(trimmed).value > 0) {
162
+ currentClass = className;
163
+ classDepth = 0;
164
+ }
124
165
  } else if ((match = trimmed.match(/^(?:module\.)?exports\.([A-Za-z_$][\w$]*)\s*=\s*(?:async\s+)?function\*?\s*\(([^)]*)\)/))) {
125
166
  pushDeclaration(nativeDeclaration(input, number, 'CommonJsFunctionExport', 'function', match[1], { parameters: splitParameters(match[2]) }, true));
167
+ } else if ((match = trimmed.match(/^(?:module\.)?exports\.([A-Za-z_$][\w$]*)\s*=\s*(?:async\s*)?(?:<[^=]+>\s*)?(?:\(([^)]*)\)|([A-Za-z_$][\w$]*))\s*(?::\s*[^=]+)?=>/))) {
168
+ pushDeclaration(nativeDeclaration(input, number, 'CommonJsFunctionExport', 'function', match[1], { parameters: splitParameters(match[2] ?? match[3]) }, true));
169
+ } else if ((match = trimmed.match(/^(?:module\.)?exports\.([A-Za-z_$][\w$]*)\s*=\s*(?:abstract\s+)?class\b(?:\s+(?!(?:extends|implements)\b)([A-Za-z_$][\w$]*))?/))) {
170
+ const className = match[2] ?? match[1];
171
+ pushDeclaration(nativeDeclaration(input, number, 'CommonJsClassExport', 'class', className, { export: 'commonjs', exportName: match[1] }, trimmed.includes('{')));
172
+ pushDeclarations(jsInlineClassMemberDeclarations(input, number, trimmed, className));
173
+ if (jsStructureDelta(trimmed).value > 0) {
174
+ currentClass = className;
175
+ classDepth = 0;
176
+ }
126
177
  } else if ((match = trimmed.match(/^(?:module\.)?exports\.([A-Za-z_$][\w$]*)\s*=/))) {
127
178
  const regionKind = jsRegionKindForDeclarationName(match[1], trimmed);
128
179
  pushDeclaration(nativeDeclaration(input, number, 'CommonJsExport', 'variable', match[1], { export: 'commonjs' }, false, { regionKind }));
129
- } else if (currentClass && (match = declarationLine.match(/^(?:(?:public|private|protected|static|async|override|readonly|abstract|accessor|get|set)\s+)*(?:async\s+)?(?:get\s+|set\s+)?(#?[A-Za-z_$][\w$]*)\??\s*(?:<[^({;]+>)?\s*\(([^)]*)\)\s*(?::\s*[^={]+)?(?:\{|=>|$)/)) && !jsControlKeyword(match[1])) {
130
- pushDeclaration(nativeDeclaration(input, number, 'MethodDefinition', 'method', `${currentClass}.${match[1]}`, {
131
- methodName: match[1],
132
- owner: currentClass,
133
- parameters: splitParameters(match[2])
134
- }, declarationLine.includes('{') || declarationLine.includes('=>')));
135
- } else if (currentClass && (match = declarationLine.match(/^(?:(?:public|private|protected|static|readonly|declare|accessor)\s+)*(#?[A-Za-z_$][\w$]*)[?!]?\s*(?::\s*([^=;{]+))?(?:[=;]|$)/))) {
136
- pushDeclaration(nativeDeclaration(input, number, 'PropertyDefinition', 'property', `${currentClass}.${match[1]}`, {
137
- propertyName: match[1],
138
- owner: currentClass,
139
- valueType: match[2]?.trim()
140
- }, false, { regionKind: 'property' }));
180
+ } else if (currentClass) {
181
+ pushDeclaration(jsClassMemberDeclaration(input, number, declarationLine, currentClass));
141
182
  }
183
+ pushDeclarations(jsExportDeclarations(input, number, trimmed));
142
184
  if (currentClass) {
143
185
  classDepth += braceDelta(trimmed);
144
186
  if (classDepth <= 0) {
@@ -147,7 +189,7 @@ function scanJavaScriptLike(input) {
147
189
  }
148
190
  }
149
191
  if (currentType) {
150
- if (number !== currentType.startLine) currentType.depth += jsStructureDelta(trimmed).value;
192
+ if (number !== currentType.startLine) updateJsTypeRegionContext(currentType, number, trimmed);
151
193
  if (currentType.depth <= 0) currentType = undefined;
152
194
  }
153
195
  updateJsObjectContextStack(objectStack, number, trimmed);
@@ -192,94 +234,4 @@ function jsBalancedDeclarationEndLine(input, lines, startLine) {
192
234
  return startLine;
193
235
  }
194
236
 
195
- function jsStructureDelta(source) {
196
- let value = 0;
197
- let opened = false;
198
- let quote;
199
- let escaped = false;
200
- for (const char of String(source ?? '')) {
201
- if (quote) {
202
- if (escaped) escaped = false;
203
- else if (char === '\\') escaped = true;
204
- else if (char === quote) quote = undefined;
205
- continue;
206
- }
207
- if (char === '\'' || char === '"' || char === '`') {
208
- quote = char;
209
- continue;
210
- }
211
- if (char === '{' || char === '[' || char === '(') {
212
- value += 1;
213
- opened = true;
214
- } else if (char === '}' || char === ']' || char === ')') {
215
- value -= 1;
216
- }
217
- }
218
- return { value, opened };
219
- }
220
-
221
- function jsTypeRegionContext(name, declarationLine, lineNumber, regionKind, typeKind) {
222
- const depth = jsStructureDelta(declarationLine).value;
223
- if (depth <= 0) return undefined;
224
- return {
225
- name,
226
- typeKind,
227
- regionKind,
228
- depth,
229
- startLine: lineNumber
230
- };
231
- }
232
-
233
- function jsTypeMemberDeclaration(input, lineNumber, declarationLine, context) {
234
- const text = String(declarationLine ?? '').trim();
235
- if (!text || /^[}\])]/.test(text) || text.startsWith('//')) return undefined;
236
- let match = text.match(/^(?:readonly\s+)?(['"]?)([A-Za-z_$][\w$-]*)\1\??\s*(?:<[^({;]+>)?\s*\(([^)]*)\)\s*(?::\s*([^;,]+))?[;,]?$/);
237
- if (match && !jsControlKeyword(match[2])) {
238
- return nativeDeclaration(input, lineNumber, 'TypeMethodSignature', 'method', `${context.name}.${match[2]}`, {
239
- owner: context.name,
240
- propertyName: match[2],
241
- parameters: splitParameters(match[3]),
242
- returnType: match[4]?.trim(),
243
- typeKind: context.typeKind
244
- }, false, {
245
- regionKind: jsTypeMemberRegionKind(context, match[2], text),
246
- metadata: { owner: context.name, propertyName: match[2], typeKind: context.typeKind }
247
- });
248
- }
249
- match = text.match(/^(?:readonly\s+)?(['"]?)([A-Za-z_$][\w$-]*)\1\??\s*:\s*(.+?)[;,]?$/);
250
- if (!match || jsControlKeyword(match[2])) return undefined;
251
- const valueType = match[3].trim();
252
- const functionLike = /=>/.test(valueType) || /^\([^)]*\)\s*=>/.test(valueType);
253
- return nativeDeclaration(input, lineNumber, functionLike ? 'TypeFunctionPropertySignature' : 'TypePropertySignature', functionLike ? 'function' : 'property', `${context.name}.${match[2]}`, {
254
- owner: context.name,
255
- propertyName: match[2],
256
- valueType,
257
- typeKind: context.typeKind
258
- }, false, {
259
- regionKind: jsTypeMemberRegionKind(context, match[2], text),
260
- metadata: { owner: context.name, propertyName: match[2], typeKind: context.typeKind }
261
- });
262
- }
263
-
264
- function jsTypeMemberRegionKind(context, propertyName, source) {
265
- return jsRegionKindForDeclarationName(propertyName, source) ?? (context.regionKind === 'type' ? 'property' : context.regionKind) ?? 'property';
266
- }
267
-
268
- function jsInlineClassMemberDeclarations(input, lineNumber, declarationLine, className) {
269
- const open = declarationLine.indexOf('{');
270
- const close = declarationLine.lastIndexOf('}');
271
- if (open < 0 || close <= open) return [];
272
- const body = declarationLine.slice(open + 1, close);
273
- const declarations = [];
274
- for (const match of body.matchAll(/(?:(?:public|private|protected|static|async|override|readonly|abstract|accessor|get|set)\s+)*(?:async\s+)?(?:get\s+|set\s+)?(#?[A-Za-z_$][\w$]*)\??\s*(?:<[^({;]+>)?\s*\(([^)]*)\)\s*(?::\s*[^={;]+)?\s*(?:\{|=>)/g)) {
275
- if (jsControlKeyword(match[1])) continue;
276
- declarations.push(nativeDeclaration(input, lineNumber, 'MethodDefinition', 'method', `${className}.${match[1]}`, {
277
- methodName: match[1],
278
- owner: className,
279
- parameters: splitParameters(match[2])
280
- }, true));
281
- }
282
- return declarations;
283
- }
284
-
285
237
  export { scanJavaScriptLike };
@@ -0,0 +1,94 @@
1
+ import { upperFirst } from './native-import-utils.js';
2
+ import { nativeDeclaration, nativeImportDeclaration, sourceLines, splitParameters } from './native-region-scanner-core.js';
3
+ import { braceBlockSpan } from './native-region-scanner-spans.js';
4
+
5
+ function scanKotlin(input) {
6
+ const declarations = [];
7
+ const lines = sourceLines(input.sourceText);
8
+ const blockStack = [];
9
+ let braceDepth = 0;
10
+ for (const [index, { line, number }] of lines.entries()) {
11
+ const trimmed = line.trim();
12
+ const lineStartDepth = depthAfterLeadingClosers(trimmed, braceDepth);
13
+ while (blockStack.length && blockStack[blockStack.length - 1].bodyDepth > lineStartDepth) blockStack.pop();
14
+ let match;
15
+ if ((match = trimmed.match(/^package\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)/))) {
16
+ declarations.push(nativeDeclaration(input, number, 'PackageHeader', 'package', match[1], {}, false));
17
+ } else if ((match = trimmed.match(/^import\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*(?:\.\*)?)(?:\s+as\s+[A-Za-z_]\w*)?$/))) {
18
+ declarations.push(nativeImportDeclaration(input, number, match[1], 'ImportDirective', 'package'));
19
+ } else if ((match = trimmed.match(/^(?:(?:public|private|protected|internal|expect|actual|open|final|abstract|sealed|data|value)\s+)*(?:(enum|annotation)\s+)?(class|interface|object)\s+([A-Za-z_]\w*)/))) {
20
+ const owner = nearestContainer(blockStack);
21
+ const name = owner ? `${owner.name}.${match[3]}` : match[3];
22
+ const hasBody = trimmed.includes('{');
23
+ declarations.push(nativeDeclaration(input, number, kotlinDeclarationKind(match[2], match[1]), kotlinSymbolKind(match[2], match[1]), name, owner ? { owner: owner.name } : {}, hasBody, spanOptions(input, lines, index, hasBody)));
24
+ if (hasBody) blockStack.push({ kind: match[2], name, bodyDepth: braceDepth + 1 });
25
+ } else if ((match = trimmed.match(/^(?:(?:public|private|protected|internal|expect|actual|open|final|abstract|inline|tailrec|operator|infix|external|suspend|override)\s+)*fun\s+(?:<[^>]+>\s*)?(?:([A-Za-z_][\w.<>?]*)\.)?([A-Za-z_]\w*)\s*\(([^)]*)\)/))) {
26
+ const owner = nearestContainer(blockStack);
27
+ const receiverType = match[1];
28
+ const target = kotlinFunctionTarget(owner, receiverType, match[2]);
29
+ const hasBody = trimmed.includes('{') || trimmed.includes('=');
30
+ declarations.push(nativeDeclaration(input, number, 'FunctionDeclaration', target.owner ? 'method' : 'function', target.name, {
31
+ parameters: splitParameters(match[3]),
32
+ methodName: match[2],
33
+ ...(target.owner ? { owner: target.owner, receiverKind: target.receiverKind } : {}),
34
+ ...(receiverType ? { receiverType } : {})
35
+ }, hasBody, {
36
+ ...spanOptions(input, lines, index, trimmed.includes('{')),
37
+ metadata: {
38
+ methodName: match[2],
39
+ ...(target.owner ? { owner: target.owner, receiverKind: target.receiverKind } : {}),
40
+ ...(receiverType ? { receiverType } : {})
41
+ }
42
+ }));
43
+ if (trimmed.includes('{')) blockStack.push({ kind: 'function', name: target.name, bodyDepth: braceDepth + 1 });
44
+ } else if ((match = trimmed.match(/^(?:(?:public|private|protected|internal|expect|actual)\s+)*typealias\s+([A-Za-z_]\w*)\s*=/))) {
45
+ declarations.push(nativeDeclaration(input, number, 'TypeAliasDeclaration', 'type', match[1], {}, false));
46
+ } else if ((match = trimmed.match(/^(?:(?:public|private|protected|internal|expect|actual|open|final|abstract|override|const|lateinit)\s+)*(?:val|var)\s+([A-Za-z_]\w*)\b/))) {
47
+ declarations.push(nativeDeclaration(input, number, 'PropertyDeclaration', 'variable', match[1], {}, false));
48
+ }
49
+ braceDepth = Math.max(0, braceDepth + braceDelta(line));
50
+ }
51
+ return declarations;
52
+ }
53
+
54
+ function spanOptions(input, lines, index, hasBraceBody) {
55
+ return hasBraceBody ? { span: braceBlockSpan(input, lines, index) } : {};
56
+ }
57
+
58
+ function depthAfterLeadingClosers(trimmed, depth) {
59
+ const closers = String(trimmed).match(/^}+/)?.[0].length ?? 0;
60
+ return Math.max(0, depth - closers);
61
+ }
62
+
63
+ function nearestContainer(blockStack) {
64
+ for (let index = blockStack.length - 1; index >= 0; index -= 1) {
65
+ if (blockStack[index].kind === 'function') return undefined;
66
+ if (blockStack[index].kind === 'class' || blockStack[index].kind === 'interface' || blockStack[index].kind === 'object') return blockStack[index];
67
+ }
68
+ return undefined;
69
+ }
70
+
71
+ function kotlinFunctionTarget(owner, receiverType, methodName) {
72
+ if (receiverType) return { name: `${receiverType}.extension.${methodName}`, owner: receiverType, receiverKind: 'extension' };
73
+ if (owner) return { name: `${owner.name}.${methodName}`, owner: owner.name, receiverKind: 'member' };
74
+ return { name: methodName };
75
+ }
76
+
77
+ function braceDelta(source) {
78
+ return [...String(source ?? '')].reduce((delta, char) => delta + (char === '{' ? 1 : char === '}' ? -1 : 0), 0);
79
+ }
80
+
81
+ function kotlinDeclarationKind(kind, prefix) {
82
+ if (prefix === 'enum') return 'EnumClassDeclaration';
83
+ if (prefix === 'annotation') return 'AnnotationClassDeclaration';
84
+ return `${upperFirst(kind)}Declaration`;
85
+ }
86
+
87
+ function kotlinSymbolKind(kind, prefix) {
88
+ if (kind === 'interface') return 'interface';
89
+ if (kind === 'object') return 'module';
90
+ if (prefix === 'enum' || prefix === 'annotation') return 'type';
91
+ return 'class';
92
+ }
93
+
94
+ export { scanKotlin };
@@ -1,4 +1,4 @@
1
- import { idFragment, uniqueStrings, upperFirst } from './native-import-utils.js';
1
+ import { idFragment } from './native-import-utils.js';
2
2
  import {
3
3
  nativeDeclaration,
4
4
  nativeImportDeclaration,
@@ -7,30 +7,16 @@ import {
7
7
  splitParameters,
8
8
  splitTypeParameters
9
9
  } from './native-region-scanner-core.js';
10
-
11
- function scanPython(input) {
12
- const declarations = [];
13
- for (const { line, number } of sourceLines(input.sourceText)) {
14
- const trimmed = line.trim();
15
- let match;
16
- if ((match = trimmed.match(/^(?:async\s+)?def\s+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*:/))) {
17
- declarations.push(nativeDeclaration(input, number, 'FunctionDef', 'function', match[1], { parameters: splitParameters(match[2]) }, true));
18
- } else if ((match = trimmed.match(/^class\s+([A-Za-z_]\w*)/))) {
19
- declarations.push(nativeDeclaration(input, number, 'ClassDef', 'class', match[1], {}, true));
20
- } else if ((match = trimmed.match(/^(?:from\s+([A-Za-z_][\w.]*)\s+import\s+.+|import\s+([A-Za-z_][\w.]*))/))) {
21
- declarations.push(nativeImportDeclaration(input, number, match[1] ?? match[2], 'Import', 'module'));
22
- }
23
- }
24
- return declarations;
25
- }
10
+ import { braceBlockSpan } from './native-region-scanner-spans.js';
26
11
 
27
12
  function scanRust(input) {
28
13
  const declarations = [];
29
- for (const { line, number } of sourceLines(input.sourceText)) {
14
+ const lines = sourceLines(input.sourceText);
15
+ for (const [index, { line, number }] of lines.entries()) {
30
16
  const trimmed = line.trim();
31
17
  let match;
32
18
  if ((match = trimmed.match(/^(?:pub(?:\([^)]*\))?\s+)?(?:async\s+)?fn\s+([A-Za-z_]\w*)\s*\(([^)]*)\)/))) {
33
- declarations.push(nativeDeclaration(input, number, 'ItemFn', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.includes('{')));
19
+ declarations.push(nativeDeclaration(input, number, 'ItemFn', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.includes('{'), { span: trimmed.includes('{') ? braceBlockSpan(input, lines, index) : undefined }));
34
20
  } else if ((match = trimmed.match(/^(?:pub(?:\([^)]*\))?\s+)?struct\s+([A-Za-z_]\w*)/))) {
35
21
  declarations.push(nativeDeclaration(input, number, 'ItemStruct', 'type', match[1], {}, trimmed.includes('{')));
36
22
  } else if ((match = trimmed.match(/^(?:pub(?:\([^)]*\))?\s+)?enum\s+([A-Za-z_]\w*)/))) {
@@ -52,7 +38,8 @@ function scanRust(input) {
52
38
 
53
39
  function scanCLike(input) {
54
40
  const declarations = [];
55
- for (const { line, number } of sourceLines(input.sourceText)) {
41
+ const lines = sourceLines(input.sourceText);
42
+ for (const [index, { line, number }] of lines.entries()) {
56
43
  const trimmed = line.trim();
57
44
  let match;
58
45
  if ((match = trimmed.match(/^#\s*include\s+[<"]([^>"]+)[>"]/))) {
@@ -60,30 +47,11 @@ function scanCLike(input) {
60
47
  } else if ((match = trimmed.match(/^#\s*define\s+([A-Za-z_]\w*)/))) {
61
48
  declarations.push(nativeMacroLoss(input, number, trimmed, 'preprocessor', match[1]));
62
49
  } else if ((match = trimmed.match(/^typedef\s+struct(?:\s+([A-Za-z_]\w*))?/))) {
63
- declarations.push(nativeDeclaration(input, number, 'TypedefStructDeclaration', 'type', match[1] ?? `anonymous_struct_${number}`, {}, trimmed.includes('{')));
50
+ declarations.push(nativeDeclaration(input, number, 'TypedefStructDeclaration', 'type', match[1] ?? `anonymous_struct_${number}`, {}, trimmed.includes('{'), { span: trimmed.includes('{') ? braceBlockSpan(input, lines, index) : undefined }));
64
51
  } else if ((match = trimmed.match(/^(?:struct|enum)\s+([A-Za-z_]\w*)/))) {
65
- declarations.push(nativeDeclaration(input, number, 'TagDeclaration', 'type', match[1], {}, trimmed.includes('{')));
52
+ declarations.push(nativeDeclaration(input, number, 'TagDeclaration', 'type', match[1], {}, trimmed.includes('{'), { span: trimmed.includes('{') ? braceBlockSpan(input, lines, index) : undefined }));
66
53
  } else if ((match = trimmed.match(/^(?:[A-Za-z_][\w\s*:&<>]+)\s+([A-Za-z_]\w*)\s*\(([^;{}]*)\)\s*(?:;|\{)?$/))) {
67
- declarations.push(nativeDeclaration(input, number, 'FunctionDeclaration', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.endsWith('{')));
68
- }
69
- }
70
- return declarations;
71
- }
72
-
73
- function scanJava(input) {
74
- const declarations = [];
75
- for (const { line, number } of sourceLines(input.sourceText)) {
76
- const trimmed = line.trim();
77
- let match;
78
- if ((match = trimmed.match(/^package\s+([A-Za-z_][\w.]*);/))) {
79
- declarations.push(nativeDeclaration(input, number, 'PackageDeclaration', 'package', match[1], {}, false));
80
- } else if ((match = trimmed.match(/^import\s+(?:static\s+)?([A-Za-z_][\w.*]*);/))) {
81
- declarations.push(nativeImportDeclaration(input, number, match[1], 'ImportDeclaration', 'package'));
82
- } else if ((match = trimmed.match(/^(?:(?:public|protected|private|abstract|final|static|sealed|non-sealed)\s+)*(class|interface|enum|record|@interface)\s+([A-Za-z_$][\w$]*)/))) {
83
- const kind = match[1] === '@interface' ? 'AnnotationDeclaration' : `${upperFirst(match[1])}Declaration`;
84
- declarations.push(nativeDeclaration(input, number, kind, javaSymbolKind(match[1]), match[2], {}, trimmed.includes('{')));
85
- } else if ((match = trimmed.match(/^(?:(?:public|protected|private|abstract|final|static|synchronized|native)\s+)*(?:<[^>]+>\s+)?[A-Za-z_$][\w$<>\[\].?,\s]*\s+([A-Za-z_$][\w$]*)\s*\(([^)]*)\)\s*(?:throws\s+[^{]+)?(?:\{|;)?$/))) {
86
- declarations.push(nativeDeclaration(input, number, 'MethodDeclaration', 'method', match[1], { parameters: splitParameters(match[2]) }, trimmed.includes('{')));
54
+ declarations.push(nativeDeclaration(input, number, 'FunctionDeclaration', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.endsWith('{'), { span: trimmed.endsWith('{') ? braceBlockSpan(input, lines, index) : undefined }));
87
55
  }
88
56
  }
89
57
  return declarations;
@@ -92,7 +60,8 @@ function scanJava(input) {
92
60
  function scanGo(input) {
93
61
  const declarations = [];
94
62
  let inImportBlock = false;
95
- for (const { line, number } of sourceLines(input.sourceText)) {
63
+ const lines = sourceLines(input.sourceText);
64
+ for (const [index, { line, number }] of lines.entries()) {
96
65
  const trimmed = line.trim();
97
66
  let match;
98
67
  if (inImportBlock) {
@@ -120,12 +89,12 @@ function scanGo(input) {
120
89
  receiver,
121
90
  typeParameters: splitTypeParameters(match[3]),
122
91
  parameters: splitParameters(match[4])
123
- }, trimmed.includes('{')));
92
+ }, trimmed.includes('{'), { span: trimmed.includes('{') ? braceBlockSpan(input, lines, index) : undefined }));
124
93
  } else if ((match = trimmed.match(/^func\s+([A-Za-z_]\w*)(?:\s*\[([^\]]+)\])?\s*\(([^)]*)\)/))) {
125
94
  declarations.push(nativeDeclaration(input, number, 'FuncDecl', 'function', match[1], {
126
95
  typeParameters: splitTypeParameters(match[2]),
127
96
  parameters: splitParameters(match[3])
128
- }, trimmed.includes('{')));
97
+ }, trimmed.includes('{'), { span: trimmed.includes('{') ? braceBlockSpan(input, lines, index) : undefined }));
129
98
  } else if ((match = trimmed.match(/^var\s+([A-Za-z_]\w*)\b/))) {
130
99
  declarations.push(nativeDeclaration(input, number, 'VarDecl', 'variable', match[1], {}, false));
131
100
  } else if ((match = trimmed.match(/^const\s+([A-Za-z_]\w*)\b/))) {
@@ -135,82 +104,6 @@ function scanGo(input) {
135
104
  return declarations;
136
105
  }
137
106
 
138
- function scanSwift(input) {
139
- const declarations = [];
140
- const protocols = new Set();
141
- for (const { line, number } of sourceLines(input.sourceText)) {
142
- const trimmed = line.trim();
143
- const declarationLine = trimmed.replace(/^(?:@[A-Za-z_][\w.]+(?:\([^)]*\))?\s+)*/, '');
144
- let match;
145
- if ((match = declarationLine.match(/^import\s+(?:(?:struct|class|enum|protocol|func|var)\s+)?([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)/))) {
146
- declarations.push(nativeImportDeclaration(input, number, match[1], 'ImportDecl', 'module'));
147
- } else if ((match = declarationLine.match(/^(?:(?:public|private(?:\([^)]*\))?|fileprivate|internal|open|final|indirect)\s+)*(struct|class|enum|protocol|actor)\s+([A-Za-z_]\w*)/))) {
148
- if (match[1] === 'protocol') protocols.add(match[2]);
149
- declarations.push(nativeDeclaration(input, number, `${upperFirst(match[1])}Decl`, swiftSymbolKind(match[1]), match[2], {}, declarationLine.includes('{')));
150
- } else if ((match = declarationLine.match(/^(?:(?:public|private(?:\([^)]*\))?|fileprivate|internal|open)\s+)*extension\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)(.*)$/))) {
151
- const extensionFields = parseSwiftExtensionTail(match[2]);
152
- const isProtocolExtension = protocols.has(match[1]) || /Protocol$/.test(match[1]);
153
- declarations.push(nativeDeclaration(input, number, isProtocolExtension ? 'ProtocolExtensionDecl' : 'ExtensionDecl', 'implementation', `${match[1]}.${isProtocolExtension ? 'protocolExtension' : 'extension'}`, {
154
- extendedType: match[1],
155
- ...extensionFields
156
- }, declarationLine.includes('{')));
157
- } else if ((match = declarationLine.match(/^(?:(?:public|private(?:\([^)]*\))?|fileprivate|internal|open|static|class|mutating|nonmutating|override|required|convenience|isolated|nonisolated)\s+)*func\s+([A-Za-z_]\w*|`[^`]+`)(?:\s*<([^>]+)>)?\s*\(([^)]*)\)/))) {
158
- declarations.push(nativeDeclaration(input, number, 'FunctionDecl', 'function', unquoteSwiftIdentifier(match[1]), {
159
- typeParameters: splitTypeParameters(match[2]),
160
- parameters: splitParameters(match[3])
161
- }, declarationLine.includes('{')));
162
- } else if ((match = declarationLine.match(/^(?:(?:public|private(?:\([^)]*\))?|fileprivate|internal|open|static|class|final|lazy|weak|unowned|override|required|nonisolated)\s+)*(let|var)\s+([A-Za-z_]\w*)\b(?::\s*([^={]+))?/))) {
163
- declarations.push(nativeDeclaration(input, number, 'PropertyDecl', 'property', match[2], {
164
- binding: match[1],
165
- valueType: match[3]?.trim()
166
- }, declarationLine.includes('{') || declarationLine.includes('=>')));
167
- } else if ((match = declarationLine.match(/^(?:(?:public|private(?:\([^)]*\))?|fileprivate|internal|open)\s+)*typealias\s+([A-Za-z_]\w*)\b(?:\s*=\s*(.+))?/))) {
168
- declarations.push(nativeDeclaration(input, number, 'TypealiasDecl', 'type', match[1], { target: match[2]?.trim() }, false));
169
- }
170
- }
171
- return declarations;
172
- }
173
-
174
- function scanCSharp(input) {
175
- const declarations = [];
176
- for (const { line, number } of sourceLines(input.sourceText)) {
177
- const trimmed = line.trim();
178
- let match;
179
- if ((match = trimmed.match(/^using\s+([A-Za-z_]\w*)\s*=\s*(.+?)\s*;/))) {
180
- declarations.push(nativeDeclaration(input, number, 'UsingAliasDirective', 'type', match[1], { target: match[2].trim() }, false));
181
- } else if ((match = trimmed.match(/^using\s+(?:static\s+)?([A-Za-z_][\w.]*)\s*;/))) {
182
- declarations.push(nativeImportDeclaration(input, number, match[1], 'UsingDirective', 'namespace'));
183
- } else if ((match = trimmed.match(/^namespace\s+([A-Za-z_][\w.]*)/))) {
184
- declarations.push(nativeDeclaration(input, number, 'NamespaceDeclaration', 'namespace', match[1], {}, trimmed.includes('{')));
185
- } else if ((match = trimmed.match(/^(?:(?:public|protected|private|internal|static|unsafe|new)\s+)*delegate\s+(.+?)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*;/))) {
186
- declarations.push(nativeDeclaration(input, number, 'DelegateDeclaration', 'type', match[2], {
187
- returnType: match[1].trim(),
188
- parameters: splitParameters(match[3])
189
- }, false));
190
- } else if ((match = trimmed.match(/^(?:(?:public|protected|private|internal|abstract|sealed|static|partial|readonly|ref|unsafe)\s+)*(class|interface|struct|enum|record(?:\s+(?:class|struct))?)\s+([A-Za-z_]\w*)/))) {
191
- declarations.push(nativeDeclaration(input, number, csharpDeclarationKind(match[1]), csharpSymbolKind(match[1]), match[2], { csharpKind: match[1].replace(/\s+/g, ' ') }, trimmed.includes('{')));
192
- } else if ((match = trimmed.match(/^(?:(?:public|protected|private|internal|static|virtual|override|async|partial|sealed|abstract|extern|new|unsafe|readonly)\s+)*(?:[A-Za-z_][\w<>\[\].?,\s]*\??|void)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*(?:=>.*|\{|;)?$/))) {
193
- const parameters = splitParameters(match[2]);
194
- const extensionReceiver = csharpExtensionReceiver(parameters);
195
- declarations.push(nativeDeclaration(input, number, extensionReceiver ? 'ExtensionMethodDeclaration' : 'MethodDeclaration', 'method', match[1], {
196
- parameters,
197
- ...(extensionReceiver ? { extensionReceiver } : {})
198
- }, trimmed.includes('{') || trimmed.includes('=>')));
199
- } else if ((match = trimmed.match(/^(?:(?:public|protected|private|internal|static|virtual|override|abstract|sealed|new|unsafe)\s+)*event\s+(.+?)\s+([A-Za-z_]\w*)\s*(?:[;{=]|=>)/))) {
200
- declarations.push(nativeDeclaration(input, number, 'EventDeclaration', 'event', match[2], {
201
- eventType: match[1].trim(),
202
- accessors: csharpAccessors(trimmed)
203
- }, trimmed.includes('{')));
204
- } else if ((match = trimmed.match(/^(?:(?:public|protected|private|internal|static|virtual|override|abstract|sealed|new|required|readonly|unsafe)\s+)*([A-Za-z_][\w<>\[\].?,\s]*\??)\s+([A-Za-z_]\w*)\s*(?:\{|=>)/))) {
205
- declarations.push(nativeDeclaration(input, number, 'PropertyDeclaration', 'property', match[2], {
206
- propertyType: match[1].trim(),
207
- accessors: csharpAccessors(trimmed)
208
- }, trimmed.includes('{') || trimmed.includes('=>')));
209
- }
210
- }
211
- return declarations;
212
- }
213
-
214
107
  function parseGoReceiver(raw) {
215
108
  const value = String(raw ?? '').trim();
216
109
  const match = value.match(/^(?:(\w+)\s+)?(.+)$/);
@@ -235,67 +128,8 @@ function goReceiverMethodName(receiver, methodName) {
235
128
  return receiver?.type ? `${receiver.type}.${methodName}` : methodName;
236
129
  }
237
130
 
238
- function parseSwiftExtensionTail(rawTail) {
239
- let tail = String(rawTail ?? '').split('{')[0].trim();
240
- const fields = {};
241
- const whereMatch = tail.match(/\bwhere\b(.+)$/);
242
- if (whereMatch) {
243
- fields.constraints = whereMatch[1].trim();
244
- tail = tail.slice(0, whereMatch.index).trim();
245
- }
246
- if (tail.startsWith(':')) {
247
- fields.conformances = tail.slice(1).split(',').map((part) => part.trim()).filter(Boolean);
248
- }
249
- return fields;
250
- }
251
-
252
- function unquoteSwiftIdentifier(identifier) {
253
- return String(identifier).replace(/^`|`$/g, '');
254
- }
255
-
256
- function javaSymbolKind(kind) {
257
- if (kind === 'interface' || kind === '@interface') return 'interface';
258
- if (kind === 'enum' || kind === 'record') return 'type';
259
- return 'class';
260
- }
261
-
262
- function swiftSymbolKind(kind) {
263
- if (kind === 'protocol') return 'protocol';
264
- if (kind === 'extension') return 'implementation';
265
- if (kind === 'struct' || kind === 'enum' || kind === 'actor') return 'type';
266
- return 'class';
267
- }
268
-
269
- function csharpSymbolKind(kind) {
270
- const normalized = String(kind).replace(/\s+/g, ' ');
271
- if (normalized === 'interface') return 'interface';
272
- if (normalized === 'struct' || normalized === 'enum' || normalized.startsWith('record')) return 'type';
273
- return 'class';
274
- }
275
-
276
- function csharpDeclarationKind(kind) {
277
- const normalized = String(kind).replace(/\s+/g, ' ');
278
- if (normalized === 'record struct') return 'RecordStructDeclaration';
279
- if (normalized === 'record class') return 'RecordClassDeclaration';
280
- if (normalized === 'record') return 'RecordDeclaration';
281
- return `${upperFirst(normalized)}Declaration`;
282
- }
283
-
284
- function csharpExtensionReceiver(parameters) {
285
- const match = String(parameters?.[0] ?? '').match(/^this\s+(.+?)\s+([A-Za-z_]\w*)$/);
286
- return match ? { type: match[1].trim(), name: match[2] } : undefined;
287
- }
288
-
289
- function csharpAccessors(source) {
290
- return uniqueStrings([...String(source ?? '').matchAll(/\b(get|set|init|add|remove)\b/g)].map((match) => match[1]));
291
- }
292
-
293
131
  export {
294
132
  scanCLike,
295
- scanCSharp,
296
133
  scanGo,
297
- scanJava,
298
- scanPython,
299
- scanRust,
300
- scanSwift
134
+ scanRust
301
135
  };