@codeyam/codeyam-cli 0.1.0-staging.1669d45 → 0.1.0-staging.2a88920
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 +8 -8
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +5 -5
- package/analyzer-template/packages/ai/index.ts +15 -2
- package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +87 -51
- package/analyzer-template/packages/ai/src/lib/astScopes/arrayDerivationDetector.ts +199 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +98 -9
- package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +139 -23
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.ts +6 -126
- package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +555 -28
- package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +88 -7
- package/analyzer-template/packages/ai/src/lib/completionCall.ts +198 -34
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +772 -243
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.ts +205 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.ts +10 -2
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.ts +16 -3
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.ts +6 -4
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.ts +43 -1
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +122 -15
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.ts +160 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.ts +40 -30
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.ts +319 -88
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.ts +129 -0
- package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +156 -0
- package/analyzer-template/packages/ai/src/lib/e2eDataTracking.ts +334 -0
- package/analyzer-template/packages/ai/src/lib/extractCriticalDataKeys.ts +120 -0
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +642 -7
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +35 -6
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +383 -6
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.ts +1 -1
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +1299 -51
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.ts +239 -0
- package/analyzer-template/packages/ai/src/lib/mergeStatements.ts +90 -96
- package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +10 -7
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChunkPrompt.ts +82 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateCriticalKeysPrompt.ts +103 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +23 -6
- package/analyzer-template/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.ts +391 -0
- package/analyzer-template/packages/ai/src/lib/resolvePathToControllable.ts +179 -45
- package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +26 -4
- package/analyzer-template/packages/ai/src/lib/worker/analyzeScopeWorker.ts +114 -2
- package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +65 -59
- package/analyzer-template/packages/analyze/src/lib/ProjectAnalyzer.ts +113 -26
- package/analyzer-template/packages/analyze/src/lib/analysisContext.ts +44 -4
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.ts +19 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.ts +19 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getAllExports.ts +11 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.ts +8 -0
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.ts +49 -1
- package/analyzer-template/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.ts +2 -1
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.ts +30 -19
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +14 -4
- package/analyzer-template/packages/analyze/src/lib/files/analyze/dependencyResolver.ts +6 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +4 -2
- package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +33 -10
- package/analyzer-template/packages/analyze/src/lib/files/analyzeRemixRoute.ts +4 -5
- package/analyzer-template/packages/analyze/src/lib/files/getImportedExports.ts +14 -12
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +189 -76
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +29 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +77 -9
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +118 -10
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +276 -17
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.ts +56 -11
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/propagateArrayItemSchemas.ts +474 -0
- package/analyzer-template/packages/analyze/src/lib/files/setImportedExports.ts +2 -1
- package/analyzer-template/packages/analyze/src/lib/utils/getFileByPath.ts +19 -0
- package/analyzer-template/packages/aws/package.json +2 -2
- package/analyzer-template/packages/database/src/lib/kysely/db.ts +8 -1
- package/analyzer-template/packages/database/src/lib/kysely/tables/commitsTable.ts +6 -0
- package/analyzer-template/packages/database/src/lib/loadAnalyses.ts +58 -1
- package/analyzer-template/packages/database/src/lib/loadAnalysis.ts +13 -0
- package/analyzer-template/packages/database/src/lib/loadBranch.ts +16 -1
- package/analyzer-template/packages/database/src/lib/loadCommit.ts +11 -0
- package/analyzer-template/packages/database/src/lib/loadCommits.ts +28 -0
- package/analyzer-template/packages/database/src/lib/loadEntities.ts +26 -3
- package/analyzer-template/packages/database/src/lib/loadEntityBranches.ts +12 -0
- package/analyzer-template/packages/database/src/lib/updateCommitMetadata.ts +7 -14
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js +8 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts +1 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js +3 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts +2 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js +45 -2
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalyses.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js +8 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadAnalysis.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js +11 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadBranch.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js +7 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommit.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts +3 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js +22 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadCommits.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts +3 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js +23 -4
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntities.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js +9 -0
- package/analyzer-template/packages/github/dist/database/src/lib/loadEntityBranches.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts +2 -2
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js +5 -4
- package/analyzer-template/packages/github/dist/database/src/lib/updateCommitMetadata.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/index.d.ts +1 -1
- package/analyzer-template/packages/github/dist/types/index.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/index.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts +25 -1
- package/analyzer-template/packages/github/dist/types/src/types/Analysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts +2 -0
- package/analyzer-template/packages/github/dist/types/src/types/Commit.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
- package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts +9 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js +29 -3
- package/analyzer-template/packages/github/dist/utils/src/lib/safeFileName.js.map +1 -1
- package/analyzer-template/packages/github/package.json +1 -1
- package/analyzer-template/packages/types/index.ts +1 -0
- package/analyzer-template/packages/types/src/types/Analysis.ts +25 -0
- package/analyzer-template/packages/types/src/types/Commit.ts +2 -0
- package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +70 -6
- package/analyzer-template/packages/types/src/types/ScopeAnalysis.ts +6 -1
- package/analyzer-template/packages/utils/dist/types/index.d.ts +1 -1
- package/analyzer-template/packages/utils/dist/types/index.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/index.js.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts +25 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Analysis.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts +2 -0
- package/analyzer-template/packages/utils/dist/types/src/types/Commit.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +56 -6
- package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts +6 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScopeAnalysis.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts +9 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js +29 -3
- package/analyzer-template/packages/utils/dist/utils/src/lib/safeFileName.js.map +1 -1
- package/analyzer-template/packages/utils/src/lib/safeFileName.ts +48 -3
- package/analyzer-template/playwright/capture.ts +20 -8
- package/analyzer-template/playwright/captureStatic.ts +1 -1
- package/analyzer-template/project/analyzeBaselineCommit.ts +5 -0
- package/analyzer-template/project/analyzeRegularCommit.ts +5 -0
- package/analyzer-template/project/captureLibraryFunctionDirect.ts +29 -26
- package/analyzer-template/project/constructMockCode.ts +367 -37
- package/analyzer-template/project/createEntitiesAndSortFiles.ts +83 -0
- package/analyzer-template/project/loadReadyToBeCaptured.ts +65 -41
- package/analyzer-template/project/orchestrateCapture/AwsCaptureTaskRunner.ts +12 -4
- package/analyzer-template/project/orchestrateCapture/SequentialCaptureTaskRunner.ts +18 -7
- package/analyzer-template/project/orchestrateCapture/taskRunner.ts +4 -2
- package/analyzer-template/project/orchestrateCapture.ts +71 -6
- package/analyzer-template/project/reconcileMockDataKeys.ts +152 -9
- package/analyzer-template/project/runAnalysis.ts +4 -0
- package/analyzer-template/project/start.ts +35 -11
- package/analyzer-template/project/writeMockDataTsx.ts +127 -4
- package/analyzer-template/project/writeScenarioComponents.ts +101 -8
- package/analyzer-template/scripts/comboWorkerLoop.cjs +98 -50
- package/background/src/lib/virtualized/project/analyzeBaselineCommit.js +5 -0
- package/background/src/lib/virtualized/project/analyzeBaselineCommit.js.map +1 -1
- package/background/src/lib/virtualized/project/analyzeRegularCommit.js +5 -0
- package/background/src/lib/virtualized/project/analyzeRegularCommit.js.map +1 -1
- package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js +3 -3
- package/background/src/lib/virtualized/project/captureLibraryFunctionDirect.js.map +1 -1
- package/background/src/lib/virtualized/project/constructMockCode.js +300 -7
- package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
- package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js +73 -1
- package/background/src/lib/virtualized/project/createEntitiesAndSortFiles.js.map +1 -1
- package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js +19 -8
- package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js +2 -2
- package/background/src/lib/virtualized/project/orchestrateCapture/AwsCaptureTaskRunner.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js +7 -5
- package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture.js +58 -6
- package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
- package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +126 -9
- package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
- package/background/src/lib/virtualized/project/runAnalysis.js +3 -0
- package/background/src/lib/virtualized/project/runAnalysis.js.map +1 -1
- package/background/src/lib/virtualized/project/start.js +32 -11
- package/background/src/lib/virtualized/project/start.js.map +1 -1
- package/background/src/lib/virtualized/project/writeMockDataTsx.js +101 -4
- package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
- package/background/src/lib/virtualized/project/writeScenarioComponents.js +57 -8
- package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
- package/codeyam-cli/src/cli.js +2 -0
- package/codeyam-cli/src/cli.js.map +1 -1
- package/codeyam-cli/src/commands/debug.js +7 -5
- package/codeyam-cli/src/commands/debug.js.map +1 -1
- package/codeyam-cli/src/commands/memory.js +273 -0
- package/codeyam-cli/src/commands/memory.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +4 -0
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
- package/codeyam-cli/src/utils/analysisRunner.js +21 -2
- package/codeyam-cli/src/utils/analysisRunner.js.map +1 -1
- package/codeyam-cli/src/utils/install-skills.js +42 -6
- package/codeyam-cli/src/utils/install-skills.js.map +1 -1
- package/codeyam-cli/src/utils/queue/job.js +1 -0
- package/codeyam-cli/src/utils/queue/job.js.map +1 -1
- package/codeyam-cli/src/utils/queue/manager.js +6 -0
- package/codeyam-cli/src/utils/queue/manager.js.map +1 -1
- package/codeyam-cli/src/utils/rules/index.js +5 -0
- package/codeyam-cli/src/utils/rules/index.js.map +1 -0
- package/codeyam-cli/src/utils/rules/parser.js +106 -0
- package/codeyam-cli/src/utils/rules/parser.js.map +1 -0
- package/codeyam-cli/src/utils/rules/pathMatcher.js +18 -0
- package/codeyam-cli/src/utils/rules/pathMatcher.js.map +1 -0
- package/codeyam-cli/src/utils/rules/staleness.js +132 -0
- package/codeyam-cli/src/utils/rules/staleness.js.map +1 -0
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +2 -0
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/database.js +7 -3
- package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
- package/codeyam-cli/src/webserver/bootstrap.js +40 -0
- package/codeyam-cli/src/webserver/bootstrap.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityItem-DsN1wKrm.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-COi5OvsN.js → EntityTypeBadge-DLqD3qNt.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-BwdQv49w.js → EntityTypeIcon-Ba2JVPzP.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-CEleMv_j.js → InlineSpinner-C8lyxW9k.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-D68KarMg.js → InteractivePreview-aht4aafF.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-L75Wvqgw.js → LibraryFunctionPreview-CVtiBnY5.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-C53WM8qn.js → LoadingDots-B0GLXMsr.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-CrNkmy4i.js → LogViewer-xgeCVgSM.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-OApQuNyq.js +16 -0
- package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-CQifa1n-.js → SafeScreenshot-DuDvi0jm.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-CyaBFX7l.js → ScenarioViewer-DzccYyI8.js} +3 -13
- package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-D36O1rzU.js → TruncatedFilePath-DyFZkK0l.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/_index-BwqWJOgH.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-BwavGCpm.js +32 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.health-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.memory-profile-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.restart-server-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-DgTPh8H-.js → chevron-down-Cx24_aWc.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chunk-EPOLDU6W-DdQKK6on.js → chunk-EPOLDU6W-CXRTFQ3F.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{circle-check-Dmr2bb1R.js → circle-check-BOARzkeR.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/copy-Bb-80kDT.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-Do4ZLUYa.js → createLucideIcon-BdhJEx6B.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-BBnGWYga.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-CbdFyxZh.js → entity._sha._-BJUiQqZF.js} +12 -12
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-B4iCfs5M.js → entity._sha.scenarios._scenarioId.fullscreen-DavjRmOY.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-wDWZZO1W.js → entity._sha_.create-scenario-D1T4TGjf.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-BMbl7MeQ.js → entity._sha_.edit._scenarioId-CTBG2mmz.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entry.client-5wRKRIH9.js → entry.client-CS2cb_eZ.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/file-code-Dhef1kWN.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DD3SDH7t.js → fileTableUtils-DMJ7zii9.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/files-CJ6lTdTA.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{git-zXjT7J0G.js → git-CPTZZ-JZ.js} +8 -8
- package/codeyam-cli/src/webserver/build/client/assets/globals-D3yhhV8x.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{index-DLbXwndH.js → index-B1h680n5.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-gPZ-lad1.js → index-lzqtyFU8.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-BsPXJ81F.js → loader-circle-B7B9V-bu.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-a78b90a2.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/memory--GCbFsBE.js +92 -0
- package/codeyam-cli/src/webserver/build/client/assets/root-eVAaavTS.js +62 -0
- package/codeyam-cli/src/webserver/build/client/assets/{search-P2FKIUql.js → search-CxXUmBSd.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{settings-B2eDuBj8.js → settings-CS5f3WzT.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{simulations-L18M6-kN.js → simulations-DwFIBT09.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-BDz7kbVA.js → triangle-alert-B6LgvRJg.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-29dDmbH8.js → useCustomSizes-C1v1PQzo.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-BUm0UVJm.js → useLastLogLine-aSv48UbS.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-CkIOKTrZ.js → useReportContext-DYxHZQuP.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useToast-KKw5kTn-.js → useToast-mBRpZPiu.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/index-BM6TDT1Y.js +1 -0
- package/codeyam-cli/src/webserver/build/server/assets/server-build-dYC34MHw.js +257 -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/templates/codeyam-memory-hook.sh +200 -0
- package/codeyam-cli/templates/codeyam:debug.md +47 -3
- package/codeyam-cli/templates/codeyam:diagnose.md +203 -25
- package/codeyam-cli/templates/codeyam:memory.md +341 -0
- package/codeyam-cli/templates/codeyam:new-rule.md +13 -0
- package/codeyam-cli/templates/rule-reflection-hook.py +160 -0
- package/codeyam-cli/templates/rules-instructions.md +93 -0
- package/package.json +8 -5
- package/packages/ai/index.js +7 -3
- package/packages/ai/index.js.map +1 -1
- package/packages/ai/src/lib/analyzeScope.js +70 -29
- package/packages/ai/src/lib/analyzeScope.js.map +1 -1
- package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js +150 -0
- package/packages/ai/src/lib/astScopes/arrayDerivationDetector.js.map +1 -0
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +78 -8
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
- package/packages/ai/src/lib/astScopes/methodSemantics.js +109 -23
- package/packages/ai/src/lib/astScopes/methodSemantics.js.map +1 -1
- package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js +1 -102
- package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js.map +1 -1
- package/packages/ai/src/lib/astScopes/processExpression.js +440 -27
- package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
- package/packages/ai/src/lib/completionCall.js +161 -30
- package/packages/ai/src/lib/completionCall.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +589 -166
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js +179 -0
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +7 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js +13 -3
- package/packages/ai/src/lib/dataStructure/helpers/BatchSchemaProcessor.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js +6 -4
- package/packages/ai/src/lib/dataStructure/helpers/ScopeTreeManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js +41 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +104 -11
- package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js +159 -0
- package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js.map +1 -0
- package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js +37 -20
- package/packages/ai/src/lib/dataStructure/helpers/deduplicateFunctionSchemas.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js +265 -79
- package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js +107 -0
- package/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.js.map +1 -0
- package/packages/ai/src/lib/dataStructureChunking.js +111 -0
- package/packages/ai/src/lib/dataStructureChunking.js.map +1 -0
- package/packages/ai/src/lib/e2eDataTracking.js +241 -0
- package/packages/ai/src/lib/e2eDataTracking.js.map +1 -0
- package/packages/ai/src/lib/extractCriticalDataKeys.js +96 -0
- package/packages/ai/src/lib/extractCriticalDataKeys.js.map +1 -0
- package/packages/ai/src/lib/generateEntityScenarioData.js +525 -8
- package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarios.js +26 -2
- package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlows.js +281 -4
- package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +946 -42
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js +194 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js.map +1 -0
- package/packages/ai/src/lib/mergeStatements.js +70 -51
- package/packages/ai/src/lib/mergeStatements.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js +10 -4
- package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js +54 -0
- package/packages/ai/src/lib/promptGenerators/generateChunkPrompt.js.map +1 -0
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js +15 -7
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js +335 -0
- package/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.js.map +1 -0
- package/packages/ai/src/lib/resolvePathToControllable.js +155 -41
- package/packages/ai/src/lib/resolvePathToControllable.js.map +1 -1
- package/packages/ai/src/lib/worker/SerializableDataStructure.js +7 -0
- package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
- package/packages/ai/src/lib/worker/analyzeScopeWorker.js +94 -1
- package/packages/ai/src/lib/worker/analyzeScopeWorker.js.map +1 -1
- package/packages/analyze/src/lib/FileAnalyzer.js +60 -36
- package/packages/analyze/src/lib/FileAnalyzer.js.map +1 -1
- package/packages/analyze/src/lib/ProjectAnalyzer.js +96 -26
- package/packages/analyze/src/lib/ProjectAnalyzer.js.map +1 -1
- package/packages/analyze/src/lib/analysisContext.js +30 -5
- package/packages/analyze/src/lib/analysisContext.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js +14 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getAllDeclaredEntityNodes.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js +14 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getAllEntityNodes.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js +6 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getAllExports.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js +6 -0
- package/packages/analyze/src/lib/asts/sourceFiles/getImportsAnalysis.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js +39 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getResolvedModule.js.map +1 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js +2 -1
- package/packages/analyze/src/lib/asts/sourceFiles/getSourceFilesForAllImports.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js +21 -9
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +14 -4
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/dependencyResolver.js +5 -0
- package/packages/analyze/src/lib/files/analyze/dependencyResolver.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js +2 -1
- package/packages/analyze/src/lib/files/analyze/gatherEntityMap.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js +31 -10
- package/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeRemixRoute.js +3 -2
- package/packages/analyze/src/lib/files/analyzeRemixRoute.js.map +1 -1
- package/packages/analyze/src/lib/files/getImportedExports.js +11 -7
- package/packages/analyze/src/lib/files/getImportedExports.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +160 -68
- package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +25 -8
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +71 -9
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +57 -9
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +233 -9
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js +46 -9
- package/packages/analyze/src/lib/files/scenarios/mergeValidatedDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/setImportedExports.js +2 -1
- package/packages/analyze/src/lib/files/setImportedExports.js.map +1 -1
- package/packages/analyze/src/lib/utils/getFileByPath.js +12 -0
- package/packages/analyze/src/lib/utils/getFileByPath.js.map +1 -0
- package/packages/database/src/lib/kysely/db.js +8 -1
- package/packages/database/src/lib/kysely/db.js.map +1 -1
- package/packages/database/src/lib/kysely/tables/commitsTable.js +3 -0
- package/packages/database/src/lib/kysely/tables/commitsTable.js.map +1 -1
- package/packages/database/src/lib/loadAnalyses.js +45 -2
- package/packages/database/src/lib/loadAnalyses.js.map +1 -1
- package/packages/database/src/lib/loadAnalysis.js +8 -0
- package/packages/database/src/lib/loadAnalysis.js.map +1 -1
- package/packages/database/src/lib/loadBranch.js +11 -1
- package/packages/database/src/lib/loadBranch.js.map +1 -1
- package/packages/database/src/lib/loadCommit.js +7 -0
- package/packages/database/src/lib/loadCommit.js.map +1 -1
- package/packages/database/src/lib/loadCommits.js +22 -1
- package/packages/database/src/lib/loadCommits.js.map +1 -1
- package/packages/database/src/lib/loadEntities.js +23 -4
- package/packages/database/src/lib/loadEntities.js.map +1 -1
- package/packages/database/src/lib/loadEntityBranches.js +9 -0
- package/packages/database/src/lib/loadEntityBranches.js.map +1 -1
- package/packages/database/src/lib/updateCommitMetadata.js +5 -4
- package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
- package/packages/types/index.js.map +1 -1
- package/packages/utils/src/lib/safeFileName.js +29 -3
- package/packages/utils/src/lib/safeFileName.js.map +1 -1
- package/scripts/finalize-analyzer.cjs +3 -3
- package/codeyam-cli/src/webserver/build/client/assets/EntityItem-vauWK972.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-DzJRkCkr.js +0 -11
- package/codeyam-cli/src/webserver/build/client/assets/_index-Be83mo_j.js +0 -11
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-BN6wu6Y-.js +0 -37
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-Bn6aCAy_.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/files-DKyMFI90.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-DTTQ3gY7.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-22590fcf.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/root-BsAarjAM.js +0 -57
- package/codeyam-cli/src/webserver/build/server/assets/index-BND5I5fv.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-CFXnd7MG.js +0 -228
|
@@ -6,6 +6,85 @@ import { methodRegistry, ArrayPushSemantics } from "./methodSemantics.js";
|
|
|
6
6
|
import { isArithmeticOperator, isAssignmentOperator, isBitwiseCompoundOperator, isComparisonOperator, isDefinedType, isNumericCompoundOperator, leftOrRightType, unwrapExpression, } from "./sharedPatterns.js";
|
|
7
7
|
import { processBindingPattern } from "./processBindings.js";
|
|
8
8
|
import { extractConditionalEffectsFromTernary, findUseStateSetters, } from "./conditionalEffectsExtractor.js";
|
|
9
|
+
import { detectArrayDerivedPattern } from "./arrayDerivationDetector.js";
|
|
10
|
+
/**
|
|
11
|
+
* Checks if a JSX element has props that reference variables from the parent scope.
|
|
12
|
+
* This is used to detect unconditionally-rendered children that should have their
|
|
13
|
+
* execution flows merged into the parent.
|
|
14
|
+
*
|
|
15
|
+
* We want to track children where the parent controls data that affects the child's
|
|
16
|
+
* conditional rendering. Static props (like title="Dashboard") don't need tracking
|
|
17
|
+
* because they don't create variable execution flows.
|
|
18
|
+
*
|
|
19
|
+
* Examples:
|
|
20
|
+
* - <WorkoutsView workouts={workouts} /> → true (workouts is a variable)
|
|
21
|
+
* - <ItemList items={items} count={count} /> → true (items, count are variables)
|
|
22
|
+
* - <Header title="Dashboard" /> → false (static string)
|
|
23
|
+
* - <Footer /> → false (no props)
|
|
24
|
+
* - <Button onClick={handleClick} /> → false (only callback, no data props)
|
|
25
|
+
*
|
|
26
|
+
* @returns true if the component has at least one prop that references a variable
|
|
27
|
+
* (excluding callbacks which typically start with 'on' or 'handle')
|
|
28
|
+
*/
|
|
29
|
+
function hasDataPropsFromParent(node, componentName) {
|
|
30
|
+
const attributes = ts.isJsxElement(node)
|
|
31
|
+
? node.openingElement.attributes.properties
|
|
32
|
+
: node.attributes.properties;
|
|
33
|
+
const dataProps = [];
|
|
34
|
+
for (const attr of attributes) {
|
|
35
|
+
// Spread attributes always reference parent data: {...props}
|
|
36
|
+
if (ts.isJsxSpreadAttribute(attr)) {
|
|
37
|
+
const spreadText = attr.expression?.getText() || '...spread';
|
|
38
|
+
dataProps.push(`{...${spreadText}}`);
|
|
39
|
+
console.log(`[UnconditionalChild] ${componentName}: Found spread attribute {${spreadText}}`);
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (ts.isJsxAttribute(attr)) {
|
|
43
|
+
const propName = attr.name.getText();
|
|
44
|
+
// Skip callback props - they don't create data-driven execution flows
|
|
45
|
+
// Callbacks typically start with 'on' (onClick, onChange) or 'handle' (handleSubmit)
|
|
46
|
+
if (propName.startsWith('on') ||
|
|
47
|
+
propName.startsWith('handle') ||
|
|
48
|
+
propName === 'ref') {
|
|
49
|
+
console.log(`[UnconditionalChild] ${componentName}: Skipping callback prop '${propName}'`);
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
// Check if the prop value is a JSX expression (references a variable)
|
|
53
|
+
// vs a string literal which is static
|
|
54
|
+
if (attr.initializer) {
|
|
55
|
+
if (ts.isJsxExpression(attr.initializer)) {
|
|
56
|
+
// JSX expression like prop={value} - this references a variable
|
|
57
|
+
// Could be a simple identifier, property access, or more complex expression
|
|
58
|
+
const expression = attr.initializer.expression;
|
|
59
|
+
if (expression) {
|
|
60
|
+
// Skip if it's just a function/arrow function (callback)
|
|
61
|
+
if (ts.isArrowFunction(expression) ||
|
|
62
|
+
ts.isFunctionExpression(expression)) {
|
|
63
|
+
console.log(`[UnconditionalChild] ${componentName}: Skipping inline callback prop '${propName}'`);
|
|
64
|
+
continue;
|
|
65
|
+
}
|
|
66
|
+
// This is a data prop that references parent state/props
|
|
67
|
+
const exprText = expression.getText();
|
|
68
|
+
dataProps.push(`${propName}={${exprText}}`);
|
|
69
|
+
console.log(`[UnconditionalChild] ${componentName}: Found data prop '${propName}' = {${exprText}}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// String literals like prop="value" are static
|
|
74
|
+
console.log(`[UnconditionalChild] ${componentName}: Skipping static prop '${propName}'`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
const hasDataProps = dataProps.length > 0;
|
|
80
|
+
if (hasDataProps) {
|
|
81
|
+
console.log(`[UnconditionalChild] ${componentName}: Has ${dataProps.length} data props: [${dataProps.join(', ')}]`);
|
|
82
|
+
}
|
|
83
|
+
else {
|
|
84
|
+
console.log(`[UnconditionalChild] ${componentName}: No data props found, will NOT track`);
|
|
85
|
+
}
|
|
86
|
+
return { hasDataProps, dataProps };
|
|
87
|
+
}
|
|
9
88
|
/**
|
|
10
89
|
* Extracts the component name from a JSX element.
|
|
11
90
|
* Returns null for intrinsic elements (div, span, etc.) since we only care about
|
|
@@ -273,6 +352,123 @@ function getSourceLocation(node, sourceFile) {
|
|
|
273
352
|
: codeSnippet,
|
|
274
353
|
};
|
|
275
354
|
}
|
|
355
|
+
/**
|
|
356
|
+
* Extracts the root array path from an expression that ends with .map().
|
|
357
|
+
* Handles chained methods like .filter().map(), .slice().map(), etc.
|
|
358
|
+
*
|
|
359
|
+
* Examples:
|
|
360
|
+
* - items.map(...) → "items"
|
|
361
|
+
* - data.users.map(...) → "data.users"
|
|
362
|
+
* - items.filter(...).map(...) → "items"
|
|
363
|
+
* - items.slice(0, 5).map(...) → "items"
|
|
364
|
+
*/
|
|
365
|
+
function extractArrayPathFromMapCall(expr, sourceFile) {
|
|
366
|
+
// Walk up the chain to find the root array
|
|
367
|
+
let current = expr.expression;
|
|
368
|
+
while (ts.isPropertyAccessExpression(current)) {
|
|
369
|
+
const methodName = current.name.getText(sourceFile);
|
|
370
|
+
// Common array methods that return arrays (so we keep going up)
|
|
371
|
+
const arrayReturningMethods = [
|
|
372
|
+
'map',
|
|
373
|
+
'filter',
|
|
374
|
+
'slice',
|
|
375
|
+
'concat',
|
|
376
|
+
'flat',
|
|
377
|
+
'flatMap',
|
|
378
|
+
'reverse',
|
|
379
|
+
'sort',
|
|
380
|
+
'toReversed',
|
|
381
|
+
'toSorted',
|
|
382
|
+
'toSpliced',
|
|
383
|
+
];
|
|
384
|
+
if (arrayReturningMethods.includes(methodName)) {
|
|
385
|
+
const objectExpr = current.expression;
|
|
386
|
+
// If the object is a call expression (chained method), keep going
|
|
387
|
+
if (ts.isCallExpression(objectExpr)) {
|
|
388
|
+
current = objectExpr.expression;
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
// Found the root - it's an identifier or property access
|
|
392
|
+
const path = StructuredPath.fromNode(objectExpr, sourceFile);
|
|
393
|
+
return path ? path.toString() : null;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
else {
|
|
397
|
+
// Not an array method we recognize
|
|
398
|
+
break;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return null;
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Extracts JSX rendering usages from a JSX expression.
|
|
405
|
+
* Detects:
|
|
406
|
+
* - array.map() calls → 'array-map' type
|
|
407
|
+
* - string interpolations (identifiers/property access) → 'text-interpolation' type
|
|
408
|
+
*
|
|
409
|
+
* Recursively searches inside && chains and ternary expressions.
|
|
410
|
+
*
|
|
411
|
+
* @param expr The expression inside {expr}
|
|
412
|
+
* @param context The analysis context
|
|
413
|
+
*/
|
|
414
|
+
function extractJsxRenderingUsage(expr, context) {
|
|
415
|
+
const unwrapped = unwrapExpression(expr);
|
|
416
|
+
const sourceLocation = getSourceLocation(expr, context.sourceFile);
|
|
417
|
+
// Detect array.map() calls
|
|
418
|
+
if (ts.isCallExpression(unwrapped)) {
|
|
419
|
+
const calleeExpr = unwrapped.expression;
|
|
420
|
+
if (ts.isPropertyAccessExpression(calleeExpr)) {
|
|
421
|
+
const methodName = calleeExpr.name.getText(context.sourceFile);
|
|
422
|
+
if (methodName === 'map') {
|
|
423
|
+
const arrayPath = extractArrayPathFromMapCall(unwrapped, context.sourceFile);
|
|
424
|
+
if (arrayPath) {
|
|
425
|
+
context.addJsxRenderingUsage({
|
|
426
|
+
path: arrayPath,
|
|
427
|
+
renderingType: 'array-map',
|
|
428
|
+
valueType: 'array',
|
|
429
|
+
sourceLocation,
|
|
430
|
+
});
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
// Detect simple string interpolations: {title} or {user.name}
|
|
436
|
+
else if (ts.isIdentifier(unwrapped) ||
|
|
437
|
+
ts.isPropertyAccessExpression(unwrapped)) {
|
|
438
|
+
const path = StructuredPath.fromNode(unwrapped, context.sourceFile);
|
|
439
|
+
if (path) {
|
|
440
|
+
const pathStr = path.toString();
|
|
441
|
+
const typeInfo = context.getTypeInfo(path);
|
|
442
|
+
// Only track as text interpolation if it's a string type
|
|
443
|
+
// Check for 'string' type, or types that contain 'string' (but not 'string[]')
|
|
444
|
+
if (typeInfo === 'string' ||
|
|
445
|
+
(typeInfo &&
|
|
446
|
+
typeInfo.includes('string') &&
|
|
447
|
+
!typeInfo.includes('string[]'))) {
|
|
448
|
+
context.addJsxRenderingUsage({
|
|
449
|
+
path: pathStr,
|
|
450
|
+
renderingType: 'text-interpolation',
|
|
451
|
+
valueType: 'string',
|
|
452
|
+
sourceLocation,
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
}
|
|
457
|
+
// Recursively search inside && chains: {showList && items.map(...)}
|
|
458
|
+
else if (ts.isBinaryExpression(unwrapped) &&
|
|
459
|
+
unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
|
|
460
|
+
// Check the right side of the && chain (where .map() typically appears)
|
|
461
|
+
const rightSide = unwrapExpression(unwrapped.right);
|
|
462
|
+
extractJsxRenderingUsage(rightSide, context);
|
|
463
|
+
// Also check nested && chains on the left
|
|
464
|
+
extractJsxRenderingUsage(unwrapped.left, context);
|
|
465
|
+
}
|
|
466
|
+
// Recursively search inside ternaries: {isEmpty ? null : items.map(...)}
|
|
467
|
+
else if (ts.isConditionalExpression(unwrapped)) {
|
|
468
|
+
extractJsxRenderingUsage(unwrapped.whenTrue, context);
|
|
469
|
+
extractJsxRenderingUsage(unwrapped.whenFalse, context);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
276
472
|
/**
|
|
277
473
|
* Counts the number of conditions in an && chain (excluding JSX consequence)
|
|
278
474
|
*/
|
|
@@ -330,6 +526,9 @@ function extractConditionalsFromJsx(node, context, parentConditions = []) {
|
|
|
330
526
|
// Process JSX expressions: {expr}
|
|
331
527
|
if (ts.isJsxExpression(child) && child.expression) {
|
|
332
528
|
const expr = unwrapExpression(child.expression);
|
|
529
|
+
// Extract JSX rendering usages (array.map, text interpolation)
|
|
530
|
+
// This handles direct usages like {items.map(...)} or {user.name}
|
|
531
|
+
extractJsxRenderingUsage(expr, context);
|
|
333
532
|
// If the expression is an && chain, extract its conditional usages
|
|
334
533
|
if (ts.isBinaryExpression(expr) &&
|
|
335
534
|
expr.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
|
|
@@ -568,8 +767,84 @@ function extractConditionalsFromJsx(node, context, parentConditions = []) {
|
|
|
568
767
|
}
|
|
569
768
|
// Recursively process nested JSX elements - Fix 32: pass parent conditions
|
|
570
769
|
else if (ts.isJsxElement(child)) {
|
|
770
|
+
// Check if this is a user-defined component (vs intrinsic element like div)
|
|
771
|
+
const componentName = getComponentNameFromJsx(child);
|
|
772
|
+
if (componentName) {
|
|
773
|
+
if (parentConditions.length > 0) {
|
|
774
|
+
// If there are parent conditions, record them as gating conditions
|
|
775
|
+
console.log(`[ChildBoundary] ${componentName}: Conditionally rendered with ${parentConditions.length} gating conditions`);
|
|
776
|
+
for (const condition of parentConditions) {
|
|
777
|
+
console.log(`[ChildBoundary] ${componentName}: Adding gating condition path='${condition.path}' isNegated=${condition.isNegated}`);
|
|
778
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
779
|
+
path: condition.path,
|
|
780
|
+
conditionType: 'truthiness',
|
|
781
|
+
location: 'ternary',
|
|
782
|
+
sourceLocation: condition.sourceLocation,
|
|
783
|
+
controlsJsxRendering: true,
|
|
784
|
+
isNegated: condition.isNegated,
|
|
785
|
+
});
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
else {
|
|
789
|
+
// No parent conditions - check if it has data props for unconditional tracking
|
|
790
|
+
console.log(`[ChildBoundary] ${componentName}: Checking for unconditional rendering with data props...`);
|
|
791
|
+
const { hasDataProps, dataProps } = hasDataPropsFromParent(child, componentName);
|
|
792
|
+
if (hasDataProps) {
|
|
793
|
+
// Fix: Track unconditionally-rendered children that receive data props
|
|
794
|
+
// These need to be tracked for flow merging even without gating conditions
|
|
795
|
+
// Example: <WorkoutsView workouts={workouts} /> - parent controls workouts data
|
|
796
|
+
console.log(`[ChildBoundary] ${componentName}: TRACKING as unconditionally-rendered with data props: [${dataProps.join(', ')}]`);
|
|
797
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
798
|
+
path: '__unconditional__',
|
|
799
|
+
conditionType: 'truthiness',
|
|
800
|
+
location: 'unconditional',
|
|
801
|
+
controlsJsxRendering: true,
|
|
802
|
+
isNegated: false,
|
|
803
|
+
});
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
}
|
|
571
807
|
extractConditionalsFromJsx(child, context, parentConditions);
|
|
572
808
|
}
|
|
809
|
+
// Handle self-closing JSX elements (e.g., <ScenarioViewer />)
|
|
810
|
+
else if (ts.isJsxSelfClosingElement(child)) {
|
|
811
|
+
// Check if this is a user-defined component (vs intrinsic element like div)
|
|
812
|
+
const componentName = getComponentNameFromJsx(child);
|
|
813
|
+
if (componentName) {
|
|
814
|
+
if (parentConditions.length > 0) {
|
|
815
|
+
// If there are parent conditions, record them as gating conditions
|
|
816
|
+
console.log(`[ChildBoundary] ${componentName}: Conditionally rendered (self-closing) with ${parentConditions.length} gating conditions`);
|
|
817
|
+
for (const condition of parentConditions) {
|
|
818
|
+
console.log(`[ChildBoundary] ${componentName}: Adding gating condition path='${condition.path}' isNegated=${condition.isNegated}`);
|
|
819
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
820
|
+
path: condition.path,
|
|
821
|
+
conditionType: 'truthiness',
|
|
822
|
+
location: 'ternary',
|
|
823
|
+
sourceLocation: condition.sourceLocation,
|
|
824
|
+
controlsJsxRendering: true,
|
|
825
|
+
isNegated: condition.isNegated,
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
else {
|
|
830
|
+
// No parent conditions - check if it has data props for unconditional tracking
|
|
831
|
+
console.log(`[ChildBoundary] ${componentName}: Checking for unconditional rendering (self-closing) with data props...`);
|
|
832
|
+
const { hasDataProps, dataProps } = hasDataPropsFromParent(child, componentName);
|
|
833
|
+
if (hasDataProps) {
|
|
834
|
+
// Fix: Track unconditionally-rendered children that receive data props
|
|
835
|
+
console.log(`[ChildBoundary] ${componentName}: TRACKING as unconditionally-rendered (self-closing) with data props: [${dataProps.join(', ')}]`);
|
|
836
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
837
|
+
path: '__unconditional__',
|
|
838
|
+
conditionType: 'truthiness',
|
|
839
|
+
location: 'unconditional',
|
|
840
|
+
controlsJsxRendering: true,
|
|
841
|
+
isNegated: false,
|
|
842
|
+
});
|
|
843
|
+
}
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
// Self-closing elements have no children, so no recursion needed
|
|
847
|
+
}
|
|
573
848
|
// Recursively process nested JSX fragments - Fix 32: pass parent conditions
|
|
574
849
|
else if (ts.isJsxFragment(child)) {
|
|
575
850
|
extractConditionalsFromJsx(child, context, parentConditions);
|
|
@@ -640,12 +915,33 @@ export function extractConditionalUsage(condition, context, location, options =
|
|
|
640
915
|
return;
|
|
641
916
|
}
|
|
642
917
|
// Handle binary expressions with || (logical OR)
|
|
643
|
-
// OR
|
|
918
|
+
// When OR is inside an && chain, we need to continue chain tracking
|
|
919
|
+
// and mark conditions as OR alternatives
|
|
644
920
|
if (ts.isBinaryExpression(unwrapped) &&
|
|
645
921
|
unwrapped.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
922
|
+
if (chainInfo) {
|
|
923
|
+
// We're inside an && chain - continue tracking but mark as OR alternatives
|
|
924
|
+
// Generate an orGroupId so conditions from both sides can be grouped
|
|
925
|
+
const orGroupId = chainInfo.currentOrGroupId ?? `or_${crypto.randomUUID().slice(0, 8)}`;
|
|
926
|
+
// Process left side with OR group tracking
|
|
927
|
+
const leftChainInfo = {
|
|
928
|
+
...chainInfo,
|
|
929
|
+
currentOrGroupId: orGroupId,
|
|
930
|
+
};
|
|
931
|
+
extractWithChainTracking(unwrapped.left, leftChainInfo, false);
|
|
932
|
+
// Process right side with same OR group
|
|
933
|
+
// Note: we use leftChainInfo's currentPosition which may have been updated
|
|
934
|
+
const rightChainInfo = {
|
|
935
|
+
...leftChainInfo,
|
|
936
|
+
currentPosition: chainInfo.currentPosition,
|
|
937
|
+
};
|
|
938
|
+
extractWithChainTracking(unwrapped.right, rightChainInfo, false);
|
|
939
|
+
}
|
|
940
|
+
else {
|
|
941
|
+
// Not inside a chain - OR breaks into independent conditional checks
|
|
942
|
+
extractWithChainTracking(unwrapped.left, null, false);
|
|
943
|
+
extractWithChainTracking(unwrapped.right, null, false);
|
|
944
|
+
}
|
|
649
945
|
return;
|
|
650
946
|
}
|
|
651
947
|
// Handle comparison operators (===, !==, <, >, <=, >=)
|
|
@@ -671,7 +967,7 @@ export function extractConditionalUsage(condition, context, location, options =
|
|
|
671
967
|
return literalValue;
|
|
672
968
|
};
|
|
673
969
|
// Helper to add a condition
|
|
674
|
-
const addCondition = (path, conditionType, comparedValues, requiredValue) => {
|
|
970
|
+
const addCondition = (path, conditionType, comparedValues, requiredValue, sourceExpr) => {
|
|
675
971
|
const usage = {
|
|
676
972
|
path,
|
|
677
973
|
conditionType,
|
|
@@ -681,6 +977,16 @@ export function extractConditionalUsage(condition, context, location, options =
|
|
|
681
977
|
isNegated,
|
|
682
978
|
controlsJsxRendering,
|
|
683
979
|
};
|
|
980
|
+
// Check for inline array-derived patterns (.length) on the source expression
|
|
981
|
+
if (sourceExpr) {
|
|
982
|
+
const arrayDerived = detectArrayDerivedPattern(sourceExpr);
|
|
983
|
+
if (arrayDerived) {
|
|
984
|
+
usage.derivedFrom = {
|
|
985
|
+
operation: arrayDerived.operation,
|
|
986
|
+
sourcePath: arrayDerived.sourcePath,
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
}
|
|
684
990
|
// Add chain info if part of a compound conditional
|
|
685
991
|
if (chainInfo) {
|
|
686
992
|
usage.chainId = chainInfo.chainId;
|
|
@@ -695,6 +1001,9 @@ export function extractConditionalUsage(condition, context, location, options =
|
|
|
695
1001
|
comparedValues,
|
|
696
1002
|
isNegated,
|
|
697
1003
|
requiredValue,
|
|
1004
|
+
...(chainInfo.currentOrGroupId && {
|
|
1005
|
+
orGroupId: chainInfo.currentOrGroupId,
|
|
1006
|
+
}),
|
|
698
1007
|
});
|
|
699
1008
|
}
|
|
700
1009
|
context.addConditionalUsage(usage);
|
|
@@ -702,21 +1011,21 @@ export function extractConditionalUsage(condition, context, location, options =
|
|
|
702
1011
|
// Check if left is a variable and right is a literal
|
|
703
1012
|
if (leftPath && isLiteralExpression(unwrapped.right)) {
|
|
704
1013
|
const literalValue = getLiteralValue(unwrapped.right, context);
|
|
705
|
-
addCondition(leftPath.toLeftHandSideString(), 'comparison', literalValue !== undefined ? [literalValue] : undefined, getRequiredValue(literalValue, isNegated));
|
|
1014
|
+
addCondition(leftPath.toLeftHandSideString(), 'comparison', literalValue !== undefined ? [literalValue] : undefined, getRequiredValue(literalValue, isNegated), unwrapped.left);
|
|
706
1015
|
return;
|
|
707
1016
|
}
|
|
708
1017
|
// Check if right is a variable and left is a literal
|
|
709
1018
|
if (rightPath && isLiteralExpression(unwrapped.left)) {
|
|
710
1019
|
const literalValue = getLiteralValue(unwrapped.left, context);
|
|
711
|
-
addCondition(rightPath.toLeftHandSideString(), 'comparison', literalValue !== undefined ? [literalValue] : undefined, getRequiredValue(literalValue, isNegated));
|
|
1020
|
+
addCondition(rightPath.toLeftHandSideString(), 'comparison', literalValue !== undefined ? [literalValue] : undefined, getRequiredValue(literalValue, isNegated), unwrapped.right);
|
|
712
1021
|
return;
|
|
713
1022
|
}
|
|
714
1023
|
// Both sides are variables - record both as comparisons without specific values
|
|
715
1024
|
if (leftPath) {
|
|
716
|
-
addCondition(leftPath.toLeftHandSideString(), 'comparison');
|
|
1025
|
+
addCondition(leftPath.toLeftHandSideString(), 'comparison', undefined, undefined, unwrapped.left);
|
|
717
1026
|
}
|
|
718
1027
|
if (rightPath) {
|
|
719
|
-
addCondition(rightPath.toLeftHandSideString(), 'comparison');
|
|
1028
|
+
addCondition(rightPath.toLeftHandSideString(), 'comparison', undefined, undefined, unwrapped.right);
|
|
720
1029
|
}
|
|
721
1030
|
return;
|
|
722
1031
|
}
|
|
@@ -740,6 +1049,15 @@ export function extractConditionalUsage(condition, context, location, options =
|
|
|
740
1049
|
isNegated,
|
|
741
1050
|
controlsJsxRendering,
|
|
742
1051
|
};
|
|
1052
|
+
// Check for inline array-derived patterns (.some(), .every(), .includes(), .length)
|
|
1053
|
+
// This populates derivedFrom so downstream code can resolve to the base array path
|
|
1054
|
+
const arrayDerived = detectArrayDerivedPattern(unwrapped);
|
|
1055
|
+
if (arrayDerived) {
|
|
1056
|
+
usage.derivedFrom = {
|
|
1057
|
+
operation: arrayDerived.operation,
|
|
1058
|
+
sourcePath: arrayDerived.sourcePath,
|
|
1059
|
+
};
|
|
1060
|
+
}
|
|
743
1061
|
// Add chain info if part of a compound conditional
|
|
744
1062
|
if (chainInfo) {
|
|
745
1063
|
usage.chainId = chainInfo.chainId;
|
|
@@ -754,6 +1072,9 @@ export function extractConditionalUsage(condition, context, location, options =
|
|
|
754
1072
|
conditionType: 'truthiness',
|
|
755
1073
|
isNegated,
|
|
756
1074
|
requiredValue: !isNegated,
|
|
1075
|
+
...(chainInfo.currentOrGroupId && {
|
|
1076
|
+
orGroupId: chainInfo.currentOrGroupId,
|
|
1077
|
+
}),
|
|
757
1078
|
});
|
|
758
1079
|
}
|
|
759
1080
|
context.addConditionalUsage(usage);
|
|
@@ -885,15 +1206,21 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
|
|
|
885
1206
|
const equivalentVariables = context.getEquivalentVariables();
|
|
886
1207
|
const structure = context.getStructure();
|
|
887
1208
|
// Propagate existing equivalencies for sub-properties
|
|
888
|
-
for (const [key,
|
|
1209
|
+
for (const [key, rawValue] of Object.entries(equivalentVariables)) {
|
|
889
1210
|
// Check if this equivalency is for a sub-property of the identifier
|
|
890
1211
|
// e.g., completeDataStructure['Function Arguments'] or completeDataStructure.foo
|
|
891
1212
|
if (key.startsWith(nodePathStr + '.') ||
|
|
892
1213
|
key.startsWith(nodePathStr + '[')) {
|
|
893
1214
|
const subPath = key.substring(nodePathStr.length);
|
|
894
1215
|
const newTargetPath = StructuredPath.fromBase(targetPath.toString() + subPath);
|
|
895
|
-
|
|
896
|
-
|
|
1216
|
+
// Handle both string and string[] values
|
|
1217
|
+
const values = Array.isArray(rawValue) ? rawValue : [rawValue];
|
|
1218
|
+
for (const value of values) {
|
|
1219
|
+
if (typeof value === 'string') {
|
|
1220
|
+
const valuePath = StructuredPath.fromBase(value);
|
|
1221
|
+
context.addEquivalence(newTargetPath, valuePath);
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
897
1224
|
}
|
|
898
1225
|
}
|
|
899
1226
|
// Propagate existing structure entries for sub-properties
|
|
@@ -1229,12 +1556,46 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
|
|
|
1229
1556
|
}
|
|
1230
1557
|
}
|
|
1231
1558
|
else if (operatorKind === ts.SyntaxKind.BarBarToken) {
|
|
1232
|
-
// For ||,
|
|
1559
|
+
// For ||, create equivalences to BOTH sides
|
|
1233
1560
|
// This enables data flow tracing through fallback expressions
|
|
1561
|
+
// e.g., `const item = items.find(...) || null` should trace to both:
|
|
1562
|
+
// - items[] (from the find result)
|
|
1563
|
+
// - null (from the fallback)
|
|
1234
1564
|
if (targetPath) {
|
|
1235
|
-
|
|
1565
|
+
// Get paths for both sides
|
|
1566
|
+
const leftPath = StructuredPath.fromNode(unwrappedNode.left, context.sourceFile);
|
|
1567
|
+
const rightPath = StructuredPath.fromNode(unwrappedNode.right, context.sourceFile);
|
|
1568
|
+
// Collect all valid paths
|
|
1569
|
+
const allPaths = [];
|
|
1570
|
+
if (leftPath)
|
|
1571
|
+
allPaths.push(leftPath);
|
|
1572
|
+
if (rightPath)
|
|
1573
|
+
allPaths.push(rightPath);
|
|
1574
|
+
// Add multiple equivalencies to track both sources
|
|
1575
|
+
if (allPaths.length > 0) {
|
|
1576
|
+
context.addMultipleEquivalencies(targetPath, allPaths);
|
|
1577
|
+
}
|
|
1578
|
+
// Process both sides to capture their internal structures
|
|
1579
|
+
processExpression({
|
|
1580
|
+
node: unwrappedNode.left,
|
|
1581
|
+
context,
|
|
1582
|
+
});
|
|
1583
|
+
processExpression({
|
|
1584
|
+
node: unwrappedNode.right,
|
|
1585
|
+
context,
|
|
1586
|
+
});
|
|
1587
|
+
// Register the type for the target path
|
|
1588
|
+
const leftType = context.inferTypeFromNode(unwrappedNode.left);
|
|
1589
|
+
const rightType = context.inferTypeFromNode(unwrappedNode.right);
|
|
1590
|
+
const orResultType = isDefinedType(leftType)
|
|
1591
|
+
? leftType
|
|
1592
|
+
: rightType || 'unknown';
|
|
1593
|
+
context.addType(targetPath, orResultType);
|
|
1594
|
+
// Return early - we've already handled equivalencies with addMultipleEquivalencies
|
|
1595
|
+
// Don't fall through to the generic addEquivalence call below
|
|
1596
|
+
return true;
|
|
1236
1597
|
}
|
|
1237
|
-
// Note:
|
|
1598
|
+
// Note: When there's no targetPath, we don't recursively process
|
|
1238
1599
|
// because || is often used in boolean contexts where the full expression matters
|
|
1239
1600
|
}
|
|
1240
1601
|
}
|
|
@@ -1312,18 +1673,44 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
|
|
|
1312
1673
|
const semantics = semanticsList[0];
|
|
1313
1674
|
// Get the source expression path (e.g., the object for obj.method())
|
|
1314
1675
|
const sourceExpr = unwrappedNode.expression.expression;
|
|
1315
|
-
const
|
|
1316
|
-
|
|
1317
|
-
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
const
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1676
|
+
const unwrappedSourceExpr = unwrapExpression(sourceExpr);
|
|
1677
|
+
// When the source is a ternary expression like (cond ? arr : arr.slice()),
|
|
1678
|
+
// apply method semantics to BOTH branches directly. The ternary itself isn't
|
|
1679
|
+
// a variable - it's just a choice between two paths that both flow to the result.
|
|
1680
|
+
if (ts.isConditionalExpression(unwrappedSourceExpr)) {
|
|
1681
|
+
const branches = [
|
|
1682
|
+
unwrappedSourceExpr.whenTrue,
|
|
1683
|
+
unwrappedSourceExpr.whenFalse,
|
|
1684
|
+
];
|
|
1685
|
+
for (const branch of branches) {
|
|
1686
|
+
const branchPath = StructuredPath.fromNode(branch, context.sourceFile);
|
|
1687
|
+
if (branchPath) {
|
|
1688
|
+
const isArraySemantics = semantics instanceof ArrayPushSemantics;
|
|
1689
|
+
const shouldApply = !isArraySemantics ||
|
|
1690
|
+
isLikelyArrayType(branch, context.typeChecker);
|
|
1691
|
+
if (shouldApply) {
|
|
1692
|
+
semantics.addEquivalences(callPath, branchPath, context);
|
|
1693
|
+
returnType = semantics.getReturnType();
|
|
1694
|
+
handledBySemantics = true;
|
|
1695
|
+
}
|
|
1696
|
+
}
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
else {
|
|
1700
|
+
// Regular (non-ternary) source expression
|
|
1701
|
+
const sourcePath = StructuredPath.fromNode(sourceExpr, context.sourceFile);
|
|
1702
|
+
if (sourcePath) {
|
|
1703
|
+
// For array-specific semantics (like push), verify the source is actually an array
|
|
1704
|
+
// This prevents router.push() from being mistakenly treated as Array.push()
|
|
1705
|
+
const isArraySemantics = semantics instanceof ArrayPushSemantics;
|
|
1706
|
+
const shouldApply = !isArraySemantics ||
|
|
1707
|
+
isLikelyArrayType(sourceExpr, context.typeChecker);
|
|
1708
|
+
if (shouldApply) {
|
|
1709
|
+
// Apply method semantics
|
|
1710
|
+
semantics.addEquivalences(callPath, sourcePath, context);
|
|
1711
|
+
returnType = semantics.getReturnType();
|
|
1712
|
+
handledBySemantics = true;
|
|
1713
|
+
}
|
|
1327
1714
|
}
|
|
1328
1715
|
}
|
|
1329
1716
|
}
|
|
@@ -1752,6 +2139,32 @@ export function processExpression({ node, context, targetPath, typeHint, }) {
|
|
|
1752
2139
|
}
|
|
1753
2140
|
// Handle Arrow Functions: (p) => p.prop, (a, b) => { ... }
|
|
1754
2141
|
if (ts.isArrowFunction(unwrappedNode)) {
|
|
2142
|
+
// If this arrow function is a child boundary (e.g., a .map() callback),
|
|
2143
|
+
// don't process its parameters here - they will be processed when the
|
|
2144
|
+
// child scope is analyzed separately. This prevents parameter variables
|
|
2145
|
+
// from leaking into the parent scope's equivalencies.
|
|
2146
|
+
// Check if this arrow function is a child boundary (i.e., should be processed
|
|
2147
|
+
// as a separate child scope, not here in the parent scope).
|
|
2148
|
+
//
|
|
2149
|
+
// We use two checks because childBoundary positions can be unreliable:
|
|
2150
|
+
// 1. Position-based check (standard isChildBoundary)
|
|
2151
|
+
// 2. Text-based check: if the arrow function text doesn't appear in the
|
|
2152
|
+
// statement text, it was replaced with a cyScope placeholder
|
|
2153
|
+
const isChildBoundary = context.isChildBoundary(unwrappedNode);
|
|
2154
|
+
// Text-based child scope detection for when positions are unreliable
|
|
2155
|
+
const arrowFnText = unwrappedNode.getText(context.sourceFile);
|
|
2156
|
+
const firstLine = arrowFnText.split('\n')[0].trim();
|
|
2157
|
+
const searchText = firstLine.substring(0, Math.min(20, firstLine.length));
|
|
2158
|
+
const isInStatementText = context.statementInfo.text.includes(searchText);
|
|
2159
|
+
const isChildScope = !isInStatementText && arrowFnText.length > 10;
|
|
2160
|
+
if (isChildBoundary || isChildScope) {
|
|
2161
|
+
// The method semantics (e.g., ArrayMapSemantics) have already established
|
|
2162
|
+
// the necessary equivalences between the child scope placeholder and array elements
|
|
2163
|
+
if (targetPath) {
|
|
2164
|
+
context.addType(targetPath, 'function');
|
|
2165
|
+
}
|
|
2166
|
+
return true;
|
|
2167
|
+
}
|
|
1755
2168
|
// Create a path for the function
|
|
1756
2169
|
const functionPath = StructuredPath.empty();
|
|
1757
2170
|
// Process parameters
|