@codeyam/codeyam-cli 0.1.0-bleeding-edge.8afd3ee → 0.1.0-staging.09652b8
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/analyzer-template/.build-info.json +7 -7
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +1 -1
- package/analyzer-template/packages/ai/index.ts +0 -1
- package/analyzer-template/packages/ai/scripts/ai-test-matrix.mjs +424 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +6 -16
- package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +197 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/paths.ts +28 -2
- package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +113 -4
- package/analyzer-template/packages/ai/src/lib/checkAllAttributes.ts +1 -3
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +430 -7
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +12 -6
- package/analyzer-template/packages/ai/src/lib/generateChangesEntityDocumentation.ts +20 -2
- package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarioData.ts +56 -160
- package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarios.ts +79 -265
- package/analyzer-template/packages/ai/src/lib/generateEntityDocumentation.ts +16 -2
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +53 -154
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +84 -254
- package/analyzer-template/packages/ai/src/lib/generateStatementAnalysis.ts +48 -71
- package/analyzer-template/packages/ai/src/lib/getLLMCallStats.ts +0 -14
- package/analyzer-template/packages/ai/src/lib/modelInfo.ts +15 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityDocumentationGenerator.ts +8 -33
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.ts +54 -62
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.ts +93 -109
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityDocumentationGenerator.ts +8 -27
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +33 -38
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.ts +30 -30
- package/analyzer-template/packages/ai/src/lib/types/index.ts +2 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +15 -7
- package/analyzer-template/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.ts +28 -21
- package/analyzer-template/packages/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.ts +18 -11
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +28 -21
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js +18 -11
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js.map +1 -1
- package/analyzer-template/packages/github/dist/utils/index.d.ts +1 -0
- package/analyzer-template/packages/github/dist/utils/index.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/index.js +1 -0
- package/analyzer-template/packages/github/dist/utils/index.js.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getNextRoutePath.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getNextRoutePath.js +2 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/getNextRoutePath.js.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js +2 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts +12 -0
- package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts.map +1 -0
- package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js +32 -0
- package/analyzer-template/packages/github/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js.map +1 -0
- package/analyzer-template/packages/ui-components/src/scenario-editor/components/DataItemEditor.tsx +1 -1
- package/analyzer-template/packages/utils/dist/utils/index.d.ts +1 -0
- package/analyzer-template/packages/utils/dist/utils/index.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/index.js +1 -0
- package/analyzer-template/packages/utils/dist/utils/index.js.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getNextRoutePath.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getNextRoutePath.js +2 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/getNextRoutePath.js.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js +2 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/nextRouteFileNameToRoute.js.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts +12 -0
- package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.d.ts.map +1 -0
- package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js +32 -0
- package/analyzer-template/packages/utils/dist/utils/src/lib/frameworks/sanitizeNextRouteSegments.js.map +1 -0
- package/analyzer-template/packages/utils/index.ts +1 -0
- package/analyzer-template/packages/utils/src/lib/frameworks/getNextRoutePath.ts +2 -1
- package/analyzer-template/packages/utils/src/lib/frameworks/nextRouteFileNameToRoute.ts +2 -1
- package/analyzer-template/packages/utils/src/lib/frameworks/sanitizeNextRouteSegments.ts +33 -0
- package/analyzer-template/project/startScenarioCapture.ts +24 -0
- package/analyzer-template/project/trackGeneratedFiles.ts +41 -0
- package/analyzer-template/project/writeMockDataTsx.ts +94 -4
- package/analyzer-template/project/writeScenarioComponents.ts +35 -27
- package/background/src/lib/virtualized/project/startScenarioCapture.js +18 -0
- package/background/src/lib/virtualized/project/startScenarioCapture.js.map +1 -1
- package/background/src/lib/virtualized/project/trackGeneratedFiles.js +30 -0
- package/background/src/lib/virtualized/project/trackGeneratedFiles.js.map +1 -0
- package/background/src/lib/virtualized/project/writeMockDataTsx.js +71 -3
- package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
- package/background/src/lib/virtualized/project/writeScenarioComponents.js +15 -11
- package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
- package/codeyam-cli/src/commands/init.js +4 -23
- package/codeyam-cli/src/commands/init.js.map +1 -1
- package/codeyam-cli/src/utils/webappDetection.js +2 -1
- package/codeyam-cli/src/utils/webappDetection.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-B9Sf8e9w.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-B0oiPem-.js → InteractivePreview-CDnfNKKQ.js} +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-DUS-3h7I.js +3 -0
- package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-BKKG1s2B.js → LogViewer-TJzDQku1.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-BgdlWM6p.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/ScenarioPreview-Bl6GY-OE.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-DmjXUj6m.js → ScenarioViewer-BDq8RX50.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/_index-Bh3y3Wsl.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-tq7Bl6-t.js +10 -0
- package/codeyam-cli/src/webserver/build/client/assets/{chart-column-VXBS6qOn.js → chart-column-q9_nHfwv.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/chunk-WWGJGFF6-DvL0YqDJ.js +26 -0
- package/codeyam-cli/src/webserver/build/client/assets/{circle-alert-n5GUC2AS.js → circle-alert-CKMpA1v_.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{clock-DKqtX8js.js → clock-Wnfog8Qw.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-C_ixaqqh.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-BHiWkb_W.js → entity._sha._-3bYjyojg.js} +10 -10
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-DtfwpN9J.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-QecTs_sq.js +5 -0
- package/codeyam-cli/src/webserver/build/client/assets/entry.client-hnkEgHrC.js +5 -0
- package/codeyam-cli/src/webserver/build/client/assets/file-text-CvCVdKLW.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/files-DgUCYhbd.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/git-WoKohOtW.js +12 -0
- package/codeyam-cli/src/webserver/build/client/assets/globals-DZfbt0u5.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/index-Vvbl94Xc.js +8 -0
- package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-v3c6DFp4.js → loader-circle-Bxm63UxG.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-c90b8608.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/root-DrVZQamX.js +16 -0
- package/codeyam-cli/src/webserver/build/client/assets/{search-DA14wXpu.js → search-CJkk16Ct.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{settings-COJUrwGu.js → settings-ConzHeiL.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/settings-LuiJ1UIm.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/simulations-B9LRwAej.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-Lumm1t01.js → useLastLogLine-CpUcCv1V.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/useToast-DOxmMaSg.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{zap-BvukH0eN.js → zap-D5R1FAcH.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/index-DzbqTxoN.js +1 -0
- package/codeyam-cli/src/webserver/build/server/assets/server-build-DGGis3OZ.js +166 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/src/webserver/server.js +1 -1
- package/codeyam-cli/src/webserver/server.js.map +1 -1
- package/codeyam-cli/templates/codeyam-setup-skill.md +5 -0
- package/package.json +7 -7
- package/packages/ai/index.js +0 -1
- package/packages/ai/index.js.map +1 -1
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +6 -15
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
- package/packages/ai/src/lib/astScopes/methodSemantics.js +134 -0
- package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
- package/packages/ai/src/lib/astScopes/paths.js +28 -3
- package/packages/ai/src/lib/astScopes/paths.js.map +1 -1
- package/packages/ai/src/lib/astScopes/processExpression.js +99 -3
- package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
- package/packages/ai/src/lib/checkAllAttributes.js +1 -3
- package/packages/ai/src/lib/checkAllAttributes.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +308 -2
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +12 -6
- package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
- package/packages/ai/src/lib/generateChangesEntityDocumentation.js +19 -1
- package/packages/ai/src/lib/generateChangesEntityDocumentation.js.map +1 -1
- package/packages/ai/src/lib/generateChangesEntityScenarioData.js +55 -156
- package/packages/ai/src/lib/generateChangesEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateChangesEntityScenarios.js +79 -262
- package/packages/ai/src/lib/generateChangesEntityScenarios.js.map +1 -1
- package/packages/ai/src/lib/generateEntityDocumentation.js +15 -1
- package/packages/ai/src/lib/generateEntityDocumentation.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarioData.js +52 -152
- package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarios.js +88 -258
- package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
- package/packages/ai/src/lib/generateStatementAnalysis.js +46 -71
- package/packages/ai/src/lib/generateStatementAnalysis.js.map +1 -1
- package/packages/ai/src/lib/getLLMCallStats.js +0 -14
- package/packages/ai/src/lib/getLLMCallStats.js.map +1 -1
- package/packages/ai/src/lib/modelInfo.js +15 -0
- package/packages/ai/src/lib/modelInfo.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityDocumentationGenerator.js +8 -33
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityDocumentationGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js +35 -41
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js +59 -72
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateEntityDocumentationGenerator.js +8 -27
- package/packages/ai/src/lib/promptGenerators/generateEntityDocumentationGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +24 -27
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js +21 -22
- package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js.map +1 -1
- package/packages/ai/src/lib/types/index.js +2 -0
- package/packages/ai/src/lib/types/index.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +16 -7
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +28 -21
- package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
- package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js +18 -11
- package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageRemix.js.map +1 -1
- package/packages/utils/index.js +1 -0
- package/packages/utils/index.js.map +1 -1
- package/packages/utils/src/lib/frameworks/getNextRoutePath.js +2 -1
- package/packages/utils/src/lib/frameworks/getNextRoutePath.js.map +1 -1
- package/packages/utils/src/lib/frameworks/nextRouteFileNameToRoute.js +2 -1
- package/packages/utils/src/lib/frameworks/nextRouteFileNameToRoute.js.map +1 -1
- package/packages/utils/src/lib/frameworks/sanitizeNextRouteSegments.js +32 -0
- package/packages/utils/src/lib/frameworks/sanitizeNextRouteSegments.js.map +1 -0
- package/analyzer-template/packages/ai/src/lib/generateEntityDataMap.ts +0 -375
- package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-rqv54FUY.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-DqXXjAJ7.js +0 -3
- package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-DU_jxCPD.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/ScenarioPreview-5DY-YIxu.js +0 -6
- package/codeyam-cli/src/webserver/build/client/assets/_index-DvSrcxsk.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-CsaMd9mb.js +0 -10
- package/codeyam-cli/src/webserver/build/client/assets/components-Dj-Ggnl2.js +0 -40
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BbR3FwNc.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-L7M9Vr5z.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-C9w-q7P3.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/entry.client-CdGoUs8A.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/file-text-B6Er7j5k.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/files-KcDVw1FY.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/git-B9uZ8eSJ.js +0 -12
- package/codeyam-cli/src/webserver/build/client/assets/globals-B0f88RTV.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-fca08d7e.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/root-Cf8VBqIb.js +0 -16
- package/codeyam-cli/src/webserver/build/client/assets/settings-NU_ZquhK.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/simulations-CNaMJ-nR.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/useToast-BRShB17p.js +0 -1
- package/codeyam-cli/src/webserver/build/client/cy-logo-cli.svg +0 -13
- package/codeyam-cli/src/webserver/build/client/favicon.svg +0 -13
- package/codeyam-cli/src/webserver/build/server/assets/index-DHr4rT4u.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-Bi1mj14J.js +0 -166
- package/codeyam-cli/src/webserver/public/cy-logo-cli.svg +0 -13
- package/codeyam-cli/src/webserver/public/favicon.svg +0 -13
- package/packages/ai/src/lib/generateEntityDataMap.js +0 -335
- package/packages/ai/src/lib/generateEntityDataMap.js.map +0 -1
- package/packages/ai/src/lib/promptGenerators/generateEntityDataMapGenerator.js +0 -17
- package/packages/ai/src/lib/promptGenerators/generateEntityDataMapGenerator.js.map +0 -1
|
@@ -159,10 +159,12 @@ const ROOT_SCOPE_NAME = 'root';
|
|
|
159
159
|
export let maxEquivalencyChainDepth = 0;
|
|
160
160
|
export let addToSchemaCallCount = 0;
|
|
161
161
|
export let followEquivalenciesCallCount = 0;
|
|
162
|
+
export let addEquivalencyCallCount = 0;
|
|
162
163
|
export function resetScopeDataStructureMetrics() {
|
|
163
164
|
maxEquivalencyChainDepth = 0;
|
|
164
165
|
addToSchemaCallCount = 0;
|
|
165
166
|
followEquivalenciesCallCount = 0;
|
|
167
|
+
addEquivalencyCallCount = 0;
|
|
166
168
|
}
|
|
167
169
|
|
|
168
170
|
export class ScopeDataStructure {
|
|
@@ -188,6 +190,10 @@ export class ScopeDataStructure {
|
|
|
188
190
|
private intermediatesOrderIndex: Map<string, EquivalencyDatabaseEntry> =
|
|
189
191
|
new Map();
|
|
190
192
|
private globalVisited: Set<string> = new Set();
|
|
193
|
+
// Separate visited set for addComplexSourcePathVariables - uses scope::path only (not value)
|
|
194
|
+
// This allows addComplexSourcePathVariables to run for each unique scope+path combo,
|
|
195
|
+
// while the main globalVisited uses scope+path+value for fine-grained deduplication
|
|
196
|
+
private complexSourceVisited: Set<string> = new Set();
|
|
191
197
|
|
|
192
198
|
constructor(
|
|
193
199
|
managers: EquivalencyManager[],
|
|
@@ -382,6 +388,18 @@ export class ScopeDataStructure {
|
|
|
382
388
|
traceId?: number;
|
|
383
389
|
}) {
|
|
384
390
|
addToSchemaCallCount++;
|
|
391
|
+
// DEBUG: Detect infinite loops
|
|
392
|
+
if (addToSchemaCallCount > 500000) {
|
|
393
|
+
console.error('INFINITE LOOP DETECTED in addToSchema', {
|
|
394
|
+
callCount: addToSchemaCallCount,
|
|
395
|
+
path,
|
|
396
|
+
value,
|
|
397
|
+
scopeNodeName: scopeNode?.name,
|
|
398
|
+
});
|
|
399
|
+
throw new Error(
|
|
400
|
+
`Infinite loop detected: addToSchema called ${addToSchemaCallCount} times`,
|
|
401
|
+
);
|
|
402
|
+
}
|
|
385
403
|
// Track max chain depth
|
|
386
404
|
if (equivalencyValueChain.length > maxEquivalencyChainDepth) {
|
|
387
405
|
maxEquivalencyChainDepth = equivalencyValueChain.length;
|
|
@@ -477,6 +495,7 @@ export class ScopeDataStructure {
|
|
|
477
495
|
path,
|
|
478
496
|
);
|
|
479
497
|
|
|
498
|
+
// Call addComplexSourcePathVariables like the original code (before visited check)
|
|
480
499
|
this.addComplexSourcePathVariables(
|
|
481
500
|
equivalenciesDatabaseEntry,
|
|
482
501
|
scopeNode,
|
|
@@ -708,6 +727,21 @@ export class ScopeDataStructure {
|
|
|
708
727
|
equivalencyValueChain?: EquivalencyValueChainItem[],
|
|
709
728
|
traceId?: number,
|
|
710
729
|
) {
|
|
730
|
+
// DEBUG: Detect infinite loops
|
|
731
|
+
addEquivalencyCallCount++;
|
|
732
|
+
if (addEquivalencyCallCount > 50000) {
|
|
733
|
+
console.error('INFINITE LOOP DETECTED in addEquivalency', {
|
|
734
|
+
callCount: addEquivalencyCallCount,
|
|
735
|
+
path,
|
|
736
|
+
equivalentPath,
|
|
737
|
+
equivalentScopeName,
|
|
738
|
+
scopeNodeName: scopeNode.name,
|
|
739
|
+
equivalencyReason,
|
|
740
|
+
});
|
|
741
|
+
throw new Error(
|
|
742
|
+
`Infinite loop detected: addEquivalency called ${addEquivalencyCallCount} times`,
|
|
743
|
+
);
|
|
744
|
+
}
|
|
711
745
|
// Temporary debugging to track down unnecessary equivalencies
|
|
712
746
|
if (
|
|
713
747
|
![
|
|
@@ -736,6 +770,8 @@ export class ScopeDataStructure {
|
|
|
736
770
|
'implicit parent equivalency - rerouted via useCallback', // 1 failure
|
|
737
771
|
'Spread operator equivalency key update: implicit parent equivalency', // 1 failure
|
|
738
772
|
'Array.from() equivalency',
|
|
773
|
+
'propagated sub-property equivalency',
|
|
774
|
+
'propagated function call return sub-property equivalency',
|
|
739
775
|
].includes(equivalencyReason)
|
|
740
776
|
) {
|
|
741
777
|
if (
|
|
@@ -771,13 +807,47 @@ export class ScopeDataStructure {
|
|
|
771
807
|
scopeNode.equivalencies[path] ||= [];
|
|
772
808
|
|
|
773
809
|
const existing = scopeNode.equivalencies[path];
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
810
|
+
const existingEquivalency = existing.find(
|
|
811
|
+
(v) =>
|
|
812
|
+
v.schemaPath === equivalentPath &&
|
|
813
|
+
v.scopeNodeName === equivalentScopeName,
|
|
814
|
+
);
|
|
815
|
+
if (existingEquivalency) {
|
|
816
|
+
// During Phase 2 (onlyEquivalencies=false), we need to still process the equivalency
|
|
817
|
+
// to build the chain and add to the database, even if the equivalency already exists
|
|
818
|
+
if (!this.onlyEquivalencies) {
|
|
819
|
+
const equivalentScopeNode = this.getScopeOrFunctionCallInfo(
|
|
820
|
+
equivalentScopeName,
|
|
821
|
+
) as ScopeNode;
|
|
822
|
+
if (equivalentScopeNode) {
|
|
823
|
+
// Extract function call name from path if it looks like a function call path
|
|
824
|
+
// e.g., "ChildComponent().signature[0].dataItem" -> "ChildComponent"
|
|
825
|
+
const pathMatch = path.match(/^([^().]+)\(\)/);
|
|
826
|
+
const previousPathScopeNodeName = pathMatch
|
|
827
|
+
? pathMatch[1]
|
|
828
|
+
: scopeNode.name;
|
|
829
|
+
|
|
830
|
+
this.addToSchema({
|
|
831
|
+
path: equivalentPath,
|
|
832
|
+
value: 'unknown',
|
|
833
|
+
scopeNode: equivalentScopeNode,
|
|
834
|
+
equivalencyValueChain: [
|
|
835
|
+
...(equivalencyValueChain ?? []),
|
|
836
|
+
{
|
|
837
|
+
id: existingEquivalency.id,
|
|
838
|
+
source: 'duplicate equivalency - Phase 2',
|
|
839
|
+
reason: equivalencyReason,
|
|
840
|
+
previousPath: {
|
|
841
|
+
scopeNodeName: previousPathScopeNodeName,
|
|
842
|
+
schemaPath: path,
|
|
843
|
+
value: scopeNode.schema[path],
|
|
844
|
+
},
|
|
845
|
+
},
|
|
846
|
+
],
|
|
847
|
+
traceId,
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
}
|
|
781
851
|
return;
|
|
782
852
|
}
|
|
783
853
|
|
|
@@ -1317,6 +1387,84 @@ export class ScopeDataStructure {
|
|
|
1317
1387
|
scopeNode,
|
|
1318
1388
|
'original equivalency',
|
|
1319
1389
|
);
|
|
1390
|
+
|
|
1391
|
+
// Propagate sub-property equivalencies when the equivalentValue is a simple variable
|
|
1392
|
+
// that has sub-properties defined in the isolatedEquivalentVariables.
|
|
1393
|
+
// This handles cases like: dataItem={{ structure: completeDataStructure }}
|
|
1394
|
+
// where completeDataStructure has sub-properties like completeDataStructure['Function Arguments']
|
|
1395
|
+
// We need to propagate these to create: dataItem.structure['Function Arguments'] equivalencies
|
|
1396
|
+
const isSimpleVariable =
|
|
1397
|
+
!equivalentValue.startsWith('signature[') &&
|
|
1398
|
+
!equivalentValue.includes('functionCallReturnValue') &&
|
|
1399
|
+
!equivalentValue.includes('.') &&
|
|
1400
|
+
!equivalentValue.includes('[');
|
|
1401
|
+
|
|
1402
|
+
if (isSimpleVariable) {
|
|
1403
|
+
// Look in current scope and all parent scopes for sub-properties
|
|
1404
|
+
const scopesToCheck = [scopeNode.name, ...scopeNode.tree];
|
|
1405
|
+
for (const scopeName of scopesToCheck) {
|
|
1406
|
+
const checkScope = this.scopeNodes[scopeName];
|
|
1407
|
+
if (!checkScope?.analysis?.isolatedEquivalentVariables) continue;
|
|
1408
|
+
|
|
1409
|
+
for (const [subPath, subValue] of Object.entries(
|
|
1410
|
+
checkScope.analysis.isolatedEquivalentVariables,
|
|
1411
|
+
)) {
|
|
1412
|
+
// Check if this is a sub-property of the equivalentValue variable
|
|
1413
|
+
// e.g., completeDataStructure['Function Arguments'] or completeDataStructure.foo
|
|
1414
|
+
const matchesDot = subPath.startsWith(equivalentValue + '.');
|
|
1415
|
+
const matchesBracket = subPath.startsWith(equivalentValue + '[');
|
|
1416
|
+
if (matchesDot || matchesBracket) {
|
|
1417
|
+
const subPropertyPath = subPath.substring(
|
|
1418
|
+
equivalentValue.length,
|
|
1419
|
+
);
|
|
1420
|
+
const newPath = cleanPath(path + subPropertyPath, allPaths);
|
|
1421
|
+
const newEquivalentValue = cleanPath(
|
|
1422
|
+
(subValue as string).replace(/::cyDuplicateKey\d+::/g, ''),
|
|
1423
|
+
allPaths,
|
|
1424
|
+
);
|
|
1425
|
+
|
|
1426
|
+
if (
|
|
1427
|
+
newEquivalentValue &&
|
|
1428
|
+
this.isValidPath(newEquivalentValue)
|
|
1429
|
+
) {
|
|
1430
|
+
this.addEquivalency(
|
|
1431
|
+
newPath,
|
|
1432
|
+
newEquivalentValue,
|
|
1433
|
+
checkScope.name, // Use the scope where the sub-property was found
|
|
1434
|
+
scopeNode,
|
|
1435
|
+
'propagated sub-property equivalency',
|
|
1436
|
+
);
|
|
1437
|
+
}
|
|
1438
|
+
}
|
|
1439
|
+
|
|
1440
|
+
// Also check if equivalentValue itself maps to a functionCallReturnValue
|
|
1441
|
+
// e.g., result = useMemo(...).functionCallReturnValue
|
|
1442
|
+
if (
|
|
1443
|
+
subPath === equivalentValue &&
|
|
1444
|
+
typeof subValue === 'string' &&
|
|
1445
|
+
subValue.endsWith('.functionCallReturnValue')
|
|
1446
|
+
) {
|
|
1447
|
+
this.propagateFunctionCallReturnSubProperties(
|
|
1448
|
+
path,
|
|
1449
|
+
subValue,
|
|
1450
|
+
scopeNode,
|
|
1451
|
+
allPaths,
|
|
1452
|
+
);
|
|
1453
|
+
}
|
|
1454
|
+
}
|
|
1455
|
+
}
|
|
1456
|
+
}
|
|
1457
|
+
|
|
1458
|
+
// Handle function call return values by propagating returnValue.* sub-properties
|
|
1459
|
+
// from the callback scope to the usage path
|
|
1460
|
+
if (equivalentValue.endsWith('.functionCallReturnValue')) {
|
|
1461
|
+
this.propagateFunctionCallReturnSubProperties(
|
|
1462
|
+
path,
|
|
1463
|
+
equivalentValue,
|
|
1464
|
+
scopeNode,
|
|
1465
|
+
allPaths,
|
|
1466
|
+
);
|
|
1467
|
+
}
|
|
1320
1468
|
}
|
|
1321
1469
|
}
|
|
1322
1470
|
|
|
@@ -1356,6 +1504,257 @@ export class ScopeDataStructure {
|
|
|
1356
1504
|
this.validateSchema(scopeNode, false, false);
|
|
1357
1505
|
}
|
|
1358
1506
|
|
|
1507
|
+
/**
|
|
1508
|
+
* Propagates returnValue.* sub-properties from a callback scope to the usage path.
|
|
1509
|
+
*
|
|
1510
|
+
* When we have an equivalency like:
|
|
1511
|
+
* DataItemEditor().signature[0].structure -> getData().functionCallReturnValue
|
|
1512
|
+
*
|
|
1513
|
+
* And the callback scope for getData has:
|
|
1514
|
+
* returnValue.args -> dataStructure.arguments
|
|
1515
|
+
*
|
|
1516
|
+
* This method creates the transitive equivalency:
|
|
1517
|
+
* DataItemEditor().signature[0].structure.args -> signature[0].dataStructure.arguments
|
|
1518
|
+
*
|
|
1519
|
+
* It also resolves variable references through parent scopes (e.g., dataStructure -> signature[0].dataStructure)
|
|
1520
|
+
* and ensures the database entry is updated with the usage path.
|
|
1521
|
+
*/
|
|
1522
|
+
private propagateFunctionCallReturnSubProperties(
|
|
1523
|
+
path: string,
|
|
1524
|
+
equivalentValue: string,
|
|
1525
|
+
scopeNode: ScopeNode,
|
|
1526
|
+
allPaths: string[],
|
|
1527
|
+
) {
|
|
1528
|
+
// Try to find the callback scope name from different patterns:
|
|
1529
|
+
// 1. "getData().functionCallReturnValue" → look up getData variable to find scope
|
|
1530
|
+
// 2. "useMemo(cyScope1(), [...]).functionCallReturnValue" → extract cyScope1 directly
|
|
1531
|
+
let callbackScopeName: string | undefined;
|
|
1532
|
+
|
|
1533
|
+
// Pattern 1: Simple function call like getData().functionCallReturnValue
|
|
1534
|
+
const simpleFunctionMatch = equivalentValue.match(
|
|
1535
|
+
/^(\w+)\(\)\.functionCallReturnValue$/,
|
|
1536
|
+
);
|
|
1537
|
+
if (simpleFunctionMatch) {
|
|
1538
|
+
const functionName = simpleFunctionMatch[1];
|
|
1539
|
+
// Find the function reference in current or parent scopes
|
|
1540
|
+
const scopesToCheck = [scopeNode.name, ...scopeNode.tree];
|
|
1541
|
+
for (const scopeName of scopesToCheck) {
|
|
1542
|
+
const checkScope = this.scopeNodes[scopeName];
|
|
1543
|
+
if (!checkScope?.analysis?.isolatedEquivalentVariables) continue;
|
|
1544
|
+
|
|
1545
|
+
const functionRef =
|
|
1546
|
+
checkScope.analysis.isolatedEquivalentVariables[functionName];
|
|
1547
|
+
if (typeof functionRef === 'string' && functionRef.endsWith('F')) {
|
|
1548
|
+
callbackScopeName = functionRef.slice(0, -1);
|
|
1549
|
+
break;
|
|
1550
|
+
}
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
|
|
1554
|
+
// Pattern 2: useMemo/useCallback with callback scope
|
|
1555
|
+
// e.g., "useMemo(cyScope1(), [deps]).functionCallReturnValue"
|
|
1556
|
+
if (!callbackScopeName) {
|
|
1557
|
+
const useMemoMatch = equivalentValue.match(
|
|
1558
|
+
/^useMemo\((\w+)\(\),\s*\[.*\]\)\.functionCallReturnValue$/,
|
|
1559
|
+
);
|
|
1560
|
+
if (useMemoMatch) {
|
|
1561
|
+
callbackScopeName = useMemoMatch[1];
|
|
1562
|
+
}
|
|
1563
|
+
}
|
|
1564
|
+
|
|
1565
|
+
if (!callbackScopeName) return;
|
|
1566
|
+
|
|
1567
|
+
const callbackScope = this.scopeNodes[callbackScopeName];
|
|
1568
|
+
if (!callbackScope) return;
|
|
1569
|
+
|
|
1570
|
+
// Look for returnValue.* sub-properties in the callback scope
|
|
1571
|
+
if (!callbackScope.analysis?.isolatedEquivalentVariables) return;
|
|
1572
|
+
|
|
1573
|
+
const isolatedVars = callbackScope.analysis.isolatedEquivalentVariables;
|
|
1574
|
+
|
|
1575
|
+
// First, check if returnValue is an alias to another variable (e.g., returnValue = intermediate)
|
|
1576
|
+
// If so, we need to look for that variable's sub-properties too
|
|
1577
|
+
const returnValueAlias =
|
|
1578
|
+
typeof isolatedVars.returnValue === 'string' &&
|
|
1579
|
+
!isolatedVars.returnValue.includes('.')
|
|
1580
|
+
? isolatedVars.returnValue
|
|
1581
|
+
: undefined;
|
|
1582
|
+
|
|
1583
|
+
// Pattern 3: Object.keys(X).reduce() - the reduce result has the same sub-properties as X
|
|
1584
|
+
// When returnValue = "Object.keys(source).reduce(...).functionCallReturnValue", look for source.* sub-properties
|
|
1585
|
+
let reduceSourceVar: string | undefined;
|
|
1586
|
+
if (typeof isolatedVars.returnValue === 'string') {
|
|
1587
|
+
const reduceMatch = isolatedVars.returnValue.match(
|
|
1588
|
+
/^Object\.keys\((\w+)\)\.reduce\(.*\)\.functionCallReturnValue$/,
|
|
1589
|
+
);
|
|
1590
|
+
if (reduceMatch) {
|
|
1591
|
+
reduceSourceVar = reduceMatch[1];
|
|
1592
|
+
}
|
|
1593
|
+
}
|
|
1594
|
+
|
|
1595
|
+
for (const [subPath, subValue] of Object.entries(isolatedVars)) {
|
|
1596
|
+
// Check for direct returnValue.* sub-properties
|
|
1597
|
+
const isReturnValueSub =
|
|
1598
|
+
subPath.startsWith('returnValue.') ||
|
|
1599
|
+
subPath.startsWith('returnValue[');
|
|
1600
|
+
|
|
1601
|
+
// Also check for alias.* sub-properties (e.g., intermediate.args when returnValue = intermediate)
|
|
1602
|
+
const isAliasSub =
|
|
1603
|
+
returnValueAlias &&
|
|
1604
|
+
(subPath.startsWith(returnValueAlias + '.') ||
|
|
1605
|
+
subPath.startsWith(returnValueAlias + '['));
|
|
1606
|
+
|
|
1607
|
+
// Also check for reduce source.* sub-properties (e.g., source['Function Arguments'] when returnValue = Object.keys(source).reduce())
|
|
1608
|
+
const isReduceSourceSub =
|
|
1609
|
+
reduceSourceVar &&
|
|
1610
|
+
(subPath.startsWith(reduceSourceVar + '.') ||
|
|
1611
|
+
subPath.startsWith(reduceSourceVar + '['));
|
|
1612
|
+
|
|
1613
|
+
if (
|
|
1614
|
+
typeof subValue !== 'string' ||
|
|
1615
|
+
(!isReturnValueSub && !isAliasSub && !isReduceSourceSub)
|
|
1616
|
+
)
|
|
1617
|
+
continue;
|
|
1618
|
+
|
|
1619
|
+
// Convert alias/reduceSource paths to returnValue paths
|
|
1620
|
+
let effectiveSubPath = subPath;
|
|
1621
|
+
if (isAliasSub && !isReturnValueSub) {
|
|
1622
|
+
// Replace the alias prefix with returnValue
|
|
1623
|
+
effectiveSubPath =
|
|
1624
|
+
'returnValue' + subPath.substring(returnValueAlias!.length);
|
|
1625
|
+
} else if (isReduceSourceSub && !isReturnValueSub && !isAliasSub) {
|
|
1626
|
+
// Replace the reduce source prefix with returnValue
|
|
1627
|
+
effectiveSubPath =
|
|
1628
|
+
'returnValue' + subPath.substring(reduceSourceVar!.length);
|
|
1629
|
+
}
|
|
1630
|
+
const subPropertyPath = effectiveSubPath.substring('returnValue'.length);
|
|
1631
|
+
const newPath = cleanPath(path + subPropertyPath, allPaths);
|
|
1632
|
+
let newEquivalentValue = cleanPath(
|
|
1633
|
+
subValue.replace(/::cyDuplicateKey\d+::/g, ''),
|
|
1634
|
+
allPaths,
|
|
1635
|
+
);
|
|
1636
|
+
|
|
1637
|
+
// Resolve variable references through parent scope equivalencies
|
|
1638
|
+
const resolved = this.resolveVariableThroughParentScopes(
|
|
1639
|
+
newEquivalentValue,
|
|
1640
|
+
callbackScope,
|
|
1641
|
+
allPaths,
|
|
1642
|
+
);
|
|
1643
|
+
newEquivalentValue = resolved.resolvedPath;
|
|
1644
|
+
const equivalentScopeName = resolved.scopeName;
|
|
1645
|
+
|
|
1646
|
+
if (!newEquivalentValue || !this.isValidPath(newEquivalentValue))
|
|
1647
|
+
continue;
|
|
1648
|
+
|
|
1649
|
+
this.addEquivalency(
|
|
1650
|
+
newPath,
|
|
1651
|
+
newEquivalentValue,
|
|
1652
|
+
equivalentScopeName,
|
|
1653
|
+
scopeNode,
|
|
1654
|
+
'propagated function call return sub-property equivalency',
|
|
1655
|
+
);
|
|
1656
|
+
|
|
1657
|
+
// Ensure the database entry has the usage path
|
|
1658
|
+
this.addUsageToEquivalencyDatabaseEntry(
|
|
1659
|
+
newPath,
|
|
1660
|
+
newEquivalentValue,
|
|
1661
|
+
equivalentScopeName,
|
|
1662
|
+
scopeNode.name,
|
|
1663
|
+
);
|
|
1664
|
+
}
|
|
1665
|
+
}
|
|
1666
|
+
|
|
1667
|
+
/**
|
|
1668
|
+
* Resolves a variable path through parent scope equivalencies.
|
|
1669
|
+
*
|
|
1670
|
+
* For example, if the path is "dataStructure.arguments" and the parent scope has
|
|
1671
|
+
* dataStructure -> signature[0].dataStructure, this returns:
|
|
1672
|
+
* { resolvedPath: "signature[0].dataStructure.arguments", scopeName: "ParentScope" }
|
|
1673
|
+
*/
|
|
1674
|
+
private resolveVariableThroughParentScopes(
|
|
1675
|
+
path: string | undefined,
|
|
1676
|
+
callbackScope: ScopeNode,
|
|
1677
|
+
allPaths: string[],
|
|
1678
|
+
): { resolvedPath: string | undefined; scopeName: string } {
|
|
1679
|
+
if (!path)
|
|
1680
|
+
return { resolvedPath: undefined, scopeName: callbackScope.name };
|
|
1681
|
+
|
|
1682
|
+
// Extract the root variable name
|
|
1683
|
+
const dotIndex = path.indexOf('.');
|
|
1684
|
+
const bracketIndex = path.indexOf('[');
|
|
1685
|
+
let firstDelimiter = -1;
|
|
1686
|
+
if (dotIndex > -1 && bracketIndex > -1) {
|
|
1687
|
+
firstDelimiter = Math.min(dotIndex, bracketIndex);
|
|
1688
|
+
} else {
|
|
1689
|
+
firstDelimiter = dotIndex > -1 ? dotIndex : bracketIndex;
|
|
1690
|
+
}
|
|
1691
|
+
|
|
1692
|
+
if (firstDelimiter === -1)
|
|
1693
|
+
return { resolvedPath: path, scopeName: callbackScope.name };
|
|
1694
|
+
|
|
1695
|
+
const rootVar = path.substring(0, firstDelimiter);
|
|
1696
|
+
const restOfPath = path.substring(firstDelimiter);
|
|
1697
|
+
|
|
1698
|
+
// Look in parent scopes for the root variable's equivalency
|
|
1699
|
+
for (const parentScopeName of callbackScope.tree || []) {
|
|
1700
|
+
const parentScope = this.scopeNodes[parentScopeName];
|
|
1701
|
+
if (!parentScope?.analysis?.isolatedEquivalentVariables) continue;
|
|
1702
|
+
|
|
1703
|
+
const rootEquiv =
|
|
1704
|
+
parentScope.analysis.isolatedEquivalentVariables[rootVar];
|
|
1705
|
+
if (typeof rootEquiv === 'string') {
|
|
1706
|
+
return {
|
|
1707
|
+
resolvedPath: cleanPath(rootEquiv + restOfPath, allPaths),
|
|
1708
|
+
scopeName: parentScopeName,
|
|
1709
|
+
};
|
|
1710
|
+
}
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
return { resolvedPath: path, scopeName: callbackScope.name };
|
|
1714
|
+
}
|
|
1715
|
+
|
|
1716
|
+
/**
|
|
1717
|
+
* Adds a usage path to the equivalency database entry that has the given source.
|
|
1718
|
+
*
|
|
1719
|
+
* The addEquivalency call creates the equivalency but doesn't always properly
|
|
1720
|
+
* link the usage in the database, so we need to do it explicitly.
|
|
1721
|
+
*/
|
|
1722
|
+
private addUsageToEquivalencyDatabaseEntry(
|
|
1723
|
+
usagePath: string,
|
|
1724
|
+
sourcePath: string,
|
|
1725
|
+
sourceScopeName: string,
|
|
1726
|
+
fallbackScopeName: string,
|
|
1727
|
+
) {
|
|
1728
|
+
const usageEntry = {
|
|
1729
|
+
scopeNodeName: usagePath.match(/^([^().]+)\(\)/)
|
|
1730
|
+
? (usagePath.match(/^([^().]+)\(\)/)?.[1] ?? fallbackScopeName)
|
|
1731
|
+
: fallbackScopeName,
|
|
1732
|
+
schemaPath: usagePath,
|
|
1733
|
+
};
|
|
1734
|
+
|
|
1735
|
+
const sourceKey = `${sourceScopeName}::${sourcePath}`;
|
|
1736
|
+
for (const entry of this.equivalencyDatabase) {
|
|
1737
|
+
if (
|
|
1738
|
+
entry.intermediatesOrder[sourceKey] === 0 ||
|
|
1739
|
+
entry.sourceCandidates.some(
|
|
1740
|
+
(sc) =>
|
|
1741
|
+
sc.scopeNodeName === sourceScopeName &&
|
|
1742
|
+
sc.schemaPath === sourcePath,
|
|
1743
|
+
)
|
|
1744
|
+
) {
|
|
1745
|
+
const usageExists = entry.usages.some(
|
|
1746
|
+
(u) =>
|
|
1747
|
+
u.scopeNodeName === usageEntry.scopeNodeName &&
|
|
1748
|
+
u.schemaPath === usageEntry.schemaPath,
|
|
1749
|
+
);
|
|
1750
|
+
if (!usageExists) {
|
|
1751
|
+
entry.usages.push(usageEntry);
|
|
1752
|
+
}
|
|
1753
|
+
break;
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1756
|
+
}
|
|
1757
|
+
|
|
1359
1758
|
private checkForArrayItemPath(
|
|
1360
1759
|
pathParts: string[],
|
|
1361
1760
|
scopeNode: ScopeNode,
|
|
@@ -1635,6 +2034,14 @@ export class ScopeDataStructure {
|
|
|
1635
2034
|
usageEquivalency.scopeNodeName,
|
|
1636
2035
|
) as ScopeNode;
|
|
1637
2036
|
|
|
2037
|
+
// Guard against infinite recursion by tracking which paths we've already
|
|
2038
|
+
// added from addComplexSourcePathVariables
|
|
2039
|
+
const complexPathKey = `${usageScopeNode.name}::${newUsageEquivalentPath}`;
|
|
2040
|
+
if (this.complexSourceVisited.has(complexPathKey)) {
|
|
2041
|
+
continue;
|
|
2042
|
+
}
|
|
2043
|
+
this.complexSourceVisited.add(complexPathKey);
|
|
2044
|
+
|
|
1638
2045
|
this.addToSchema({
|
|
1639
2046
|
path: newUsageEquivalentPath,
|
|
1640
2047
|
value: 'unknown',
|
|
@@ -1785,6 +2192,7 @@ export class ScopeDataStructure {
|
|
|
1785
2192
|
|
|
1786
2193
|
for (let i = 0; i < cleanEquivalencyValueChain.length; ++i) {
|
|
1787
2194
|
const pathInfo = cleanEquivalencyValueChain[i].currentPath;
|
|
2195
|
+
const previousPath = cleanEquivalencyValueChain[i].previousPath;
|
|
1788
2196
|
|
|
1789
2197
|
const schemaPathParts = this.splitPath(pathInfo.schemaPath);
|
|
1790
2198
|
const isSignaturePath =
|
|
@@ -1798,6 +2206,21 @@ export class ScopeDataStructure {
|
|
|
1798
2206
|
databaseEntry.usages.push(pathInfo);
|
|
1799
2207
|
}
|
|
1800
2208
|
|
|
2209
|
+
// Also add previousPath as a usage if it matches the criteria
|
|
2210
|
+
// This handles propagated sub-property equivalencies where the JSX prop path
|
|
2211
|
+
// is in previousPath and should be tracked as a usage
|
|
2212
|
+
if (previousPath) {
|
|
2213
|
+
const prevSchemaPathParts = this.splitPath(previousPath.schemaPath);
|
|
2214
|
+
const isPrevSignaturePath =
|
|
2215
|
+
prevSchemaPathParts.findIndex((p) => p.startsWith('signature[')) > 0;
|
|
2216
|
+
if (
|
|
2217
|
+
prevSchemaPathParts[0].startsWith('returnValue') ||
|
|
2218
|
+
isPrevSignaturePath
|
|
2219
|
+
) {
|
|
2220
|
+
databaseEntry.usages.push(previousPath);
|
|
2221
|
+
}
|
|
2222
|
+
}
|
|
2223
|
+
|
|
1801
2224
|
const pathId = this.uniqueId(pathInfo);
|
|
1802
2225
|
let intermediateIndex = cleanEquivalencyValueChain.length - i - 1;
|
|
1803
2226
|
const existingIntermediateIndex =
|
package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts
CHANGED
|
@@ -408,17 +408,26 @@ function checkIfObjectOrFunction(path: string, schema: ScopeNode['schema']) {
|
|
|
408
408
|
}
|
|
409
409
|
}
|
|
410
410
|
|
|
411
|
-
// Methods that are ambiguous - used on both arrays and non-arrays
|
|
411
|
+
// Methods that are ambiguous - used on both arrays and non-arrays
|
|
412
|
+
// These methods exist on arrays but also on Map, Set, Headers, FormData, URLSearchParams, etc.
|
|
412
413
|
// Don't infer array type from these alone without additional evidence
|
|
413
|
-
const AMBIGUOUS_ARRAY_METHODS = new Set([
|
|
414
|
+
const AMBIGUOUS_ARRAY_METHODS = new Set([
|
|
415
|
+
'push',
|
|
416
|
+
'pop',
|
|
417
|
+
'entries',
|
|
418
|
+
'keys',
|
|
419
|
+
'values',
|
|
420
|
+
'forEach',
|
|
421
|
+
]);
|
|
414
422
|
|
|
415
423
|
// Methods that are strongly indicative of arrays - only arrays have these
|
|
424
|
+
// Note: entries, keys, values, forEach are NOT in this list because they also exist
|
|
425
|
+
// on Map, Set, Headers, FormData, URLSearchParams, and other iterable types
|
|
416
426
|
const STRONG_ARRAY_METHODS = new Set([
|
|
417
427
|
'map',
|
|
418
428
|
'filter',
|
|
419
429
|
'reduce',
|
|
420
430
|
'reduceRight',
|
|
421
|
-
'forEach',
|
|
422
431
|
'every',
|
|
423
432
|
'some',
|
|
424
433
|
'find',
|
|
@@ -429,9 +438,6 @@ const STRONG_ARRAY_METHODS = new Set([
|
|
|
429
438
|
'flatMap',
|
|
430
439
|
'fill',
|
|
431
440
|
'copyWithin',
|
|
432
|
-
'entries',
|
|
433
|
-
'keys',
|
|
434
|
-
'values',
|
|
435
441
|
'toReversed',
|
|
436
442
|
'toSorted',
|
|
437
443
|
'toSpliced',
|
|
@@ -25,8 +25,7 @@ export default async function generateChangesEntityDocumentation({
|
|
|
25
25
|
|
|
26
26
|
const { completion: documentation, stats } = await completionCall({
|
|
27
27
|
type: 'entityDocumentation',
|
|
28
|
-
systemMessage:
|
|
29
|
-
'You are an expert coder and educator. You think a lot about how people can understand new things, recognizing that it is a mixture of direct facts and numerous examples from different perspectives.',
|
|
28
|
+
systemMessage: SYSTEM_MESSAGE,
|
|
30
29
|
prompt,
|
|
31
30
|
model,
|
|
32
31
|
jsonResponse: false,
|
|
@@ -62,3 +61,22 @@ export default async function generateChangesEntityDocumentation({
|
|
|
62
61
|
|
|
63
62
|
return { documentation, llmCall };
|
|
64
63
|
}
|
|
64
|
+
|
|
65
|
+
const SYSTEM_MESSAGE = `You are a technical documentation writer updating existing documentation after code changes.
|
|
66
|
+
|
|
67
|
+
## When to Update
|
|
68
|
+
- If existing documentation is still accurate: respond with exactly "No changes needed"
|
|
69
|
+
- If code changed significantly: provide updated documentation
|
|
70
|
+
|
|
71
|
+
## Style
|
|
72
|
+
- Be concise—use bullets, not paragraphs
|
|
73
|
+
- Provide diverse examples (no repetitive variations)
|
|
74
|
+
- In Overview, describe intent directly without mentioning the function name
|
|
75
|
+
|
|
76
|
+
## Required Sections (when updating)
|
|
77
|
+
Return documentation with exactly these markdown headers:
|
|
78
|
+
- ## Overview
|
|
79
|
+
- ## Inputs
|
|
80
|
+
- ## Output
|
|
81
|
+
- ## Examples
|
|
82
|
+
`;
|