@shapeshift-labs/frontier-lang-compiler 0.2.98 → 0.2.100
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/declarations/semantic-edit-bundle.d.ts +90 -0
- package/dist/declarations/semantic-edit-script.d.ts +34 -37
- package/dist/declarations/semantic-lineage.d.ts +63 -34
- package/dist/declarations/semantic-patch-bundle-index.d.ts +3 -0
- package/dist/declarations/semantic-patch-bundle.d.ts +23 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/internal/index-impl/declarationRecord.js +2 -2
- package/dist/internal/index-impl/inferSemanticLineageEvents.js +8 -0
- package/dist/internal/index-impl/projectSemanticEditScriptToSource.js +56 -64
- package/dist/internal/index-impl/replaySemanticEditProjection.js +54 -22
- package/dist/internal/index-impl/semanticEditBundleAdmission.js +220 -0
- package/dist/internal/index-impl/semanticEditBundleIndex.js +16 -10
- package/dist/internal/index-impl/semanticEditSourceRanges.js +204 -0
- package/dist/internal/index-impl/semanticHistoryLineageResolution.js +35 -1
- package/dist/internal/index-impl/semanticIndexFromNativeDeclarations.js +2 -2
- package/dist/internal/index-impl/semanticLineageInferenceMatching.js +150 -13
- package/dist/internal/index-impl/semanticLineageResolutionRecords.js +28 -1
- package/dist/internal/index-impl/semanticPatchBundleAdmission.js +130 -11
- package/dist/internal/index-impl/semanticPatchBundleLineageLinks.js +199 -0
- package/dist/internal/index-impl/semanticPatchBundleOverlaps.js +6 -2
- package/dist/internal/index-impl/semanticPatchBundleRecords.js +65 -126
- package/dist/internal/index-impl/semanticPatchBundleSourceRecords.js +127 -0
- package/dist/internal/index-impl/sourceTextForSpan.js +4 -9
- package/dist/lightweight-dependency-relations.js +113 -7
- package/dist/native-import-utils.js +15 -1
- package/dist/native-region-scanner-js-helpers.js +61 -17
- package/dist/native-region-scanner-js.js +12 -4
- package/dist/semantic-import-regions.js +3 -3
- package/package.json +1 -1
|
@@ -1,6 +1,9 @@
|
|
|
1
1
|
import{idFragment,normalizeSemanticMergeReadiness,uniqueStrings}from'../../native-import-utils.js';
|
|
2
|
+
import{createSemanticEditBundleAdmission}from'./semanticEditBundleAdmission.js';
|
|
2
3
|
import{createSemanticPatchBundleAdmission}from'./semanticPatchBundleAdmission.js';
|
|
3
4
|
import{semanticEditRecordIndex,semanticEditSummary}from'./semanticEditBundleIndex.js';
|
|
5
|
+
import{lineageLinkInputs,linkAdmissionLineage,normalizeLineageResolutionLinks,semanticLineageLinkIndex}from'./semanticPatchBundleLineageLinks.js';
|
|
6
|
+
import{normalizeRegions,normalizeSourceMapLinks,normalizeSources,sourceRef}from'./semanticPatchBundleSourceRecords.js';
|
|
4
7
|
import{normalizeSemanticTransformIdentityRecords,semanticTransformInputs,semanticTransformRecordIndex,semanticTransformSummary}from'./semanticTransformIdentityRecords.js';
|
|
5
8
|
|
|
6
9
|
export const SemanticPatchBundleAdmissionStatuses=Object.freeze(['proposed','queued','admitted','needs-review','blocked','rejected']);
|
|
@@ -12,7 +15,15 @@ export function createSemanticPatchBundleRecord(input={},options={}){
|
|
|
12
15
|
const semanticEditScripts=array(options.semanticEditScripts??source.semanticEditScripts??source.semanticEditScript);
|
|
13
16
|
const semanticEditProjections=array(options.semanticEditProjections??source.semanticEditProjections??source.semanticEditProjection);
|
|
14
17
|
const semanticEditReplays=array(options.semanticEditReplays??source.semanticEditReplays??source.semanticEditReplay);
|
|
15
|
-
const
|
|
18
|
+
const evidenceRecords=[...array(options.evidence??source.evidence),...array(patch?.evidence),...array(mergeCandidate?.evidence),...semanticEditScripts.flatMap((script)=>array(script.evidence))];
|
|
19
|
+
const editAdmission=createSemanticEditBundleAdmission({
|
|
20
|
+
semanticEditScripts,semanticEditProjections,semanticEditReplays,
|
|
21
|
+
evidence:evidenceRecords,
|
|
22
|
+
...(source.metadata?.semanticEditAdmission??{}),
|
|
23
|
+
...(source.semanticEditAdmission??{}),
|
|
24
|
+
...(options.semanticEditAdmission??{})
|
|
25
|
+
});
|
|
26
|
+
const editIndex=semanticEditRecordIndex(semanticEditScripts,semanticEditProjections,semanticEditReplays,source);
|
|
16
27
|
const transformContext={sourceLanguage:options.sourceLanguage??source.sourceLanguage??source.language,targetLanguage:options.targetLanguage??source.targetLanguage};
|
|
17
28
|
const semanticTransformIdentities=normalizeSemanticTransformIdentityRecords(semanticTransformInputs(source,options),transformContext);
|
|
18
29
|
const semanticTransformIndex=semanticTransformRecordIndex(semanticTransformIdentities,source);
|
|
@@ -28,17 +39,18 @@ export function createSemanticPatchBundleRecord(input={},options={}){
|
|
|
28
39
|
sourceRef(source.before,'before',source.beforeHash),
|
|
29
40
|
sourceRef(source.after,'after',source.afterHash)
|
|
30
41
|
],source);
|
|
31
|
-
const evidenceRecords=[...array(options.evidence??source.evidence),...array(patch?.evidence),...array(mergeCandidate?.evidence),...semanticEditScripts.flatMap((script)=>array(script.evidence))];
|
|
32
42
|
const patchId=firstString(options.patchId,source.patchId,patch?.id,mergeCandidate?.patchId);
|
|
33
43
|
const mergeCandidateId=firstString(options.mergeCandidateId,source.mergeCandidateId,mergeCandidate?.id);
|
|
34
44
|
const baseHash=firstString(options.baseHash,source.baseHash,source.beforeHash,patch?.baseHash,mergeCandidate?.baseHash,...sources.map((item)=>item.baseHash));
|
|
35
45
|
const targetHash=firstString(options.targetHash,source.targetHash,source.afterHash,patch?.targetHash,mergeCandidate?.targetHash,...sources.map((item)=>item.targetHash));
|
|
36
46
|
const readiness=normalizeSemanticMergeReadiness(firstString(options.readiness,source.readiness,source.admission?.readiness,mergeCandidate?.readiness))
|
|
37
47
|
?? firstString(options.readiness,source.readiness,source.admission?.readiness,mergeCandidate?.readiness,'needs-review');
|
|
38
|
-
const
|
|
39
|
-
const
|
|
48
|
+
const lineageLinks=normalizeLineageResolutionLinks(lineageLinkInputs(source,options,changedRegions,targetPortability));
|
|
49
|
+
const lineageIndex=semanticLineageLinkIndex(lineageLinks,changedRegions,targetPortability);
|
|
50
|
+
const evidenceIds=uniqueStrings([...strings(options.evidenceIds),...strings(source.evidenceIds),...evidenceRecords.map((record)=>record?.id),...strings(mergeCandidate?.evidenceIds),...lineageIndex.evidenceIds]);
|
|
51
|
+
const proofIds=uniqueStrings([...strings(options.proofIds),...strings(source.proofIds),...evidenceRecords.filter((record)=>record?.kind==='proof').map((record)=>record.id),...strings(mergeCandidate?.proofIds),...lineageIndex.proofIds]);
|
|
40
52
|
const historyIds=uniqueStrings([...strings(options.historyIds),...strings(options.historyId),...strings(source.historyIds),...strings(source.historyId)]);
|
|
41
|
-
const semanticOperationIds=uniqueStrings([...strings(options.semanticOperationIds),...strings(options.semanticOperationId),...strings(source.semanticOperationIds),...strings(source.semanticOperationId),...strings(patch?.semanticOperationIds),...strings(mergeCandidate?.semanticOperationIds),...
|
|
53
|
+
const semanticOperationIds=uniqueStrings([...strings(options.semanticOperationIds),...strings(options.semanticOperationId),...strings(source.semanticOperationIds),...strings(source.semanticOperationId),...strings(patch?.semanticOperationIds),...strings(mergeCandidate?.semanticOperationIds),...editIndex.semanticEditOperationIds]);
|
|
42
54
|
const conflictKeys=uniqueStrings([
|
|
43
55
|
...strings(options.conflictKeys),
|
|
44
56
|
...strings(source.conflictKeys),
|
|
@@ -46,12 +58,12 @@ export function createSemanticPatchBundleRecord(input={},options={}){
|
|
|
46
58
|
...changedRegions.flatMap((region)=>[region.conflictKey,...array(region.admission?.conflictKeys)]),
|
|
47
59
|
...(source.metadata?.semanticMergeConflictSummary?.conflictKeys??[])
|
|
48
60
|
]);
|
|
49
|
-
const admission=createSemanticPatchBundleAdmission(options.admission??source.admission,{readiness,conflictKeys,source,mergeCandidate,semanticTransformIndex,semanticTransformIdentities});
|
|
61
|
+
const admission=linkAdmissionLineage(createSemanticPatchBundleAdmission(options.admission??source.admission,{readiness,conflictKeys,source,mergeCandidate,evidenceRecords,semanticTransformIndex,semanticTransformIdentities,semanticEditAdmission:editAdmission}),lineageLinks);
|
|
50
62
|
const id=options.id??(source.kind==='frontier.lang.semanticPatchBundleRecord'?source.id:undefined)
|
|
51
63
|
??`semantic_patch_bundle_${idFragment(firstString(source.id,patchId,mergeCandidateId,source.sourcePath,source.language,'record'))}`;
|
|
52
64
|
const language=options.language??source.language??mergeCandidate?.language??sources.find((item)=>item.language)?.language;
|
|
53
65
|
const sourcePath=options.sourcePath??source.sourcePath??mergeCandidate?.sourcePath??sources.find((item)=>item.sourcePath)?.sourcePath;
|
|
54
|
-
const index=recordIndex({baseHash,targetHash,sources,changedRegions,sourceMapLinks,evidenceIds,proofIds,historyIds,semanticOperationIds,patchId,mergeCandidateId,admission,semanticEditIndex,semanticTransformIndex,targetPortability});
|
|
66
|
+
const index=recordIndex({baseHash,targetHash,sources,changedRegions,sourceMapLinks,evidenceIds,proofIds,historyIds,semanticOperationIds,patchId,mergeCandidateId,admission,semanticEditAdmission:editAdmission,semanticEditIndex:editIndex,semanticTransformIndex,targetPortability,lineageLinks});
|
|
55
67
|
return{
|
|
56
68
|
kind:'frontier.lang.semanticPatchBundleRecord',
|
|
57
69
|
version:1,
|
|
@@ -71,22 +83,24 @@ export function createSemanticPatchBundleRecord(input={},options={}){
|
|
|
71
83
|
proofIds,
|
|
72
84
|
historyIds,
|
|
73
85
|
semanticOperationIds,
|
|
74
|
-
semanticEditScriptIds:
|
|
75
|
-
semanticEditProjectionIds:
|
|
76
|
-
semanticEditReplayIds:
|
|
86
|
+
semanticEditScriptIds:editIndex.semanticEditScriptIds,
|
|
87
|
+
semanticEditProjectionIds:editIndex.semanticEditProjectionIds,
|
|
88
|
+
semanticEditReplayIds:editIndex.semanticEditReplayIds,
|
|
77
89
|
semanticTransformIdentityIds:semanticTransformIndex.semanticTransformIds,
|
|
78
90
|
admission,
|
|
79
91
|
index,
|
|
80
|
-
summary:{changedRegions:changedRegions.length,sourceMapLinks:sourceMapLinks.length,evidenceIds:evidenceIds.length,proofIds:proofIds.length,historyIds:historyIds.length,semanticOperations:semanticOperationIds.length,semanticEditScripts:semanticEditScripts.length,semanticEditProjections:semanticEditProjections.length,semanticEditReplays:semanticEditReplays.length,semanticEditProjectionEdits:
|
|
92
|
+
summary:{changedRegions:changedRegions.length,sourceMapLinks:sourceMapLinks.length,evidenceIds:evidenceIds.length,proofIds:proofIds.length,historyIds:historyIds.length,semanticOperations:semanticOperationIds.length,semanticEditScripts:semanticEditScripts.length,semanticEditProjections:semanticEditProjections.length,semanticEditReplays:semanticEditReplays.length,semanticEditProjectionEdits:editIndex.semanticEditProjectionEditCount,semanticEditReplayEdits:editIndex.semanticEditReplayEditCount,semanticEditBundleStatus:editAdmission.status,semanticTransformIdentities:semanticTransformIdentities.length,reviewRequired:admission.reviewRequired,autoMergeClaim:admission.autoMergeClaim},
|
|
81
93
|
metadata:compactRecord({
|
|
82
94
|
sourceChangeSetId:source.kind==='frontier.lang.nativeSourceChangeSet'?source.id:undefined,
|
|
83
95
|
patchRisk:patch?.risk,
|
|
84
96
|
nativeChangeSummary:source.summary,
|
|
85
97
|
changedRegionProjectionSummary:source.metadata?.changedRegionProjectionSummary,
|
|
86
98
|
semanticMergeConflictSummary:source.metadata?.semanticMergeConflictSummary,
|
|
87
|
-
semanticEditSummary:semanticEditSummary(
|
|
99
|
+
semanticEditSummary:semanticEditSummary(editIndex),
|
|
100
|
+
semanticEditAdmission:editAdmission,
|
|
88
101
|
semanticTransformSummary:semanticTransformSummary(semanticTransformIndex),
|
|
89
102
|
targetPortability,
|
|
103
|
+
semanticLineageResolutionLinks:lineageLinks,
|
|
90
104
|
...options.metadata
|
|
91
105
|
})
|
|
92
106
|
};
|
|
@@ -96,131 +110,47 @@ export function querySemanticPatchBundleRecords(records,query={}){
|
|
|
96
110
|
return array(records).filter(Boolean).filter((record)=>matchesRecord(record,query)).sort((left,right)=>String(left.id).localeCompare(String(right.id)));
|
|
97
111
|
}
|
|
98
112
|
|
|
99
|
-
function normalizeSources(entries,context){
|
|
100
|
-
return entries.filter(Boolean).map((entry,index)=>compactRecord({
|
|
101
|
-
id:entry.id??entry.sourceId,
|
|
102
|
-
side:entry.side,
|
|
103
|
-
importId:entry.importId??entry.importResultId,
|
|
104
|
-
language:entry.language??context.language,
|
|
105
|
-
sourcePath:entry.sourcePath??context.sourcePath,
|
|
106
|
-
sourceHash:entry.sourceHash??entry.hash,
|
|
107
|
-
baseHash:entry.baseHash??entry.beforeHash??context.baseHash??context.beforeHash,
|
|
108
|
-
targetHash:entry.targetHash??entry.afterHash??context.targetHash??context.afterHash,
|
|
109
|
-
nativeSourceId:entry.nativeSourceId,
|
|
110
|
-
nativeAstId:entry.nativeAstId,
|
|
111
|
-
semanticIndexId:entry.semanticIndexId,
|
|
112
|
-
universalAstId:entry.universalAstId,
|
|
113
|
-
sourceMapIds:uniqueStrings(entry.sourceMapIds),
|
|
114
|
-
ordinal:index
|
|
115
|
-
})).filter((entry)=>entry.importId||entry.sourcePath||entry.sourceHash||entry.baseHash||entry.targetHash);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
function sourceRef(importResult,side,sourceHash){
|
|
119
|
-
if(!importResult)return undefined;
|
|
120
|
-
return compactRecord({
|
|
121
|
-
id:`${side}_${importResult.id??idFragment(importResult.sourcePath??'source')}`,side,importId:importResult.id,
|
|
122
|
-
language:importResult.language,
|
|
123
|
-
sourcePath:importResult.sourcePath,
|
|
124
|
-
sourceHash:sourceHash??importResult.nativeSource?.sourceHash??importResult.nativeAst?.sourceHash??importResult.sourceHash,
|
|
125
|
-
nativeSourceId:importResult.nativeSource?.id,
|
|
126
|
-
nativeAstId:importResult.nativeAst?.id,
|
|
127
|
-
semanticIndexId:importResult.semanticIndex?.id,
|
|
128
|
-
universalAstId:importResult.universalAst?.id,
|
|
129
|
-
sourceMapIds:uniqueStrings((importResult.sourceMaps??[]).map((map)=>map.id))
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
function normalizeRegions(regions,context){
|
|
134
|
-
return regions.filter(Boolean).map((region,index)=>{
|
|
135
|
-
const projection=region.metadata?.changedRegionProjection??region.projection;
|
|
136
|
-
const projected=projection?.region??{};
|
|
137
|
-
const key=firstString(region.key,region.ownershipKey,projected.key,region.conflictKey,region.id);
|
|
138
|
-
const conflictKey=firstString(region.conflictKey,projection?.conflictKey,key);
|
|
139
|
-
const links=array(projection?.sourceMapLinks??region.sourceMapLinks);
|
|
140
|
-
return compactRecord({
|
|
141
|
-
id:region.id??projected.id??`changed_region_${index+1}`,
|
|
142
|
-
key,
|
|
143
|
-
conflictKey,
|
|
144
|
-
changeKind:region.changeKind??projection?.changeKind,
|
|
145
|
-
regionKind:region.regionKind??region.ownershipRegionKind??projected.kind,
|
|
146
|
-
granularity:region.granularity??projected.granularity,
|
|
147
|
-
precision:region.precision??projected.precision,
|
|
148
|
-
language:region.language??projection?.language??context.language,
|
|
149
|
-
sourcePath:region.sourcePath??projection?.sourcePath??context.sourcePath,
|
|
150
|
-
sourceHash:region.sourceHash??projection?.after?.sourceHash??projection?.before?.sourceHash,
|
|
151
|
-
symbolId:region.symbolId??projected.symbolId,
|
|
152
|
-
symbolName:region.symbolName??region.name??projected.symbolName,
|
|
153
|
-
symbolKind:region.symbolKind??projected.symbolKind,
|
|
154
|
-
sourceSpan:region.sourceSpan??projected.sourceSpan,
|
|
155
|
-
sourceMapLinkIds:uniqueStrings([...strings(region.sourceMapLinkIds),...links.map((link)=>link.id)]),
|
|
156
|
-
sourceMapIds:uniqueStrings([...strings(region.sourceMapIds),...links.map((link)=>link.sourceMapId)]),
|
|
157
|
-
sourceMapMappingIds:uniqueStrings([...strings(region.sourceMapMappingIds),...links.map((link)=>link.sourceMapMappingId)]),
|
|
158
|
-
admission:compactRecord({
|
|
159
|
-
readiness:projection?.admission?.readiness??region.admission?.readiness,
|
|
160
|
-
action:projection?.admission?.action??region.admission?.action,
|
|
161
|
-
reasonCodes:uniqueStrings([...strings(region.admission?.reasonCodes),...strings(projection?.admission?.reasons)]),
|
|
162
|
-
conflictKeys:uniqueStrings([...strings(region.admission?.conflictKeys),...strings(projection?.admission?.conflictKeys)])
|
|
163
|
-
}),
|
|
164
|
-
metadata:region.metadata
|
|
165
|
-
});
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
|
|
169
|
-
function normalizeSourceMapLinks(links){
|
|
170
|
-
const seen=new Set();
|
|
171
|
-
const result=[];
|
|
172
|
-
for(const link of links.filter(Boolean)){
|
|
173
|
-
const id=link.id??`source_map_link_${result.length+1}`;
|
|
174
|
-
if(seen.has(id))continue;
|
|
175
|
-
seen.add(id);
|
|
176
|
-
result.push(compactRecord({
|
|
177
|
-
id,side:link.side,sourceMapId:link.sourceMapId,sourceMapMappingId:link.sourceMapMappingId,
|
|
178
|
-
sourcePath:link.sourcePath,sourceHash:link.sourceHash,targetPath:link.targetPath,targetHash:link.targetHash,
|
|
179
|
-
semanticSymbolId:link.semanticSymbolId,
|
|
180
|
-
semanticOccurrenceId:link.semanticOccurrenceId,
|
|
181
|
-
semanticNodeId:link.semanticNodeId,
|
|
182
|
-
nativeSourceId:link.nativeSourceId,
|
|
183
|
-
nativeAstNodeId:link.nativeAstNodeId,
|
|
184
|
-
precision:link.precision,
|
|
185
|
-
sourceSpan:link.sourceSpan,
|
|
186
|
-
generatedSpan:link.generatedSpan,
|
|
187
|
-
regionKey:link.ownershipRegionKey,
|
|
188
|
-
regionKind:link.ownershipRegionKind
|
|
189
|
-
}));
|
|
190
|
-
}
|
|
191
|
-
return result;
|
|
192
|
-
}
|
|
193
|
-
|
|
194
113
|
function recordIndex(parts){
|
|
195
|
-
const
|
|
114
|
+
const editIndex=parts.semanticEditIndex??semanticEditRecordIndex([],[],[],parts);
|
|
115
|
+
const editAdmission=parts.semanticEditAdmission??{};
|
|
196
116
|
const semanticTransformIndex=parts.semanticTransformIndex??semanticTransformRecordIndex([],parts);
|
|
117
|
+
const lineageIndex=semanticLineageLinkIndex(parts.lineageLinks,parts.changedRegions,parts.targetPortability,parts.admission);
|
|
197
118
|
return{
|
|
198
119
|
baseHashes:uniqueStrings([parts.baseHash,...parts.sources.map((item)=>item.baseHash)]),
|
|
199
120
|
targetHashes:uniqueStrings([parts.targetHash,...parts.sources.map((item)=>item.targetHash)]),
|
|
200
121
|
sourceHashes:uniqueStrings(parts.sources.map((item)=>item.sourceHash)),
|
|
201
|
-
sourcePaths:uniqueStrings([...parts.sources.map((item)=>item.sourcePath),...
|
|
202
|
-
regionKeys:uniqueStrings([...parts.changedRegions.map((region)=>region.key),...
|
|
122
|
+
sourcePaths:uniqueStrings([...parts.sources.map((item)=>item.sourcePath),...strings(editAdmission.sourcePaths),...editIndex.projectedSourcePaths,...semanticTransformIndex.transformSourcePaths,...semanticTransformIndex.transformTargetPaths,...lineageIndex.sourcePaths]),
|
|
123
|
+
regionKeys:uniqueStrings([...parts.changedRegions.map((region)=>region.key),...editIndex.anchorKeys]),
|
|
203
124
|
regionKinds:uniqueStrings(parts.changedRegions.map((region)=>region.regionKind)),
|
|
204
|
-
conflictKeys:uniqueStrings([...parts.changedRegions.flatMap((region)=>[region.conflictKey,...array(region.admission?.conflictKeys)]),...
|
|
125
|
+
conflictKeys:uniqueStrings([...parts.changedRegions.flatMap((region)=>[region.conflictKey,...array(region.admission?.conflictKeys)]),...editIndex.conflictKeys]),
|
|
205
126
|
sourceMapIds:uniqueStrings([...parts.sourceMapLinks.map((link)=>link.sourceMapId),...parts.changedRegions.flatMap((region)=>region.sourceMapIds??[])]),
|
|
206
127
|
sourceMapMappingIds:uniqueStrings([...parts.sourceMapLinks.map((link)=>link.sourceMapMappingId),...parts.changedRegions.flatMap((region)=>region.sourceMapMappingIds??[])]),
|
|
207
128
|
sourceMapLinkIds:uniqueStrings(parts.sourceMapLinks.map((link)=>link.id)),
|
|
208
|
-
evidenceIds:parts.evidenceIds,
|
|
209
|
-
proofIds:parts.proofIds,
|
|
129
|
+
evidenceIds:uniqueStrings([...parts.evidenceIds,...lineageIndex.evidenceIds]),
|
|
130
|
+
proofIds:uniqueStrings([...parts.proofIds,...lineageIndex.proofIds]),
|
|
131
|
+
lineageResolutionIds:lineageIndex.lineageResolutionIds,
|
|
132
|
+
lineageEventIds:lineageIndex.lineageEventIds,
|
|
133
|
+
lineageSourcePaths:lineageIndex.sourcePaths,
|
|
134
|
+
lineageEvidenceIds:lineageIndex.evidenceIds,
|
|
135
|
+
lineageProofIds:lineageIndex.proofIds,
|
|
136
|
+
lineageReasonCodes:lineageIndex.reasonCodes,
|
|
210
137
|
historyIds:parts.historyIds,
|
|
211
138
|
semanticOperationIds:uniqueStrings(parts.semanticOperationIds),
|
|
212
|
-
semanticEditScriptIds:
|
|
213
|
-
semanticEditProjectionIds:
|
|
214
|
-
semanticEditReplayIds:
|
|
215
|
-
semanticEditReplayStatuses:
|
|
216
|
-
semanticEditReplayActions:
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
139
|
+
semanticEditScriptIds:editIndex.semanticEditScriptIds,
|
|
140
|
+
semanticEditProjectionIds:editIndex.semanticEditProjectionIds,
|
|
141
|
+
semanticEditReplayIds:editIndex.semanticEditReplayIds,
|
|
142
|
+
semanticEditReplayStatuses:editIndex.semanticEditReplayStatuses,
|
|
143
|
+
semanticEditReplayActions:editIndex.semanticEditReplayActions,
|
|
144
|
+
semanticEditAdmissionStatuses:uniqueStrings([editAdmission.status]),
|
|
145
|
+
semanticEditAdmissionActions:uniqueStrings([editAdmission.action]),
|
|
146
|
+
semanticEditAdmissionReadinesses:uniqueStrings([editAdmission.readiness]),
|
|
147
|
+
semanticEditReplayCurrentHashes:editIndex.semanticEditReplayCurrentHashes,
|
|
148
|
+
semanticEditReplayOutputHashes:editIndex.semanticEditReplayOutputHashes,
|
|
149
|
+
semanticEditKeys:editIndex.semanticEditKeys,
|
|
150
|
+
semanticIdentityHashes:editIndex.semanticIdentityHashes,
|
|
151
|
+
sourceIdentityHashes:editIndex.sourceIdentityHashes,
|
|
152
|
+
operationContentHashes:editIndex.operationContentHashes,
|
|
153
|
+
editContentHashes:editIndex.editContentHashes,
|
|
224
154
|
semanticTransformIds:semanticTransformIndex.semanticTransformIds,
|
|
225
155
|
semanticTransformKeys:semanticTransformIndex.semanticTransformKeys,
|
|
226
156
|
semanticTransformIdentityHashes:semanticTransformIndex.semanticTransformIdentityHashes,
|
|
@@ -243,7 +173,7 @@ function recordIndex(parts){
|
|
|
243
173
|
}
|
|
244
174
|
|
|
245
175
|
function matchesRecord(record,query){
|
|
246
|
-
const index=record.index??recordIndex({...record,baseHash:record.baseHash,targetHash:record.targetHash,sources:record.sources??[],changedRegions:record.changedRegions??[],sourceMapLinks:record.sourceMapLinks??[],evidenceIds:record.evidenceIds??[],proofIds:record.proofIds??[],historyIds:record.historyIds??[],semanticOperationIds:record.semanticOperationIds??[],patchId:record.patchId,mergeCandidateId:record.mergeCandidateId,admission:record.admission??{},targetPortability:record.metadata?.targetPortability});
|
|
176
|
+
const index=record.index??recordIndex({...record,baseHash:record.baseHash,targetHash:record.targetHash,sources:record.sources??[],changedRegions:record.changedRegions??[],sourceMapLinks:record.sourceMapLinks??[],evidenceIds:record.evidenceIds??[],proofIds:record.proofIds??[],historyIds:record.historyIds??[],semanticOperationIds:record.semanticOperationIds??[],patchId:record.patchId,mergeCandidateId:record.mergeCandidateId,admission:record.admission??{},semanticEditAdmission:record.admission?.semanticEditAdmission??record.metadata?.semanticEditAdmission,targetPortability:record.metadata?.targetPortability,lineageLinks:normalizeLineageResolutionLinks([...array(record.metadata?.semanticLineageResolutionLinks),...array(record.admission?.metadata?.semanticLineageResolutionLinks)])});
|
|
247
177
|
return matchAny(queryValues(query.id,query.ids),[record.id])
|
|
248
178
|
&&matchAny(queryValues(query.patchId,query.patchIds),index.patchIds)
|
|
249
179
|
&&matchAny(queryValues(query.mergeCandidateId,query.mergeCandidateIds),index.mergeCandidateIds)
|
|
@@ -259,6 +189,12 @@ function matchesRecord(record,query){
|
|
|
259
189
|
&&matchAny(queryValues(query.sourceMapLinkId,query.sourceMapLinkIds),index.sourceMapLinkIds)
|
|
260
190
|
&&matchAny(queryValues(query.evidenceId,query.evidenceIds),index.evidenceIds)
|
|
261
191
|
&&matchAny(queryValues(query.proofId,query.proofIds),index.proofIds)
|
|
192
|
+
&&matchAny(queryValues(query.lineageResolutionId,query.lineageResolutionIds,query.semanticLineageResolutionId,query.semanticLineageResolutionIds),index.lineageResolutionIds)
|
|
193
|
+
&&matchAny(queryValues(query.lineageEventId,query.lineageEventIds),index.lineageEventIds)
|
|
194
|
+
&&matchAny(queryValues(query.lineageSourcePath,query.lineageSourcePaths),index.lineageSourcePaths)
|
|
195
|
+
&&matchAny(queryValues(query.lineageEvidenceId,query.lineageEvidenceIds),index.lineageEvidenceIds)
|
|
196
|
+
&&matchAny(queryValues(query.lineageProofId,query.lineageProofIds),index.lineageProofIds)
|
|
197
|
+
&&matchAny(queryValues(query.lineageReasonCode,query.lineageReasonCodes),index.lineageReasonCodes)
|
|
262
198
|
&&matchAny(queryValues(query.historyId,query.historyIds),index.historyIds)
|
|
263
199
|
&&matchAny(queryValues(query.semanticOperationId,query.semanticOperationIds),index.semanticOperationIds)
|
|
264
200
|
&&matchAny(queryValues(query.semanticEditScriptId,query.semanticEditScriptIds),index.semanticEditScriptIds)
|
|
@@ -266,6 +202,9 @@ function matchesRecord(record,query){
|
|
|
266
202
|
&&matchAny(queryValues(query.semanticEditReplayId,query.semanticEditReplayIds),index.semanticEditReplayIds)
|
|
267
203
|
&&matchAny(queryValues(query.semanticEditReplayStatus,query.semanticEditReplayStatuses),index.semanticEditReplayStatuses)
|
|
268
204
|
&&matchAny(queryValues(query.semanticEditReplayAction,query.semanticEditReplayActions),index.semanticEditReplayActions)
|
|
205
|
+
&&matchAny(queryValues(query.semanticEditAdmissionStatus,query.semanticEditAdmissionStatuses),index.semanticEditAdmissionStatuses)
|
|
206
|
+
&&matchAny(queryValues(query.semanticEditAdmissionAction,query.semanticEditAdmissionActions),index.semanticEditAdmissionActions)
|
|
207
|
+
&&matchAny(queryValues(query.semanticEditAdmissionReadiness,query.semanticEditAdmissionReadinesses),index.semanticEditAdmissionReadinesses)
|
|
269
208
|
&&matchAny(queryValues(query.semanticEditReplayCurrentHash,query.semanticEditReplayCurrentHashes),index.semanticEditReplayCurrentHashes)
|
|
270
209
|
&&matchAny(queryValues(query.semanticEditReplayOutputHash,query.semanticEditReplayOutputHashes),index.semanticEditReplayOutputHashes)
|
|
271
210
|
&&matchAny(queryValues(query.semanticEditKey,query.semanticEditKeys),index.semanticEditKeys)
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { idFragment, uniqueStrings } from '../../native-import-utils.js';
|
|
2
|
+
|
|
3
|
+
export function normalizeSources(entries, context) {
|
|
4
|
+
return entries.filter(Boolean).map((entry, index) => compactRecord({
|
|
5
|
+
id: entry.id ?? entry.sourceId,
|
|
6
|
+
side: entry.side,
|
|
7
|
+
importId: entry.importId ?? entry.importResultId,
|
|
8
|
+
language: entry.language ?? context.language,
|
|
9
|
+
sourcePath: entry.sourcePath ?? context.sourcePath,
|
|
10
|
+
sourceHash: entry.sourceHash ?? entry.hash,
|
|
11
|
+
baseHash: entry.baseHash ?? entry.beforeHash ?? context.baseHash ?? context.beforeHash,
|
|
12
|
+
targetHash: entry.targetHash ?? entry.afterHash ?? context.targetHash ?? context.afterHash,
|
|
13
|
+
nativeSourceId: entry.nativeSourceId,
|
|
14
|
+
nativeAstId: entry.nativeAstId,
|
|
15
|
+
semanticIndexId: entry.semanticIndexId,
|
|
16
|
+
universalAstId: entry.universalAstId,
|
|
17
|
+
sourceMapIds: uniqueStrings(entry.sourceMapIds),
|
|
18
|
+
ordinal: index
|
|
19
|
+
})).filter((entry) => entry.importId || entry.sourcePath || entry.sourceHash || entry.baseHash || entry.targetHash);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function sourceRef(importResult, side, sourceHash) {
|
|
23
|
+
if (!importResult) return undefined;
|
|
24
|
+
return compactRecord({
|
|
25
|
+
id: `${side}_${importResult.id ?? idFragment(importResult.sourcePath ?? 'source')}`,
|
|
26
|
+
side,
|
|
27
|
+
importId: importResult.id,
|
|
28
|
+
language: importResult.language,
|
|
29
|
+
sourcePath: importResult.sourcePath,
|
|
30
|
+
sourceHash: sourceHash ?? importResult.nativeSource?.sourceHash ?? importResult.nativeAst?.sourceHash ?? importResult.sourceHash,
|
|
31
|
+
nativeSourceId: importResult.nativeSource?.id,
|
|
32
|
+
nativeAstId: importResult.nativeAst?.id,
|
|
33
|
+
semanticIndexId: importResult.semanticIndex?.id,
|
|
34
|
+
universalAstId: importResult.universalAst?.id,
|
|
35
|
+
sourceMapIds: uniqueStrings((importResult.sourceMaps ?? []).map((map) => map.id))
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function normalizeRegions(regions, context) {
|
|
40
|
+
return regions.filter(Boolean).map((region, index) => {
|
|
41
|
+
const projection = region.metadata?.changedRegionProjection ?? region.projection;
|
|
42
|
+
const projected = projection?.region ?? {};
|
|
43
|
+
const key = firstString(region.key, region.ownershipKey, projected.key, region.conflictKey, region.id);
|
|
44
|
+
const conflictKey = firstString(region.conflictKey, projection?.conflictKey, key);
|
|
45
|
+
const links = array(projection?.sourceMapLinks ?? region.sourceMapLinks);
|
|
46
|
+
return compactRecord({
|
|
47
|
+
id: region.id ?? projected.id ?? `changed_region_${index + 1}`,
|
|
48
|
+
key,
|
|
49
|
+
conflictKey,
|
|
50
|
+
changeKind: region.changeKind ?? projection?.changeKind,
|
|
51
|
+
regionKind: region.regionKind ?? region.ownershipRegionKind ?? projected.kind,
|
|
52
|
+
granularity: region.granularity ?? projected.granularity,
|
|
53
|
+
precision: region.precision ?? projected.precision,
|
|
54
|
+
language: region.language ?? projection?.language ?? context.language,
|
|
55
|
+
sourcePath: region.sourcePath ?? projection?.sourcePath ?? context.sourcePath,
|
|
56
|
+
sourceHash: region.sourceHash ?? projection?.after?.sourceHash ?? projection?.before?.sourceHash,
|
|
57
|
+
symbolId: region.symbolId ?? projected.symbolId,
|
|
58
|
+
symbolName: region.symbolName ?? region.name ?? projected.symbolName,
|
|
59
|
+
symbolKind: region.symbolKind ?? projected.symbolKind,
|
|
60
|
+
sourceSpan: region.sourceSpan ?? projected.sourceSpan,
|
|
61
|
+
sourceMapLinkIds: uniqueStrings([...strings(region.sourceMapLinkIds), ...links.map((link) => link.id)]),
|
|
62
|
+
sourceMapIds: uniqueStrings([...strings(region.sourceMapIds), ...links.map((link) => link.sourceMapId)]),
|
|
63
|
+
sourceMapMappingIds: uniqueStrings([...strings(region.sourceMapMappingIds), ...links.map((link) => link.sourceMapMappingId)]),
|
|
64
|
+
lineageResolutionIds: uniqueStrings([...strings(region.lineageResolutionIds), ...strings(projection?.lineageResolutionIds), ...strings(region.metadata?.bidirectionalTargetChange?.lineageResolutionIds), ...strings(region.metadata?.semanticHistoryLineageResolution?.lineageResolutionIds), region.metadata?.semanticHistoryLineageResolution?.id]),
|
|
65
|
+
lineageEventIds: uniqueStrings([...strings(region.lineageEventIds), ...strings(projection?.lineageEventIds), ...strings(region.metadata?.semanticHistoryLineageResolution?.lineageEventIds)]),
|
|
66
|
+
lineageSourcePaths: uniqueStrings([...strings(region.lineageSourcePaths), ...strings(projection?.lineageSourcePaths), ...strings(region.metadata?.semanticHistoryLineageResolution?.sourcePaths)]),
|
|
67
|
+
lineageEvidenceIds: uniqueStrings([...strings(region.lineageEvidenceIds), ...strings(projection?.lineageEvidenceIds), ...strings(region.metadata?.semanticHistoryLineageResolution?.evidenceIds)]),
|
|
68
|
+
lineageProofIds: uniqueStrings([...strings(region.lineageProofIds), ...strings(projection?.lineageProofIds), ...strings(region.metadata?.semanticHistoryLineageResolution?.proofIds)]),
|
|
69
|
+
lineageReasonCodes: uniqueStrings([...strings(region.lineageReasonCodes), ...strings(projection?.lineageReasonCodes), ...strings(region.metadata?.semanticHistoryLineageResolution?.reasonCodes)]),
|
|
70
|
+
admission: compactRecord({
|
|
71
|
+
readiness: projection?.admission?.readiness ?? region.admission?.readiness,
|
|
72
|
+
action: projection?.admission?.action ?? region.admission?.action,
|
|
73
|
+
reasonCodes: uniqueStrings([...strings(region.admission?.reasonCodes), ...strings(projection?.admission?.reasons)]),
|
|
74
|
+
conflictKeys: uniqueStrings([...strings(region.admission?.conflictKeys), ...strings(projection?.admission?.conflictKeys)])
|
|
75
|
+
}),
|
|
76
|
+
metadata: region.metadata
|
|
77
|
+
});
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
export function normalizeSourceMapLinks(links) {
|
|
82
|
+
const seen = new Set();
|
|
83
|
+
const result = [];
|
|
84
|
+
for (const link of links.filter(Boolean)) {
|
|
85
|
+
const id = link.id ?? `source_map_link_${result.length + 1}`;
|
|
86
|
+
if (seen.has(id)) continue;
|
|
87
|
+
seen.add(id);
|
|
88
|
+
result.push(compactRecord({
|
|
89
|
+
id,
|
|
90
|
+
side: link.side,
|
|
91
|
+
sourceMapId: link.sourceMapId,
|
|
92
|
+
sourceMapMappingId: link.sourceMapMappingId,
|
|
93
|
+
sourcePath: link.sourcePath,
|
|
94
|
+
sourceHash: link.sourceHash,
|
|
95
|
+
targetPath: link.targetPath,
|
|
96
|
+
targetHash: link.targetHash,
|
|
97
|
+
semanticSymbolId: link.semanticSymbolId,
|
|
98
|
+
semanticOccurrenceId: link.semanticOccurrenceId,
|
|
99
|
+
semanticNodeId: link.semanticNodeId,
|
|
100
|
+
nativeSourceId: link.nativeSourceId,
|
|
101
|
+
nativeAstNodeId: link.nativeAstNodeId,
|
|
102
|
+
precision: link.precision,
|
|
103
|
+
sourceSpan: link.sourceSpan,
|
|
104
|
+
generatedSpan: link.generatedSpan,
|
|
105
|
+
regionKey: link.ownershipRegionKey,
|
|
106
|
+
regionKind: link.ownershipRegionKind
|
|
107
|
+
}));
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function array(value) {
|
|
113
|
+
if (value === undefined || value === null) return [];
|
|
114
|
+
return Array.isArray(value) ? value : [value];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function strings(value) {
|
|
118
|
+
return array(value).map((entry) => String(entry ?? '')).filter(Boolean);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function firstString(...values) {
|
|
122
|
+
return values.map((value) => value === undefined || value === null ? '' : String(value)).find(Boolean);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function compactRecord(value) {
|
|
126
|
+
return Object.fromEntries(Object.entries(value ?? {}).filter(([, entry]) => entry !== undefined && (!Array.isArray(entry) || entry.length > 0)));
|
|
127
|
+
}
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
+
import { spanOffsets } from './semanticEditSourceRanges.js';
|
|
2
|
+
|
|
1
3
|
export function sourceTextForSpan(sourceText, span) {
|
|
2
4
|
if (typeof sourceText !== 'string' || !span) return undefined;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
}
|
|
6
|
-
if (typeof span.startLine === 'number') {
|
|
7
|
-
const lines = sourceText.split(/\r?\n/);
|
|
8
|
-
const endLine = typeof span.endLine === 'number' && span.endLine >= span.startLine ? span.endLine : span.startLine;
|
|
9
|
-
return lines.slice(span.startLine - 1, endLine).join('\n');
|
|
10
|
-
}
|
|
11
|
-
return undefined;
|
|
5
|
+
const range = spanOffsets(sourceText, span);
|
|
6
|
+
return range ? sourceText.slice(range.start, range.end) : undefined;
|
|
12
7
|
}
|
|
@@ -68,12 +68,14 @@ function addIdentifierTarget(map, identifier, target) {
|
|
|
68
68
|
|
|
69
69
|
function scanDeclarationDependencies(input, documentId, scan, identifiers, lines, records) {
|
|
70
70
|
const state = { inBlockComment: false };
|
|
71
|
+
const factState = { braceDepth: 0, pendingSwitch: false, switchDepth: 0 };
|
|
71
72
|
for (let lineNumber = scan.startLine; lineNumber <= scan.endLine; lineNumber += 1) {
|
|
72
73
|
const scanLine = maskDependencyLine(input, lines[lineNumber - 1]?.line ?? '', state);
|
|
73
|
-
addLightweightSemanticFacts(input, documentId, scan.declaration, scanLine, lineNumber, records);
|
|
74
|
+
addLightweightSemanticFacts(input, documentId, scan.declaration, scanLine, lineNumber, records, factState);
|
|
74
75
|
for (const match of scanLine.matchAll(/[A-Za-z_$][\w$]*/g)) {
|
|
75
76
|
const name = match[0];
|
|
76
77
|
if (!isDependencyIdentifier(name) || !identifiers.has(name)) continue;
|
|
78
|
+
if (isIgnoredDependencyOccurrence(input, scanLine, match.index, name)) continue;
|
|
77
79
|
const targets = identifiers.get(name).filter((target) => target.symbolId !== scan.declaration.symbolId);
|
|
78
80
|
for (const target of targets) {
|
|
79
81
|
addDependencyRecord(input, documentId, scan.declaration, target, {
|
|
@@ -87,10 +89,11 @@ function scanDeclarationDependencies(input, documentId, scan, identifiers, lines
|
|
|
87
89
|
}
|
|
88
90
|
}
|
|
89
91
|
|
|
90
|
-
function addLightweightSemanticFacts(input, documentId, declaration, line, lineNumber, records) {
|
|
92
|
+
function addLightweightSemanticFacts(input, documentId, declaration, line, lineNumber, records, factState) {
|
|
93
|
+
if (!shouldScanRuntimeFacts(input, declaration)) return;
|
|
91
94
|
const text = String(line ?? '').trim();
|
|
92
95
|
if (!text) return;
|
|
93
|
-
for (const item of lightweightControlFlowKinds(text)) {
|
|
96
|
+
for (const item of lightweightControlFlowKinds(text, factState)) {
|
|
94
97
|
addFactRecord(input, documentId, declaration, 'controlFlow', item, lineNumber, records);
|
|
95
98
|
}
|
|
96
99
|
for (const item of lightweightEffectKinds(text)) {
|
|
@@ -99,11 +102,45 @@ function addLightweightSemanticFacts(input, documentId, declaration, line, lineN
|
|
|
99
102
|
for (const item of lightweightMutationKinds(text)) {
|
|
100
103
|
addFactRecord(input, documentId, declaration, 'mutation', item, lineNumber, records);
|
|
101
104
|
}
|
|
105
|
+
updateLightweightFactState(text, factState);
|
|
102
106
|
}
|
|
103
107
|
|
|
104
|
-
function
|
|
108
|
+
function shouldScanRuntimeFacts(input, declaration) {
|
|
109
|
+
if (!isJavaScriptLike(input)) return true;
|
|
110
|
+
if (declaration?.fields?.typeKind) return false;
|
|
111
|
+
if (/^Type(?:Alias|Method|Property|FunctionProperty)/.test(String(declaration?.kind ?? ''))) return false;
|
|
112
|
+
return !['interface', 'type'].includes(String(declaration?.symbolKind ?? '').toLowerCase());
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function isJavaScriptLike(input) {
|
|
116
|
+
return ['javascript', 'typescript'].includes(String(input?.language ?? '').toLowerCase());
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function isIgnoredDependencyOccurrence(input, line, startIndex, name) {
|
|
120
|
+
if (!isJavaScriptLike(input)) return false;
|
|
121
|
+
const endIndex = startIndex + String(name).length;
|
|
122
|
+
const previous = previousNonSpace(line, startIndex - 1);
|
|
123
|
+
const next = nextNonSpace(line, endIndex);
|
|
124
|
+
return previous === '.' || next === ':';
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function previousNonSpace(line, index) {
|
|
128
|
+
for (let cursor = index; cursor >= 0; cursor -= 1) {
|
|
129
|
+
if (!/\s/.test(line[cursor])) return line[cursor];
|
|
130
|
+
}
|
|
131
|
+
return '';
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function nextNonSpace(line, index) {
|
|
135
|
+
for (let cursor = index; cursor < line.length; cursor += 1) {
|
|
136
|
+
if (!/\s/.test(line[cursor])) return line[cursor];
|
|
137
|
+
}
|
|
138
|
+
return '';
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
function lightweightControlFlowKinds(line, state = {}) {
|
|
105
142
|
const kinds = [];
|
|
106
|
-
if (
|
|
143
|
+
if (hasBranchSyntax(line, state)) kinds.push('branch');
|
|
107
144
|
if (/\b(for|while|do)\b/.test(line)) kinds.push('loop');
|
|
108
145
|
if (/\b(return|yield)\b/.test(line)) kinds.push('exit');
|
|
109
146
|
if (/\b(throw|catch|finally|try)\b/.test(line)) kinds.push('exception');
|
|
@@ -114,7 +151,7 @@ function lightweightControlFlowKinds(line) {
|
|
|
114
151
|
function lightweightEffectKinds(line) {
|
|
115
152
|
const kinds = [];
|
|
116
153
|
if (/\bawait\b|import\s*\(/.test(line)) kinds.push('async');
|
|
117
|
-
if (
|
|
154
|
+
if (hasGlobalNetworkCall(line)) kinds.push('network');
|
|
118
155
|
if (/\b(localStorage|sessionStorage|indexedDB|caches|cookie)\b/.test(line)) kinds.push('storage');
|
|
119
156
|
if (/\b(setTimeout|setInterval|requestAnimationFrame|queueMicrotask)\s*\(/.test(line)) kinds.push('scheduler');
|
|
120
157
|
if (/\b(console|process|Deno|Bun)\s*\./.test(line)) kinds.push('host');
|
|
@@ -125,12 +162,81 @@ function lightweightEffectKinds(line) {
|
|
|
125
162
|
function lightweightMutationKinds(line) {
|
|
126
163
|
const kinds = [];
|
|
127
164
|
if (/\bdelete\s+[A-Za-z_$][\w$.[\]]*/.test(line)) kinds.push('delete');
|
|
128
|
-
if (
|
|
165
|
+
if (hasRuntimeAssignment(line)) kinds.push('assignment');
|
|
129
166
|
if (/\+\+|--|(?:\+=|-=|\*=|\/=|%=|\|\|=|&&=|\?\?=)/.test(line)) kinds.push('update');
|
|
130
167
|
if (/\.(?:push|pop|shift|unshift|splice|sort|reverse|set|add|delete|clear)\s*\(/.test(line)) kinds.push('mutating-call');
|
|
131
168
|
return kinds;
|
|
132
169
|
}
|
|
133
170
|
|
|
171
|
+
function hasBranchSyntax(line, state) {
|
|
172
|
+
return /\bif\s*\(/.test(line)
|
|
173
|
+
|| /(?:^|[}\s;])else\b(?:\s+if\s*\(|\s*[{;]|$)/.test(line)
|
|
174
|
+
|| /\bswitch\s*\(/.test(line)
|
|
175
|
+
|| ((state?.switchDepth ?? 0) > 0 && /^\s*(?:case\b[^:]*|default)\s*:/.test(line));
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function updateLightweightFactState(line, state = {}) {
|
|
179
|
+
const hadSwitch = /\bswitch\s*\(/.test(line);
|
|
180
|
+
const beforeDepth = state.braceDepth ?? 0;
|
|
181
|
+
const delta = blockBraceDelta(line);
|
|
182
|
+
if (hadSwitch) state.pendingSwitch = true;
|
|
183
|
+
state.braceDepth = Math.max(0, beforeDepth + delta);
|
|
184
|
+
if (state.pendingSwitch && state.braceDepth > beforeDepth) {
|
|
185
|
+
state.switchDepth = state.braceDepth;
|
|
186
|
+
state.pendingSwitch = false;
|
|
187
|
+
}
|
|
188
|
+
if ((state.switchDepth ?? 0) > 0 && state.braceDepth < state.switchDepth) {
|
|
189
|
+
state.switchDepth = 0;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function blockBraceDelta(line) {
|
|
194
|
+
let delta = 0;
|
|
195
|
+
for (const char of String(line ?? '')) {
|
|
196
|
+
if (char === '{') delta += 1;
|
|
197
|
+
else if (char === '}') delta -= 1;
|
|
198
|
+
}
|
|
199
|
+
return delta;
|
|
200
|
+
}
|
|
201
|
+
|
|
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
|
+
function hasRuntimeAssignment(line) {
|
|
216
|
+
const text = String(line ?? '');
|
|
217
|
+
for (let index = 0; index < text.length; index += 1) {
|
|
218
|
+
if (text[index] !== '=' || !isPlainAssignmentOperator(text, index)) continue;
|
|
219
|
+
if (!isLocalDeclarationInitializer(text, index)) return true;
|
|
220
|
+
}
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function isPlainAssignmentOperator(text, index) {
|
|
225
|
+
const previous = text[index - 1] ?? '';
|
|
226
|
+
const next = text[index + 1] ?? '';
|
|
227
|
+
if (next === '=' || next === '>') return false;
|
|
228
|
+
return !['=', '!', '<', '>', '+', '-', '*', '/', '%', '&', '|', '?', '^'].includes(previous);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
function isLocalDeclarationInitializer(text, index) {
|
|
232
|
+
const prefix = text.slice(0, index);
|
|
233
|
+
const statementStart = Math.max(prefix.lastIndexOf(';'), prefix.lastIndexOf('{'), prefix.lastIndexOf('}'));
|
|
234
|
+
const statement = prefix.slice(statementStart + 1).trim();
|
|
235
|
+
return /^(?:export\s+)?(?:declare\s+)?(?:const|let|var|using)\b/.test(statement)
|
|
236
|
+
|| /^for\s*\([^;)]*(?:const|let|var)\b/.test(statement)
|
|
237
|
+
|| /^(?:export\s+)?type\s+[A-Za-z_$][\w$]*(?:\s*<[^>]+>)?\s*$/.test(statement);
|
|
238
|
+
}
|
|
239
|
+
|
|
134
240
|
function addFactRecord(input, documentId, declaration, predicate, factKind, lineNumber, records) {
|
|
135
241
|
const key = `${declaration.symbolId}|${predicate}|${factKind}|${lineNumber}`;
|
|
136
242
|
if (records.seen.has(key)) return;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export function uniqueStrings(values) {
|
|
2
|
-
return [...new Set((values ?? []).map((value) => String(value)).filter(Boolean))];
|
|
2
|
+
return [...new Set((values ?? []).filter((value) => value !== undefined && value !== null).map((value) => String(value)).filter(Boolean))];
|
|
3
3
|
}
|
|
4
4
|
|
|
5
5
|
export function uniqueRecordsById(records) {
|
|
@@ -141,3 +141,17 @@ export function idFragment(value) {
|
|
|
141
141
|
.replace(/^_+|_+$/g, '')
|
|
142
142
|
.slice(0, 80) || 'native';
|
|
143
143
|
}
|
|
144
|
+
|
|
145
|
+
export function caseSensitiveIdFragment(value) {
|
|
146
|
+
const text = String(value ?? 'native');
|
|
147
|
+
return `${idFragment(text)}_${caseSensitiveHash(text)}`;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
function caseSensitiveHash(value) {
|
|
151
|
+
let hash = 0x811c9dc5;
|
|
152
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
153
|
+
hash ^= value.charCodeAt(index);
|
|
154
|
+
hash = Math.imul(hash, 0x01000193);
|
|
155
|
+
}
|
|
156
|
+
return (hash >>> 0).toString(36);
|
|
157
|
+
}
|