@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
@@ -4,125 +4,22 @@ import {
4
4
  nativeImportDeclaration,
5
5
  nativeMacroLoss,
6
6
  sourceLines,
7
- splitParameters,
8
- splitTypeParameters
7
+ splitParameters
9
8
  } from './native-region-scanner-core.js';
10
-
11
- function scanPhp(input) {
12
- const declarations = [];
13
- for (const { line, number } of sourceLines(input.sourceText)) {
14
- const trimmed = line.trim().replace(/^<\?php\s*/, '');
15
- let match;
16
- if ((match = trimmed.match(/^namespace\s+([A-Za-z_][\w\\]*)\s*;/))) {
17
- declarations.push(nativeDeclaration(input, number, 'NamespaceDefinition', 'namespace', match[1], {}, false));
18
- } else if ((match = trimmed.match(/^use\s+([A-Za-z_][\w\\]*)(?:\s+as\s+([A-Za-z_]\w*))?\s*;/))) {
19
- declarations.push(nativeImportDeclaration(input, number, match[1], 'UseDeclaration', 'namespace'));
20
- } else if ((match = trimmed.match(/^(?:(?:abstract|final|readonly)\s+)*(class|interface|trait|enum)\s+([A-Za-z_]\w*)/))) {
21
- declarations.push(nativeDeclaration(input, number, `${upperFirst(match[1])}Declaration`, phpSymbolKind(match[1]), match[2], {}, trimmed.includes('{')));
22
- } else if ((match = trimmed.match(/^(?:(?:public|protected|private|static|final|abstract)\s+)*function\s+&?\s*([A-Za-z_]\w*)\s*\(([^)]*)\)/))) {
23
- declarations.push(nativeDeclaration(input, number, 'FunctionDeclaration', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.includes('{')));
24
- }
25
- }
26
- return declarations;
27
- }
28
-
29
- function scanRuby(input) {
30
- const declarations = [];
31
- for (const { line, number } of sourceLines(input.sourceText)) {
32
- const trimmed = line.trim();
33
- let match;
34
- if ((match = trimmed.match(/^(?:require|load)\s+['"]([^'"]+)['"]/))) {
35
- declarations.push(nativeImportDeclaration(input, number, match[1], 'Require', 'module'));
36
- } else if ((match = trimmed.match(/^module\s+([A-Za-z_]\w*(?:::[A-Za-z_]\w*)*)/))) {
37
- declarations.push(nativeDeclaration(input, number, 'Module', 'module', match[1], {}, true));
38
- } else if ((match = trimmed.match(/^class\s+([A-Za-z_]\w*(?:::[A-Za-z_]\w*)*)/))) {
39
- declarations.push(nativeDeclaration(input, number, 'Class', 'class', match[1], {}, true));
40
- } else if ((match = trimmed.match(/^def\s+(?:self\.)?([A-Za-z_]\w*[!?=]?)\s*(?:\(([^)]*)\)|([^#=]*))?/))) {
41
- declarations.push(nativeDeclaration(input, number, 'Def', 'method', match[1], { parameters: splitParameters(match[2] ?? match[3]) }, true));
42
- }
43
- }
44
- return declarations;
45
- }
46
-
47
- function scanKotlin(input) {
48
- const declarations = [];
49
- for (const { line, number } of sourceLines(input.sourceText)) {
50
- const trimmed = line.trim();
51
- let match;
52
- if ((match = trimmed.match(/^package\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)/))) {
53
- declarations.push(nativeDeclaration(input, number, 'PackageHeader', 'package', match[1], {}, false));
54
- } else if ((match = trimmed.match(/^import\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*(?:\.\*)?)(?:\s+as\s+[A-Za-z_]\w*)?$/))) {
55
- declarations.push(nativeImportDeclaration(input, number, match[1], 'ImportDirective', 'package'));
56
- } 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*)/))) {
57
- declarations.push(nativeDeclaration(input, number, kotlinDeclarationKind(match[2], match[1]), kotlinSymbolKind(match[2], match[1]), match[3], {}, trimmed.includes('{')));
58
- } 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*\(([^)]*)\)/))) {
59
- declarations.push(nativeDeclaration(input, number, 'FunctionDeclaration', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.includes('{') || trimmed.includes('=')));
60
- } else if ((match = trimmed.match(/^(?:(?:public|private|protected|internal|expect|actual)\s+)*typealias\s+([A-Za-z_]\w*)\s*=/))) {
61
- declarations.push(nativeDeclaration(input, number, 'TypeAliasDeclaration', 'type', match[1], {}, false));
62
- } 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/))) {
63
- declarations.push(nativeDeclaration(input, number, 'PropertyDeclaration', 'variable', match[1], {}, false));
64
- }
65
- }
66
- return declarations;
67
- }
68
-
69
- function scanScala(input) {
70
- const declarations = [];
71
- for (const { line, number } of sourceLines(input.sourceText)) {
72
- const trimmed = line.trim();
73
- let match;
74
- if ((match = trimmed.match(/^package\s+([A-Za-z_]\w*(?:\.[A-Za-z_]\w*)*)/))) {
75
- declarations.push(nativeDeclaration(input, number, 'PackageClause', 'package', match[1], {}, false));
76
- } else if ((match = trimmed.match(/^import\s+(.+?);?$/))) {
77
- declarations.push(nativeImportDeclaration(input, number, match[1].trim(), 'Import', 'package'));
78
- } else if ((match = trimmed.match(/^(?:(?:private|protected|final|sealed|abstract|case|implicit|lazy|override|inline|transparent|open)\s+)*(class|trait|object|enum)\s+([A-Za-z_]\w*)/))) {
79
- declarations.push(nativeDeclaration(input, number, `${upperFirst(match[1])}Def`, scalaSymbolKind(match[1]), match[2], {}, trimmed.includes('{') || trimmed.includes(':')));
80
- } else if ((match = trimmed.match(/^(?:(?:private|protected|final|implicit|override|inline)\s+)*def\s+([A-Za-z_]\w*)\s*(?:\[[^\]]+\])?\s*\(([^)]*)\)/))) {
81
- declarations.push(nativeDeclaration(input, number, 'DefDef', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.includes('{') || trimmed.includes('=')));
82
- } else if ((match = trimmed.match(/^(?:(?:private|protected|final|implicit|opaque)\s+)*type\s+([A-Za-z_]\w*)\b/))) {
83
- declarations.push(nativeDeclaration(input, number, 'TypeDef', 'type', match[1], {}, false));
84
- } else if ((match = trimmed.match(/^(?:(?:private|protected|final|implicit|lazy|override|inline)\s+)*(?:val|var)\s+([A-Za-z_]\w*)\b/))) {
85
- declarations.push(nativeDeclaration(input, number, 'ValDef', 'variable', match[1], {}, false));
86
- }
87
- }
88
- return declarations;
89
- }
90
-
91
- function scanDart(input) {
92
- const declarations = [];
93
- for (const { line, number } of sourceLines(input.sourceText)) {
94
- const trimmed = line.trim();
95
- let match;
96
- if ((match = trimmed.match(/^(?:import|export)\s+['"]([^'"]+)['"]/))) {
97
- declarations.push(nativeImportDeclaration(input, number, match[1], 'UriBasedDirective', 'library'));
98
- } else if ((match = trimmed.match(/^part\s+['"]([^'"]+)['"]/))) {
99
- declarations.push(nativeImportDeclaration(input, number, match[1], 'PartDirective', 'library'));
100
- } else if ((match = trimmed.match(/^(?:(?:abstract|base|final|interface|sealed)\s+)*(class|mixin|enum)\s+([A-Za-z_]\w*)/))) {
101
- declarations.push(nativeDeclaration(input, number, `${upperFirst(match[1])}Declaration`, dartSymbolKind(match[1]), match[2], {}, trimmed.includes('{')));
102
- } else if ((match = trimmed.match(/^extension\s+([A-Za-z_]\w*)\s+on\s+.+\{/))) {
103
- declarations.push(nativeDeclaration(input, number, 'ExtensionDeclaration', 'implementation', match[1], {}, true));
104
- } else if ((match = trimmed.match(/^typedef\s+([A-Za-z_]\w*)\b/))) {
105
- declarations.push(nativeDeclaration(input, number, 'TypeAlias', 'type', match[1], {}, false));
106
- } else if ((match = trimmed.match(/^(?:(?:external|static)\s+)*(?:[A-Za-z_]\w*(?:<[^>]+>)?\??|void)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*(?:async\s*)?(?:\{|=>|;)/))) {
107
- declarations.push(nativeDeclaration(input, number, 'FunctionDeclaration', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.includes('{') || trimmed.includes('=>')));
108
- } else if ((match = trimmed.match(/^(?:(?:static|external|late)\s+)*(?:const|final|var)\s+(?:[A-Za-z_]\w*(?:<[^>]+>)?\??\s+)?([A-Za-z_]\w*)\b/))) {
109
- declarations.push(nativeDeclaration(input, number, 'VariableDeclaration', 'variable', match[1], {}, false));
110
- }
111
- }
112
- return declarations;
113
- }
9
+ import { braceBlockSpan, endKeywordBlockSpan, sqlStatementSpan } from './native-region-scanner-spans.js';
114
10
 
115
11
  function scanLua(input) {
116
12
  const declarations = [];
117
- for (const { line, number } of sourceLines(input.sourceText)) {
13
+ const lines = sourceLines(input.sourceText);
14
+ for (const [index, { line, number }] of lines.entries()) {
118
15
  const trimmed = line.trim();
119
16
  let match;
120
17
  if ((match = trimmed.match(/^(?:local\s+[A-Za-z_]\w*\s*=\s*)?require\s*\(?\s*['"]([^'"]+)['"]\s*\)?/))) {
121
18
  declarations.push(nativeImportDeclaration(input, number, match[1], 'RequireCall', 'module'));
122
19
  } else if ((match = trimmed.match(/^(?:local\s+)?function\s+([A-Za-z_]\w*(?:[.:][A-Za-z_]\w*)*)\s*\(([^)]*)\)/))) {
123
- declarations.push(nativeDeclaration(input, number, 'FunctionDeclaration', 'function', match[1], { parameters: splitParameters(match[2]) }, true));
20
+ declarations.push(nativeDeclaration(input, number, 'FunctionDeclaration', 'function', match[1], { parameters: splitParameters(match[2]) }, true, endSpanOptions(input, lines, index)));
124
21
  } else if ((match = trimmed.match(/^(?:local\s+)?([A-Za-z_]\w*(?:[.:][A-Za-z_]\w*)*)\s*=\s*function\s*\(([^)]*)\)/))) {
125
- declarations.push(nativeDeclaration(input, number, 'FunctionAssignment', 'function', match[1], { parameters: splitParameters(match[2]) }, true));
22
+ declarations.push(nativeDeclaration(input, number, 'FunctionAssignment', 'function', match[1], { parameters: splitParameters(match[2]) }, true, endSpanOptions(input, lines, index)));
126
23
  } else if ((match = trimmed.match(/^local\s+([A-Za-z_]\w*)\s*=\s*(?:\{|\w+)/))) {
127
24
  declarations.push(nativeDeclaration(input, number, 'LocalDeclaration', 'variable', match[1], {}, false));
128
25
  }
@@ -132,15 +29,16 @@ function scanLua(input) {
132
29
 
133
30
  function scanShell(input) {
134
31
  const declarations = [];
135
- for (const { line, number } of sourceLines(input.sourceText)) {
32
+ const lines = sourceLines(input.sourceText);
33
+ for (const [index, { line, number }] of lines.entries()) {
136
34
  const trimmed = line.trim();
137
35
  let match;
138
36
  if ((match = trimmed.match(/^(?:source|\.)\s+(?:"([^"]+)"|'([^']+)'|([./A-Za-z0-9_-][\w./-]*))(?:\s|$)/))) {
139
37
  declarations.push(nativeImportDeclaration(input, number, match[1] ?? match[2] ?? match[3], 'SourceCommand', 'file'));
140
38
  } else if ((match = trimmed.match(/^function\s+([A-Za-z_][\w-]*)\s*(?:\(\s*\))?\s*(?:\{|$)/))) {
141
- declarations.push(nativeDeclaration(input, number, 'FunctionDefinition', 'function', match[1], {}, true));
39
+ declarations.push(nativeDeclaration(input, number, 'FunctionDefinition', 'function', match[1], {}, true, spanOptions(input, lines, index, trimmed.includes('{'))));
142
40
  } else if ((match = trimmed.match(/^([A-Za-z_][\w-]*)\s*\(\s*\)\s*(?:\{|$)/))) {
143
- declarations.push(nativeDeclaration(input, number, 'FunctionDefinition', 'function', match[1], {}, true));
41
+ declarations.push(nativeDeclaration(input, number, 'FunctionDefinition', 'function', match[1], {}, true, spanOptions(input, lines, index, trimmed.includes('{'))));
144
42
  } else if ((match = trimmed.match(/^(?:export\s+)?(?:readonly\s+)?([A-Za-z_]\w*)=/))) {
145
43
  declarations.push(nativeDeclaration(input, number, 'VariableAssignment', 'variable', match[1], {}, false));
146
44
  } else if ((match = trimmed.match(/^alias\s+([A-Za-z_][\w-]*)=/))) {
@@ -152,14 +50,15 @@ function scanShell(input) {
152
50
 
153
51
  function scanSql(input) {
154
52
  const declarations = [];
155
- for (const { line, number } of sourceLines(input.sourceText)) {
53
+ const lines = sourceLines(input.sourceText);
54
+ for (const [index, { line, number }] of lines.entries()) {
156
55
  const trimmed = line.trim();
157
56
  let match;
158
57
  if ((match = trimmed.match(/^CREATE\s+EXTENSION\s+(?:IF\s+NOT\s+EXISTS\s+)?((?:"[^"]+"|`[^`]+`|\[[^\]]+\]|[A-Za-z_][\w$-]*))/i))) {
159
58
  declarations.push(nativeImportDeclaration(input, number, normalizeSqlIdentifier(match[1]), 'CreateExtensionStatement', 'extension'));
160
59
  } else if ((match = trimmed.match(/^CREATE\s+(?:OR\s+REPLACE\s+)?(?:TEMP(?:ORARY)?\s+)?((?:UNIQUE\s+)?INDEX|MATERIALIZED\s+VIEW|TABLE|VIEW|FUNCTION|PROCEDURE|TRIGGER|SCHEMA|TYPE)\s+(?:IF\s+NOT\s+EXISTS\s+)?((?:"[^"]+"|`[^`]+`|\[[^\]]+\]|[A-Za-z_][\w$]*)(?:\s*\.\s*(?:"[^"]+"|`[^`]+`|\[[^\]]+\]|[A-Za-z_][\w$]*))?)/i))) {
161
60
  const objectKind = match[1].toUpperCase().replace(/\s+/g, ' ');
162
- declarations.push(nativeDeclaration(input, number, sqlLanguageKind(objectKind), sqlSymbolKind(objectKind), normalizeSqlIdentifier(match[2]), { objectKind }, trimmed.includes('(')));
61
+ declarations.push(nativeDeclaration(input, number, sqlLanguageKind(objectKind), sqlSymbolKind(objectKind), normalizeSqlIdentifier(match[2]), { objectKind }, trimmed.includes('('), { span: sqlStatementSpan(input, lines, index) }));
163
62
  }
164
63
  }
165
64
  return declarations;
@@ -167,7 +66,8 @@ function scanSql(input) {
167
66
 
168
67
  function scanZig(input) {
169
68
  const declarations = [];
170
- for (const { line, number } of sourceLines(input.sourceText)) {
69
+ const lines = sourceLines(input.sourceText);
70
+ for (const [index, { line, number }] of lines.entries()) {
171
71
  const trimmed = line.trim();
172
72
  let match;
173
73
  if ((match = trimmed.match(/^(?:(?:pub|export)\s+)?(?:const|var)\s+([A-Za-z_]\w*)\s*=\s*@import\(\s*["']([^"']+)["']\s*\)\s*;?/))) {
@@ -175,9 +75,9 @@ function scanZig(input) {
175
75
  } else if ((match = trimmed.match(/^(?:(?:pub|export)\s+)?usingnamespace\s+@import\(\s*["']([^"']+)["']\s*\)\s*;?/))) {
176
76
  declarations.push(nativeImportDeclaration(input, number, match[1], 'UsingNamespaceImport', 'module'));
177
77
  } else if ((match = trimmed.match(/^(?:(?:pub|export)\s+)?const\s+([A-Za-z_]\w*)\s*=\s*(?:extern\s+)?(struct|enum|union|opaque|error)\b/))) {
178
- declarations.push(nativeDeclaration(input, number, `Const${upperFirst(match[2])}Declaration`, 'type', match[1], { zigKind: match[2] }, trimmed.includes('{')));
78
+ declarations.push(nativeDeclaration(input, number, `Const${upperFirst(match[2])}Declaration`, 'type', match[1], { zigKind: match[2] }, trimmed.includes('{'), spanOptions(input, lines, index, trimmed.includes('{'))));
179
79
  } else if ((match = trimmed.match(/^(?:(?:pub|export|extern|inline)\s+)*(?:fn)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)/))) {
180
- declarations.push(nativeDeclaration(input, number, 'FnDeclaration', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.includes('{')));
80
+ declarations.push(nativeDeclaration(input, number, 'FnDeclaration', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.includes('{'), spanOptions(input, lines, index, trimmed.includes('{'))));
181
81
  } else if ((match = trimmed.match(/^(?:(?:pub|export)\s+)?const\s+([A-Za-z_]\w*)\b/))) {
182
82
  declarations.push(nativeDeclaration(input, number, 'ConstDeclaration', 'constant', match[1], {}, false));
183
83
  } else if ((match = trimmed.match(/^(?:(?:pub|export)\s+)?var\s+([A-Za-z_]\w*)\b/))) {
@@ -190,37 +90,12 @@ function scanZig(input) {
190
90
  return declarations;
191
91
  }
192
92
 
193
- function phpSymbolKind(kind) {
194
- if (kind === 'interface') return 'interface';
195
- if (kind === 'trait') return 'trait';
196
- if (kind === 'enum') return 'type';
197
- return 'class';
198
- }
199
-
200
- function kotlinDeclarationKind(kind, prefix) {
201
- if (prefix === 'enum') return 'EnumClassDeclaration';
202
- if (prefix === 'annotation') return 'AnnotationClassDeclaration';
203
- return `${upperFirst(kind)}Declaration`;
204
- }
205
-
206
- function kotlinSymbolKind(kind, prefix) {
207
- if (kind === 'interface') return 'interface';
208
- if (kind === 'object') return 'module';
209
- if (prefix === 'enum' || prefix === 'annotation') return 'type';
210
- return 'class';
211
- }
212
-
213
- function scalaSymbolKind(kind) {
214
- if (kind === 'trait') return 'trait';
215
- if (kind === 'object') return 'module';
216
- if (kind === 'enum') return 'type';
217
- return 'class';
93
+ function spanOptions(input, lines, index, hasBraceBody) {
94
+ return hasBraceBody ? { span: braceBlockSpan(input, lines, index) } : {};
218
95
  }
219
96
 
220
- function dartSymbolKind(kind) {
221
- if (kind === 'mixin') return 'trait';
222
- if (kind === 'enum') return 'type';
223
- return 'class';
97
+ function endSpanOptions(input, lines, index) {
98
+ return { span: endKeywordBlockSpan(input, lines, index) };
224
99
  }
225
100
 
226
101
  function sqlSymbolKind(kind) {
@@ -247,12 +122,7 @@ function zigMetaName(source) {
247
122
  }
248
123
 
249
124
  export {
250
- scanDart,
251
- scanKotlin,
252
125
  scanLua,
253
- scanPhp,
254
- scanRuby,
255
- scanScala,
256
126
  scanShell,
257
127
  scanSql,
258
128
  scanZig
@@ -6,17 +6,19 @@ import {
6
6
  sourceLines,
7
7
  splitParameters
8
8
  } from './native-region-scanner-core.js';
9
+ import { braceBlockSpan, endKeywordBlockSpan, pythonBlockSpan, terminatedBlockSpan } from './native-region-scanner-spans.js';
9
10
 
10
11
  function scanElixir(input) {
11
12
  const declarations = [];
12
13
  let currentModule;
13
- for (const { line, number } of sourceLines(input.sourceText)) {
14
+ const lines = sourceLines(input.sourceText);
15
+ for (const [index, { line, number }] of lines.entries()) {
14
16
  const trimmed = line.trim();
15
17
  let match;
16
18
  let recordedMeta = false;
17
19
  if ((match = trimmed.match(/^defmodule\s+([A-Z]\w*(?:\.[A-Z]\w*)*)\s+do\b/))) {
18
20
  currentModule = match[1];
19
- declarations.push(nativeDeclaration(input, number, 'ModuleDefinition', 'module', match[1], {}, true));
21
+ declarations.push(nativeDeclaration(input, number, 'ModuleDefinition', 'module', match[1], {}, true, endSpanOptions(input, lines, index)));
20
22
  } else if ((match = trimmed.match(/^(?:alias|import|require)\s+([A-Z]\w*(?:\.[A-Z]\w*)*)/))) {
21
23
  declarations.push(nativeImportDeclaration(input, number, match[1], 'ImportDirective', 'module'));
22
24
  } else if ((match = trimmed.match(/^use\s+([A-Z]\w*(?:\.[A-Z]\w*)*)/))) {
@@ -26,7 +28,8 @@ function scanElixir(input) {
26
28
  declarations.push(nativeMacroLoss(input, number, trimmed, 'macroExpansion', match[2]));
27
29
  recordedMeta = true;
28
30
  } else if ((match = trimmed.match(/^defp?\s+([A-Za-z_]\w*[!?]?)\s*(?:\(([^)]*)\)|([^,]*))?/))) {
29
- declarations.push(nativeDeclaration(input, number, 'FunctionDefinition', 'function', match[1], { parameters: splitParameters(match[2] ?? match[3]) }, /\bdo\b/.test(trimmed)));
31
+ const hasDoBlock = /\bdo\b/.test(trimmed);
32
+ declarations.push(nativeDeclaration(input, number, 'FunctionDefinition', 'function', match[1], { parameters: splitParameters(match[2] ?? match[3]) }, hasDoBlock, hasDoBlock ? endSpanOptions(input, lines, index) : {}));
30
33
  } else if (trimmed.startsWith('defstruct')) {
31
34
  declarations.push(nativeDeclaration(input, number, 'StructDefinition', 'type', currentModule ?? `struct_${number}`, {}, true));
32
35
  } else if ((match = trimmed.match(/^@(type|typep|opaque|callback)\s+([A-Za-z_]\w*[!?]?)/))) {
@@ -39,10 +42,19 @@ function scanElixir(input) {
39
42
  return declarations;
40
43
  }
41
44
 
45
+ function endSpanOptions(input, lines, index) {
46
+ return { span: endKeywordBlockSpan(input, lines, index) };
47
+ }
48
+
49
+ function braceSpanOptions(input, lines, index, hasBraceBody) {
50
+ return hasBraceBody ? { span: braceBlockSpan(input, lines, index) } : {};
51
+ }
52
+
42
53
  function scanErlang(input) {
43
54
  const declarations = [];
44
55
  const seenFunctions = new Set();
45
- for (const { line, number } of sourceLines(input.sourceText)) {
56
+ const lines = sourceLines(input.sourceText);
57
+ for (const [index, { line, number }] of lines.entries()) {
46
58
  const trimmed = line.trim();
47
59
  let match;
48
60
  let recordedMacro = false;
@@ -70,7 +82,7 @@ function scanErlang(input) {
70
82
  const name = erlangAtomName(match[1]);
71
83
  if (!seenFunctions.has(name)) {
72
84
  seenFunctions.add(name);
73
- declarations.push(nativeDeclaration(input, number, 'FunctionClause', 'function', name, { parameters: splitParameters(match[2]) }, true));
85
+ declarations.push(nativeDeclaration(input, number, 'FunctionClause', 'function', name, { parameters: splitParameters(match[2]) }, true, { span: terminatedBlockSpan(input, lines, index, /\.\s*$/) }));
74
86
  }
75
87
  }
76
88
  if (!recordedMacro && /(^|[^A-Za-z0-9_])\?[A-Za-z_]\w*/.test(trimmed)) {
@@ -83,7 +95,8 @@ function scanErlang(input) {
83
95
  function scanHaskell(input) {
84
96
  const declarations = [];
85
97
  const seenFunctions = new Set();
86
- for (const { line, number } of sourceLines(input.sourceText)) {
98
+ const lines = sourceLines(input.sourceText);
99
+ for (const [index, { line, number }] of lines.entries()) {
87
100
  const trimmed = line.trim();
88
101
  let match;
89
102
  if (/^#\s*(?:if|ifdef|ifndef|else|elif|endif|define|include)\b/.test(trimmed)) {
@@ -106,12 +119,15 @@ function scanHaskell(input) {
106
119
  } else if ((match = trimmed.match(/^class\s+(?:\([^)]*\)\s*=>\s*)?([A-Z][A-Za-z0-9_']*)\b/))) {
107
120
  declarations.push(nativeDeclaration(input, number, 'ClassDeclaration', 'type', match[1], {}, /\bwhere\b/.test(trimmed)));
108
121
  } else if ((match = trimmed.match(/^([a-z_][A-Za-z0-9_']*)\s*::\s*(.+)$/))) {
109
- seenFunctions.add(match[1]);
110
- declarations.push(nativeDeclaration(input, number, 'FunctionSignature', 'function', match[1], { signature: match[2].trim() }, false));
122
+ declarations.push(nativeDeclaration(input, number, 'FunctionSignature', 'function', match[1], { signature: match[2].trim() }, false, {
123
+ regionKind: 'declaration',
124
+ symbolId: `symbol:${input.language}:signature:${idFragment(match[1])}`,
125
+ metadata: { signatureOnly: true }
126
+ }));
111
127
  } else if ((match = trimmed.match(/^([a-z_][A-Za-z0-9_']*)\b[^=]*=/))) {
112
128
  if (!seenFunctions.has(match[1])) {
113
129
  seenFunctions.add(match[1]);
114
- declarations.push(nativeDeclaration(input, number, 'FunctionBinding', 'function', match[1], {}, true));
130
+ declarations.push(nativeDeclaration(input, number, 'FunctionBinding', 'function', match[1], {}, true, { span: pythonBlockSpan(input, lines, index) }));
115
131
  }
116
132
  }
117
133
  }
@@ -120,7 +136,8 @@ function scanHaskell(input) {
120
136
 
121
137
  function scanR(input) {
122
138
  const declarations = [];
123
- for (const { line, number } of sourceLines(input.sourceText)) {
139
+ const lines = sourceLines(input.sourceText);
140
+ for (const [index, { line, number }] of lines.entries()) {
124
141
  const trimmed = line.trim();
125
142
  let match;
126
143
  if ((match = trimmed.match(/^(?:library|require)\s*\(\s*["']?([A-Za-z_][\w.-]*)["']?/))) {
@@ -130,7 +147,7 @@ function scanR(input) {
130
147
  } else if ((match = trimmed.match(/^source\s*\(\s*["']([^"']+)["']/))) {
131
148
  declarations.push(nativeImportDeclaration(input, number, match[1], 'SourceCall', 'module'));
132
149
  } else if ((match = trimmed.match(/^([A-Za-z_][\w.]*)\s*(?:<-|=)\s*function\s*\(([^)]*)\)/))) {
133
- declarations.push(nativeDeclaration(input, number, 'FunctionAssignment', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.includes('{')));
150
+ declarations.push(nativeDeclaration(input, number, 'FunctionAssignment', 'function', match[1], { parameters: splitParameters(match[2]) }, trimmed.includes('{'), braceSpanOptions(input, lines, index, trimmed.includes('{'))));
134
151
  } else if ((match = trimmed.match(/^([A-Za-z_][\w.]*)\s*<-\s*R6Class\s*\(\s*["']([^"']+)["']/))) {
135
152
  declarations.push(nativeDeclaration(input, number, 'R6ClassDeclaration', 'class', match[2] || match[1], { binding: match[1] }, true));
136
153
  declarations.push(nativeMacroLoss(input, number, trimmed, 'dynamicRuntime', match[2] || match[1]));
@@ -154,9 +171,19 @@ function scanR(input) {
154
171
  }
155
172
 
156
173
  function scanGenericDeclarations(input) {
157
- return sourceLines(input.sourceText)
174
+ const lines = sourceLines(input.sourceText);
175
+ return lines
176
+ .map(({ line, number }, index) => ({ line, number, index }))
158
177
  .filter(({ line }) => /\b(function|class|struct|enum|trait|interface|def)\b/.test(line))
159
- .map(({ line, number }) => nativeDeclaration(input, number, 'NativeDeclaration', 'variable', idFragment(line.trim()).slice(0, 40), { source: line.trim() }, true));
178
+ .map(({ line, number, index }) => nativeDeclaration(input, number, 'NativeDeclaration', 'variable', idFragment(line.trim()).slice(0, 40), { source: line.trim() }, true, genericSpanOptions(input, lines, index)));
179
+ }
180
+
181
+ function genericSpanOptions(input, lines, index) {
182
+ const line = lines[index]?.line.trim() ?? '';
183
+ if (line.includes('{')) return { span: braceBlockSpan(input, lines, index) };
184
+ if (/\b(?:class|module|def|function)\b/.test(line)) return { span: endKeywordBlockSpan(input, lines, index) };
185
+ if (/:\s*$/.test(line)) return { span: pythonBlockSpan(input, lines, index) };
186
+ return {};
160
187
  }
161
188
 
162
189
  function elixirMetaName(source) {
@@ -0,0 +1,97 @@
1
+ import { upperFirst } from './native-import-utils.js';
2
+ import { nativeDeclaration, nativeImportDeclaration, sourceLines, splitParameters, splitTypeParameters } from './native-region-scanner-core.js';
3
+ import { braceBlockSpan } from './native-region-scanner-spans.js';
4
+
5
+ function scanJava(input) {
6
+ const declarations = [];
7
+ const blockStack = [];
8
+ const lines = sourceLines(input.sourceText);
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
+
15
+ let match;
16
+ if ((match = trimmed.match(/^package\s+([A-Za-z_][\w.]*);/))) {
17
+ declarations.push(nativeDeclaration(input, number, 'PackageDeclaration', 'package', match[1], {}, false));
18
+ } else if ((match = trimmed.match(/^import\s+(?:static\s+)?([A-Za-z_][\w.*]*);/))) {
19
+ declarations.push(nativeImportDeclaration(input, number, match[1], 'ImportDeclaration', 'package'));
20
+ } 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$]*)/))) {
21
+ const owner = nearestType(blockStack);
22
+ const name = owner ? `${owner.name}.${match[3]}` : match[3];
23
+ const kind = match[2] === '@interface' ? 'AnnotationDeclaration' : `${upperFirst(match[2])}Declaration`;
24
+ const hasBody = trimmed.includes('{');
25
+ declarations.push(nativeDeclaration(input, number, kind, javaSymbolKind(match[2]), name, {
26
+ modifiers: javaModifiers(match[1]),
27
+ ...(owner ? { owner: owner.name } : {})
28
+ }, hasBody, spanOptions(input, lines, index, hasBody)));
29
+ if (hasBody) blockStack.push({ kind: javaTypeStackKind(match[2]), name, bodyDepth: braceDepth + 1 });
30
+ } 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+[^{]+)?(?:\{.*|;)?$/))) {
31
+ const owner = nearestType(blockStack);
32
+ const target = javaMethodTarget(owner, match[1], match[3]);
33
+ const hasBody = trimmed.includes('{');
34
+ declarations.push(nativeDeclaration(input, number, 'MethodDeclaration', target.owner ? 'method' : 'function', target.name, {
35
+ methodName: match[3],
36
+ modifiers: javaModifiers(match[1]),
37
+ typeParameters: splitTypeParameters(match[2]),
38
+ parameters: splitParameters(match[4]),
39
+ ...(target.owner ? { owner: target.owner, receiverKind: target.receiverKind } : {})
40
+ }, hasBody, {
41
+ ...spanOptions(input, lines, index, hasBody),
42
+ metadata: {
43
+ methodName: match[3],
44
+ modifiers: javaModifiers(match[1]),
45
+ ...(target.owner ? { owner: target.owner, receiverKind: target.receiverKind } : {})
46
+ }
47
+ }));
48
+ if (hasBody) blockStack.push({ kind: 'method', name: target.name, bodyDepth: braceDepth + 1 });
49
+ }
50
+ braceDepth = Math.max(0, braceDepth + braceDelta(line));
51
+ }
52
+ return declarations;
53
+ }
54
+
55
+ function spanOptions(input, lines, index, hasBraceBody) {
56
+ return hasBraceBody ? { span: braceBlockSpan(input, lines, index) } : {};
57
+ }
58
+
59
+ function depthAfterLeadingClosers(trimmed, depth) {
60
+ const closers = String(trimmed).match(/^}+/)?.[0].length ?? 0;
61
+ return Math.max(0, depth - closers);
62
+ }
63
+
64
+ function nearestType(blockStack) {
65
+ for (let index = blockStack.length - 1; index >= 0; index -= 1) {
66
+ if (blockStack[index].kind === 'method') return undefined;
67
+ if (['class', 'interface', 'enum', 'record', 'annotation'].includes(blockStack[index].kind)) return blockStack[index];
68
+ }
69
+ return undefined;
70
+ }
71
+
72
+ function javaMethodTarget(owner, modifiers, methodName) {
73
+ if (!owner) return { name: methodName };
74
+ const receiverKind = /\bstatic\b/.test(modifiers) ? 'static' : 'member';
75
+ return { name: receiverKind === 'static' ? `${owner.name}.static.${methodName}` : `${owner.name}.${methodName}`, owner: owner.name, receiverKind };
76
+ }
77
+
78
+ function javaModifiers(raw) {
79
+ return splitParameters(String(raw ?? '').trim().replace(/\s+/g, ','));
80
+ }
81
+
82
+ function javaTypeStackKind(kind) {
83
+ if (kind === '@interface') return 'annotation';
84
+ return String(kind).replace(/\s+/g, ' ');
85
+ }
86
+
87
+ function braceDelta(source) {
88
+ return [...String(source ?? '')].reduce((delta, char) => delta + (char === '{' ? 1 : char === '}' ? -1 : 0), 0);
89
+ }
90
+
91
+ function javaSymbolKind(kind) {
92
+ if (kind === 'interface' || kind === '@interface') return 'interface';
93
+ if (kind === 'enum' || kind === 'record') return 'type';
94
+ return 'class';
95
+ }
96
+
97
+ export { scanJava };
@@ -0,0 +1,100 @@
1
+ import { jsControlKeyword, nativeDeclaration, nativeSignatureDeclaration, splitParameters } from './native-region-scanner-core.js';
2
+ import { jsInitializerKind, jsVariableHasBody } from './native-region-scanner-js-helpers.js';
3
+
4
+ function jsClassMemberDeclaration(input, lineNumber, declarationLine, className) {
5
+ const method = jsClassMethodMatch(declarationLine);
6
+ if (method && !jsControlKeyword(method.name)) return jsClassMethodDeclaration(input, lineNumber, method, className);
7
+ const property = jsClassPropertyMatch(declarationLine);
8
+ if (!property || jsControlKeyword(property.name)) return undefined;
9
+ return jsClassPropertyDeclaration(input, lineNumber, property, className);
10
+ }
11
+
12
+ function jsInlineClassMemberDeclarations(input, lineNumber, declarationLine, className) {
13
+ const open = declarationLine.indexOf('{');
14
+ const close = declarationLine.lastIndexOf('}');
15
+ if (open < 0 || close <= open) return [];
16
+ const body = declarationLine.slice(open + 1, close);
17
+ const declarations = [];
18
+ const pattern = /((?:(?: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;
19
+ for (const match of body.matchAll(pattern)) {
20
+ const method = { modifiers: match[1], name: match[2], parameters: match[3], source: match[0] };
21
+ if (!jsControlKeyword(method.name)) declarations.push(jsClassMethodDeclaration(input, lineNumber, method, className));
22
+ }
23
+ return declarations;
24
+ }
25
+
26
+ function jsClassMethodMatch(declarationLine) {
27
+ const 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*[^={]+)?(?:\{|=>|$)/);
28
+ if (!match) return undefined;
29
+ return { modifiers: match[1], name: match[2], parameters: match[3], source: declarationLine };
30
+ }
31
+
32
+ function jsClassPropertyMatch(declarationLine) {
33
+ const match = declarationLine.match(/^((?:(?:public|private|protected|static|readonly|declare|accessor)\s+)*)(#?[A-Za-z_$][\w$]*)[?!]?\s*(?::\s*([^=;{]+))?(?:[=;]|$)/);
34
+ if (!match) return undefined;
35
+ return { modifiers: match[1], name: match[2], source: declarationLine, valueType: match[3]?.trim() };
36
+ }
37
+
38
+ function jsClassMethodDeclaration(input, lineNumber, method, className) {
39
+ const target = jsClassMemberTarget(className, method.modifiers, method.name);
40
+ const hasBody = String(method.source ?? '').includes('{') || String(method.source ?? '').includes('=>');
41
+ return (hasBody ? nativeDeclaration : nativeSignatureDeclaration)(input, lineNumber, 'MethodDefinition', 'method', target.name, {
42
+ methodName: method.name,
43
+ owner: className,
44
+ receiverKind: target.receiverKind,
45
+ accessorKind: jsAccessorKind(method.modifiers),
46
+ modifiers: jsModifiers(method.modifiers),
47
+ parameters: splitParameters(method.parameters)
48
+ }, hasBody, { metadata: jsClassMemberMetadata(className, target, method.name, method.modifiers) });
49
+ }
50
+
51
+ function jsClassPropertyDeclaration(input, lineNumber, property, className) {
52
+ const initializerKind = jsInitializerKind(property.source ?? '', property.name);
53
+ const hasBody = jsVariableHasBody(initializerKind, property.source ?? '');
54
+ const target = jsClassMemberTarget(className, property.modifiers, property.name);
55
+ return nativeDeclaration(input, lineNumber, 'PropertyDefinition', initializerKind === 'function' ? 'function' : 'property', target.name, {
56
+ propertyName: property.name,
57
+ owner: className,
58
+ receiverKind: target.receiverKind,
59
+ valueType: property.valueType,
60
+ initializerKind,
61
+ modifiers: jsModifiers(property.modifiers)
62
+ }, hasBody, {
63
+ regionKind: initializerKind === 'function' ? 'body' : 'property',
64
+ metadata: {
65
+ initializerKind,
66
+ ...jsClassMemberMetadata(className, target, property.name, property.modifiers)
67
+ }
68
+ });
69
+ }
70
+
71
+ function jsClassMemberTarget(className, modifiers, memberName) {
72
+ const receiverKind = /\bstatic\b/.test(modifiers) ? 'static' : 'member';
73
+ return {
74
+ name: receiverKind === 'static' ? `${className}.static.${memberName}` : `${className}.${memberName}`,
75
+ receiverKind
76
+ };
77
+ }
78
+
79
+ function jsClassMemberMetadata(owner, target, memberName, modifiers) {
80
+ return {
81
+ owner,
82
+ receiverKind: target.receiverKind,
83
+ propertyName: memberName,
84
+ methodName: memberName,
85
+ modifiers: jsModifiers(modifiers),
86
+ accessorKind: jsAccessorKind(modifiers)
87
+ };
88
+ }
89
+
90
+ function jsAccessorKind(modifiers) {
91
+ if (/\bget\b/.test(modifiers)) return 'get';
92
+ if (/\bset\b/.test(modifiers)) return 'set';
93
+ return undefined;
94
+ }
95
+
96
+ function jsModifiers(raw) {
97
+ return String(raw ?? '').trim().split(/\s+/).filter(Boolean);
98
+ }
99
+
100
+ export { jsClassMemberDeclaration, jsInlineClassMemberDeclarations };