@shapeshift-labs/frontier-lang-compiler 0.2.105 → 0.2.107
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 +11 -0
- package/dist/declarations/import-adapter-options-native.d.ts +3 -0
- package/dist/declarations/js-ts-safe-merge.d.ts +36 -0
- package/dist/declarations/native-project.d.ts +110 -0
- package/dist/internal/index-impl/createNativeProjectImportResult.js +177 -3
- package/dist/internal/index-impl/createTypeScriptCompilerNativeImporterAdapter.js +4 -0
- package/dist/internal/index-impl/replaySemanticEditProjection.js +1 -1
- package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +202 -16
- package/dist/internal/index-impl/typeScriptDeclaration.js +62 -9
- package/dist/internal/index-impl/visitTypeScriptAstNode.js +1 -0
- package/dist/js-ts-safe-merge-composed.js +6 -1
- package/dist/js-ts-safe-merge-semantic-artifact-ledger.js +197 -0
- package/dist/js-ts-safe-merge-semantic-artifacts.js +266 -0
- package/dist/js-ts-safe-merge.js +6 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -176,6 +176,17 @@ edit conflicts. Fixture failures include the fixture id and the actual
|
|
|
176
176
|
reason-code or gate values so distributed swarm evidence can point at a stable
|
|
177
177
|
case instead of an agent transcript.
|
|
178
178
|
|
|
179
|
+
Successful `safeMergeJsTsImportsAndDeclarations` and `safeMergeJsTsSource`
|
|
180
|
+
results also include `semanticArtifacts`. These artifacts convert the
|
|
181
|
+
JS/TS ledger-approved head-to-merged source edits into a semantic edit script,
|
|
182
|
+
projection, replay, and already-applied replay. This is intentionally different
|
|
183
|
+
from asking the generic three-way edit classifier to bless every JS/TS case:
|
|
184
|
+
simultaneous import specifier additions are safe only because the JS/TS ledger
|
|
185
|
+
gates proved independent additions, stable anchors, and source replay. The
|
|
186
|
+
artifacts keep `autoMergeClaim: false` and `semanticEquivalenceClaim: false`,
|
|
187
|
+
but give coordinators machine-readable proof that the projected source matches
|
|
188
|
+
the merge output and that applying the same projection again is a no-op.
|
|
189
|
+
|
|
179
190
|
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.
|
|
180
191
|
|
|
181
192
|
```js
|
|
@@ -76,6 +76,9 @@ export interface TypeScriptCompilerNativeImporterAdapterOptions {
|
|
|
76
76
|
readonly diagnostics?: readonly NativeImporterAdapterDiagnostic[];
|
|
77
77
|
readonly typescript?: unknown;
|
|
78
78
|
readonly ts?: unknown;
|
|
79
|
+
readonly program?: { readonly getTypeChecker?: () => unknown } | unknown;
|
|
80
|
+
readonly typeChecker?: unknown;
|
|
81
|
+
readonly checker?: unknown;
|
|
79
82
|
readonly sourceFile?: unknown;
|
|
80
83
|
readonly createSourceFile?: (input: NativeImporterAdapterParseInput, typescript?: unknown) => unknown;
|
|
81
84
|
readonly scriptTarget?: unknown;
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { FrontierSourceLanguage } from '@shapeshift-labs/frontier-lang-kernel';
|
|
2
|
+
import type { SemanticEditProjection, SemanticEditReplay, SemanticEditScript } from './semantic-edit-script.js';
|
|
2
3
|
import type {
|
|
3
4
|
JsTsSafeMemberMergePolicy,
|
|
4
5
|
JsTsSafeMemberMergePolicyRegion
|
|
@@ -110,6 +111,40 @@ export interface JsTsSafeMergeSummary {
|
|
|
110
111
|
readonly composedPhases?: number;
|
|
111
112
|
}
|
|
112
113
|
|
|
114
|
+
export interface JsTsSafeMergeSemanticArtifacts {
|
|
115
|
+
readonly kind: 'frontier.lang.jsTsSafeMergeSemanticArtifacts';
|
|
116
|
+
readonly version: 1;
|
|
117
|
+
readonly schema: 'frontier.lang.jsTsSafeMergeSemanticArtifacts.v1';
|
|
118
|
+
readonly id: string;
|
|
119
|
+
readonly hash: string;
|
|
120
|
+
readonly sourcePath?: string;
|
|
121
|
+
readonly language?: FrontierSourceLanguage | string;
|
|
122
|
+
readonly status: 'verified' | 'blocked' | string;
|
|
123
|
+
readonly script?: SemanticEditScript;
|
|
124
|
+
readonly projection?: SemanticEditProjection;
|
|
125
|
+
readonly replay?: SemanticEditReplay;
|
|
126
|
+
readonly alreadyAppliedReplay?: SemanticEditReplay;
|
|
127
|
+
readonly admission: {
|
|
128
|
+
readonly status: 'auto-merge-candidate' | 'blocked' | string;
|
|
129
|
+
readonly action: 'apply' | 'human-review' | string;
|
|
130
|
+
readonly reviewRequired: boolean;
|
|
131
|
+
readonly autoApplyCandidate: boolean;
|
|
132
|
+
readonly autoMergeClaim: false;
|
|
133
|
+
readonly semanticEquivalenceClaim: false;
|
|
134
|
+
readonly reasonCodes: readonly string[];
|
|
135
|
+
};
|
|
136
|
+
readonly summary: {
|
|
137
|
+
readonly operations: number;
|
|
138
|
+
readonly edits: number;
|
|
139
|
+
readonly replayStatus?: string;
|
|
140
|
+
readonly alreadyAppliedReplayStatus?: string;
|
|
141
|
+
readonly projectedSourceMatchesMerged: boolean;
|
|
142
|
+
readonly replayOutputMatchesMerged: boolean;
|
|
143
|
+
};
|
|
144
|
+
readonly evidence?: readonly unknown[];
|
|
145
|
+
readonly metadata?: Record<string, unknown>;
|
|
146
|
+
}
|
|
147
|
+
|
|
113
148
|
export interface JsTsSafeMergeResult {
|
|
114
149
|
readonly kind: 'frontier.lang.jsTsSafeMerge';
|
|
115
150
|
readonly version: 1;
|
|
@@ -124,6 +159,7 @@ export interface JsTsSafeMergeResult {
|
|
|
124
159
|
readonly gates: readonly JsTsSafeMergeGate[];
|
|
125
160
|
readonly admission: JsTsSafeMergeAdmission;
|
|
126
161
|
readonly summary: JsTsSafeMergeSummary;
|
|
162
|
+
readonly semanticArtifacts?: JsTsSafeMergeSemanticArtifacts;
|
|
127
163
|
readonly metadata?: Record<string, unknown>;
|
|
128
164
|
}
|
|
129
165
|
|
|
@@ -77,6 +77,114 @@ export interface ImportNativeProjectOptions {
|
|
|
77
77
|
readonly sources: readonly NativeProjectSourceInput[];
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
+
export type NativeProjectSymbolGraphRemainingField =
|
|
81
|
+
| 'moduleEdges[].resolvedModulePath'
|
|
82
|
+
| 'moduleEdges[].targetDocumentId'
|
|
83
|
+
| 'moduleEdges[].resolvedTargetSymbolId'
|
|
84
|
+
| 'moduleEdges[].resolutionKind'
|
|
85
|
+
| 'moduleEdges[].packageName'
|
|
86
|
+
| 'moduleEdges[].packageExportCondition'
|
|
87
|
+
| 'reExportIdentities[].originSymbolId'
|
|
88
|
+
| 'reExportIdentities[].exportedSymbolId'
|
|
89
|
+
| 'reExportIdentities[].localSymbolId'
|
|
90
|
+
| 'publicContractRegions[].apiSurfaceKind'
|
|
91
|
+
| 'publicContractRegions[].signatureHash'
|
|
92
|
+
| 'publicContractRegions[].contractHash'
|
|
93
|
+
| string;
|
|
94
|
+
|
|
95
|
+
export interface NativeProjectSymbolGraphFileHashRecord {
|
|
96
|
+
readonly id: string;
|
|
97
|
+
readonly documentId: string;
|
|
98
|
+
readonly sourcePath?: string;
|
|
99
|
+
readonly language?: FrontierSourceLanguage | string;
|
|
100
|
+
readonly sourceHash: string;
|
|
101
|
+
readonly algorithm?: string;
|
|
102
|
+
readonly value: string;
|
|
103
|
+
readonly factId?: string;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export interface NativeProjectSymbolGraphModuleEdgeRecord {
|
|
107
|
+
readonly id: string;
|
|
108
|
+
readonly sourceDocumentId: string;
|
|
109
|
+
readonly targetSymbolId: string;
|
|
110
|
+
readonly predicate: 'imports' | 'exports' | string;
|
|
111
|
+
readonly edgeKind?: 'import' | 'export' | 're-export' | string;
|
|
112
|
+
readonly sourcePath?: string;
|
|
113
|
+
readonly sourceHash?: string;
|
|
114
|
+
readonly moduleSpecifier?: string;
|
|
115
|
+
readonly importKind?: string;
|
|
116
|
+
readonly exportKind?: string;
|
|
117
|
+
readonly importedName?: string;
|
|
118
|
+
readonly exportedName?: string;
|
|
119
|
+
readonly localName?: string;
|
|
120
|
+
readonly namespace?: string;
|
|
121
|
+
readonly isTypeOnly?: boolean;
|
|
122
|
+
readonly isReExport?: boolean;
|
|
123
|
+
readonly publicContract?: boolean;
|
|
124
|
+
readonly evidenceIds?: readonly string[];
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface NativeProjectSymbolGraphReExportIdentityRecord {
|
|
128
|
+
readonly kind?: 'frontier.lang.reExportIdentity' | string;
|
|
129
|
+
readonly version?: 1;
|
|
130
|
+
readonly id: string;
|
|
131
|
+
readonly sourceDocumentId?: string;
|
|
132
|
+
readonly sourcePath?: string;
|
|
133
|
+
readonly sourceHash?: string;
|
|
134
|
+
readonly moduleSpecifier?: string;
|
|
135
|
+
readonly exportedName?: string;
|
|
136
|
+
readonly importedName?: string;
|
|
137
|
+
readonly localName?: string;
|
|
138
|
+
readonly namespace?: string;
|
|
139
|
+
readonly isTypeOnly?: boolean;
|
|
140
|
+
readonly symbolId?: string;
|
|
141
|
+
readonly relationId?: string;
|
|
142
|
+
readonly ownershipRegionId?: string;
|
|
143
|
+
readonly ownershipRegionKey?: string;
|
|
144
|
+
readonly publicContract?: boolean;
|
|
145
|
+
readonly factId?: string;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export interface NativeProjectSymbolGraphPublicContractRegionRecord {
|
|
149
|
+
readonly id: string;
|
|
150
|
+
readonly key?: string;
|
|
151
|
+
readonly regionKind?: string;
|
|
152
|
+
readonly granularity?: string;
|
|
153
|
+
readonly language?: FrontierSourceLanguage | string;
|
|
154
|
+
readonly documentId?: string;
|
|
155
|
+
readonly sourcePath?: string;
|
|
156
|
+
readonly sourceHash?: string;
|
|
157
|
+
readonly symbolId?: string;
|
|
158
|
+
readonly symbolName?: string;
|
|
159
|
+
readonly symbolKind?: string;
|
|
160
|
+
readonly nativeAstNodeId?: string;
|
|
161
|
+
readonly sourceSpan?: SourceSpan;
|
|
162
|
+
readonly precision?: string;
|
|
163
|
+
readonly publicContract?: boolean;
|
|
164
|
+
readonly exportedName?: string;
|
|
165
|
+
readonly moduleSpecifier?: string;
|
|
166
|
+
readonly edgeKind?: string;
|
|
167
|
+
readonly factId?: string;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
export interface NativeProjectSymbolGraphSummary {
|
|
171
|
+
readonly kind: 'frontier.lang.projectSymbolGraph';
|
|
172
|
+
readonly version: 1;
|
|
173
|
+
readonly projectRoot?: string;
|
|
174
|
+
readonly sourceCount: number;
|
|
175
|
+
readonly documentCount: number;
|
|
176
|
+
readonly symbolCount: number;
|
|
177
|
+
readonly occurrenceCount: number;
|
|
178
|
+
readonly relationCount: number;
|
|
179
|
+
readonly factCount: number;
|
|
180
|
+
readonly fileHashes: readonly NativeProjectSymbolGraphFileHashRecord[];
|
|
181
|
+
readonly importEdges: readonly NativeProjectSymbolGraphModuleEdgeRecord[];
|
|
182
|
+
readonly exportEdges: readonly NativeProjectSymbolGraphModuleEdgeRecord[];
|
|
183
|
+
readonly reExportIdentities: readonly NativeProjectSymbolGraphReExportIdentityRecord[];
|
|
184
|
+
readonly publicContractRegions: readonly NativeProjectSymbolGraphPublicContractRegionRecord[];
|
|
185
|
+
readonly remainingFields: readonly NativeProjectSymbolGraphRemainingField[];
|
|
186
|
+
}
|
|
187
|
+
|
|
80
188
|
export interface NativeProjectImportResultMetadata extends Record<string, unknown> {
|
|
81
189
|
readonly importResultContract?: NativeImportResultContract;
|
|
82
190
|
readonly projectAdmission?: NativeProjectImportAdmission;
|
|
@@ -84,6 +192,7 @@ export interface NativeProjectImportResultMetadata extends Record<string, unknow
|
|
|
84
192
|
readonly nativeImportLossSummary?: NativeImportLossSummary;
|
|
85
193
|
readonly semanticMergeReadiness?: SemanticMergeReadiness;
|
|
86
194
|
readonly readinessReasons?: readonly string[];
|
|
195
|
+
readonly projectSymbolGraph?: NativeProjectSymbolGraphSummary;
|
|
87
196
|
}
|
|
88
197
|
|
|
89
198
|
export interface NativeProjectImportResult {
|
|
@@ -102,6 +211,7 @@ export interface NativeProjectImportResult {
|
|
|
102
211
|
readonly losses: readonly NativeAstLossRecord[];
|
|
103
212
|
readonly evidence: readonly EvidenceRecord[];
|
|
104
213
|
readonly mergeCandidates: readonly SemanticMergeCandidateRecord[];
|
|
214
|
+
readonly projectSymbolGraph?: NativeProjectSymbolGraphSummary;
|
|
105
215
|
readonly metadata?: NativeProjectImportResultMetadata;
|
|
106
216
|
}
|
|
107
217
|
|
|
@@ -4,7 +4,15 @@ export function createNativeProjectImportResult(input, imports) {
|
|
|
4
4
|
const idPart = idFragment(input.id ?? input.projectRoot ?? 'native_project');
|
|
5
5
|
const nodes = {};
|
|
6
6
|
const rootIds = [];
|
|
7
|
-
const
|
|
7
|
+
const mergedSemanticIndex = mergeSemanticIndexes(imports, input, idPart);
|
|
8
|
+
const projectSymbolGraph = createProjectSymbolGraphSummary(mergedSemanticIndex, imports, input);
|
|
9
|
+
const semanticIndex = mergedSemanticIndex ? {
|
|
10
|
+
...mergedSemanticIndex,
|
|
11
|
+
metadata: {
|
|
12
|
+
...mergedSemanticIndex.metadata,
|
|
13
|
+
projectSymbolGraph
|
|
14
|
+
}
|
|
15
|
+
} : mergedSemanticIndex;
|
|
8
16
|
const nativeSources = [];
|
|
9
17
|
const sourceMaps = [];
|
|
10
18
|
const losses = [];
|
|
@@ -43,6 +51,7 @@ export function createNativeProjectImportResult(input, imports) {
|
|
|
43
51
|
sourceCount: imports.length,
|
|
44
52
|
nativeImportLossSummary,
|
|
45
53
|
sourcePreservationSummary,
|
|
54
|
+
projectSymbolGraph,
|
|
46
55
|
...input.documentMetadata
|
|
47
56
|
}
|
|
48
57
|
});
|
|
@@ -60,6 +69,7 @@ export function createNativeProjectImportResult(input, imports) {
|
|
|
60
69
|
sourceCount: imports.length,
|
|
61
70
|
nativeImportLossSummary,
|
|
62
71
|
sourcePreservationSummary,
|
|
72
|
+
projectSymbolGraph,
|
|
63
73
|
...input.universalAstMetadata
|
|
64
74
|
}
|
|
65
75
|
});
|
|
@@ -75,7 +85,8 @@ export function createNativeProjectImportResult(input, imports) {
|
|
|
75
85
|
sourceMapIds: sourceMaps.map((sourceMap) => sourceMap.id),
|
|
76
86
|
sourceCount: imports.length,
|
|
77
87
|
nativeImportLossSummary,
|
|
78
|
-
sourcePreservationSummary
|
|
88
|
+
sourcePreservationSummary,
|
|
89
|
+
projectSymbolGraph
|
|
79
90
|
}
|
|
80
91
|
});
|
|
81
92
|
const projectResult = {
|
|
@@ -94,11 +105,13 @@ export function createNativeProjectImportResult(input, imports) {
|
|
|
94
105
|
losses: uniqueLosses,
|
|
95
106
|
evidence: uniqueEvidence,
|
|
96
107
|
mergeCandidates,
|
|
108
|
+
projectSymbolGraph,
|
|
97
109
|
metadata: {
|
|
98
110
|
sourceCount: imports.length,
|
|
99
111
|
sourcePaths: imports.map((result) => result.sourcePath).filter(Boolean),
|
|
100
112
|
nativeImportLossSummary,
|
|
101
113
|
sourcePreservationSummary,
|
|
114
|
+
projectSymbolGraph,
|
|
102
115
|
...input.metadata
|
|
103
116
|
}
|
|
104
117
|
};
|
|
@@ -120,7 +133,168 @@ export function createNativeProjectImportResult(input, imports) {
|
|
|
120
133
|
readinessReasons: importResultContract.readiness.reasons,
|
|
121
134
|
regionSummary: importResultContract.regions,
|
|
122
135
|
sourceMapSummary: importResultContract.sourceMaps,
|
|
123
|
-
adapterCoverageSummary: importResultContract.adapterCoverage
|
|
136
|
+
adapterCoverageSummary: importResultContract.adapterCoverage,
|
|
137
|
+
projectSymbolGraph
|
|
124
138
|
}
|
|
125
139
|
};
|
|
126
140
|
}
|
|
141
|
+
|
|
142
|
+
const PROJECT_SYMBOL_GRAPH_REMAINING_FIELDS = Object.freeze([
|
|
143
|
+
'moduleEdges[].resolvedModulePath',
|
|
144
|
+
'moduleEdges[].targetDocumentId',
|
|
145
|
+
'moduleEdges[].resolvedTargetSymbolId',
|
|
146
|
+
'moduleEdges[].resolutionKind',
|
|
147
|
+
'moduleEdges[].packageName',
|
|
148
|
+
'moduleEdges[].packageExportCondition',
|
|
149
|
+
'reExportIdentities[].originSymbolId',
|
|
150
|
+
'reExportIdentities[].exportedSymbolId',
|
|
151
|
+
'reExportIdentities[].localSymbolId',
|
|
152
|
+
'publicContractRegions[].apiSurfaceKind',
|
|
153
|
+
'publicContractRegions[].signatureHash',
|
|
154
|
+
'publicContractRegions[].contractHash'
|
|
155
|
+
]);
|
|
156
|
+
|
|
157
|
+
function createProjectSymbolGraphSummary(semanticIndex, imports, input) {
|
|
158
|
+
const documents = semanticIndex?.documents ?? [];
|
|
159
|
+
const symbolsById = new Map((semanticIndex?.symbols ?? []).map((symbol) => [symbol.id, symbol]));
|
|
160
|
+
const documentsById = new Map(documents.map((document) => [document.id, document]));
|
|
161
|
+
const facts = semanticIndex?.facts ?? [];
|
|
162
|
+
const moduleEdgeFacts = facts.filter((fact) => fact.predicate === 'moduleEdge');
|
|
163
|
+
const moduleEdgeByRelation = new Map(moduleEdgeFacts.map((fact) => [fact.subjectId, fact]));
|
|
164
|
+
const relations = semanticIndex?.relations ?? [];
|
|
165
|
+
const importEdges = relations
|
|
166
|
+
.filter((relation) => relation.predicate === 'imports')
|
|
167
|
+
.map((relation) => moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById));
|
|
168
|
+
const exportEdges = relations
|
|
169
|
+
.filter((relation) => relation.predicate === 'exports')
|
|
170
|
+
.map((relation) => moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById));
|
|
171
|
+
const reExportIdentities = uniqueRecords([
|
|
172
|
+
...facts
|
|
173
|
+
.filter((fact) => fact.predicate === 'reExportIdentity' && fact.value)
|
|
174
|
+
.map((fact) => ({ ...objectValue(fact.value), factId: fact.id })),
|
|
175
|
+
...exportEdges
|
|
176
|
+
.filter((edge) => edge.isReExport)
|
|
177
|
+
.map((edge) => compactRecord({
|
|
178
|
+
id: `reexport_${idFragment(edge.id)}`,
|
|
179
|
+
sourceDocumentId: edge.sourceDocumentId,
|
|
180
|
+
sourcePath: edge.sourcePath,
|
|
181
|
+
sourceHash: edge.sourceHash,
|
|
182
|
+
moduleSpecifier: edge.moduleSpecifier,
|
|
183
|
+
symbolId: edge.targetSymbolId,
|
|
184
|
+
relationId: edge.id,
|
|
185
|
+
publicContract: edge.publicContract
|
|
186
|
+
}))
|
|
187
|
+
]);
|
|
188
|
+
const publicContractRegions = uniqueRecords(facts
|
|
189
|
+
.filter((fact) => fact.predicate === 'publicContractRegion' && fact.value)
|
|
190
|
+
.map((fact) => ({ ...objectValue(fact.value), factId: fact.id, symbolId: fact.subjectId })));
|
|
191
|
+
const fileHashes = uniqueRecords([
|
|
192
|
+
...documents.map((document) => fileHashRecord(document)),
|
|
193
|
+
...facts
|
|
194
|
+
.filter((fact) => fact.predicate === 'fileHash' && fact.value)
|
|
195
|
+
.map((fact) => ({ ...objectValue(fact.value), id: `file_hash_${idFragment(fact.subjectId)}`, factId: fact.id, documentId: fact.subjectId }))
|
|
196
|
+
].filter(Boolean));
|
|
197
|
+
return {
|
|
198
|
+
kind: 'frontier.lang.projectSymbolGraph',
|
|
199
|
+
version: 1,
|
|
200
|
+
projectRoot: input.projectRoot,
|
|
201
|
+
sourceCount: imports.length,
|
|
202
|
+
documentCount: documents.length,
|
|
203
|
+
symbolCount: semanticIndex?.symbols?.length ?? 0,
|
|
204
|
+
occurrenceCount: semanticIndex?.occurrences?.length ?? 0,
|
|
205
|
+
relationCount: relations.length,
|
|
206
|
+
factCount: facts.length,
|
|
207
|
+
fileHashes,
|
|
208
|
+
importEdges,
|
|
209
|
+
exportEdges,
|
|
210
|
+
reExportIdentities,
|
|
211
|
+
publicContractRegions,
|
|
212
|
+
remainingFields: PROJECT_SYMBOL_GRAPH_REMAINING_FIELDS
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
function moduleEdgeRecord(relation, moduleEdgeByRelation, symbolsById, documentsById) {
|
|
217
|
+
const fact = moduleEdgeByRelation.get(relation.id);
|
|
218
|
+
const value = objectValue(fact?.value);
|
|
219
|
+
const metadata = objectValue(relation.metadata);
|
|
220
|
+
const moduleEdge = objectValue(metadata.moduleEdge);
|
|
221
|
+
const symbol = symbolsById.get(relation.targetId);
|
|
222
|
+
const symbolMetadata = objectValue(symbol?.metadata);
|
|
223
|
+
const document = documentsById.get(relation.sourceId);
|
|
224
|
+
const moduleSpecifier = firstString(
|
|
225
|
+
moduleEdge.moduleSpecifier,
|
|
226
|
+
value.moduleSpecifier,
|
|
227
|
+
metadata.moduleSpecifier,
|
|
228
|
+
symbolMetadata.moduleSpecifier,
|
|
229
|
+
symbol?.kind === 'module' ? symbol.name : undefined
|
|
230
|
+
);
|
|
231
|
+
return compactRecord({
|
|
232
|
+
id: relation.id,
|
|
233
|
+
sourceDocumentId: relation.sourceId,
|
|
234
|
+
targetSymbolId: relation.targetId,
|
|
235
|
+
predicate: relation.predicate,
|
|
236
|
+
edgeKind: firstString(moduleEdge.edgeKind, value.edgeKind, relation.predicate === 'imports' ? 'import' : moduleSpecifier ? 're-export' : 'export'),
|
|
237
|
+
sourcePath: document?.path,
|
|
238
|
+
sourceHash: document?.sourceHash,
|
|
239
|
+
moduleSpecifier,
|
|
240
|
+
importKind: firstString(moduleEdge.importKind, value.importKind),
|
|
241
|
+
exportKind: firstString(moduleEdge.exportKind, value.exportKind),
|
|
242
|
+
importedName: firstString(moduleEdge.importedName, value.importedName),
|
|
243
|
+
exportedName: firstString(moduleEdge.exportedName, value.exportedName),
|
|
244
|
+
localName: firstString(moduleEdge.localName, value.localName),
|
|
245
|
+
namespace: firstString(moduleEdge.namespace, value.namespace),
|
|
246
|
+
isTypeOnly: firstBoolean(moduleEdge.isTypeOnly, value.isTypeOnly),
|
|
247
|
+
isReExport: firstBoolean(moduleEdge.isReExport, value.isReExport) ?? (relation.predicate === 'exports' && Boolean(moduleSpecifier)),
|
|
248
|
+
publicContract: firstBoolean(moduleEdge.publicContract, value.publicContract, metadata.publicContract),
|
|
249
|
+
evidenceIds: uniqueStrings([...(relation.evidenceIds ?? []), ...(fact?.evidenceIds ?? [])])
|
|
250
|
+
});
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
function fileHashRecord(document) {
|
|
254
|
+
if (!document?.sourceHash) return undefined;
|
|
255
|
+
const sourceHash = String(document.sourceHash);
|
|
256
|
+
const separator = sourceHash.indexOf(':');
|
|
257
|
+
return compactRecord({
|
|
258
|
+
id: `file_hash_${idFragment(document.id)}`,
|
|
259
|
+
documentId: document.id,
|
|
260
|
+
sourcePath: document.path,
|
|
261
|
+
language: document.language,
|
|
262
|
+
sourceHash,
|
|
263
|
+
algorithm: separator > 0 ? sourceHash.slice(0, separator) : undefined,
|
|
264
|
+
value: separator > 0 ? sourceHash.slice(separator + 1) : sourceHash
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function objectValue(value) {
|
|
269
|
+
return value && typeof value === 'object' && !Array.isArray(value) ? value : {};
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
function compactRecord(record) {
|
|
273
|
+
return Object.fromEntries(Object.entries(record).filter(([, value]) => value !== undefined));
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function uniqueRecords(records) {
|
|
277
|
+
const seen = new Set();
|
|
278
|
+
const result = [];
|
|
279
|
+
for (const record of records) {
|
|
280
|
+
const key = record.id ?? record.factId ?? JSON.stringify(record);
|
|
281
|
+
if (seen.has(key)) continue;
|
|
282
|
+
seen.add(key);
|
|
283
|
+
result.push(record);
|
|
284
|
+
}
|
|
285
|
+
return result;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
function firstString(...values) {
|
|
289
|
+
for (const value of values) {
|
|
290
|
+
if (value !== undefined && value !== null && String(value)) return String(value);
|
|
291
|
+
}
|
|
292
|
+
return undefined;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
function firstBoolean(...values) {
|
|
296
|
+
for (const value of values) {
|
|
297
|
+
if (typeof value === 'boolean') return value;
|
|
298
|
+
}
|
|
299
|
+
return undefined;
|
|
300
|
+
}
|
|
@@ -25,6 +25,8 @@ export function createTypeScriptCompilerNativeImporterAdapter(options = {}) {
|
|
|
25
25
|
diagnostics: options.diagnostics,
|
|
26
26
|
parse(input) {
|
|
27
27
|
const ts = options.typescript ?? options.ts ?? input.options?.typescript ?? input.options?.ts;
|
|
28
|
+
const program = options.program ?? input.options?.program;
|
|
29
|
+
const typeChecker = options.typeChecker ?? options.checker ?? input.options?.typeChecker ?? input.options?.checker ?? program?.getTypeChecker?.();
|
|
28
30
|
const sourceFile = input.options?.sourceFile ?? input.options?.ast ?? options.sourceFile ?? createTypeScriptSourceFile(ts, input, options);
|
|
29
31
|
if (!sourceFile) {
|
|
30
32
|
return missingInjectedParserResult(input, {
|
|
@@ -37,6 +39,8 @@ export function createTypeScriptCompilerNativeImporterAdapter(options = {}) {
|
|
|
37
39
|
parser: options.parser ?? 'typescript-compiler-api',
|
|
38
40
|
astFormat: 'typescript-compiler-api',
|
|
39
41
|
ts,
|
|
42
|
+
program,
|
|
43
|
+
typeChecker,
|
|
40
44
|
maxNodes: options.maxNodes,
|
|
41
45
|
includeTokens: options.includeTokens
|
|
42
46
|
});
|
|
@@ -207,7 +207,7 @@ function currentSymbolRangeLabel(edit) {
|
|
|
207
207
|
}
|
|
208
208
|
|
|
209
209
|
function replayStatus(reasonCodes, edits, projection) {
|
|
210
|
-
if (reasonCodes.
|
|
210
|
+
if (reasonCodes.length) return 'blocked';
|
|
211
211
|
if (!edits.length && !(projection.edits ?? []).length) return 'evidence-only';
|
|
212
212
|
if (edits.some((edit) => edit.status === 'blocked')) return 'blocked';
|
|
213
213
|
if (edits.some((edit) => edit.status === 'conflict')) return 'conflict';
|