@shapeshift-labs/frontier-lang-compiler 0.2.111 → 0.2.112
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 +7 -0
- package/dist/declarations/js-ts-safe-project-merge.d.ts +3 -0
- package/dist/declarations/native-project-module-resolution.d.ts +11 -0
- package/dist/declarations/native-project.d.ts +6 -6
- package/dist/index.d.ts +1 -0
- package/dist/internal/index-impl/createNativeProjectImportResult.js +6 -6
- package/dist/internal/index-impl/projectSymbolGraphModuleResolution.js +65 -0
- package/dist/js-ts-safe-project-merge-graph.js +1 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -198,6 +198,7 @@ import { safeMergeJsTsProject } from '@shapeshift-labs/frontier-lang-compiler';
|
|
|
198
198
|
|
|
199
199
|
const project = safeMergeJsTsProject({
|
|
200
200
|
language: 'typescript',
|
|
201
|
+
moduleResolution: { baseUrl: '.', paths: { '@app/*': ['src/*'] } },
|
|
201
202
|
baseFiles: { 'src/index.ts': 'export const stable = 1;\n' },
|
|
202
203
|
workerFiles: { 'src/index.ts': 'export const stable = 1;\nexport const workerOnly = 1;\n' },
|
|
203
204
|
headFiles: { 'src/index.ts': 'export const stable = 1;\n' }
|
|
@@ -208,6 +209,11 @@ console.log(project.outputFiles[0].sourcePath); // "src/index.ts"
|
|
|
208
209
|
console.log(project.files[0].semanticArtifacts.status); // "verified"
|
|
209
210
|
```
|
|
210
211
|
|
|
212
|
+
When `includeOutputProjectSymbolGraph` is enabled, the same
|
|
213
|
+
`moduleResolution` shape is used for output graph artifacts. Resolution is
|
|
214
|
+
runtime-neutral: `baseUrl`, `paths`, `aliases`, and `compilerOptions.paths`
|
|
215
|
+
are matched against the supplied project files, not the host filesystem.
|
|
216
|
+
|
|
211
217
|
High-risk native features also have explicit evidence policies. These policies are advisory in this package: they tell a swarm or admission queue what evidence is missing without silently changing the existing readiness classification.
|
|
212
218
|
|
|
213
219
|
```js
|
|
@@ -817,6 +823,7 @@ const imported = await runNativeImporterAdapter(babelAdapter, {
|
|
|
817
823
|
|
|
818
824
|
const project = await importNativeProject({
|
|
819
825
|
projectRoot: 'src',
|
|
826
|
+
moduleResolution: { baseUrl: '.', paths: { '@app/*': ['src/*'] } },
|
|
820
827
|
adapters: [babelAdapter, pythonAstAdapter, rustSynAdapter, clangAstAdapter, goAstAdapter, javaAstAdapter, kotlinPsiAdapter, csharpRoslynAdapter, swiftSyntaxAdapter],
|
|
821
828
|
sources: [
|
|
822
829
|
{ language: 'typescript', adapter: babelAdapter.id, sourcePath: 'src/todo.ts', sourceText },
|
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
} from './js-ts-safe-merge.js';
|
|
9
9
|
import type { JsTsSafeMemberMergePolicy, JsTsSafeMemberMergePolicyRegion } from './js-ts-safe-member-merge.js';
|
|
10
10
|
import type { NativeProjectImportResult, NativeProjectSymbolGraphSummary } from './native-project.js';
|
|
11
|
+
import type { NativeProjectModuleResolutionOptions } from './native-project-module-resolution.js';
|
|
11
12
|
|
|
12
13
|
export type JsTsProjectSafeMergeStatus = 'merged' | 'blocked';
|
|
13
14
|
export type JsTsProjectSafeMergeFileStatus = 'merged' | 'blocked';
|
|
@@ -55,6 +56,8 @@ export interface JsTsProjectSafeMergeInput {
|
|
|
55
56
|
readonly allowFileAdditions?: boolean;
|
|
56
57
|
readonly allowFileDeletes?: boolean;
|
|
57
58
|
readonly includeOutputProjectSymbolGraph?: boolean;
|
|
59
|
+
readonly moduleResolution?: NativeProjectModuleResolutionOptions;
|
|
60
|
+
readonly tsconfig?: NativeProjectModuleResolutionOptions;
|
|
58
61
|
readonly workerChangeSetId?: string;
|
|
59
62
|
readonly headChangeSetId?: string;
|
|
60
63
|
readonly policy?: JsTsSafeMemberMergePolicy | readonly JsTsSafeMemberMergePolicyRegion[];
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export type NativeProjectModuleResolutionPaths = Readonly<Record<string, readonly string[] | string>>;
|
|
2
|
+
|
|
3
|
+
export interface NativeProjectModuleResolutionOptions {
|
|
4
|
+
readonly baseUrl?: string;
|
|
5
|
+
readonly paths?: NativeProjectModuleResolutionPaths;
|
|
6
|
+
readonly aliases?: NativeProjectModuleResolutionPaths;
|
|
7
|
+
readonly compilerOptions?: {
|
|
8
|
+
readonly baseUrl?: string;
|
|
9
|
+
readonly paths?: NativeProjectModuleResolutionPaths;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
@@ -49,11 +49,11 @@ import type { JavaScriptNativeImporterAdapterOptions, TypeScriptCompilerNativeIm
|
|
|
49
49
|
import type { JavaAstNativeImporterAdapterOptions, KotlinPsiNativeImporterAdapterOptions, CSharpRoslynNativeImporterAdapterOptions, SwiftSyntaxNativeImporterAdapterOptions, TreeSitterNativeImporterAdapterOptions } from './import-adapter-options-platform.js';
|
|
50
50
|
import type { NativeTargetProjectionAdapterCoverageInput, NativeTargetProjectionAdapterSummary, NativeTargetProjectionAdapterInput, NativeTargetProjectionAdapterResult, NativeTargetProjectionAdapter, NativeTargetProjectionAdapterResolverInput, NativeTargetProjectionResult } from './target-adapters.js';
|
|
51
51
|
import type { NativeImportRoundtripReadinessStatus, NativeImportRoundtripReadinessOptions, NativeImportRoundtripReadinessClassification } from './roundtrip.js';
|
|
52
|
+
import type { NativeProjectModuleResolutionOptions } from './native-project-module-resolution.js';
|
|
52
53
|
|
|
53
54
|
export interface NativeProjectSourceInput extends ImportNativeSourceOptions {
|
|
54
55
|
readonly adapter?: NativeImporterAdapter | string;
|
|
55
|
-
readonly adapterOptions?: Record<string, unknown>;
|
|
56
|
-
readonly adapterMetadata?: Record<string, unknown>;
|
|
56
|
+
readonly adapterOptions?: Record<string, unknown>; readonly adapterMetadata?: Record<string, unknown>;
|
|
57
57
|
}
|
|
58
58
|
|
|
59
59
|
export interface ImportNativeProjectOptions {
|
|
@@ -70,15 +70,15 @@ export interface ImportNativeProjectOptions {
|
|
|
70
70
|
readonly patchId?: string;
|
|
71
71
|
readonly author?: string;
|
|
72
72
|
readonly metadata?: Record<string, unknown>;
|
|
73
|
-
readonly
|
|
74
|
-
readonly
|
|
73
|
+
readonly moduleResolution?: NativeProjectModuleResolutionOptions;
|
|
74
|
+
readonly tsconfig?: NativeProjectModuleResolutionOptions;
|
|
75
|
+
readonly adapterOptions?: Record<string, unknown>; readonly adapterMetadata?: Record<string, unknown>;
|
|
75
76
|
readonly adapters?: readonly NativeImporterAdapter[];
|
|
76
77
|
readonly adapterResolver?: (source: NativeProjectSourceInput, adapters: readonly NativeImporterAdapter[]) => NativeImporterAdapter | undefined;
|
|
77
78
|
readonly sources: readonly NativeProjectSourceInput[];
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
export type NativeProjectSymbolGraphRemainingField =
|
|
81
|
-
| 'moduleEdges[].resolutionKind'
|
|
82
82
|
| 'moduleEdges[].packageName'
|
|
83
83
|
| 'moduleEdges[].packageExportCondition'
|
|
84
84
|
| 'reExportIdentities[].originSymbolId'
|
|
@@ -112,7 +112,7 @@ export interface NativeProjectSymbolGraphModuleEdgeRecord {
|
|
|
112
112
|
readonly resolvedModulePath?: string;
|
|
113
113
|
readonly targetDocumentId?: string;
|
|
114
114
|
readonly resolvedTargetSymbolId?: string;
|
|
115
|
-
readonly resolutionKind?: 'relative-source' | 'relative-missing' | string;
|
|
115
|
+
readonly resolutionKind?: 'relative-source' | 'relative-missing' | 'alias-source' | 'alias-missing' | 'path-alias-source' | 'path-alias-missing' | 'base-url-source' | 'base-url-missing' | string;
|
|
116
116
|
readonly importKind?: string;
|
|
117
117
|
readonly exportKind?: string;
|
|
118
118
|
readonly importedName?: string;
|
package/dist/index.d.ts
CHANGED
|
@@ -40,6 +40,7 @@ export * from './declarations/import-adapter-options-native.js';
|
|
|
40
40
|
export * from './declarations/import-adapter-options-platform.js';
|
|
41
41
|
export * from './declarations/target-adapters.js';
|
|
42
42
|
export * from './declarations/native-project-admission.js';
|
|
43
|
+
export * from './declarations/native-project-module-resolution.js';
|
|
43
44
|
export * from './declarations/native-project.js';
|
|
44
45
|
export * from './declarations/roundtrip.js';
|
|
45
46
|
export * from './declarations/runtime.js';
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import{idFragment,uniqueByEvidenceId,uniqueByLossId,uniqueStrings}from'../../native-import-utils.js';import{createDocument,createPatch,createUniversalAstEnvelope}from'@shapeshift-labs/frontier-lang-kernel';
|
|
2
2
|
import{createNativeImportResultContract}from'./createNativeImportResultContract.js';import{createProjectImportAdmissionRecord}from'./createProjectImportAdmissionRecord.js';import{mergeSemanticIndexes}from'./mergeSemanticIndexes.js';import{summarizeNativeImportLosses}from'./summarizeNativeImportLosses.js';import{summarizeProjectSourcePreservation}from'./summarizeProjectSourcePreservation.js';
|
|
3
|
-
import{createProjectModuleSymbolResolver,
|
|
3
|
+
import{createProjectModuleSymbolResolver,resolveProjectModule}from'./projectSymbolGraphModuleResolution.js';
|
|
4
4
|
export function createNativeProjectImportResult(input, imports) {
|
|
5
5
|
const idPart = idFragment(input.id ?? input.projectRoot ?? 'native_project');
|
|
6
6
|
const nodes = {};
|
|
@@ -141,7 +141,6 @@ export function createNativeProjectImportResult(input, imports) {
|
|
|
141
141
|
}
|
|
142
142
|
|
|
143
143
|
const PROJECT_SYMBOL_GRAPH_REMAINING_FIELDS = Object.freeze([
|
|
144
|
-
'moduleEdges[].resolutionKind',
|
|
145
144
|
'moduleEdges[].packageName',
|
|
146
145
|
'moduleEdges[].packageExportCondition',
|
|
147
146
|
'reExportIdentities[].originSymbolId',
|
|
@@ -157,6 +156,7 @@ function createProjectSymbolGraphSummary(semanticIndex, imports, input) {
|
|
|
157
156
|
const symbolsById = new Map((semanticIndex?.symbols ?? []).map((symbol) => [symbol.id, symbol]));
|
|
158
157
|
const documentsById = new Map(documents.map((document) => [document.id, document]));
|
|
159
158
|
const documentsByPath = new Map(documents.filter((document) => document.path).map((document) => [document.path, document]));
|
|
159
|
+
const moduleResolution = input.moduleResolution ?? input.tsconfig;
|
|
160
160
|
const resolveTargetSymbolId = createProjectModuleSymbolResolver(semanticIndex?.symbols ?? [], documents);
|
|
161
161
|
const facts = semanticIndex?.facts ?? [];
|
|
162
162
|
const moduleEdgeFacts = facts.filter((fact) => fact.predicate === 'moduleEdge');
|
|
@@ -164,10 +164,10 @@ function createProjectSymbolGraphSummary(semanticIndex, imports, input) {
|
|
|
164
164
|
const relations = semanticIndex?.relations ?? [];
|
|
165
165
|
const importEdges = relations
|
|
166
166
|
.filter((relation) => relation.predicate === 'imports')
|
|
167
|
-
.map((relation) => moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, resolveTargetSymbolId));
|
|
167
|
+
.map((relation) => moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, moduleResolution, resolveTargetSymbolId));
|
|
168
168
|
const exportEdges = relations
|
|
169
169
|
.filter((relation) => relation.predicate === 'exports')
|
|
170
|
-
.map((relation) => moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, resolveTargetSymbolId));
|
|
170
|
+
.map((relation) => moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, moduleResolution, resolveTargetSymbolId));
|
|
171
171
|
const reExportIdentities = uniqueRecords([
|
|
172
172
|
...facts
|
|
173
173
|
.filter((fact) => fact.predicate === 'reExportIdentity' && fact.value)
|
|
@@ -213,7 +213,7 @@ function createProjectSymbolGraphSummary(semanticIndex, imports, input) {
|
|
|
213
213
|
};
|
|
214
214
|
}
|
|
215
215
|
|
|
216
|
-
function moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, resolveTargetSymbolId) {
|
|
216
|
+
function moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById, documentsByPath, moduleResolution, resolveTargetSymbolId) {
|
|
217
217
|
const fact = moduleEdgeByRelation.get(relation.id);
|
|
218
218
|
const value = objectValue(fact?.value);
|
|
219
219
|
const metadata = objectValue(relation.metadata);
|
|
@@ -231,7 +231,7 @@ function moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documents
|
|
|
231
231
|
symbolMetadata.source,
|
|
232
232
|
symbol?.kind === 'module' ? symbol.name : undefined
|
|
233
233
|
);
|
|
234
|
-
const resolution =
|
|
234
|
+
const resolution = resolveProjectModule(document?.path, moduleSpecifier, documentsByPath, moduleResolution);
|
|
235
235
|
const record = {
|
|
236
236
|
id: relation.id,
|
|
237
237
|
sourceDocumentId: relation.sourceId,
|
|
@@ -10,6 +10,12 @@ export function resolveRelativeProjectModule(sourcePath, moduleSpecifier, docume
|
|
|
10
10
|
};
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
+
export function resolveProjectModule(sourcePath, moduleSpecifier, documentsByPath, moduleResolution) {
|
|
14
|
+
if (!sourcePath || !moduleSpecifier) return undefined;
|
|
15
|
+
if (String(moduleSpecifier).startsWith('.')) return resolveRelativeProjectModule(sourcePath, moduleSpecifier, documentsByPath);
|
|
16
|
+
return resolveConfiguredProjectModule(moduleSpecifier, documentsByPath, moduleResolution);
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
export function createProjectModuleSymbolResolver(symbols, documents) {
|
|
14
20
|
const documentsByPath = new Map(documents.filter((document) => document.path).map((document) => [document.path, document]));
|
|
15
21
|
const exportedByDocumentAndName = new Map();
|
|
@@ -27,6 +33,44 @@ export function createProjectModuleSymbolResolver(symbols, documents) {
|
|
|
27
33
|
};
|
|
28
34
|
}
|
|
29
35
|
|
|
36
|
+
function resolveConfiguredProjectModule(moduleSpecifier, documentsByPath, moduleResolution) {
|
|
37
|
+
const candidates = configuredModuleCandidates(moduleSpecifier, moduleResolution);
|
|
38
|
+
let firstMissing;
|
|
39
|
+
for (const candidate of candidates) {
|
|
40
|
+
const target = moduleTargetDocument(candidate.path, documentsByPath);
|
|
41
|
+
if (target) return { path: target.path, documentId: target.id, kind: `${candidate.kind}-source` };
|
|
42
|
+
firstMissing ??= { path: candidate.path, kind: `${candidate.kind}-missing` };
|
|
43
|
+
}
|
|
44
|
+
return firstMissing;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function configuredModuleCandidates(moduleSpecifier, moduleResolution = {}) {
|
|
48
|
+
const compilerOptions = moduleResolution.compilerOptions ?? {};
|
|
49
|
+
const baseUrl = normalizeProjectPath(moduleResolution.baseUrl ?? compilerOptions.baseUrl ?? '');
|
|
50
|
+
return uniquePaths([
|
|
51
|
+
...aliasCandidates(moduleSpecifier, moduleResolution.aliases, 'alias', baseUrl),
|
|
52
|
+
...aliasCandidates(moduleSpecifier, moduleResolution.paths ?? compilerOptions.paths, 'path-alias', baseUrl),
|
|
53
|
+
...baseUrlCandidates(moduleSpecifier, baseUrl)
|
|
54
|
+
]);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function aliasCandidates(moduleSpecifier, aliases, kind, baseUrl) {
|
|
58
|
+
return Object.entries(aliases ?? {}).flatMap(([pattern, targetPatterns]) => {
|
|
59
|
+
const capture = patternCapture(moduleSpecifier, pattern);
|
|
60
|
+
if (capture === undefined) return [];
|
|
61
|
+
const targets = Array.isArray(targetPatterns) ? targetPatterns : [targetPatterns];
|
|
62
|
+
return targets.map((targetPattern) => ({
|
|
63
|
+
kind,
|
|
64
|
+
path: normalizeProjectPath(joinProjectPath(baseUrl, String(targetPattern).replace('*', capture)))
|
|
65
|
+
}));
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function baseUrlCandidates(moduleSpecifier, baseUrl) {
|
|
70
|
+
if (!baseUrl || String(moduleSpecifier).startsWith('@')) return [];
|
|
71
|
+
return [{ kind: 'base-url', path: normalizeProjectPath(joinProjectPath(baseUrl, moduleSpecifier)) }];
|
|
72
|
+
}
|
|
73
|
+
|
|
30
74
|
function moduleTargetDocument(path, documentsByPath) {
|
|
31
75
|
for (const candidate of modulePathCandidates(path)) {
|
|
32
76
|
const document = documentsByPath.get(candidate);
|
|
@@ -49,6 +93,27 @@ function symbolKey(documentId, name) {
|
|
|
49
93
|
return `${documentId}\u0000${name}`;
|
|
50
94
|
}
|
|
51
95
|
|
|
96
|
+
function patternCapture(value, pattern) {
|
|
97
|
+
if (pattern === value) return '';
|
|
98
|
+
if (!String(pattern).includes('*')) return undefined;
|
|
99
|
+
const [prefix, suffix = ''] = String(pattern).split('*');
|
|
100
|
+
if (!String(value).startsWith(prefix) || !String(value).endsWith(suffix)) return undefined;
|
|
101
|
+
return String(value).slice(prefix.length, String(value).length - suffix.length);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function uniquePaths(candidates) {
|
|
105
|
+
const seen = new Set();
|
|
106
|
+
return candidates.filter((candidate) => {
|
|
107
|
+
if (!candidate.path || seen.has(candidate.path)) return false;
|
|
108
|
+
seen.add(candidate.path);
|
|
109
|
+
return true;
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
function joinProjectPath(left, right) {
|
|
114
|
+
return left ? `${left}/${right}` : String(right);
|
|
115
|
+
}
|
|
116
|
+
|
|
52
117
|
function normalizeProjectPath(path) {
|
|
53
118
|
const parts = [];
|
|
54
119
|
for (const part of String(path).split('/')) {
|
|
@@ -14,6 +14,7 @@ function createJsTsProjectSafeMergeGraphArtifacts(input, outputFiles, mergeId) {
|
|
|
14
14
|
const projectImport = createNativeProjectImportResult({
|
|
15
15
|
id: `${mergeId}_output_project_import`,
|
|
16
16
|
projectRoot: input.projectRoot,
|
|
17
|
+
moduleResolution: input.moduleResolution ?? input.tsconfig,
|
|
17
18
|
sources,
|
|
18
19
|
metadata: {
|
|
19
20
|
projectSafeMergeId: mergeId,
|
package/package.json
CHANGED