agentic-qe 3.7.8 → 3.7.10
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/.claude/skills/.validation/README.md +111 -111
- package/.claude/skills/.validation/examples/chaos-engineering-output.example.json +530 -530
- package/.claude/skills/.validation/examples/performance-testing-output.example.json +252 -252
- package/.claude/skills/.validation/examples/security-testing-output.example.json +413 -413
- package/.claude/skills/.validation/examples/testability-scoring-output.example.json +350 -350
- package/.claude/skills/.validation/schemas/skill-eval.schema.json +462 -462
- package/.claude/skills/.validation/schemas/skill-frontmatter.schema.json +341 -341
- package/.claude/skills/.validation/schemas/skill-output-meta.schema.json +199 -199
- package/.claude/skills/.validation/schemas/skill-output.template.json +610 -610
- package/.claude/skills/.validation/skill-validation-mcp-integration.md +250 -250
- package/.claude/skills/.validation/templates/eval.template.yaml +366 -366
- package/.claude/skills/.validation/templates/schemas/output.json +145 -145
- package/.claude/skills/.validation/templates/security-testing-eval.template.yaml +725 -725
- package/.claude/skills/.validation/templates/skill-frontmatter.example.yaml +225 -225
- package/.claude/skills/.validation/test-data/invalid-output.json +5 -5
- package/.claude/skills/.validation/test-data/minimal-output.json +9 -9
- package/.claude/skills/.validation/test-data/sample-output.json +73 -73
- package/.claude/skills/a11y-ally/evals/a11y-ally.yaml +376 -376
- package/.claude/skills/a11y-ally/schemas/output.json +549 -549
- package/.claude/skills/accessibility-testing/evals/accessibility-testing.yaml +719 -719
- package/.claude/skills/accessibility-testing/schemas/output.json +776 -776
- package/.claude/skills/accessibility-testing/test-data/sample-output.json +191 -191
- package/.claude/skills/agentic-quality-engineering/schemas/output.json +577 -577
- package/.claude/skills/api-testing-patterns/evals/api-testing-patterns.yaml +696 -696
- package/.claude/skills/api-testing-patterns/schemas/output.json +845 -845
- package/.claude/skills/aqe-v2-v3-migration/schemas/output.json +513 -513
- package/.claude/skills/brutal-honesty-review/schemas/output.json +291 -291
- package/.claude/skills/bug-reporting-excellence/schemas/output.json +288 -288
- package/.claude/skills/chaos-engineering-resilience/evals/chaos-engineering-resilience.yaml +761 -761
- package/.claude/skills/chaos-engineering-resilience/schemas/output.json +1205 -1205
- package/.claude/skills/cicd-pipeline-qe-orchestrator/evals/cicd-pipeline-qe-orchestrator.yaml +157 -157
- package/.claude/skills/cicd-pipeline-qe-orchestrator/schemas/output.json +542 -542
- package/.claude/skills/code-review-quality/schemas/output.json +264 -264
- package/.claude/skills/compatibility-testing/evals/compatibility-testing.yaml +410 -410
- package/.claude/skills/compatibility-testing/schemas/output.json +551 -551
- package/.claude/skills/compliance-testing/evals/compliance-testing.yaml +1107 -1107
- package/.claude/skills/compliance-testing/schemas/output.json +845 -845
- package/.claude/skills/consultancy-practices/schemas/output.json +282 -282
- package/.claude/skills/contract-testing/evals/contract-testing.yaml +748 -748
- package/.claude/skills/contract-testing/schemas/output.json +638 -638
- package/.claude/skills/database-testing/evals/database-testing.yaml +968 -968
- package/.claude/skills/database-testing/schemas/output.json +1446 -1446
- package/.claude/skills/debug-loop/SKILL.md +61 -61
- package/.claude/skills/enterprise-integration-testing/SKILL.md +735 -735
- package/.claude/skills/enterprise-integration-testing/evals/enterprise-integration-testing.yaml +158 -0
- package/.claude/skills/enterprise-integration-testing/schemas/output.json +74 -0
- package/.claude/skills/enterprise-integration-testing/scripts/validate-config.json +25 -0
- package/.claude/skills/iterative-loop/SKILL.md +371 -371
- package/.claude/skills/localization-testing/evals/localization-testing.yaml +544 -544
- package/.claude/skills/localization-testing/schemas/output.json +325 -325
- package/.claude/skills/middleware-testing-patterns/SKILL.md +798 -798
- package/.claude/skills/middleware-testing-patterns/evals/middleware-testing-patterns.yaml +153 -0
- package/.claude/skills/middleware-testing-patterns/schemas/output.json +58 -0
- package/.claude/skills/middleware-testing-patterns/scripts/validate-config.json +25 -0
- package/.claude/skills/mobile-testing/evals/mobile-testing.yaml +537 -537
- package/.claude/skills/mobile-testing/schemas/output.json +318 -318
- package/.claude/skills/mutation-testing/evals/mutation-testing.yaml +652 -652
- package/.claude/skills/mutation-testing/schemas/output.json +707 -707
- package/.claude/skills/mutation-testing/test-data/sample-output.json +295 -295
- package/.claude/skills/n8n-expression-testing/evals/n8n-expression-testing.yaml +450 -450
- package/.claude/skills/n8n-expression-testing/schemas/output.json +369 -369
- package/.claude/skills/n8n-integration-testing-patterns/evals/n8n-integration-testing-patterns.yaml +522 -522
- package/.claude/skills/n8n-integration-testing-patterns/schemas/output.json +291 -291
- package/.claude/skills/n8n-security-testing/evals/n8n-security-testing.yaml +493 -493
- package/.claude/skills/n8n-security-testing/schemas/output.json +293 -293
- package/.claude/skills/n8n-trigger-testing-strategies/evals/n8n-trigger-testing-strategies.yaml +500 -500
- package/.claude/skills/n8n-trigger-testing-strategies/schemas/output.json +295 -295
- package/.claude/skills/n8n-workflow-testing-fundamentals/evals/n8n-workflow-testing-fundamentals.yaml +497 -497
- package/.claude/skills/n8n-workflow-testing-fundamentals/schemas/output.json +254 -254
- package/.claude/skills/observability-testing-patterns/SKILL.md +930 -930
- package/.claude/skills/observability-testing-patterns/evals/observability-testing-patterns.yaml +157 -0
- package/.claude/skills/observability-testing-patterns/schemas/output.json +58 -0
- package/.claude/skills/observability-testing-patterns/scripts/validate-config.json +25 -0
- package/.claude/skills/pentest-validation/SKILL.md +268 -268
- package/.claude/skills/pentest-validation/evals/pentest-validation.yaml +708 -708
- package/.claude/skills/pentest-validation/schemas/output.json +281 -281
- package/.claude/skills/performance-analysis/evals/performance-analysis.yaml +144 -144
- package/.claude/skills/performance-analysis/schemas/output.json +588 -588
- package/.claude/skills/performance-testing/evals/performance-testing.yaml +772 -772
- package/.claude/skills/performance-testing/schemas/output.json +1184 -1184
- package/.claude/skills/pr-review/SKILL.md +61 -61
- package/.claude/skills/qcsd-cicd-swarm/SKILL.md +2206 -2206
- package/.claude/skills/qcsd-cicd-swarm/evals/qcsd-cicd-swarm.yaml +211 -0
- package/.claude/skills/qcsd-cicd-swarm/schemas/output.json +86 -0
- package/.claude/skills/qcsd-cicd-swarm/scripts/validate-config.json +30 -0
- package/.claude/skills/qcsd-development-swarm/SKILL.md +2154 -2154
- package/.claude/skills/qcsd-development-swarm/evals/qcsd-development-swarm.yaml +162 -0
- package/.claude/skills/qcsd-development-swarm/schemas/output.json +72 -0
- package/.claude/skills/qcsd-development-swarm/scripts/validate-config.json +25 -0
- package/.claude/skills/qcsd-ideation-swarm/evals/qcsd-ideation-swarm.yaml +138 -138
- package/.claude/skills/qcsd-ideation-swarm/schemas/output.json +568 -568
- package/.claude/skills/qcsd-production-swarm/SKILL.md +2781 -2781
- package/.claude/skills/qcsd-production-swarm/evals/qcsd-production-swarm.yaml +246 -246
- package/.claude/skills/qcsd-production-swarm/schemas/output.json +505 -505
- package/.claude/skills/qcsd-production-swarm/scripts/validate-config.json +25 -25
- package/.claude/skills/qe-chaos-resilience/evals/qe-chaos-resilience.yaml +443 -443
- package/.claude/skills/qe-chaos-resilience/schemas/output.json +314 -314
- package/.claude/skills/qe-code-intelligence/evals/qe-code-intelligence.yaml +459 -459
- package/.claude/skills/qe-code-intelligence/schemas/output.json +315 -315
- package/.claude/skills/qe-contract-testing/evals/qe-contract-testing.yaml +513 -513
- package/.claude/skills/qe-contract-testing/schemas/output.json +295 -295
- package/.claude/skills/qe-coverage-analysis/evals/qe-coverage-analysis.yaml +494 -494
- package/.claude/skills/qe-coverage-analysis/schemas/output.json +286 -286
- package/.claude/skills/qe-defect-intelligence/evals/qe-defect-intelligence.yaml +511 -511
- package/.claude/skills/qe-defect-intelligence/schemas/output.json +283 -283
- package/.claude/skills/qe-iterative-loop/schemas/output.json +264 -264
- package/.claude/skills/qe-learning-optimization/evals/qe-learning-optimization.yaml +144 -144
- package/.claude/skills/qe-learning-optimization/schemas/output.json +288 -288
- package/.claude/skills/qe-quality-assessment/evals/qe-quality-assessment.yaml +506 -506
- package/.claude/skills/qe-quality-assessment/schemas/output.json +550 -550
- package/.claude/skills/qe-requirements-validation/evals/qe-requirements-validation.yaml +598 -598
- package/.claude/skills/qe-requirements-validation/schemas/output.json +587 -587
- package/.claude/skills/qe-security-compliance/evals/qe-security-compliance.yaml +595 -595
- package/.claude/skills/qe-security-compliance/schemas/output.json +498 -498
- package/.claude/skills/qe-test-execution/evals/qe-test-execution.yaml +607 -607
- package/.claude/skills/qe-test-execution/schemas/output.json +529 -529
- package/.claude/skills/qe-test-generation/evals/qe-test-generation.yaml +148 -148
- package/.claude/skills/qe-test-generation/schemas/output.json +439 -439
- package/.claude/skills/qe-visual-accessibility/evals/qe-visual-accessibility.yaml +142 -142
- package/.claude/skills/qe-visual-accessibility/schemas/output.json +491 -491
- package/.claude/skills/quality-metrics/evals/quality-metrics.yaml +494 -494
- package/.claude/skills/quality-metrics/schemas/output.json +403 -403
- package/.claude/skills/refactoring-patterns/schemas/output.json +475 -475
- package/.claude/skills/regression-testing/evals/regression-testing.yaml +504 -504
- package/.claude/skills/regression-testing/schemas/output.json +311 -311
- package/.claude/skills/release/SKILL.md +347 -347
- package/.claude/skills/risk-based-testing/evals/risk-based-testing.yaml +141 -141
- package/.claude/skills/risk-based-testing/schemas/output.json +480 -480
- package/.claude/skills/security-testing/evals/security-testing.yaml +789 -789
- package/.claude/skills/security-testing/schemas/output.json +879 -879
- package/.claude/skills/security-visual-testing/evals/security-visual-testing.yaml +163 -163
- package/.claude/skills/security-visual-testing/schemas/output.json +486 -486
- package/.claude/skills/sfdipot-product-factors/SKILL.md +239 -239
- package/.claude/skills/sherlock-review/schemas/output.json +297 -297
- package/.claude/skills/shift-left-testing/evals/shift-left-testing.yaml +145 -145
- package/.claude/skills/shift-left-testing/schemas/output.json +459 -459
- package/.claude/skills/shift-right-testing/evals/shift-right-testing.yaml +147 -147
- package/.claude/skills/shift-right-testing/schemas/output.json +418 -418
- package/.claude/skills/skills-manifest.json +1 -1
- package/.claude/skills/tdd-london-chicago/schemas/output.json +444 -444
- package/.claude/skills/technical-writing/schemas/output.json +268 -268
- package/.claude/skills/test-automation-strategy/evals/test-automation-strategy.yaml +148 -148
- package/.claude/skills/test-automation-strategy/schemas/output.json +444 -444
- package/.claude/skills/test-data-management/evals/test-data-management.yaml +504 -504
- package/.claude/skills/test-data-management/schemas/output.json +284 -284
- package/.claude/skills/test-design-techniques/evals/test-design-techniques.yaml +142 -142
- package/.claude/skills/test-design-techniques/schemas/output.json +295 -295
- package/.claude/skills/test-environment-management/schemas/output.json +310 -310
- package/.claude/skills/test-idea-rewriting/SKILL.md +229 -229
- package/.claude/skills/test-reporting-analytics/evals/test-reporting-analytics.yaml +155 -155
- package/.claude/skills/test-reporting-analytics/schemas/output.json +329 -329
- package/.claude/skills/testability-scoring/evals/testability-scoring.yaml +814 -814
- package/.claude/skills/testability-scoring/resources/templates/config.template.js +84 -84
- package/.claude/skills/testability-scoring/schemas/output.json +606 -606
- package/.claude/skills/testability-scoring/scripts/generate-html-report.js +1007 -1007
- package/.claude/skills/trust-tier-manifest.json +78 -7
- package/.claude/skills/verification-quality/evals/verification-quality.yaml +150 -150
- package/.claude/skills/verification-quality/schemas/output.json +432 -432
- package/.claude/skills/visual-testing-advanced/evals/visual-testing-advanced.yaml +154 -154
- package/.claude/skills/visual-testing-advanced/schemas/output.json +294 -294
- package/.claude/skills/wms-testing-patterns/evals/wms-testing-patterns.yaml +165 -165
- package/.claude/skills/wms-testing-patterns/schemas/output.json +150 -150
- package/.claude/skills/wms-testing-patterns/scripts/validate-config.json +51 -51
- package/CHANGELOG.md +34 -0
- package/README.md +169 -900
- package/assets/agents/v3/helpers/quality-criteria/evidence-classification.md +116 -116
- package/assets/agents/v3/helpers/quality-criteria/htsm-categories.md +139 -139
- package/assets/governance/constitution.md +202 -202
- package/assets/governance/shards/chaos-resilience.shard.md +221 -221
- package/assets/governance/shards/code-intelligence.shard.md +178 -178
- package/assets/governance/shards/contract-testing.shard.md +206 -206
- package/assets/governance/shards/coverage-analysis.shard.md +146 -146
- package/assets/governance/shards/defect-intelligence.shard.md +182 -182
- package/assets/governance/shards/learning-optimization.shard.md +248 -248
- package/assets/governance/shards/quality-assessment.shard.md +165 -165
- package/assets/governance/shards/requirements-validation.shard.md +177 -177
- package/assets/governance/shards/security-compliance.shard.md +196 -196
- package/assets/governance/shards/test-execution.shard.md +156 -156
- package/assets/governance/shards/test-generation.shard.md +128 -128
- package/assets/governance/shards/visual-accessibility.shard.md +209 -209
- package/assets/hooks/cross-phase-memory.yaml +253 -253
- package/assets/patterns/adr-051-booster-patterns.json +78 -78
- package/assets/patterns/adr-051-embedding-patterns.json +147 -147
- package/assets/patterns/adr-051-integration-summary.json +62 -62
- package/assets/patterns/adr-051-reasoning-patterns.json +166 -166
- package/assets/patterns/adr-051-router-patterns.json +113 -113
- package/assets/patterns/index.json +136 -136
- package/assets/skills/.validation/README.md +111 -111
- package/assets/skills/.validation/examples/chaos-engineering-output.example.json +530 -530
- package/assets/skills/.validation/examples/performance-testing-output.example.json +252 -252
- package/assets/skills/.validation/examples/security-testing-output.example.json +413 -413
- package/assets/skills/.validation/examples/testability-scoring-output.example.json +350 -350
- package/assets/skills/.validation/schemas/skill-eval.schema.json +462 -462
- package/assets/skills/.validation/schemas/skill-frontmatter.schema.json +341 -341
- package/assets/skills/.validation/schemas/skill-output-meta.schema.json +199 -199
- package/assets/skills/.validation/schemas/skill-output.template.json +610 -610
- package/assets/skills/.validation/skill-validation-mcp-integration.md +250 -250
- package/assets/skills/.validation/templates/eval.template.yaml +366 -366
- package/assets/skills/.validation/templates/schemas/output.json +145 -145
- package/assets/skills/.validation/templates/security-testing-eval.template.yaml +725 -725
- package/assets/skills/.validation/templates/skill-frontmatter.example.yaml +225 -225
- package/assets/skills/.validation/test-data/invalid-output.json +5 -5
- package/assets/skills/.validation/test-data/minimal-output.json +9 -9
- package/assets/skills/.validation/test-data/sample-output.json +73 -73
- package/assets/skills/a11y-ally/SKILL.md +1664 -1658
- package/assets/skills/a11y-ally/evals/a11y-ally.yaml +376 -0
- package/assets/skills/a11y-ally/schemas/output.json +549 -0
- package/assets/skills/a11y-ally/scripts/validate-config.json +42 -0
- package/assets/skills/accessibility-testing/evals/accessibility-testing.yaml +719 -719
- package/assets/skills/accessibility-testing/schemas/output.json +776 -776
- package/assets/skills/accessibility-testing/test-data/sample-output.json +191 -191
- package/assets/skills/agentic-quality-engineering/schemas/output.json +577 -577
- package/assets/skills/api-testing-patterns/evals/api-testing-patterns.yaml +696 -696
- package/assets/skills/api-testing-patterns/schemas/output.json +845 -845
- package/assets/skills/aqe-v2-v3-migration/schemas/output.json +513 -513
- package/assets/skills/brutal-honesty-review/SKILL.md +5 -0
- package/assets/skills/brutal-honesty-review/schemas/output.json +291 -0
- package/assets/skills/brutal-honesty-review/scripts/validate-config.json +34 -0
- package/assets/skills/bug-reporting-excellence/schemas/output.json +288 -288
- package/assets/skills/chaos-engineering-resilience/evals/chaos-engineering-resilience.yaml +761 -761
- package/assets/skills/chaos-engineering-resilience/schemas/output.json +1205 -1205
- package/assets/skills/cicd-pipeline-qe-orchestrator/README.md +1 -1
- package/assets/skills/cicd-pipeline-qe-orchestrator/SKILL.md +6 -0
- package/assets/skills/cicd-pipeline-qe-orchestrator/evals/cicd-pipeline-qe-orchestrator.yaml +157 -0
- package/assets/skills/cicd-pipeline-qe-orchestrator/schemas/output.json +542 -0
- package/assets/skills/cicd-pipeline-qe-orchestrator/scripts/validate-config.json +42 -0
- package/assets/skills/code-review-quality/schemas/output.json +264 -264
- package/assets/skills/compatibility-testing/evals/compatibility-testing.yaml +410 -410
- package/assets/skills/compatibility-testing/schemas/output.json +551 -551
- package/assets/skills/compliance-testing/evals/compliance-testing.yaml +1107 -1107
- package/assets/skills/compliance-testing/schemas/output.json +845 -845
- package/assets/skills/consultancy-practices/schemas/output.json +282 -282
- package/assets/skills/contract-testing/evals/contract-testing.yaml +748 -748
- package/assets/skills/contract-testing/schemas/output.json +638 -638
- package/assets/skills/database-testing/evals/database-testing.yaml +968 -968
- package/assets/skills/database-testing/schemas/output.json +1446 -1446
- package/assets/skills/debug-loop/SKILL.md +61 -61
- package/assets/skills/enterprise-integration-testing/SKILL.md +735 -735
- package/assets/skills/enterprise-integration-testing/evals/enterprise-integration-testing.yaml +158 -0
- package/assets/skills/enterprise-integration-testing/schemas/output.json +74 -0
- package/assets/skills/enterprise-integration-testing/scripts/validate-config.json +25 -0
- package/assets/skills/localization-testing/evals/localization-testing.yaml +544 -544
- package/assets/skills/localization-testing/schemas/output.json +325 -325
- package/assets/skills/middleware-testing-patterns/SKILL.md +798 -798
- package/assets/skills/middleware-testing-patterns/evals/middleware-testing-patterns.yaml +153 -0
- package/assets/skills/middleware-testing-patterns/schemas/output.json +58 -0
- package/assets/skills/middleware-testing-patterns/scripts/validate-config.json +25 -0
- package/assets/skills/mobile-testing/evals/mobile-testing.yaml +537 -537
- package/assets/skills/mobile-testing/schemas/output.json +318 -318
- package/assets/skills/mutation-testing/evals/mutation-testing.yaml +652 -652
- package/assets/skills/mutation-testing/schemas/output.json +707 -707
- package/assets/skills/mutation-testing/test-data/sample-output.json +295 -295
- package/assets/skills/n8n-expression-testing/SKILL.md +6 -0
- package/assets/skills/n8n-expression-testing/evals/n8n-expression-testing.yaml +450 -0
- package/assets/skills/n8n-expression-testing/schemas/output.json +369 -0
- package/assets/skills/n8n-expression-testing/scripts/validate-config.json +39 -0
- package/assets/skills/n8n-integration-testing-patterns/SKILL.md +6 -0
- package/assets/skills/n8n-integration-testing-patterns/evals/n8n-integration-testing-patterns.yaml +522 -0
- package/assets/skills/n8n-integration-testing-patterns/schemas/output.json +291 -0
- package/assets/skills/n8n-integration-testing-patterns/scripts/validate-config.json +34 -0
- package/assets/skills/n8n-security-testing/SKILL.md +6 -0
- package/assets/skills/n8n-security-testing/evals/n8n-security-testing.yaml +493 -0
- package/assets/skills/n8n-security-testing/schemas/output.json +293 -0
- package/assets/skills/n8n-security-testing/scripts/validate-config.json +34 -0
- package/assets/skills/n8n-trigger-testing-strategies/SKILL.md +6 -0
- package/assets/skills/n8n-trigger-testing-strategies/evals/n8n-trigger-testing-strategies.yaml +500 -0
- package/assets/skills/n8n-trigger-testing-strategies/schemas/output.json +295 -0
- package/assets/skills/n8n-trigger-testing-strategies/scripts/validate-config.json +34 -0
- package/assets/skills/n8n-workflow-testing-fundamentals/SKILL.md +6 -0
- package/assets/skills/n8n-workflow-testing-fundamentals/evals/n8n-workflow-testing-fundamentals.yaml +497 -0
- package/assets/skills/n8n-workflow-testing-fundamentals/schemas/output.json +254 -0
- package/assets/skills/n8n-workflow-testing-fundamentals/scripts/validate-config.json +35 -0
- package/assets/skills/observability-testing-patterns/SKILL.md +930 -930
- package/assets/skills/observability-testing-patterns/evals/observability-testing-patterns.yaml +157 -0
- package/assets/skills/observability-testing-patterns/schemas/output.json +58 -0
- package/assets/skills/observability-testing-patterns/scripts/validate-config.json +25 -0
- package/assets/skills/pentest-validation/SKILL.md +268 -268
- package/assets/skills/pentest-validation/evals/pentest-validation.yaml +708 -708
- package/assets/skills/pentest-validation/schemas/output.json +281 -281
- package/assets/skills/pentest-validation/scripts/validate-config.json +12 -0
- package/assets/skills/performance-testing/evals/performance-testing.yaml +772 -772
- package/assets/skills/performance-testing/schemas/output.json +1184 -1184
- package/assets/skills/pr-review/SKILL.md +61 -61
- package/assets/skills/qcsd-cicd-swarm/SKILL.md +2206 -2206
- package/assets/skills/qcsd-cicd-swarm/evals/qcsd-cicd-swarm.yaml +211 -0
- package/assets/skills/qcsd-cicd-swarm/schemas/output.json +86 -0
- package/assets/skills/qcsd-cicd-swarm/scripts/validate-config.json +30 -0
- package/assets/skills/qcsd-development-swarm/SKILL.md +2154 -2154
- package/assets/skills/qcsd-development-swarm/evals/qcsd-development-swarm.yaml +162 -0
- package/assets/skills/qcsd-development-swarm/schemas/output.json +72 -0
- package/assets/skills/qcsd-development-swarm/scripts/validate-config.json +25 -0
- package/assets/skills/qcsd-ideation-swarm/evals/qcsd-ideation-swarm.yaml +138 -0
- package/assets/skills/qcsd-ideation-swarm/schemas/output.json +568 -0
- package/assets/skills/qcsd-ideation-swarm/scripts/validate-config.json +25 -0
- package/assets/skills/qcsd-production-swarm/SKILL.md +2781 -0
- package/assets/skills/qcsd-production-swarm/evals/qcsd-production-swarm.yaml +246 -0
- package/assets/skills/qcsd-production-swarm/schemas/output.json +505 -0
- package/assets/skills/qcsd-production-swarm/scripts/validate-config.json +25 -0
- package/assets/skills/qcsd-refinement-swarm/evals/qcsd-refinement-swarm.yaml +139 -0
- package/assets/skills/qcsd-refinement-swarm/schemas/output.json +811 -0
- package/assets/skills/qcsd-refinement-swarm/scripts/validate-config.json +25 -0
- package/assets/skills/qe-chaos-resilience/evals/qe-chaos-resilience.yaml +443 -443
- package/assets/skills/qe-chaos-resilience/schemas/output.json +314 -314
- package/assets/skills/qe-code-intelligence/evals/qe-code-intelligence.yaml +459 -459
- package/assets/skills/qe-code-intelligence/schemas/output.json +315 -315
- package/assets/skills/qe-contract-testing/evals/qe-contract-testing.yaml +513 -513
- package/assets/skills/qe-contract-testing/schemas/output.json +295 -295
- package/assets/skills/qe-coverage-analysis/evals/qe-coverage-analysis.yaml +494 -494
- package/assets/skills/qe-coverage-analysis/schemas/output.json +286 -286
- package/assets/skills/qe-defect-intelligence/evals/qe-defect-intelligence.yaml +511 -511
- package/assets/skills/qe-defect-intelligence/schemas/output.json +283 -283
- package/assets/skills/qe-iterative-loop/schemas/output.json +264 -264
- package/assets/skills/qe-learning-optimization/evals/qe-learning-optimization.yaml +144 -144
- package/assets/skills/qe-learning-optimization/schemas/output.json +288 -288
- package/assets/skills/qe-quality-assessment/evals/qe-quality-assessment.yaml +506 -506
- package/assets/skills/qe-quality-assessment/schemas/output.json +550 -550
- package/assets/skills/qe-requirements-validation/evals/qe-requirements-validation.yaml +598 -598
- package/assets/skills/qe-requirements-validation/schemas/output.json +587 -587
- package/assets/skills/qe-security-compliance/evals/qe-security-compliance.yaml +595 -595
- package/assets/skills/qe-security-compliance/schemas/output.json +498 -498
- package/assets/skills/qe-test-execution/evals/qe-test-execution.yaml +607 -607
- package/assets/skills/qe-test-execution/schemas/output.json +529 -529
- package/assets/skills/qe-test-generation/evals/qe-test-generation.yaml +148 -148
- package/assets/skills/qe-test-generation/schemas/output.json +439 -439
- package/assets/skills/qe-visual-accessibility/evals/qe-visual-accessibility.yaml +142 -142
- package/assets/skills/qe-visual-accessibility/schemas/output.json +491 -491
- package/assets/skills/quality-metrics/evals/quality-metrics.yaml +494 -494
- package/assets/skills/quality-metrics/schemas/output.json +403 -403
- package/assets/skills/refactoring-patterns/schemas/output.json +475 -475
- package/assets/skills/regression-testing/evals/regression-testing.yaml +504 -504
- package/assets/skills/regression-testing/schemas/output.json +311 -311
- package/assets/skills/risk-based-testing/evals/risk-based-testing.yaml +141 -141
- package/assets/skills/risk-based-testing/schemas/output.json +480 -480
- package/assets/skills/security-testing/evals/security-testing.yaml +789 -789
- package/assets/skills/security-testing/schemas/output.json +879 -879
- package/assets/skills/security-visual-testing/evals/security-visual-testing.yaml +163 -163
- package/assets/skills/security-visual-testing/schemas/output.json +486 -486
- package/assets/skills/security-visual-testing/scripts/validate-config.json +45 -0
- package/assets/skills/sfdipot-product-factors/SKILL.md +239 -239
- package/assets/skills/sherlock-review/SKILL.md +5 -0
- package/assets/skills/sherlock-review/schemas/output.json +297 -0
- package/assets/skills/sherlock-review/scripts/validate-config.json +35 -0
- package/assets/skills/shift-left-testing/evals/shift-left-testing.yaml +145 -145
- package/assets/skills/shift-left-testing/schemas/output.json +459 -459
- package/assets/skills/shift-right-testing/evals/shift-right-testing.yaml +147 -147
- package/assets/skills/shift-right-testing/schemas/output.json +418 -418
- package/assets/skills/tdd-london-chicago/schemas/output.json +444 -444
- package/assets/skills/technical-writing/schemas/output.json +268 -268
- package/assets/skills/test-automation-strategy/evals/test-automation-strategy.yaml +148 -148
- package/assets/skills/test-automation-strategy/schemas/output.json +444 -444
- package/assets/skills/test-data-management/evals/test-data-management.yaml +504 -504
- package/assets/skills/test-data-management/schemas/output.json +284 -284
- package/assets/skills/test-design-techniques/evals/test-design-techniques.yaml +142 -142
- package/assets/skills/test-design-techniques/schemas/output.json +295 -295
- package/assets/skills/test-environment-management/schemas/output.json +310 -310
- package/assets/skills/test-idea-rewriting/SKILL.md +229 -229
- package/assets/skills/test-reporting-analytics/evals/test-reporting-analytics.yaml +155 -155
- package/assets/skills/test-reporting-analytics/schemas/output.json +329 -329
- package/assets/skills/testability-scoring/SKILL.md +5 -0
- package/assets/skills/testability-scoring/evals/testability-scoring.yaml +814 -0
- package/assets/skills/testability-scoring/resources/templates/config.template.js +84 -84
- package/assets/skills/testability-scoring/schemas/output.json +606 -0
- package/assets/skills/testability-scoring/scripts/generate-html-report.js +1007 -1007
- package/assets/skills/testability-scoring/scripts/validate-config.json +42 -0
- package/assets/skills/trust-tier-manifest.json +2404 -0
- package/assets/skills/verification-quality/evals/verification-quality.yaml +150 -150
- package/assets/skills/verification-quality/schemas/output.json +432 -432
- package/assets/skills/visual-testing-advanced/evals/visual-testing-advanced.yaml +154 -154
- package/assets/skills/visual-testing-advanced/schemas/output.json +294 -294
- package/assets/skills/wms-testing-patterns/evals/wms-testing-patterns.yaml +165 -0
- package/assets/skills/wms-testing-patterns/schemas/output.json +150 -0
- package/assets/skills/wms-testing-patterns/scripts/validate-config.json +51 -0
- package/assets/templates/validation-summary.json +56 -56
- package/dist/benchmarks/performance-benchmarks.js +1 -1
- package/dist/cli/bundle.js +9158 -2288
- package/dist/cli/commands/hooks.d.ts.map +1 -1
- package/dist/cli/commands/hooks.js +92 -0
- package/dist/cli/commands/hooks.js.map +1 -1
- package/dist/cli/commands/mcp.d.ts.map +1 -1
- package/dist/cli/commands/mcp.js +11 -9
- package/dist/cli/commands/mcp.js.map +1 -1
- package/dist/cli/commands/migrate.js +2 -2
- package/dist/coordination/constants.d.ts +1 -1
- package/dist/coordination/constants.js +1 -1
- package/dist/coordination/handlers/coverage-handlers.js +1 -1
- package/dist/coordination/handlers/coverage-handlers.js.map +1 -1
- package/dist/domains/code-intelligence/services/semantic-analyzer.d.ts +1 -1
- package/dist/domains/code-intelligence/services/semantic-analyzer.d.ts.map +1 -1
- package/dist/domains/code-intelligence/services/semantic-analyzer.js +1 -1
- package/dist/domains/code-intelligence/services/semantic-analyzer.js.map +1 -1
- package/dist/domains/coverage-analysis/coordinator.js +1 -1
- package/dist/domains/coverage-analysis/services/coverage-analyzer.js +1 -1
- package/dist/domains/coverage-analysis/services/coverage-embedder.d.ts +1 -1
- package/dist/domains/coverage-analysis/services/coverage-embedder.js +1 -1
- package/dist/domains/coverage-analysis/services/gap-detector.js +1 -1
- package/dist/domains/coverage-analysis/services/ghost-coverage-analyzer.js +1 -1
- package/dist/domains/coverage-analysis/services/hnsw-index.d.ts +2 -2
- package/dist/domains/coverage-analysis/services/hnsw-index.js +3 -3
- package/dist/domains/coverage-analysis/services/sublinear-analyzer.d.ts +1 -1
- package/dist/domains/coverage-analysis/services/sublinear-analyzer.js +1 -1
- package/dist/domains/test-execution/services/test-prioritizer.js +1 -1
- package/dist/domains/test-generation/context/rust-context-builder.d.ts +31 -0
- package/dist/domains/test-generation/context/rust-context-builder.d.ts.map +1 -0
- package/dist/domains/test-generation/context/rust-context-builder.js +27 -0
- package/dist/domains/test-generation/context/rust-context-builder.js.map +1 -0
- package/dist/domains/test-generation/coordinator.js +3 -3
- package/dist/domains/test-generation/coordinator.js.map +1 -1
- package/dist/domains/test-generation/detectors/mobile-detector.d.ts +41 -0
- package/dist/domains/test-generation/detectors/mobile-detector.d.ts.map +1 -0
- package/dist/domains/test-generation/detectors/mobile-detector.js +111 -0
- package/dist/domains/test-generation/detectors/mobile-detector.js.map +1 -0
- package/dist/domains/test-generation/detectors/spring-detector.d.ts +22 -0
- package/dist/domains/test-generation/detectors/spring-detector.d.ts.map +1 -0
- package/dist/domains/test-generation/detectors/spring-detector.js +37 -0
- package/dist/domains/test-generation/detectors/spring-detector.js.map +1 -0
- package/dist/domains/test-generation/factories/test-generator-factory.d.ts +2 -1
- package/dist/domains/test-generation/factories/test-generator-factory.d.ts.map +1 -1
- package/dist/domains/test-generation/factories/test-generator-factory.js +33 -13
- package/dist/domains/test-generation/factories/test-generator-factory.js.map +1 -1
- package/dist/domains/test-generation/generators/flutter-test-generator.d.ts +107 -0
- package/dist/domains/test-generation/generators/flutter-test-generator.d.ts.map +1 -0
- package/dist/domains/test-generation/generators/flutter-test-generator.js +590 -0
- package/dist/domains/test-generation/generators/flutter-test-generator.js.map +1 -0
- package/dist/domains/test-generation/generators/go-test-generator.d.ts +139 -0
- package/dist/domains/test-generation/generators/go-test-generator.d.ts.map +1 -0
- package/dist/domains/test-generation/generators/go-test-generator.js +654 -0
- package/dist/domains/test-generation/generators/go-test-generator.js.map +1 -0
- package/dist/domains/test-generation/generators/index.d.ts +8 -0
- package/dist/domains/test-generation/generators/index.d.ts.map +1 -1
- package/dist/domains/test-generation/generators/index.js +8 -0
- package/dist/domains/test-generation/generators/index.js.map +1 -1
- package/dist/domains/test-generation/generators/jest-rn-generator.d.ts +95 -0
- package/dist/domains/test-generation/generators/jest-rn-generator.d.ts.map +1 -0
- package/dist/domains/test-generation/generators/jest-rn-generator.js +591 -0
- package/dist/domains/test-generation/generators/jest-rn-generator.js.map +1 -0
- package/dist/domains/test-generation/generators/junit5-generator.d.ts +107 -0
- package/dist/domains/test-generation/generators/junit5-generator.d.ts.map +1 -0
- package/dist/domains/test-generation/generators/junit5-generator.js +588 -0
- package/dist/domains/test-generation/generators/junit5-generator.js.map +1 -0
- package/dist/domains/test-generation/generators/kotlin-junit-generator.d.ts +109 -0
- package/dist/domains/test-generation/generators/kotlin-junit-generator.d.ts.map +1 -0
- package/dist/domains/test-generation/generators/kotlin-junit-generator.js +588 -0
- package/dist/domains/test-generation/generators/kotlin-junit-generator.js.map +1 -0
- package/dist/domains/test-generation/generators/pytest-generator.d.ts +8 -1
- package/dist/domains/test-generation/generators/pytest-generator.d.ts.map +1 -1
- package/dist/domains/test-generation/generators/pytest-generator.js +57 -0
- package/dist/domains/test-generation/generators/pytest-generator.js.map +1 -1
- package/dist/domains/test-generation/generators/rust-test-generator.d.ts +80 -0
- package/dist/domains/test-generation/generators/rust-test-generator.d.ts.map +1 -0
- package/dist/domains/test-generation/generators/rust-test-generator.js +442 -0
- package/dist/domains/test-generation/generators/rust-test-generator.js.map +1 -0
- package/dist/domains/test-generation/generators/swift-testing-generator.d.ts +97 -0
- package/dist/domains/test-generation/generators/swift-testing-generator.d.ts.map +1 -0
- package/dist/domains/test-generation/generators/swift-testing-generator.js +482 -0
- package/dist/domains/test-generation/generators/swift-testing-generator.js.map +1 -0
- package/dist/domains/test-generation/generators/xunit-generator.d.ts +110 -0
- package/dist/domains/test-generation/generators/xunit-generator.d.ts.map +1 -0
- package/dist/domains/test-generation/generators/xunit-generator.js +611 -0
- package/dist/domains/test-generation/generators/xunit-generator.js.map +1 -0
- package/dist/domains/test-generation/interfaces.d.ts +11 -2
- package/dist/domains/test-generation/interfaces.d.ts.map +1 -1
- package/dist/domains/test-generation/prompts/language-prompts.d.ts +29 -0
- package/dist/domains/test-generation/prompts/language-prompts.d.ts.map +1 -0
- package/dist/domains/test-generation/prompts/language-prompts.js +135 -0
- package/dist/domains/test-generation/prompts/language-prompts.js.map +1 -0
- package/dist/domains/test-generation/services/compilation-validator.d.ts +43 -0
- package/dist/domains/test-generation/services/compilation-validator.d.ts.map +1 -0
- package/dist/domains/test-generation/services/compilation-validator.js +134 -0
- package/dist/domains/test-generation/services/compilation-validator.js.map +1 -0
- package/dist/domains/test-generation/services/index.d.ts +2 -1
- package/dist/domains/test-generation/services/index.d.ts.map +1 -1
- package/dist/domains/test-generation/services/index.js +3 -1
- package/dist/domains/test-generation/services/index.js.map +1 -1
- package/dist/domains/test-generation/services/test-file-resolver.d.ts +32 -0
- package/dist/domains/test-generation/services/test-file-resolver.d.ts.map +1 -0
- package/dist/domains/test-generation/services/test-file-resolver.js +159 -0
- package/dist/domains/test-generation/services/test-file-resolver.js.map +1 -0
- package/dist/domains/test-generation/services/test-generator.d.ts +10 -0
- package/dist/domains/test-generation/services/test-generator.d.ts.map +1 -1
- package/dist/domains/test-generation/services/test-generator.js +87 -10
- package/dist/domains/test-generation/services/test-generator.js.map +1 -1
- package/dist/governance/feature-flags.js +2 -2
- package/dist/governance/feature-flags.js.map +1 -1
- package/dist/governance/shard-embeddings.js +1 -1
- package/dist/init/init-wizard-hooks.d.ts.map +1 -1
- package/dist/init/init-wizard-hooks.js +0 -1
- package/dist/init/init-wizard-hooks.js.map +1 -1
- package/dist/init/phases/07-hooks.d.ts.map +1 -1
- package/dist/init/phases/07-hooks.js +0 -2
- package/dist/init/phases/07-hooks.js.map +1 -1
- package/dist/init/phases/08-mcp.d.ts +8 -4
- package/dist/init/phases/08-mcp.d.ts.map +1 -1
- package/dist/init/phases/08-mcp.js +13 -31
- package/dist/init/phases/08-mcp.js.map +1 -1
- package/dist/init/phases/10-workers.js +4 -4
- package/dist/init/phases/10-workers.js.map +1 -1
- package/dist/init/settings-merge.d.ts.map +1 -1
- package/dist/init/settings-merge.js +0 -2
- package/dist/init/settings-merge.js.map +1 -1
- package/dist/init/token-bootstrap.js +1 -1
- package/dist/init/token-bootstrap.js.map +1 -1
- package/dist/integrations/rl-suite/algorithms/decision-transformer.js +1 -1
- package/dist/kernel/constants.d.ts +2 -2
- package/dist/kernel/constants.js +2 -2
- package/dist/kernel/hnsw-adapter.js +1 -1
- package/dist/kernel/progressive-hnsw-backend.d.ts +2 -2
- package/dist/kernel/progressive-hnsw-backend.js +2 -2
- package/dist/learning/dream/concept-graph.d.ts +1 -1
- package/dist/learning/dream/concept-graph.js +1 -1
- package/dist/learning/dream/dream-engine.d.ts +1 -1
- package/dist/learning/dream/dream-engine.js +1 -1
- package/dist/learning/dream/index.d.ts +1 -1
- package/dist/learning/dream/index.js +1 -1
- package/dist/learning/dream/types.d.ts +1 -1
- package/dist/learning/dream/types.d.ts.map +1 -1
- package/dist/learning/dream/types.js +1 -1
- package/dist/learning/dream/types.js.map +1 -1
- package/dist/learning/token-tracker.js +1 -1
- package/dist/learning/token-tracker.js.map +1 -1
- package/dist/mcp/bundle.js +7538 -893
- package/dist/routing/qe-agent-registry.js +4 -4
- package/dist/routing/qe-agent-registry.js.map +1 -1
- package/dist/routing/types.d.ts +5 -8
- package/dist/routing/types.d.ts.map +1 -1
- package/dist/routing/types.js.map +1 -1
- package/dist/shared/embeddings/embedding-cache.js +2 -2
- package/dist/shared/embeddings/index.d.ts +2 -2
- package/dist/shared/embeddings/index.js +2 -2
- package/dist/shared/embeddings/nomic-embedder.d.ts +4 -4
- package/dist/shared/embeddings/nomic-embedder.js +2 -2
- package/dist/shared/embeddings/ollama-client.d.ts +1 -1
- package/dist/shared/embeddings/ollama-client.js +2 -2
- package/dist/shared/embeddings/ollama-client.js.map +1 -1
- package/dist/shared/embeddings/types.d.ts +2 -2
- package/dist/shared/embeddings/types.js +2 -2
- package/dist/shared/language-detector.d.ts +46 -0
- package/dist/shared/language-detector.d.ts.map +1 -0
- package/dist/shared/language-detector.js +183 -0
- package/dist/shared/language-detector.js.map +1 -0
- package/dist/shared/llm/providers/ollama.js +1 -1
- package/dist/shared/metrics/code-metrics.d.ts.map +1 -1
- package/dist/shared/metrics/code-metrics.js +24 -1
- package/dist/shared/metrics/code-metrics.js.map +1 -1
- package/dist/shared/parsers/index.d.ts +2 -0
- package/dist/shared/parsers/index.d.ts.map +1 -1
- package/dist/shared/parsers/index.js +2 -0
- package/dist/shared/parsers/index.js.map +1 -1
- package/dist/shared/parsers/interfaces.d.ts +81 -0
- package/dist/shared/parsers/interfaces.d.ts.map +1 -0
- package/dist/shared/parsers/interfaces.js +6 -0
- package/dist/shared/parsers/interfaces.js.map +1 -0
- package/dist/shared/parsers/multi-language-parser.d.ts +144 -0
- package/dist/shared/parsers/multi-language-parser.d.ts.map +1 -0
- package/dist/shared/parsers/multi-language-parser.js +1271 -0
- package/dist/shared/parsers/multi-language-parser.js.map +1 -0
- package/dist/shared/parsers/rust-ownership-analyzer.d.ts +45 -0
- package/dist/shared/parsers/rust-ownership-analyzer.d.ts.map +1 -0
- package/dist/shared/parsers/rust-ownership-analyzer.js +52 -0
- package/dist/shared/parsers/rust-ownership-analyzer.js.map +1 -0
- package/dist/shared/parsers/typescript-parser.d.ts +16 -0
- package/dist/shared/parsers/typescript-parser.d.ts.map +1 -1
- package/dist/shared/parsers/typescript-parser.js +85 -0
- package/dist/shared/parsers/typescript-parser.js.map +1 -1
- package/dist/shared/types/test-frameworks.d.ts +25 -0
- package/dist/shared/types/test-frameworks.d.ts.map +1 -0
- package/dist/shared/types/test-frameworks.js +111 -0
- package/dist/shared/types/test-frameworks.js.map +1 -0
- package/package.json +1 -1
- package/scripts/prepare-assets.sh +16 -2
|
@@ -0,0 +1,1271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Language Parser Registry (ADR-076)
|
|
3
|
+
* Regex-based parsers for non-TypeScript languages.
|
|
4
|
+
* Extracts function/class/import declarations for test generation.
|
|
5
|
+
*
|
|
6
|
+
* Uses two key utilities to handle complex syntax that naive line-by-line regex misses:
|
|
7
|
+
* 1. joinMultiLineSignatures — collapses multi-line function/class declarations into single logical lines
|
|
8
|
+
* 2. matchBalancedBrackets — handles nested generics like Map<String, List<Foo>> correctly
|
|
9
|
+
*/
|
|
10
|
+
// ============================================================================
|
|
11
|
+
// Shared Parsing Utilities
|
|
12
|
+
// ============================================================================
|
|
13
|
+
// Maximum line length for regex matching. Joined multi-line signatures can be long;
|
|
14
|
+
// lines beyond this limit are skipped to prevent polynomial-time regex backtracking (CWE-1333).
|
|
15
|
+
const MAX_REGEX_LINE_LEN = 1000;
|
|
16
|
+
/**
|
|
17
|
+
* Join multi-line signatures into single logical lines.
|
|
18
|
+
* Handles: function params spanning lines, class declarations with long implements lists,
|
|
19
|
+
* multi-line annotations/attributes, and continuation lines.
|
|
20
|
+
*
|
|
21
|
+
* Returns { logicalLines, lineMap } where lineMap[logicalIndex] = originalStartLine (1-based).
|
|
22
|
+
*/
|
|
23
|
+
export function joinMultiLineSignatures(content) {
|
|
24
|
+
const rawLines = content.split('\n');
|
|
25
|
+
const logicalLines = [];
|
|
26
|
+
const lineMap = [];
|
|
27
|
+
let buffer = '';
|
|
28
|
+
let bufferStartLine = 0;
|
|
29
|
+
let openParens = 0;
|
|
30
|
+
let openAngles = 0;
|
|
31
|
+
let openSquare = 0;
|
|
32
|
+
for (let i = 0; i < rawLines.length; i++) {
|
|
33
|
+
const line = rawLines[i];
|
|
34
|
+
const trimmed = line.trim();
|
|
35
|
+
// Skip pure comment/blank lines — emit them as-is
|
|
36
|
+
if (trimmed === '' || trimmed.startsWith('//') || trimmed.startsWith('#') || trimmed.startsWith('*')) {
|
|
37
|
+
if (buffer) {
|
|
38
|
+
// Inside a continuation — keep accumulating
|
|
39
|
+
buffer += ' ' + trimmed;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
logicalLines.push(line);
|
|
43
|
+
lineMap.push(i + 1);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (!buffer) {
|
|
47
|
+
bufferStartLine = i + 1;
|
|
48
|
+
}
|
|
49
|
+
buffer = buffer ? buffer + ' ' + trimmed : line;
|
|
50
|
+
// Count bracket balance (ignoring strings/comments for simplicity — good enough for declarations)
|
|
51
|
+
for (const ch of trimmed) {
|
|
52
|
+
if (ch === '(')
|
|
53
|
+
openParens++;
|
|
54
|
+
else if (ch === ')')
|
|
55
|
+
openParens = Math.max(0, openParens - 1);
|
|
56
|
+
else if (ch === '<')
|
|
57
|
+
openAngles++;
|
|
58
|
+
else if (ch === '>')
|
|
59
|
+
openAngles = Math.max(0, openAngles - 1);
|
|
60
|
+
else if (ch === '[')
|
|
61
|
+
openSquare++;
|
|
62
|
+
else if (ch === ']')
|
|
63
|
+
openSquare = Math.max(0, openSquare - 1);
|
|
64
|
+
}
|
|
65
|
+
// Line is complete when all brackets are balanced
|
|
66
|
+
if (openParens === 0 && openAngles === 0 && openSquare === 0) {
|
|
67
|
+
logicalLines.push(buffer);
|
|
68
|
+
lineMap.push(bufferStartLine);
|
|
69
|
+
buffer = '';
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Flush remaining buffer
|
|
73
|
+
if (buffer) {
|
|
74
|
+
logicalLines.push(buffer);
|
|
75
|
+
lineMap.push(bufferStartLine);
|
|
76
|
+
}
|
|
77
|
+
return { logicalLines, lineMap };
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Extract balanced bracket content starting at a given position.
|
|
81
|
+
* Handles nested brackets: Map<String, List<Foo>> returns "String, List<Foo>"
|
|
82
|
+
*
|
|
83
|
+
* @param str - The string to scan
|
|
84
|
+
* @param startIdx - Index of the opening bracket character
|
|
85
|
+
* @param open - Opening bracket char (default '<')
|
|
86
|
+
* @param close - Closing bracket char (default '>')
|
|
87
|
+
* @returns The content between brackets (excluding the brackets), or undefined if unbalanced
|
|
88
|
+
*/
|
|
89
|
+
export function matchBalancedBrackets(str, startIdx, open = '<', close = '>') {
|
|
90
|
+
if (str[startIdx] !== open)
|
|
91
|
+
return undefined;
|
|
92
|
+
let depth = 1;
|
|
93
|
+
let i = startIdx + 1;
|
|
94
|
+
while (i < str.length && depth > 0) {
|
|
95
|
+
if (str[i] === open)
|
|
96
|
+
depth++;
|
|
97
|
+
else if (str[i] === close)
|
|
98
|
+
depth--;
|
|
99
|
+
i++;
|
|
100
|
+
}
|
|
101
|
+
if (depth !== 0)
|
|
102
|
+
return undefined;
|
|
103
|
+
return str.substring(startIdx + 1, i - 1);
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Extract the full type expression starting at an index, handling nested generics.
|
|
107
|
+
* E.g., from "Map<String, List<Foo>> remaining" extracts "Map<String, List<Foo>>"
|
|
108
|
+
*/
|
|
109
|
+
export function extractFullType(str, startIdx = 0) {
|
|
110
|
+
let i = startIdx;
|
|
111
|
+
// Skip whitespace
|
|
112
|
+
while (i < str.length && str[i] === ' ')
|
|
113
|
+
i++;
|
|
114
|
+
const typeStart = i;
|
|
115
|
+
// Walk through identifier chars
|
|
116
|
+
while (i < str.length && /[\w.]/.test(str[i]))
|
|
117
|
+
i++;
|
|
118
|
+
// If next char is '<', consume balanced generics
|
|
119
|
+
if (i < str.length && str[i] === '<') {
|
|
120
|
+
const inner = matchBalancedBrackets(str, i);
|
|
121
|
+
if (inner !== undefined) {
|
|
122
|
+
i += inner.length + 2; // +2 for < and >
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// Handle array suffixes [], ?, !, etc.
|
|
126
|
+
while (i < str.length && /[[\]?!*&]/.test(str[i]))
|
|
127
|
+
i++;
|
|
128
|
+
return str.substring(typeStart, i).trim();
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Collect decorators/attributes by scanning backwards from a line index.
|
|
132
|
+
* Handles multi-line attribute chains like:
|
|
133
|
+
* #[derive(Debug)]
|
|
134
|
+
* #[serde(rename_all = "camelCase")]
|
|
135
|
+
* pub struct Foo { ... }
|
|
136
|
+
*
|
|
137
|
+
* @param lines - Array of source lines
|
|
138
|
+
* @param lineIdx - Index of the declaration line (0-based)
|
|
139
|
+
* @param prefix - Decorator prefix to look for ('@', '#[', '[')
|
|
140
|
+
*/
|
|
141
|
+
export function collectDecorators(lines, lineIdx, prefix) {
|
|
142
|
+
const decorators = [];
|
|
143
|
+
for (let j = lineIdx - 1; j >= 0; j--) {
|
|
144
|
+
const trimmed = lines[j].trim();
|
|
145
|
+
if (trimmed.startsWith(prefix)) {
|
|
146
|
+
decorators.unshift(trimmed);
|
|
147
|
+
}
|
|
148
|
+
else if (trimmed === '' || trimmed.startsWith('//') || trimmed.startsWith('*') || trimmed.startsWith('#')) {
|
|
149
|
+
// Allow blank lines and comments between decorators
|
|
150
|
+
continue;
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
return decorators;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Parse a balanced parenthesized parameter string.
|
|
160
|
+
* Unlike regex [^)]*, this handles nested parens/generics inside parameter types.
|
|
161
|
+
* Input: content after opening '(' — e.g. "id: Long, filter: Map<String, List<Int>>"
|
|
162
|
+
*/
|
|
163
|
+
export function extractParenContent(line, openIdx) {
|
|
164
|
+
return matchBalancedBrackets(line, openIdx, '(', ')');
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Split a parameter string by commas, respecting nested generics depth.
|
|
168
|
+
* "String id, Map<String, List<Foo>> map" -> ["String id", "Map<String, List<Foo>> map"]
|
|
169
|
+
*/
|
|
170
|
+
function splitParamsGenericAware(paramsStr) {
|
|
171
|
+
const params = [];
|
|
172
|
+
let depth = 0;
|
|
173
|
+
let current = '';
|
|
174
|
+
for (const ch of paramsStr) {
|
|
175
|
+
if (ch === '<' || ch === '(')
|
|
176
|
+
depth++;
|
|
177
|
+
else if (ch === '>' || ch === ')')
|
|
178
|
+
depth--;
|
|
179
|
+
if (ch === ',' && depth === 0) {
|
|
180
|
+
params.push(current.trim());
|
|
181
|
+
current = '';
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
current += ch;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
if (current.trim())
|
|
188
|
+
params.push(current.trim());
|
|
189
|
+
return params;
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Count braces in a line to track nesting depth.
|
|
193
|
+
* Returns the delta (opens - closes).
|
|
194
|
+
*/
|
|
195
|
+
function countBraceDelta(line) {
|
|
196
|
+
let delta = 0;
|
|
197
|
+
let inString = false;
|
|
198
|
+
let stringChar = '';
|
|
199
|
+
for (let i = 0; i < line.length; i++) {
|
|
200
|
+
const ch = line[i];
|
|
201
|
+
if (inString) {
|
|
202
|
+
if (ch === stringChar && line[i - 1] !== '\\')
|
|
203
|
+
inString = false;
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
if (ch === '"' || ch === '\'' || ch === '`') {
|
|
207
|
+
inString = true;
|
|
208
|
+
stringChar = ch;
|
|
209
|
+
}
|
|
210
|
+
else if (ch === '{') {
|
|
211
|
+
delta++;
|
|
212
|
+
}
|
|
213
|
+
else if (ch === '}') {
|
|
214
|
+
delta--;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
return delta;
|
|
218
|
+
}
|
|
219
|
+
// --- Python Parser ---
|
|
220
|
+
class PythonParser {
|
|
221
|
+
language = 'python';
|
|
222
|
+
supportedExtensions = ['.py'];
|
|
223
|
+
async parseFile(content, filePath) {
|
|
224
|
+
return {
|
|
225
|
+
functions: this.extractFunctions(content),
|
|
226
|
+
classes: this.extractClasses(content),
|
|
227
|
+
imports: this.extractImports(content),
|
|
228
|
+
language: 'python',
|
|
229
|
+
filePath,
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
extractFunctions(content) {
|
|
233
|
+
const functions = [];
|
|
234
|
+
const rawLines = content.split('\n');
|
|
235
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
236
|
+
// Match: def function_name(params) -> return_type:
|
|
237
|
+
// or: async def function_name(params) -> return_type:
|
|
238
|
+
const funcRegex = /^(\s*)(async\s+)?def\s+(\w+)\s*\(([^)]*)\)(?:\s*->\s*([^:]*\S))?\s*:/;
|
|
239
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
240
|
+
if (logicalLines[i].length > MAX_REGEX_LINE_LEN)
|
|
241
|
+
continue;
|
|
242
|
+
const match = logicalLines[i].match(funcRegex);
|
|
243
|
+
if (match) {
|
|
244
|
+
const indent = match[1].length;
|
|
245
|
+
const isAsync = !!match[2];
|
|
246
|
+
const name = match[3];
|
|
247
|
+
const paramsStr = match[4];
|
|
248
|
+
const returnType = match[5]?.trim();
|
|
249
|
+
const origLine = lineMap[i] - 1; // 0-based index into rawLines
|
|
250
|
+
// Find end of function (next line at same or lower indent, or end of file)
|
|
251
|
+
let endLine = origLine + 1;
|
|
252
|
+
for (let j = origLine + 1; j < rawLines.length; j++) {
|
|
253
|
+
const line = rawLines[j];
|
|
254
|
+
if (line.trim() === '' || line.trim().startsWith('#'))
|
|
255
|
+
continue;
|
|
256
|
+
const lineIndent = line.match(/^(\s*)/)?.[1].length ?? 0;
|
|
257
|
+
if (lineIndent <= indent && line.trim() !== '') {
|
|
258
|
+
endLine = j;
|
|
259
|
+
break;
|
|
260
|
+
}
|
|
261
|
+
endLine = j + 1;
|
|
262
|
+
}
|
|
263
|
+
const decorators = collectDecorators(rawLines, origLine, '@');
|
|
264
|
+
functions.push({
|
|
265
|
+
name,
|
|
266
|
+
parameters: this.parseParams(paramsStr),
|
|
267
|
+
returnType,
|
|
268
|
+
isAsync,
|
|
269
|
+
isPublic: !name.startsWith('_'),
|
|
270
|
+
complexity: 1,
|
|
271
|
+
decorators,
|
|
272
|
+
genericParams: [],
|
|
273
|
+
startLine: lineMap[i],
|
|
274
|
+
endLine,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return functions;
|
|
279
|
+
}
|
|
280
|
+
extractClasses(content) {
|
|
281
|
+
const classes = [];
|
|
282
|
+
const rawLines = content.split('\n');
|
|
283
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
284
|
+
const classRegex = /^(\s*)class\s+(\w+)(?:\(([^)]*)\))?\s*:/;
|
|
285
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
286
|
+
const match = logicalLines[i].match(classRegex);
|
|
287
|
+
if (match) {
|
|
288
|
+
const indent = match[1].length;
|
|
289
|
+
const name = match[2];
|
|
290
|
+
const bases = match[3]
|
|
291
|
+
? match[3].split(',').map((b) => b.trim())
|
|
292
|
+
: [];
|
|
293
|
+
const origLine = lineMap[i] - 1;
|
|
294
|
+
// Find end of class
|
|
295
|
+
let endLine = origLine + 1;
|
|
296
|
+
for (let j = origLine + 1; j < rawLines.length; j++) {
|
|
297
|
+
const line = rawLines[j];
|
|
298
|
+
if (line.trim() === '' || line.trim().startsWith('#'))
|
|
299
|
+
continue;
|
|
300
|
+
const lineIndent = line.match(/^(\s*)/)?.[1].length ?? 0;
|
|
301
|
+
if (lineIndent <= indent && line.trim() !== '') {
|
|
302
|
+
endLine = j;
|
|
303
|
+
break;
|
|
304
|
+
}
|
|
305
|
+
endLine = j + 1;
|
|
306
|
+
}
|
|
307
|
+
// Extract methods within class
|
|
308
|
+
const classContent = rawLines.slice(origLine + 1, endLine).join('\n');
|
|
309
|
+
const methods = this.extractFunctions(classContent).map((f) => ({
|
|
310
|
+
...f,
|
|
311
|
+
startLine: f.startLine + origLine,
|
|
312
|
+
endLine: f.endLine + origLine,
|
|
313
|
+
}));
|
|
314
|
+
const decorators = collectDecorators(rawLines, origLine, '@');
|
|
315
|
+
classes.push({
|
|
316
|
+
name,
|
|
317
|
+
methods,
|
|
318
|
+
properties: [],
|
|
319
|
+
isPublic: !name.startsWith('_'),
|
|
320
|
+
implements: [],
|
|
321
|
+
extends: bases[0] || undefined,
|
|
322
|
+
decorators,
|
|
323
|
+
startLine: lineMap[i],
|
|
324
|
+
endLine,
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
return classes;
|
|
329
|
+
}
|
|
330
|
+
extractImports(content) {
|
|
331
|
+
const imports = [];
|
|
332
|
+
const lines = content.split('\n');
|
|
333
|
+
for (const line of lines) {
|
|
334
|
+
if (line.length > MAX_REGEX_LINE_LEN)
|
|
335
|
+
continue;
|
|
336
|
+
// from module import name1, name2
|
|
337
|
+
const fromMatch = line.match(/^\s*from\s+(\S+)\s+import\s+(.+)/);
|
|
338
|
+
if (fromMatch) {
|
|
339
|
+
const names = fromMatch[2]
|
|
340
|
+
.split(',')
|
|
341
|
+
.map((n) => n.trim().split(' as ')[0]);
|
|
342
|
+
imports.push({
|
|
343
|
+
module: fromMatch[1],
|
|
344
|
+
namedImports: names,
|
|
345
|
+
isTypeOnly: false,
|
|
346
|
+
});
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
// import module
|
|
350
|
+
const importMatch = line.match(/^\s*import\s+(\S+)/);
|
|
351
|
+
if (importMatch) {
|
|
352
|
+
imports.push({
|
|
353
|
+
module: importMatch[1],
|
|
354
|
+
namedImports: [],
|
|
355
|
+
isTypeOnly: false,
|
|
356
|
+
});
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return imports;
|
|
360
|
+
}
|
|
361
|
+
parseParams(paramsStr) {
|
|
362
|
+
if (!paramsStr.trim())
|
|
363
|
+
return [];
|
|
364
|
+
return splitParamsGenericAware(paramsStr)
|
|
365
|
+
.map((p) => p.trim())
|
|
366
|
+
.filter((p) => p && p !== 'self' && p !== 'cls')
|
|
367
|
+
.map((p) => {
|
|
368
|
+
const [nameDefault, type] = p.split(':').map((s) => s.trim());
|
|
369
|
+
const [name, defaultValue] = nameDefault
|
|
370
|
+
.split('=')
|
|
371
|
+
.map((s) => s.trim());
|
|
372
|
+
return {
|
|
373
|
+
name,
|
|
374
|
+
type: type?.split('=')[0].trim() || undefined,
|
|
375
|
+
isOptional: !!defaultValue || name.startsWith('*'),
|
|
376
|
+
defaultValue: defaultValue || undefined,
|
|
377
|
+
};
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
// --- Java Parser ---
|
|
382
|
+
class JavaParser {
|
|
383
|
+
language = 'java';
|
|
384
|
+
supportedExtensions = ['.java'];
|
|
385
|
+
async parseFile(content, filePath) {
|
|
386
|
+
return {
|
|
387
|
+
functions: this.extractFunctions(content),
|
|
388
|
+
classes: this.extractClasses(content),
|
|
389
|
+
imports: this.extractImports(content),
|
|
390
|
+
language: 'java',
|
|
391
|
+
filePath,
|
|
392
|
+
};
|
|
393
|
+
}
|
|
394
|
+
extractFunctions(content) {
|
|
395
|
+
const functions = [];
|
|
396
|
+
const rawLines = content.split('\n');
|
|
397
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
398
|
+
// Match method declarations — use a simpler regex without <[^>]+> so generics don't break
|
|
399
|
+
const methodRegex = /^\s*(public|private|protected)?\s*(static)?\s*(async)?\s*(?:<\S+>\s+)?([\w<>,.[\]?]+(?:\s+[\w<>,.[\]?]+)*)\s+(\w+)\s*\(([^)]*)\)/;
|
|
400
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
401
|
+
const line = logicalLines[i];
|
|
402
|
+
if (line.includes(' class ') || line.includes(' interface '))
|
|
403
|
+
continue;
|
|
404
|
+
if (line.length > MAX_REGEX_LINE_LEN)
|
|
405
|
+
continue;
|
|
406
|
+
const match = line.match(methodRegex);
|
|
407
|
+
if (match) {
|
|
408
|
+
const visibility = match[1] || 'default';
|
|
409
|
+
const name = match[5];
|
|
410
|
+
const paramsStr = match[6];
|
|
411
|
+
// Extract the full return type with balanced generics
|
|
412
|
+
const returnTypeRaw = match[4]?.trim();
|
|
413
|
+
let returnType = returnTypeRaw;
|
|
414
|
+
// If the raw return type was truncated by the regex, try to extract full type
|
|
415
|
+
if (returnTypeRaw && returnTypeRaw.includes('<')) {
|
|
416
|
+
const angleIdx = returnTypeRaw.indexOf('<');
|
|
417
|
+
const inner = matchBalancedBrackets(returnTypeRaw, angleIdx);
|
|
418
|
+
if (inner !== undefined) {
|
|
419
|
+
returnType = returnTypeRaw.substring(0, angleIdx) + '<' + inner + '>';
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
const origLine = lineMap[i] - 1;
|
|
423
|
+
const decorators = collectDecorators(rawLines, origLine, '@');
|
|
424
|
+
functions.push({
|
|
425
|
+
name,
|
|
426
|
+
parameters: this.parseParams(paramsStr),
|
|
427
|
+
returnType: returnType === 'void' ? undefined : returnType,
|
|
428
|
+
isAsync: returnType?.includes('CompletableFuture') || false,
|
|
429
|
+
isPublic: visibility === 'public',
|
|
430
|
+
complexity: 1,
|
|
431
|
+
decorators,
|
|
432
|
+
genericParams: [],
|
|
433
|
+
startLine: lineMap[i],
|
|
434
|
+
endLine: lineMap[i],
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
return functions;
|
|
439
|
+
}
|
|
440
|
+
extractClasses(content) {
|
|
441
|
+
const classes = [];
|
|
442
|
+
const rawLines = content.split('\n');
|
|
443
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
444
|
+
const classRegex = /^\s*(public|private|protected)?\s*(abstract)?\s*class\s+(\w+)(?:<[^{]*>)?(?:\s+extends\s+(\w+))?(?:\s+implements\s+([^{\s]+(?:\s+[^{\s]+)*))?\s*\{?/;
|
|
445
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
446
|
+
if (logicalLines[i].length > MAX_REGEX_LINE_LEN)
|
|
447
|
+
continue;
|
|
448
|
+
const match = logicalLines[i].match(classRegex);
|
|
449
|
+
if (match) {
|
|
450
|
+
const name = match[3];
|
|
451
|
+
const extendsName = match[4];
|
|
452
|
+
const implementsList = match[5]
|
|
453
|
+
? match[5].split(',').map((s) => s.trim())
|
|
454
|
+
: [];
|
|
455
|
+
const origLine = lineMap[i] - 1;
|
|
456
|
+
const decorators = collectDecorators(rawLines, origLine, '@');
|
|
457
|
+
classes.push({
|
|
458
|
+
name,
|
|
459
|
+
methods: [],
|
|
460
|
+
properties: [],
|
|
461
|
+
isPublic: (match[1] || 'default') === 'public',
|
|
462
|
+
implements: implementsList,
|
|
463
|
+
extends: extendsName,
|
|
464
|
+
decorators,
|
|
465
|
+
startLine: lineMap[i],
|
|
466
|
+
endLine: lineMap[i],
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
return classes;
|
|
471
|
+
}
|
|
472
|
+
extractImports(content) {
|
|
473
|
+
const imports = [];
|
|
474
|
+
const lines = content.split('\n');
|
|
475
|
+
for (const line of lines) {
|
|
476
|
+
if (line.length > MAX_REGEX_LINE_LEN)
|
|
477
|
+
continue;
|
|
478
|
+
const match = line.match(/^\s*import +(static +)?(\S[^;]*);/);
|
|
479
|
+
if (match) {
|
|
480
|
+
const module = match[2].trim();
|
|
481
|
+
const parts = module.split('.');
|
|
482
|
+
const name = parts[parts.length - 1];
|
|
483
|
+
imports.push({
|
|
484
|
+
module,
|
|
485
|
+
namedImports: name === '*' ? [] : [name],
|
|
486
|
+
isTypeOnly: false,
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
return imports;
|
|
491
|
+
}
|
|
492
|
+
parseParams(paramsStr) {
|
|
493
|
+
if (!paramsStr.trim())
|
|
494
|
+
return [];
|
|
495
|
+
return splitParamsGenericAware(paramsStr).map((p) => {
|
|
496
|
+
const parts = p.trim().split(/\s+/);
|
|
497
|
+
// Handle annotations: @NotNull String name
|
|
498
|
+
const filtered = parts.filter((part) => !part.startsWith('@'));
|
|
499
|
+
const name = filtered[filtered.length - 1] || '';
|
|
500
|
+
const type = filtered.slice(0, -1).join(' ') || undefined;
|
|
501
|
+
return { name, type, isOptional: false, defaultValue: undefined };
|
|
502
|
+
});
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
// --- C# Parser ---
|
|
506
|
+
class CSharpParser {
|
|
507
|
+
language = 'csharp';
|
|
508
|
+
supportedExtensions = ['.cs'];
|
|
509
|
+
async parseFile(content, filePath) {
|
|
510
|
+
return {
|
|
511
|
+
functions: this.extractMethods(content),
|
|
512
|
+
classes: this.extractClasses(content),
|
|
513
|
+
imports: this.extractImports(content),
|
|
514
|
+
language: 'csharp',
|
|
515
|
+
filePath,
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
extractMethods(content) {
|
|
519
|
+
const functions = [];
|
|
520
|
+
const rawLines = content.split('\n');
|
|
521
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
522
|
+
const methodRegex = /^\s*(public|private|protected|internal)?\s*(static)?\s*(async)?\s*([\w<>,.[\]?]+(?:\s+[\w<>,.[\]?]+)*)\s+(\w+)\s*\(([^)]*)\)/;
|
|
523
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
524
|
+
const line = logicalLines[i];
|
|
525
|
+
if (line.includes(' class ') || line.includes(' interface ') || line.includes(' namespace '))
|
|
526
|
+
continue;
|
|
527
|
+
if (line.length > MAX_REGEX_LINE_LEN)
|
|
528
|
+
continue;
|
|
529
|
+
const match = line.match(methodRegex);
|
|
530
|
+
if (match) {
|
|
531
|
+
const visibility = match[1] || 'private';
|
|
532
|
+
const isAsync = !!match[3] || match[4]?.includes('Task') || false;
|
|
533
|
+
const returnTypeRaw = match[4]?.trim();
|
|
534
|
+
let returnType = returnTypeRaw;
|
|
535
|
+
// Extract full generic type
|
|
536
|
+
if (returnTypeRaw && returnTypeRaw.includes('<')) {
|
|
537
|
+
const angleIdx = returnTypeRaw.indexOf('<');
|
|
538
|
+
const inner = matchBalancedBrackets(returnTypeRaw, angleIdx);
|
|
539
|
+
if (inner !== undefined) {
|
|
540
|
+
returnType = returnTypeRaw.substring(0, angleIdx) + '<' + inner + '>';
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
const name = match[5];
|
|
544
|
+
const paramsStr = match[6];
|
|
545
|
+
const origLine = lineMap[i] - 1;
|
|
546
|
+
const decorators = collectDecorators(rawLines, origLine, '[');
|
|
547
|
+
functions.push({
|
|
548
|
+
name,
|
|
549
|
+
parameters: this.parseParams(paramsStr),
|
|
550
|
+
returnType: returnType === 'void' ? undefined : returnType,
|
|
551
|
+
isAsync,
|
|
552
|
+
isPublic: visibility === 'public',
|
|
553
|
+
complexity: 1,
|
|
554
|
+
decorators,
|
|
555
|
+
genericParams: [],
|
|
556
|
+
startLine: lineMap[i],
|
|
557
|
+
endLine: lineMap[i],
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return functions;
|
|
562
|
+
}
|
|
563
|
+
extractClasses(content) {
|
|
564
|
+
const classes = [];
|
|
565
|
+
const rawLines = content.split('\n');
|
|
566
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
567
|
+
const classRegex = /^\s*(public|private|protected|internal)?\s*(abstract|sealed|static|partial)?\s*class\s+(\w+)(?:<[^{]*>)?(?:\s*:\s*([^{\s]+(?:\s+[^{\s]+)*))?\s*\{?/;
|
|
568
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
569
|
+
if (logicalLines[i].length > MAX_REGEX_LINE_LEN)
|
|
570
|
+
continue;
|
|
571
|
+
const match = logicalLines[i].match(classRegex);
|
|
572
|
+
if (match) {
|
|
573
|
+
const name = match[3];
|
|
574
|
+
const bases = match[4]
|
|
575
|
+
? match[4].split(',').map((s) => s.trim())
|
|
576
|
+
: [];
|
|
577
|
+
const origLine = lineMap[i] - 1;
|
|
578
|
+
const decorators = collectDecorators(rawLines, origLine, '[');
|
|
579
|
+
classes.push({
|
|
580
|
+
name,
|
|
581
|
+
methods: [],
|
|
582
|
+
properties: [],
|
|
583
|
+
isPublic: (match[1] || 'internal') === 'public',
|
|
584
|
+
implements: bases.slice(1),
|
|
585
|
+
extends: bases[0] || undefined,
|
|
586
|
+
decorators,
|
|
587
|
+
startLine: lineMap[i],
|
|
588
|
+
endLine: lineMap[i],
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
return classes;
|
|
593
|
+
}
|
|
594
|
+
extractImports(content) {
|
|
595
|
+
const imports = [];
|
|
596
|
+
const lines = content.split('\n');
|
|
597
|
+
for (const line of lines) {
|
|
598
|
+
if (line.length > MAX_REGEX_LINE_LEN)
|
|
599
|
+
continue;
|
|
600
|
+
const match = line.match(/^\s*using +(static +)?(\S[^;]*);/);
|
|
601
|
+
if (match) {
|
|
602
|
+
imports.push({
|
|
603
|
+
module: match[2].trim(),
|
|
604
|
+
namedImports: [],
|
|
605
|
+
isTypeOnly: false,
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
return imports;
|
|
610
|
+
}
|
|
611
|
+
parseParams(paramsStr) {
|
|
612
|
+
if (!paramsStr.trim())
|
|
613
|
+
return [];
|
|
614
|
+
return splitParamsGenericAware(paramsStr).map((p) => {
|
|
615
|
+
const parts = p.trim().split(/\s+/);
|
|
616
|
+
const name = parts[parts.length - 1] || '';
|
|
617
|
+
const type = parts.slice(0, -1).join(' ') || undefined;
|
|
618
|
+
return {
|
|
619
|
+
name,
|
|
620
|
+
type,
|
|
621
|
+
isOptional: type?.endsWith('?') || false,
|
|
622
|
+
defaultValue: undefined,
|
|
623
|
+
};
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
// --- Go Parser ---
|
|
628
|
+
class GoParser {
|
|
629
|
+
language = 'go';
|
|
630
|
+
supportedExtensions = ['.go'];
|
|
631
|
+
async parseFile(content, filePath) {
|
|
632
|
+
return {
|
|
633
|
+
functions: this.extractFunctions(content),
|
|
634
|
+
classes: this.extractStructs(content),
|
|
635
|
+
imports: this.extractImports(content),
|
|
636
|
+
language: 'go',
|
|
637
|
+
filePath,
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
extractFunctions(content) {
|
|
641
|
+
const functions = [];
|
|
642
|
+
const rawLines = content.split('\n');
|
|
643
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
644
|
+
// func Name(params) returnType {
|
|
645
|
+
// func (r *Receiver) Name(params) returnType {
|
|
646
|
+
const funcRegex = /^\s*func\s+(?:\((\w+)\s+\*?(\w+)\)\s+)?(\w+)\s*\(([^)]*)\)\s*([\w*[\](),\s]*)\s*\{?/;
|
|
647
|
+
// Track brace depth to filter nested function literals (Go closures).
|
|
648
|
+
// Go methods use receiver syntax at top level, so only depth 0 is valid.
|
|
649
|
+
let braceDepth = 0;
|
|
650
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
651
|
+
const line = logicalLines[i];
|
|
652
|
+
if (line.length > MAX_REGEX_LINE_LEN) {
|
|
653
|
+
braceDepth += (line.match(/\{/g)?.length ?? 0) - (line.match(/\}/g)?.length ?? 0);
|
|
654
|
+
continue;
|
|
655
|
+
}
|
|
656
|
+
const match = line.match(funcRegex);
|
|
657
|
+
if (match && braceDepth === 0) {
|
|
658
|
+
const name = match[3];
|
|
659
|
+
const paramsStr = match[4];
|
|
660
|
+
const returnType = match[5]?.trim() || undefined;
|
|
661
|
+
functions.push({
|
|
662
|
+
name,
|
|
663
|
+
parameters: this.parseParams(paramsStr),
|
|
664
|
+
returnType: returnType || undefined,
|
|
665
|
+
isAsync: false,
|
|
666
|
+
isPublic: name[0] === name[0].toUpperCase(),
|
|
667
|
+
complexity: 1,
|
|
668
|
+
decorators: [],
|
|
669
|
+
genericParams: [],
|
|
670
|
+
startLine: lineMap[i],
|
|
671
|
+
endLine: lineMap[i],
|
|
672
|
+
});
|
|
673
|
+
}
|
|
674
|
+
// Update brace depth after checking for function match
|
|
675
|
+
braceDepth += countBraceDelta(line);
|
|
676
|
+
if (braceDepth < 0)
|
|
677
|
+
braceDepth = 0;
|
|
678
|
+
}
|
|
679
|
+
return functions;
|
|
680
|
+
}
|
|
681
|
+
extractStructs(content) {
|
|
682
|
+
const structs = [];
|
|
683
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
684
|
+
const structRegex = /^\s*type\s+(\w+)\s+struct\s*\{/;
|
|
685
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
686
|
+
const match = logicalLines[i].match(structRegex);
|
|
687
|
+
if (match) {
|
|
688
|
+
const name = match[1];
|
|
689
|
+
structs.push({
|
|
690
|
+
name,
|
|
691
|
+
methods: [],
|
|
692
|
+
properties: [],
|
|
693
|
+
isPublic: name[0] === name[0].toUpperCase(),
|
|
694
|
+
implements: [],
|
|
695
|
+
extends: undefined,
|
|
696
|
+
decorators: [],
|
|
697
|
+
startLine: lineMap[i],
|
|
698
|
+
endLine: lineMap[i],
|
|
699
|
+
});
|
|
700
|
+
}
|
|
701
|
+
}
|
|
702
|
+
return structs;
|
|
703
|
+
}
|
|
704
|
+
extractImports(content) {
|
|
705
|
+
const imports = [];
|
|
706
|
+
const singleImport = /^\s*import\s+"([^"]+)"/;
|
|
707
|
+
const multiImportStart = /^\s*import\s*\(/;
|
|
708
|
+
const multiImportLine = /^\s*"([^"]+)"/;
|
|
709
|
+
const lines = content.split('\n');
|
|
710
|
+
let inMultiImport = false;
|
|
711
|
+
for (const line of lines) {
|
|
712
|
+
if (inMultiImport) {
|
|
713
|
+
if (line.includes(')')) {
|
|
714
|
+
inMultiImport = false;
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
const match = line.match(multiImportLine);
|
|
718
|
+
if (match)
|
|
719
|
+
imports.push({
|
|
720
|
+
module: match[1],
|
|
721
|
+
namedImports: [],
|
|
722
|
+
isTypeOnly: false,
|
|
723
|
+
});
|
|
724
|
+
}
|
|
725
|
+
else {
|
|
726
|
+
const single = line.match(singleImport);
|
|
727
|
+
if (single) {
|
|
728
|
+
imports.push({
|
|
729
|
+
module: single[1],
|
|
730
|
+
namedImports: [],
|
|
731
|
+
isTypeOnly: false,
|
|
732
|
+
});
|
|
733
|
+
}
|
|
734
|
+
else if (multiImportStart.test(line)) {
|
|
735
|
+
inMultiImport = true;
|
|
736
|
+
}
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
return imports;
|
|
740
|
+
}
|
|
741
|
+
parseParams(paramsStr) {
|
|
742
|
+
if (!paramsStr.trim())
|
|
743
|
+
return [];
|
|
744
|
+
return splitParamsGenericAware(paramsStr).map((p) => {
|
|
745
|
+
const parts = p.trim().split(/\s+/);
|
|
746
|
+
const name = parts[0] || '';
|
|
747
|
+
const type = parts.slice(1).join(' ') || undefined;
|
|
748
|
+
return { name, type, isOptional: false, defaultValue: undefined };
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
}
|
|
752
|
+
// --- Rust Parser ---
|
|
753
|
+
class RustParser {
|
|
754
|
+
language = 'rust';
|
|
755
|
+
supportedExtensions = ['.rs'];
|
|
756
|
+
async parseFile(content, filePath) {
|
|
757
|
+
return {
|
|
758
|
+
functions: this.extractFunctions(content),
|
|
759
|
+
classes: this.extractStructsAndImpls(content),
|
|
760
|
+
imports: this.extractImports(content),
|
|
761
|
+
language: 'rust',
|
|
762
|
+
filePath,
|
|
763
|
+
};
|
|
764
|
+
}
|
|
765
|
+
extractFunctions(content) {
|
|
766
|
+
const functions = [];
|
|
767
|
+
const rawLines = content.split('\n');
|
|
768
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
769
|
+
// Updated regex: use [^{]* instead of [^>]+ for generics to handle lifetimes
|
|
770
|
+
const fnRegex = /^\s*(pub(?:\(crate\))? +)?(async +)?fn\s+(\w+)(?:<[^{]*>)?\s*\(([^)]*)\)(?:\s*->\s*([^{\s]+(?:\s+[^{\s]+)*))?\s*(?:where\s+[^{\s]+(?:\s+[^{\s]+)*)?\s*\{?/;
|
|
771
|
+
// Track brace depth to filter nested closures.
|
|
772
|
+
// Rust functions at depth 0 (top-level) and depth 1 (inside impl/mod blocks) are valid.
|
|
773
|
+
let braceDepth = 0;
|
|
774
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
775
|
+
const line = logicalLines[i];
|
|
776
|
+
const match = line.match(fnRegex);
|
|
777
|
+
if (match && braceDepth <= 1) {
|
|
778
|
+
const isPub = !!match[1];
|
|
779
|
+
const isAsync = !!match[2];
|
|
780
|
+
const name = match[3];
|
|
781
|
+
const paramsStr = match[4];
|
|
782
|
+
const returnType = match[5]?.trim();
|
|
783
|
+
const origLine = lineMap[i] - 1;
|
|
784
|
+
const decorators = collectDecorators(rawLines, origLine, '#[');
|
|
785
|
+
functions.push({
|
|
786
|
+
name,
|
|
787
|
+
parameters: this.parseParams(paramsStr),
|
|
788
|
+
returnType,
|
|
789
|
+
isAsync,
|
|
790
|
+
isPublic: isPub,
|
|
791
|
+
complexity: 1,
|
|
792
|
+
decorators,
|
|
793
|
+
genericParams: [],
|
|
794
|
+
startLine: lineMap[i],
|
|
795
|
+
endLine: lineMap[i],
|
|
796
|
+
});
|
|
797
|
+
}
|
|
798
|
+
// Update brace depth after checking for function match
|
|
799
|
+
braceDepth += countBraceDelta(line);
|
|
800
|
+
if (braceDepth < 0)
|
|
801
|
+
braceDepth = 0;
|
|
802
|
+
}
|
|
803
|
+
return functions;
|
|
804
|
+
}
|
|
805
|
+
extractStructsAndImpls(content) {
|
|
806
|
+
const structs = [];
|
|
807
|
+
const rawLines = content.split('\n');
|
|
808
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
809
|
+
// Updated: use [^{]* for generics with lifetimes
|
|
810
|
+
const structRegex = /^\s*(pub(?:\(crate\))?\s+)?struct\s+(\w+)(?:<[^{]*>)?\s*/;
|
|
811
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
812
|
+
const match = logicalLines[i].match(structRegex);
|
|
813
|
+
if (match) {
|
|
814
|
+
const origLine = lineMap[i] - 1;
|
|
815
|
+
const decorators = collectDecorators(rawLines, origLine, '#[');
|
|
816
|
+
structs.push({
|
|
817
|
+
name: match[2],
|
|
818
|
+
methods: [],
|
|
819
|
+
properties: [],
|
|
820
|
+
isPublic: !!match[1],
|
|
821
|
+
implements: [],
|
|
822
|
+
extends: undefined,
|
|
823
|
+
decorators,
|
|
824
|
+
startLine: lineMap[i],
|
|
825
|
+
endLine: lineMap[i],
|
|
826
|
+
});
|
|
827
|
+
}
|
|
828
|
+
}
|
|
829
|
+
return structs;
|
|
830
|
+
}
|
|
831
|
+
extractImports(content) {
|
|
832
|
+
const imports = [];
|
|
833
|
+
const lines = content.split('\n');
|
|
834
|
+
for (const line of lines) {
|
|
835
|
+
if (line.length > MAX_REGEX_LINE_LEN)
|
|
836
|
+
continue;
|
|
837
|
+
const match = line.match(/^\s*use +(\S[^;]*);/);
|
|
838
|
+
if (match) {
|
|
839
|
+
imports.push({
|
|
840
|
+
module: match[1].trim(),
|
|
841
|
+
namedImports: [],
|
|
842
|
+
isTypeOnly: false,
|
|
843
|
+
});
|
|
844
|
+
}
|
|
845
|
+
}
|
|
846
|
+
return imports;
|
|
847
|
+
}
|
|
848
|
+
parseParams(paramsStr) {
|
|
849
|
+
if (!paramsStr.trim())
|
|
850
|
+
return [];
|
|
851
|
+
return splitParamsGenericAware(paramsStr)
|
|
852
|
+
.map((p) => p.trim())
|
|
853
|
+
.filter((p) => p && p !== '&self' && p !== '&mut self' && p !== 'self')
|
|
854
|
+
.map((p) => {
|
|
855
|
+
const colonIdx = p.indexOf(':');
|
|
856
|
+
if (colonIdx === -1)
|
|
857
|
+
return {
|
|
858
|
+
name: p,
|
|
859
|
+
type: undefined,
|
|
860
|
+
isOptional: false,
|
|
861
|
+
defaultValue: undefined,
|
|
862
|
+
};
|
|
863
|
+
const name = p.substring(0, colonIdx).trim();
|
|
864
|
+
const type = p.substring(colonIdx + 1).trim();
|
|
865
|
+
return { name, type, isOptional: false, defaultValue: undefined };
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
// --- Swift Parser ---
|
|
870
|
+
class SwiftParser {
|
|
871
|
+
language = 'swift';
|
|
872
|
+
supportedExtensions = ['.swift'];
|
|
873
|
+
async parseFile(content, filePath) {
|
|
874
|
+
return {
|
|
875
|
+
functions: this.extractFunctions(content),
|
|
876
|
+
classes: this.extractClasses(content),
|
|
877
|
+
imports: this.extractImports(content),
|
|
878
|
+
language: 'swift',
|
|
879
|
+
filePath,
|
|
880
|
+
};
|
|
881
|
+
}
|
|
882
|
+
extractFunctions(content) {
|
|
883
|
+
const functions = [];
|
|
884
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
885
|
+
const funcRegex = /^\s*(public|private|internal|open)?\s*(static)?\s*func\s+(\w+)(?:<[^{]*>)?\s*\(([^)]*)\)(?:\s*(async))?\s*(?:throws +)?(?:->\s*([^{\s]+(?:\s+[^{\s]+)*))?\s*\{?/;
|
|
886
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
887
|
+
if (logicalLines[i].length > MAX_REGEX_LINE_LEN)
|
|
888
|
+
continue;
|
|
889
|
+
const match = logicalLines[i].match(funcRegex);
|
|
890
|
+
if (match) {
|
|
891
|
+
const visibility = match[1] || 'internal';
|
|
892
|
+
const isAsync = !!match[5];
|
|
893
|
+
const name = match[3];
|
|
894
|
+
const paramsStr = match[4];
|
|
895
|
+
const returnType = match[6]?.trim();
|
|
896
|
+
functions.push({
|
|
897
|
+
name,
|
|
898
|
+
parameters: this.parseParams(paramsStr),
|
|
899
|
+
returnType,
|
|
900
|
+
isAsync,
|
|
901
|
+
isPublic: visibility === 'public' || visibility === 'open',
|
|
902
|
+
complexity: 1,
|
|
903
|
+
decorators: [],
|
|
904
|
+
genericParams: [],
|
|
905
|
+
startLine: lineMap[i],
|
|
906
|
+
endLine: lineMap[i],
|
|
907
|
+
});
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
return functions;
|
|
911
|
+
}
|
|
912
|
+
extractClasses(content) {
|
|
913
|
+
const classes = [];
|
|
914
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
915
|
+
const classRegex = /^\s*(public|private|internal|open)?\s*(class|struct|protocol)\s+(\w+)(?:<[^{]*>)?(?:\s*:\s*([^{\s]+(?:\s+[^{\s]+)*))?\s*\{?/;
|
|
916
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
917
|
+
if (logicalLines[i].length > MAX_REGEX_LINE_LEN)
|
|
918
|
+
continue;
|
|
919
|
+
const match = logicalLines[i].match(classRegex);
|
|
920
|
+
if (match) {
|
|
921
|
+
const name = match[3];
|
|
922
|
+
const conformances = match[4]
|
|
923
|
+
? match[4].split(',').map((s) => s.trim())
|
|
924
|
+
: [];
|
|
925
|
+
classes.push({
|
|
926
|
+
name,
|
|
927
|
+
methods: [],
|
|
928
|
+
properties: [],
|
|
929
|
+
isPublic: (match[1] || 'internal') === 'public' || match[1] === 'open',
|
|
930
|
+
implements: conformances.slice(1),
|
|
931
|
+
extends: conformances[0] || undefined,
|
|
932
|
+
decorators: [],
|
|
933
|
+
startLine: lineMap[i],
|
|
934
|
+
endLine: lineMap[i],
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
return classes;
|
|
939
|
+
}
|
|
940
|
+
extractImports(content) {
|
|
941
|
+
const imports = [];
|
|
942
|
+
const lines = content.split('\n');
|
|
943
|
+
for (const line of lines) {
|
|
944
|
+
const match = line.match(/^\s*import\s+(\w+)/);
|
|
945
|
+
if (match)
|
|
946
|
+
imports.push({
|
|
947
|
+
module: match[1],
|
|
948
|
+
namedImports: [],
|
|
949
|
+
isTypeOnly: false,
|
|
950
|
+
});
|
|
951
|
+
}
|
|
952
|
+
return imports;
|
|
953
|
+
}
|
|
954
|
+
parseParams(paramsStr) {
|
|
955
|
+
if (!paramsStr.trim())
|
|
956
|
+
return [];
|
|
957
|
+
return splitParamsGenericAware(paramsStr).map((p) => {
|
|
958
|
+
const parts = p.trim().split(':');
|
|
959
|
+
const labelAndName = parts[0]?.trim().split(/\s+/) || [];
|
|
960
|
+
const name = labelAndName[labelAndName.length - 1] || '';
|
|
961
|
+
const type = parts.slice(1).join(':').trim();
|
|
962
|
+
return {
|
|
963
|
+
name,
|
|
964
|
+
type: type || undefined,
|
|
965
|
+
isOptional: type?.endsWith('?') || false,
|
|
966
|
+
defaultValue: undefined,
|
|
967
|
+
};
|
|
968
|
+
});
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
// --- Kotlin Parser ---
|
|
972
|
+
class KotlinParser {
|
|
973
|
+
language = 'kotlin';
|
|
974
|
+
supportedExtensions = ['.kt', '.kts'];
|
|
975
|
+
async parseFile(content, filePath) {
|
|
976
|
+
return {
|
|
977
|
+
functions: this.extractFunctions(content),
|
|
978
|
+
classes: this.extractClasses(content),
|
|
979
|
+
imports: this.extractImports(content),
|
|
980
|
+
language: 'kotlin',
|
|
981
|
+
filePath,
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
extractFunctions(content) {
|
|
985
|
+
const functions = [];
|
|
986
|
+
const rawLines = content.split('\n');
|
|
987
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
988
|
+
const funcRegex = /^\s*(public|private|protected|internal)?\s*(suspend)?\s*fun\s+(?:<[^{]*> +)?(\w+)\s*\(([^)]*)\)(?:\s*:\s*([^{=\s]+(?:\s+[^{=\s]+)*))?\s*/;
|
|
989
|
+
// Track brace depth to filter nested lambdas that look like functions.
|
|
990
|
+
// Kotlin functions at depth 0 (top-level) and depth 1 (inside class bodies) are valid.
|
|
991
|
+
let braceDepth = 0;
|
|
992
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
993
|
+
const line = logicalLines[i];
|
|
994
|
+
if (line.length > MAX_REGEX_LINE_LEN) {
|
|
995
|
+
braceDepth += (line.match(/\{/g)?.length ?? 0) - (line.match(/\}/g)?.length ?? 0);
|
|
996
|
+
continue;
|
|
997
|
+
}
|
|
998
|
+
const match = line.match(funcRegex);
|
|
999
|
+
if (match && braceDepth <= 1) {
|
|
1000
|
+
const visibility = match[1] || 'public';
|
|
1001
|
+
const isSuspend = !!match[2];
|
|
1002
|
+
const name = match[3];
|
|
1003
|
+
const paramsStr = match[4];
|
|
1004
|
+
let returnType = match[5]?.trim();
|
|
1005
|
+
// Extract full generic return type
|
|
1006
|
+
if (returnType && returnType.includes('<')) {
|
|
1007
|
+
const angleIdx = returnType.indexOf('<');
|
|
1008
|
+
const inner = matchBalancedBrackets(returnType, angleIdx);
|
|
1009
|
+
if (inner !== undefined) {
|
|
1010
|
+
returnType = returnType.substring(0, angleIdx) + '<' + inner + '>';
|
|
1011
|
+
}
|
|
1012
|
+
}
|
|
1013
|
+
const origLine = lineMap[i] - 1;
|
|
1014
|
+
const decorators = collectDecorators(rawLines, origLine, '@');
|
|
1015
|
+
functions.push({
|
|
1016
|
+
name,
|
|
1017
|
+
parameters: this.parseParams(paramsStr),
|
|
1018
|
+
returnType,
|
|
1019
|
+
isAsync: isSuspend,
|
|
1020
|
+
isPublic: visibility === 'public',
|
|
1021
|
+
complexity: 1,
|
|
1022
|
+
decorators,
|
|
1023
|
+
genericParams: [],
|
|
1024
|
+
startLine: lineMap[i],
|
|
1025
|
+
endLine: lineMap[i],
|
|
1026
|
+
});
|
|
1027
|
+
}
|
|
1028
|
+
// Update brace depth after checking for function match
|
|
1029
|
+
braceDepth += countBraceDelta(line);
|
|
1030
|
+
if (braceDepth < 0)
|
|
1031
|
+
braceDepth = 0;
|
|
1032
|
+
}
|
|
1033
|
+
return functions;
|
|
1034
|
+
}
|
|
1035
|
+
extractClasses(content) {
|
|
1036
|
+
const classes = [];
|
|
1037
|
+
const rawLines = content.split('\n');
|
|
1038
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
1039
|
+
const classRegex = /^\s*(public|private|protected|internal)?\s*(data|sealed|abstract|open)?\s*class\s+(\w+)(?:<[^{]*>)?(?:\s*(?:\([^)]*\))?\s*:\s*([^{\s]+(?:\s+[^{\s]+)*))?\s*\{?/;
|
|
1040
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
1041
|
+
if (logicalLines[i].length > MAX_REGEX_LINE_LEN)
|
|
1042
|
+
continue;
|
|
1043
|
+
const match = logicalLines[i].match(classRegex);
|
|
1044
|
+
if (match) {
|
|
1045
|
+
const name = match[3];
|
|
1046
|
+
const bases = match[4]
|
|
1047
|
+
? match[4]
|
|
1048
|
+
.split(',')
|
|
1049
|
+
.map((s) => s.trim().split('(')[0].trim())
|
|
1050
|
+
: [];
|
|
1051
|
+
const origLine = lineMap[i] - 1;
|
|
1052
|
+
const decorators = collectDecorators(rawLines, origLine, '@');
|
|
1053
|
+
classes.push({
|
|
1054
|
+
name,
|
|
1055
|
+
methods: [],
|
|
1056
|
+
properties: [],
|
|
1057
|
+
isPublic: (match[1] || 'public') === 'public',
|
|
1058
|
+
implements: bases.slice(1),
|
|
1059
|
+
extends: bases[0] || undefined,
|
|
1060
|
+
decorators,
|
|
1061
|
+
startLine: lineMap[i],
|
|
1062
|
+
endLine: lineMap[i],
|
|
1063
|
+
});
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1066
|
+
return classes;
|
|
1067
|
+
}
|
|
1068
|
+
extractImports(content) {
|
|
1069
|
+
const imports = [];
|
|
1070
|
+
const lines = content.split('\n');
|
|
1071
|
+
for (const line of lines) {
|
|
1072
|
+
const match = line.match(/^\s*import\s+([^\s]+)/);
|
|
1073
|
+
if (match)
|
|
1074
|
+
imports.push({
|
|
1075
|
+
module: match[1],
|
|
1076
|
+
namedImports: [],
|
|
1077
|
+
isTypeOnly: false,
|
|
1078
|
+
});
|
|
1079
|
+
}
|
|
1080
|
+
return imports;
|
|
1081
|
+
}
|
|
1082
|
+
parseParams(paramsStr) {
|
|
1083
|
+
if (!paramsStr.trim())
|
|
1084
|
+
return [];
|
|
1085
|
+
return splitParamsGenericAware(paramsStr).map((p) => {
|
|
1086
|
+
// Split on first colon only, since types can contain colons in rare cases
|
|
1087
|
+
const colonIdx = p.indexOf(':');
|
|
1088
|
+
if (colonIdx === -1) {
|
|
1089
|
+
const cleaned = p.replace('val ', '').replace('var ', '').trim();
|
|
1090
|
+
return { name: cleaned, type: undefined, isOptional: false, defaultValue: undefined };
|
|
1091
|
+
}
|
|
1092
|
+
const nameWithVal = p.substring(0, colonIdx)
|
|
1093
|
+
.replace('val ', '')
|
|
1094
|
+
.replace('var ', '')
|
|
1095
|
+
.trim();
|
|
1096
|
+
const typeAndDefault = p.substring(colonIdx + 1).trim();
|
|
1097
|
+
const eqIdx = typeAndDefault.indexOf('=');
|
|
1098
|
+
const type = eqIdx >= 0 ? typeAndDefault.substring(0, eqIdx).trim() : typeAndDefault;
|
|
1099
|
+
const hasDefault = eqIdx >= 0;
|
|
1100
|
+
return {
|
|
1101
|
+
name: nameWithVal,
|
|
1102
|
+
type,
|
|
1103
|
+
isOptional: hasDefault || type?.endsWith('?') || false,
|
|
1104
|
+
defaultValue: undefined,
|
|
1105
|
+
};
|
|
1106
|
+
});
|
|
1107
|
+
}
|
|
1108
|
+
}
|
|
1109
|
+
// --- Dart Parser ---
|
|
1110
|
+
class DartParser {
|
|
1111
|
+
language = 'dart';
|
|
1112
|
+
supportedExtensions = ['.dart'];
|
|
1113
|
+
async parseFile(content, filePath) {
|
|
1114
|
+
return {
|
|
1115
|
+
functions: this.extractFunctions(content),
|
|
1116
|
+
classes: this.extractClasses(content),
|
|
1117
|
+
imports: this.extractImports(content),
|
|
1118
|
+
language: 'dart',
|
|
1119
|
+
filePath,
|
|
1120
|
+
};
|
|
1121
|
+
}
|
|
1122
|
+
extractFunctions(content) {
|
|
1123
|
+
const functions = [];
|
|
1124
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
1125
|
+
const funcRegex = /^\s*([\w<>,.?]+(?:\s+[\w<>,.?]+)*)\s+(\w+)\s*\(([^)]*)\)(?:\s*(async))?\s*\{/;
|
|
1126
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
1127
|
+
const line = logicalLines[i];
|
|
1128
|
+
if (line.includes(' class '))
|
|
1129
|
+
continue;
|
|
1130
|
+
if (line.length > MAX_REGEX_LINE_LEN)
|
|
1131
|
+
continue;
|
|
1132
|
+
const match = line.match(funcRegex);
|
|
1133
|
+
if (match) {
|
|
1134
|
+
const returnTypeRaw = match[1].trim();
|
|
1135
|
+
let returnType = returnTypeRaw;
|
|
1136
|
+
// Extract full generic return type
|
|
1137
|
+
if (returnTypeRaw && returnTypeRaw.includes('<')) {
|
|
1138
|
+
const angleIdx = returnTypeRaw.indexOf('<');
|
|
1139
|
+
const inner = matchBalancedBrackets(returnTypeRaw, angleIdx);
|
|
1140
|
+
if (inner !== undefined) {
|
|
1141
|
+
returnType = returnTypeRaw.substring(0, angleIdx) + '<' + inner + '>';
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
const name = match[2];
|
|
1145
|
+
const paramsStr = match[3];
|
|
1146
|
+
const isAsync = !!match[4] || returnType.includes('Future');
|
|
1147
|
+
functions.push({
|
|
1148
|
+
name,
|
|
1149
|
+
parameters: this.parseParams(paramsStr),
|
|
1150
|
+
returnType: returnType === 'void' ? undefined : returnType,
|
|
1151
|
+
isAsync,
|
|
1152
|
+
isPublic: !name.startsWith('_'),
|
|
1153
|
+
complexity: 1,
|
|
1154
|
+
decorators: [],
|
|
1155
|
+
genericParams: [],
|
|
1156
|
+
startLine: lineMap[i],
|
|
1157
|
+
endLine: lineMap[i],
|
|
1158
|
+
});
|
|
1159
|
+
}
|
|
1160
|
+
}
|
|
1161
|
+
return functions;
|
|
1162
|
+
}
|
|
1163
|
+
extractClasses(content) {
|
|
1164
|
+
const classes = [];
|
|
1165
|
+
const { logicalLines, lineMap } = joinMultiLineSignatures(content);
|
|
1166
|
+
const classRegex = /^\s*(abstract +)?class\s+(\w+)(?:<[^{]*>)?(?:\s+extends\s+(\w+))?(?:\s+(?:with|implements)\s+([^{\s]+(?:\s+[^{\s]+)*))?\s*\{/;
|
|
1167
|
+
for (let i = 0; i < logicalLines.length; i++) {
|
|
1168
|
+
if (logicalLines[i].length > MAX_REGEX_LINE_LEN)
|
|
1169
|
+
continue;
|
|
1170
|
+
const match = logicalLines[i].match(classRegex);
|
|
1171
|
+
if (match) {
|
|
1172
|
+
const name = match[2];
|
|
1173
|
+
const extendsName = match[3];
|
|
1174
|
+
const mixinsAndInterfaces = match[4]
|
|
1175
|
+
? match[4].split(',').map((s) => s.trim())
|
|
1176
|
+
: [];
|
|
1177
|
+
classes.push({
|
|
1178
|
+
name,
|
|
1179
|
+
methods: [],
|
|
1180
|
+
properties: [],
|
|
1181
|
+
isPublic: !name.startsWith('_'),
|
|
1182
|
+
implements: mixinsAndInterfaces,
|
|
1183
|
+
extends: extendsName,
|
|
1184
|
+
decorators: [],
|
|
1185
|
+
startLine: lineMap[i],
|
|
1186
|
+
endLine: lineMap[i],
|
|
1187
|
+
});
|
|
1188
|
+
}
|
|
1189
|
+
}
|
|
1190
|
+
return classes;
|
|
1191
|
+
}
|
|
1192
|
+
extractImports(content) {
|
|
1193
|
+
const imports = [];
|
|
1194
|
+
const lines = content.split('\n');
|
|
1195
|
+
for (const line of lines) {
|
|
1196
|
+
const match = line.match(/^\s*import\s+'([^']+)'/);
|
|
1197
|
+
if (match)
|
|
1198
|
+
imports.push({
|
|
1199
|
+
module: match[1],
|
|
1200
|
+
namedImports: [],
|
|
1201
|
+
isTypeOnly: false,
|
|
1202
|
+
});
|
|
1203
|
+
}
|
|
1204
|
+
return imports;
|
|
1205
|
+
}
|
|
1206
|
+
parseParams(paramsStr) {
|
|
1207
|
+
if (!paramsStr.trim())
|
|
1208
|
+
return [];
|
|
1209
|
+
// Remove curly/square brackets for named/optional params
|
|
1210
|
+
const clean = paramsStr.replace(/[{}[\]]/g, '');
|
|
1211
|
+
return splitParamsGenericAware(clean)
|
|
1212
|
+
.map((p) => p.trim())
|
|
1213
|
+
.filter((p) => p)
|
|
1214
|
+
.map((p) => {
|
|
1215
|
+
const parts = p
|
|
1216
|
+
.replace('required ', '')
|
|
1217
|
+
.trim()
|
|
1218
|
+
.split(/\s+/);
|
|
1219
|
+
const name = parts[parts.length - 1] || '';
|
|
1220
|
+
const type = parts.slice(0, -1).join(' ') || undefined;
|
|
1221
|
+
return {
|
|
1222
|
+
name,
|
|
1223
|
+
type,
|
|
1224
|
+
isOptional: p.includes('?') || p.includes('{'),
|
|
1225
|
+
defaultValue: undefined,
|
|
1226
|
+
};
|
|
1227
|
+
});
|
|
1228
|
+
}
|
|
1229
|
+
}
|
|
1230
|
+
// ============================================================================
|
|
1231
|
+
// Parser Registry
|
|
1232
|
+
// ============================================================================
|
|
1233
|
+
/**
|
|
1234
|
+
* Registry of all language parsers.
|
|
1235
|
+
* Provides regex-based parsing for Python, Java, C#, Go, Rust, Swift, Kotlin, Dart.
|
|
1236
|
+
*/
|
|
1237
|
+
export class TreeSitterParserRegistry {
|
|
1238
|
+
parsers = new Map();
|
|
1239
|
+
constructor() {
|
|
1240
|
+
this.register(new PythonParser());
|
|
1241
|
+
this.register(new JavaParser());
|
|
1242
|
+
this.register(new CSharpParser());
|
|
1243
|
+
this.register(new GoParser());
|
|
1244
|
+
this.register(new RustParser());
|
|
1245
|
+
this.register(new SwiftParser());
|
|
1246
|
+
this.register(new KotlinParser());
|
|
1247
|
+
this.register(new DartParser());
|
|
1248
|
+
}
|
|
1249
|
+
register(parser) {
|
|
1250
|
+
this.parsers.set(parser.language, parser);
|
|
1251
|
+
}
|
|
1252
|
+
getParser(language) {
|
|
1253
|
+
return this.parsers.get(language);
|
|
1254
|
+
}
|
|
1255
|
+
async parseFile(content, filePath, language) {
|
|
1256
|
+
const parser = this.parsers.get(language);
|
|
1257
|
+
if (!parser)
|
|
1258
|
+
return undefined;
|
|
1259
|
+
return parser.parseFile(content, filePath);
|
|
1260
|
+
}
|
|
1261
|
+
getSupportedLanguages() {
|
|
1262
|
+
return Array.from(this.parsers.keys());
|
|
1263
|
+
}
|
|
1264
|
+
supportsLanguage(language) {
|
|
1265
|
+
return this.parsers.has(language);
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
export const treeSitterRegistry = new TreeSitterParserRegistry();
|
|
1269
|
+
// Export individual parsers for direct use
|
|
1270
|
+
export { PythonParser, JavaParser, CSharpParser, GoParser, RustParser, SwiftParser, KotlinParser, DartParser, };
|
|
1271
|
+
//# sourceMappingURL=multi-language-parser.js.map
|