@shapeshift-labs/frontier-lang-compiler 0.2.144 → 0.2.146
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/dist/internal/index-impl/syntaxDeclaration.js +23 -0
- package/dist/internal/index-impl/typeScriptDeclaration.js +14 -0
- package/dist/internal/index-impl/typeScriptExportedDeclarationEntries.js +1 -0
- package/dist/js-ts-safe-project-merge-graph.js +30 -7
- package/dist/js-ts-safe-project-merge-public-contracts.js +117 -0
- package/dist/js-ts-semantic-merge-member-source.js +11 -2
- package/package.json +1 -1
|
@@ -15,6 +15,29 @@ export function syntaxDeclaration(node, nativeNodeId, input) {
|
|
|
15
15
|
if (kind === 'ClassDeclaration') return namedDeclaration(input, nativeNodeId, node.id, 'class');
|
|
16
16
|
if (kind === 'TSInterfaceDeclaration' || kind === 'InterfaceDeclaration') return namedDeclaration(input, nativeNodeId, node.id, 'interface');
|
|
17
17
|
if (kind === 'TSTypeAliasDeclaration' || kind === 'TypeAliasDeclaration') return namedDeclaration(input, nativeNodeId, node.id, 'type');
|
|
18
|
+
if (kind === 'TSModuleDeclaration' || kind === 'ModuleDeclaration') return syntaxModuleDeclaration(input, nativeNodeId, node);
|
|
18
19
|
if (kind === 'VariableDeclarator') return namedDeclaration(input, nativeNodeId, node.id, 'variable');
|
|
19
20
|
return undefined;
|
|
20
21
|
}
|
|
22
|
+
|
|
23
|
+
function syntaxModuleDeclaration(input, nativeNodeId, node) {
|
|
24
|
+
const name = syntaxName(node.id ?? node.name);
|
|
25
|
+
if (!name) return undefined;
|
|
26
|
+
return {
|
|
27
|
+
...declarationRecord(input, nativeNodeId, name, 'module', 'definition'),
|
|
28
|
+
metadata: {
|
|
29
|
+
scan: 'syntax-module-declaration',
|
|
30
|
+
moduleName: name,
|
|
31
|
+
namespace: name
|
|
32
|
+
}
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function syntaxName(node) {
|
|
37
|
+
if (!node) return undefined;
|
|
38
|
+
if (typeof node === 'string') return node;
|
|
39
|
+
if (typeof node.name === 'string') return node.name;
|
|
40
|
+
if (typeof node.value === 'string') return node.value;
|
|
41
|
+
if (typeof node.text === 'string') return node.text;
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
@@ -14,6 +14,7 @@ export function typeScriptDeclaration(node, kind, nativeNodeId, input, options =
|
|
|
14
14
|
if (kind === 'ClassDeclaration') return declarationWithExports(enrich(namedDeclaration(input, nativeNodeId, node.name, 'class')), exportedEntries, enrich, node);
|
|
15
15
|
if (kind === 'InterfaceDeclaration') return declarationWithExports(enrich(namedDeclaration(input, nativeNodeId, node.name, 'interface')), exportedEntries, enrich, node);
|
|
16
16
|
if (kind === 'TypeAliasDeclaration' || kind === 'EnumDeclaration') return declarationWithExports(enrich(namedDeclaration(input, nativeNodeId, node.name, 'type')), exportedEntries, enrich, node);
|
|
17
|
+
if (kind === 'ModuleDeclaration') return declarationWithExports(enrich(moduleDeclaration(input, nativeNodeId, node), node.name ?? node), exportedEntries, enrich, node);
|
|
17
18
|
if (kind === 'VariableDeclaration') return enrich(namedDeclaration(input, nativeNodeId, node.name, 'variable'));
|
|
18
19
|
if (kind === 'MethodDeclaration' || kind === 'MethodSignature') return enrich(namedDeclaration(input, nativeNodeId, node.name, 'method'));
|
|
19
20
|
return undefined;
|
|
@@ -25,6 +26,19 @@ function declarationWithExports(declaration, exportedEntries, enrich, node) {
|
|
|
25
26
|
return exports.length ? [declaration, ...exports] : declaration;
|
|
26
27
|
}
|
|
27
28
|
|
|
29
|
+
function moduleDeclaration(input, nativeNodeId, node) {
|
|
30
|
+
const name = stringFromTsExpression(node.name);
|
|
31
|
+
if (!name) return undefined;
|
|
32
|
+
return {
|
|
33
|
+
...declarationRecord(input, nativeNodeId, name, 'module', 'definition'),
|
|
34
|
+
metadata: compactRecord({
|
|
35
|
+
scan: 'typescript-module-declaration',
|
|
36
|
+
moduleName: name,
|
|
37
|
+
namespace: name
|
|
38
|
+
})
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
28
42
|
function enrichTypeScriptDeclaration(node, symbolNode, declaration, input, options) {
|
|
29
43
|
if (!declaration) return declaration;
|
|
30
44
|
const checker = options.typeChecker ?? options.checker ?? options.program?.getTypeChecker?.();
|
|
@@ -92,6 +92,7 @@ function exportedSymbolKind(kind) {
|
|
|
92
92
|
if (kind === 'ClassDeclaration') return 'class';
|
|
93
93
|
if (kind === 'InterfaceDeclaration') return 'interface';
|
|
94
94
|
if (kind === 'TypeAliasDeclaration' || kind === 'EnumDeclaration') return 'type';
|
|
95
|
+
if (kind === 'ModuleDeclaration') return 'module';
|
|
95
96
|
return undefined;
|
|
96
97
|
}
|
|
97
98
|
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { idFragment } from './native-import-utils.js';
|
|
2
2
|
import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
|
|
3
3
|
import { compactRecord } from './js-ts-safe-merge-context.js';
|
|
4
|
+
import { augmentProjectSymbolGraphPublicContracts } from './js-ts-safe-project-merge-public-contracts.js';
|
|
4
5
|
import { createNativeProjectImportResult } from './internal/index-impl/createNativeProjectImportResult.js';
|
|
5
6
|
import { importNativeSource } from './internal/index-impl/importNativeSource.js';
|
|
6
7
|
import {
|
|
@@ -92,22 +93,26 @@ function createProjectGraphStageArtifacts(input, files, mergeId, stageName, stag
|
|
|
92
93
|
...(stageName === 'output' ? { outputProjectImportSource: projectGraphImportSource } : {})
|
|
93
94
|
}
|
|
94
95
|
}, imports);
|
|
95
|
-
const
|
|
96
|
+
const projectSymbolGraph = augmentProjectSymbolGraphPublicContracts(projectImport.projectSymbolGraph, files, input, stageName);
|
|
97
|
+
const stageProjectImport = projectSymbolGraph === projectImport.projectSymbolGraph
|
|
98
|
+
? projectImport
|
|
99
|
+
: attachProjectSymbolGraph(projectImport, projectSymbolGraph);
|
|
100
|
+
const edgeLimitConflicts = projectGraphEdgeLimitConflicts(limits, stageName, projectSymbolGraph);
|
|
96
101
|
const serialized = projectGraphSerializedLimitConflict(limits, stageName, {
|
|
97
|
-
projectImport,
|
|
98
|
-
projectSymbolGraph
|
|
102
|
+
projectImport: stageProjectImport,
|
|
103
|
+
projectSymbolGraph
|
|
99
104
|
});
|
|
100
105
|
const limitConflicts = [...edgeLimitConflicts, serialized.conflict].filter(Boolean);
|
|
101
106
|
if (limitConflicts.length) {
|
|
102
|
-
return limitedProjectGraphStage(stageName, projectGraphImportSource, sourceStats,
|
|
107
|
+
return limitedProjectGraphStage(stageName, projectGraphImportSource, sourceStats, projectSymbolGraph, limitConflicts, serialized.serializedBytes);
|
|
103
108
|
}
|
|
104
109
|
return {
|
|
105
110
|
kind: 'frontier.lang.jsTsProjectGraphStage',
|
|
106
111
|
version: 1,
|
|
107
112
|
stage: stageName,
|
|
108
|
-
projectImport,
|
|
109
|
-
projectSymbolGraph
|
|
110
|
-
summary: projectGraphStageSummary(stageName,
|
|
113
|
+
projectImport: stageProjectImport,
|
|
114
|
+
projectSymbolGraph,
|
|
115
|
+
summary: projectGraphStageSummary(stageName, projectSymbolGraph, projectGraphImportSource, sourceStats, serialized.serializedBytes, [])
|
|
111
116
|
};
|
|
112
117
|
}
|
|
113
118
|
|
|
@@ -215,6 +220,24 @@ function stageFile(file, sourceText, input) {
|
|
|
215
220
|
});
|
|
216
221
|
}
|
|
217
222
|
|
|
223
|
+
function attachProjectSymbolGraph(projectImport, projectSymbolGraph) {
|
|
224
|
+
return {
|
|
225
|
+
...projectImport,
|
|
226
|
+
projectSymbolGraph,
|
|
227
|
+
semanticIndex: projectImport.semanticIndex ? {
|
|
228
|
+
...projectImport.semanticIndex,
|
|
229
|
+
metadata: {
|
|
230
|
+
...projectImport.semanticIndex.metadata,
|
|
231
|
+
projectSymbolGraph
|
|
232
|
+
}
|
|
233
|
+
} : projectImport.semanticIndex,
|
|
234
|
+
metadata: {
|
|
235
|
+
...projectImport.metadata,
|
|
236
|
+
projectSymbolGraph
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
218
241
|
function hashText(sourceText) {
|
|
219
242
|
return hashSemanticValue(sourceText);
|
|
220
243
|
}
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { hashSemanticValue } from '@shapeshift-labs/frontier-lang-kernel';
|
|
2
|
+
import { compactRecord } from './js-ts-safe-merge-context.js';
|
|
3
|
+
import { findContainer, normalizeKind, normalizeMemberText, parseMembers } from './js-ts-semantic-merge-parse.js';
|
|
4
|
+
import { idFragment } from './native-import-utils.js';
|
|
5
|
+
|
|
6
|
+
function augmentProjectSymbolGraphPublicContracts(projectSymbolGraph, files, input, stageName) {
|
|
7
|
+
const existingRegions = Array.isArray(projectSymbolGraph?.publicContractRegions) ? projectSymbolGraph.publicContractRegions : [];
|
|
8
|
+
const seenKeys = new Set(existingRegions.map((region) => region?.key).filter(Boolean));
|
|
9
|
+
const syntheticRegions = [];
|
|
10
|
+
for (const file of files) {
|
|
11
|
+
syntheticRegions.push(...syntheticPublicContractRegions(file, input, stageName, seenKeys));
|
|
12
|
+
}
|
|
13
|
+
if (!syntheticRegions.length) return projectSymbolGraph;
|
|
14
|
+
return {
|
|
15
|
+
...projectSymbolGraph,
|
|
16
|
+
publicContractRegions: [...existingRegions, ...syntheticRegions]
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function syntheticPublicContractRegions(file, input, stageName, seenKeys) {
|
|
21
|
+
if (typeof file?.sourceText !== 'string' || !file.sourcePath) return [];
|
|
22
|
+
const records = [];
|
|
23
|
+
for (const region of publicContractPolicyRegionsForPath(input, file.sourcePath)) {
|
|
24
|
+
const kind = normalizeKind(region?.kind);
|
|
25
|
+
if (!['interface', 'type', 'class'].includes(kind) || typeof region?.name !== 'string') continue;
|
|
26
|
+
const container = findContainer(file.sourceText, region);
|
|
27
|
+
if (container.reasonCodes.length || !isExportedContainer(file.sourceText, container.value)) continue;
|
|
28
|
+
const members = parseMembers(container.value.body, kind);
|
|
29
|
+
if (members.reasonCodes.length) continue;
|
|
30
|
+
const key = `source#${file.sourcePath}#export#${region.name}`;
|
|
31
|
+
if (seenKeys.has(key)) continue;
|
|
32
|
+
seenKeys.add(key);
|
|
33
|
+
records.push(syntheticPublicContractRegion(file, input, stageName, kind, region.name, key, members.members));
|
|
34
|
+
}
|
|
35
|
+
return records;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function syntheticPublicContractRegion(file, input, stageName, kind, name, key, members) {
|
|
39
|
+
const language = file.language ?? input.language ?? languageForPath(file.sourcePath);
|
|
40
|
+
const memberRecords = members.map((member) => compactRecord({
|
|
41
|
+
key: member.key,
|
|
42
|
+
memberKind: member.memberKind,
|
|
43
|
+
signature: normalizeMemberText(member.text, kind)
|
|
44
|
+
}));
|
|
45
|
+
const signatureHash = hashSemanticValue({
|
|
46
|
+
kind: 'frontier.lang.syntheticPublicContractSignature',
|
|
47
|
+
language,
|
|
48
|
+
sourcePath: file.sourcePath,
|
|
49
|
+
symbolName: name,
|
|
50
|
+
sourceKind: kind,
|
|
51
|
+
members: memberRecords
|
|
52
|
+
});
|
|
53
|
+
const contractHash = hashSemanticValue({
|
|
54
|
+
kind: 'frontier.lang.syntheticPublicContractRegionHash',
|
|
55
|
+
language,
|
|
56
|
+
sourcePath: file.sourcePath,
|
|
57
|
+
key,
|
|
58
|
+
symbolName: name,
|
|
59
|
+
symbolKind: 'export',
|
|
60
|
+
apiSurfaceKind: 'module-export',
|
|
61
|
+
exportedName: name,
|
|
62
|
+
edgeKind: 'export',
|
|
63
|
+
signatureHash
|
|
64
|
+
});
|
|
65
|
+
return compactRecord({
|
|
66
|
+
id: `region_${idFragment(stageName)}_${idFragment(key)}`,
|
|
67
|
+
key,
|
|
68
|
+
regionKind: 'export',
|
|
69
|
+
granularity: 'symbol',
|
|
70
|
+
language,
|
|
71
|
+
sourcePath: file.sourcePath,
|
|
72
|
+
sourceHash: file.sourceHash,
|
|
73
|
+
symbolId: `symbol:${language}:export:${idFragment(name)}`,
|
|
74
|
+
symbolName: name,
|
|
75
|
+
symbolKind: 'export',
|
|
76
|
+
publicContract: true,
|
|
77
|
+
exportedName: name,
|
|
78
|
+
edgeKind: 'export',
|
|
79
|
+
apiSurfaceKind: 'module-export',
|
|
80
|
+
signatureHash,
|
|
81
|
+
contractHash,
|
|
82
|
+
metadata: {
|
|
83
|
+
source: 'js-ts-safe-project-merge-policy',
|
|
84
|
+
projectGraphStage: stageName,
|
|
85
|
+
sourceKind: kind,
|
|
86
|
+
memberKeys: memberRecords.map((member) => member.key)
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function publicContractPolicyRegionsForPath(input, sourcePath) {
|
|
92
|
+
const policy = input.policyByPath?.[sourcePath]
|
|
93
|
+
?? input.mergePolicyByPath?.[sourcePath]
|
|
94
|
+
?? input.policy
|
|
95
|
+
?? input.mergePolicy;
|
|
96
|
+
const regions = Array.isArray(policy)
|
|
97
|
+
? policy
|
|
98
|
+
: policy?.unorderedRegions
|
|
99
|
+
?? policy?.unorderedMemberRegions
|
|
100
|
+
?? policy?.safeList
|
|
101
|
+
?? policy?.safeMembers
|
|
102
|
+
?? [];
|
|
103
|
+
return Array.isArray(regions) ? regions : [];
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function isExportedContainer(sourceText, container) {
|
|
107
|
+
if (!container) return false;
|
|
108
|
+
return /^\s*export\b/.test(sourceText.slice(container.start, container.openStart));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function languageForPath(sourcePath) {
|
|
112
|
+
const path = String(sourcePath ?? '').toLowerCase();
|
|
113
|
+
if (path.endsWith('.js') || path.endsWith('.jsx') || path.endsWith('.mjs') || path.endsWith('.cjs')) return 'javascript';
|
|
114
|
+
return 'typescript';
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export { augmentProjectSymbolGraphPublicContracts };
|
|
@@ -17,7 +17,7 @@ function removePreparedMemberAdditions(sourceText, preparedRegions, side) {
|
|
|
17
17
|
const replacements = preparedRegions
|
|
18
18
|
.map((region) => ({
|
|
19
19
|
range: region[side],
|
|
20
|
-
replacement: removeMembersFromBody(region[side].body, region[`${side}AddedMembers`] ?? [], region.kind)
|
|
20
|
+
replacement: removeMembersFromBody(region[side].body, region[`${side}AddedMembers`] ?? [], region.kind, region.base.body)
|
|
21
21
|
}))
|
|
22
22
|
.sort((left, right) => right.range.bodyStart - left.range.bodyStart);
|
|
23
23
|
for (const { range, replacement } of replacements) {
|
|
@@ -88,16 +88,25 @@ function appendReadyBody(before, kind) {
|
|
|
88
88
|
return `${before.replace(/\s*$/, '')},`;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
function removeMembersFromBody(body, members, kind) {
|
|
91
|
+
function removeMembersFromBody(body, members, kind, baseBody) {
|
|
92
92
|
let output = body;
|
|
93
93
|
for (const member of [...members].sort((left, right) => right.start - left.start || right.end - left.end)) {
|
|
94
94
|
output = `${output.slice(0, member.start)}${output.slice(member.end)}`;
|
|
95
95
|
}
|
|
96
96
|
if (kind !== 'object') return output;
|
|
97
|
+
if (typeof baseBody === 'string' && sameObjectBodyIgnoringTrailingDelimiter(output, baseBody)) return baseBody;
|
|
97
98
|
const trailing = String(body ?? '').match(/\s*$/)?.[0] ?? '';
|
|
98
99
|
return output.replace(/,\s*$/, trailing);
|
|
99
100
|
}
|
|
100
101
|
|
|
102
|
+
function sameObjectBodyIgnoringTrailingDelimiter(left, right) {
|
|
103
|
+
return normalizeObjectTrailingDelimiter(left) === normalizeObjectTrailingDelimiter(right);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function normalizeObjectTrailingDelimiter(body) {
|
|
107
|
+
return String(body ?? '').replace(/,\s*$/, (trailing) => trailing.replace(',', ''));
|
|
108
|
+
}
|
|
109
|
+
|
|
101
110
|
function minimumIndent(lines) {
|
|
102
111
|
const indents = lines.filter((line) => line.trim()).map(leadingWhitespace);
|
|
103
112
|
return indents.length ? Math.min(...indents) : 0;
|
package/package.json
CHANGED