@shapeshift-labs/frontier-lang-compiler 0.2.103 → 0.2.105
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 +14 -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 +86 -0
- package/dist/declarations/js-ts-safe-merge.d.ts +131 -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 +265 -0
- package/dist/js-ts-safe-merge-analyze.js +279 -0
- package/dist/js-ts-safe-merge-composed.js +170 -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 +82 -0
- package/dist/js-ts-semantic-merge-member-utils.js +18 -0
- package/dist/js-ts-semantic-merge-parse.js +16 -0
- package/dist/js-ts-semantic-merge.js +24 -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
|
@@ -7,6 +7,7 @@ import {
|
|
|
7
7
|
isDependencyIdentifier,
|
|
8
8
|
maskDependencyLine
|
|
9
9
|
} from './lightweight-dependency-language.js';
|
|
10
|
+
import { lightweightEffectKinds } from './lightweight-dependency-effects.js';
|
|
10
11
|
import { sourceLines } from './native-region-scanner-core.js';
|
|
11
12
|
|
|
12
13
|
export function lightweightDependencyRelations(input, declarations, documentId) {
|
|
@@ -108,6 +109,7 @@ function addLightweightSemanticFacts(input, documentId, declaration, line, lineN
|
|
|
108
109
|
function shouldScanRuntimeFacts(input, declaration) {
|
|
109
110
|
if (!isJavaScriptLike(input)) return true;
|
|
110
111
|
if (declaration?.fields?.typeKind) return false;
|
|
112
|
+
if (['object', 'array'].includes(declaration?.fields?.initializerKind)) return false;
|
|
111
113
|
if (/^Type(?:Alias|Method|Property|FunctionProperty)/.test(String(declaration?.kind ?? ''))) return false;
|
|
112
114
|
return !['interface', 'type'].includes(String(declaration?.symbolKind ?? '').toLowerCase());
|
|
113
115
|
}
|
|
@@ -119,6 +121,10 @@ function isJavaScriptLike(input) {
|
|
|
119
121
|
function isIgnoredDependencyOccurrence(input, line, startIndex, name) {
|
|
120
122
|
if (!isJavaScriptLike(input)) return false;
|
|
121
123
|
const endIndex = startIndex + String(name).length;
|
|
124
|
+
const beforeText = line.slice(0, startIndex);
|
|
125
|
+
if (/\b(?:async\s+)?function\*?\s*$/.test(beforeText) || /\bclass\s*$/.test(beforeText)) return true;
|
|
126
|
+
const afterText = line.slice(endIndex);
|
|
127
|
+
if (/^\s*\([^)]*\)\s*\{/.test(afterText) && /^\s*(?:async\s+)?(?:get\s+|set\s+)?$/.test(beforeText)) return true;
|
|
122
128
|
const previous = previousNonSpace(line, startIndex - 1);
|
|
123
129
|
const next = nextNonSpace(line, endIndex);
|
|
124
130
|
return previous === '.' || next === ':';
|
|
@@ -148,17 +154,6 @@ function lightweightControlFlowKinds(line, state = {}) {
|
|
|
148
154
|
return kinds;
|
|
149
155
|
}
|
|
150
156
|
|
|
151
|
-
function lightweightEffectKinds(line) {
|
|
152
|
-
const kinds = [];
|
|
153
|
-
if (/\bawait\b|import\s*\(/.test(line)) kinds.push('async');
|
|
154
|
-
if (hasGlobalNetworkCall(line)) kinds.push('network');
|
|
155
|
-
if (/\b(localStorage|sessionStorage|indexedDB|caches|cookie)\b/.test(line)) kinds.push('storage');
|
|
156
|
-
if (/\b(setTimeout|setInterval|requestAnimationFrame|queueMicrotask)\s*\(/.test(line)) kinds.push('scheduler');
|
|
157
|
-
if (/\b(console|process|Deno|Bun)\s*\./.test(line)) kinds.push('host');
|
|
158
|
-
if (/\b(document|window|navigator|location|history)\s*\./.test(line)) kinds.push('browser');
|
|
159
|
-
return kinds;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
157
|
function lightweightMutationKinds(line) {
|
|
163
158
|
const kinds = [];
|
|
164
159
|
if (/\bdelete\s+[A-Za-z_$][\w$.[\]]*/.test(line)) kinds.push('delete');
|
|
@@ -199,24 +194,11 @@ function blockBraceDelta(line) {
|
|
|
199
194
|
return delta;
|
|
200
195
|
}
|
|
201
196
|
|
|
202
|
-
function hasGlobalNetworkCall(line) {
|
|
203
|
-
return hasBareCall(line, ['fetch', 'XMLHttpRequest', 'WebSocket', 'EventSource'])
|
|
204
|
-
|| hasGlobalPropertyCall(line, ['fetch', 'XMLHttpRequest', 'WebSocket', 'EventSource']);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function hasBareCall(line, names) {
|
|
208
|
-
return names.some((name) => new RegExp(`(?:^|[^\\w$.])${name}\\s*\\(`).test(line));
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
function hasGlobalPropertyCall(line, names) {
|
|
212
|
-
return names.some((name) => new RegExp(`\\b(?:window|globalThis|self)\\s*\\.\\s*${name}\\s*\\(`).test(line));
|
|
213
|
-
}
|
|
214
|
-
|
|
215
197
|
function hasRuntimeAssignment(line) {
|
|
216
198
|
const text = String(line ?? '');
|
|
217
199
|
for (let index = 0; index < text.length; index += 1) {
|
|
218
200
|
if (text[index] !== '=' || !isPlainAssignmentOperator(text, index)) continue;
|
|
219
|
-
if (!isLocalDeclarationInitializer(text, index)) return true;
|
|
201
|
+
if (!isLocalDeclarationInitializer(text, index) && !isJsxAttributeInitializer(text, index)) return true;
|
|
220
202
|
}
|
|
221
203
|
return false;
|
|
222
204
|
}
|
|
@@ -237,6 +219,8 @@ function isLocalDeclarationInitializer(text, index) {
|
|
|
237
219
|
|| /^(?:export\s+)?type\s+[A-Za-z_$][\w$]*(?:\s*<[^>]+>)?\s*$/.test(statement);
|
|
238
220
|
}
|
|
239
221
|
|
|
222
|
+
function isJsxAttributeInitializer(text, index) { const before = text.slice(0, index); const open = before.lastIndexOf('<'); return open >= 0 && before.lastIndexOf('>') < open && /<[A-Za-z][^<>{}]*\s[A-Za-z_$][\w:.-]*\s*$/.test(before.slice(open)); }
|
|
223
|
+
|
|
240
224
|
function addFactRecord(input, documentId, declaration, predicate, factKind, lineNumber, records) {
|
|
241
225
|
const key = `${declaration.symbolId}|${predicate}|${factKind}|${lineNumber}`;
|
|
242
226
|
if (records.seen.has(key)) return;
|
|
@@ -280,7 +264,9 @@ function addDependencyRecord(input, documentId, caller, target, occurrence, reco
|
|
|
280
264
|
confidence: 'lexical-reference',
|
|
281
265
|
sourceDocumentId: documentId,
|
|
282
266
|
sourceName: caller.name,
|
|
283
|
-
targetName: target.name
|
|
267
|
+
targetName: target.name,
|
|
268
|
+
occurrenceId,
|
|
269
|
+
sourceSpan: span
|
|
284
270
|
}
|
|
285
271
|
});
|
|
286
272
|
records.occurrences.push({
|
|
@@ -306,5 +292,6 @@ function addDependencyRecord(input, documentId, caller, target, occurrence, reco
|
|
|
306
292
|
}
|
|
307
293
|
|
|
308
294
|
function isCallReference(line, afterIdentifierIndex) {
|
|
309
|
-
|
|
295
|
+
const rest = String(line ?? '').slice(afterIdentifierIndex);
|
|
296
|
+
return /^\s*(?:\(|\?\.\s*\(|\?\.\s*(?:[A-Za-z_$][\w$]*|\[[^\]]+\])(?:\s*(?:\.|\?\.)\s*(?:[A-Za-z_$][\w$]*|\[[^\]]+\]))*\s*(?:\?\.)?\s*\()/.test(rest);
|
|
310
297
|
}
|
|
@@ -8,7 +8,7 @@ function nativeDeclaration(input, lineNumber, languageKind, symbolKind, name, fi
|
|
|
8
8
|
languageKind: `${input.language}.${languageKind}`,
|
|
9
9
|
name,
|
|
10
10
|
symbolKind,
|
|
11
|
-
symbolId: `symbol:${input.language}:${idFragment(name)}`,
|
|
11
|
+
symbolId: options.symbolId ?? `symbol:${input.language}:${idFragment(name)}`,
|
|
12
12
|
span: options.span ?? spanForLine(input, lineNumber),
|
|
13
13
|
fields,
|
|
14
14
|
metadata: { scan: 'lightweight-declaration', hasBody, ...options.metadata },
|
|
@@ -18,6 +18,22 @@ function nativeDeclaration(input, lineNumber, languageKind, symbolKind, name, fi
|
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
|
|
21
|
+
function nativeSignatureDeclaration(input, lineNumber, languageKind, symbolKind, name, fields = {}, _hasBody = false, options = {}) {
|
|
22
|
+
const signatureParts = [name, fields.signature, fields.returnType, fields.valueType, ...(fields.parameters ?? [])];
|
|
23
|
+
const signatureKey = idFragment(signatureParts.filter(Boolean).join(':') || `${name}:${lineNumber}`);
|
|
24
|
+
const sourcePath = input.sourcePath ?? `${input.language}:memory`;
|
|
25
|
+
const regionKind = options.regionKind ?? 'declaration';
|
|
26
|
+
return nativeDeclaration(input, lineNumber, languageKind, symbolKind, name, fields, false, {
|
|
27
|
+
regionKind,
|
|
28
|
+
symbolId: options.symbolId ?? `symbol:${input.language}:signature:${idFragment(name)}:${signatureKey}`,
|
|
29
|
+
metadata: {
|
|
30
|
+
signatureOnly: true,
|
|
31
|
+
ownershipRegionKey: options.ownershipRegionKey ?? `source#${sourcePath}#${regionKind}#${name}#${signatureKey}`,
|
|
32
|
+
...options.metadata
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
|
|
21
37
|
function nativeImportDeclaration(input, lineNumber, importPath, languageKind, symbolKind, options = {}) {
|
|
22
38
|
const name = String(options.name ?? importPath);
|
|
23
39
|
const nodeId = `native_${idFragment(languageKind)}_${lineNumber}_${idFragment(name)}`;
|
|
@@ -65,6 +81,20 @@ function nativeImportBindingDeclaration(input, lineNumber, importPath, binding,
|
|
|
65
81
|
});
|
|
66
82
|
}
|
|
67
83
|
|
|
84
|
+
function nativeExportDeclaration(input, lineNumber, exportedName, languageKind = 'ExportDeclaration', fields = {}, options = {}) {
|
|
85
|
+
const name = String(options.name ?? exportedName ?? 'default');
|
|
86
|
+
return nativeDeclaration(input, lineNumber, languageKind, options.symbolKind ?? 'export', name, {
|
|
87
|
+
exportedName: String(exportedName ?? name),
|
|
88
|
+
...fields
|
|
89
|
+
}, false, {
|
|
90
|
+
role: options.role ?? 'export',
|
|
91
|
+
regionKind: options.regionKind ?? 'export',
|
|
92
|
+
span: options.span,
|
|
93
|
+
symbolId: options.symbolId ?? `symbol:${input.language}:export:${idFragment(name)}`,
|
|
94
|
+
metadata: { scan: 'lightweight-export', ...options.metadata }
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
|
|
68
98
|
function nativeMacroLoss(input, lineNumber, source, kind, name = idFragment(source).slice(0, 40)) {
|
|
69
99
|
const nodeId = `native_${kind}_${lineNumber}_${idFragment(name)}`;
|
|
70
100
|
return {
|
|
@@ -202,9 +232,11 @@ export {
|
|
|
202
232
|
jsControlKeyword,
|
|
203
233
|
lightweightCoverageLosses,
|
|
204
234
|
nativeDeclaration,
|
|
235
|
+
nativeExportDeclaration,
|
|
205
236
|
nativeImportDeclaration,
|
|
206
237
|
nativeImportBindingDeclaration,
|
|
207
238
|
nativeMacroLoss,
|
|
239
|
+
nativeSignatureDeclaration,
|
|
208
240
|
sourceLines,
|
|
209
241
|
splitParameters,
|
|
210
242
|
splitTypeParameters
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import { uniqueStrings, 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 scanCSharp(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
|
+
|
|
15
|
+
let match;
|
|
16
|
+
if ((match = trimmed.match(/^using\s+([A-Za-z_]\w*)\s*=\s*(.+?)\s*;/))) {
|
|
17
|
+
declarations.push(nativeDeclaration(input, number, 'UsingAliasDirective', 'type', match[1], { target: match[2].trim() }, false));
|
|
18
|
+
} else if ((match = trimmed.match(/^using\s+(?:static\s+)?([A-Za-z_][\w.]*)\s*;/))) {
|
|
19
|
+
declarations.push(nativeImportDeclaration(input, number, match[1], 'UsingDirective', 'namespace'));
|
|
20
|
+
} else if ((match = trimmed.match(/^namespace\s+([A-Za-z_][\w.]*)/))) {
|
|
21
|
+
const hasBody = trimmed.includes('{');
|
|
22
|
+
declarations.push(nativeDeclaration(input, number, 'NamespaceDeclaration', 'namespace', match[1], {}, hasBody, spanOptions(input, lines, index, hasBody)));
|
|
23
|
+
if (hasBody) blockStack.push({ kind: 'namespace', name: match[1], bodyDepth: braceDepth + 1 });
|
|
24
|
+
} else if ((match = trimmed.match(/^((?:(?:public|protected|private|internal|static|unsafe|new)\s+)*)delegate\s+(.+?)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*;/))) {
|
|
25
|
+
declarations.push(nativeDeclaration(input, number, 'DelegateDeclaration', 'type', match[3], {
|
|
26
|
+
returnType: match[2].trim(),
|
|
27
|
+
parameters: splitParameters(match[4]),
|
|
28
|
+
modifiers: csharpModifiers(match[1])
|
|
29
|
+
}, false));
|
|
30
|
+
} 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*)/))) {
|
|
31
|
+
const owner = nearestType(blockStack);
|
|
32
|
+
const name = owner ? `${owner.name}.${match[3]}` : match[3];
|
|
33
|
+
const hasBody = trimmed.includes('{');
|
|
34
|
+
declarations.push(nativeDeclaration(input, number, csharpDeclarationKind(match[2]), csharpSymbolKind(match[2]), name, {
|
|
35
|
+
csharpKind: match[2].replace(/\s+/g, ' '),
|
|
36
|
+
modifiers: csharpModifiers(match[1]),
|
|
37
|
+
...(owner ? { owner: owner.name } : {})
|
|
38
|
+
}, hasBody, spanOptions(input, lines, index, hasBody)));
|
|
39
|
+
if (hasBody) blockStack.push({ kind: csharpTypeStackKind(match[2]), name, bodyDepth: braceDepth + 1 });
|
|
40
|
+
} 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*(?:=>.*|\{.*|;)?$/))) {
|
|
41
|
+
const parameters = splitParameters(match[3]);
|
|
42
|
+
const owner = nearestType(blockStack);
|
|
43
|
+
const extensionReceiver = csharpExtensionReceiver(parameters);
|
|
44
|
+
const target = csharpMethodTarget(owner, match[1], match[2], extensionReceiver);
|
|
45
|
+
const hasBody = trimmed.includes('{') || trimmed.includes('=>');
|
|
46
|
+
declarations.push(nativeDeclaration(input, number, extensionReceiver ? 'ExtensionMethodDeclaration' : 'MethodDeclaration', target.owner ? 'method' : 'function', target.name, {
|
|
47
|
+
parameters,
|
|
48
|
+
methodName: match[2],
|
|
49
|
+
modifiers: csharpModifiers(match[1]),
|
|
50
|
+
...(target.owner ? { owner: target.owner, receiverKind: target.receiverKind } : {}),
|
|
51
|
+
...(extensionReceiver ? { extensionReceiver } : {})
|
|
52
|
+
}, hasBody, {
|
|
53
|
+
...spanOptions(input, lines, index, trimmed.includes('{')),
|
|
54
|
+
metadata: {
|
|
55
|
+
methodName: match[2],
|
|
56
|
+
modifiers: csharpModifiers(match[1]),
|
|
57
|
+
...(target.owner ? { owner: target.owner, receiverKind: target.receiverKind } : {}),
|
|
58
|
+
...(extensionReceiver ? { extensionReceiver } : {})
|
|
59
|
+
}
|
|
60
|
+
}));
|
|
61
|
+
if (trimmed.includes('{')) blockStack.push({ kind: 'method', name: target.name, bodyDepth: braceDepth + 1 });
|
|
62
|
+
} 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*(?:[;{=]|=>)/))) {
|
|
63
|
+
const owner = nearestType(blockStack);
|
|
64
|
+
const name = owner ? `${owner.name}.${match[3]}` : match[3];
|
|
65
|
+
declarations.push(nativeDeclaration(input, number, 'EventDeclaration', 'event', name, {
|
|
66
|
+
eventType: match[2].trim(),
|
|
67
|
+
accessors: csharpAccessors(trimmed),
|
|
68
|
+
modifiers: csharpModifiers(match[1]),
|
|
69
|
+
...(owner ? { owner: owner.name, eventName: match[3] } : {})
|
|
70
|
+
}, trimmed.includes('{'), spanOptions(input, lines, index, trimmed.includes('{'))));
|
|
71
|
+
} 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*(?:\{|=>)/))) {
|
|
72
|
+
const owner = nearestType(blockStack);
|
|
73
|
+
const name = owner ? `${owner.name}.${match[3]}` : match[3];
|
|
74
|
+
declarations.push(nativeDeclaration(input, number, 'PropertyDeclaration', 'property', name, {
|
|
75
|
+
propertyType: match[2].trim(),
|
|
76
|
+
accessors: csharpAccessors(trimmed),
|
|
77
|
+
modifiers: csharpModifiers(match[1]),
|
|
78
|
+
...(owner ? { owner: owner.name, propertyName: match[3] } : {})
|
|
79
|
+
}, trimmed.includes('{') || trimmed.includes('=>'), spanOptions(input, lines, index, trimmed.includes('{'))));
|
|
80
|
+
}
|
|
81
|
+
braceDepth = Math.max(0, braceDepth + braceDelta(line));
|
|
82
|
+
}
|
|
83
|
+
return declarations;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function spanOptions(input, lines, index, hasBraceBody) {
|
|
87
|
+
return hasBraceBody ? { span: braceBlockSpan(input, lines, index) } : {};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function depthAfterLeadingClosers(trimmed, depth) {
|
|
91
|
+
const closers = String(trimmed).match(/^}+/)?.[0].length ?? 0;
|
|
92
|
+
return Math.max(0, depth - closers);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function nearestType(blockStack) {
|
|
96
|
+
for (let index = blockStack.length - 1; index >= 0; index -= 1) {
|
|
97
|
+
if (blockStack[index].kind === 'method') return undefined;
|
|
98
|
+
if (['class', 'interface', 'struct', 'record'].includes(blockStack[index].kind)) return blockStack[index];
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function csharpMethodTarget(owner, modifiers, methodName, extensionReceiver) {
|
|
104
|
+
if (extensionReceiver) return { name: `${extensionReceiver.type}.extension.${methodName}`, owner: extensionReceiver.type, receiverKind: 'extension' };
|
|
105
|
+
if (!owner) return { name: methodName };
|
|
106
|
+
const receiverKind = /\bstatic\b/.test(modifiers) ? 'static' : 'member';
|
|
107
|
+
return { name: receiverKind === 'static' ? `${owner.name}.static.${methodName}` : `${owner.name}.${methodName}`, owner: owner.name, receiverKind };
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function csharpModifiers(raw) {
|
|
111
|
+
return splitParameters(String(raw ?? '').trim().replace(/\s+/g, ','));
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function csharpTypeStackKind(kind) {
|
|
115
|
+
const normalized = String(kind).replace(/\s+/g, ' ');
|
|
116
|
+
if (normalized.startsWith('record')) return 'record';
|
|
117
|
+
if (normalized === 'enum') return 'enum';
|
|
118
|
+
if (normalized === 'struct') return 'struct';
|
|
119
|
+
if (normalized === 'interface') return 'interface';
|
|
120
|
+
return 'class';
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function csharpSymbolKind(kind) {
|
|
124
|
+
const normalized = String(kind).replace(/\s+/g, ' ');
|
|
125
|
+
if (normalized === 'interface') return 'interface';
|
|
126
|
+
if (normalized === 'struct' || normalized === 'enum' || normalized.startsWith('record')) return 'type';
|
|
127
|
+
return 'class';
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function csharpDeclarationKind(kind) {
|
|
131
|
+
const normalized = String(kind).replace(/\s+/g, ' ');
|
|
132
|
+
if (normalized === 'record struct') return 'RecordStructDeclaration';
|
|
133
|
+
if (normalized === 'record class') return 'RecordClassDeclaration';
|
|
134
|
+
if (normalized === 'record') return 'RecordDeclaration';
|
|
135
|
+
return `${upperFirst(normalized)}Declaration`;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function csharpExtensionReceiver(parameters) {
|
|
139
|
+
const match = String(parameters?.[0] ?? '').match(/^this\s+(.+?)\s+([A-Za-z_]\w*)$/);
|
|
140
|
+
return match ? { type: match[1].trim(), name: match[2] } : undefined;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function csharpAccessors(source) {
|
|
144
|
+
return uniqueStrings([...String(source ?? '').matchAll(/\b(get|set|init|add|remove)\b/g)].map((match) => match[1]));
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function braceDelta(source) {
|
|
148
|
+
return [...String(source ?? '')].reduce((delta, char) => delta + (char === '{' ? 1 : char === '}' ? -1 : 0), 0);
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export { scanCSharp };
|
|
@@ -0,0 +1,91 @@
|
|
|
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 scanDart(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
|
+
|
|
15
|
+
let match;
|
|
16
|
+
if ((match = trimmed.match(/^(?:import|export)\s+['"]([^'"]+)['"]/))) {
|
|
17
|
+
declarations.push(nativeImportDeclaration(input, number, match[1], 'UriBasedDirective', 'library'));
|
|
18
|
+
} else if ((match = trimmed.match(/^part\s+['"]([^'"]+)['"]/))) {
|
|
19
|
+
declarations.push(nativeImportDeclaration(input, number, match[1], 'PartDirective', 'library'));
|
|
20
|
+
} else if ((match = trimmed.match(/^(?:(?:abstract|base|final|interface|sealed)\s+)*(class|mixin|enum)\s+([A-Za-z_]\w*)/))) {
|
|
21
|
+
const hasBody = trimmed.includes('{');
|
|
22
|
+
declarations.push(nativeDeclaration(input, number, `${upperFirst(match[1])}Declaration`, dartSymbolKind(match[1]), match[2], {}, hasBody, spanOptions(input, lines, index, hasBody)));
|
|
23
|
+
if (hasBody) blockStack.push({ kind: match[1], name: match[2], bodyDepth: braceDepth + 1 });
|
|
24
|
+
} else if ((match = trimmed.match(/^extension(?:\s+([A-Za-z_]\w*))?\s+on\s+([A-Za-z_]\w*(?:<[^>]+>)?)\s*\{/))) {
|
|
25
|
+
const name = match[1] ? `${match[1]}.extension` : `${match[2]}.extension`;
|
|
26
|
+
declarations.push(nativeDeclaration(input, number, 'ExtensionDeclaration', 'implementation', name, {
|
|
27
|
+
receiverType: match[2],
|
|
28
|
+
...(match[1] ? { extensionName: match[1] } : {})
|
|
29
|
+
}, true, spanOptions(input, lines, index, true)));
|
|
30
|
+
blockStack.push({ kind: 'extension', name, receiverType: match[2], bodyDepth: braceDepth + 1 });
|
|
31
|
+
} else if ((match = trimmed.match(/^typedef\s+([A-Za-z_]\w*)\b/))) {
|
|
32
|
+
declarations.push(nativeDeclaration(input, number, 'TypeAlias', 'type', match[1], {}, false));
|
|
33
|
+
} else if ((match = trimmed.match(/^((?:(?:external|static)\s+)*)(?:[A-Za-z_]\w*(?:<[^>]+>)?\??|void)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*(?:async\s*)?(?:\{|=>|;)/))) {
|
|
34
|
+
const owner = nearestContainer(blockStack);
|
|
35
|
+
const target = dartFunctionTarget(owner, match[1], match[2]);
|
|
36
|
+
const hasBraceBody = trimmed.includes('{');
|
|
37
|
+
declarations.push(nativeDeclaration(input, number, 'FunctionDeclaration', target.owner ? 'method' : 'function', target.name, {
|
|
38
|
+
parameters: splitParameters(match[3]),
|
|
39
|
+
...(target.owner ? { owner: target.owner, methodName: match[2], receiverKind: target.receiverKind } : {}),
|
|
40
|
+
...(owner?.receiverType ? { receiverType: owner.receiverType } : {})
|
|
41
|
+
}, hasBraceBody || trimmed.includes('=>'), {
|
|
42
|
+
...spanOptions(input, lines, index, hasBraceBody),
|
|
43
|
+
metadata: {
|
|
44
|
+
...(target.owner ? { owner: target.owner, methodName: match[2], receiverKind: target.receiverKind } : {}),
|
|
45
|
+
...(owner?.receiverType ? { receiverType: owner.receiverType } : {})
|
|
46
|
+
}
|
|
47
|
+
}));
|
|
48
|
+
if (hasBraceBody) blockStack.push({ kind: 'function', name: target.name, bodyDepth: braceDepth + 1 });
|
|
49
|
+
} else if ((match = trimmed.match(/^(?:(?:static|external|late)\s+)*(?:const|final|var)\s+(?:[A-Za-z_]\w*(?:<[^>]+>)?\??\s+)?([A-Za-z_]\w*)\b/))) {
|
|
50
|
+
declarations.push(nativeDeclaration(input, number, 'VariableDeclaration', 'variable', match[1], {}, false));
|
|
51
|
+
}
|
|
52
|
+
braceDepth = Math.max(0, braceDepth + braceDelta(line));
|
|
53
|
+
}
|
|
54
|
+
return declarations;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function spanOptions(input, lines, index, hasBraceBody) {
|
|
58
|
+
return hasBraceBody ? { span: braceBlockSpan(input, lines, index) } : {};
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function depthAfterLeadingClosers(trimmed, depth) {
|
|
62
|
+
const closers = String(trimmed).match(/^}+/)?.[0].length ?? 0;
|
|
63
|
+
return Math.max(0, depth - closers);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function nearestContainer(blockStack) {
|
|
67
|
+
for (let index = blockStack.length - 1; index >= 0; index -= 1) {
|
|
68
|
+
if (blockStack[index].kind === 'function') return undefined;
|
|
69
|
+
if (['class', 'mixin', 'enum', 'extension'].includes(blockStack[index].kind)) return blockStack[index];
|
|
70
|
+
}
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function dartFunctionTarget(owner, modifiers, methodName) {
|
|
75
|
+
if (!owner) return { name: methodName };
|
|
76
|
+
if (owner.kind === 'extension') return { name: `${owner.name}.${methodName}`, owner: owner.name, receiverKind: 'extension' };
|
|
77
|
+
const receiverKind = /\bstatic\b/.test(modifiers) ? 'static' : 'member';
|
|
78
|
+
return { name: receiverKind === 'static' ? `${owner.name}.static.${methodName}` : `${owner.name}.${methodName}`, owner: owner.name, receiverKind };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function braceDelta(source) {
|
|
82
|
+
return [...String(source ?? '')].reduce((delta, char) => delta + (char === '{' ? 1 : char === '}' ? -1 : 0), 0);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function dartSymbolKind(kind) {
|
|
86
|
+
if (kind === 'mixin') return 'trait';
|
|
87
|
+
if (kind === 'enum') return 'type';
|
|
88
|
+
return 'class';
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { scanDart };
|
|
@@ -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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
194
|
-
|
|
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
|
|
221
|
-
|
|
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
|