@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.
- package/README.md +13 -0
- package/dist/declarations/bidirectional-target-change-source-edit.d.ts +30 -0
- package/dist/declarations/bidirectional-target-change.d.ts +10 -0
- package/dist/declarations/js-ts-safe-member-merge.d.ts +58 -0
- package/dist/declarations/js-ts-safe-merge.d.ts +120 -0
- package/dist/declarations/js-ts-semantic-conflict-sidecars.d.ts +235 -0
- package/dist/declarations/js-ts-semantic-merge-contracts.d.ts +287 -0
- package/dist/declarations/js-ts-semantic-merge.d.ts +4 -0
- package/dist/declarations/native-import-losses.d.ts +3 -0
- package/dist/declarations/semantic-edit-replay-diagnostics.d.ts +12 -0
- package/dist/declarations/semantic-edit-script.d.ts +7 -4
- package/dist/declarations/semantic-patch-bundle-index.d.ts +45 -0
- package/dist/declarations/semantic-patch-bundle.d.ts +6 -4
- package/dist/declarations/semantic-sidecar-example.d.ts +18 -0
- package/dist/declarations/semantic-transform-identity.d.ts +3 -0
- package/dist/declarations/source-preservation.d.ts +72 -0
- package/dist/declarations/universal-capability.d.ts +4 -0
- package/dist/declarations/universal-conversion-artifacts.d.ts +61 -1
- package/dist/declarations/universal-conversion-compact-counts.d.ts +51 -0
- package/dist/declarations/universal-conversion-plan.d.ts +6 -1
- package/dist/declarations/universal-representation-coverage.d.ts +90 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +3 -0
- package/dist/internal/index-impl/bidirectionalExactSourceBackprojection.js +199 -0
- package/dist/internal/index-impl/bidirectionalSameLanguageSourceProjection.js +112 -0
- package/dist/internal/index-impl/bidirectionalSourceEditProjection.js +319 -0
- package/dist/internal/index-impl/bidirectionalSourceEditProjectionArtifacts.js +67 -0
- package/dist/internal/index-impl/bidirectionalTargetChangeRecordInternals.js +17 -5
- package/dist/internal/index-impl/bidirectionalTargetRoundtripEvidence.js +58 -20
- package/dist/internal/index-impl/createBidirectionalTargetChangeRecord.js +60 -7
- package/dist/internal/index-impl/createLightweightNativeImport.js +1 -0
- package/dist/internal/index-impl/createNativeSourcePreservation.js +28 -2
- package/dist/internal/index-impl/diffNativeSymbols.js +3 -3
- package/dist/internal/index-impl/nativeChangeProjectionSourceMapLinks.js +2 -0
- package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +43 -8
- package/dist/internal/index-impl/replaySemanticEditLineEndings.js +34 -0
- package/dist/internal/index-impl/replaySemanticEditProjection.js +39 -19
- package/dist/internal/index-impl/semanticEditBundleAdmission.js +7 -3
- package/dist/internal/index-impl/semanticEditBundleIndex.js +47 -1
- package/dist/internal/index-impl/semanticEditExplicitSourceReplacement.js +40 -0
- package/dist/internal/index-impl/semanticEditOperationCoverage.js +33 -3
- package/dist/internal/index-impl/semanticEditProjectionRecord.js +29 -0
- package/dist/internal/index-impl/semanticEditReplayDiagnostics.js +39 -0
- package/dist/internal/index-impl/semanticEditReplaySourceReplacement.js +85 -0
- package/dist/internal/index-impl/semanticEditScripts.js +4 -0
- package/dist/internal/index-impl/semanticEditSourceRanges.js +27 -0
- package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +1 -0
- package/dist/internal/index-impl/semanticPatchBundleAdmission.js +41 -7
- package/dist/internal/index-impl/semanticPatchBundleRecords.js +16 -0
- package/dist/internal/index-impl/semanticPatchBundleSourceRecords.js +2 -0
- package/dist/internal/index-impl/semanticSidecarQuality.js +111 -0
- package/dist/internal/index-impl/semanticSourceEditDedupe.js +69 -9
- package/dist/internal/index-impl/semanticTransformIdentityRecords.js +85 -9
- package/dist/js-ts-safe-member-merge-result.js +158 -0
- package/dist/js-ts-safe-member-merge.js +202 -0
- package/dist/js-ts-safe-merge-analyze.js +279 -0
- package/dist/js-ts-safe-merge-constants.js +50 -0
- package/dist/js-ts-safe-merge-context.js +118 -0
- package/dist/js-ts-safe-merge-ledger-validation.js +92 -0
- package/dist/js-ts-safe-merge-ledger.js +85 -0
- package/dist/js-ts-safe-merge-parse-declarations.js +210 -0
- package/dist/js-ts-safe-merge-parse-statements.js +155 -0
- package/dist/js-ts-safe-merge-plan.js +190 -0
- package/dist/js-ts-safe-merge.js +175 -0
- package/dist/js-ts-semantic-conflict-sidecar-constants.js +77 -0
- package/dist/js-ts-semantic-conflict-sidecar-detectors.js +195 -0
- package/dist/js-ts-semantic-conflict-sidecar-normalize.js +203 -0
- package/dist/js-ts-semantic-conflict-sidecar-utils.js +190 -0
- package/dist/js-ts-semantic-conflict-sidecars.js +81 -0
- package/dist/js-ts-semantic-merge-contract-helpers.js +128 -0
- package/dist/js-ts-semantic-merge-contracts.js +217 -0
- package/dist/js-ts-semantic-merge-member-containers.js +100 -0
- package/dist/js-ts-semantic-merge-member-keys.js +142 -0
- package/dist/js-ts-semantic-merge-member-segments.js +185 -0
- package/dist/js-ts-semantic-merge-member-source.js +64 -0
- package/dist/js-ts-semantic-merge-member-utils.js +18 -0
- package/dist/js-ts-semantic-merge-parse.js +15 -0
- package/dist/js-ts-semantic-merge.js +21 -0
- package/dist/lightweight-dependency-effects.js +51 -0
- package/dist/lightweight-dependency-language.js +12 -1
- package/dist/lightweight-dependency-relations.js +14 -27
- package/dist/native-region-scanner-core.js +33 -1
- package/dist/native-region-scanner-csharp.js +151 -0
- package/dist/native-region-scanner-dart.js +91 -0
- package/dist/native-region-scanner-dynamic.js +21 -151
- package/dist/native-region-scanner-functional.js +40 -13
- package/dist/native-region-scanner-java.js +97 -0
- package/dist/native-region-scanner-js-class.js +100 -0
- package/dist/native-region-scanner-js-helpers.js +28 -86
- package/dist/native-region-scanner-js-imports.js +121 -1
- package/dist/native-region-scanner-js-nested.js +96 -8
- package/dist/native-region-scanner-js-structure.js +27 -0
- package/dist/native-region-scanner-js-types.js +99 -0
- package/dist/native-region-scanner-js.js +70 -118
- package/dist/native-region-scanner-kotlin.js +94 -0
- package/dist/native-region-scanner-main.js +15 -181
- package/dist/native-region-scanner-php.js +80 -0
- package/dist/native-region-scanner-python.js +62 -0
- package/dist/native-region-scanner-ruby.js +72 -0
- package/dist/native-region-scanner-scala.js +91 -0
- package/dist/native-region-scanner-spans.js +74 -0
- package/dist/native-region-scanner-swift.js +155 -0
- package/dist/native-region-scanner.js +14 -10
- package/dist/native-source-ledger-helpers.js +195 -0
- package/dist/native-source-ledger.js +306 -0
- package/dist/native-source-preservation-scanner.js +4 -0
- package/dist/semantic-import-callsite-regions.js +136 -0
- package/dist/semantic-import-effect-regions.js +283 -0
- package/dist/semantic-import-regions.js +11 -2
- package/dist/semantic-import-sidecar-entry.js +16 -2
- package/dist/semantic-import-sidecar-types.d.ts +2 -0
- package/dist/semantic-sidecar-example.js +68 -0
- package/dist/universal-capability-matrix.js +23 -0
- package/dist/universal-conversion-artifact-query.js +79 -2
- package/dist/universal-conversion-artifact-semantic-edit.js +103 -0
- package/dist/universal-conversion-artifact-summary.js +33 -1
- package/dist/universal-conversion-artifacts.js +13 -48
- package/dist/universal-conversion-plan-scoring.js +21 -1
- package/dist/universal-conversion-plan-summary.js +30 -0
- package/dist/universal-conversion-plan.js +25 -9
- package/dist/universal-conversion-route-metadata.js +96 -0
- package/dist/universal-conversion-route-operations.js +7 -0
- package/dist/universal-representation-coverage.js +193 -0
- package/package.json +1 -1
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
|
-
jsControlKeyword,
|
|
3
2
|
nativeDeclaration,
|
|
4
3
|
splitParameters
|
|
5
4
|
} from './native-region-scanner-core.js';
|
|
6
|
-
import { jsImportDeclarations } from './native-region-scanner-js-imports.js';
|
|
5
|
+
import { jsExportDeclarations, jsImportDeclarations } from './native-region-scanner-js-imports.js';
|
|
7
6
|
function jsCommentOnlyLine(trimmed) {
|
|
8
7
|
return trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*');
|
|
9
8
|
}
|
|
@@ -71,13 +70,8 @@ function jsObjectRegionContext(name, declarationLine, lineNumber, regionKind) {
|
|
|
71
70
|
if (initializerKind !== 'object' && initializerKind !== 'array') return undefined;
|
|
72
71
|
const depth = jsContainerDelta(declarationLine);
|
|
73
72
|
if (depth <= 0) return undefined;
|
|
74
|
-
return {
|
|
75
|
-
|
|
76
|
-
regionKind: regionKind ?? jsRegionKindForDeclarationName(name, declarationLine),
|
|
77
|
-
initializerKind,
|
|
78
|
-
depth,
|
|
79
|
-
startLine: lineNumber
|
|
80
|
-
};
|
|
73
|
+
return { name, regionKind: regionKind ?? jsRegionKindForDeclarationName(name, declarationLine), initializerKind, depth, startLine: lineNumber,
|
|
74
|
+
arrayRecords: initializerKind === 'array' && /(?:define|create|make|build)\w*(?:tools?|actions?|handlers?|commands?|events?|effects?|workflows?)/i.test(declarationLine) };
|
|
81
75
|
}
|
|
82
76
|
|
|
83
77
|
function jsInitializerKind(line, name) {
|
|
@@ -127,15 +121,17 @@ function jsExportedContainerDeclaration(input, lineNumber, trimmed) {
|
|
|
127
121
|
}
|
|
128
122
|
|
|
129
123
|
function jsExportedFunctionWrapperDeclaration(input, lineNumber, trimmed) {
|
|
130
|
-
const match = trimmed.match(/^export\s+default\s+(
|
|
124
|
+
const match = trimmed.match(/^export\s+default\s+(.+)$/);
|
|
131
125
|
if (!match) return undefined;
|
|
132
|
-
const
|
|
133
|
-
|
|
126
|
+
const unwrapped = jsUnwrapFunctionWrapperArgument(match[1]);
|
|
127
|
+
if (!unwrapped) return undefined;
|
|
128
|
+
const { wrapper, wrappers, argument } = unwrapped;
|
|
129
|
+
const wrapperFields = { wrapper, ...(wrappers.length > 1 ? { wrappers } : {}) };
|
|
134
130
|
let functionMatch = argument.match(/^(?:async\s+)?function\*?\s*([A-Za-z_$][\w$]*)?\s*(?:<[^({;]+>)?\s*\(([^)]*)\)/);
|
|
135
131
|
if (functionMatch) {
|
|
136
132
|
return nativeDeclaration(input, lineNumber, 'ExportDefaultFunctionWrapperDeclaration', 'function', functionMatch[1] ?? 'default', {
|
|
137
133
|
exportDefault: true,
|
|
138
|
-
|
|
134
|
+
...wrapperFields,
|
|
139
135
|
parameters: splitParameters(functionMatch[2])
|
|
140
136
|
}, true);
|
|
141
137
|
}
|
|
@@ -143,7 +139,7 @@ function jsExportedFunctionWrapperDeclaration(input, lineNumber, trimmed) {
|
|
|
143
139
|
if (functionMatch) {
|
|
144
140
|
return nativeDeclaration(input, lineNumber, 'ExportDefaultFunctionWrapperDeclaration', 'function', 'default', {
|
|
145
141
|
exportDefault: true,
|
|
146
|
-
|
|
142
|
+
...wrapperFields,
|
|
147
143
|
parameters: splitParameters(functionMatch[1] ?? functionMatch[2])
|
|
148
144
|
}, true);
|
|
149
145
|
}
|
|
@@ -151,21 +147,33 @@ function jsExportedFunctionWrapperDeclaration(input, lineNumber, trimmed) {
|
|
|
151
147
|
if (classMatch) {
|
|
152
148
|
return nativeDeclaration(input, lineNumber, 'ExportDefaultClassWrapperDeclaration', 'class', classMatch[1] ?? 'default', {
|
|
153
149
|
exportDefault: true,
|
|
154
|
-
|
|
150
|
+
...wrapperFields
|
|
155
151
|
}, true);
|
|
156
152
|
}
|
|
157
153
|
const aliasMatch = argument.match(/^([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\s*(?:[,)]|$)/);
|
|
158
154
|
if (!aliasMatch) return undefined;
|
|
159
155
|
return nativeDeclaration(input, lineNumber, 'ExportDefaultWrappedAlias', 'variable', 'default', {
|
|
160
156
|
exportDefault: true,
|
|
161
|
-
|
|
157
|
+
...wrapperFields,
|
|
162
158
|
alias: aliasMatch[1],
|
|
163
159
|
initializerKind: 'function-wrapper'
|
|
164
160
|
}, false, {
|
|
165
|
-
metadata: { exportDefault: true,
|
|
161
|
+
metadata: { exportDefault: true, ...wrapperFields, alias: aliasMatch[1], initializerKind: 'function-wrapper' }
|
|
166
162
|
});
|
|
167
163
|
}
|
|
168
164
|
|
|
165
|
+
function jsUnwrapFunctionWrapperArgument(source) {
|
|
166
|
+
const wrappers = [];
|
|
167
|
+
let argument = String(source ?? '').trim();
|
|
168
|
+
let match;
|
|
169
|
+
while ((match = argument.match(/^((?:React\.)?(?:forwardRef|memo|lazy|observer)|Object\.freeze)\s*(?:<[^>]+>)?\s*\(\s*(.+)$/))) {
|
|
170
|
+
wrappers.push(match[1]);
|
|
171
|
+
argument = match[2].trim();
|
|
172
|
+
}
|
|
173
|
+
if (!wrappers.length) return undefined;
|
|
174
|
+
return { wrapper: wrappers[0], wrappers, argument };
|
|
175
|
+
}
|
|
176
|
+
|
|
169
177
|
function jsExportAliasDeclaration(input, lineNumber, trimmed) {
|
|
170
178
|
let match = trimmed.match(/^export\s+default\s+([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\s*;?$/);
|
|
171
179
|
if (match) return jsAliasExport(input, lineNumber, 'ExportDefaultAlias', 'default', match[1], { exportDefault: true }, trimmed);
|
|
@@ -202,72 +210,6 @@ function jsContainerExport(input, lineNumber, languageKind, name, initializer, f
|
|
|
202
210
|
return { declaration, context };
|
|
203
211
|
}
|
|
204
212
|
|
|
205
|
-
function jsObjectPropertyDeclaration(input, lineNumber, trimmed, context) {
|
|
206
|
-
if (/^[}\])]/.test(trimmed) || trimmed.startsWith('...')) return undefined;
|
|
207
|
-
const methodMatch = trimmed.match(/^(?:(?:async|get|set)\s+)?(['"]?)([A-Za-z_$][\w$-]*)\1\s*\(([^)]*)\)\s*(?:[:\w\s<>\[\]]*)?(?:\{|=>|,|$)/);
|
|
208
|
-
if (methodMatch && !jsControlKeyword(methodMatch[2])) {
|
|
209
|
-
const name = `${context.name}.${methodMatch[2]}`;
|
|
210
|
-
return nativeDeclaration(input, lineNumber, 'ObjectMethod', 'function', name, {
|
|
211
|
-
owner: context.name,
|
|
212
|
-
propertyName: methodMatch[2],
|
|
213
|
-
parameters: splitParameters(methodMatch[3])
|
|
214
|
-
}, true, {
|
|
215
|
-
regionKind: jsPropertyRegionKind(context, methodMatch[2], 'function'),
|
|
216
|
-
metadata: { owner: context.name, propertyName: methodMatch[2], initializerKind: 'function' }
|
|
217
|
-
});
|
|
218
|
-
}
|
|
219
|
-
const propertyMatch = trimmed.match(/^(?:(['"])([^'"]+)\1|([A-Za-z_$][\w$-]*))\s*:\s*(.+?)(?:,)?$/);
|
|
220
|
-
if (!propertyMatch) return undefined;
|
|
221
|
-
const propertyName = propertyMatch[2] ?? propertyMatch[3];
|
|
222
|
-
if (!propertyName || jsControlKeyword(propertyName)) return undefined;
|
|
223
|
-
const value = propertyMatch[4].trim();
|
|
224
|
-
const initializerKind = jsPropertyInitializerKind(value);
|
|
225
|
-
const functionLike = initializerKind === 'function';
|
|
226
|
-
const name = `${context.name}.${propertyName}`;
|
|
227
|
-
return nativeDeclaration(input, lineNumber, functionLike ? 'ObjectFunctionProperty' : 'ObjectProperty', functionLike ? 'function' : 'property', name, {
|
|
228
|
-
owner: context.name,
|
|
229
|
-
propertyName,
|
|
230
|
-
initializerKind
|
|
231
|
-
}, functionLike || initializerKind === 'object' || initializerKind === 'array', {
|
|
232
|
-
regionKind: jsPropertyRegionKind(context, propertyName, value),
|
|
233
|
-
metadata: { owner: context.name, propertyName, initializerKind }
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
function jsRouteRecordDeclaration(input, lineNumber, trimmed, context) {
|
|
238
|
-
if (context.regionKind !== 'route') return undefined;
|
|
239
|
-
const match = trimmed.match(/^(?:\{\s*)?(?:path|route|href|url)\s*:\s*(['"`])([^'"`]+)\1/);
|
|
240
|
-
if (!match) return undefined;
|
|
241
|
-
const routePath = match[2];
|
|
242
|
-
return nativeDeclaration(input, lineNumber, 'RouteRecord', 'route', `${context.name}.${routePath}`, {
|
|
243
|
-
owner: context.name,
|
|
244
|
-
routePath
|
|
245
|
-
}, true, {
|
|
246
|
-
regionKind: 'route',
|
|
247
|
-
metadata: { owner: context.name, routePath, initializerKind: 'object' }
|
|
248
|
-
});
|
|
249
|
-
}
|
|
250
|
-
|
|
251
|
-
function jsPropertyInitializerKind(value) {
|
|
252
|
-
const text = String(value ?? '').trim();
|
|
253
|
-
if (/^(?:async\s*)?(?:function\b|\([^)]*\)\s*=>|[A-Za-z_$][\w$]*\s*=>)/.test(text)) return 'function';
|
|
254
|
-
const containerKind = jsContainerInitializerKind(text, undefined, text);
|
|
255
|
-
if (containerKind) return containerKind;
|
|
256
|
-
if (/^['"`]/.test(text)) return 'string';
|
|
257
|
-
if (/^(?:true|false)\b/.test(text)) return 'boolean';
|
|
258
|
-
if (/^[0-9]/.test(text)) return 'number';
|
|
259
|
-
return 'expression';
|
|
260
|
-
}
|
|
261
|
-
|
|
262
|
-
function jsPropertyRegionKind(context, propertyName, value) {
|
|
263
|
-
const named = jsRegionKindForDeclarationName(propertyName, value);
|
|
264
|
-
if (named) return named;
|
|
265
|
-
if (context.regionKind === 'route') return 'route';
|
|
266
|
-
if (context.regionKind === 'content') return 'content';
|
|
267
|
-
if (context.regionKind === 'config') return 'config';
|
|
268
|
-
return 'property';
|
|
269
|
-
}
|
|
270
|
-
|
|
271
213
|
function jsContainerInitializerKind(initializer, name, source) {
|
|
272
214
|
const text = String(initializer ?? '').trim();
|
|
273
215
|
if (text.startsWith('{')) return 'object';
|
|
@@ -279,7 +221,7 @@ function jsContainerInitializerKind(initializer, name, source) {
|
|
|
279
221
|
|
|
280
222
|
function jsContainerWrapperLooksSemantic(callee, name, source) {
|
|
281
223
|
const signal = `${callee ?? ''} ${name ?? ''} ${source ?? ''}`.replace(/([a-z0-9])([A-Z])/g, '$1 $2').toLowerCase();
|
|
282
|
-
return /\b(define|create|make|build|object\.freeze)\b/.test(signal) && /\b(config|settings|options|routes?|router|content|docs?|schema|registry|manifest|catalog|menu|nav)\b/.test(signal);
|
|
224
|
+
return /\b(define|create|make|build|object\.freeze)\b/.test(signal) && /\b(actions?|handlers?|tools?|commands?|events?|effects?|workflows?|config|settings|options|routes?|router|content|docs?|schema|registry|manifest|catalog|menu|nav)\b/.test(signal);
|
|
283
225
|
}
|
|
284
226
|
|
|
285
227
|
function jsContainerDelta(source) {
|
|
@@ -316,5 +258,5 @@ function findUnescapedBacktick(text, startIndex) {
|
|
|
316
258
|
|
|
317
259
|
export { jsCommentOnlyLine, jsContainerDelta, jsDeclarationScanLine };
|
|
318
260
|
export { jsExportAliasDeclaration, jsExportedContainerDeclaration, jsExportedFunctionWrapperDeclaration };
|
|
319
|
-
export { jsInitializerKind, jsImportDeclarations,
|
|
320
|
-
export { jsRegionKindForDeclarationName,
|
|
261
|
+
export { jsContainerInitializerKind, jsExportDeclarations, jsInitializerKind, jsImportDeclarations, jsObjectRegionContext };
|
|
262
|
+
export { jsRegionKindForDeclarationName, jsVariableHasBody, jsVariableSymbolKind };
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import {
|
|
2
|
+
nativeExportDeclaration,
|
|
2
3
|
nativeImportBindingDeclaration,
|
|
3
4
|
nativeImportDeclaration
|
|
4
5
|
} from './native-region-scanner-core.js';
|
|
6
|
+
import { idFragment } from './native-import-utils.js';
|
|
5
7
|
|
|
6
8
|
export function jsImportDeclarations(input, lineNumber, trimmed) {
|
|
7
9
|
const importEquals = trimmed.match(/^import\s+(type\s+)?([A-Za-z_$][\w$]*)\s*=\s*require\s*\(\s*(['"])([^'"]+)\3\s*\)/);
|
|
@@ -28,7 +30,10 @@ export function jsImportDeclarations(input, lineNumber, trimmed) {
|
|
|
28
30
|
: exportMatch[4]
|
|
29
31
|
? jsNamedImportBindings(exportMatch[4], { typeOnly, reexport: true })
|
|
30
32
|
: [];
|
|
31
|
-
return
|
|
33
|
+
return [
|
|
34
|
+
...jsImportModuleDeclarations(input, lineNumber, importPath, 'ExportFromDeclaration', bindings, { typeOnly, reexport: true, exportStar: Boolean(exportMatch[2]) }),
|
|
35
|
+
...jsExportModuleDeclarations(input, lineNumber, importPath, bindings, { typeOnly, exportStar: Boolean(exportMatch[2]) })
|
|
36
|
+
];
|
|
32
37
|
}
|
|
33
38
|
const destructuredRequireMatch = trimmed.match(/^(?:const|let|var)\s+\{([^}]+)\}\s*=\s*(?:await\s+)?(require|import)\s*\(\s*(['"])([^'"]+)\3\s*\)/);
|
|
34
39
|
if (destructuredRequireMatch) {
|
|
@@ -54,6 +59,34 @@ export function jsImportDeclarations(input, lineNumber, trimmed) {
|
|
|
54
59
|
return [];
|
|
55
60
|
}
|
|
56
61
|
|
|
62
|
+
export function jsExportDeclarations(input, lineNumber, trimmed) {
|
|
63
|
+
if (/^export\s+(?:type\s+)?(?:\*|\{[^}]+\}\s+from\b)/.test(trimmed)) return [];
|
|
64
|
+
const named = trimmed.match(/^export\s+(type\s+)?\{([^}]+)\}\s*;?$/);
|
|
65
|
+
if (named) return jsLocalExportDeclarations(input, lineNumber, named[2], { typeOnly: Boolean(named[1]) });
|
|
66
|
+
const namespace = trimmed.match(/^export\s+as\s+namespace\s+([A-Za-z_$][\w$]*)\s*;?$/);
|
|
67
|
+
if (namespace) return [nativeExportDeclaration(input, lineNumber, namespace[1], 'ExportNamespaceDeclaration', {
|
|
68
|
+
exportKind: 'namespace'
|
|
69
|
+
})];
|
|
70
|
+
const assignment = trimmed.match(/^export\s*=\s*([A-Za-z_$][\w$]*(?:\.[A-Za-z_$][\w$]*)*)\s*;?$/);
|
|
71
|
+
if (assignment) return [nativeExportDeclaration(input, lineNumber, 'module.exports', 'ExportAssignment', {
|
|
72
|
+
exportKind: 'assignment',
|
|
73
|
+
localName: assignment[1]
|
|
74
|
+
}, { name: 'module.exports' })];
|
|
75
|
+
if (!trimmed.startsWith('export ')) return [];
|
|
76
|
+
const defaultMatch = trimmed.match(/^export\s+default\s+(.+)$/);
|
|
77
|
+
if (defaultMatch) return [nativeExportDeclaration(input, lineNumber, 'default', 'ExportDefaultDeclaration', {
|
|
78
|
+
exportDefault: true,
|
|
79
|
+
localName: jsExportedDeclarationName(defaultMatch[1])
|
|
80
|
+
}, { name: 'default' })];
|
|
81
|
+
const declarationSource = trimmed.replace(/^export\s+(?:declare\s+)?/, '');
|
|
82
|
+
if (!jsExportedDeclarationLooksComplete(declarationSource)) return [];
|
|
83
|
+
const exportedName = jsExportedDeclarationName(declarationSource);
|
|
84
|
+
if (!exportedName) return [];
|
|
85
|
+
return [nativeExportDeclaration(input, lineNumber, exportedName, 'ExportNamedDeclaration', {
|
|
86
|
+
declarationKind: jsExportedDeclarationKind(declarationSource)
|
|
87
|
+
})];
|
|
88
|
+
}
|
|
89
|
+
|
|
57
90
|
function jsDestructuredImportBindings(raw, importKind) {
|
|
58
91
|
return String(raw ?? '')
|
|
59
92
|
.split(',')
|
|
@@ -100,6 +133,47 @@ function jsImportModuleDeclarations(input, lineNumber, importPath, languageKind,
|
|
|
100
133
|
];
|
|
101
134
|
}
|
|
102
135
|
|
|
136
|
+
function jsExportModuleDeclarations(input, lineNumber, importPath, bindings = [], metadata = {}) {
|
|
137
|
+
const exports = bindings.map((binding) => ({
|
|
138
|
+
localName: binding.importedName,
|
|
139
|
+
exportedName: binding.exportedName ?? binding.localName,
|
|
140
|
+
exportKind: binding.importKind,
|
|
141
|
+
...(binding.typeOnly ? { typeOnly: true } : {})
|
|
142
|
+
}));
|
|
143
|
+
const statementName = metadata.exportStar
|
|
144
|
+
? `* from ${importPath}`
|
|
145
|
+
: exports.length
|
|
146
|
+
? `{${exports.map((binding) => binding.exportedName).join(',')}} from ${importPath}`
|
|
147
|
+
: `from ${importPath}`;
|
|
148
|
+
return [
|
|
149
|
+
nativeExportDeclaration(input, lineNumber, statementName, 'ExportFromDeclaration', {
|
|
150
|
+
importPath: String(importPath),
|
|
151
|
+
exportBindings: exports,
|
|
152
|
+
...(metadata.typeOnly ? { typeOnly: true } : {}),
|
|
153
|
+
...(metadata.exportStar ? { exportStar: true } : {})
|
|
154
|
+
}, { symbolKind: 'module', metadata }),
|
|
155
|
+
...exports.map((binding) => nativeExportDeclaration(input, lineNumber, binding.exportedName, 'ExportBinding', {
|
|
156
|
+
...binding,
|
|
157
|
+
importPath: String(importPath)
|
|
158
|
+
}, { metadata: { ...binding, importPath: String(importPath) } }))
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
function jsLocalExportDeclarations(input, lineNumber, raw, options = {}) {
|
|
163
|
+
const bindings = jsNamedExportBindings(raw, options);
|
|
164
|
+
if (!bindings.length) return [];
|
|
165
|
+
return [
|
|
166
|
+
nativeExportDeclaration(input, lineNumber, `{${bindings.map((binding) => binding.exportedName).join(',')}}`, 'ExportNamedDeclaration', {
|
|
167
|
+
exportBindings: bindings,
|
|
168
|
+
...(options.typeOnly ? { typeOnly: true } : {})
|
|
169
|
+
}, {
|
|
170
|
+
symbolId: `symbol:${input.language}:export:statement:${idFragment(bindings.map((binding) => binding.exportedName).join('_'))}`,
|
|
171
|
+
metadata: { bindingCount: bindings.length, ...(options.typeOnly ? { typeOnly: true } : {}) }
|
|
172
|
+
}),
|
|
173
|
+
...bindings.map((binding) => nativeExportDeclaration(input, lineNumber, binding.exportedName, 'ExportBinding', binding, { metadata: binding }))
|
|
174
|
+
];
|
|
175
|
+
}
|
|
176
|
+
|
|
103
177
|
function jsImportBindingsFromClause(clause, options = {}) {
|
|
104
178
|
const source = String(clause ?? '').trim();
|
|
105
179
|
if (!source) return [];
|
|
@@ -142,3 +216,49 @@ function jsNamedImportBinding(raw, options = {}) {
|
|
|
142
216
|
typeOnly
|
|
143
217
|
};
|
|
144
218
|
}
|
|
219
|
+
|
|
220
|
+
function jsNamedExportBindings(raw, options = {}) {
|
|
221
|
+
return String(raw ?? '').split(',').map((part) => jsNamedExportBinding(part, options)).filter(Boolean);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function jsNamedExportBinding(raw, options = {}) {
|
|
225
|
+
let text = String(raw ?? '').trim();
|
|
226
|
+
if (!text) return undefined;
|
|
227
|
+
let typeOnly = Boolean(options.typeOnly);
|
|
228
|
+
if (text.startsWith('type ')) {
|
|
229
|
+
typeOnly = true;
|
|
230
|
+
text = text.slice(5).trim();
|
|
231
|
+
}
|
|
232
|
+
const match = text.match(/^([A-Za-z_$][\w$]*|\*)\s*(?:as\s+([A-Za-z_$][\w$]*|\*))?$/);
|
|
233
|
+
if (!match) return undefined;
|
|
234
|
+
const localName = match[1];
|
|
235
|
+
return { localName, exportedName: match[2] ?? localName, exportKind: typeOnly ? 'type-named' : 'named', typeOnly };
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
function jsExportedDeclarationName(source) {
|
|
239
|
+
const text = String(source ?? '').trim();
|
|
240
|
+
return text.match(/^(?:async\s+)?function\*?\s+([A-Za-z_$][\w$]*)/)?.[1]
|
|
241
|
+
?? text.match(/^(?:abstract\s+)?class\s+([A-Za-z_$][\w$]*)/)?.[1]
|
|
242
|
+
?? text.match(/^(?:const|let|var)\s+([A-Za-z_$][\w$]*)/)?.[1]
|
|
243
|
+
?? text.match(/^type\s+([A-Za-z_$][\w$]*)/)?.[1]
|
|
244
|
+
?? text.match(/^interface\s+([A-Za-z_$][\w$]*)/)?.[1]
|
|
245
|
+
?? text.match(/^(?:const\s+)?enum\s+([A-Za-z_$][\w$]*)/)?.[1]
|
|
246
|
+
?? text.match(/^([A-Za-z_$][\w$]*)\b/)?.[1]
|
|
247
|
+
?? 'default';
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function jsExportedDeclarationKind(source) {
|
|
251
|
+
const text = String(source ?? '').trim();
|
|
252
|
+
if (/^(?:async\s+)?function/.test(text)) return 'function';
|
|
253
|
+
if (/^(?:abstract\s+)?class/.test(text)) return 'class';
|
|
254
|
+
if (/^interface\b|^type\b|^(?:const\s+)?enum\b/.test(text)) return 'type';
|
|
255
|
+
if (/^(?:const|let|var)\b/.test(text)) return 'variable';
|
|
256
|
+
return 'value';
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function jsExportedDeclarationLooksComplete(source) {
|
|
260
|
+
const text = String(source ?? '').trim();
|
|
261
|
+
if (/^(?:async\s+)?function/.test(text)) return text.includes(')') && /[;{]/.test(text);
|
|
262
|
+
if (/^(?:abstract\s+)?class/.test(text)) return text.includes('{') || text.endsWith(';');
|
|
263
|
+
return true;
|
|
264
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { nativeDeclaration } from './native-region-scanner-core.js';
|
|
2
|
-
import { jsContainerDelta, jsRegionKindForDeclarationName } from './native-region-scanner-js-helpers.js';
|
|
1
|
+
import { jsControlKeyword, nativeDeclaration, splitParameters } from './native-region-scanner-core.js';
|
|
2
|
+
import { jsContainerDelta, jsContainerInitializerKind, jsRegionKindForDeclarationName } from './native-region-scanner-js-helpers.js';
|
|
3
3
|
|
|
4
4
|
function jsCurrentObjectContext(stack) {
|
|
5
5
|
return stack[stack.length - 1];
|
|
@@ -9,6 +9,21 @@ function jsContextAllowsPropertyScan(context) {
|
|
|
9
9
|
return context?.initializerKind === 'object';
|
|
10
10
|
}
|
|
11
11
|
|
|
12
|
+
function jsArrayObjectContextFromLine(context, lineNumber, source) {
|
|
13
|
+
if (context?.initializerKind !== 'array' || context.arrayRecords !== true || !String(source ?? '').trim().startsWith('{')) return undefined;
|
|
14
|
+
const depth = jsContainerDelta(source);
|
|
15
|
+
if (depth <= 0) return undefined;
|
|
16
|
+
const index = (context.nextItemIndex ?? 0) + 1;
|
|
17
|
+
context.nextItemIndex = index;
|
|
18
|
+
return { name: `${context.name}.${index}`, ownerName: context.name, regionKind: context.regionKind, initializerKind: 'object', arrayItem: true, depth, startLine: lineNumber };
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function updateJsArrayObjectContextName(context, source) {
|
|
22
|
+
if (!context?.arrayItem) return;
|
|
23
|
+
const match = String(source ?? '').trim().match(/^(?:name|id|key|slug|tool|command)\s*:\s*(['"`])([^'"`]+)\1/);
|
|
24
|
+
if (match) context.name = `${context.ownerName}.${match[2]}`;
|
|
25
|
+
}
|
|
26
|
+
|
|
12
27
|
function jsNestedObjectContextFromDeclaration(declaration, lineNumber, source) {
|
|
13
28
|
const initializerKind = declaration?.fields?.initializerKind ?? declaration?.metadata?.initializerKind;
|
|
14
29
|
if (initializerKind !== 'object' && initializerKind !== 'array') return undefined;
|
|
@@ -32,9 +47,9 @@ function jsInlineNestedObjectDeclarations(input, lineNumber, source, parentDecla
|
|
|
32
47
|
for (const entry of splitTopLevelEntries(body)) {
|
|
33
48
|
const parsed = parseObjectEntry(entry);
|
|
34
49
|
if (!parsed) continue;
|
|
35
|
-
const initializerKind = nestedInitializerKind(parsed.value);
|
|
50
|
+
const initializerKind = parsed.method ? 'function' : nestedInitializerKind(parsed.value);
|
|
36
51
|
const name = `${parentDeclaration.name}.${parsed.key}`;
|
|
37
|
-
const regionKind = nestedPropertyRegionKind(parentDeclaration, parsed.key, parsed.value);
|
|
52
|
+
const regionKind = initializerKind === 'function' ? 'body' : nestedPropertyRegionKind(parentDeclaration, parsed.key, parsed.value);
|
|
38
53
|
const declaration = nativeDeclaration(input, lineNumber, initializerKind === 'function' ? 'NestedObjectFunctionProperty' : 'NestedObjectProperty', initializerKind === 'function' ? 'function' : 'property', name, {
|
|
39
54
|
owner: parentDeclaration.name,
|
|
40
55
|
propertyName: parsed.key,
|
|
@@ -57,6 +72,73 @@ function updateJsObjectContextStack(stack, lineNumber, source) {
|
|
|
57
72
|
while (stack.length && stack[stack.length - 1].depth <= 0) stack.pop();
|
|
58
73
|
}
|
|
59
74
|
|
|
75
|
+
function jsObjectPropertyDeclaration(input, lineNumber, trimmed, context) {
|
|
76
|
+
if (/^[}\])]/.test(trimmed) || trimmed.startsWith('...')) return undefined;
|
|
77
|
+
const methodMatch = trimmed.match(/^(?:(?:async|get|set)\s+)?(?:\[\s*(['"`])([^'"`]+)\1\s*\]|(['"`]?)([A-Za-z_$][\w$-]*)\3)\s*\(([^)]*)\)\s*(?:[:\w\s<>\[\]]*)?(?:\{|=>|,|$)/);
|
|
78
|
+
const methodName = methodMatch?.[2] ?? methodMatch?.[4];
|
|
79
|
+
if (methodMatch && !jsControlKeyword(methodName)) {
|
|
80
|
+
const name = `${context.name}.${methodName}`;
|
|
81
|
+
return nativeDeclaration(input, lineNumber, 'ObjectMethod', 'function', name, {
|
|
82
|
+
owner: context.name,
|
|
83
|
+
propertyName: methodName,
|
|
84
|
+
parameters: splitParameters(methodMatch[5])
|
|
85
|
+
}, true, {
|
|
86
|
+
regionKind: 'body',
|
|
87
|
+
metadata: { owner: context.name, propertyName: methodName, initializerKind: 'function' }
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
const propertyMatch = trimmed.match(/^(?:\[\s*(['"`])([^'"`]+)\1\s*\]|(['"`])([^'"`]+)\3|([A-Za-z_$][\w$-]*))\s*:\s*(.+?)(?:,)?$/);
|
|
91
|
+
if (!propertyMatch) return undefined;
|
|
92
|
+
const propertyName = propertyMatch[2] ?? propertyMatch[4] ?? propertyMatch[5];
|
|
93
|
+
if (!propertyName || jsControlKeyword(propertyName)) return undefined;
|
|
94
|
+
const value = propertyMatch[6].trim();
|
|
95
|
+
const initializerKind = jsPropertyInitializerKind(value);
|
|
96
|
+
const functionLike = initializerKind === 'function';
|
|
97
|
+
const name = `${context.name}.${propertyName}`;
|
|
98
|
+
return nativeDeclaration(input, lineNumber, functionLike ? 'ObjectFunctionProperty' : 'ObjectProperty', functionLike ? 'function' : 'property', name, {
|
|
99
|
+
owner: context.name,
|
|
100
|
+
propertyName,
|
|
101
|
+
initializerKind
|
|
102
|
+
}, functionLike || initializerKind === 'object' || initializerKind === 'array', {
|
|
103
|
+
regionKind: functionLike ? 'body' : jsPropertyRegionKind(context, propertyName, value),
|
|
104
|
+
metadata: { owner: context.name, propertyName, initializerKind }
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function jsRouteRecordDeclaration(input, lineNumber, trimmed, context) {
|
|
109
|
+
if (context.regionKind !== 'route') return undefined;
|
|
110
|
+
const match = trimmed.match(/^(?:\{\s*)?(?:path|route|href|url)\s*:\s*(['"`])([^'"`]+)\1/);
|
|
111
|
+
if (!match) return undefined;
|
|
112
|
+
const routePath = match[2];
|
|
113
|
+
return nativeDeclaration(input, lineNumber, 'RouteRecord', 'route', `${context.name}.${routePath}`, {
|
|
114
|
+
owner: context.name,
|
|
115
|
+
routePath
|
|
116
|
+
}, true, {
|
|
117
|
+
regionKind: 'route',
|
|
118
|
+
metadata: { owner: context.name, routePath, initializerKind: 'object' }
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function jsPropertyInitializerKind(value) {
|
|
123
|
+
const text = String(value ?? '').trim();
|
|
124
|
+
if (/^(?:async\s*)?(?:function\b|\([^)]*\)\s*=>|[A-Za-z_$][\w$]*\s*=>)/.test(text)) return 'function';
|
|
125
|
+
const containerKind = jsContainerInitializerKind(text, undefined, text);
|
|
126
|
+
if (containerKind) return containerKind;
|
|
127
|
+
if (/^['"`]/.test(text)) return 'string';
|
|
128
|
+
if (/^(?:true|false)\b/.test(text)) return 'boolean';
|
|
129
|
+
if (/^[0-9]/.test(text)) return 'number';
|
|
130
|
+
return 'expression';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function jsPropertyRegionKind(context, propertyName, value) {
|
|
134
|
+
const named = jsRegionKindForDeclarationName(propertyName, value);
|
|
135
|
+
if (named) return named;
|
|
136
|
+
if (context.regionKind === 'route') return 'route';
|
|
137
|
+
if (context.regionKind === 'content') return 'content';
|
|
138
|
+
if (context.regionKind === 'config') return 'config';
|
|
139
|
+
return 'property';
|
|
140
|
+
}
|
|
141
|
+
|
|
60
142
|
function inlineObjectBody(source) {
|
|
61
143
|
const text = String(source ?? '');
|
|
62
144
|
const open = text.indexOf('{');
|
|
@@ -113,10 +195,12 @@ function splitTopLevelEntries(body) {
|
|
|
113
195
|
}
|
|
114
196
|
|
|
115
197
|
function parseObjectEntry(entry) {
|
|
116
|
-
if (!entry || entry.startsWith('...')
|
|
117
|
-
const match = entry.match(/^(
|
|
118
|
-
if (
|
|
119
|
-
|
|
198
|
+
if (!entry || entry.startsWith('...')) return undefined;
|
|
199
|
+
const match = entry.match(/^(?:\[\s*(['"`])([^'"`]+)\1\s*\]|(['"`])([^'"`]+)\3|([A-Za-z_$][\w$-]*))\s*:\s*(.+)$/s);
|
|
200
|
+
if (match) return { key: match[2] ?? match[4] ?? match[5], value: match[6].trim() };
|
|
201
|
+
const methodMatch = entry.match(/^(?:(?:async|get|set)\s+)?(?:\[\s*(['"`])([^'"`]+)\1\s*\]|(['"`]?)([A-Za-z_$][\w$-]*)\3)\s*\(([^)]*)\)\s*(?:[:\w\s<>\[\]]*)?(?:\{|=>|$)/s);
|
|
202
|
+
if (!methodMatch) return undefined;
|
|
203
|
+
return { key: methodMatch[2] ?? methodMatch[4], value: entry.trim(), method: true };
|
|
120
204
|
}
|
|
121
205
|
|
|
122
206
|
function nestedInitializerKind(value) {
|
|
@@ -139,9 +223,13 @@ function nestedPropertyRegionKind(parentDeclaration, propertyName, value) {
|
|
|
139
223
|
}
|
|
140
224
|
|
|
141
225
|
export {
|
|
226
|
+
jsArrayObjectContextFromLine,
|
|
142
227
|
jsContextAllowsPropertyScan,
|
|
143
228
|
jsCurrentObjectContext,
|
|
144
229
|
jsInlineNestedObjectDeclarations,
|
|
145
230
|
jsNestedObjectContextFromDeclaration,
|
|
231
|
+
jsObjectPropertyDeclaration,
|
|
232
|
+
jsRouteRecordDeclaration,
|
|
233
|
+
updateJsArrayObjectContextName,
|
|
146
234
|
updateJsObjectContextStack
|
|
147
235
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
function jsStructureDelta(source) {
|
|
2
|
+
let value = 0;
|
|
3
|
+
let opened = false;
|
|
4
|
+
let quote;
|
|
5
|
+
let escaped = false;
|
|
6
|
+
for (const char of String(source ?? '')) {
|
|
7
|
+
if (quote) {
|
|
8
|
+
if (escaped) escaped = false;
|
|
9
|
+
else if (char === '\\') escaped = true;
|
|
10
|
+
else if (char === quote) quote = undefined;
|
|
11
|
+
continue;
|
|
12
|
+
}
|
|
13
|
+
if (char === '\'' || char === '"' || char === '`') {
|
|
14
|
+
quote = char;
|
|
15
|
+
continue;
|
|
16
|
+
}
|
|
17
|
+
if (char === '{' || char === '[' || char === '(') {
|
|
18
|
+
value += 1;
|
|
19
|
+
opened = true;
|
|
20
|
+
} else if (char === '}' || char === ']' || char === ')') {
|
|
21
|
+
value -= 1;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
return { value, opened };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export { jsStructureDelta };
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {
|
|
2
|
+
jsControlKeyword,
|
|
3
|
+
nativeDeclaration,
|
|
4
|
+
nativeSignatureDeclaration,
|
|
5
|
+
splitParameters
|
|
6
|
+
} from './native-region-scanner-core.js';
|
|
7
|
+
import { jsRegionKindForDeclarationName } from './native-region-scanner-js-helpers.js';
|
|
8
|
+
import { jsStructureDelta } from './native-region-scanner-js-structure.js';
|
|
9
|
+
|
|
10
|
+
function jsTypeRegionContext(name, declarationLine, lineNumber, regionKind, typeKind) {
|
|
11
|
+
const depth = jsStructureDelta(declarationLine).value;
|
|
12
|
+
if (depth <= 0) return undefined;
|
|
13
|
+
return {
|
|
14
|
+
name,
|
|
15
|
+
typeKind,
|
|
16
|
+
regionKind,
|
|
17
|
+
depth,
|
|
18
|
+
startLine: lineNumber,
|
|
19
|
+
memberStack: []
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
function jsCurrentTypeMemberContext(context) {
|
|
24
|
+
return context.memberStack.at(-1) ?? context;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function updateJsTypeRegionContext(context, lineNumber, source) {
|
|
28
|
+
const delta = jsStructureDelta(source).value;
|
|
29
|
+
context.depth += delta;
|
|
30
|
+
for (const memberContext of context.memberStack) {
|
|
31
|
+
if (memberContext.startLine !== lineNumber) memberContext.depth += delta;
|
|
32
|
+
}
|
|
33
|
+
while (context.memberStack.length && context.memberStack.at(-1).depth <= 0) context.memberStack.pop();
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function jsTypeMemberDeclaration(input, lineNumber, declarationLine, context) {
|
|
37
|
+
const text = String(declarationLine ?? '').trim();
|
|
38
|
+
if (!text || /^[}\])]/.test(text) || text.startsWith('//')) return undefined;
|
|
39
|
+
let match = text.match(/^(?:readonly\s+)?(['"]?)([A-Za-z_$][\w$-]*)\1\??\s*(?:<[^({;]+>)?\s*\(([^)]*)\)\s*(?::\s*([^;,]+))?[;,]?$/);
|
|
40
|
+
if (match && !jsControlKeyword(match[2])) {
|
|
41
|
+
return nativeSignatureDeclaration(input, lineNumber, 'TypeMethodSignature', 'method', `${context.name}.${match[2]}`, {
|
|
42
|
+
owner: context.name,
|
|
43
|
+
propertyName: match[2],
|
|
44
|
+
parameters: splitParameters(match[3]),
|
|
45
|
+
returnType: match[4]?.trim(),
|
|
46
|
+
typeKind: context.typeKind
|
|
47
|
+
}, false, {
|
|
48
|
+
regionKind: jsTypeMemberRegionKind(context, match[2], text),
|
|
49
|
+
metadata: { owner: context.name, propertyName: match[2], typeKind: context.typeKind }
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
match = text.match(/^(?:readonly\s+)?(['"]?)([A-Za-z_$][\w$-]*)\1\??\s*:\s*(.+?)[;,]?$/);
|
|
53
|
+
if (!match || jsControlKeyword(match[2])) return undefined;
|
|
54
|
+
const valueType = match[3].trim();
|
|
55
|
+
const functionLike = /=>/.test(valueType) || /^\([^)]*\)\s*=>/.test(valueType);
|
|
56
|
+
const hasNestedTypeLiteralBody = jsTypeMemberValueStartsTypeLiteral(valueType) && jsStructureDelta(text).value > 0;
|
|
57
|
+
return (functionLike ? nativeSignatureDeclaration : nativeDeclaration)(input, lineNumber, functionLike ? 'TypeFunctionPropertySignature' : 'TypePropertySignature', functionLike ? 'function' : 'property', `${context.name}.${match[2]}`, {
|
|
58
|
+
owner: context.name,
|
|
59
|
+
propertyName: match[2],
|
|
60
|
+
valueType,
|
|
61
|
+
typeKind: context.typeKind
|
|
62
|
+
}, hasNestedTypeLiteralBody, {
|
|
63
|
+
regionKind: jsTypeMemberRegionKind(context, match[2], text),
|
|
64
|
+
metadata: { owner: context.name, propertyName: match[2], typeKind: context.typeKind }
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function jsNestedTypeMemberContextFromDeclaration(declaration, lineNumber, source, parentContext) {
|
|
69
|
+
if (!declaration) return undefined;
|
|
70
|
+
const depth = jsStructureDelta(source).value;
|
|
71
|
+
if (depth <= 0) return undefined;
|
|
72
|
+
const valueType = declaration.fields?.valueType ?? declaration.fields?.returnType;
|
|
73
|
+
const nestedTypeLiteral = jsTypeMemberValueStartsTypeLiteral(valueType);
|
|
74
|
+
return {
|
|
75
|
+
name: nestedTypeLiteral ? declaration.name : parentContext.name,
|
|
76
|
+
typeKind: parentContext.typeKind,
|
|
77
|
+
regionKind: nestedTypeLiteral ? (declaration.regionKind ?? 'property') : parentContext.regionKind,
|
|
78
|
+
depth,
|
|
79
|
+
startLine: lineNumber,
|
|
80
|
+
suppressMembers: !nestedTypeLiteral
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function jsTypeMemberValueStartsTypeLiteral(valueType) {
|
|
85
|
+
const text = String(valueType ?? '').trim();
|
|
86
|
+
return text.startsWith('{') || /=>\s*\{\s*$/.test(text);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function jsTypeMemberRegionKind(context, propertyName) {
|
|
90
|
+
return jsRegionKindForDeclarationName(propertyName) ?? (context.regionKind === 'type' ? 'property' : context.regionKind) ?? 'property';
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export {
|
|
94
|
+
jsCurrentTypeMemberContext,
|
|
95
|
+
jsNestedTypeMemberContextFromDeclaration,
|
|
96
|
+
jsTypeMemberDeclaration,
|
|
97
|
+
jsTypeRegionContext,
|
|
98
|
+
updateJsTypeRegionContext
|
|
99
|
+
};
|