@codeyam/codeyam-cli 0.1.0-staging.323686 → 0.1.0-staging.4813bf3
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 +5 -5
- package/analyzer-template/packages/ai/index.ts +7 -1
- package/analyzer-template/packages/ai/package.json +2 -2
- package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +62 -18
- package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +67 -9
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.ts +10 -17
- package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +409 -50
- package/analyzer-template/packages/ai/src/lib/astScopes/sharedPatterns.ts +28 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +21 -6
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +992 -249
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.ts +5 -1
- 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 +31 -3
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +37 -15
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.ts +70 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +126 -11
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.ts +179 -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 +367 -96
- package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +33 -15
- package/analyzer-template/packages/ai/src/lib/generateEntityDataStructure.ts +58 -3
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +315 -6
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +9 -5
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +49 -5
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.ts +1 -1
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +649 -142
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.ts +1 -1
- package/analyzer-template/packages/ai/src/lib/isolateScopes.ts +51 -3
- package/analyzer-template/packages/ai/src/lib/mergeJsonTypeDefinitions.ts +5 -0
- package/analyzer-template/packages/ai/src/lib/mergeStatements.ts +90 -96
- package/analyzer-template/packages/ai/src/lib/promptGenerators/collapseNullableObjects.ts +118 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +10 -7
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.ts +24 -4
- package/analyzer-template/packages/ai/src/lib/resolvePathToControllable.ts +25 -13
- package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +4 -3
- package/analyzer-template/packages/analyze/index.ts +2 -0
- 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/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 +89 -9
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +19 -4
- package/analyzer-template/packages/analyze/src/lib/files/analyze/gatherEntityMap.ts +4 -2
- package/analyzer-template/packages/analyze/src/lib/files/analyze/validateDependencyAnalyses.ts +0 -3
- 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/TransformationTracer.ts +1315 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +61 -13
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +37 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +229 -19
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +117 -9
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +459 -39
- 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/index.ts +1 -0
- package/analyzer-template/packages/analyze/src/lib/utils/getFileByPath.ts +19 -0
- package/analyzer-template/packages/aws/package.json +1 -1
- package/analyzer-template/packages/database/package.json +1 -1
- package/analyzer-template/packages/database/src/lib/analysisBranchToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/analysisToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/branchToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/commitBranchToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/commitToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/fileToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/kysely/db.ts +6 -0
- package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +1 -1
- package/analyzer-template/packages/database/src/lib/kysely/tables/labsRequestsTable.ts +52 -0
- package/analyzer-template/packages/database/src/lib/projectToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/saveFiles.ts +1 -1
- package/analyzer-template/packages/database/src/lib/scenarioToDb.ts +1 -1
- package/analyzer-template/packages/database/src/lib/userScenarioToDb.ts +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/analysisBranchToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/analysisToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/branchToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/commitBranchToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/commitToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/fileToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/db.d.ts +2 -0
- 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 +3 -0
- 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/debugReportsTable.d.ts +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts +23 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.d.ts.map +1 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
- package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/projectToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/saveFiles.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/scenarioToDb.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts +7 -0
- package/analyzer-template/packages/github/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +5 -5
- 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/package.json +1 -1
- package/analyzer-template/packages/types/src/types/ProjectMetadata.ts +7 -0
- package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +6 -5
- package/analyzer-template/packages/types/src/types/ScopeAnalysis.ts +6 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts +7 -0
- package/analyzer-template/packages/utils/dist/types/src/types/ProjectMetadata.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +5 -5
- 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/project/constructMockCode.ts +90 -10
- package/analyzer-template/project/writeMockDataTsx.ts +181 -8
- package/analyzer-template/project/writeScenarioComponents.ts +60 -12
- package/analyzer-template/project/writeSimpleRoot.ts +21 -11
- package/background/src/lib/local/createLocalAnalyzer.js +1 -1
- package/background/src/lib/local/createLocalAnalyzer.js.map +1 -1
- package/background/src/lib/virtualized/project/constructMockCode.js +75 -4
- package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
- package/background/src/lib/virtualized/project/writeMockDataTsx.js +162 -4
- package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
- package/background/src/lib/virtualized/project/writeScenarioComponents.js +60 -15
- package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
- package/background/src/lib/virtualized/project/writeSimpleRoot.js +21 -11
- package/background/src/lib/virtualized/project/writeSimpleRoot.js.map +1 -1
- package/codeyam-cli/scripts/apply-setup.js +180 -0
- package/codeyam-cli/scripts/apply-setup.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/codeyam-cli.js +18 -2
- package/codeyam-cli/src/codeyam-cli.js.map +1 -1
- package/codeyam-cli/src/commands/analyze.js +4 -2
- package/codeyam-cli/src/commands/analyze.js.map +1 -1
- package/codeyam-cli/src/commands/baseline.js +2 -0
- package/codeyam-cli/src/commands/baseline.js.map +1 -1
- package/codeyam-cli/src/commands/debug.js +9 -5
- package/codeyam-cli/src/commands/debug.js.map +1 -1
- package/codeyam-cli/src/commands/default.js +31 -20
- package/codeyam-cli/src/commands/default.js.map +1 -1
- package/codeyam-cli/src/commands/detect-universal-mocks.js +2 -0
- package/codeyam-cli/src/commands/detect-universal-mocks.js.map +1 -1
- package/codeyam-cli/src/commands/init.js +49 -257
- package/codeyam-cli/src/commands/init.js.map +1 -1
- package/codeyam-cli/src/commands/memory.js +17 -26
- package/codeyam-cli/src/commands/memory.js.map +1 -1
- package/codeyam-cli/src/commands/recapture.js +2 -0
- package/codeyam-cli/src/commands/recapture.js.map +1 -1
- package/codeyam-cli/src/commands/setup-sandbox.js +2 -0
- package/codeyam-cli/src/commands/setup-sandbox.js.map +1 -1
- package/codeyam-cli/src/commands/setup-simulations.js +284 -0
- package/codeyam-cli/src/commands/setup-simulations.js.map +1 -0
- package/codeyam-cli/src/commands/test-startup.js +2 -0
- package/codeyam-cli/src/commands/test-startup.js.map +1 -1
- package/codeyam-cli/src/commands/verify.js +14 -2
- package/codeyam-cli/src/commands/verify.js.map +1 -1
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +128 -86
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
- package/codeyam-cli/src/utils/analyzer.js +7 -0
- package/codeyam-cli/src/utils/analyzer.js.map +1 -1
- package/codeyam-cli/src/utils/backgroundServer.js +5 -0
- package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/utils/generateReport.js +2 -2
- package/codeyam-cli/src/utils/install-skills.js +70 -45
- package/codeyam-cli/src/utils/install-skills.js.map +1 -1
- package/codeyam-cli/src/utils/labsAutoCheck.js +19 -0
- package/codeyam-cli/src/utils/labsAutoCheck.js.map +1 -0
- package/codeyam-cli/src/utils/progress.js +7 -0
- package/codeyam-cli/src/utils/progress.js.map +1 -1
- package/codeyam-cli/src/utils/queue/job.js +4 -0
- package/codeyam-cli/src/utils/queue/job.js.map +1 -1
- package/codeyam-cli/src/utils/requireSimulations.js +10 -0
- package/codeyam-cli/src/utils/requireSimulations.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js +82 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/confusionDetector.test.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js +230 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/contextBuilder.test.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js +67 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/assertRules.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js +105 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/captureFixture.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js +34 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/loadCapturedFixture.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js +162 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/runClaude.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js +75 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/helpers/setupTempProject.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js +378 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/integration/ruleReflectionE2E.test.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js +115 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/promptBuilder.test.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js +127 -0
- package/codeyam-cli/src/utils/ruleReflection/__tests__/transcriptParser.test.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js +50 -0
- package/codeyam-cli/src/utils/ruleReflection/confusionDetector.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js +116 -0
- package/codeyam-cli/src/utils/ruleReflection/contextBuilder.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/index.js +5 -0
- package/codeyam-cli/src/utils/ruleReflection/index.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js +44 -0
- package/codeyam-cli/src/utils/ruleReflection/promptBuilder.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js +85 -0
- package/codeyam-cli/src/utils/ruleReflection/transcriptParser.js.map +1 -0
- package/codeyam-cli/src/utils/ruleReflection/types.js +5 -0
- package/codeyam-cli/src/utils/ruleReflection/types.js.map +1 -0
- package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js +293 -0
- package/codeyam-cli/src/utils/rules/__tests__/ruleState.test.js.map +1 -0
- package/codeyam-cli/src/utils/rules/index.js +1 -0
- package/codeyam-cli/src/utils/rules/index.js.map +1 -1
- package/codeyam-cli/src/utils/rules/parser.js +2 -25
- package/codeyam-cli/src/utils/rules/parser.js.map +1 -1
- package/codeyam-cli/src/utils/rules/ruleState.js +150 -0
- package/codeyam-cli/src/utils/rules/ruleState.js.map +1 -0
- package/codeyam-cli/src/utils/rules/staleness.js +16 -11
- package/codeyam-cli/src/utils/rules/staleness.js.map +1 -1
- package/codeyam-cli/src/utils/serverState.js +37 -10
- package/codeyam-cli/src/utils/serverState.js.map +1 -1
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js +21 -44
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/database.js +15 -3
- package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
- package/codeyam-cli/src/webserver/backgroundServer.js +24 -0
- package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/CopyButton-CA3JxPb7.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{EntityItem-DsN1wKrm.js → EntityItem-B86KKU7e.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-DLqD3qNt.js → EntityTypeBadge-B5ctlSYt.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeIcon-Ba2JVPzP.js → EntityTypeIcon-BqY8gDAW.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InlineSpinner-C8lyxW9k.js → InlineSpinner-ClaLpuOo.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-aht4aafF.js → InteractivePreview-BDhPilK7.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{LibraryFunctionPreview-CVtiBnY5.js → LibraryFunctionPreview-VeqEBv9v.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LoadingDots-B0GLXMsr.js → LoadingDots-Bs7Nn1Jr.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{LogViewer-xgeCVgSM.js → LogViewer-Bm3PmcCz.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ReportIssueModal-OApQuNyq.js → ReportIssueModal-CgMEzchJ.js} +3 -8
- package/codeyam-cli/src/webserver/build/client/assets/{SafeScreenshot-DuDvi0jm.js → SafeScreenshot-Gq3Ocjo6.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{ScenarioViewer-DzccYyI8.js → ScenarioViewer-CBui0id_.js} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-DyFZkK0l.js → TruncatedFilePath-CiwXDxLh.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{_index-BwqWJOgH.js → _index-B3TDXxnk.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{activity.(_tab)-BwavGCpm.js → activity.(_tab)-BtBFH820.js} +6 -11
- package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-CN61MOMa.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.agent-transcripts-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.labs-unlock-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/api.save-fixture-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/book-open-PttOB2SF.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/{chevron-down-Cx24_aWc.js → chevron-down-TJp6ofnp.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{chunk-EPOLDU6W-CXRTFQ3F.js → chunk-JZWAC4HX-JE9ZIoBl.js} +12 -12
- package/codeyam-cli/src/webserver/build/client/assets/{circle-check-BOARzkeR.js → circle-check-CXhHQYrI.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/copy-6y9ALfGT.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/{createLucideIcon-BdhJEx6B.js → createLucideIcon-Ca9fAY46.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{dev.empty-BBnGWYga.js → dev.empty-C0epRiVn.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-BJUiQqZF.js → entity._sha._-BVnB8a9L.js} +10 -10
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha.scenarios._scenarioId.fullscreen-DavjRmOY.js → entity._sha.scenarios._scenarioId.fullscreen-CBoafmVs.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.create-scenario-D1T4TGjf.js → entity._sha_.create-scenario-DGgZjdFg.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha_.edit._scenarioId-CTBG2mmz.js → entity._sha_.edit._scenarioId-38yPijoD.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{entry.client-CS2cb_eZ.js → entry.client-BSHEfydn.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{fileTableUtils-DMJ7zii9.js → fileTableUtils-DCPhhSMo.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{files-CJ6lTdTA.js → files-0N0YJQv7.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{git-CPTZZ-JZ.js → git-DXnyr8uP.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/globals-CKT08Djd.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{index-lzqtyFU8.js → index-CcsFv748.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{index-B1h680n5.js → index-ChN9-fAY.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/labs-BLJ7HxOC.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{loader-circle-B7B9V-bu.js → loader-circle-CTqLEAGU.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-b171b9d3.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/memory-CCQd4aZA.js +78 -0
- package/codeyam-cli/src/webserver/build/client/assets/pause-D6vreykR.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/root-CHhiHoo_.js +62 -0
- package/codeyam-cli/src/webserver/build/client/assets/{search-CxXUmBSd.js → search-B8VUL8nl.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/settings-BejnUJ6R.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{simulations-DwFIBT09.js → simulations-CPoAg7Zo.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/terminal-BrCP7uQo.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/{triangle-alert-B6LgvRJg.js → triangle-alert-BZz2NjYa.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useCustomSizes-C1v1PQzo.js → useCustomSizes-DNwUduNu.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-aSv48UbS.js → useLastLogLine-COky1GVF.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useReportContext-DYxHZQuP.js → useReportContext-CpZgwliL.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/{useToast-mBRpZPiu.js → useToast-Bv9JFvUO.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/{index-DVzYx8PN.js → index-8Fv-lH1-.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-Akn3iYFP.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:debug.md → codeyam-debug.md} +1 -1
- package/codeyam-cli/templates/codeyam-diagnose.md +481 -0
- package/codeyam-cli/templates/codeyam-memory-hook.sh +19 -20
- package/codeyam-cli/templates/codeyam-memory.md +392 -0
- package/codeyam-cli/templates/codeyam-new-rule.md +13 -0
- package/codeyam-cli/templates/{codeyam:setup.md → codeyam-setup.md} +13 -1
- package/codeyam-cli/templates/{codeyam:sim.md → codeyam-sim.md} +1 -1
- package/codeyam-cli/templates/{codeyam:test.md → codeyam-test.md} +1 -1
- package/codeyam-cli/templates/{codeyam:verify.md → codeyam-verify.md} +1 -1
- package/codeyam-cli/templates/rule-notification-hook.py +56 -0
- package/codeyam-cli/templates/rule-reflection-hook.py +627 -0
- package/codeyam-cli/templates/rules-instructions.md +132 -0
- package/package.json +2 -2
- package/packages/ai/index.js +3 -2
- package/packages/ai/index.js.map +1 -1
- package/packages/ai/src/lib/analyzeScope.js +50 -13
- package/packages/ai/src/lib/analyzeScope.js.map +1 -1
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js +54 -8
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
- package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js +10 -14
- package/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.js.map +1 -1
- package/packages/ai/src/lib/astScopes/processExpression.js +317 -44
- package/packages/ai/src/lib/astScopes/processExpression.js.map +1 -1
- package/packages/ai/src/lib/astScopes/sharedPatterns.js +25 -0
- package/packages/ai/src/lib/astScopes/sharedPatterns.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +763 -171
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js +5 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.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 +33 -3
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +36 -11
- package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js +63 -0
- package/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.js.map +1 -0
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js +113 -11
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/convertTypeAnnotationsToValues.js +173 -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 +309 -84
- package/packages/ai/src/lib/dataStructure/helpers/fillInSchemaGapsAndUnknowns.js.map +1 -1
- package/packages/ai/src/lib/dataStructureChunking.js +26 -11
- package/packages/ai/src/lib/dataStructureChunking.js.map +1 -1
- package/packages/ai/src/lib/generateEntityDataStructure.js +46 -2
- package/packages/ai/src/lib/generateEntityDataStructure.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarioData.js +227 -4
- package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarios.js +7 -1
- package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlows.js +26 -4
- package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +447 -80
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -1
- package/packages/ai/src/lib/isolateScopes.js +39 -3
- package/packages/ai/src/lib/isolateScopes.js.map +1 -1
- package/packages/ai/src/lib/mergeJsonTypeDefinitions.js +5 -0
- package/packages/ai/src/lib/mergeJsonTypeDefinitions.js.map +1 -1
- 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/collapseNullableObjects.js +97 -0
- package/packages/ai/src/lib/promptGenerators/collapseNullableObjects.js.map +1 -0
- 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/generateEntityScenarioDataGenerator.js +17 -2
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
- package/packages/ai/src/lib/resolvePathToControllable.js +24 -14
- package/packages/ai/src/lib/resolvePathToControllable.js.map +1 -1
- package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
- package/packages/analyze/index.js +1 -0
- package/packages/analyze/index.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/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 +65 -7
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +17 -4
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.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 +0 -3
- 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/TransformationTracer.js +880 -0
- package/packages/analyze/src/lib/files/scenarios/TransformationTracer.js.map +1 -0
- package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js +56 -10
- package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +33 -8
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +150 -17
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +56 -8
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +399 -31
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.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/index.js +1 -0
- package/packages/analyze/src/lib/index.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/analysisBranchToDb.js +1 -1
- package/packages/database/src/lib/analysisBranchToDb.js.map +1 -1
- package/packages/database/src/lib/analysisToDb.js +1 -1
- package/packages/database/src/lib/analysisToDb.js.map +1 -1
- package/packages/database/src/lib/branchToDb.js +1 -1
- package/packages/database/src/lib/branchToDb.js.map +1 -1
- package/packages/database/src/lib/commitBranchToDb.js +1 -1
- package/packages/database/src/lib/commitBranchToDb.js.map +1 -1
- package/packages/database/src/lib/commitToDb.js +1 -1
- package/packages/database/src/lib/commitToDb.js.map +1 -1
- package/packages/database/src/lib/fileToDb.js +1 -1
- package/packages/database/src/lib/fileToDb.js.map +1 -1
- package/packages/database/src/lib/kysely/db.js +3 -0
- package/packages/database/src/lib/kysely/db.js.map +1 -1
- package/packages/database/src/lib/kysely/tables/labsRequestsTable.js +35 -0
- package/packages/database/src/lib/kysely/tables/labsRequestsTable.js.map +1 -0
- package/packages/database/src/lib/projectToDb.js +1 -1
- package/packages/database/src/lib/projectToDb.js.map +1 -1
- package/packages/database/src/lib/saveFiles.js +1 -1
- package/packages/database/src/lib/saveFiles.js.map +1 -1
- package/packages/database/src/lib/scenarioToDb.js +1 -1
- package/packages/database/src/lib/scenarioToDb.js.map +1 -1
- package/scripts/finalize-analyzer.cjs +8 -76
- package/codeyam-cli/src/webserver/build/client/assets/copy-Bb-80kDT.js +0 -6
- package/codeyam-cli/src/webserver/build/client/assets/file-code-Dhef1kWN.js +0 -6
- package/codeyam-cli/src/webserver/build/client/assets/globals-D3yhhV8x.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-7522edd4.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/memory-yxFcrxBX.js +0 -92
- package/codeyam-cli/src/webserver/build/client/assets/root-eVAaavTS.js +0 -62
- package/codeyam-cli/src/webserver/build/client/assets/settings-CS5f3WzT.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-4Cr0uToj.js +0 -257
- package/codeyam-cli/templates/codeyam:diagnose.md +0 -803
- package/codeyam-cli/templates/codeyam:memory.md +0 -462
- package/codeyam-cli/templates/codeyam:new-rule.md +0 -13
|
@@ -9,6 +9,7 @@ import { StructuredPath } from './paths';
|
|
|
9
9
|
import { nodeToSource } from './nodeToSource';
|
|
10
10
|
import { methodRegistry, ArrayPushSemantics } from './methodSemantics';
|
|
11
11
|
import {
|
|
12
|
+
getComparisonOperatorString,
|
|
12
13
|
isArithmeticOperator,
|
|
13
14
|
isAssignmentOperator,
|
|
14
15
|
isBitwiseCompoundOperator,
|
|
@@ -25,6 +26,179 @@ import {
|
|
|
25
26
|
} from './conditionalEffectsExtractor';
|
|
26
27
|
import { detectArrayDerivedPattern } from './arrayDerivationDetector';
|
|
27
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Recursively extracts root variable names from an expression AST node.
|
|
31
|
+
* Used to identify which variables flow into JSX expression children,
|
|
32
|
+
* so we can link them to the return value schema.
|
|
33
|
+
*
|
|
34
|
+
* Examples:
|
|
35
|
+
* - `filteredTopPaths.map(...)` → ['filteredTopPaths']
|
|
36
|
+
* - `a && b` → ['a', 'b']
|
|
37
|
+
* - `condition ? x : y` → ['condition', 'x', 'y']
|
|
38
|
+
*/
|
|
39
|
+
function extractRootVariableNames(node: ts.Expression): string[] {
|
|
40
|
+
const ignoredIdentifiers = new Set([
|
|
41
|
+
'undefined',
|
|
42
|
+
'null',
|
|
43
|
+
'true',
|
|
44
|
+
'false',
|
|
45
|
+
'NaN',
|
|
46
|
+
'Infinity',
|
|
47
|
+
]);
|
|
48
|
+
|
|
49
|
+
if (ts.isIdentifier(node)) {
|
|
50
|
+
const name = node.text;
|
|
51
|
+
return ignoredIdentifiers.has(name) ? [] : [name];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (ts.isPropertyAccessExpression(node)) {
|
|
55
|
+
return extractRootVariableNames(node.expression);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
if (ts.isCallExpression(node)) {
|
|
59
|
+
return extractRootVariableNames(node.expression);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (ts.isBinaryExpression(node)) {
|
|
63
|
+
return [
|
|
64
|
+
...extractRootVariableNames(node.left),
|
|
65
|
+
...extractRootVariableNames(node.right),
|
|
66
|
+
];
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
if (ts.isPrefixUnaryExpression(node)) {
|
|
70
|
+
return extractRootVariableNames(node.operand);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (ts.isConditionalExpression(node)) {
|
|
74
|
+
return [
|
|
75
|
+
...extractRootVariableNames(node.condition),
|
|
76
|
+
...extractRootVariableNames(node.whenTrue),
|
|
77
|
+
...extractRootVariableNames(node.whenFalse),
|
|
78
|
+
];
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (ts.isParenthesizedExpression(node)) {
|
|
82
|
+
return extractRootVariableNames(node.expression);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
// Stop recursion at JSX elements and other terminal nodes
|
|
86
|
+
if (
|
|
87
|
+
ts.isJsxElement(node) ||
|
|
88
|
+
ts.isJsxFragment(node) ||
|
|
89
|
+
ts.isJsxSelfClosingElement(node)
|
|
90
|
+
) {
|
|
91
|
+
return [];
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
return [];
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Checks if a JSX element has props that reference variables from the parent scope.
|
|
99
|
+
* This is used to detect unconditionally-rendered children that should have their
|
|
100
|
+
* execution flows merged into the parent.
|
|
101
|
+
*
|
|
102
|
+
* We want to track children where the parent controls data that affects the child's
|
|
103
|
+
* conditional rendering. Static props (like title="Dashboard") don't need tracking
|
|
104
|
+
* because they don't create variable execution flows.
|
|
105
|
+
*
|
|
106
|
+
* Examples:
|
|
107
|
+
* - <WorkoutsView workouts={workouts} /> → true (workouts is a variable)
|
|
108
|
+
* - <ItemList items={items} count={count} /> → true (items, count are variables)
|
|
109
|
+
* - <Header title="Dashboard" /> → false (static string)
|
|
110
|
+
* - <Footer /> → false (no props)
|
|
111
|
+
* - <Button onClick={handleClick} /> → false (only callback, no data props)
|
|
112
|
+
*
|
|
113
|
+
* @returns true if the component has at least one prop that references a variable
|
|
114
|
+
* (excluding callbacks which typically start with 'on' or 'handle')
|
|
115
|
+
*/
|
|
116
|
+
function hasDataPropsFromParent(
|
|
117
|
+
node: ts.JsxElement | ts.JsxSelfClosingElement,
|
|
118
|
+
componentName: string,
|
|
119
|
+
): { hasDataProps: boolean; dataProps: string[] } {
|
|
120
|
+
const attributes = ts.isJsxElement(node)
|
|
121
|
+
? node.openingElement.attributes.properties
|
|
122
|
+
: node.attributes.properties;
|
|
123
|
+
|
|
124
|
+
const dataProps: string[] = [];
|
|
125
|
+
|
|
126
|
+
for (const attr of attributes) {
|
|
127
|
+
// Spread attributes always reference parent data: {...props}
|
|
128
|
+
if (ts.isJsxSpreadAttribute(attr)) {
|
|
129
|
+
const spreadText = attr.expression?.getText() || '...spread';
|
|
130
|
+
dataProps.push(`{...${spreadText}}`);
|
|
131
|
+
console.log(
|
|
132
|
+
`[UnconditionalChild] ${componentName}: Found spread attribute {${spreadText}}`,
|
|
133
|
+
);
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
if (ts.isJsxAttribute(attr)) {
|
|
138
|
+
const propName = attr.name.getText();
|
|
139
|
+
|
|
140
|
+
// Skip callback props - they don't create data-driven execution flows
|
|
141
|
+
// Callbacks typically start with 'on' (onClick, onChange) or 'handle' (handleSubmit)
|
|
142
|
+
if (
|
|
143
|
+
propName.startsWith('on') ||
|
|
144
|
+
propName.startsWith('handle') ||
|
|
145
|
+
propName === 'ref'
|
|
146
|
+
) {
|
|
147
|
+
console.log(
|
|
148
|
+
`[UnconditionalChild] ${componentName}: Skipping callback prop '${propName}'`,
|
|
149
|
+
);
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Check if the prop value is a JSX expression (references a variable)
|
|
154
|
+
// vs a string literal which is static
|
|
155
|
+
if (attr.initializer) {
|
|
156
|
+
if (ts.isJsxExpression(attr.initializer)) {
|
|
157
|
+
// JSX expression like prop={value} - this references a variable
|
|
158
|
+
// Could be a simple identifier, property access, or more complex expression
|
|
159
|
+
const expression = attr.initializer.expression;
|
|
160
|
+
if (expression) {
|
|
161
|
+
// Skip if it's just a function/arrow function (callback)
|
|
162
|
+
if (
|
|
163
|
+
ts.isArrowFunction(expression) ||
|
|
164
|
+
ts.isFunctionExpression(expression)
|
|
165
|
+
) {
|
|
166
|
+
console.log(
|
|
167
|
+
`[UnconditionalChild] ${componentName}: Skipping inline callback prop '${propName}'`,
|
|
168
|
+
);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
// This is a data prop that references parent state/props
|
|
172
|
+
const exprText = expression.getText();
|
|
173
|
+
dataProps.push(`${propName}={${exprText}}`);
|
|
174
|
+
console.log(
|
|
175
|
+
`[UnconditionalChild] ${componentName}: Found data prop '${propName}' = {${exprText}}`,
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
} else {
|
|
179
|
+
// String literals like prop="value" are static
|
|
180
|
+
console.log(
|
|
181
|
+
`[UnconditionalChild] ${componentName}: Skipping static prop '${propName}'`,
|
|
182
|
+
);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
const hasDataProps = dataProps.length > 0;
|
|
189
|
+
if (hasDataProps) {
|
|
190
|
+
console.log(
|
|
191
|
+
`[UnconditionalChild] ${componentName}: Has ${dataProps.length} data props: [${dataProps.join(', ')}]`,
|
|
192
|
+
);
|
|
193
|
+
} else {
|
|
194
|
+
console.log(
|
|
195
|
+
`[UnconditionalChild] ${componentName}: No data props found, will NOT track`,
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return { hasDataProps, dataProps };
|
|
200
|
+
}
|
|
201
|
+
|
|
28
202
|
/**
|
|
29
203
|
* Extracts the component name from a JSX element.
|
|
30
204
|
* Returns null for intrinsic elements (div, span, etc.) since we only care about
|
|
@@ -921,18 +1095,50 @@ function extractConditionalsFromJsx(
|
|
|
921
1095
|
// Recursively process nested JSX elements - Fix 32: pass parent conditions
|
|
922
1096
|
else if (ts.isJsxElement(child)) {
|
|
923
1097
|
// Check if this is a user-defined component (vs intrinsic element like div)
|
|
924
|
-
// If it's a component AND there are parent conditions, record the gating conditions
|
|
925
1098
|
const componentName = getComponentNameFromJsx(child);
|
|
926
|
-
if (componentName
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
1099
|
+
if (componentName) {
|
|
1100
|
+
if (parentConditions.length > 0) {
|
|
1101
|
+
// If there are parent conditions, record them as gating conditions
|
|
1102
|
+
console.log(
|
|
1103
|
+
`[ChildBoundary] ${componentName}: Conditionally rendered with ${parentConditions.length} gating conditions`,
|
|
1104
|
+
);
|
|
1105
|
+
for (const condition of parentConditions) {
|
|
1106
|
+
console.log(
|
|
1107
|
+
`[ChildBoundary] ${componentName}: Adding gating condition path='${condition.path}' isNegated=${condition.isNegated}`,
|
|
1108
|
+
);
|
|
1109
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
1110
|
+
path: condition.path,
|
|
1111
|
+
conditionType: 'truthiness',
|
|
1112
|
+
location: 'ternary',
|
|
1113
|
+
sourceLocation: condition.sourceLocation,
|
|
1114
|
+
controlsJsxRendering: true,
|
|
1115
|
+
isNegated: condition.isNegated,
|
|
1116
|
+
});
|
|
1117
|
+
}
|
|
1118
|
+
} else {
|
|
1119
|
+
// No parent conditions - check if it has data props for unconditional tracking
|
|
1120
|
+
console.log(
|
|
1121
|
+
`[ChildBoundary] ${componentName}: Checking for unconditional rendering with data props...`,
|
|
1122
|
+
);
|
|
1123
|
+
const { hasDataProps, dataProps } = hasDataPropsFromParent(
|
|
1124
|
+
child,
|
|
1125
|
+
componentName,
|
|
1126
|
+
);
|
|
1127
|
+
if (hasDataProps) {
|
|
1128
|
+
// Fix: Track unconditionally-rendered children that receive data props
|
|
1129
|
+
// These need to be tracked for flow merging even without gating conditions
|
|
1130
|
+
// Example: <WorkoutsView workouts={workouts} /> - parent controls workouts data
|
|
1131
|
+
console.log(
|
|
1132
|
+
`[ChildBoundary] ${componentName}: TRACKING as unconditionally-rendered with data props: [${dataProps.join(', ')}]`,
|
|
1133
|
+
);
|
|
1134
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
1135
|
+
path: '__unconditional__',
|
|
1136
|
+
conditionType: 'truthiness',
|
|
1137
|
+
location: 'unconditional',
|
|
1138
|
+
controlsJsxRendering: true,
|
|
1139
|
+
isNegated: false,
|
|
1140
|
+
});
|
|
1141
|
+
}
|
|
936
1142
|
}
|
|
937
1143
|
}
|
|
938
1144
|
extractConditionalsFromJsx(child, context, parentConditions);
|
|
@@ -940,18 +1146,48 @@ function extractConditionalsFromJsx(
|
|
|
940
1146
|
// Handle self-closing JSX elements (e.g., <ScenarioViewer />)
|
|
941
1147
|
else if (ts.isJsxSelfClosingElement(child)) {
|
|
942
1148
|
// Check if this is a user-defined component (vs intrinsic element like div)
|
|
943
|
-
// If it's a component AND there are parent conditions, record the gating conditions
|
|
944
1149
|
const componentName = getComponentNameFromJsx(child);
|
|
945
|
-
if (componentName
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
1150
|
+
if (componentName) {
|
|
1151
|
+
if (parentConditions.length > 0) {
|
|
1152
|
+
// If there are parent conditions, record them as gating conditions
|
|
1153
|
+
console.log(
|
|
1154
|
+
`[ChildBoundary] ${componentName}: Conditionally rendered (self-closing) with ${parentConditions.length} gating conditions`,
|
|
1155
|
+
);
|
|
1156
|
+
for (const condition of parentConditions) {
|
|
1157
|
+
console.log(
|
|
1158
|
+
`[ChildBoundary] ${componentName}: Adding gating condition path='${condition.path}' isNegated=${condition.isNegated}`,
|
|
1159
|
+
);
|
|
1160
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
1161
|
+
path: condition.path,
|
|
1162
|
+
conditionType: 'truthiness',
|
|
1163
|
+
location: 'ternary',
|
|
1164
|
+
sourceLocation: condition.sourceLocation,
|
|
1165
|
+
controlsJsxRendering: true,
|
|
1166
|
+
isNegated: condition.isNegated,
|
|
1167
|
+
});
|
|
1168
|
+
}
|
|
1169
|
+
} else {
|
|
1170
|
+
// No parent conditions - check if it has data props for unconditional tracking
|
|
1171
|
+
console.log(
|
|
1172
|
+
`[ChildBoundary] ${componentName}: Checking for unconditional rendering (self-closing) with data props...`,
|
|
1173
|
+
);
|
|
1174
|
+
const { hasDataProps, dataProps } = hasDataPropsFromParent(
|
|
1175
|
+
child,
|
|
1176
|
+
componentName,
|
|
1177
|
+
);
|
|
1178
|
+
if (hasDataProps) {
|
|
1179
|
+
// Fix: Track unconditionally-rendered children that receive data props
|
|
1180
|
+
console.log(
|
|
1181
|
+
`[ChildBoundary] ${componentName}: TRACKING as unconditionally-rendered (self-closing) with data props: [${dataProps.join(', ')}]`,
|
|
1182
|
+
);
|
|
1183
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
1184
|
+
path: '__unconditional__',
|
|
1185
|
+
conditionType: 'truthiness',
|
|
1186
|
+
location: 'unconditional',
|
|
1187
|
+
controlsJsxRendering: true,
|
|
1188
|
+
isNegated: false,
|
|
1189
|
+
});
|
|
1190
|
+
}
|
|
955
1191
|
}
|
|
956
1192
|
}
|
|
957
1193
|
// Self-closing elements have no children, so no recursion needed
|
|
@@ -1127,6 +1363,11 @@ export function extractConditionalUsage(
|
|
|
1127
1363
|
return literalValue;
|
|
1128
1364
|
};
|
|
1129
1365
|
|
|
1366
|
+
// Get the comparison operator string for the compound condition
|
|
1367
|
+
const comparisonOperator = getComparisonOperatorString(
|
|
1368
|
+
unwrapped.operatorToken.kind,
|
|
1369
|
+
);
|
|
1370
|
+
|
|
1130
1371
|
// Helper to add a condition
|
|
1131
1372
|
const addCondition = (
|
|
1132
1373
|
path: string,
|
|
@@ -1171,6 +1412,7 @@ export function extractConditionalUsage(
|
|
|
1171
1412
|
comparedValues,
|
|
1172
1413
|
isNegated,
|
|
1173
1414
|
requiredValue,
|
|
1415
|
+
...(comparisonOperator && { comparisonOperator }),
|
|
1174
1416
|
...(chainInfo.currentOrGroupId && {
|
|
1175
1417
|
orGroupId: chainInfo.currentOrGroupId,
|
|
1176
1418
|
}),
|
|
@@ -1449,7 +1691,7 @@ export function processExpression({
|
|
|
1449
1691
|
const structure = context.getStructure();
|
|
1450
1692
|
|
|
1451
1693
|
// Propagate existing equivalencies for sub-properties
|
|
1452
|
-
for (const [key,
|
|
1694
|
+
for (const [key, rawValue] of Object.entries(equivalentVariables)) {
|
|
1453
1695
|
// Check if this equivalency is for a sub-property of the identifier
|
|
1454
1696
|
// e.g., completeDataStructure['Function Arguments'] or completeDataStructure.foo
|
|
1455
1697
|
if (
|
|
@@ -1460,8 +1702,14 @@ export function processExpression({
|
|
|
1460
1702
|
const newTargetPath = StructuredPath.fromBase(
|
|
1461
1703
|
targetPath.toString() + subPath,
|
|
1462
1704
|
);
|
|
1463
|
-
|
|
1464
|
-
|
|
1705
|
+
// Handle both string and string[] values
|
|
1706
|
+
const values = Array.isArray(rawValue) ? rawValue : [rawValue];
|
|
1707
|
+
for (const value of values) {
|
|
1708
|
+
if (typeof value === 'string') {
|
|
1709
|
+
const valuePath = StructuredPath.fromBase(value);
|
|
1710
|
+
context.addEquivalence(newTargetPath, valuePath);
|
|
1711
|
+
}
|
|
1712
|
+
}
|
|
1465
1713
|
}
|
|
1466
1714
|
}
|
|
1467
1715
|
|
|
@@ -1945,23 +2193,47 @@ export function processExpression({
|
|
|
1945
2193
|
// - items[] (from the find result)
|
|
1946
2194
|
// - null (from the fallback)
|
|
1947
2195
|
if (targetPath) {
|
|
1948
|
-
//
|
|
2196
|
+
// Get paths for both sides
|
|
2197
|
+
const leftPath = StructuredPath.fromNode(
|
|
2198
|
+
unwrappedNode.left,
|
|
2199
|
+
context.sourceFile,
|
|
2200
|
+
);
|
|
2201
|
+
const rightPath = StructuredPath.fromNode(
|
|
2202
|
+
unwrappedNode.right,
|
|
2203
|
+
context.sourceFile,
|
|
2204
|
+
);
|
|
2205
|
+
|
|
2206
|
+
// Collect all valid paths
|
|
2207
|
+
const allPaths: StructuredPath[] = [];
|
|
2208
|
+
if (leftPath) allPaths.push(leftPath);
|
|
2209
|
+
if (rightPath) allPaths.push(rightPath);
|
|
2210
|
+
|
|
2211
|
+
// Add multiple equivalencies to track both sources
|
|
2212
|
+
if (allPaths.length > 0) {
|
|
2213
|
+
context.addMultipleEquivalencies(targetPath, allPaths);
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
// Process both sides to capture their internal structures
|
|
1949
2217
|
processExpression({
|
|
1950
2218
|
node: unwrappedNode.left,
|
|
1951
2219
|
context,
|
|
1952
|
-
targetPath,
|
|
1953
2220
|
});
|
|
1954
|
-
// Process right side recursively for completeness
|
|
1955
2221
|
processExpression({
|
|
1956
2222
|
node: unwrappedNode.right,
|
|
1957
2223
|
context,
|
|
1958
|
-
targetPath,
|
|
1959
2224
|
});
|
|
1960
|
-
|
|
1961
|
-
|
|
1962
|
-
|
|
1963
|
-
|
|
1964
|
-
)
|
|
2225
|
+
|
|
2226
|
+
// Register the type for the target path
|
|
2227
|
+
const leftType = context.inferTypeFromNode(unwrappedNode.left);
|
|
2228
|
+
const rightType = context.inferTypeFromNode(unwrappedNode.right);
|
|
2229
|
+
const orResultType = isDefinedType(leftType)
|
|
2230
|
+
? leftType
|
|
2231
|
+
: rightType || 'unknown';
|
|
2232
|
+
context.addType(targetPath, orResultType);
|
|
2233
|
+
|
|
2234
|
+
// Return early - we've already handled equivalencies with addMultipleEquivalencies
|
|
2235
|
+
// Don't fall through to the generic addEquivalence call below
|
|
2236
|
+
return true;
|
|
1965
2237
|
}
|
|
1966
2238
|
// Note: When there's no targetPath, we don't recursively process
|
|
1967
2239
|
// because || is often used in boolean contexts where the full expression matters
|
|
@@ -2071,24 +2343,56 @@ export function processExpression({
|
|
|
2071
2343
|
|
|
2072
2344
|
// Get the source expression path (e.g., the object for obj.method())
|
|
2073
2345
|
const sourceExpr = unwrappedNode.expression.expression;
|
|
2074
|
-
const
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2346
|
+
const unwrappedSourceExpr = unwrapExpression(sourceExpr);
|
|
2347
|
+
|
|
2348
|
+
// When the source is a ternary expression like (cond ? arr : arr.slice()),
|
|
2349
|
+
// apply method semantics to BOTH branches directly. The ternary itself isn't
|
|
2350
|
+
// a variable - it's just a choice between two paths that both flow to the result.
|
|
2351
|
+
if (ts.isConditionalExpression(unwrappedSourceExpr)) {
|
|
2352
|
+
const branches = [
|
|
2353
|
+
unwrappedSourceExpr.whenTrue,
|
|
2354
|
+
unwrappedSourceExpr.whenFalse,
|
|
2355
|
+
];
|
|
2078
2356
|
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2357
|
+
for (const branch of branches) {
|
|
2358
|
+
const branchPath = StructuredPath.fromNode(
|
|
2359
|
+
branch,
|
|
2360
|
+
context.sourceFile,
|
|
2361
|
+
);
|
|
2362
|
+
if (branchPath) {
|
|
2363
|
+
const isArraySemantics = semantics instanceof ArrayPushSemantics;
|
|
2364
|
+
const shouldApply =
|
|
2365
|
+
!isArraySemantics ||
|
|
2366
|
+
isLikelyArrayType(branch, context.typeChecker);
|
|
2367
|
+
|
|
2368
|
+
if (shouldApply) {
|
|
2369
|
+
semantics.addEquivalences(callPath, branchPath, context);
|
|
2370
|
+
returnType = semantics.getReturnType();
|
|
2371
|
+
handledBySemantics = true;
|
|
2372
|
+
}
|
|
2373
|
+
}
|
|
2374
|
+
}
|
|
2375
|
+
} else {
|
|
2376
|
+
// Regular (non-ternary) source expression
|
|
2377
|
+
const sourcePath = StructuredPath.fromNode(
|
|
2378
|
+
sourceExpr,
|
|
2379
|
+
context.sourceFile,
|
|
2380
|
+
);
|
|
2086
2381
|
|
|
2087
|
-
if (
|
|
2088
|
-
//
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2382
|
+
if (sourcePath) {
|
|
2383
|
+
// For array-specific semantics (like push), verify the source is actually an array
|
|
2384
|
+
// This prevents router.push() from being mistakenly treated as Array.push()
|
|
2385
|
+
const isArraySemantics = semantics instanceof ArrayPushSemantics;
|
|
2386
|
+
const shouldApply =
|
|
2387
|
+
!isArraySemantics ||
|
|
2388
|
+
isLikelyArrayType(sourceExpr, context.typeChecker);
|
|
2389
|
+
|
|
2390
|
+
if (shouldApply) {
|
|
2391
|
+
// Apply method semantics
|
|
2392
|
+
semantics.addEquivalences(callPath, sourcePath, context);
|
|
2393
|
+
returnType = semantics.getReturnType();
|
|
2394
|
+
handledBySemantics = true;
|
|
2395
|
+
}
|
|
2092
2396
|
}
|
|
2093
2397
|
}
|
|
2094
2398
|
}
|
|
@@ -2646,6 +2950,35 @@ export function processExpression({
|
|
|
2646
2950
|
|
|
2647
2951
|
// Handle Arrow Functions: (p) => p.prop, (a, b) => { ... }
|
|
2648
2952
|
if (ts.isArrowFunction(unwrappedNode)) {
|
|
2953
|
+
// If this arrow function is a child boundary (e.g., a .map() callback),
|
|
2954
|
+
// don't process its parameters here - they will be processed when the
|
|
2955
|
+
// child scope is analyzed separately. This prevents parameter variables
|
|
2956
|
+
// from leaking into the parent scope's equivalencies.
|
|
2957
|
+
// Check if this arrow function is a child boundary (i.e., should be processed
|
|
2958
|
+
// as a separate child scope, not here in the parent scope).
|
|
2959
|
+
//
|
|
2960
|
+
// We use two checks because childBoundary positions can be unreliable:
|
|
2961
|
+
// 1. Position-based check (standard isChildBoundary)
|
|
2962
|
+
// 2. Text-based check: if the arrow function text doesn't appear in the
|
|
2963
|
+
// statement text, it was replaced with a cyScope placeholder
|
|
2964
|
+
const isChildBoundary = context.isChildBoundary(unwrappedNode);
|
|
2965
|
+
|
|
2966
|
+
// Text-based child scope detection for when positions are unreliable
|
|
2967
|
+
const arrowFnText = unwrappedNode.getText(context.sourceFile);
|
|
2968
|
+
const firstLine = arrowFnText.split('\n')[0].trim();
|
|
2969
|
+
const searchText = firstLine.substring(0, Math.min(20, firstLine.length));
|
|
2970
|
+
const isInStatementText = context.statementInfo.text.includes(searchText);
|
|
2971
|
+
const isChildScope = !isInStatementText && arrowFnText.length > 10;
|
|
2972
|
+
|
|
2973
|
+
if (isChildBoundary || isChildScope) {
|
|
2974
|
+
// The method semantics (e.g., ArrayMapSemantics) have already established
|
|
2975
|
+
// the necessary equivalences between the child scope placeholder and array elements
|
|
2976
|
+
if (targetPath) {
|
|
2977
|
+
context.addType(targetPath, 'function');
|
|
2978
|
+
}
|
|
2979
|
+
return true;
|
|
2980
|
+
}
|
|
2981
|
+
|
|
2649
2982
|
// Create a path for the function
|
|
2650
2983
|
const functionPath = StructuredPath.empty();
|
|
2651
2984
|
|
|
@@ -3076,6 +3409,19 @@ export function processExpression({
|
|
|
3076
3409
|
for (const child of unwrappedNode.children) {
|
|
3077
3410
|
// Process expressions in JSX children: <div>{expr}</div>
|
|
3078
3411
|
if (ts.isJsxExpression(child) && child.expression) {
|
|
3412
|
+
// When processing return value JSX, link root variables to return value schema
|
|
3413
|
+
if (targetPath && targetPath.base !== '') {
|
|
3414
|
+
const varNames = [
|
|
3415
|
+
...new Set(extractRootVariableNames(child.expression)),
|
|
3416
|
+
];
|
|
3417
|
+
for (const varName of varNames) {
|
|
3418
|
+
context.addEquivalence(
|
|
3419
|
+
targetPath.withProperty(varName),
|
|
3420
|
+
StructuredPath.fromBase(varName),
|
|
3421
|
+
);
|
|
3422
|
+
}
|
|
3423
|
+
}
|
|
3424
|
+
|
|
3079
3425
|
// Process the expression with StructuredPath.empty() as targetPath
|
|
3080
3426
|
// to trigger type registration without imposing prefix
|
|
3081
3427
|
processExpression({
|
|
@@ -3110,6 +3456,19 @@ export function processExpression({
|
|
|
3110
3456
|
for (const child of unwrappedNode.children) {
|
|
3111
3457
|
// Process expressions in JSX children: <>{expr}</>
|
|
3112
3458
|
if (ts.isJsxExpression(child) && child.expression) {
|
|
3459
|
+
// When processing return value JSX, link root variables to return value schema
|
|
3460
|
+
if (targetPath && targetPath.base !== '') {
|
|
3461
|
+
const varNames = [
|
|
3462
|
+
...new Set(extractRootVariableNames(child.expression)),
|
|
3463
|
+
];
|
|
3464
|
+
for (const varName of varNames) {
|
|
3465
|
+
context.addEquivalence(
|
|
3466
|
+
targetPath.withProperty(varName),
|
|
3467
|
+
StructuredPath.fromBase(varName),
|
|
3468
|
+
);
|
|
3469
|
+
}
|
|
3470
|
+
}
|
|
3471
|
+
|
|
3113
3472
|
// Process the expression to extract structure
|
|
3114
3473
|
processExpression({
|
|
3115
3474
|
node: child.expression,
|
|
@@ -71,6 +71,34 @@ export function isComparisonOperator(kind: ts.SyntaxKind): boolean {
|
|
|
71
71
|
);
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Returns the string representation of a comparison operator token.
|
|
76
|
+
*/
|
|
77
|
+
export function getComparisonOperatorString(
|
|
78
|
+
kind: ts.SyntaxKind,
|
|
79
|
+
): string | undefined {
|
|
80
|
+
switch (kind) {
|
|
81
|
+
case ts.SyntaxKind.EqualsEqualsToken:
|
|
82
|
+
return '==';
|
|
83
|
+
case ts.SyntaxKind.EqualsEqualsEqualsToken:
|
|
84
|
+
return '===';
|
|
85
|
+
case ts.SyntaxKind.ExclamationEqualsToken:
|
|
86
|
+
return '!=';
|
|
87
|
+
case ts.SyntaxKind.ExclamationEqualsEqualsToken:
|
|
88
|
+
return '!==';
|
|
89
|
+
case ts.SyntaxKind.LessThanToken:
|
|
90
|
+
return '<';
|
|
91
|
+
case ts.SyntaxKind.LessThanEqualsToken:
|
|
92
|
+
return '<=';
|
|
93
|
+
case ts.SyntaxKind.GreaterThanToken:
|
|
94
|
+
return '>';
|
|
95
|
+
case ts.SyntaxKind.GreaterThanEqualsToken:
|
|
96
|
+
return '>=';
|
|
97
|
+
default:
|
|
98
|
+
return undefined;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
74
102
|
/**
|
|
75
103
|
* Checks if an operator is an arithmetic operator
|
|
76
104
|
*/
|
|
@@ -287,8 +287,9 @@ export interface AstScopeAnalysisResult {
|
|
|
287
287
|
// Variable structure map (variable path -> type)
|
|
288
288
|
structure: Record<string, string>;
|
|
289
289
|
|
|
290
|
-
// Variable equivalence map (variable path -> equivalent variable path)
|
|
291
|
-
|
|
290
|
+
// Variable equivalence map (variable path -> equivalent variable path(s))
|
|
291
|
+
// Supports multiple equivalencies per key for OR expressions (e.g., x = a || b)
|
|
292
|
+
equivalentVariables: Record<string, string | string[]>;
|
|
292
293
|
|
|
293
294
|
// Environment variables accessed in this scope
|
|
294
295
|
environmentVariables: string[];
|
|
@@ -348,8 +349,9 @@ export interface ConditionalUsage {
|
|
|
348
349
|
|
|
349
350
|
/**
|
|
350
351
|
* Where this conditional usage occurs
|
|
352
|
+
* 'unconditional' is used for children that are always rendered but receive data props
|
|
351
353
|
*/
|
|
352
|
-
location: 'if' | 'ternary' | 'logical-and' | 'switch';
|
|
354
|
+
location: 'if' | 'ternary' | 'logical-and' | 'switch' | 'unconditional';
|
|
353
355
|
|
|
354
356
|
/**
|
|
355
357
|
* Source location information for this conditional usage
|
|
@@ -431,6 +433,12 @@ export interface CompoundConditional {
|
|
|
431
433
|
isNegated: boolean;
|
|
432
434
|
/** Required value for this condition to be true */
|
|
433
435
|
requiredValue?: string | boolean;
|
|
436
|
+
/**
|
|
437
|
+
* The comparison operator used (e.g., '>', '<', '>=', '<=', '===', '!==').
|
|
438
|
+
* Preserves the original operator so flow generation can distinguish
|
|
439
|
+
* `length > 0` from `length === 0`.
|
|
440
|
+
*/
|
|
441
|
+
comparisonOperator?: string;
|
|
434
442
|
/**
|
|
435
443
|
* When conditions are part of an OR expression within an && chain,
|
|
436
444
|
* they share the same orGroupId. Conditions with the same orGroupId
|
|
@@ -441,7 +449,7 @@ export interface CompoundConditional {
|
|
|
441
449
|
orGroupId?: string;
|
|
442
450
|
}[];
|
|
443
451
|
/** Where this compound conditional occurs */
|
|
444
|
-
location: 'if' | 'ternary' | 'logical-and' | 'switch';
|
|
452
|
+
location: 'if' | 'ternary' | 'logical-and' | 'switch' | 'unconditional';
|
|
445
453
|
/** Source location for the entire compound expression */
|
|
446
454
|
sourceLocation: {
|
|
447
455
|
lineNumber: number;
|
|
@@ -509,6 +517,13 @@ export interface AnalysisContext {
|
|
|
509
517
|
// Add an equivalence relationship between two variable paths
|
|
510
518
|
addEquivalence(leftSide: StructuredPath, rightSide: StructuredPath): void;
|
|
511
519
|
|
|
520
|
+
// Add multiple equivalence relationships for a single variable path.
|
|
521
|
+
// Used for OR expressions like `x = a || b` where x is equivalent to both a and b.
|
|
522
|
+
addMultipleEquivalencies(
|
|
523
|
+
leftSide: StructuredPath,
|
|
524
|
+
rightSides: StructuredPath[],
|
|
525
|
+
): void;
|
|
526
|
+
|
|
512
527
|
// Add a type for a variable path
|
|
513
528
|
addType(path: StructuredPath, type: string): void;
|
|
514
529
|
|
|
@@ -555,8 +570,8 @@ export interface AnalysisContext {
|
|
|
555
570
|
// Get the built-up structure
|
|
556
571
|
getStructure(): Record<string, string>;
|
|
557
572
|
|
|
558
|
-
// Get the built-up equivalence map
|
|
559
|
-
getEquivalentVariables(): Record<string, string>;
|
|
573
|
+
// Get the built-up equivalence map (supports multiple values for OR expressions)
|
|
574
|
+
getEquivalentVariables(): Record<string, string | string[]>;
|
|
560
575
|
|
|
561
576
|
// Utilties for child boundaries (need to be skipped while capturing equivalencies)
|
|
562
577
|
getChildBoundary(
|