@codeyam/codeyam-cli 0.1.0-staging.e38f7bd → 0.1.0-staging.eb21b2f
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/common/execAsync.ts +1 -1
- package/analyzer-template/log.txt +3 -3
- package/analyzer-template/package.json +21 -17
- package/analyzer-template/packages/ai/index.ts +21 -5
- package/analyzer-template/packages/ai/package.json +4 -4
- package/analyzer-template/packages/ai/src/lib/__mocks__/completionCall.ts +122 -0
- package/analyzer-template/packages/ai/src/lib/analyzeScope.ts +228 -24
- package/analyzer-template/packages/ai/src/lib/astScopes/arrayDerivationDetector.ts +199 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/astScopeAnalyzer.ts +205 -10
- package/analyzer-template/packages/ai/src/lib/astScopes/conditionalEffectsExtractor.ts +644 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/methodSemantics.ts +181 -23
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/forInStatementHandler.ts +10 -17
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/ifStatementHandler.ts +18 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.ts +38 -1
- package/analyzer-template/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.ts +181 -1
- package/analyzer-template/packages/ai/src/lib/astScopes/processExpression.ts +1619 -125
- package/analyzer-template/packages/ai/src/lib/astScopes/sharedPatterns.ts +28 -0
- package/analyzer-template/packages/ai/src/lib/astScopes/types.ts +324 -5
- package/analyzer-template/packages/ai/src/lib/checkAllAttributes.ts +29 -10
- package/analyzer-template/packages/ai/src/lib/completionCall.ts +216 -36
- package/analyzer-template/packages/ai/src/lib/dataStructure/ScopeDataStructure.ts +2543 -399
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.ts +21 -4
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.ts +976 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.ts +243 -77
- 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 +71 -2
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.ts +161 -19
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/coerceObjectsToPrimitivesBySchema.ts +70 -0
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.ts +163 -14
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.ts +98 -0
- 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 +441 -82
- package/analyzer-template/packages/ai/src/lib/dataStructure/helpers/fixNullIdsBySchema.ts +129 -0
- package/analyzer-template/packages/ai/src/lib/dataStructureChunking.ts +183 -0
- package/analyzer-template/packages/ai/src/lib/deepEqual.ts +30 -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/generateChangesEntityScenarioData.ts +74 -7
- package/analyzer-template/packages/ai/src/lib/generateChangesEntityScenarios.ts +89 -112
- package/analyzer-template/packages/ai/src/lib/generateEntityDataStructure.ts +63 -2
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarioData.ts +1419 -101
- package/analyzer-template/packages/ai/src/lib/generateEntityScenarios.ts +216 -109
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlows.ts +710 -0
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.ts +528 -0
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromConditionals.ts +2484 -0
- package/analyzer-template/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.ts +239 -0
- package/analyzer-template/packages/ai/src/lib/getConditionalUsagesFromCode.ts +143 -31
- package/analyzer-template/packages/ai/src/lib/guessScenarioDataFromDescription.ts +8 -2
- package/analyzer-template/packages/ai/src/lib/isolateScopes.ts +328 -7
- package/analyzer-template/packages/ai/src/lib/mergeJsonTypeDefinitions.ts +5 -0
- package/analyzer-template/packages/ai/src/lib/mergeStatements.ts +111 -87
- package/analyzer-template/packages/ai/src/lib/promptGenerators/collapseNullableObjects.ts +118 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/gatherAttributesMap.ts +17 -7
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.ts +1 -1
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.ts +32 -102
- 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 +110 -6
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.ts +14 -53
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateMissingKeysPrompt.ts +58 -0
- package/analyzer-template/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.ts +28 -2
- package/analyzer-template/packages/ai/src/lib/promptGenerators/simplifyKeysForLLM.ts +391 -0
- package/analyzer-template/packages/ai/src/lib/resolvePathToControllable.ts +824 -0
- package/analyzer-template/packages/ai/src/lib/splitOutsideParentheses.ts +5 -1
- package/analyzer-template/packages/ai/src/lib/validateExecutionFlowPaths.ts +531 -0
- package/analyzer-template/packages/ai/src/lib/worker/SerializableDataStructure.ts +127 -3
- package/analyzer-template/packages/ai/src/lib/worker/analyzeScopeWorker.ts +121 -2
- package/analyzer-template/packages/analyze/index.ts +2 -0
- package/analyzer-template/packages/analyze/src/lib/FileAnalyzer.ts +79 -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/nodes/index.ts +1 -0
- package/analyzer-template/packages/analyze/src/lib/asts/nodes/isAsyncFunction.ts +67 -0
- 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 +570 -180
- package/analyzer-template/packages/analyze/src/lib/files/analyze/analyzeEntities.ts +54 -1
- package/analyzer-template/packages/analyze/src/lib/files/analyze/dependencyResolver.ts +6 -0
- package/analyzer-template/packages/analyze/src/lib/files/analyze/findOrCreateEntity.ts +3 -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/analyzeChange.ts +31 -15
- package/analyzer-template/packages/analyze/src/lib/files/analyzeEntity.ts +11 -7
- package/analyzer-template/packages/analyze/src/lib/files/analyzeInitial.ts +11 -12
- package/analyzer-template/packages/analyze/src/lib/files/analyzeRemixRoute.ts +4 -5
- package/analyzer-template/packages/analyze/src/lib/files/enums/steps.ts +1 -1
- package/analyzer-template/packages/analyze/src/lib/files/getImportedExports.ts +22 -13
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/TransformationTracer.ts +1315 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.ts +313 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/enrichUnknownTypesFromSourceEquivalencies.ts +102 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.ts +711 -78
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.ts +1 -1
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateChangesScenarios.ts +28 -62
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateDataStructure.ts +550 -137
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.ts +264 -0
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarioData.ts +78 -83
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateScenarios.ts +4 -8
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.ts +1067 -167
- 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/index.ts +1 -0
- package/analyzer-template/packages/analyze/src/lib/utils/getFileByPath.ts +19 -0
- package/analyzer-template/packages/aws/codebuild/index.ts +1 -0
- package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.d.ts +11 -1
- package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.d.ts.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.js +29 -18
- package/analyzer-template/packages/aws/dist/src/lib/codebuild/waitForBuild.js.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.d.ts +2 -2
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.d.ts.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.js +2 -2
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsDefineContainer.js.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.d.ts +8 -18
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.d.ts.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.js +17 -61
- package/analyzer-template/packages/aws/dist/src/lib/ecs/ecsTaskFactory.js.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.d.ts +15 -0
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.d.ts.map +1 -0
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.js +31 -0
- package/analyzer-template/packages/aws/dist/src/lib/s3/checkS3ObjectExists.js.map +1 -0
- package/analyzer-template/packages/aws/dist/src/lib/s3/uploadFileToS3.d.ts.map +1 -1
- package/analyzer-template/packages/aws/dist/src/lib/s3/uploadFileToS3.js +8 -1
- package/analyzer-template/packages/aws/dist/src/lib/s3/uploadFileToS3.js.map +1 -1
- package/analyzer-template/packages/aws/package.json +3 -3
- package/analyzer-template/packages/aws/s3/index.ts +1 -0
- package/analyzer-template/packages/aws/src/lib/codebuild/waitForBuild.ts +43 -19
- package/analyzer-template/packages/aws/src/lib/ecs/ecsDefineContainer.ts +3 -3
- package/analyzer-template/packages/aws/src/lib/ecs/ecsTaskFactory.ts +17 -69
- package/analyzer-template/packages/aws/src/lib/s3/checkS3ObjectExists.ts +47 -0
- package/analyzer-template/packages/aws/src/lib/s3/uploadFileToS3.ts +8 -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 +18 -5
- package/analyzer-template/packages/database/src/lib/kysely/tableRelations.ts +2 -2
- package/analyzer-template/packages/database/src/lib/kysely/tables/commitsTable.ts +6 -0
- package/analyzer-template/packages/database/src/lib/kysely/tables/debugReportsTable.ts +36 -9
- package/analyzer-template/packages/database/src/lib/kysely/tables/labsRequestsTable.ts +52 -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/loadReadyToBeCapturedAnalyses.ts +30 -5
- 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/updateCommitMetadata.ts +7 -14
- package/analyzer-template/packages/database/src/lib/userScenarioToDb.ts +1 -1
- package/analyzer-template/packages/generate/index.ts +3 -0
- package/analyzer-template/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.ts +17 -1
- package/analyzer-template/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.ts +193 -0
- package/analyzer-template/packages/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.ts +73 -0
- package/analyzer-template/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.ts +9 -4
- package/analyzer-template/packages/generate/src/lib/deepMerge.ts +26 -1
- package/analyzer-template/packages/generate/src/lib/directExecutionScript.ts +17 -2
- package/analyzer-template/packages/generate/src/lib/getComponentScenarioPath.ts +8 -3
- package/analyzer-template/packages/generate/src/lib/scenarioComponentForServer.ts +114 -0
- 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 +4 -2
- 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 +13 -3
- 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/tableRelations.d.ts +2 -2
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/analysesTable.d.ts +1 -11
- 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/kysely/tables/debugReportsTable.d.ts +30 -7
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.js +9 -3
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/debugReportsTable.js.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/entitiesTable.d.ts +1 -0
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/entitiesTable.d.ts.map +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/kysely/tables/scenariosTable.d.ts +2 -6
- package/analyzer-template/packages/github/dist/database/src/lib/kysely/tables/scenariosTable.d.ts.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/loadReadyToBeCapturedAnalyses.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/database/src/lib/loadReadyToBeCapturedAnalyses.js +23 -5
- package/analyzer-template/packages/github/dist/database/src/lib/loadReadyToBeCapturedAnalyses.js.map +1 -1
- 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/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/generate/index.d.ts +3 -0
- package/analyzer-template/packages/github/dist/generate/index.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/index.js +3 -0
- package/analyzer-template/packages/github/dist/generate/index.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +16 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.d.ts +9 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.d.ts.map +1 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js +189 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js.map +1 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.d.ts +20 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.d.ts.map +1 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js +53 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js.map +1 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +8 -4
- package/analyzer-template/packages/github/dist/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.js +27 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/deepMerge.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/directExecutionScript.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/directExecutionScript.js +10 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/directExecutionScript.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/getComponentScenarioPath.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/getComponentScenarioPath.js +7 -3
- package/analyzer-template/packages/github/dist/generate/src/lib/getComponentScenarioPath.js.map +1 -1
- package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.d.ts +8 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.d.ts.map +1 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.js +89 -0
- package/analyzer-template/packages/github/dist/generate/src/lib/scenarioComponentForServer.js.map +1 -0
- package/analyzer-template/packages/github/dist/github/src/lib/loadOrCreateCommit.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/github/src/lib/loadOrCreateCommit.js +10 -0
- package/analyzer-template/packages/github/dist/github/src/lib/loadOrCreateCommit.js.map +1 -1
- package/analyzer-template/packages/github/dist/github/src/lib/syncPrimaryBranch.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/github/src/lib/syncPrimaryBranch.js +3 -0
- package/analyzer-template/packages/github/dist/github/src/lib/syncPrimaryBranch.js.map +1 -1
- package/analyzer-template/packages/github/dist/types/index.d.ts +2 -2
- 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 +87 -13
- 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/Entity.d.ts +2 -0
- package/analyzer-template/packages/github/dist/types/src/types/Entity.d.ts.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/Scenario.d.ts +11 -6
- package/analyzer-template/packages/github/dist/types/src/types/Scenario.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/types/src/types/ScenariosDataStructure.d.ts +199 -3
- 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/types/src/types/StatementInfo.d.ts +2 -0
- package/analyzer-template/packages/github/dist/types/src/types/StatementInfo.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/applyUniversalMocks.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/applyUniversalMocks.js +26 -2
- package/analyzer-template/packages/github/dist/utils/src/lib/applyUniversalMocks.js.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
- package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js +25 -0
- package/analyzer-template/packages/github/dist/utils/src/lib/lightweightEntityExtractor.js.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/github/src/lib/loadOrCreateCommit.ts +14 -0
- package/analyzer-template/packages/github/src/lib/syncPrimaryBranch.ts +2 -0
- package/analyzer-template/packages/process/index.ts +2 -0
- package/analyzer-template/packages/process/package.json +12 -0
- package/analyzer-template/packages/process/tsconfig.json +8 -0
- package/analyzer-template/packages/types/index.ts +5 -0
- package/analyzer-template/packages/types/src/types/Analysis.ts +104 -13
- package/analyzer-template/packages/types/src/types/Commit.ts +2 -0
- package/analyzer-template/packages/types/src/types/Entity.ts +2 -0
- package/analyzer-template/packages/types/src/types/ProjectMetadata.ts +7 -0
- package/analyzer-template/packages/types/src/types/Scenario.ts +11 -10
- package/analyzer-template/packages/types/src/types/ScenariosDataStructure.ts +228 -3
- package/analyzer-template/packages/types/src/types/ScopeAnalysis.ts +6 -1
- package/analyzer-template/packages/types/src/types/StatementInfo.ts +2 -0
- package/analyzer-template/packages/ui-components/package.json +4 -4
- package/analyzer-template/packages/ui-components/src/components/ScenarioDetailInteractiveView.tsx +23 -7
- package/analyzer-template/packages/utils/dist/types/index.d.ts +2 -2
- 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 +87 -13
- 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/Entity.d.ts +2 -0
- package/analyzer-template/packages/utils/dist/types/src/types/Entity.d.ts.map +1 -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/Scenario.d.ts +11 -6
- package/analyzer-template/packages/utils/dist/types/src/types/Scenario.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/types/src/types/ScenariosDataStructure.d.ts +199 -3
- 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/types/src/types/StatementInfo.d.ts +2 -0
- package/analyzer-template/packages/utils/dist/types/src/types/StatementInfo.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/applyUniversalMocks.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/applyUniversalMocks.js +26 -2
- package/analyzer-template/packages/utils/dist/utils/src/lib/applyUniversalMocks.js.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js +93 -2
- package/analyzer-template/packages/utils/dist/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.d.ts.map +1 -1
- package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js +25 -0
- package/analyzer-template/packages/utils/dist/utils/src/lib/lightweightEntityExtractor.js.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/applyUniversalMocks.ts +28 -2
- package/analyzer-template/packages/utils/src/lib/fs/rsyncCopy.ts +108 -2
- package/analyzer-template/packages/utils/src/lib/lightweightEntityExtractor.ts +27 -0
- package/analyzer-template/packages/utils/src/lib/safeFileName.ts +48 -3
- package/analyzer-template/playwright/capture.ts +57 -26
- package/analyzer-template/playwright/captureStatic.ts +1 -1
- package/analyzer-template/playwright/getCodeYamInfo.ts +12 -7
- package/analyzer-template/playwright/takeElementScreenshot.ts +26 -11
- package/analyzer-template/playwright/takeScreenshot.ts +15 -9
- package/analyzer-template/playwright/waitForServer.ts +21 -6
- package/analyzer-template/project/TESTING.md +83 -0
- package/analyzer-template/project/analyzeBaselineCommit.ts +9 -0
- package/analyzer-template/project/analyzeBranchCommit.ts +4 -0
- package/analyzer-template/project/analyzeFileEntities.ts +4 -0
- package/analyzer-template/project/analyzeRegularCommit.ts +9 -0
- package/analyzer-template/project/captureLibraryFunctionDirect.ts +29 -26
- package/analyzer-template/project/constructMockCode.ts +1319 -158
- package/analyzer-template/project/controller/startController.ts +16 -1
- package/analyzer-template/project/createEntitiesAndSortFiles.ts +83 -0
- package/analyzer-template/project/executeLibraryFunctionDirect.ts +7 -3
- package/analyzer-template/project/loadReadyToBeCaptured.ts +82 -42
- package/analyzer-template/project/mocks/analyzeFileMock.ts +8 -7
- package/analyzer-template/project/orchestrateCapture/AwsCaptureTaskRunner.ts +12 -4
- package/analyzer-template/project/orchestrateCapture/KyselyAnalysisLoader.ts +13 -9
- package/analyzer-template/project/orchestrateCapture/SequentialCaptureTaskRunner.ts +93 -42
- package/analyzer-template/project/orchestrateCapture/taskRunner.ts +4 -2
- package/analyzer-template/project/orchestrateCapture.ts +88 -12
- package/analyzer-template/project/reconcileMockDataKeys.ts +245 -2
- package/analyzer-template/project/runAnalysis.ts +11 -0
- package/analyzer-template/project/runMultiScenarioServer.ts +11 -10
- package/analyzer-template/project/serverOnlyModules.ts +413 -0
- package/analyzer-template/project/start.ts +72 -19
- package/analyzer-template/project/startScenarioCapture.ts +79 -41
- package/analyzer-template/project/writeMockDataTsx.ts +466 -73
- package/analyzer-template/project/writeScenarioClientWrapper.ts +21 -0
- package/analyzer-template/project/writeScenarioComponents.ts +1447 -214
- package/analyzer-template/project/writeScenarioFiles.ts +26 -0
- package/analyzer-template/project/writeSimpleRoot.ts +56 -22
- package/analyzer-template/project/writeUniversalMocks.ts +32 -11
- package/analyzer-template/scripts/comboWorkerLoop.cjs +99 -50
- package/analyzer-template/scripts/defaultCmd.sh +9 -0
- package/analyzer-template/tsconfig.json +2 -1
- package/background/src/lib/local/createLocalAnalyzer.js +2 -30
- package/background/src/lib/local/createLocalAnalyzer.js.map +1 -1
- package/background/src/lib/local/execAsync.js +1 -1
- package/background/src/lib/local/execAsync.js.map +1 -1
- package/background/src/lib/virtualized/common/execAsync.js +1 -1
- package/background/src/lib/virtualized/common/execAsync.js.map +1 -1
- package/background/src/lib/virtualized/project/analyzeBaselineCommit.js +7 -1
- package/background/src/lib/virtualized/project/analyzeBaselineCommit.js.map +1 -1
- package/background/src/lib/virtualized/project/analyzeBranchCommit.js +2 -1
- package/background/src/lib/virtualized/project/analyzeBranchCommit.js.map +1 -1
- package/background/src/lib/virtualized/project/analyzeFileEntities.js +2 -1
- package/background/src/lib/virtualized/project/analyzeFileEntities.js.map +1 -1
- package/background/src/lib/virtualized/project/analyzeRegularCommit.js +7 -1
- 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 +1171 -120
- package/background/src/lib/virtualized/project/constructMockCode.js.map +1 -1
- package/background/src/lib/virtualized/project/controller/startController.js +11 -1
- package/background/src/lib/virtualized/project/controller/startController.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/executeLibraryFunctionDirect.js +6 -3
- package/background/src/lib/virtualized/project/executeLibraryFunctionDirect.js.map +1 -1
- package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js +34 -9
- package/background/src/lib/virtualized/project/loadReadyToBeCaptured.js.map +1 -1
- package/background/src/lib/virtualized/project/mocks/analyzeFileMock.js +7 -7
- package/background/src/lib/virtualized/project/mocks/analyzeFileMock.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/KyselyAnalysisLoader.js +12 -6
- package/background/src/lib/virtualized/project/orchestrateCapture/KyselyAnalysisLoader.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js +73 -36
- package/background/src/lib/virtualized/project/orchestrateCapture/SequentialCaptureTaskRunner.js.map +1 -1
- package/background/src/lib/virtualized/project/orchestrateCapture.js +72 -13
- package/background/src/lib/virtualized/project/orchestrateCapture.js.map +1 -1
- package/background/src/lib/virtualized/project/reconcileMockDataKeys.js +204 -2
- package/background/src/lib/virtualized/project/reconcileMockDataKeys.js.map +1 -1
- package/background/src/lib/virtualized/project/runAnalysis.js +9 -0
- package/background/src/lib/virtualized/project/runAnalysis.js.map +1 -1
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js +11 -9
- package/background/src/lib/virtualized/project/runMultiScenarioServer.js.map +1 -1
- package/background/src/lib/virtualized/project/serverOnlyModules.js +338 -0
- package/background/src/lib/virtualized/project/serverOnlyModules.js.map +1 -0
- package/background/src/lib/virtualized/project/start.js +62 -19
- package/background/src/lib/virtualized/project/start.js.map +1 -1
- package/background/src/lib/virtualized/project/startScenarioCapture.js +61 -31
- package/background/src/lib/virtualized/project/startScenarioCapture.js.map +1 -1
- package/background/src/lib/virtualized/project/writeMockDataTsx.js +404 -62
- package/background/src/lib/virtualized/project/writeMockDataTsx.js.map +1 -1
- package/background/src/lib/virtualized/project/writeScenarioClientWrapper.js +15 -0
- package/background/src/lib/virtualized/project/writeScenarioClientWrapper.js.map +1 -0
- package/background/src/lib/virtualized/project/writeScenarioComponents.js +1066 -146
- package/background/src/lib/virtualized/project/writeScenarioComponents.js.map +1 -1
- package/background/src/lib/virtualized/project/writeScenarioFiles.js +19 -0
- package/background/src/lib/virtualized/project/writeScenarioFiles.js.map +1 -1
- package/background/src/lib/virtualized/project/writeSimpleRoot.js +57 -20
- package/background/src/lib/virtualized/project/writeSimpleRoot.js.map +1 -1
- package/background/src/lib/virtualized/project/writeUniversalMocks.js +27 -12
- package/background/src/lib/virtualized/project/writeUniversalMocks.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 +11 -1
- 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 +5 -3
- package/codeyam-cli/src/commands/analyze.js.map +1 -1
- package/codeyam-cli/src/commands/baseline.js +176 -0
- package/codeyam-cli/src/commands/baseline.js.map +1 -0
- package/codeyam-cli/src/commands/debug.js +44 -18
- package/codeyam-cli/src/commands/debug.js.map +1 -1
- package/codeyam-cli/src/commands/default.js +30 -34
- 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 +307 -0
- package/codeyam-cli/src/commands/memory.js.map +1 -0
- package/codeyam-cli/src/commands/recapture.js +228 -0
- package/codeyam-cli/src/commands/recapture.js.map +1 -0
- package/codeyam-cli/src/commands/report.js +72 -24
- package/codeyam-cli/src/commands/report.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/start.js +8 -12
- package/codeyam-cli/src/commands/start.js.map +1 -1
- package/codeyam-cli/src/commands/status.js +23 -1
- package/codeyam-cli/src/commands/status.js.map +1 -1
- package/codeyam-cli/src/commands/test-startup.js +3 -1
- 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/commands/wipe.js +108 -0
- package/codeyam-cli/src/commands/wipe.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js +179 -0
- package/codeyam-cli/src/utils/__tests__/npmVersionCheck.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/serverVersionStaleness.test.js +81 -0
- package/codeyam-cli/src/utils/__tests__/serverVersionStaleness.test.js.map +1 -0
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js +128 -82
- package/codeyam-cli/src/utils/__tests__/setupClaudeCodeSettings.test.js.map +1 -1
- package/codeyam-cli/src/utils/analysisRunner.js +29 -15
- package/codeyam-cli/src/utils/analysisRunner.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 +104 -23
- package/codeyam-cli/src/utils/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/utils/database.js +91 -5
- package/codeyam-cli/src/utils/database.js.map +1 -1
- package/codeyam-cli/src/utils/generateReport.js +253 -106
- package/codeyam-cli/src/utils/generateReport.js.map +1 -1
- package/codeyam-cli/src/utils/git.js +79 -0
- package/codeyam-cli/src/utils/git.js.map +1 -0
- package/codeyam-cli/src/utils/install-skills.js +76 -42
- 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/npmVersionCheck.js +76 -0
- package/codeyam-cli/src/utils/npmVersionCheck.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/__tests__/manager.test.js +38 -0
- package/codeyam-cli/src/utils/queue/__tests__/manager.test.js.map +1 -1
- package/codeyam-cli/src/utils/queue/job.js +249 -16
- package/codeyam-cli/src/utils/queue/job.js.map +1 -1
- package/codeyam-cli/src/utils/queue/manager.js +103 -7
- package/codeyam-cli/src/utils/queue/manager.js.map +1 -1
- package/codeyam-cli/src/utils/queue/persistence.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 +116 -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 +6 -0
- package/codeyam-cli/src/utils/rules/index.js.map +1 -0
- package/codeyam-cli/src/utils/rules/parser.js +83 -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/ruleState.js +150 -0
- package/codeyam-cli/src/utils/rules/ruleState.js.map +1 -0
- package/codeyam-cli/src/utils/rules/staleness.js +137 -0
- package/codeyam-cli/src/utils/rules/staleness.js.map +1 -0
- 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 -42
- package/codeyam-cli/src/utils/setupClaudeCodeSettings.js.map +1 -1
- package/codeyam-cli/src/utils/versionInfo.js +46 -15
- package/codeyam-cli/src/utils/versionInfo.js.map +1 -1
- package/codeyam-cli/src/utils/wipe.js +128 -0
- package/codeyam-cli/src/utils/wipe.js.map +1 -0
- package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js +66 -0
- package/codeyam-cli/src/webserver/__tests__/dependency-smoke.test.js.map +1 -0
- package/codeyam-cli/src/webserver/app/lib/database.js +118 -6
- package/codeyam-cli/src/webserver/app/lib/database.js.map +1 -1
- package/codeyam-cli/src/webserver/app/lib/dbNotifier.js.map +1 -1
- package/codeyam-cli/src/webserver/backgroundServer.js +55 -10
- package/codeyam-cli/src/webserver/backgroundServer.js.map +1 -1
- package/codeyam-cli/src/webserver/bootstrap.js +60 -0
- package/codeyam-cli/src/webserver/bootstrap.js.map +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/CopyButton-jNYXRRNI.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/EntityItem-bwuHPyTa.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/{EntityTypeBadge-kykTbcnD.js → EntityTypeBadge-CvzqMxcu.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-BH0XDim7.js +41 -0
- package/codeyam-cli/src/webserver/build/client/assets/InlineSpinner-EhOseatT.js +34 -0
- package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-yjIHlOGa.js +25 -0
- package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-Cq5o8jL4.js +3 -0
- package/codeyam-cli/src/webserver/build/client/assets/LoadingDots-BvMu2i-g.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/LogViewer-kgBTLoJD.js +3 -0
- package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-BzPgx-xO.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-CwZrv-Ok.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-BX2Ny2Qj.js +10 -0
- package/codeyam-cli/src/webserver/build/client/assets/{TruncatedFilePath-C06nsHKY.js → TruncatedFilePath-CDpEprKa.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/_index-BRx8ZGZo.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-4S4yPfFw.js +27 -0
- package/codeyam-cli/src/webserver/build/client/assets/agent-transcripts-DHKuQSmR.js +17 -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.health-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.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/api.save-fixture-l0sNRNKZ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/book-open-D4IPYH_y.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/chevron-down-CG65viiV.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/chunk-JZWAC4HX-DB3aFuEO.js +51 -0
- package/codeyam-cli/src/webserver/build/client/assets/circle-check-igfMr5DY.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/copy-Coc4o_8c.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-D1zB-pYc.js +21 -0
- package/codeyam-cli/src/webserver/build/client/assets/{cy-logo-cli-C1gnJVOL.svg → cy-logo-cli-CCKUIm0S.svg} +2 -2
- package/codeyam-cli/src/webserver/build/client/assets/cy-logo-cli-DcX-ZS3p.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-JTAjQ54M.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{entity._sha._-CYqBrC9s.js → entity._sha._-B0h9AqE6.js} +22 -15
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha.scenarios._scenarioId.fullscreen-DjLxr2JB.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-CtYowLOt.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-PePWg17F.js +5 -0
- package/codeyam-cli/src/webserver/build/client/assets/entry.client-I-Wo99C_.js +29 -0
- package/codeyam-cli/src/webserver/build/client/assets/executionFlowCoverage-BWhdfn70.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-9sMMAiWJ.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/files-Co65J0s3.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/git-BdHOxVfg.js +15 -0
- package/codeyam-cli/src/webserver/build/client/assets/globals-CCgBKWy4.css +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/html2canvas-pro.esm-fmIEn3Bc.js +9 -0
- package/codeyam-cli/src/webserver/build/client/assets/index-CUM5iXwc.js +9 -0
- package/codeyam-cli/src/webserver/build/client/assets/index-_417gcQW.js +3 -0
- package/codeyam-cli/src/webserver/build/client/assets/labs-BK0C1H1T.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/loader-circle-TzRHMVog.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/manifest-390cb8fa.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/memory-CzZySbBE.js +78 -0
- package/codeyam-cli/src/webserver/build/client/assets/pause-hjzB7t2z.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/preload-helper-ckwbz45p.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/root-DnbDhvTU.js +62 -0
- package/codeyam-cli/src/webserver/build/client/assets/scenarioStatus-B_8jpV3e.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/search-DcAwD_Ln.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/settings-CclxrcPK.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/simulations-DVNJVQgD.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/terminal-DbEAHMbA.js +11 -0
- package/codeyam-cli/src/webserver/build/client/assets/triangle-alert-CAD5b1o_.js +6 -0
- package/codeyam-cli/src/webserver/build/client/assets/useCustomSizes-BqgrAzs3.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{useLastLogLine-Blr5oZDE.js → useLastLogLine-DAFqfEDH.js} +1 -1
- package/codeyam-cli/src/webserver/build/client/assets/useReportContext-DZlYx2c4.js +1 -0
- package/codeyam-cli/src/webserver/build/client/assets/{useToast-Bbf4Hokd.js → useToast-ihdMtlf6.js} +1 -1
- package/codeyam-cli/src/webserver/build/server/assets/index-CXfuiwt3.js +1 -0
- package/codeyam-cli/src/webserver/build/server/assets/server-build-BSvme_Ao.js +259 -0
- package/codeyam-cli/src/webserver/build/server/index.js +1 -1
- package/codeyam-cli/src/webserver/build-info.json +5 -5
- package/codeyam-cli/src/webserver/devServer.js +1 -3
- package/codeyam-cli/src/webserver/devServer.js.map +1 -1
- package/codeyam-cli/src/webserver/server.js +35 -25
- package/codeyam-cli/src/webserver/server.js.map +1 -1
- package/codeyam-cli/templates/{codeyam-debug-skill.md → codeyam-debug.md} +48 -4
- package/codeyam-cli/templates/codeyam-diagnose.md +481 -0
- package/codeyam-cli/templates/codeyam-memory-hook.sh +199 -0
- package/codeyam-cli/templates/codeyam-memory.md +396 -0
- package/codeyam-cli/templates/codeyam-new-rule.md +13 -0
- package/codeyam-cli/templates/{codeyam-setup-skill.md → codeyam-setup.md} +151 -4
- package/codeyam-cli/templates/{codeyam-sim-skill.md → codeyam-sim.md} +1 -1
- package/codeyam-cli/templates/{codeyam-test-skill.md → codeyam-test.md} +1 -1
- package/codeyam-cli/templates/{codeyam-verify-skill.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 +25 -22
- package/packages/ai/index.js +8 -6
- package/packages/ai/index.js.map +1 -1
- package/packages/ai/src/lib/analyzeScope.js +181 -13
- 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 +154 -9
- package/packages/ai/src/lib/astScopes/astScopeAnalyzer.js.map +1 -1
- package/packages/ai/src/lib/astScopes/conditionalEffectsExtractor.js +435 -0
- package/packages/ai/src/lib/astScopes/conditionalEffectsExtractor.js.map +1 -0
- package/packages/ai/src/lib/astScopes/methodSemantics.js +138 -23
- package/packages/ai/src/lib/astScopes/methodSemantics.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/patterns/ifStatementHandler.js +8 -0
- package/packages/ai/src/lib/astScopes/patterns/ifStatementHandler.js.map +1 -1
- package/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.js +23 -0
- package/packages/ai/src/lib/astScopes/patterns/switchStatementHandler.js.map +1 -1
- package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js +138 -1
- package/packages/ai/src/lib/astScopes/patterns/variableDeclarationHandler.js.map +1 -1
- package/packages/ai/src/lib/astScopes/processExpression.js +1235 -104
- 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/checkAllAttributes.js +24 -9
- package/packages/ai/src/lib/checkAllAttributes.js.map +1 -1
- package/packages/ai/src/lib/completionCall.js +178 -31
- package/packages/ai/src/lib/completionCall.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js +1961 -224
- package/packages/ai/src/lib/dataStructure/ScopeDataStructure.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js +19 -4
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/JavascriptFrameworkManager.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js +661 -0
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/MuiManager.js.map +1 -0
- package/packages/ai/src/lib/dataStructure/equivalencyManagers/frameworks/ReactFrameworkManager.js +180 -56
- 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 +66 -2
- package/packages/ai/src/lib/dataStructure/helpers/cleanKnownObjectFunctions.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/cleanNonObjectFunctions.js +139 -13
- 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 +142 -12
- package/packages/ai/src/lib/dataStructure/helpers/convertDotNotation.js.map +1 -1
- package/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.js +86 -0
- package/packages/ai/src/lib/dataStructure/helpers/convertNullToUndefinedBySchema.js.map +1 -0
- 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 +371 -73
- 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 +130 -0
- package/packages/ai/src/lib/dataStructureChunking.js.map +1 -0
- package/packages/ai/src/lib/deepEqual.js +32 -0
- package/packages/ai/src/lib/deepEqual.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/generateChangesEntityScenarioData.js +62 -5
- package/packages/ai/src/lib/generateChangesEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateChangesEntityScenarios.js +81 -90
- package/packages/ai/src/lib/generateChangesEntityScenarios.js.map +1 -1
- package/packages/ai/src/lib/generateEntityDataStructure.js +50 -1
- package/packages/ai/src/lib/generateEntityDataStructure.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarioData.js +1127 -91
- package/packages/ai/src/lib/generateEntityScenarioData.js.map +1 -1
- package/packages/ai/src/lib/generateEntityScenarios.js +193 -83
- package/packages/ai/src/lib/generateEntityScenarios.js.map +1 -1
- package/packages/ai/src/lib/generateExecutionFlows.js +495 -0
- package/packages/ai/src/lib/generateExecutionFlows.js.map +1 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.js +380 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionalEffects.js.map +1 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js +1807 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromConditionals.js.map +1 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js +194 -0
- package/packages/ai/src/lib/generateExecutionFlowsFromJsxUsages.js.map +1 -0
- package/packages/ai/src/lib/getConditionalUsagesFromCode.js +84 -14
- package/packages/ai/src/lib/getConditionalUsagesFromCode.js.map +1 -1
- package/packages/ai/src/lib/guessScenarioDataFromDescription.js +2 -1
- package/packages/ai/src/lib/guessScenarioDataFromDescription.js.map +1 -1
- package/packages/ai/src/lib/isolateScopes.js +270 -7
- 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 +88 -46
- 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 +16 -4
- package/packages/ai/src/lib/promptGenerators/gatherAttributesMap.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenarioDataGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.js +21 -64
- package/packages/ai/src/lib/promptGenerators/generateChangesEntityScenariosGenerator.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 +83 -6
- package/packages/ai/src/lib/promptGenerators/generateEntityScenarioDataGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js +10 -34
- package/packages/ai/src/lib/promptGenerators/generateEntityScenariosGenerator.js.map +1 -1
- package/packages/ai/src/lib/promptGenerators/generateMissingKeysPrompt.js +45 -0
- package/packages/ai/src/lib/promptGenerators/generateMissingKeysPrompt.js.map +1 -0
- package/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.js +16 -3
- package/packages/ai/src/lib/promptGenerators/guessNewScenarioDataFromDescriptionGenerator.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 +677 -0
- package/packages/ai/src/lib/resolvePathToControllable.js.map +1 -0
- package/packages/ai/src/lib/splitOutsideParentheses.js +3 -1
- package/packages/ai/src/lib/splitOutsideParentheses.js.map +1 -1
- package/packages/ai/src/lib/worker/SerializableDataStructure.js +29 -0
- package/packages/ai/src/lib/worker/SerializableDataStructure.js.map +1 -1
- package/packages/ai/src/lib/worker/analyzeScopeWorker.js +98 -1
- package/packages/ai/src/lib/worker/analyzeScopeWorker.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 +75 -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/nodes/index.js +1 -0
- package/packages/analyze/src/lib/asts/nodes/index.js.map +1 -1
- package/packages/analyze/src/lib/asts/nodes/isAsyncFunction.js +52 -0
- package/packages/analyze/src/lib/asts/nodes/isAsyncFunction.js.map +1 -0
- 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 +428 -123
- package/packages/analyze/src/lib/files/analyze/analyzeEntities/prepareDataStructures.js.map +1 -1
- package/packages/analyze/src/lib/files/analyze/analyzeEntities.js +42 -1
- 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/findOrCreateEntity.js +2 -0
- package/packages/analyze/src/lib/files/analyze/findOrCreateEntity.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/analyzeChange.js +21 -11
- package/packages/analyze/src/lib/files/analyzeChange.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeEntity.js +9 -8
- package/packages/analyze/src/lib/files/analyzeEntity.js.map +1 -1
- package/packages/analyze/src/lib/files/analyzeInitial.js +9 -10
- package/packages/analyze/src/lib/files/analyzeInitial.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/enums/steps.js +1 -1
- package/packages/analyze/src/lib/files/enums/steps.js.map +1 -1
- package/packages/analyze/src/lib/files/getImportedExports.js +17 -8
- 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 +255 -0
- package/packages/analyze/src/lib/files/scenarios/enrichArrayTypesFromChildSignatures.js.map +1 -0
- package/packages/analyze/src/lib/files/scenarios/enrichUnknownTypesFromSourceEquivalencies.js +85 -0
- package/packages/analyze/src/lib/files/scenarios/enrichUnknownTypesFromSourceEquivalencies.js.map +1 -0
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js +550 -62
- package/packages/analyze/src/lib/files/scenarios/gatherDataForMocks.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.js +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateChangesScenarioData.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateChangesScenarios.js +29 -34
- package/packages/analyze/src/lib/files/scenarios/generateChangesScenarios.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js +404 -85
- package/packages/analyze/src/lib/files/scenarios/generateDataStructure.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js +144 -0
- package/packages/analyze/src/lib/files/scenarios/generateExecutionFlows.js.map +1 -0
- package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js +56 -69
- package/packages/analyze/src/lib/files/scenarios/generateScenarioData.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/generateScenarios.js +4 -8
- package/packages/analyze/src/lib/files/scenarios/generateScenarios.js.map +1 -1
- package/packages/analyze/src/lib/files/scenarios/mergeInDependentDataStructure.js +875 -141
- 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/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/aws/src/lib/ecs/ecsDefineContainer.js +2 -2
- package/packages/aws/src/lib/ecs/ecsDefineContainer.js.map +1 -1
- package/packages/aws/src/lib/ecs/ecsTaskFactory.js +17 -61
- package/packages/aws/src/lib/ecs/ecsTaskFactory.js.map +1 -1
- 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 +13 -3
- 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/kysely/tables/debugReportsTable.js +9 -3
- package/packages/database/src/lib/kysely/tables/debugReportsTable.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/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/loadReadyToBeCapturedAnalyses.js +23 -5
- package/packages/database/src/lib/loadReadyToBeCapturedAnalyses.js.map +1 -1
- 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/packages/database/src/lib/updateCommitMetadata.js +5 -4
- package/packages/database/src/lib/updateCommitMetadata.js.map +1 -1
- package/packages/generate/index.js +3 -0
- package/packages/generate/index.js.map +1 -1
- package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js +16 -1
- package/packages/generate/src/lib/componentScenarioPage/componentScenarioPageNext.js.map +1 -1
- package/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js +189 -0
- package/packages/generate/src/lib/componentScenarioPage/generateScenarioClientWrapper.js.map +1 -0
- package/packages/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js +53 -0
- package/packages/generate/src/lib/componentScenarioPage/generateScenarioServerComponent.js.map +1 -0
- package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js +8 -4
- package/packages/generate/src/lib/componentScenarioPage/getIFrameMessageListenerCode.js.map +1 -1
- package/packages/generate/src/lib/deepMerge.js +27 -1
- package/packages/generate/src/lib/deepMerge.js.map +1 -1
- package/packages/generate/src/lib/directExecutionScript.js +10 -1
- package/packages/generate/src/lib/directExecutionScript.js.map +1 -1
- package/packages/generate/src/lib/getComponentScenarioPath.js +7 -3
- package/packages/generate/src/lib/getComponentScenarioPath.js.map +1 -1
- package/packages/generate/src/lib/scenarioComponentForServer.js +89 -0
- package/packages/generate/src/lib/scenarioComponentForServer.js.map +1 -0
- package/packages/github/src/lib/loadOrCreateCommit.js +10 -0
- package/packages/github/src/lib/loadOrCreateCommit.js.map +1 -1
- package/packages/github/src/lib/syncPrimaryBranch.js +3 -0
- package/packages/github/src/lib/syncPrimaryBranch.js.map +1 -1
- package/packages/process/index.js +3 -0
- package/packages/process/index.js.map +1 -0
- package/packages/process/src/GlobalProcessManager.js.map +1 -0
- package/{background/src/lib/process → packages/process/src}/ProcessManager.js +1 -1
- package/packages/process/src/ProcessManager.js.map +1 -0
- package/packages/process/src/index.js.map +1 -0
- package/packages/process/src/managedExecAsync.js.map +1 -0
- package/packages/types/index.js.map +1 -1
- package/packages/utils/src/lib/applyUniversalMocks.js +26 -2
- package/packages/utils/src/lib/applyUniversalMocks.js.map +1 -1
- package/packages/utils/src/lib/fs/rsyncCopy.js +93 -2
- package/packages/utils/src/lib/fs/rsyncCopy.js.map +1 -1
- package/packages/utils/src/lib/lightweightEntityExtractor.js +25 -0
- package/packages/utils/src/lib/lightweightEntityExtractor.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 +8 -74
- package/analyzer-template/packages/ai/src/lib/findMatchingAttribute.ts +0 -102
- package/analyzer-template/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.ts +0 -197
- package/analyzer-template/packages/ai/src/lib/generateChangesEntityKeyAttributes.ts +0 -271
- package/analyzer-template/packages/ai/src/lib/generateEntityKeyAttributes.ts +0 -294
- package/analyzer-template/packages/ai/src/lib/promptGenerators/generateEntityKeyAttributesGenerator.ts +0 -67
- package/analyzer-template/packages/ai/src/lib/transformMockDataToMatchSchema.ts +0 -156
- package/analyzer-template/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.ts +0 -115
- package/analyzer-template/process/INTEGRATION_COMPLETE.md +0 -333
- package/analyzer-template/process/INTEGRATION_EXAMPLE.md +0 -525
- package/analyzer-template/process/README.md +0 -507
- package/background/src/lib/process/GlobalProcessManager.js.map +0 -1
- package/background/src/lib/process/ProcessManager.js.map +0 -1
- package/background/src/lib/process/index.js.map +0 -1
- package/background/src/lib/process/managedExecAsync.js.map +0 -1
- package/codeyam-cli/scripts/fixtures/cal.com/universal-mocks/packages/prisma/index.js +0 -238
- package/codeyam-cli/scripts/fixtures/cal.com/universal-mocks/packages/prisma/index.js.map +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityItem-D4htqD-x.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/EntityTypeIcon-Catz6XEN.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/InteractivePreview-TlHocYno.js +0 -26
- package/codeyam-cli/src/webserver/build/client/assets/LibraryFunctionPreview-CVMmGuIc.js +0 -3
- package/codeyam-cli/src/webserver/build/client/assets/LogViewer-JkfQ-VaI.js +0 -3
- package/codeyam-cli/src/webserver/build/client/assets/ReportIssueModal-CVZ0H4BL.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/SafeScreenshot-BrMAP1nP.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/ScenarioViewer-CJhE4cCv.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/_index-faVIcr_i.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/activity.(_tab)-CLMa2sgx.js +0 -7
- package/codeyam-cli/src/webserver/build/client/assets/chevron-down-DwYjrK_h.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/chunk-WWGJGFF6-CgXbbZRx.js +0 -26
- package/codeyam-cli/src/webserver/build/client/assets/circle-check-B2oHQ-zo.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/createLucideIcon-BBYuR56H.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/dev.empty-CT0Q5lVu.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.create-scenario-Bj5GHkhb.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/entity._sha_.edit._scenarioId-eW5z9AyZ.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/entry.client-B9tSboXM.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/fileTableUtils-CmO-EZAB.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/files-DLinnTOx.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/git-CIxwBQvb.js +0 -12
- package/codeyam-cli/src/webserver/build/client/assets/globals-xPz593l2.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/html2canvas-pro.esm-XQCGvadH.js +0 -5
- package/codeyam-cli/src/webserver/build/client/assets/index-_LjBsTxX.js +0 -8
- package/codeyam-cli/src/webserver/build/client/assets/loader-circle-D_EGChhq.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/manifest-ca438c41.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/root-CHHYHuzL.js +0 -16
- package/codeyam-cli/src/webserver/build/client/assets/search-DY8yoDpH.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/server-build-CMKNK2uU.css +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/settings-BT6wVHd5.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/simulations-gv3H7JV7.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/triangle-alert-BthANBVv.js +0 -1
- package/codeyam-cli/src/webserver/build/client/assets/useReportContext-CANr3QJ5.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/index-BtBPtyHx.js +0 -1
- package/codeyam-cli/src/webserver/build/server/assets/server-build-N2cTnejq.js +0 -166
- package/codeyam-cli/templates/debug-command.md +0 -141
- package/packages/ai/src/lib/findMatchingAttribute.js +0 -77
- package/packages/ai/src/lib/findMatchingAttribute.js.map +0 -1
- package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js +0 -136
- package/packages/ai/src/lib/gatherRelevantDependentKeyAttributes.js.map +0 -1
- package/packages/ai/src/lib/generateChangesEntityKeyAttributes.js +0 -220
- package/packages/ai/src/lib/generateChangesEntityKeyAttributes.js.map +0 -1
- package/packages/ai/src/lib/generateEntityKeyAttributes.js +0 -241
- package/packages/ai/src/lib/generateEntityKeyAttributes.js.map +0 -1
- package/packages/ai/src/lib/isFrontend.js +0 -5
- package/packages/ai/src/lib/isFrontend.js.map +0 -1
- package/packages/ai/src/lib/promptGenerators/generateEntityKeyAttributesGenerator.js +0 -40
- package/packages/ai/src/lib/promptGenerators/generateEntityKeyAttributesGenerator.js.map +0 -1
- package/packages/ai/src/lib/transformMockDataToMatchSchema.js +0 -124
- package/packages/ai/src/lib/transformMockDataToMatchSchema.js.map +0 -1
- package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js +0 -72
- package/packages/analyze/src/lib/files/scenarios/generateKeyAttributes.js.map +0 -1
- /package/analyzer-template/{process → packages/process/src}/GlobalProcessManager.ts +0 -0
- /package/analyzer-template/{process → packages/process/src}/ProcessManager.ts +0 -0
- /package/analyzer-template/{process → packages/process/src}/index.ts +0 -0
- /package/analyzer-template/{process → packages/process/src}/managedExecAsync.ts +0 -0
- /package/codeyam-cli/src/webserver/build/client/assets/{InteractivePreview-CMKNK2uU.css → styles-CMKNK2uU.css} +0 -0
- /package/{background/src/lib/process → packages/process/src}/GlobalProcessManager.js +0 -0
- /package/{background/src/lib/process → packages/process/src}/index.js +0 -0
- /package/{background/src/lib/process → packages/process/src}/managedExecAsync.js +0 -0
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
-
import
|
|
2
|
+
import * as crypto from 'crypto';
|
|
3
|
+
import {
|
|
4
|
+
AnalysisContext,
|
|
5
|
+
CompoundConditional,
|
|
6
|
+
ConditionalUsage,
|
|
7
|
+
} from './types';
|
|
3
8
|
import { StructuredPath } from './paths';
|
|
4
9
|
import { nodeToSource } from './nodeToSource';
|
|
5
10
|
import { methodRegistry, ArrayPushSemantics } from './methodSemantics';
|
|
6
11
|
import {
|
|
12
|
+
getComparisonOperatorString,
|
|
7
13
|
isArithmeticOperator,
|
|
8
14
|
isAssignmentOperator,
|
|
9
15
|
isBitwiseCompoundOperator,
|
|
@@ -14,6 +20,409 @@ import {
|
|
|
14
20
|
unwrapExpression,
|
|
15
21
|
} from './sharedPatterns';
|
|
16
22
|
import { processBindingPattern } from './processBindings';
|
|
23
|
+
import {
|
|
24
|
+
extractConditionalEffectsFromTernary,
|
|
25
|
+
findUseStateSetters,
|
|
26
|
+
} from './conditionalEffectsExtractor';
|
|
27
|
+
import { detectArrayDerivedPattern } from './arrayDerivationDetector';
|
|
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
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Extracts the component name from a JSX element.
|
|
204
|
+
* Returns null for intrinsic elements (div, span, etc.) since we only care about
|
|
205
|
+
* custom components for gating condition tracking.
|
|
206
|
+
*
|
|
207
|
+
* Examples:
|
|
208
|
+
* - <ChildViewer /> → "ChildViewer"
|
|
209
|
+
* - <ScenarioViewer scenario={...} /> → "ScenarioViewer"
|
|
210
|
+
* - <div> → null (intrinsic element)
|
|
211
|
+
*/
|
|
212
|
+
function getComponentNameFromJsx(
|
|
213
|
+
node: ts.JsxElement | ts.JsxSelfClosingElement,
|
|
214
|
+
): string | null {
|
|
215
|
+
let tagName: ts.JsxTagNameExpression;
|
|
216
|
+
|
|
217
|
+
if (ts.isJsxElement(node)) {
|
|
218
|
+
tagName = node.openingElement.tagName;
|
|
219
|
+
} else {
|
|
220
|
+
tagName = node.tagName;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Get the text of the tag name
|
|
224
|
+
const name = tagName.getText();
|
|
225
|
+
|
|
226
|
+
// Check if it's a custom component (starts with uppercase) vs intrinsic element
|
|
227
|
+
// Custom components start with uppercase: <MyComponent />
|
|
228
|
+
// Intrinsic elements start with lowercase: <div />
|
|
229
|
+
if (
|
|
230
|
+
name &&
|
|
231
|
+
name[0] === name[0].toUpperCase() &&
|
|
232
|
+
name[0] !== name[0].toLowerCase()
|
|
233
|
+
) {
|
|
234
|
+
return name;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Extracts condition paths from a logical AND chain expression.
|
|
242
|
+
* Used for creating gating conditions for child components.
|
|
243
|
+
*
|
|
244
|
+
* Example: `hasData && isReady && <Component />` returns ['hasData', 'isReady']
|
|
245
|
+
*/
|
|
246
|
+
function extractConditionPathsFromAndChain(
|
|
247
|
+
expr: ts.Expression,
|
|
248
|
+
sourceFile: ts.SourceFile,
|
|
249
|
+
): string[] {
|
|
250
|
+
const paths: string[] = [];
|
|
251
|
+
const unwrapped = unwrapExpression(expr);
|
|
252
|
+
|
|
253
|
+
if (
|
|
254
|
+
ts.isBinaryExpression(unwrapped) &&
|
|
255
|
+
unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken
|
|
256
|
+
) {
|
|
257
|
+
// Recursively get conditions from left side
|
|
258
|
+
paths.push(
|
|
259
|
+
...extractConditionPathsFromAndChain(unwrapped.left, sourceFile),
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
// Process right side if it's not JSX (JSX is the consequence, not a condition)
|
|
263
|
+
const rightUnwrapped = unwrapExpression(unwrapped.right);
|
|
264
|
+
if (
|
|
265
|
+
!ts.isJsxElement(rightUnwrapped) &&
|
|
266
|
+
!ts.isJsxSelfClosingElement(rightUnwrapped) &&
|
|
267
|
+
!ts.isJsxFragment(rightUnwrapped)
|
|
268
|
+
) {
|
|
269
|
+
paths.push(
|
|
270
|
+
...extractConditionPathsFromAndChain(unwrapped.right, sourceFile),
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
} else {
|
|
274
|
+
// Base case: extract path from this expression
|
|
275
|
+
const path = StructuredPath.fromNode(unwrapped, sourceFile);
|
|
276
|
+
if (path) {
|
|
277
|
+
paths.push(path.toString());
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
return paths;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Finds the rightmost JSX element in an && chain.
|
|
286
|
+
* Example: `a && b && <Component />` returns <Component />
|
|
287
|
+
*/
|
|
288
|
+
function findJsxInAndChain(
|
|
289
|
+
expr: ts.Expression,
|
|
290
|
+
): ts.JsxElement | ts.JsxSelfClosingElement | null {
|
|
291
|
+
const unwrapped = unwrapExpression(expr);
|
|
292
|
+
|
|
293
|
+
if (ts.isJsxElement(unwrapped) || ts.isJsxSelfClosingElement(unwrapped)) {
|
|
294
|
+
return unwrapped;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (
|
|
298
|
+
ts.isBinaryExpression(unwrapped) &&
|
|
299
|
+
unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken
|
|
300
|
+
) {
|
|
301
|
+
// Check right side first (most common case: condition && <Jsx />)
|
|
302
|
+
const rightResult = findJsxInAndChain(unwrapped.right);
|
|
303
|
+
if (rightResult) return rightResult;
|
|
304
|
+
|
|
305
|
+
// Also check left side for rare cases
|
|
306
|
+
return findJsxInAndChain(unwrapped.left);
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
return null;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
/**
|
|
313
|
+
* Fix 32: Finds a JSX fragment in an && chain.
|
|
314
|
+
* Example: `activeTab && <><ChildA /><ChildB /></>` returns the fragment
|
|
315
|
+
* This is needed to propagate parent conditions through fragments.
|
|
316
|
+
*/
|
|
317
|
+
function findJsxFragmentInAndChain(expr: ts.Expression): ts.JsxFragment | null {
|
|
318
|
+
const unwrapped = unwrapExpression(expr);
|
|
319
|
+
|
|
320
|
+
if (ts.isJsxFragment(unwrapped)) {
|
|
321
|
+
return unwrapped;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
if (
|
|
325
|
+
ts.isBinaryExpression(unwrapped) &&
|
|
326
|
+
unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken
|
|
327
|
+
) {
|
|
328
|
+
// Check right side first (most common case: condition && <></>)
|
|
329
|
+
const rightResult = findJsxFragmentInAndChain(unwrapped.right);
|
|
330
|
+
if (rightResult) return rightResult;
|
|
331
|
+
|
|
332
|
+
// Also check left side for rare cases
|
|
333
|
+
return findJsxFragmentInAndChain(unwrapped.left);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
return null;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
/**
|
|
340
|
+
* Detects if a property access looks like an environment variable store access.
|
|
341
|
+
* Matches patterns like `env.DATABASE_URL`, `env.IS_FORMBRICKS_CLOUD`, etc.
|
|
342
|
+
* where the object is named "env" and the property looks like an env var name.
|
|
343
|
+
*/
|
|
344
|
+
function isEnvStoreAccess(fullText: string): boolean {
|
|
345
|
+
// Match: env.SOME_VAR or env.someVar (but object must be exactly "env")
|
|
346
|
+
// This catches patterns from @t3-oss/env-nextjs and similar packages
|
|
347
|
+
const envStorePattern = /^env\.[A-Z_][A-Z0-9_]*$/;
|
|
348
|
+
return envStorePattern.test(fullText);
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
/**
|
|
352
|
+
* Converts a call expression argument to a StructuredPath.
|
|
353
|
+
*
|
|
354
|
+
* IMPORTANT: We always use the original source text for callbacks, never cyScope names.
|
|
355
|
+
* cyScope names are internal identifiers for child scopes and should NEVER appear
|
|
356
|
+
* in schema paths or call signatures. Using cyScope names causes data merge conflicts
|
|
357
|
+
* because the same callback gets different identifiers in different contexts.
|
|
358
|
+
*/
|
|
359
|
+
function getArgPathForCallSignature(
|
|
360
|
+
arg: ts.Expression,
|
|
361
|
+
context: AnalysisContext,
|
|
362
|
+
): StructuredPath {
|
|
363
|
+
// Always use the standard path conversion - never replace with cyScope names
|
|
364
|
+
return (
|
|
365
|
+
StructuredPath.fromNode(arg, context.sourceFile) ||
|
|
366
|
+
nodeToSource(arg, context.sourceFile)
|
|
367
|
+
);
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
/**
|
|
371
|
+
* Builds a StructuredPath for a call expression using the original source text.
|
|
372
|
+
*
|
|
373
|
+
* IMPORTANT: This function ensures consistent call signatures by always using
|
|
374
|
+
* the original callback text, never cyScope names. This prevents schema path
|
|
375
|
+
* conflicts where the same call would have different paths.
|
|
376
|
+
*/
|
|
377
|
+
function buildCallPathFromSource(
|
|
378
|
+
node: ts.CallExpression,
|
|
379
|
+
context: AnalysisContext,
|
|
380
|
+
): StructuredPath | null {
|
|
381
|
+
const expression = node.expression;
|
|
382
|
+
|
|
383
|
+
// Convert arguments using original source text
|
|
384
|
+
const argPaths = node.arguments.map((arg) =>
|
|
385
|
+
getArgPathForCallSignature(arg, context),
|
|
386
|
+
);
|
|
387
|
+
|
|
388
|
+
// Handle type arguments if present
|
|
389
|
+
let typeArgs: string[] | undefined = undefined;
|
|
390
|
+
if (node.typeArguments && node.typeArguments.length > 0) {
|
|
391
|
+
typeArgs = node.typeArguments.map((typeArg) =>
|
|
392
|
+
typeArg.getText(context.sourceFile),
|
|
393
|
+
);
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
if (ts.isIdentifier(expression)) {
|
|
397
|
+
// Simple function call: func(arg1, arg2)
|
|
398
|
+
return StructuredPath.fromFunction(expression.text, argPaths, typeArgs);
|
|
399
|
+
} else if (ts.isPropertyAccessExpression(expression)) {
|
|
400
|
+
// Method call: obj.method(arg1, arg2)
|
|
401
|
+
const objPath = StructuredPath.fromNode(
|
|
402
|
+
expression.expression,
|
|
403
|
+
context.sourceFile,
|
|
404
|
+
);
|
|
405
|
+
if (!objPath) return null;
|
|
406
|
+
return objPath
|
|
407
|
+
.withProperty(expression.name.text)
|
|
408
|
+
.withFunctionCall(argPaths, typeArgs);
|
|
409
|
+
} else if (ts.isCallExpression(expression)) {
|
|
410
|
+
// Chained call: func(arg1)(arg2)
|
|
411
|
+
const funcPath = buildCallPathFromSource(expression, context);
|
|
412
|
+
if (!funcPath) return null;
|
|
413
|
+
return funcPath.withFunctionCall(argPaths, typeArgs);
|
|
414
|
+
} else if (ts.isElementAccessExpression(expression)) {
|
|
415
|
+
// Element access call: obj[key](args)
|
|
416
|
+
const basePath = StructuredPath.fromNode(expression, context.sourceFile);
|
|
417
|
+
if (!basePath) return null;
|
|
418
|
+
return basePath.withFunctionCall(argPaths, typeArgs);
|
|
419
|
+
} else {
|
|
420
|
+
// Complex call expression
|
|
421
|
+
const basePath = StructuredPath.fromNode(expression, context.sourceFile);
|
|
422
|
+
if (!basePath) return null;
|
|
423
|
+
return basePath.withFunctionCall(argPaths, typeArgs);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
17
426
|
|
|
18
427
|
/**
|
|
19
428
|
* Checks if an expression is likely an array type.
|
|
@@ -114,131 +523,1014 @@ export function markConditionVariablesAsNullable(
|
|
|
114
523
|
}
|
|
115
524
|
|
|
116
525
|
/**
|
|
117
|
-
*
|
|
118
|
-
|
|
526
|
+
* Helper to extract source location from an AST node
|
|
527
|
+
*/
|
|
528
|
+
function getSourceLocation(
|
|
529
|
+
node: ts.Node,
|
|
530
|
+
sourceFile: ts.SourceFile,
|
|
531
|
+
): ConditionalUsage['sourceLocation'] {
|
|
532
|
+
const start = node.getStart(sourceFile);
|
|
533
|
+
const { line, character } = sourceFile.getLineAndCharacterOfPosition(start);
|
|
534
|
+
const codeSnippet = node.getText(sourceFile);
|
|
535
|
+
|
|
536
|
+
return {
|
|
537
|
+
lineNumber: line + 1, // Convert to 1-based
|
|
538
|
+
column: character,
|
|
539
|
+
codeSnippet:
|
|
540
|
+
codeSnippet.length > 100
|
|
541
|
+
? codeSnippet.slice(0, 100) + '...'
|
|
542
|
+
: codeSnippet,
|
|
543
|
+
};
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Extracts the root array path from an expression that ends with .map().
|
|
548
|
+
* Handles chained methods like .filter().map(), .slice().map(), etc.
|
|
119
549
|
*
|
|
120
|
-
*
|
|
550
|
+
* Examples:
|
|
551
|
+
* - items.map(...) → "items"
|
|
552
|
+
* - data.users.map(...) → "data.users"
|
|
553
|
+
* - items.filter(...).map(...) → "items"
|
|
554
|
+
* - items.slice(0, 5).map(...) → "items"
|
|
555
|
+
*/
|
|
556
|
+
function extractArrayPathFromMapCall(
|
|
557
|
+
expr: ts.CallExpression,
|
|
558
|
+
sourceFile: ts.SourceFile,
|
|
559
|
+
): string | null {
|
|
560
|
+
// Walk up the chain to find the root array
|
|
561
|
+
let current: ts.Expression = expr.expression;
|
|
562
|
+
|
|
563
|
+
while (ts.isPropertyAccessExpression(current)) {
|
|
564
|
+
const methodName = current.name.getText(sourceFile);
|
|
565
|
+
|
|
566
|
+
// Common array methods that return arrays (so we keep going up)
|
|
567
|
+
const arrayReturningMethods = [
|
|
568
|
+
'map',
|
|
569
|
+
'filter',
|
|
570
|
+
'slice',
|
|
571
|
+
'concat',
|
|
572
|
+
'flat',
|
|
573
|
+
'flatMap',
|
|
574
|
+
'reverse',
|
|
575
|
+
'sort',
|
|
576
|
+
'toReversed',
|
|
577
|
+
'toSorted',
|
|
578
|
+
'toSpliced',
|
|
579
|
+
];
|
|
580
|
+
|
|
581
|
+
if (arrayReturningMethods.includes(methodName)) {
|
|
582
|
+
const objectExpr = current.expression;
|
|
583
|
+
|
|
584
|
+
// If the object is a call expression (chained method), keep going
|
|
585
|
+
if (ts.isCallExpression(objectExpr)) {
|
|
586
|
+
current = objectExpr.expression;
|
|
587
|
+
} else {
|
|
588
|
+
// Found the root - it's an identifier or property access
|
|
589
|
+
const path = StructuredPath.fromNode(objectExpr, sourceFile);
|
|
590
|
+
return path ? path.toString() : null;
|
|
591
|
+
}
|
|
592
|
+
} else {
|
|
593
|
+
// Not an array method we recognize
|
|
594
|
+
break;
|
|
595
|
+
}
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
return null;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
/**
|
|
602
|
+
* Extracts JSX rendering usages from a JSX expression.
|
|
603
|
+
* Detects:
|
|
604
|
+
* - array.map() calls → 'array-map' type
|
|
605
|
+
* - string interpolations (identifiers/property access) → 'text-interpolation' type
|
|
606
|
+
*
|
|
607
|
+
* Recursively searches inside && chains and ternary expressions.
|
|
608
|
+
*
|
|
609
|
+
* @param expr The expression inside {expr}
|
|
121
610
|
* @param context The analysis context
|
|
122
|
-
* @param location Where this condition appears (if, ternary, logical-and, switch)
|
|
123
611
|
*/
|
|
124
|
-
|
|
125
|
-
|
|
612
|
+
function extractJsxRenderingUsage(
|
|
613
|
+
expr: ts.Expression,
|
|
126
614
|
context: AnalysisContext,
|
|
127
|
-
location: ConditionalUsage['location'],
|
|
128
615
|
): void {
|
|
129
|
-
const unwrapped = unwrapExpression(
|
|
616
|
+
const unwrapped = unwrapExpression(expr);
|
|
617
|
+
const sourceLocation = getSourceLocation(expr, context.sourceFile);
|
|
130
618
|
|
|
131
|
-
//
|
|
132
|
-
|
|
133
|
-
|
|
619
|
+
// Detect array.map() calls
|
|
620
|
+
if (ts.isCallExpression(unwrapped)) {
|
|
621
|
+
const calleeExpr = unwrapped.expression;
|
|
622
|
+
|
|
623
|
+
if (ts.isPropertyAccessExpression(calleeExpr)) {
|
|
624
|
+
const methodName = calleeExpr.name.getText(context.sourceFile);
|
|
625
|
+
|
|
626
|
+
if (methodName === 'map') {
|
|
627
|
+
const arrayPath = extractArrayPathFromMapCall(
|
|
628
|
+
unwrapped,
|
|
629
|
+
context.sourceFile,
|
|
630
|
+
);
|
|
631
|
+
|
|
632
|
+
if (arrayPath) {
|
|
633
|
+
context.addJsxRenderingUsage({
|
|
634
|
+
path: arrayPath,
|
|
635
|
+
renderingType: 'array-map',
|
|
636
|
+
valueType: 'array',
|
|
637
|
+
sourceLocation,
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
// Detect simple string interpolations: {title} or {user.name}
|
|
644
|
+
else if (
|
|
645
|
+
ts.isIdentifier(unwrapped) ||
|
|
646
|
+
ts.isPropertyAccessExpression(unwrapped)
|
|
647
|
+
) {
|
|
648
|
+
const path = StructuredPath.fromNode(unwrapped, context.sourceFile);
|
|
649
|
+
|
|
650
|
+
if (path) {
|
|
651
|
+
const pathStr = path.toString();
|
|
652
|
+
const typeInfo = context.getTypeInfo(path);
|
|
653
|
+
|
|
654
|
+
// Only track as text interpolation if it's a string type
|
|
655
|
+
// Check for 'string' type, or types that contain 'string' (but not 'string[]')
|
|
656
|
+
if (
|
|
657
|
+
typeInfo === 'string' ||
|
|
658
|
+
(typeInfo &&
|
|
659
|
+
typeInfo.includes('string') &&
|
|
660
|
+
!typeInfo.includes('string[]'))
|
|
661
|
+
) {
|
|
662
|
+
context.addJsxRenderingUsage({
|
|
663
|
+
path: pathStr,
|
|
664
|
+
renderingType: 'text-interpolation',
|
|
665
|
+
valueType: 'string',
|
|
666
|
+
sourceLocation,
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
// Recursively search inside && chains: {showList && items.map(...)}
|
|
672
|
+
else if (
|
|
134
673
|
ts.isBinaryExpression(unwrapped) &&
|
|
135
674
|
unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken
|
|
136
675
|
) {
|
|
137
|
-
//
|
|
138
|
-
|
|
676
|
+
// Check the right side of the && chain (where .map() typically appears)
|
|
677
|
+
const rightSide = unwrapExpression(unwrapped.right);
|
|
678
|
+
extractJsxRenderingUsage(rightSide, context);
|
|
679
|
+
// Also check nested && chains on the left
|
|
680
|
+
extractJsxRenderingUsage(unwrapped.left, context);
|
|
681
|
+
}
|
|
682
|
+
// Recursively search inside ternaries: {isEmpty ? null : items.map(...)}
|
|
683
|
+
else if (ts.isConditionalExpression(unwrapped)) {
|
|
684
|
+
extractJsxRenderingUsage(unwrapped.whenTrue, context);
|
|
685
|
+
extractJsxRenderingUsage(unwrapped.whenFalse, context);
|
|
686
|
+
}
|
|
687
|
+
}
|
|
139
688
|
|
|
140
|
-
|
|
689
|
+
/**
|
|
690
|
+
* Counts the number of conditions in an && chain (excluding JSX consequence)
|
|
691
|
+
*/
|
|
692
|
+
function countConditionsInAndChain(expr: ts.Expression): number {
|
|
693
|
+
const unwrapped = unwrapExpression(expr);
|
|
694
|
+
|
|
695
|
+
if (
|
|
696
|
+
ts.isBinaryExpression(unwrapped) &&
|
|
697
|
+
unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken
|
|
698
|
+
) {
|
|
699
|
+
const leftCount = countConditionsInAndChain(unwrapped.left);
|
|
141
700
|
const rightUnwrapped = unwrapExpression(unwrapped.right);
|
|
142
701
|
const isJsxConsequence =
|
|
143
702
|
ts.isJsxElement(rightUnwrapped) ||
|
|
144
703
|
ts.isJsxSelfClosingElement(rightUnwrapped) ||
|
|
145
704
|
ts.isJsxFragment(rightUnwrapped);
|
|
146
705
|
|
|
147
|
-
if (
|
|
148
|
-
|
|
706
|
+
if (isJsxConsequence) {
|
|
707
|
+
return leftCount;
|
|
149
708
|
}
|
|
150
|
-
return;
|
|
709
|
+
return leftCount + countConditionsInAndChain(unwrapped.right);
|
|
151
710
|
}
|
|
152
711
|
|
|
153
|
-
//
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
712
|
+
// Single condition (not an && chain)
|
|
713
|
+
return 1;
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
/**
|
|
717
|
+
* Chain tracking info for compound conditionals
|
|
718
|
+
*/
|
|
719
|
+
interface ChainInfo {
|
|
720
|
+
chainId: string;
|
|
721
|
+
chainLength: number;
|
|
722
|
+
chainExpression: string;
|
|
723
|
+
currentPosition: number;
|
|
724
|
+
compound: CompoundConditional;
|
|
725
|
+
/**
|
|
726
|
+
* When processing OR expressions within an && chain, this tracks the
|
|
727
|
+
* current OR group ID. Conditions added while this is set will be marked
|
|
728
|
+
* as OR alternatives (only one needs to be true).
|
|
729
|
+
*/
|
|
730
|
+
currentOrGroupId?: string;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
/**
|
|
734
|
+
* Parent gating condition accumulated during JSX traversal.
|
|
735
|
+
* Used to track conditions from parent && chains that gate child components.
|
|
736
|
+
*/
|
|
737
|
+
interface ParentGatingCondition {
|
|
738
|
+
path: string;
|
|
739
|
+
sourceLocation: { lineNumber: number; column: number; codeSnippet: string };
|
|
740
|
+
isNegated?: boolean;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
/**
|
|
744
|
+
* Extracts conditionals from JSX elements by recursively traversing children.
|
|
745
|
+
*
|
|
746
|
+
* This is CRITICAL for extracting compound conditionals from JSX expressions
|
|
747
|
+
* like `{hasNewerVersion && !isActive && <Banner />}`.
|
|
748
|
+
*
|
|
749
|
+
* This function is called BEFORE the child boundary check in processExpression
|
|
750
|
+
* because JSX elements are NOT scopes - their expressions use variables from
|
|
751
|
+
* the parent scope and should have their conditionals extracted regardless of
|
|
752
|
+
* whether the JSX is within a child boundary.
|
|
753
|
+
*
|
|
754
|
+
* Fix 32: Added parentConditions parameter to track gating conditions from
|
|
755
|
+
* parent && chains. When we find a component nested inside multiple conditionals
|
|
756
|
+
* like `{activeTab && <>{ternary ? ... : <Component />}</>}`, ALL parent
|
|
757
|
+
* conditions should be added as gating conditions for the component.
|
|
758
|
+
*
|
|
759
|
+
* @param node The JSX element, self-closing element, or fragment to traverse
|
|
760
|
+
* @param context The analysis context
|
|
761
|
+
* @param parentConditions Accumulated gating conditions from parent && chains
|
|
762
|
+
*/
|
|
763
|
+
function extractConditionalsFromJsx(
|
|
764
|
+
node: ts.JsxElement | ts.JsxSelfClosingElement | ts.JsxFragment,
|
|
765
|
+
context: AnalysisContext,
|
|
766
|
+
parentConditions: ParentGatingCondition[] = [],
|
|
767
|
+
): void {
|
|
768
|
+
// Get children to process
|
|
769
|
+
let children: ts.NodeArray<ts.JsxChild> | undefined;
|
|
770
|
+
|
|
771
|
+
if (ts.isJsxElement(node)) {
|
|
772
|
+
children = node.children;
|
|
773
|
+
} else if (ts.isJsxFragment(node)) {
|
|
774
|
+
children = node.children;
|
|
775
|
+
}
|
|
776
|
+
// JsxSelfClosingElement has no children
|
|
777
|
+
|
|
778
|
+
if (!children) {
|
|
161
779
|
return;
|
|
162
780
|
}
|
|
163
781
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
isComparisonOperator(unwrapped.operatorToken.kind)
|
|
169
|
-
) {
|
|
170
|
-
// Try to extract the variable and the compared value
|
|
171
|
-
const leftPath = StructuredPath.fromNode(
|
|
172
|
-
unwrapped.left,
|
|
173
|
-
context.sourceFile,
|
|
174
|
-
);
|
|
175
|
-
const rightPath = StructuredPath.fromNode(
|
|
176
|
-
unwrapped.right,
|
|
177
|
-
context.sourceFile,
|
|
178
|
-
);
|
|
782
|
+
for (const child of children) {
|
|
783
|
+
// Process JSX expressions: {expr}
|
|
784
|
+
if (ts.isJsxExpression(child) && child.expression) {
|
|
785
|
+
const expr = unwrapExpression(child.expression);
|
|
179
786
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
787
|
+
// Extract JSX rendering usages (array.map, text interpolation)
|
|
788
|
+
// This handles direct usages like {items.map(...)} or {user.name}
|
|
789
|
+
extractJsxRenderingUsage(expr, context);
|
|
790
|
+
|
|
791
|
+
// If the expression is an && chain, extract its conditional usages
|
|
792
|
+
if (
|
|
793
|
+
ts.isBinaryExpression(expr) &&
|
|
794
|
+
expr.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken
|
|
795
|
+
) {
|
|
796
|
+
// Mark nullable variables
|
|
797
|
+
markConditionVariablesAsNullable(expr, context);
|
|
798
|
+
// Extract conditional usage (this handles compound conditionals)
|
|
799
|
+
// Pass controlsJsxRendering: true since this conditional controls JSX rendering
|
|
800
|
+
extractConditionalUsage(expr, context, 'logical-and', {
|
|
801
|
+
controlsJsxRendering: true,
|
|
802
|
+
});
|
|
803
|
+
|
|
804
|
+
// Extract all condition paths from the && chain for gating tracking
|
|
805
|
+
const conditionPaths = extractConditionPathsFromAndChain(
|
|
806
|
+
expr,
|
|
807
|
+
context.sourceFile,
|
|
808
|
+
);
|
|
809
|
+
const sourceLocation = getSourceLocation(expr, context.sourceFile);
|
|
810
|
+
|
|
811
|
+
// Fix 32: Build accumulated conditions including parent conditions
|
|
812
|
+
const accumulatedConditions: ParentGatingCondition[] = [
|
|
813
|
+
...parentConditions,
|
|
814
|
+
...conditionPaths.map((path) => ({
|
|
815
|
+
path,
|
|
816
|
+
sourceLocation,
|
|
817
|
+
isNegated: false,
|
|
818
|
+
})),
|
|
819
|
+
];
|
|
820
|
+
|
|
821
|
+
// Track gating conditions for child components
|
|
822
|
+
// Example: {hasAnalysis && <ScenarioViewer />}
|
|
823
|
+
const jsxElement = findJsxInAndChain(expr);
|
|
824
|
+
if (jsxElement) {
|
|
825
|
+
const componentName = getComponentNameFromJsx(jsxElement);
|
|
826
|
+
if (componentName) {
|
|
827
|
+
// Fix 32: Add ALL accumulated conditions (parent + current) as gating conditions
|
|
828
|
+
for (const condition of accumulatedConditions) {
|
|
829
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
830
|
+
path: condition.path,
|
|
831
|
+
conditionType: 'truthiness',
|
|
832
|
+
location: 'logical-and',
|
|
833
|
+
sourceLocation: condition.sourceLocation,
|
|
834
|
+
controlsJsxRendering: true,
|
|
835
|
+
isNegated: condition.isNegated,
|
|
836
|
+
});
|
|
837
|
+
}
|
|
838
|
+
}
|
|
839
|
+
|
|
840
|
+
// Fix 32: Recursively process nested JSX with accumulated conditions
|
|
841
|
+
if (
|
|
842
|
+
ts.isJsxElement(jsxElement) ||
|
|
843
|
+
ts.isJsxSelfClosingElement(jsxElement)
|
|
844
|
+
) {
|
|
845
|
+
extractConditionalsFromJsx(
|
|
846
|
+
jsxElement,
|
|
847
|
+
context,
|
|
848
|
+
accumulatedConditions,
|
|
849
|
+
);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// Fix 32: Also check for nested JSX fragments
|
|
854
|
+
const jsxFragment = findJsxFragmentInAndChain(expr);
|
|
855
|
+
if (jsxFragment) {
|
|
856
|
+
extractConditionalsFromJsx(
|
|
857
|
+
jsxFragment,
|
|
858
|
+
context,
|
|
859
|
+
accumulatedConditions,
|
|
860
|
+
);
|
|
861
|
+
}
|
|
862
|
+
}
|
|
863
|
+
// If the expression is a ternary, extract its conditional
|
|
864
|
+
else if (ts.isConditionalExpression(expr)) {
|
|
865
|
+
// Pass controlsJsxRendering: true since this conditional controls JSX rendering
|
|
866
|
+
extractConditionalUsage(expr.condition, context, 'ternary', {
|
|
867
|
+
controlsJsxRendering: true,
|
|
868
|
+
});
|
|
869
|
+
|
|
870
|
+
// Track gating conditions for components in both branches of the ternary
|
|
871
|
+
// Example: {isError ? <ErrorView /> : <SuccessView />}
|
|
872
|
+
const conditionPath = StructuredPath.fromNode(
|
|
873
|
+
unwrapExpression(expr.condition),
|
|
874
|
+
context.sourceFile,
|
|
875
|
+
);
|
|
876
|
+
const sourceLocation = getSourceLocation(expr, context.sourceFile);
|
|
877
|
+
|
|
878
|
+
// Recursively process the whenTrue and whenFalse branches for JSX
|
|
879
|
+
const whenTrue = unwrapExpression(expr.whenTrue);
|
|
880
|
+
const whenFalse = unwrapExpression(expr.whenFalse);
|
|
881
|
+
|
|
882
|
+
// Fix 32: Build conditions for whenTrue branch (parent conditions + ternary condition truthy)
|
|
883
|
+
const whenTrueConditions: ParentGatingCondition[] = [
|
|
884
|
+
...parentConditions,
|
|
885
|
+
...(conditionPath
|
|
886
|
+
? [
|
|
887
|
+
{
|
|
888
|
+
path: conditionPath.toString(),
|
|
889
|
+
sourceLocation,
|
|
890
|
+
isNegated: false,
|
|
891
|
+
},
|
|
892
|
+
]
|
|
893
|
+
: []),
|
|
894
|
+
];
|
|
895
|
+
|
|
896
|
+
// Fix 32: Build conditions for whenFalse branch (parent conditions + ternary condition falsy)
|
|
897
|
+
const whenFalseConditions: ParentGatingCondition[] = [
|
|
898
|
+
...parentConditions,
|
|
899
|
+
...(conditionPath
|
|
900
|
+
? [
|
|
901
|
+
{
|
|
902
|
+
path: conditionPath.toString(),
|
|
903
|
+
sourceLocation,
|
|
904
|
+
isNegated: true,
|
|
905
|
+
},
|
|
906
|
+
]
|
|
907
|
+
: []),
|
|
908
|
+
];
|
|
909
|
+
|
|
910
|
+
// Handle whenTrue branch (condition is truthy)
|
|
911
|
+
if (ts.isJsxElement(whenTrue) || ts.isJsxSelfClosingElement(whenTrue)) {
|
|
912
|
+
const componentName = getComponentNameFromJsx(whenTrue);
|
|
913
|
+
if (componentName) {
|
|
914
|
+
// Fix 32: Add ALL conditions (parent + ternary) as gating conditions
|
|
915
|
+
for (const condition of whenTrueConditions) {
|
|
916
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
917
|
+
path: condition.path,
|
|
918
|
+
conditionType: 'truthiness',
|
|
919
|
+
location: 'ternary',
|
|
920
|
+
sourceLocation: condition.sourceLocation,
|
|
921
|
+
controlsJsxRendering: true,
|
|
922
|
+
isNegated: condition.isNegated,
|
|
923
|
+
});
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
if (
|
|
928
|
+
ts.isJsxElement(whenTrue) ||
|
|
929
|
+
ts.isJsxSelfClosingElement(whenTrue) ||
|
|
930
|
+
ts.isJsxFragment(whenTrue)
|
|
931
|
+
) {
|
|
932
|
+
extractConditionalsFromJsx(whenTrue, context, whenTrueConditions);
|
|
933
|
+
}
|
|
934
|
+
|
|
935
|
+
// Handle whenFalse branch (condition is falsy/negated)
|
|
936
|
+
if (
|
|
937
|
+
ts.isJsxElement(whenFalse) ||
|
|
938
|
+
ts.isJsxSelfClosingElement(whenFalse)
|
|
939
|
+
) {
|
|
940
|
+
const componentName = getComponentNameFromJsx(whenFalse);
|
|
941
|
+
if (componentName) {
|
|
942
|
+
// Fix 32: Add ALL conditions (parent + ternary) as gating conditions
|
|
943
|
+
for (const condition of whenFalseConditions) {
|
|
944
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
945
|
+
path: condition.path,
|
|
946
|
+
conditionType: 'truthiness',
|
|
947
|
+
location: 'ternary',
|
|
948
|
+
sourceLocation: condition.sourceLocation,
|
|
949
|
+
controlsJsxRendering: true,
|
|
950
|
+
isNegated: condition.isNegated,
|
|
951
|
+
});
|
|
952
|
+
}
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
if (
|
|
956
|
+
ts.isJsxElement(whenFalse) ||
|
|
957
|
+
ts.isJsxSelfClosingElement(whenFalse) ||
|
|
958
|
+
ts.isJsxFragment(whenFalse)
|
|
959
|
+
) {
|
|
960
|
+
extractConditionalsFromJsx(whenFalse, context, whenFalseConditions);
|
|
961
|
+
}
|
|
962
|
+
// Handle chained ternaries: a ? <A/> : b ? <B/> : <C/>
|
|
963
|
+
// When whenFalse is another ConditionalExpression, recursively process it
|
|
964
|
+
else if (ts.isConditionalExpression(whenFalse)) {
|
|
965
|
+
// Extract conditional usage for the nested ternary's condition
|
|
966
|
+
extractConditionalUsage(whenFalse.condition, context, 'ternary', {
|
|
967
|
+
controlsJsxRendering: true,
|
|
968
|
+
});
|
|
969
|
+
|
|
970
|
+
// Get the nested condition path
|
|
971
|
+
const nestedConditionPath = StructuredPath.fromNode(
|
|
972
|
+
unwrapExpression(whenFalse.condition),
|
|
973
|
+
context.sourceFile,
|
|
974
|
+
);
|
|
975
|
+
const nestedSourceLocation = getSourceLocation(
|
|
976
|
+
whenFalse,
|
|
977
|
+
context.sourceFile,
|
|
978
|
+
);
|
|
979
|
+
|
|
980
|
+
const nestedWhenTrue = unwrapExpression(whenFalse.whenTrue);
|
|
981
|
+
const nestedWhenFalse = unwrapExpression(whenFalse.whenFalse);
|
|
982
|
+
|
|
983
|
+
// Fix 32: Build conditions for nested whenTrue (parent falsy + nested truthy)
|
|
984
|
+
const nestedWhenTrueConditions: ParentGatingCondition[] = [
|
|
985
|
+
...whenFalseConditions, // Parent ternary was falsy to get here
|
|
986
|
+
...(nestedConditionPath
|
|
987
|
+
? [
|
|
988
|
+
{
|
|
989
|
+
path: nestedConditionPath.toString(),
|
|
990
|
+
sourceLocation: nestedSourceLocation,
|
|
991
|
+
isNegated: false,
|
|
992
|
+
},
|
|
993
|
+
]
|
|
994
|
+
: []),
|
|
995
|
+
];
|
|
996
|
+
|
|
997
|
+
// Fix 32: Build conditions for nested whenFalse (parent falsy + nested falsy)
|
|
998
|
+
const nestedWhenFalseConditions: ParentGatingCondition[] = [
|
|
999
|
+
...whenFalseConditions, // Parent ternary was falsy to get here
|
|
1000
|
+
...(nestedConditionPath
|
|
1001
|
+
? [
|
|
1002
|
+
{
|
|
1003
|
+
path: nestedConditionPath.toString(),
|
|
1004
|
+
sourceLocation: nestedSourceLocation,
|
|
1005
|
+
isNegated: true,
|
|
1006
|
+
},
|
|
1007
|
+
]
|
|
1008
|
+
: []),
|
|
1009
|
+
];
|
|
1010
|
+
|
|
1011
|
+
// Handle nested whenTrue branch
|
|
1012
|
+
if (
|
|
1013
|
+
ts.isJsxElement(nestedWhenTrue) ||
|
|
1014
|
+
ts.isJsxSelfClosingElement(nestedWhenTrue)
|
|
1015
|
+
) {
|
|
1016
|
+
const componentName = getComponentNameFromJsx(nestedWhenTrue);
|
|
1017
|
+
if (componentName) {
|
|
1018
|
+
// Fix 32: Add ALL accumulated conditions
|
|
1019
|
+
for (const condition of nestedWhenTrueConditions) {
|
|
1020
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
1021
|
+
path: condition.path,
|
|
1022
|
+
conditionType: 'truthiness',
|
|
1023
|
+
location: 'ternary',
|
|
1024
|
+
sourceLocation: condition.sourceLocation,
|
|
1025
|
+
controlsJsxRendering: true,
|
|
1026
|
+
isNegated: condition.isNegated,
|
|
1027
|
+
});
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
if (
|
|
1032
|
+
ts.isJsxElement(nestedWhenTrue) ||
|
|
1033
|
+
ts.isJsxSelfClosingElement(nestedWhenTrue) ||
|
|
1034
|
+
ts.isJsxFragment(nestedWhenTrue)
|
|
1035
|
+
) {
|
|
1036
|
+
extractConditionalsFromJsx(
|
|
1037
|
+
nestedWhenTrue,
|
|
1038
|
+
context,
|
|
1039
|
+
nestedWhenTrueConditions,
|
|
1040
|
+
);
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
// Handle nested whenFalse branch (this could be another chained ternary or JSX)
|
|
1044
|
+
if (
|
|
1045
|
+
ts.isJsxElement(nestedWhenFalse) ||
|
|
1046
|
+
ts.isJsxSelfClosingElement(nestedWhenFalse)
|
|
1047
|
+
) {
|
|
1048
|
+
const componentName = getComponentNameFromJsx(nestedWhenFalse);
|
|
1049
|
+
if (componentName) {
|
|
1050
|
+
// Fix 32: Add ALL accumulated conditions
|
|
1051
|
+
for (const condition of nestedWhenFalseConditions) {
|
|
1052
|
+
context.addChildBoundaryGatingCondition(componentName, {
|
|
1053
|
+
path: condition.path,
|
|
1054
|
+
conditionType: 'truthiness',
|
|
1055
|
+
location: 'ternary',
|
|
1056
|
+
sourceLocation: condition.sourceLocation,
|
|
1057
|
+
controlsJsxRendering: true,
|
|
1058
|
+
isNegated: condition.isNegated,
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
if (
|
|
1064
|
+
ts.isJsxElement(nestedWhenFalse) ||
|
|
1065
|
+
ts.isJsxSelfClosingElement(nestedWhenFalse) ||
|
|
1066
|
+
ts.isJsxFragment(nestedWhenFalse)
|
|
1067
|
+
) {
|
|
1068
|
+
extractConditionalsFromJsx(
|
|
1069
|
+
nestedWhenFalse,
|
|
1070
|
+
context,
|
|
1071
|
+
nestedWhenFalseConditions,
|
|
1072
|
+
);
|
|
1073
|
+
}
|
|
1074
|
+
// If nestedWhenFalse is yet another ConditionalExpression, the recursion
|
|
1075
|
+
// will handle it on the next iteration when this function processes it
|
|
1076
|
+
else if (ts.isConditionalExpression(nestedWhenFalse)) {
|
|
1077
|
+
// Recursively handle deeper nesting by wrapping in a synthetic process
|
|
1078
|
+
// We create a fake JsxExpression context to reuse the same logic
|
|
1079
|
+
const syntheticChild = {
|
|
1080
|
+
kind: ts.SyntaxKind.JsxExpression,
|
|
1081
|
+
expression: nestedWhenFalse,
|
|
1082
|
+
} as unknown as ts.JsxExpression;
|
|
1083
|
+
// Process via the main JSX expression handler by recursing
|
|
1084
|
+
// For now, just extract conditionals directly
|
|
1085
|
+
extractConditionalUsage(
|
|
1086
|
+
nestedWhenFalse.condition,
|
|
1087
|
+
context,
|
|
1088
|
+
'ternary',
|
|
1089
|
+
{ controlsJsxRendering: true },
|
|
1090
|
+
);
|
|
1091
|
+
}
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
// Recursively process nested JSX elements - Fix 32: pass parent conditions
|
|
1096
|
+
else if (ts.isJsxElement(child)) {
|
|
1097
|
+
// Check if this is a user-defined component (vs intrinsic element like div)
|
|
1098
|
+
const componentName = getComponentNameFromJsx(child);
|
|
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
|
+
}
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
extractConditionalsFromJsx(child, context, parentConditions);
|
|
1145
|
+
}
|
|
1146
|
+
// Handle self-closing JSX elements (e.g., <ScenarioViewer />)
|
|
1147
|
+
else if (ts.isJsxSelfClosingElement(child)) {
|
|
1148
|
+
// Check if this is a user-defined component (vs intrinsic element like div)
|
|
1149
|
+
const componentName = getComponentNameFromJsx(child);
|
|
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
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
// Self-closing elements have no children, so no recursion needed
|
|
1194
|
+
}
|
|
1195
|
+
// Recursively process nested JSX fragments - Fix 32: pass parent conditions
|
|
1196
|
+
else if (ts.isJsxFragment(child)) {
|
|
1197
|
+
extractConditionalsFromJsx(child, context, parentConditions);
|
|
1198
|
+
}
|
|
1199
|
+
}
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
/**
|
|
1203
|
+
* Options for extractConditionalUsage
|
|
1204
|
+
*/
|
|
1205
|
+
interface ExtractConditionalOptions {
|
|
1206
|
+
/**
|
|
1207
|
+
* Whether this conditional controls JSX rendering.
|
|
1208
|
+
* Set to true when the conditional appears in a JSX expression like {cond && <Component />}
|
|
1209
|
+
*/
|
|
1210
|
+
controlsJsxRendering?: boolean;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
/**
|
|
1214
|
+
* Extracts conditional usages from a condition expression for key attribute detection.
|
|
1215
|
+
* This function identifies which attributes are used in conditionals and how they're used.
|
|
1216
|
+
* It also tracks compound conditionals (&&-chains) where all conditions must be true together.
|
|
1217
|
+
*
|
|
1218
|
+
* @param condition The condition expression to analyze
|
|
1219
|
+
* @param context The analysis context
|
|
1220
|
+
* @param location Where this condition appears (if, ternary, logical-and, switch)
|
|
1221
|
+
* @param options Additional options including controlsJsxRendering flag
|
|
1222
|
+
*/
|
|
1223
|
+
export function extractConditionalUsage(
|
|
1224
|
+
condition: ts.Expression,
|
|
1225
|
+
context: AnalysisContext,
|
|
1226
|
+
location: ConditionalUsage['location'],
|
|
1227
|
+
options: ExtractConditionalOptions = {},
|
|
1228
|
+
): void {
|
|
1229
|
+
const { controlsJsxRendering } = options;
|
|
1230
|
+
// Internal recursive function with chain tracking
|
|
1231
|
+
function extractWithChainTracking(
|
|
1232
|
+
expr: ts.Expression,
|
|
1233
|
+
chainInfo: ChainInfo | null,
|
|
1234
|
+
isNegated: boolean,
|
|
1235
|
+
): void {
|
|
1236
|
+
const unwrapped = unwrapExpression(expr);
|
|
1237
|
+
|
|
1238
|
+
// Handle binary expressions with && (logical AND chains)
|
|
1239
|
+
// Example: `a && b && <Component />` - both a and b are conditional checks
|
|
1240
|
+
if (
|
|
1241
|
+
ts.isBinaryExpression(unwrapped) &&
|
|
1242
|
+
unwrapped.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken
|
|
1243
|
+
) {
|
|
1244
|
+
// Track if we're creating the chain at this level (root of the chain)
|
|
1245
|
+
const isChainRoot = !chainInfo;
|
|
1246
|
+
|
|
1247
|
+
// If no chainInfo, this is the root of a new chain
|
|
1248
|
+
if (isChainRoot) {
|
|
1249
|
+
const chainLength = countConditionsInAndChain(unwrapped);
|
|
1250
|
+
// Only create chain tracking for chains with 2+ conditions
|
|
1251
|
+
if (chainLength >= 2) {
|
|
1252
|
+
const chainId = `chain_${crypto.randomUUID().slice(0, 8)}`;
|
|
1253
|
+
const chainExpression = unwrapped.getText(context.sourceFile);
|
|
1254
|
+
const compound: CompoundConditional = {
|
|
1255
|
+
chainId,
|
|
1256
|
+
expression:
|
|
1257
|
+
chainExpression.length > 200
|
|
1258
|
+
? chainExpression.slice(0, 200) + '...'
|
|
1259
|
+
: chainExpression,
|
|
1260
|
+
conditions: [],
|
|
1261
|
+
location,
|
|
1262
|
+
sourceLocation: getSourceLocation(unwrapped, context.sourceFile),
|
|
1263
|
+
controlsJsxRendering,
|
|
1264
|
+
};
|
|
1265
|
+
chainInfo = {
|
|
1266
|
+
chainId,
|
|
1267
|
+
chainLength,
|
|
1268
|
+
chainExpression: compound.expression,
|
|
1269
|
+
currentPosition: 0,
|
|
1270
|
+
compound,
|
|
1271
|
+
};
|
|
1272
|
+
}
|
|
1273
|
+
}
|
|
1274
|
+
|
|
1275
|
+
// Recursively process left side
|
|
1276
|
+
extractWithChainTracking(unwrapped.left, chainInfo, false);
|
|
1277
|
+
|
|
1278
|
+
// Process right side if it's not JSX (JSX is the consequence, not the condition)
|
|
1279
|
+
const rightUnwrapped = unwrapExpression(unwrapped.right);
|
|
1280
|
+
const isJsxConsequence =
|
|
1281
|
+
ts.isJsxElement(rightUnwrapped) ||
|
|
1282
|
+
ts.isJsxSelfClosingElement(rightUnwrapped) ||
|
|
1283
|
+
ts.isJsxFragment(rightUnwrapped);
|
|
1284
|
+
|
|
1285
|
+
if (!isJsxConsequence) {
|
|
1286
|
+
extractWithChainTracking(unwrapped.right, chainInfo, false);
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
// If this is the root of the chain, register the compound conditional
|
|
1290
|
+
if (isChainRoot && chainInfo) {
|
|
1291
|
+
context.addCompoundConditional(chainInfo.compound);
|
|
1292
|
+
}
|
|
189
1293
|
return;
|
|
190
1294
|
}
|
|
191
1295
|
|
|
192
|
-
//
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
1296
|
+
// Handle binary expressions with || (logical OR)
|
|
1297
|
+
// When OR is inside an && chain, we need to continue chain tracking
|
|
1298
|
+
// and mark conditions as OR alternatives
|
|
1299
|
+
if (
|
|
1300
|
+
ts.isBinaryExpression(unwrapped) &&
|
|
1301
|
+
unwrapped.operatorToken.kind === ts.SyntaxKind.BarBarToken
|
|
1302
|
+
) {
|
|
1303
|
+
if (chainInfo) {
|
|
1304
|
+
// We're inside an && chain - continue tracking but mark as OR alternatives
|
|
1305
|
+
// Generate an orGroupId so conditions from both sides can be grouped
|
|
1306
|
+
const orGroupId =
|
|
1307
|
+
chainInfo.currentOrGroupId ?? `or_${crypto.randomUUID().slice(0, 8)}`;
|
|
1308
|
+
|
|
1309
|
+
// Process left side with OR group tracking
|
|
1310
|
+
const leftChainInfo = {
|
|
1311
|
+
...chainInfo,
|
|
1312
|
+
currentOrGroupId: orGroupId,
|
|
1313
|
+
};
|
|
1314
|
+
extractWithChainTracking(unwrapped.left, leftChainInfo, false);
|
|
1315
|
+
|
|
1316
|
+
// Process right side with same OR group
|
|
1317
|
+
// Note: we use leftChainInfo's currentPosition which may have been updated
|
|
1318
|
+
const rightChainInfo = {
|
|
1319
|
+
...leftChainInfo,
|
|
1320
|
+
currentPosition: chainInfo.currentPosition,
|
|
1321
|
+
};
|
|
1322
|
+
extractWithChainTracking(unwrapped.right, rightChainInfo, false);
|
|
1323
|
+
} else {
|
|
1324
|
+
// Not inside a chain - OR breaks into independent conditional checks
|
|
1325
|
+
extractWithChainTracking(unwrapped.left, null, false);
|
|
1326
|
+
extractWithChainTracking(unwrapped.right, null, false);
|
|
1327
|
+
}
|
|
201
1328
|
return;
|
|
202
1329
|
}
|
|
203
1330
|
|
|
204
|
-
//
|
|
205
|
-
if (
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
1331
|
+
// Handle comparison operators (===, !==, <, >, <=, >=)
|
|
1332
|
+
// Example: `if (status === 'active')` - status is compared against 'active'
|
|
1333
|
+
if (
|
|
1334
|
+
ts.isBinaryExpression(unwrapped) &&
|
|
1335
|
+
isComparisonOperator(unwrapped.operatorToken.kind)
|
|
1336
|
+
) {
|
|
1337
|
+
// Try to extract the variable and the compared value
|
|
1338
|
+
const leftPath = StructuredPath.fromNode(
|
|
1339
|
+
unwrapped.left,
|
|
1340
|
+
context.sourceFile,
|
|
1341
|
+
);
|
|
1342
|
+
const rightPath = StructuredPath.fromNode(
|
|
1343
|
+
unwrapped.right,
|
|
1344
|
+
context.sourceFile,
|
|
1345
|
+
);
|
|
1346
|
+
|
|
1347
|
+
// Determine the compared value for computing requiredValue
|
|
1348
|
+
const getRequiredValue = (
|
|
1349
|
+
literalValue: string | undefined,
|
|
1350
|
+
isNegatedComparison: boolean,
|
|
1351
|
+
): string | boolean | undefined => {
|
|
1352
|
+
if (literalValue === undefined) return undefined;
|
|
1353
|
+
// For !== comparisons, the condition is true when NOT equal to the value
|
|
1354
|
+
// For === comparisons, the condition is true when equal to the value
|
|
1355
|
+
const isNotEqual =
|
|
1356
|
+
unwrapped.operatorToken.kind ===
|
|
1357
|
+
ts.SyntaxKind.ExclamationEqualsEqualsToken ||
|
|
1358
|
+
unwrapped.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken;
|
|
1359
|
+
if (isNotEqual) {
|
|
1360
|
+
// !== 'value' means requiredValue is NOT 'value', but we express this as "not 'value'"
|
|
1361
|
+
return `not ${literalValue}`;
|
|
1362
|
+
}
|
|
1363
|
+
return literalValue;
|
|
1364
|
+
};
|
|
1365
|
+
|
|
1366
|
+
// Get the comparison operator string for the compound condition
|
|
1367
|
+
const comparisonOperator = getComparisonOperatorString(
|
|
1368
|
+
unwrapped.operatorToken.kind,
|
|
1369
|
+
);
|
|
1370
|
+
|
|
1371
|
+
// Helper to add a condition
|
|
1372
|
+
const addCondition = (
|
|
1373
|
+
path: string,
|
|
1374
|
+
conditionType: 'comparison' | 'truthiness',
|
|
1375
|
+
comparedValues?: string[],
|
|
1376
|
+
requiredValue?: string | boolean,
|
|
1377
|
+
sourceExpr?: ts.Expression,
|
|
1378
|
+
) => {
|
|
1379
|
+
const usage: ConditionalUsage = {
|
|
1380
|
+
path,
|
|
1381
|
+
conditionType,
|
|
1382
|
+
comparedValues,
|
|
1383
|
+
location,
|
|
1384
|
+
sourceLocation: getSourceLocation(unwrapped, context.sourceFile),
|
|
1385
|
+
isNegated,
|
|
1386
|
+
controlsJsxRendering,
|
|
1387
|
+
};
|
|
1388
|
+
|
|
1389
|
+
// Check for inline array-derived patterns (.length) on the source expression
|
|
1390
|
+
if (sourceExpr) {
|
|
1391
|
+
const arrayDerived = detectArrayDerivedPattern(sourceExpr);
|
|
1392
|
+
if (arrayDerived) {
|
|
1393
|
+
usage.derivedFrom = {
|
|
1394
|
+
operation: arrayDerived.operation,
|
|
1395
|
+
sourcePath: arrayDerived.sourcePath,
|
|
1396
|
+
};
|
|
1397
|
+
}
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
// Add chain info if part of a compound conditional
|
|
1401
|
+
if (chainInfo) {
|
|
1402
|
+
usage.chainId = chainInfo.chainId;
|
|
1403
|
+
usage.chainPosition = chainInfo.currentPosition;
|
|
1404
|
+
usage.chainLength = chainInfo.chainLength;
|
|
1405
|
+
usage.chainExpression = chainInfo.chainExpression;
|
|
1406
|
+
chainInfo.currentPosition++;
|
|
1407
|
+
|
|
1408
|
+
// Add to compound conditional conditions
|
|
1409
|
+
chainInfo.compound.conditions.push({
|
|
1410
|
+
path,
|
|
1411
|
+
conditionType,
|
|
1412
|
+
comparedValues,
|
|
1413
|
+
isNegated,
|
|
1414
|
+
requiredValue,
|
|
1415
|
+
...(comparisonOperator && { comparisonOperator }),
|
|
1416
|
+
...(chainInfo.currentOrGroupId && {
|
|
1417
|
+
orGroupId: chainInfo.currentOrGroupId,
|
|
1418
|
+
}),
|
|
1419
|
+
});
|
|
1420
|
+
}
|
|
1421
|
+
|
|
1422
|
+
context.addConditionalUsage(usage);
|
|
1423
|
+
};
|
|
1424
|
+
|
|
1425
|
+
// Check if left is a variable and right is a literal
|
|
1426
|
+
if (leftPath && isLiteralExpression(unwrapped.right)) {
|
|
1427
|
+
const literalValue = getLiteralValue(unwrapped.right, context);
|
|
1428
|
+
addCondition(
|
|
1429
|
+
leftPath.toLeftHandSideString(),
|
|
1430
|
+
'comparison',
|
|
1431
|
+
literalValue !== undefined ? [literalValue] : undefined,
|
|
1432
|
+
getRequiredValue(literalValue, isNegated),
|
|
1433
|
+
unwrapped.left, // Pass source expression for array derivation detection
|
|
1434
|
+
);
|
|
1435
|
+
return;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
// Check if right is a variable and left is a literal
|
|
1439
|
+
if (rightPath && isLiteralExpression(unwrapped.left)) {
|
|
1440
|
+
const literalValue = getLiteralValue(unwrapped.left, context);
|
|
1441
|
+
addCondition(
|
|
1442
|
+
rightPath.toLeftHandSideString(),
|
|
1443
|
+
'comparison',
|
|
1444
|
+
literalValue !== undefined ? [literalValue] : undefined,
|
|
1445
|
+
getRequiredValue(literalValue, isNegated),
|
|
1446
|
+
unwrapped.right, // Pass source expression for array derivation detection
|
|
1447
|
+
);
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1450
|
+
|
|
1451
|
+
// Both sides are variables - record both as comparisons without specific values
|
|
1452
|
+
if (leftPath) {
|
|
1453
|
+
addCondition(
|
|
1454
|
+
leftPath.toLeftHandSideString(),
|
|
1455
|
+
'comparison',
|
|
1456
|
+
undefined,
|
|
1457
|
+
undefined,
|
|
1458
|
+
unwrapped.left,
|
|
1459
|
+
);
|
|
1460
|
+
}
|
|
1461
|
+
if (rightPath) {
|
|
1462
|
+
addCondition(
|
|
1463
|
+
rightPath.toLeftHandSideString(),
|
|
1464
|
+
'comparison',
|
|
1465
|
+
undefined,
|
|
1466
|
+
undefined,
|
|
1467
|
+
unwrapped.right,
|
|
1468
|
+
);
|
|
1469
|
+
}
|
|
1470
|
+
return;
|
|
211
1471
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
1472
|
+
|
|
1473
|
+
// Handle prefix unary NOT expression: !variable
|
|
1474
|
+
// Example: `if (!isVisible)` - isVisible is a truthiness check (negated)
|
|
1475
|
+
if (
|
|
1476
|
+
ts.isPrefixUnaryExpression(unwrapped) &&
|
|
1477
|
+
unwrapped.operator === ts.SyntaxKind.ExclamationToken
|
|
1478
|
+
) {
|
|
1479
|
+
extractWithChainTracking(unwrapped.operand, chainInfo, !isNegated);
|
|
1480
|
+
return;
|
|
218
1481
|
}
|
|
219
|
-
return;
|
|
220
|
-
}
|
|
221
1482
|
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
1483
|
+
// Handle simple identifiers or property accesses (truthiness checks)
|
|
1484
|
+
// Example: `if (x)` or `x && <JSX />` - x is checked for truthiness
|
|
1485
|
+
const path = StructuredPath.fromNode(unwrapped, context.sourceFile);
|
|
1486
|
+
if (path && !path.isLiteral()) {
|
|
1487
|
+
const pathStr = path.toLeftHandSideString();
|
|
1488
|
+
const usage: ConditionalUsage = {
|
|
1489
|
+
path: pathStr,
|
|
1490
|
+
conditionType: 'truthiness',
|
|
1491
|
+
location,
|
|
1492
|
+
sourceLocation: getSourceLocation(unwrapped, context.sourceFile),
|
|
1493
|
+
isNegated,
|
|
1494
|
+
controlsJsxRendering,
|
|
1495
|
+
};
|
|
1496
|
+
|
|
1497
|
+
// Check for inline array-derived patterns (.some(), .every(), .includes(), .length)
|
|
1498
|
+
// This populates derivedFrom so downstream code can resolve to the base array path
|
|
1499
|
+
const arrayDerived = detectArrayDerivedPattern(unwrapped);
|
|
1500
|
+
if (arrayDerived) {
|
|
1501
|
+
usage.derivedFrom = {
|
|
1502
|
+
operation: arrayDerived.operation,
|
|
1503
|
+
sourcePath: arrayDerived.sourcePath,
|
|
1504
|
+
};
|
|
1505
|
+
}
|
|
231
1506
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
1507
|
+
// Add chain info if part of a compound conditional
|
|
1508
|
+
if (chainInfo) {
|
|
1509
|
+
usage.chainId = chainInfo.chainId;
|
|
1510
|
+
usage.chainPosition = chainInfo.currentPosition;
|
|
1511
|
+
usage.chainLength = chainInfo.chainLength;
|
|
1512
|
+
usage.chainExpression = chainInfo.chainExpression;
|
|
1513
|
+
chainInfo.currentPosition++;
|
|
1514
|
+
|
|
1515
|
+
// Add to compound conditional conditions
|
|
1516
|
+
// For truthiness, requiredValue is true if not negated, false if negated
|
|
1517
|
+
chainInfo.compound.conditions.push({
|
|
1518
|
+
path: pathStr,
|
|
1519
|
+
conditionType: 'truthiness',
|
|
1520
|
+
isNegated,
|
|
1521
|
+
requiredValue: !isNegated,
|
|
1522
|
+
...(chainInfo.currentOrGroupId && {
|
|
1523
|
+
orGroupId: chainInfo.currentOrGroupId,
|
|
1524
|
+
}),
|
|
1525
|
+
});
|
|
1526
|
+
}
|
|
1527
|
+
|
|
1528
|
+
context.addConditionalUsage(usage);
|
|
1529
|
+
}
|
|
241
1530
|
}
|
|
1531
|
+
|
|
1532
|
+
// Start extraction with no chain info
|
|
1533
|
+
extractWithChainTracking(condition, null, false);
|
|
242
1534
|
}
|
|
243
1535
|
|
|
244
1536
|
/**
|
|
@@ -341,7 +1633,28 @@ export function processExpression({
|
|
|
341
1633
|
) {
|
|
342
1634
|
markConditionVariablesAsNullable(unwrappedNode, context);
|
|
343
1635
|
// Extract conditional usages for key attribute detection
|
|
344
|
-
|
|
1636
|
+
// Only call from the OUTERMOST && expression to avoid duplicates
|
|
1637
|
+
// Check if parent is also a && (meaning we're nested)
|
|
1638
|
+
const parent = unwrappedNode.parent;
|
|
1639
|
+
const parentIsAndChain =
|
|
1640
|
+
parent &&
|
|
1641
|
+
ts.isBinaryExpression(parent) &&
|
|
1642
|
+
parent.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken;
|
|
1643
|
+
if (!parentIsAndChain) {
|
|
1644
|
+
extractConditionalUsage(unwrappedNode, context, 'logical-and');
|
|
1645
|
+
}
|
|
1646
|
+
}
|
|
1647
|
+
|
|
1648
|
+
// CRITICAL: Extract conditionals from JSX BEFORE checking child boundaries
|
|
1649
|
+
// JSX elements are NOT scopes - their expressions use variables from the parent scope.
|
|
1650
|
+
// Even if the JSX element is within a child boundary (e.g., because it contains callbacks),
|
|
1651
|
+
// we must still extract conditionals from JSX expression children like {x && <div>...</div>}
|
|
1652
|
+
if (
|
|
1653
|
+
ts.isJsxElement(unwrappedNode) ||
|
|
1654
|
+
ts.isJsxSelfClosingElement(unwrappedNode) ||
|
|
1655
|
+
ts.isJsxFragment(unwrappedNode)
|
|
1656
|
+
) {
|
|
1657
|
+
extractConditionalsFromJsx(unwrappedNode, context);
|
|
345
1658
|
}
|
|
346
1659
|
|
|
347
1660
|
// If the node falls within an excluded child scope, stop processing it.
|
|
@@ -378,7 +1691,7 @@ export function processExpression({
|
|
|
378
1691
|
const structure = context.getStructure();
|
|
379
1692
|
|
|
380
1693
|
// Propagate existing equivalencies for sub-properties
|
|
381
|
-
for (const [key,
|
|
1694
|
+
for (const [key, rawValue] of Object.entries(equivalentVariables)) {
|
|
382
1695
|
// Check if this equivalency is for a sub-property of the identifier
|
|
383
1696
|
// e.g., completeDataStructure['Function Arguments'] or completeDataStructure.foo
|
|
384
1697
|
if (
|
|
@@ -389,8 +1702,14 @@ export function processExpression({
|
|
|
389
1702
|
const newTargetPath = StructuredPath.fromBase(
|
|
390
1703
|
targetPath.toString() + subPath,
|
|
391
1704
|
);
|
|
392
|
-
|
|
393
|
-
|
|
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
|
+
}
|
|
394
1713
|
}
|
|
395
1714
|
}
|
|
396
1715
|
|
|
@@ -535,7 +1854,8 @@ export function processExpression({
|
|
|
535
1854
|
// Check if this is an environment variable access
|
|
536
1855
|
const fullText = unwrappedNode.getText(context.sourceFile);
|
|
537
1856
|
if (
|
|
538
|
-
fullText.includes('.env.') //
|
|
1857
|
+
fullText.includes('.env.') || // process.env.X, window.env.X
|
|
1858
|
+
isEnvStoreAccess(fullText) // env.X where env is likely an env config object
|
|
539
1859
|
) {
|
|
540
1860
|
context.addEnvironmentVariable(fullText);
|
|
541
1861
|
}
|
|
@@ -842,6 +2162,14 @@ export function processExpression({
|
|
|
842
2162
|
// e.g., `const tab = segments[0] || 'default'` should trace tab back to segments[0]
|
|
843
2163
|
if (operatorKind === ts.SyntaxKind.QuestionQuestionToken) {
|
|
844
2164
|
// specifically for ?? we create an equivalence to the left side
|
|
2165
|
+
// IMPORTANT: Also process the left side recursively to apply method semantics
|
|
2166
|
+
// (e.g., for `const segments = splat?.split('/') ?? []`, we need split semantics)
|
|
2167
|
+
processExpression({
|
|
2168
|
+
node: unwrappedNode.left,
|
|
2169
|
+
context,
|
|
2170
|
+
// Don't pass targetPath here - we'll establish equivalence separately below
|
|
2171
|
+
});
|
|
2172
|
+
|
|
845
2173
|
if (targetPath) {
|
|
846
2174
|
resultPath = StructuredPath.fromNode(
|
|
847
2175
|
unwrappedNode.left,
|
|
@@ -859,15 +2187,55 @@ export function processExpression({
|
|
|
859
2187
|
);
|
|
860
2188
|
}
|
|
861
2189
|
} else if (operatorKind === ts.SyntaxKind.BarBarToken) {
|
|
862
|
-
// For ||,
|
|
2190
|
+
// For ||, create equivalences to BOTH sides
|
|
863
2191
|
// This enables data flow tracing through fallback expressions
|
|
2192
|
+
// e.g., `const item = items.find(...) || null` should trace to both:
|
|
2193
|
+
// - items[] (from the find result)
|
|
2194
|
+
// - null (from the fallback)
|
|
864
2195
|
if (targetPath) {
|
|
865
|
-
|
|
2196
|
+
// Get paths for both sides
|
|
2197
|
+
const leftPath = StructuredPath.fromNode(
|
|
866
2198
|
unwrappedNode.left,
|
|
867
2199
|
context.sourceFile,
|
|
868
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
|
|
2217
|
+
processExpression({
|
|
2218
|
+
node: unwrappedNode.left,
|
|
2219
|
+
context,
|
|
2220
|
+
});
|
|
2221
|
+
processExpression({
|
|
2222
|
+
node: unwrappedNode.right,
|
|
2223
|
+
context,
|
|
2224
|
+
});
|
|
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;
|
|
869
2237
|
}
|
|
870
|
-
// Note:
|
|
2238
|
+
// Note: When there's no targetPath, we don't recursively process
|
|
871
2239
|
// because || is often used in boolean contexts where the full expression matters
|
|
872
2240
|
}
|
|
873
2241
|
} else if (operatorKind === ts.SyntaxKind.InstanceOfKeyword) {
|
|
@@ -930,9 +2298,10 @@ export function processExpression({
|
|
|
930
2298
|
return false;
|
|
931
2299
|
}
|
|
932
2300
|
|
|
933
|
-
//
|
|
934
|
-
//
|
|
935
|
-
|
|
2301
|
+
// Build call path using original source text for consistent schema paths.
|
|
2302
|
+
// IMPORTANT: Never use cyScope names in call paths - they are internal identifiers
|
|
2303
|
+
// that should not appear in schema paths or call signatures.
|
|
2304
|
+
const callPath = buildCallPathFromSource(unwrappedNode, context);
|
|
936
2305
|
|
|
937
2306
|
// 2. Process all arguments recursively WITH targetPath for proper equivalence
|
|
938
2307
|
for (let i = 0; i < unwrappedNode.arguments.length; i++) {
|
|
@@ -974,24 +2343,56 @@ export function processExpression({
|
|
|
974
2343
|
|
|
975
2344
|
// Get the source expression path (e.g., the object for obj.method())
|
|
976
2345
|
const sourceExpr = unwrappedNode.expression.expression;
|
|
977
|
-
const
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
if (
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
988
|
-
|
|
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
|
+
];
|
|
2356
|
+
|
|
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
|
+
);
|
|
989
2381
|
|
|
990
|
-
if (
|
|
991
|
-
//
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
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
|
+
}
|
|
995
2396
|
}
|
|
996
2397
|
}
|
|
997
2398
|
}
|
|
@@ -1099,6 +2500,13 @@ export function processExpression({
|
|
|
1099
2500
|
// Create a path for this property within the base
|
|
1100
2501
|
const propPath = targetPath.withProperty(propName);
|
|
1101
2502
|
|
|
2503
|
+
// Handle child boundaries (callback functions) in object properties
|
|
2504
|
+
// This establishes equivalency between the property path and the child scope
|
|
2505
|
+
// e.g., columns[0].renderCell → cyScope1()
|
|
2506
|
+
if (context.isChildBoundary(property.initializer)) {
|
|
2507
|
+
context.addChildBoundaryEquivalence(propPath, property.initializer);
|
|
2508
|
+
}
|
|
2509
|
+
|
|
1102
2510
|
// Process the property value with propPath as targetPath
|
|
1103
2511
|
// This allows nested object literals to work correctly
|
|
1104
2512
|
processExpression({
|
|
@@ -1398,14 +2806,30 @@ export function processExpression({
|
|
|
1398
2806
|
// Extract conditional usages for key attribute detection
|
|
1399
2807
|
extractConditionalUsage(unwrappedNode.condition, context, 'ternary');
|
|
1400
2808
|
|
|
2809
|
+
// Extract conditional effects (setter calls in ternary branches)
|
|
2810
|
+
const knownSetters = findUseStateSetters(context.sourceFile);
|
|
2811
|
+
const effects = extractConditionalEffectsFromTernary(
|
|
2812
|
+
unwrappedNode,
|
|
2813
|
+
context,
|
|
2814
|
+
knownSetters,
|
|
2815
|
+
);
|
|
2816
|
+
for (const effect of effects) {
|
|
2817
|
+
context.addConditionalEffect(effect);
|
|
2818
|
+
}
|
|
2819
|
+
|
|
1401
2820
|
// Process all parts recursively
|
|
1402
2821
|
processExpression({
|
|
1403
2822
|
node: unwrappedNode.condition,
|
|
1404
2823
|
context,
|
|
1405
2824
|
typeHint: 'boolean | unknown',
|
|
1406
2825
|
}); //TODO: could we capture that this is evidence of a boolean type?
|
|
1407
|
-
|
|
1408
|
-
|
|
2826
|
+
|
|
2827
|
+
// Process both branches WITH targetPath to establish equivalencies
|
|
2828
|
+
// This is critical for tracing nested properties through ternary assignments
|
|
2829
|
+
// e.g., const items = condition ? arr1 : arr2; items.map(i => i.prop)
|
|
2830
|
+
// We need items to be equivalent to both arr1 AND arr2 for proper tracing
|
|
2831
|
+
processExpression({ node: unwrappedNode.whenTrue, context, targetPath });
|
|
2832
|
+
processExpression({ node: unwrappedNode.whenFalse, context, targetPath });
|
|
1409
2833
|
|
|
1410
2834
|
// Create a path for the whole expression
|
|
1411
2835
|
const expressionSourcePath = nodeToSource(
|
|
@@ -1428,10 +2852,22 @@ export function processExpression({
|
|
|
1428
2852
|
// Register type for the expression
|
|
1429
2853
|
context.addType(expressionSourcePath, resultType);
|
|
1430
2854
|
|
|
1431
|
-
// If targetPath is provided,
|
|
2855
|
+
// If targetPath is provided, only register type (don't overwrite branch equivalencies)
|
|
2856
|
+
// The equivalencies to individual branches (set above) are more useful for tracing
|
|
2857
|
+
// than an equivalency to the entire ternary expression text
|
|
1432
2858
|
if (targetPath) {
|
|
1433
|
-
|
|
1434
|
-
|
|
2859
|
+
// NOTE: We intentionally do NOT add equivalence here.
|
|
2860
|
+
// The branch processing above already added equivalencies:
|
|
2861
|
+
// targetPath -> whenTrue branch
|
|
2862
|
+
// targetPath -> whenFalse branch
|
|
2863
|
+
// Adding an equivalence to expressionSourcePath would overwrite those
|
|
2864
|
+
// with a useless equivalence to the ternary text itself.
|
|
2865
|
+
//
|
|
2866
|
+
// Use updateSchemaType instead of addType because:
|
|
2867
|
+
// 1. Branch processing may have already set a type on targetPath
|
|
2868
|
+
// 2. addType has a guard that prevents overwriting specific types with 'unknown'
|
|
2869
|
+
// 3. updateSchemaType bypasses this guard, ensuring the ternary's computed type is used
|
|
2870
|
+
context.updateSchemaType(targetPath, resultType);
|
|
1435
2871
|
}
|
|
1436
2872
|
|
|
1437
2873
|
return true;
|
|
@@ -1514,6 +2950,35 @@ export function processExpression({
|
|
|
1514
2950
|
|
|
1515
2951
|
// Handle Arrow Functions: (p) => p.prop, (a, b) => { ... }
|
|
1516
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
|
+
|
|
1517
2982
|
// Create a path for the function
|
|
1518
2983
|
const functionPath = StructuredPath.empty();
|
|
1519
2984
|
|
|
@@ -1944,6 +3409,19 @@ export function processExpression({
|
|
|
1944
3409
|
for (const child of unwrappedNode.children) {
|
|
1945
3410
|
// Process expressions in JSX children: <div>{expr}</div>
|
|
1946
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
|
+
|
|
1947
3425
|
// Process the expression with StructuredPath.empty() as targetPath
|
|
1948
3426
|
// to trigger type registration without imposing prefix
|
|
1949
3427
|
processExpression({
|
|
@@ -1978,6 +3456,19 @@ export function processExpression({
|
|
|
1978
3456
|
for (const child of unwrappedNode.children) {
|
|
1979
3457
|
// Process expressions in JSX children: <>{expr}</>
|
|
1980
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
|
+
|
|
1981
3472
|
// Process the expression to extract structure
|
|
1982
3473
|
processExpression({
|
|
1983
3474
|
node: child.expression,
|
|
@@ -2232,6 +3723,9 @@ function processJsxAttribute(
|
|
|
2232
3723
|
if (ts.isJsxExpression(attr.initializer) && attr.initializer.expression) {
|
|
2233
3724
|
const expression = attr.initializer.expression;
|
|
2234
3725
|
if (context.isChildBoundary(expression)) {
|
|
3726
|
+
// Create equivalency between attribute path and child scope
|
|
3727
|
+
// e.g., Grid().signature[0].renderRow → cyScope1()
|
|
3728
|
+
context.addChildBoundaryEquivalence(attributePath, expression);
|
|
2235
3729
|
return true;
|
|
2236
3730
|
}
|
|
2237
3731
|
|