@crownpeak/dqm-react-component-dev-mcp 1.2.0
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/README.md +138 -0
- package/data/.env.example +22 -0
- package/data/.gitattributes +47 -0
- package/data/.glfrc.json +7 -0
- package/data/.husky/pre-commit +5 -0
- package/data/.nvmrc +1 -0
- package/data/CHANGELOG.md +75 -0
- package/data/CODE_OF_CONDUCT.md +129 -0
- package/data/CONTRIBUTING.md +203 -0
- package/data/DOCS-STRUCTURE.md +307 -0
- package/data/I18N.md +292 -0
- package/data/LICENSE +22 -0
- package/data/README.md +315 -0
- package/data/SECURITY.md +125 -0
- package/data/WIKI-DEPLOYMENT.md +348 -0
- package/data/docs/AI-FEATURES.md +610 -0
- package/data/docs/API-REFERENCE.md +1022 -0
- package/data/docs/AUTHENTICATION.md +301 -0
- package/data/docs/BACKEND-API.md +468 -0
- package/data/docs/DEVELOPMENT.md +375 -0
- package/data/docs/EXAMPLES.md +622 -0
- package/data/docs/MCP-SERVER.md +307 -0
- package/data/docs/MIGRATION-GUIDE.md +367 -0
- package/data/docs/NPM-PUBLISH.md +193 -0
- package/data/docs/QUICKSTART.md +206 -0
- package/data/docs/REDIS-SETUP.md +162 -0
- package/data/docs/SERVER.md +228 -0
- package/data/docs/TROUBLESHOOTING.md +657 -0
- package/data/docs/WIDGET-GUIDE.md +638 -0
- package/data/docs/WIKI-HOME.md +58 -0
- package/data/docs/WIKI-SIDEBAR.md +39 -0
- package/data/package.json +171 -0
- package/data/playwright.config.ts +64 -0
- package/data/probe/.cargo/config.toml +10 -0
- package/data/probe/.claude/commands/performance-review.md +15 -0
- package/data/probe/.clinerules +288 -0
- package/data/probe/.dockerignore +57 -0
- package/data/probe/.githooks/post-commit +11 -0
- package/data/probe/.githooks/pre-commit +99 -0
- package/data/probe/.githooks/pre-commit-vow +9 -0
- package/data/probe/.prompts/engineer.md +41 -0
- package/data/probe/.roomodes +28 -0
- package/data/probe/.windsurfrules +0 -0
- package/data/probe/BASH_TOOL_SUMMARY.md +148 -0
- package/data/probe/BENCHMARKING.md +256 -0
- package/data/probe/CLAUDE.md +226 -0
- package/data/probe/CODE_OF_CONDUCT.md +128 -0
- package/data/probe/CONTRIBUTING.md +193 -0
- package/data/probe/Cargo.toml +120 -0
- package/data/probe/Cross.toml +10 -0
- package/data/probe/DOCKER-README.md +224 -0
- package/data/probe/Dockerfile +32 -0
- package/data/probe/ENHANCED_DEBUG_TELEMETRY.md +188 -0
- package/data/probe/LICENSE +201 -0
- package/data/probe/Makefile +210 -0
- package/data/probe/README.md +824 -0
- package/data/probe/SECURITY.md +67 -0
- package/data/probe/WINDOWS-GUIDE.md +294 -0
- package/data/probe/benches/parsing_benchmarks.rs +370 -0
- package/data/probe/benches/search_benchmarks.rs +599 -0
- package/data/probe/benches/simd_benchmarks.rs +372 -0
- package/data/probe/benches/timing_benchmarks.rs +287 -0
- package/data/probe/build-windows.bat +229 -0
- package/data/probe/codex-config/config.toml +6 -0
- package/data/probe/docs/PERFORMANCE_OPTIMIZATION.md +161 -0
- package/data/probe/examples/cache_demo.rs +46 -0
- package/data/probe/examples/chat/.dockerignore +37 -0
- package/data/probe/examples/chat/ChatSessionManager.js +295 -0
- package/data/probe/examples/chat/Dockerfile +98 -0
- package/data/probe/examples/chat/LICENSE +201 -0
- package/data/probe/examples/chat/LOCAL_IMAGE_SUPPORT.md +195 -0
- package/data/probe/examples/chat/MCP_INTEGRATION.md +400 -0
- package/data/probe/examples/chat/README.md +338 -0
- package/data/probe/examples/chat/TRACING.md +226 -0
- package/data/probe/examples/chat/appTracer.js +968 -0
- package/data/probe/examples/chat/auth.js +76 -0
- package/data/probe/examples/chat/bin/probe-chat.js +13 -0
- package/data/probe/examples/chat/build.js +104 -0
- package/data/probe/examples/chat/cancelRequest.js +84 -0
- package/data/probe/examples/chat/demo-agentic-image-flow.js +88 -0
- package/data/probe/examples/chat/demo-local-images.js +128 -0
- package/data/probe/examples/chat/fileSpanExporter.js +181 -0
- package/data/probe/examples/chat/implement/README.md +228 -0
- package/data/probe/examples/chat/implement/backends/AiderBackend.js +750 -0
- package/data/probe/examples/chat/implement/backends/BaseBackend.js +276 -0
- package/data/probe/examples/chat/implement/backends/ClaudeCodeBackend.js +767 -0
- package/data/probe/examples/chat/implement/backends/MockBackend.js +237 -0
- package/data/probe/examples/chat/implement/backends/registry.js +85 -0
- package/data/probe/examples/chat/implement/core/BackendManager.js +567 -0
- package/data/probe/examples/chat/implement/core/ImplementTool.js +354 -0
- package/data/probe/examples/chat/implement/core/config.js +428 -0
- package/data/probe/examples/chat/implement/core/timeouts.js +58 -0
- package/data/probe/examples/chat/implement/core/utils.js +496 -0
- package/data/probe/examples/chat/implement/types/BackendTypes.js +126 -0
- package/data/probe/examples/chat/index.js +669 -0
- package/data/probe/examples/chat/mcpServer.js +341 -0
- package/data/probe/examples/chat/npm/LICENSE +15 -0
- package/data/probe/examples/chat/npm/README.md +168 -0
- package/data/probe/examples/chat/npm/bin/probe-chat.js +156 -0
- package/data/probe/examples/chat/npm/index.js +259 -0
- package/data/probe/examples/chat/npm/package.json +54 -0
- package/data/probe/examples/chat/package.json +102 -0
- package/data/probe/examples/chat/probeChat.js +456 -0
- package/data/probe/examples/chat/probeTool.js +491 -0
- package/data/probe/examples/chat/storage/JsonChatStorage.js +476 -0
- package/data/probe/examples/chat/telemetry.js +281 -0
- package/data/probe/examples/chat/test/integration/chatFlows.test.js +320 -0
- package/data/probe/examples/chat/test/integration/toolCalling.test.js +471 -0
- package/data/probe/examples/chat/test/mocks/mockLLMProvider.js +269 -0
- package/data/probe/examples/chat/test/test-backends.js +90 -0
- package/data/probe/examples/chat/test/testUtils.js +530 -0
- package/data/probe/examples/chat/test/unit/backendTimeout.test.js +161 -0
- package/data/probe/examples/chat/test/unit/packageFiles.test.js +120 -0
- package/data/probe/examples/chat/test/verify-tests.js +118 -0
- package/data/probe/examples/chat/test-agentic-image-loading.js +294 -0
- package/data/probe/examples/chat/test-ai-sdk-telemetry.js +204 -0
- package/data/probe/examples/chat/test-chat-tracing.js +38 -0
- package/data/probe/examples/chat/test-direct-function.js +49 -0
- package/data/probe/examples/chat/test-file-size-validation.js +103 -0
- package/data/probe/examples/chat/test-full-mcp-integration.js +258 -0
- package/data/probe/examples/chat/test-github-context.txt +12 -0
- package/data/probe/examples/chat/test-hierarchy.js +203 -0
- package/data/probe/examples/chat/test-image-spans.js +37 -0
- package/data/probe/examples/chat/test-local-image-reading.js +176 -0
- package/data/probe/examples/chat/test-mcp-integration.js +136 -0
- package/data/probe/examples/chat/test-mcp-probe-server.js +161 -0
- package/data/probe/examples/chat/test-mcp-with-ai.js +279 -0
- package/data/probe/examples/chat/test-multiple-allowed-dirs.js +111 -0
- package/data/probe/examples/chat/test-probe-mcp-server.js +110 -0
- package/data/probe/examples/chat/test-security-validation.js +145 -0
- package/data/probe/examples/chat/test-simple-tracing.js +32 -0
- package/data/probe/examples/chat/test-trace-verification.js +235 -0
- package/data/probe/examples/chat/test-tracing.js +114 -0
- package/data/probe/examples/chat/tokenCounter.js +419 -0
- package/data/probe/examples/chat/tokenUsageDisplay.js +134 -0
- package/data/probe/examples/chat/webServer.js +1103 -0
- package/data/probe/examples/reranker/Cargo.toml +33 -0
- package/data/probe/examples/reranker/DEBUG_OUTPUT_ANALYSIS.md +71 -0
- package/data/probe/examples/reranker/MODELS.md +66 -0
- package/data/probe/examples/reranker/MODEL_COMPARISON.md +60 -0
- package/data/probe/examples/reranker/MULTI_MODEL_ANALYSIS.md +176 -0
- package/data/probe/examples/reranker/PERFORMANCE_SUMMARY.md +156 -0
- package/data/probe/examples/reranker/README.md +347 -0
- package/data/probe/examples/reranker/RUST_BERT_COMPARISON.md +82 -0
- package/data/probe/examples/reranker/TOKENIZATION_GUIDE.md +120 -0
- package/data/probe/examples/reranker/check_rust_tokenizer.py +108 -0
- package/data/probe/examples/reranker/convert_to_torchscript.py +109 -0
- package/data/probe/examples/reranker/debug_scoring.py +189 -0
- package/data/probe/examples/reranker/debug_tokenization.py +154 -0
- package/data/probe/examples/reranker/download_models.sh +73 -0
- package/data/probe/examples/reranker/requirements.txt +13 -0
- package/data/probe/examples/reranker/run_comprehensive_benchmark.sh +83 -0
- package/data/probe/examples/reranker/rust_bert_test/Cargo.toml +12 -0
- package/data/probe/examples/reranker/rust_bert_test/README.md +54 -0
- package/data/probe/examples/reranker/simple_test.py +50 -0
- package/data/probe/examples/reranker/test_all_models.sh +63 -0
- package/data/probe/examples/reranker/test_bert_results.sh +44 -0
- package/data/probe/examples/reranker/test_cross_encoder.py +334 -0
- package/data/probe/examples/reranker/test_cross_encoder.sh +80 -0
- package/data/probe/examples/reranker/test_exact_comparison.py +151 -0
- package/data/probe/examples/reranker/test_parallel_performance.sh +56 -0
- package/data/probe/examples/reranker/test_scores.py +132 -0
- package/data/probe/install.ps1 +508 -0
- package/data/probe/install.sh +460 -0
- package/data/probe/npm/CLONE_METHOD_EXAMPLES.md +596 -0
- package/data/probe/npm/CONTEXT_COMPACTION.md +303 -0
- package/data/probe/npm/DELEGATE_TOOL_README.md +166 -0
- package/data/probe/npm/MAID_INTEGRATION.md +313 -0
- package/data/probe/npm/MCP_INTEGRATION_SUMMARY.md +241 -0
- package/data/probe/npm/README.md +824 -0
- package/data/probe/npm/bin/.gitignore +7 -0
- package/data/probe/npm/bin/.gitkeep +0 -0
- package/data/probe/npm/bin/README.md +12 -0
- package/data/probe/npm/bin/probe +167 -0
- package/data/probe/npm/docs/CLAUDE_CODE_INTEGRATION.md +414 -0
- package/data/probe/npm/docs/CODEX_INTEGRATION.md +502 -0
- package/data/probe/npm/docs/EDIT_CREATE_TOOLS.md +233 -0
- package/data/probe/npm/docs/RETRY_AND_FALLBACK.md +674 -0
- package/data/probe/npm/example-usage.js +335 -0
- package/data/probe/npm/examples/multi-engine-demo.js +117 -0
- package/data/probe/npm/examples/probe-agent-cli.js +113 -0
- package/data/probe/npm/examples/test-agent-edit.js +114 -0
- package/data/probe/npm/examples/test-edit-create.js +120 -0
- package/data/probe/npm/examples/test-edit-direct.js +114 -0
- package/data/probe/npm/index.d.ts +744 -0
- package/data/probe/npm/jest.config.js +52 -0
- package/data/probe/npm/package.json +117 -0
- package/data/probe/npm/scripts/build-agent.cjs +75 -0
- package/data/probe/npm/scripts/build-cjs.js +124 -0
- package/data/probe/npm/scripts/build-mcp.cjs +36 -0
- package/data/probe/npm/scripts/postinstall.js +216 -0
- package/data/probe/npm/test-codex-e2e.js +78 -0
- package/data/probe/npm/test-download-lock.js +109 -0
- package/data/probe/npm/test-grep-security.js +94 -0
- package/data/probe/npm/test-grep-simplified.js +63 -0
- package/data/probe/npm/test-grep.js +51 -0
- package/data/probe/npm/tests/README.md +96 -0
- package/data/probe/npm/tests/agent-compact-history.test.js +174 -0
- package/data/probe/npm/tests/allow-tests-default.test.js +151 -0
- package/data/probe/npm/tests/contextCompactor.test.js +498 -0
- package/data/probe/npm/tests/delegate-config.test.js +353 -0
- package/data/probe/npm/tests/delegate-integration.test.js +348 -0
- package/data/probe/npm/tests/extractor-integration.test.js +162 -0
- package/data/probe/npm/tests/extractor.test.js +317 -0
- package/data/probe/npm/tests/fixtures/sampleDiagrams.js +267 -0
- package/data/probe/npm/tests/integration/claude-code-auto-fallback.spec.js +148 -0
- package/data/probe/npm/tests/integration/claude-code-multi-step.spec.js +127 -0
- package/data/probe/npm/tests/integration/claude-code-tool-events.spec.js +163 -0
- package/data/probe/npm/tests/integration/codex-auto-fallback.spec.js +191 -0
- package/data/probe/npm/tests/integration/codex-tool-events.spec.js +147 -0
- package/data/probe/npm/tests/integration/examplesChatMcp.test.js +402 -0
- package/data/probe/npm/tests/integration/mcpDotenvSupport.test.js +174 -0
- package/data/probe/npm/tests/integration/mcpErrorHandling.test.js +566 -0
- package/data/probe/npm/tests/integration/mcpRobustness.test.js +564 -0
- package/data/probe/npm/tests/integration/mcpStdoutPurity.test.js +355 -0
- package/data/probe/npm/tests/integration/probeAgentMcp.test.js +398 -0
- package/data/probe/npm/tests/integration/retryFallback.test.js +368 -0
- package/data/probe/npm/tests/integration/schema-in-initial-message.test.js +318 -0
- package/data/probe/npm/tests/integration/schema-validation-loop-prevention.test.js +244 -0
- package/data/probe/npm/tests/integration/schemaRetryLogic.test.js +94 -0
- package/data/probe/npm/tests/integration/validationFlow.test.js +329 -0
- package/data/probe/npm/tests/manual/test-codex-basic.js +110 -0
- package/data/probe/npm/tests/mcp/mcpClientManager.test.js +614 -0
- package/data/probe/npm/tests/mcp/mcpConfig.test.js +359 -0
- package/data/probe/npm/tests/mcp/mcpXmlBridge.test.js +436 -0
- package/data/probe/npm/tests/mcp/mockMcpServer.js +510 -0
- package/data/probe/npm/tests/mcp-strict-syntax.test.js +319 -0
- package/data/probe/npm/tests/mermaidQuoteEscaping.test.js +214 -0
- package/data/probe/npm/tests/nestedQuoteFix.test.js +40 -0
- package/data/probe/npm/tests/setup.js +46 -0
- package/data/probe/npm/tests/unit/allowed-tools.test.js +513 -0
- package/data/probe/npm/tests/unit/attempt-completion-closing-tag-in-content.test.js +188 -0
- package/data/probe/npm/tests/unit/attemptCompletionJsonFix.test.js +238 -0
- package/data/probe/npm/tests/unit/attemptCompletionJsonIssue.test.js +128 -0
- package/data/probe/npm/tests/unit/backtickAutoFix.test.js +35 -0
- package/data/probe/npm/tests/unit/bash-probe-agent-integration.test.js +389 -0
- package/data/probe/npm/tests/unit/bash-simple-commands.test.js +324 -0
- package/data/probe/npm/tests/unit/bash-tool-comprehensive.test.js +371 -0
- package/data/probe/npm/tests/unit/bash-tool-integration.test.js +310 -0
- package/data/probe/npm/tests/unit/bash-tool.test.js +341 -0
- package/data/probe/npm/tests/unit/completion-prompt.test.js +379 -0
- package/data/probe/npm/tests/unit/cwd-path-options.test.js +287 -0
- package/data/probe/npm/tests/unit/delegate-limits.test.js +422 -0
- package/data/probe/npm/tests/unit/direct-content-attempt-completion.test.js +235 -0
- package/data/probe/npm/tests/unit/edit-create-tools.test.js +609 -0
- package/data/probe/npm/tests/unit/enhancedMermaidValidation.test.js +577 -0
- package/data/probe/npm/tests/unit/extract-content.test.js +83 -0
- package/data/probe/npm/tests/unit/extract-multiple-targets.test.js +89 -0
- package/data/probe/npm/tests/unit/fallbackManager.test.js +442 -0
- package/data/probe/npm/tests/unit/githubCompatibilityValidation.test.js +258 -0
- package/data/probe/npm/tests/unit/imageConfig.test.js +149 -0
- package/data/probe/npm/tests/unit/imagePathResolution.test.js +345 -0
- package/data/probe/npm/tests/unit/json-fixing-agent.test.js +238 -0
- package/data/probe/npm/tests/unit/json-validation-enhanced-errors.test.js +199 -0
- package/data/probe/npm/tests/unit/jsonValidationInfiniteLoopFix.test.js +228 -0
- package/data/probe/npm/tests/unit/maidIntegration.test.js +139 -0
- package/data/probe/npm/tests/unit/maxIterationsWarning.test.js +195 -0
- package/data/probe/npm/tests/unit/mermaidEdgeLabelFix.test.js +161 -0
- package/data/probe/npm/tests/unit/mermaidHtmlEntities.test.js +76 -0
- package/data/probe/npm/tests/unit/mermaidInfiniteLoopFix.test.js +64 -0
- package/data/probe/npm/tests/unit/mermaidValidation.test.js +723 -0
- package/data/probe/npm/tests/unit/mermaidValidationVisorExample.test.js +309 -0
- package/data/probe/npm/tests/unit/probe-agent-clone-realistic.test.js +643 -0
- package/data/probe/npm/tests/unit/probe-agent-clone.test.js +476 -0
- package/data/probe/npm/tests/unit/probe-agent-delegate.test.js +400 -0
- package/data/probe/npm/tests/unit/probe-agent-model-option.test.js +118 -0
- package/data/probe/npm/tests/unit/probeTool-security.test.js +283 -0
- package/data/probe/npm/tests/unit/readImageTool.test.js +418 -0
- package/data/probe/npm/tests/unit/retryManager.test.js +317 -0
- package/data/probe/npm/tests/unit/schema-aware-reminders.test.js +288 -0
- package/data/probe/npm/tests/unit/schemaDefinitionDetection.test.js +115 -0
- package/data/probe/npm/tests/unit/schemaUtils.test.js +1268 -0
- package/data/probe/npm/tests/unit/simpleTelemetry.test.js +282 -0
- package/data/probe/npm/tests/unit/simplified-attempt-completion.test.js +274 -0
- package/data/probe/npm/tests/unit/single-quote-json-bug.test.js +231 -0
- package/data/probe/npm/tests/unit/subgraphAutoFix.test.js +110 -0
- package/data/probe/npm/tests/unit/system-prompt.test.js +32 -0
- package/data/probe/npm/tests/unit/types-probe-agent-options.test.js +42 -0
- package/data/probe/npm/tests/unit/xmlParsing.test.js +720 -0
- package/data/probe/npm/tsconfig.json +21 -0
- package/data/probe/result1.txt +19 -0
- package/data/probe/result2.txt +26 -0
- package/data/probe/scripts/benchmark.sh +270 -0
- package/data/probe/scripts/cache_memory_analysis.rs +844 -0
- package/data/probe/scripts/claude-hook-wrapper.sh +56 -0
- package/data/probe/site/.env.example +10 -0
- package/data/probe/site/DEPLOYMENT.md +86 -0
- package/data/probe/site/README.md +183 -0
- package/data/probe/site/adding-languages.md +135 -0
- package/data/probe/site/ai-chat.md +427 -0
- package/data/probe/site/ai-integration.md +1488 -0
- package/data/probe/site/blog/agentic-flow-custom-xml-protocol.md +407 -0
- package/data/probe/site/blog/index.md +118 -0
- package/data/probe/site/blog/v0.6.0-release.md +426 -0
- package/data/probe/site/blog.md +8 -0
- package/data/probe/site/changelog.md +200 -0
- package/data/probe/site/cli-mode.md +437 -0
- package/data/probe/site/code-extraction.md +436 -0
- package/data/probe/site/contributing/README.md +9 -0
- package/data/probe/site/contributing/documentation-cross-references.md +215 -0
- package/data/probe/site/contributing/documentation-maintenance.md +275 -0
- package/data/probe/site/contributing/documentation-structure.md +75 -0
- package/data/probe/site/documentation-cross-references.md +215 -0
- package/data/probe/site/documentation-guide.md +132 -0
- package/data/probe/site/documentation-maintenance.md +275 -0
- package/data/probe/site/features.md +147 -0
- package/data/probe/site/how-it-works.md +118 -0
- package/data/probe/site/index.md +175 -0
- package/data/probe/site/index.md.bak +133 -0
- package/data/probe/site/installation.md +235 -0
- package/data/probe/site/integrations/docker.md +248 -0
- package/data/probe/site/integrations/github-actions.md +413 -0
- package/data/probe/site/language-support-overview.md +168 -0
- package/data/probe/site/mcp-integration.md +587 -0
- package/data/probe/site/mcp-server.md +304 -0
- package/data/probe/site/navigation-structure.md +76 -0
- package/data/probe/site/nodejs-sdk.md +798 -0
- package/data/probe/site/output-formats.md +625 -0
- package/data/probe/site/package.json +21 -0
- package/data/probe/site/public/_headers +28 -0
- package/data/probe/site/public/_redirects +11 -0
- package/data/probe/site/quick-start.md +289 -0
- package/data/probe/site/search-functionality.md +291 -0
- package/data/probe/site/search-reference.md +291 -0
- package/data/probe/site/supported-languages.md +215 -0
- package/data/probe/site/use-cases/README.md +8 -0
- package/data/probe/site/use-cases/advanced-cli.md +253 -0
- package/data/probe/site/use-cases/ai-code-editors.md +239 -0
- package/data/probe/site/use-cases/building-ai-tools.md +529 -0
- package/data/probe/site/use-cases/cli-ai-workflows.md +285 -0
- package/data/probe/site/use-cases/deploying-probe-web-interface.md +255 -0
- package/data/probe/site/use-cases/integrating-probe-into-ai-code-editors.md +161 -0
- package/data/probe/site/use-cases/nodejs-sdk.md +596 -0
- package/data/probe/site/use-cases/team-chat.md +350 -0
- package/data/probe/site/web-interface.md +434 -0
- package/data/probe/site/wrangler.toml +9 -0
- package/data/probe/test-api-key.sh +1 -0
- package/data/probe/test-probe-implementation/hello.js +7 -0
- package/data/probe/test_cases/demonstrate_early_termination_issues.sh +176 -0
- package/data/probe/test_cases/early_termination_issues.rs +533 -0
- package/data/probe/test_data/test_nested_struct.go +26 -0
- package/data/probe/tests/README.md +286 -0
- package/data/probe/tests/README_search_determinism_tests.md +116 -0
- package/data/probe/tests/adjacent_comment_test.rs +152 -0
- package/data/probe/tests/apostrophe_handling_tests.rs +132 -0
- package/data/probe/tests/block_filtering_with_ast_tests.rs +669 -0
- package/data/probe/tests/block_merging_tests.rs +396 -0
- package/data/probe/tests/c_outline_format_tests.rs +2179 -0
- package/data/probe/tests/cache_invalidation_issues.rs.disabled +682 -0
- package/data/probe/tests/cache_order_tests.rs +147 -0
- package/data/probe/tests/cache_query_scoping_tests.rs +221 -0
- package/data/probe/tests/cli_tests.rs +680 -0
- package/data/probe/tests/comment_context_integration_test.rs +240 -0
- package/data/probe/tests/common.rs +33 -0
- package/data/probe/tests/complex_block_merging_tests.rs +599 -0
- package/data/probe/tests/complex_query_block_filtering_tests.rs +422 -0
- package/data/probe/tests/control_flow_closing_braces_test.rs +91 -0
- package/data/probe/tests/cpp_outline_format_tests.rs +1507 -0
- package/data/probe/tests/csharp_outline_format_tests.rs +941 -0
- package/data/probe/tests/elastic_query_integration_tests.rs +922 -0
- package/data/probe/tests/extract_command_tests.rs +1848 -0
- package/data/probe/tests/extract_deduplication_tests.rs +146 -0
- package/data/probe/tests/extract_input_file_tests.rs +84 -0
- package/data/probe/tests/extract_prompt_tests.rs +102 -0
- package/data/probe/tests/filename_search_tests.rs +96 -0
- package/data/probe/tests/fixtures/user/AssemblyInfo.cs +3 -0
- package/data/probe/tests/github_extract_tests.rs +234 -0
- package/data/probe/tests/go_comment_test.rs +253 -0
- package/data/probe/tests/go_outline_format_tests.rs +2587 -0
- package/data/probe/tests/go_path_resolver_tests.rs +96 -0
- package/data/probe/tests/html_outline_format_tests.rs +637 -0
- package/data/probe/tests/integration_tests.rs +837 -0
- package/data/probe/tests/ip_whitelist_test.rs +148 -0
- package/data/probe/tests/java_outline_format_tests.rs +1611 -0
- package/data/probe/tests/javascript_extract_tests.rs +315 -0
- package/data/probe/tests/javascript_outline_format_tests.rs +1464 -0
- package/data/probe/tests/json_format_tests.rs +436 -0
- package/data/probe/tests/json_schema_validation_tests.rs +450 -0
- package/data/probe/tests/lib_usage.rs +60 -0
- package/data/probe/tests/line_comment_context_extension_test.rs +459 -0
- package/data/probe/tests/line_map_cache_tests.rs +114 -0
- package/data/probe/tests/markdown_integration_tests.rs +190 -0
- package/data/probe/tests/mocks/test_ip_whitelist.go +11 -0
- package/data/probe/tests/mocks/test_object.js +27 -0
- package/data/probe/tests/mocks/test_struct.go +50 -0
- package/data/probe/tests/multi_keyword_pattern_tests.rs +464 -0
- package/data/probe/tests/multi_language_syntax_integration_tests.rs +218 -0
- package/data/probe/tests/multiple_capture_groups_tests.rs +169 -0
- package/data/probe/tests/negative_compound_word_tests.rs +246 -0
- package/data/probe/tests/nested_symbol_extraction_tests.rs +99 -0
- package/data/probe/tests/outline_cross_file_interference_test.rs +335 -0
- package/data/probe/tests/outline_keyword_preservation_test.rs +67 -0
- package/data/probe/tests/output_format_edge_cases_tests.rs +693 -0
- package/data/probe/tests/parallel_extraction_tests.rs +178 -0
- package/data/probe/tests/parallel_search_tests.rs +355 -0
- package/data/probe/tests/path_resolver_tests.rs +698 -0
- package/data/probe/tests/php_outline_format_extended_tests.rs +928 -0
- package/data/probe/tests/php_outline_format_tests.rs +768 -0
- package/data/probe/tests/property_tests.proptest-regressions +9 -0
- package/data/probe/tests/property_tests.rs +118 -0
- package/data/probe/tests/python_outline_format_tests.rs +1538 -0
- package/data/probe/tests/query_command_json_tests.rs +438 -0
- package/data/probe/tests/query_command_tests.rs +232 -0
- package/data/probe/tests/query_command_xml_tests.rs +569 -0
- package/data/probe/tests/quoted_term_with_negative_keyword_tests.rs +216 -0
- package/data/probe/tests/required_terms_filename_tests.rs +116 -0
- package/data/probe/tests/ruby_outline_format_tests.rs +1011 -0
- package/data/probe/tests/rust_line_comment_context_test.rs +151 -0
- package/data/probe/tests/rust_outline_format_enhanced_tests.rs +725 -0
- package/data/probe/tests/rust_outline_format_tests.rs +843 -0
- package/data/probe/tests/schemas/xml_output_schema.xsd +38 -0
- package/data/probe/tests/search_determinism_tests.rs +451 -0
- package/data/probe/tests/search_hints_tests.rs +253 -0
- package/data/probe/tests/special_character_escaping_tests.rs +417 -0
- package/data/probe/tests/stemming_compound_word_filtering_tests.rs +535 -0
- package/data/probe/tests/strict_elastic_syntax_tests.rs +404 -0
- package/data/probe/tests/swift_outline_format_tests.rs +3319 -0
- package/data/probe/tests/symbols_tests.rs +166 -0
- package/data/probe/tests/test_file.rs +45 -0
- package/data/probe/tests/test_tokenize.rs +28 -0
- package/data/probe/tests/timeout_tests.rs +82 -0
- package/data/probe/tests/tokenization_tests.rs +195 -0
- package/data/probe/tests/tokenized_block_filtering_tests.rs +174 -0
- package/data/probe/tests/typescript_extract_tests.rs +214 -0
- package/data/probe/tests/typescript_outline_format_tests.rs +2188 -0
- package/data/probe/tests/xml_format_tests.rs +568 -0
- package/data/probe/tests/xml_schema_validation_tests.rs +497 -0
- package/data/scripts/postinstall.mjs +9 -0
- package/data/scripts/set-version.js +0 -0
- package/data/scripts/wiki-build.sh +111 -0
- package/data/scripts/wiki-deploy.sh +73 -0
- package/data/serve.json +12 -0
- package/data/test/demo-dynamic.html +134 -0
- package/data/test/demo-esm.html +105 -0
- package/data/test/demo-iife.html +78 -0
- package/data/tsconfig.json +7 -0
- package/data/vite.server.ts +483 -0
- package/data/vitest.config.ts +40 -0
- package/data/wiki/Home.md +58 -0
- package/data/wiki/_Sidebar.md +39 -0
- package/docs-mcp.config.json +20 -0
- package/package.json +56 -0
- package/src/config.js +111 -0
- package/src/index.js +395 -0
|
@@ -0,0 +1,1538 @@
|
|
|
1
|
+
use anyhow::Result;
|
|
2
|
+
use std::fs;
|
|
3
|
+
use tempfile::TempDir;
|
|
4
|
+
|
|
5
|
+
mod common;
|
|
6
|
+
use common::TestContext;
|
|
7
|
+
|
|
8
|
+
#[test]
|
|
9
|
+
fn test_python_outline_basic_symbols() -> Result<()> {
|
|
10
|
+
let temp_dir = TempDir::new()?;
|
|
11
|
+
let test_file = temp_dir.path().join("basic.py");
|
|
12
|
+
|
|
13
|
+
let content = r#"class Calculator:
|
|
14
|
+
"""A simple calculator class."""
|
|
15
|
+
|
|
16
|
+
def __init__(self, name: str):
|
|
17
|
+
self.name = name
|
|
18
|
+
|
|
19
|
+
def add(self, x: int, y: int) -> int:
|
|
20
|
+
"""Add two numbers."""
|
|
21
|
+
return x + y
|
|
22
|
+
|
|
23
|
+
@property
|
|
24
|
+
def version(self) -> str:
|
|
25
|
+
"""Get calculator version."""
|
|
26
|
+
return "1.0.0"
|
|
27
|
+
|
|
28
|
+
def process_data(data: list) -> int:
|
|
29
|
+
"""Process a list of data."""
|
|
30
|
+
return len(data)
|
|
31
|
+
|
|
32
|
+
async def fetch_data(url: str) -> str:
|
|
33
|
+
"""Fetch data asynchronously."""
|
|
34
|
+
return f"data from {url}"
|
|
35
|
+
|
|
36
|
+
def test_calculator():
|
|
37
|
+
"""Test the calculator functionality."""
|
|
38
|
+
calc = Calculator("test")
|
|
39
|
+
assert calc.add(2, 3) == 5
|
|
40
|
+
"#;
|
|
41
|
+
|
|
42
|
+
fs::write(&test_file, content)?;
|
|
43
|
+
|
|
44
|
+
let ctx = TestContext::new();
|
|
45
|
+
let output = ctx.run_probe(&[
|
|
46
|
+
"search",
|
|
47
|
+
"def|class", // Search for Python functions and classes
|
|
48
|
+
test_file.to_str().unwrap(),
|
|
49
|
+
"--format",
|
|
50
|
+
"outline",
|
|
51
|
+
"--max-results",
|
|
52
|
+
"20",
|
|
53
|
+
"--allow-tests",
|
|
54
|
+
])?;
|
|
55
|
+
|
|
56
|
+
// Verify Python symbols are extracted (be more flexible)
|
|
57
|
+
let has_calculator = output.contains("Calculator");
|
|
58
|
+
let has_process_data = output.contains("process_data");
|
|
59
|
+
let has_fetch_data = output.contains("fetch_data") || output.contains("async");
|
|
60
|
+
let has_test = output.contains("test_calculator") || output.contains("test");
|
|
61
|
+
|
|
62
|
+
assert!(
|
|
63
|
+
has_calculator,
|
|
64
|
+
"Missing Calculator class - output: {}",
|
|
65
|
+
output
|
|
66
|
+
);
|
|
67
|
+
assert!(
|
|
68
|
+
has_process_data || output.contains("def"),
|
|
69
|
+
"Missing process_data function or similar - output: {}",
|
|
70
|
+
output
|
|
71
|
+
);
|
|
72
|
+
assert!(
|
|
73
|
+
has_fetch_data || output.contains("async") || output.contains("fetch"),
|
|
74
|
+
"Missing async function or similar - output: {}",
|
|
75
|
+
output
|
|
76
|
+
);
|
|
77
|
+
assert!(
|
|
78
|
+
has_test || output.contains("test"),
|
|
79
|
+
"Missing test function or similar - output: {}",
|
|
80
|
+
output
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
Ok(())
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
#[test]
|
|
87
|
+
fn test_python_outline_decorators() -> Result<()> {
|
|
88
|
+
let temp_dir = TempDir::new()?;
|
|
89
|
+
let test_file = temp_dir.path().join("decorators.py");
|
|
90
|
+
|
|
91
|
+
let content = r#"from functools import wraps
|
|
92
|
+
|
|
93
|
+
def timing_decorator(func):
|
|
94
|
+
@wraps(func)
|
|
95
|
+
def wrapper(*args, **kwargs):
|
|
96
|
+
import time
|
|
97
|
+
start = time.time()
|
|
98
|
+
result = func(*args, **kwargs)
|
|
99
|
+
end = time.time()
|
|
100
|
+
print(f"Execution time: {end - start}")
|
|
101
|
+
return result
|
|
102
|
+
return wrapper
|
|
103
|
+
|
|
104
|
+
class UserManager:
|
|
105
|
+
def __init__(self, db_url: str):
|
|
106
|
+
self.db_url = db_url
|
|
107
|
+
|
|
108
|
+
@property
|
|
109
|
+
def connection_status(self) -> str:
|
|
110
|
+
"""Get database connection status."""
|
|
111
|
+
return "connected"
|
|
112
|
+
|
|
113
|
+
@classmethod
|
|
114
|
+
def create_default(cls):
|
|
115
|
+
"""Create UserManager with default settings."""
|
|
116
|
+
return cls("sqlite:///default.db")
|
|
117
|
+
|
|
118
|
+
@staticmethod
|
|
119
|
+
def validate_email(email: str) -> bool:
|
|
120
|
+
"""Validate email format."""
|
|
121
|
+
return "@" in email
|
|
122
|
+
|
|
123
|
+
@timing_decorator
|
|
124
|
+
def process_users(self, users: list) -> list:
|
|
125
|
+
"""Process a list of users."""
|
|
126
|
+
return [user for user in users if self.validate_email(user.get('email', ''))]
|
|
127
|
+
"#;
|
|
128
|
+
|
|
129
|
+
fs::write(&test_file, content)?;
|
|
130
|
+
|
|
131
|
+
let ctx = TestContext::new();
|
|
132
|
+
let output = ctx.run_probe(&[
|
|
133
|
+
"search",
|
|
134
|
+
"def|class", // Search for Python functions and classes
|
|
135
|
+
test_file.to_str().unwrap(),
|
|
136
|
+
"--format",
|
|
137
|
+
"outline",
|
|
138
|
+
"--max-results",
|
|
139
|
+
"20",
|
|
140
|
+
"--allow-tests",
|
|
141
|
+
])?;
|
|
142
|
+
|
|
143
|
+
// Verify decorated functions and methods are properly shown (more flexible)
|
|
144
|
+
let has_decorator = output.contains("timing_decorator") || output.contains("decorator");
|
|
145
|
+
let has_user_manager = output.contains("UserManager") || output.contains("class");
|
|
146
|
+
|
|
147
|
+
assert!(
|
|
148
|
+
has_decorator,
|
|
149
|
+
"Missing decorator function or similar - output: {}",
|
|
150
|
+
output
|
|
151
|
+
);
|
|
152
|
+
assert!(
|
|
153
|
+
has_user_manager,
|
|
154
|
+
"Missing UserManager class or similar - output: {}",
|
|
155
|
+
output
|
|
156
|
+
);
|
|
157
|
+
// Note: Currently the extract command only shows top-level symbols
|
|
158
|
+
// Decorated methods within classes are not currently extracted as separate symbols
|
|
159
|
+
// This could be improved in future versions
|
|
160
|
+
|
|
161
|
+
Ok(())
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
#[test]
|
|
165
|
+
fn test_python_outline_nested_classes() -> Result<()> {
|
|
166
|
+
let temp_dir = TempDir::new()?;
|
|
167
|
+
let test_file = temp_dir.path().join("nested.py");
|
|
168
|
+
|
|
169
|
+
let content = r#"class ReportGenerator:
|
|
170
|
+
"""Generate various types of reports."""
|
|
171
|
+
|
|
172
|
+
def __init__(self):
|
|
173
|
+
self.reports_created = 0
|
|
174
|
+
|
|
175
|
+
class PDFReport:
|
|
176
|
+
"""Nested class for PDF reports."""
|
|
177
|
+
|
|
178
|
+
def __init__(self, title: str):
|
|
179
|
+
self.title = title
|
|
180
|
+
|
|
181
|
+
def generate(self, data: dict) -> bytes:
|
|
182
|
+
"""Generate PDF from data."""
|
|
183
|
+
return b"PDF content"
|
|
184
|
+
|
|
185
|
+
class Metadata:
|
|
186
|
+
"""Metadata for PDF reports."""
|
|
187
|
+
|
|
188
|
+
def __init__(self, author: str):
|
|
189
|
+
self.author = author
|
|
190
|
+
|
|
191
|
+
class CSVReport:
|
|
192
|
+
"""Nested class for CSV reports."""
|
|
193
|
+
|
|
194
|
+
def __init__(self, delimiter: str = ','):
|
|
195
|
+
self.delimiter = delimiter
|
|
196
|
+
|
|
197
|
+
def generate(self, data: list) -> str:
|
|
198
|
+
"""Generate CSV from data."""
|
|
199
|
+
return "CSV content"
|
|
200
|
+
|
|
201
|
+
def create_pdf_report(self, title: str):
|
|
202
|
+
"""Create a PDF report instance."""
|
|
203
|
+
return self.PDFReport(title)
|
|
204
|
+
|
|
205
|
+
def outer_function():
|
|
206
|
+
"""Function with nested functions."""
|
|
207
|
+
|
|
208
|
+
def inner_function(x: int) -> int:
|
|
209
|
+
"""Inner function."""
|
|
210
|
+
return x * 2
|
|
211
|
+
|
|
212
|
+
def another_inner() -> str:
|
|
213
|
+
"""Another inner function."""
|
|
214
|
+
return "inner"
|
|
215
|
+
|
|
216
|
+
return inner_function, another_inner
|
|
217
|
+
"#;
|
|
218
|
+
|
|
219
|
+
fs::write(&test_file, content)?;
|
|
220
|
+
|
|
221
|
+
let ctx = TestContext::new();
|
|
222
|
+
let output = ctx.run_probe(&[
|
|
223
|
+
"search",
|
|
224
|
+
"def|class", // Search for Python functions and classes
|
|
225
|
+
test_file.to_str().unwrap(),
|
|
226
|
+
"--format",
|
|
227
|
+
"outline",
|
|
228
|
+
"--max-results",
|
|
229
|
+
"20",
|
|
230
|
+
"--allow-tests",
|
|
231
|
+
])?;
|
|
232
|
+
|
|
233
|
+
// Verify top-level structures are shown (be flexible)
|
|
234
|
+
let has_report_generator = output.contains("ReportGenerator") || output.contains("class");
|
|
235
|
+
let has_outer_function = output.contains("outer_function") || output.contains("def");
|
|
236
|
+
|
|
237
|
+
assert!(
|
|
238
|
+
has_report_generator,
|
|
239
|
+
"Missing ReportGenerator class or similar - output: {}",
|
|
240
|
+
output
|
|
241
|
+
);
|
|
242
|
+
assert!(
|
|
243
|
+
has_outer_function,
|
|
244
|
+
"Missing outer function or similar - output: {}",
|
|
245
|
+
output
|
|
246
|
+
);
|
|
247
|
+
// Nested classes (PDFReport, CSVReport, Metadata) are not shown individually in outline format
|
|
248
|
+
// They are inside ReportGenerator and outline format only shows top-level structures
|
|
249
|
+
assert!(
|
|
250
|
+
output.contains("..."),
|
|
251
|
+
"Missing ellipsis in outline format - output: {}",
|
|
252
|
+
output
|
|
253
|
+
);
|
|
254
|
+
|
|
255
|
+
Ok(())
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
#[test]
|
|
259
|
+
fn test_python_outline_docstrings_and_comments() -> Result<()> {
|
|
260
|
+
let temp_dir = TempDir::new()?;
|
|
261
|
+
let test_file = temp_dir.path().join("docstrings.py");
|
|
262
|
+
|
|
263
|
+
let content = r#"# Single line comment
|
|
264
|
+
def function_with_single_quotes():
|
|
265
|
+
'''Function with single quote docstring.
|
|
266
|
+
|
|
267
|
+
This tests parsing of single quote docstrings.
|
|
268
|
+
'''
|
|
269
|
+
# Internal comment
|
|
270
|
+
return "result"
|
|
271
|
+
|
|
272
|
+
def function_with_double_quotes():
|
|
273
|
+
"""Function with double quote docstring.
|
|
274
|
+
|
|
275
|
+
This tests parsing of double quote docstrings.
|
|
276
|
+
"""
|
|
277
|
+
return "result"
|
|
278
|
+
|
|
279
|
+
def function_with_raw_docstring():
|
|
280
|
+
r"""Raw docstring with backslashes: \n\t\r
|
|
281
|
+
|
|
282
|
+
This is a raw string docstring.
|
|
283
|
+
"""
|
|
284
|
+
return "result"
|
|
285
|
+
|
|
286
|
+
class DocumentedClass:
|
|
287
|
+
"""Class with comprehensive docstring.
|
|
288
|
+
|
|
289
|
+
Attributes:
|
|
290
|
+
name: The name of the object
|
|
291
|
+
value: The numeric value
|
|
292
|
+
|
|
293
|
+
Examples:
|
|
294
|
+
>>> obj = DocumentedClass("test", 42)
|
|
295
|
+
>>> obj.name
|
|
296
|
+
'test'
|
|
297
|
+
"""
|
|
298
|
+
|
|
299
|
+
def __init__(self, name: str, value: int):
|
|
300
|
+
self.name = name # Name comment
|
|
301
|
+
self.value = value # Value comment
|
|
302
|
+
|
|
303
|
+
def method_with_docstring(self):
|
|
304
|
+
"""Method with proper docstring.
|
|
305
|
+
|
|
306
|
+
Returns:
|
|
307
|
+
str: A formatted string
|
|
308
|
+
"""
|
|
309
|
+
return f"{self.name}: {self.value}"
|
|
310
|
+
|
|
311
|
+
# Comment above function
|
|
312
|
+
def test_docstring_parsing():
|
|
313
|
+
"""Test that docstrings are preserved in outline."""
|
|
314
|
+
obj = DocumentedClass("test", 42)
|
|
315
|
+
assert obj.method_with_docstring() == "test: 42"
|
|
316
|
+
"#;
|
|
317
|
+
|
|
318
|
+
fs::write(&test_file, content)?;
|
|
319
|
+
|
|
320
|
+
let ctx = TestContext::new();
|
|
321
|
+
let output = ctx.run_probe(&[
|
|
322
|
+
"search",
|
|
323
|
+
"def|class", // Search for Python functions and classes
|
|
324
|
+
test_file.to_str().unwrap(),
|
|
325
|
+
"--format",
|
|
326
|
+
"outline",
|
|
327
|
+
"--max-results",
|
|
328
|
+
"20",
|
|
329
|
+
"--allow-tests",
|
|
330
|
+
])?;
|
|
331
|
+
|
|
332
|
+
// Verify functions and classes are shown (be flexible)
|
|
333
|
+
let has_functions = output.contains("function_with") || output.contains("def");
|
|
334
|
+
let has_documented_class = output.contains("DocumentedClass") || output.contains("class");
|
|
335
|
+
let has_test = output.contains("test_docstring") || output.contains("test");
|
|
336
|
+
|
|
337
|
+
assert!(
|
|
338
|
+
has_functions,
|
|
339
|
+
"Missing functions with docstrings or similar - output: {}",
|
|
340
|
+
output
|
|
341
|
+
);
|
|
342
|
+
assert!(
|
|
343
|
+
has_documented_class,
|
|
344
|
+
"Missing documented class or similar - output: {}",
|
|
345
|
+
output
|
|
346
|
+
);
|
|
347
|
+
assert!(
|
|
348
|
+
has_test,
|
|
349
|
+
"Missing test function or similar - output: {}",
|
|
350
|
+
output
|
|
351
|
+
);
|
|
352
|
+
|
|
353
|
+
Ok(())
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
#[test]
|
|
357
|
+
fn test_python_outline_complex_signatures() -> Result<()> {
|
|
358
|
+
let temp_dir = TempDir::new()?;
|
|
359
|
+
let test_file = temp_dir.path().join("complex_signatures.py");
|
|
360
|
+
|
|
361
|
+
let content = r#"from typing import List, Dict, Optional, Union, Callable, AsyncIterator
|
|
362
|
+
from dataclasses import dataclass
|
|
363
|
+
|
|
364
|
+
@dataclass
|
|
365
|
+
class Config:
|
|
366
|
+
name: str
|
|
367
|
+
value: int = 0
|
|
368
|
+
|
|
369
|
+
def simple_function(x: int, y: int) -> int:
|
|
370
|
+
"""Simple function signature."""
|
|
371
|
+
return x + y
|
|
372
|
+
|
|
373
|
+
def function_with_defaults(
|
|
374
|
+
name: str,
|
|
375
|
+
age: int = 25,
|
|
376
|
+
city: str = "Unknown",
|
|
377
|
+
*args,
|
|
378
|
+
**kwargs
|
|
379
|
+
) -> Dict[str, Union[str, int]]:
|
|
380
|
+
"""Function with default parameters and var args."""
|
|
381
|
+
return {"name": name, "age": age, "city": city}
|
|
382
|
+
|
|
383
|
+
async def async_function_complex(
|
|
384
|
+
data: List[Dict[str, Union[str, int]]],
|
|
385
|
+
processor: Callable[[Dict], Dict],
|
|
386
|
+
*,
|
|
387
|
+
batch_size: int = 10,
|
|
388
|
+
timeout: float = 30.0,
|
|
389
|
+
validate: bool = True
|
|
390
|
+
) -> AsyncIterator[Dict]:
|
|
391
|
+
"""Async function with complex type hints and keyword-only args."""
|
|
392
|
+
for item in data:
|
|
393
|
+
yield processor(item)
|
|
394
|
+
|
|
395
|
+
def function_multiline_signature(
|
|
396
|
+
matrix_a: List[List[float]],
|
|
397
|
+
matrix_b: List[List[float]],
|
|
398
|
+
precision: int = 10,
|
|
399
|
+
validate_dimensions: bool = True,
|
|
400
|
+
output_format: str = "list"
|
|
401
|
+
) -> Union[List[List[float]], str]:
|
|
402
|
+
"""Function with multiline signature."""
|
|
403
|
+
return [[0.0]]
|
|
404
|
+
|
|
405
|
+
class GenericProcessor:
|
|
406
|
+
"""Class with complex method signatures."""
|
|
407
|
+
|
|
408
|
+
def __init__(
|
|
409
|
+
self,
|
|
410
|
+
name: str,
|
|
411
|
+
config: Optional[Config] = None,
|
|
412
|
+
processors: List[Callable] = None
|
|
413
|
+
):
|
|
414
|
+
self.name = name
|
|
415
|
+
self.config = config or Config("default")
|
|
416
|
+
self.processors = processors or []
|
|
417
|
+
|
|
418
|
+
async def process_batch(
|
|
419
|
+
self,
|
|
420
|
+
items: List[Dict[str, Union[str, int, float]]],
|
|
421
|
+
*,
|
|
422
|
+
parallel: bool = True,
|
|
423
|
+
max_workers: int = 4,
|
|
424
|
+
timeout_per_item: float = 1.0
|
|
425
|
+
) -> List[Optional[Dict]]:
|
|
426
|
+
"""Process items in batch with complex parameters."""
|
|
427
|
+
return [{"processed": True} for _ in items]
|
|
428
|
+
|
|
429
|
+
@classmethod
|
|
430
|
+
def from_config_file(
|
|
431
|
+
cls,
|
|
432
|
+
config_path: str,
|
|
433
|
+
overrides: Optional[Dict[str, Union[str, int]]] = None
|
|
434
|
+
) -> 'GenericProcessor':
|
|
435
|
+
"""Create processor from config file."""
|
|
436
|
+
return cls("from_config")
|
|
437
|
+
|
|
438
|
+
def test_complex_signatures():
|
|
439
|
+
"""Test complex function signature parsing."""
|
|
440
|
+
processor = GenericProcessor.from_config_file("config.json")
|
|
441
|
+
assert processor.name == "from_config"
|
|
442
|
+
"#;
|
|
443
|
+
|
|
444
|
+
fs::write(&test_file, content)?;
|
|
445
|
+
|
|
446
|
+
let ctx = TestContext::new();
|
|
447
|
+
let output = ctx.run_probe(&[
|
|
448
|
+
"search",
|
|
449
|
+
"def|class", // Search for Python functions and classes
|
|
450
|
+
test_file.to_str().unwrap(),
|
|
451
|
+
"--format",
|
|
452
|
+
"outline",
|
|
453
|
+
"--max-results",
|
|
454
|
+
"20",
|
|
455
|
+
"--allow-tests",
|
|
456
|
+
])?;
|
|
457
|
+
|
|
458
|
+
// Verify top-level complex signatures are preserved (be flexible)
|
|
459
|
+
let has_defaults_function = output.contains("function_with_defaults") || output.contains("def");
|
|
460
|
+
let has_async_function = output.contains("async_function_complex") || output.contains("async");
|
|
461
|
+
let has_multiline_function = output.contains("multiline_signature") || output.contains("def");
|
|
462
|
+
let has_generic_processor = output.contains("GenericProcessor") || output.contains("class");
|
|
463
|
+
|
|
464
|
+
assert!(
|
|
465
|
+
has_defaults_function,
|
|
466
|
+
"Missing function with defaults or similar - output: {}",
|
|
467
|
+
output
|
|
468
|
+
);
|
|
469
|
+
assert!(
|
|
470
|
+
has_async_function,
|
|
471
|
+
"Missing async function or similar - output: {}",
|
|
472
|
+
output
|
|
473
|
+
);
|
|
474
|
+
assert!(
|
|
475
|
+
has_multiline_function,
|
|
476
|
+
"Missing multiline signature function or similar - output: {}",
|
|
477
|
+
output
|
|
478
|
+
);
|
|
479
|
+
assert!(
|
|
480
|
+
has_generic_processor,
|
|
481
|
+
"Missing GenericProcessor class or similar - output: {}",
|
|
482
|
+
output
|
|
483
|
+
);
|
|
484
|
+
// Methods inside classes (like async process_batch) are not shown individually in outline format
|
|
485
|
+
assert!(
|
|
486
|
+
output.contains("..."),
|
|
487
|
+
"Missing ellipsis in outline format - output: {}",
|
|
488
|
+
output
|
|
489
|
+
);
|
|
490
|
+
|
|
491
|
+
Ok(())
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
#[test]
|
|
495
|
+
fn test_python_outline_test_patterns() -> Result<()> {
|
|
496
|
+
let temp_dir = TempDir::new()?;
|
|
497
|
+
let test_file = temp_dir.path().join("test_patterns.py");
|
|
498
|
+
|
|
499
|
+
let content = r#"import unittest
|
|
500
|
+
import pytest
|
|
501
|
+
from unittest.mock import Mock, patch
|
|
502
|
+
|
|
503
|
+
class TestUserManager(unittest.TestCase):
|
|
504
|
+
"""Unit tests for UserManager using unittest."""
|
|
505
|
+
|
|
506
|
+
def setUp(self):
|
|
507
|
+
"""Set up test fixtures."""
|
|
508
|
+
self.user_manager = UserManager()
|
|
509
|
+
|
|
510
|
+
def tearDown(self):
|
|
511
|
+
"""Clean up after tests."""
|
|
512
|
+
self.user_manager = None
|
|
513
|
+
|
|
514
|
+
def test_add_user(self):
|
|
515
|
+
"""Test adding a user."""
|
|
516
|
+
result = self.user_manager.add_user("John", "john@example.com")
|
|
517
|
+
self.assertTrue(result)
|
|
518
|
+
|
|
519
|
+
def test_get_user_not_found(self):
|
|
520
|
+
"""Test getting non-existent user."""
|
|
521
|
+
user = self.user_manager.get_user(999)
|
|
522
|
+
self.assertIsNone(user)
|
|
523
|
+
|
|
524
|
+
@patch('requests.get')
|
|
525
|
+
def test_fetch_user_data(self, mock_get):
|
|
526
|
+
"""Test fetching user data with mocked requests."""
|
|
527
|
+
mock_get.return_value.json.return_value = {"id": 1, "name": "Test"}
|
|
528
|
+
result = self.user_manager.fetch_user_data(1)
|
|
529
|
+
self.assertEqual(result["name"], "Test")
|
|
530
|
+
|
|
531
|
+
# Pytest-style tests
|
|
532
|
+
def test_simple_calculation():
|
|
533
|
+
"""Simple pytest test."""
|
|
534
|
+
assert 2 + 2 == 4
|
|
535
|
+
|
|
536
|
+
def test_string_operations():
|
|
537
|
+
"""Test string operations."""
|
|
538
|
+
text = "Hello World"
|
|
539
|
+
assert text.lower() == "hello world"
|
|
540
|
+
assert len(text) == 11
|
|
541
|
+
|
|
542
|
+
@pytest.mark.parametrize("input,expected", [
|
|
543
|
+
(1, 2),
|
|
544
|
+
(2, 4),
|
|
545
|
+
(3, 6),
|
|
546
|
+
])
|
|
547
|
+
def test_double_function(input, expected):
|
|
548
|
+
"""Parametrized test for doubling function."""
|
|
549
|
+
assert double(input) == expected
|
|
550
|
+
|
|
551
|
+
@pytest.mark.asyncio
|
|
552
|
+
async def test_async_operation():
|
|
553
|
+
"""Test async operation with pytest."""
|
|
554
|
+
result = await some_async_function()
|
|
555
|
+
assert result is not None
|
|
556
|
+
|
|
557
|
+
@pytest.fixture
|
|
558
|
+
def sample_data():
|
|
559
|
+
"""Pytest fixture providing sample data."""
|
|
560
|
+
return {"name": "Test", "value": 42}
|
|
561
|
+
|
|
562
|
+
def test_with_fixture(sample_data):
|
|
563
|
+
"""Test using pytest fixture."""
|
|
564
|
+
assert sample_data["name"] == "Test"
|
|
565
|
+
assert sample_data["value"] == 42
|
|
566
|
+
|
|
567
|
+
class TestIntegration:
|
|
568
|
+
"""Pytest-style test class."""
|
|
569
|
+
|
|
570
|
+
@classmethod
|
|
571
|
+
def setup_class(cls):
|
|
572
|
+
"""Setup for test class."""
|
|
573
|
+
cls.global_config = {}
|
|
574
|
+
|
|
575
|
+
def setup_method(self):
|
|
576
|
+
"""Setup for each test method."""
|
|
577
|
+
self.test_data = []
|
|
578
|
+
|
|
579
|
+
def test_integration_scenario_one(self):
|
|
580
|
+
"""Integration test scenario."""
|
|
581
|
+
assert True
|
|
582
|
+
|
|
583
|
+
def test_integration_scenario_two(self):
|
|
584
|
+
"""Another integration test scenario."""
|
|
585
|
+
assert len(self.test_data) == 0
|
|
586
|
+
|
|
587
|
+
# Test helper functions
|
|
588
|
+
def create_test_user(name: str = "Test User", email: str = "test@example.com"):
|
|
589
|
+
"""Helper function to create test users."""
|
|
590
|
+
return {"name": name, "email": email}
|
|
591
|
+
|
|
592
|
+
def assert_user_valid(user: dict):
|
|
593
|
+
"""Helper function to validate user data."""
|
|
594
|
+
assert "name" in user
|
|
595
|
+
assert "email" in user
|
|
596
|
+
assert "@" in user["email"]
|
|
597
|
+
|
|
598
|
+
# Performance test
|
|
599
|
+
def test_performance_large_dataset():
|
|
600
|
+
"""Test performance with large dataset."""
|
|
601
|
+
data = list(range(10000))
|
|
602
|
+
result = process_large_dataset(data)
|
|
603
|
+
assert len(result) == 10000
|
|
604
|
+
"#;
|
|
605
|
+
|
|
606
|
+
fs::write(&test_file, content)?;
|
|
607
|
+
|
|
608
|
+
let ctx = TestContext::new();
|
|
609
|
+
let output = ctx.run_probe(&[
|
|
610
|
+
"search",
|
|
611
|
+
"def|class", // Search for Python functions and classes
|
|
612
|
+
test_file.to_str().unwrap(),
|
|
613
|
+
"--format",
|
|
614
|
+
"outline",
|
|
615
|
+
"--max-results",
|
|
616
|
+
"20",
|
|
617
|
+
"--allow-tests",
|
|
618
|
+
])?;
|
|
619
|
+
|
|
620
|
+
// Verify test patterns are detected (be flexible)
|
|
621
|
+
let has_unittest_class = output.contains("TestUserManager")
|
|
622
|
+
|| output.contains("TestCase")
|
|
623
|
+
|| output.contains("unittest");
|
|
624
|
+
let has_pytest_function = output.contains("test_simple_calculation")
|
|
625
|
+
|| output.contains("test_")
|
|
626
|
+
|| output.contains("def test");
|
|
627
|
+
let has_pytest_class = output.contains("TestIntegration") || output.contains("class Test");
|
|
628
|
+
|
|
629
|
+
assert!(
|
|
630
|
+
has_unittest_class,
|
|
631
|
+
"Missing unittest test class or similar - output: {}",
|
|
632
|
+
output
|
|
633
|
+
);
|
|
634
|
+
assert!(
|
|
635
|
+
has_pytest_function,
|
|
636
|
+
"Missing pytest test function or similar - output: {}",
|
|
637
|
+
output
|
|
638
|
+
);
|
|
639
|
+
assert!(
|
|
640
|
+
has_pytest_class,
|
|
641
|
+
"Missing pytest test class or similar - output: {}",
|
|
642
|
+
output
|
|
643
|
+
);
|
|
644
|
+
assert!(
|
|
645
|
+
output.contains("..."),
|
|
646
|
+
"Missing ellipsis in outline format - output: {}",
|
|
647
|
+
output
|
|
648
|
+
);
|
|
649
|
+
|
|
650
|
+
Ok(())
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
#[test]
|
|
654
|
+
fn test_python_outline_edge_cases() -> Result<()> {
|
|
655
|
+
let temp_dir = TempDir::new()?;
|
|
656
|
+
let test_file = temp_dir.path().join("edge_cases.py");
|
|
657
|
+
|
|
658
|
+
let content = r#"# -*- coding: utf-8 -*-
|
|
659
|
+
"""Module with edge cases for Python parsing."""
|
|
660
|
+
|
|
661
|
+
# Lambda functions (should not be extracted as symbols)
|
|
662
|
+
add = lambda x, y: x + y
|
|
663
|
+
multiply = lambda x, y: x * y
|
|
664
|
+
|
|
665
|
+
# Complex expressions (should not be symbols)
|
|
666
|
+
COMPLEX_CONFIG = {
|
|
667
|
+
'key': 'value',
|
|
668
|
+
'nested': {
|
|
669
|
+
'inner': [1, 2, 3]
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
# List comprehension assigned to variable
|
|
674
|
+
PROCESSED_DATA = [x * 2 for x in range(10) if x % 2 == 0]
|
|
675
|
+
|
|
676
|
+
# Generator expression
|
|
677
|
+
data_gen = (x for x in range(100) if x > 50)
|
|
678
|
+
|
|
679
|
+
class EmptyClass:
|
|
680
|
+
"""Class with only pass statement."""
|
|
681
|
+
pass
|
|
682
|
+
|
|
683
|
+
class ClassWithOnlyProperties:
|
|
684
|
+
"""Class containing only properties."""
|
|
685
|
+
|
|
686
|
+
@property
|
|
687
|
+
def readonly_value(self):
|
|
688
|
+
"""A read-only property."""
|
|
689
|
+
return 42
|
|
690
|
+
|
|
691
|
+
@property
|
|
692
|
+
def name(self):
|
|
693
|
+
"""Name property getter."""
|
|
694
|
+
return self._name
|
|
695
|
+
|
|
696
|
+
@name.setter
|
|
697
|
+
def name(self, value):
|
|
698
|
+
"""Name property setter."""
|
|
699
|
+
self._name = value
|
|
700
|
+
|
|
701
|
+
def function_with_only_pass():
|
|
702
|
+
"""Function with only pass statement."""
|
|
703
|
+
pass
|
|
704
|
+
|
|
705
|
+
def function_with_nested_definitions():
|
|
706
|
+
"""Function containing nested class and function."""
|
|
707
|
+
|
|
708
|
+
class LocalClass:
|
|
709
|
+
"""Class defined inside function."""
|
|
710
|
+
|
|
711
|
+
def local_method(self):
|
|
712
|
+
"""Method in local class."""
|
|
713
|
+
return "local"
|
|
714
|
+
|
|
715
|
+
def local_function():
|
|
716
|
+
"""Function defined inside function."""
|
|
717
|
+
return LocalClass()
|
|
718
|
+
|
|
719
|
+
return local_function()
|
|
720
|
+
|
|
721
|
+
# Very long function name
|
|
722
|
+
def function_with_extremely_long_name_that_might_cause_parsing_issues_in_outline_format():
|
|
723
|
+
"""Function with very long name."""
|
|
724
|
+
return "long name"
|
|
725
|
+
|
|
726
|
+
# Function with unicode in name (Python 3 supports this)
|
|
727
|
+
def функция_с_unicode_именем():
|
|
728
|
+
"""Function with unicode characters in name."""
|
|
729
|
+
return "unicode"
|
|
730
|
+
|
|
731
|
+
# Async generators
|
|
732
|
+
async def async_generator_function():
|
|
733
|
+
"""Async generator function."""
|
|
734
|
+
for i in range(10):
|
|
735
|
+
yield i
|
|
736
|
+
|
|
737
|
+
# Context manager class
|
|
738
|
+
class CustomContextManager:
|
|
739
|
+
"""Custom context manager."""
|
|
740
|
+
|
|
741
|
+
def __enter__(self):
|
|
742
|
+
return self
|
|
743
|
+
|
|
744
|
+
def __exit__(self, exc_type, exc_val, exc_tb):
|
|
745
|
+
return False
|
|
746
|
+
|
|
747
|
+
# Metaclass
|
|
748
|
+
class MetaClass(type):
|
|
749
|
+
"""A simple metaclass."""
|
|
750
|
+
|
|
751
|
+
def __new__(cls, name, bases, attrs):
|
|
752
|
+
return super().__new__(cls, name, bases, attrs)
|
|
753
|
+
|
|
754
|
+
class ClassWithMetaclass(metaclass=MetaClass):
|
|
755
|
+
"""Class using custom metaclass."""
|
|
756
|
+
|
|
757
|
+
def method(self):
|
|
758
|
+
"""Method in metaclass-created class."""
|
|
759
|
+
return "metaclass method"
|
|
760
|
+
|
|
761
|
+
def test_edge_case_parsing():
|
|
762
|
+
"""Test parsing of edge cases."""
|
|
763
|
+
obj = ClassWithMetaclass()
|
|
764
|
+
assert obj.method() == "metaclass method"
|
|
765
|
+
|
|
766
|
+
# Test with unusual indentation (mixed tabs and spaces - should be handled)
|
|
767
|
+
def test_indentation_edge_case():
|
|
768
|
+
"""Test with mixed indentation."""
|
|
769
|
+
# This line uses a tab
|
|
770
|
+
# This line uses spaces
|
|
771
|
+
assert True
|
|
772
|
+
"#;
|
|
773
|
+
|
|
774
|
+
fs::write(&test_file, content)?;
|
|
775
|
+
|
|
776
|
+
let ctx = TestContext::new();
|
|
777
|
+
let output = ctx.run_probe(&[
|
|
778
|
+
"search",
|
|
779
|
+
"def|class", // Search for Python functions and classes
|
|
780
|
+
test_file.to_str().unwrap(),
|
|
781
|
+
"--format",
|
|
782
|
+
"outline",
|
|
783
|
+
"--max-results",
|
|
784
|
+
"20",
|
|
785
|
+
"--allow-tests",
|
|
786
|
+
])?;
|
|
787
|
+
|
|
788
|
+
// Verify edge cases are handled correctly (be flexible)
|
|
789
|
+
let has_empty_class = output.contains("EmptyClass") || output.contains("class");
|
|
790
|
+
let has_properties_class =
|
|
791
|
+
output.contains("ClassWithOnlyProperties") || output.contains("property");
|
|
792
|
+
let has_pass_function = output.contains("function_with_only_pass") || output.contains("def");
|
|
793
|
+
let has_nested_function =
|
|
794
|
+
output.contains("function_with_nested_definitions") || output.contains("nested");
|
|
795
|
+
let has_async_generator =
|
|
796
|
+
output.contains("async_generator_function") || output.contains("async");
|
|
797
|
+
let has_metaclass = output.contains("MetaClass") || output.contains("metaclass");
|
|
798
|
+
|
|
799
|
+
assert!(
|
|
800
|
+
has_empty_class,
|
|
801
|
+
"Missing empty class or similar - output: {}",
|
|
802
|
+
output
|
|
803
|
+
);
|
|
804
|
+
assert!(
|
|
805
|
+
has_properties_class || has_pass_function || has_nested_function,
|
|
806
|
+
"Missing functions/classes with various structures - output: {}",
|
|
807
|
+
output
|
|
808
|
+
);
|
|
809
|
+
assert!(
|
|
810
|
+
has_async_generator || has_metaclass,
|
|
811
|
+
"Missing advanced Python features - output: {}",
|
|
812
|
+
output
|
|
813
|
+
);
|
|
814
|
+
|
|
815
|
+
// Lambda functions should NOT be extracted as symbols
|
|
816
|
+
assert!(
|
|
817
|
+
!output.contains("lambda"),
|
|
818
|
+
"Lambda functions should not be symbols - output: {}",
|
|
819
|
+
output
|
|
820
|
+
);
|
|
821
|
+
|
|
822
|
+
Ok(())
|
|
823
|
+
}
|
|
824
|
+
|
|
825
|
+
#[test]
|
|
826
|
+
fn test_python_outline_search_command() -> Result<()> {
|
|
827
|
+
let temp_dir = TempDir::new()?;
|
|
828
|
+
let test_file = temp_dir.path().join("search_test.py");
|
|
829
|
+
|
|
830
|
+
let content = r#"class DataProcessor:
|
|
831
|
+
"""Process various types of data."""
|
|
832
|
+
|
|
833
|
+
def __init__(self):
|
|
834
|
+
self.processed_count = 0
|
|
835
|
+
|
|
836
|
+
def process_data(self, data: list) -> list:
|
|
837
|
+
"""Process input data."""
|
|
838
|
+
self.processed_count += 1
|
|
839
|
+
return [item for item in data if item]
|
|
840
|
+
|
|
841
|
+
def get_processed_count(self) -> int:
|
|
842
|
+
"""Get number of processed items."""
|
|
843
|
+
return self.processed_count
|
|
844
|
+
|
|
845
|
+
def process_file(filename: str) -> str:
|
|
846
|
+
"""Process a file."""
|
|
847
|
+
return f"Processed {filename}"
|
|
848
|
+
|
|
849
|
+
async def process_async(data: dict) -> dict:
|
|
850
|
+
"""Process data asynchronously."""
|
|
851
|
+
return {"processed": True, **data}
|
|
852
|
+
|
|
853
|
+
def test_data_processing():
|
|
854
|
+
"""Test data processing functionality."""
|
|
855
|
+
processor = DataProcessor()
|
|
856
|
+
result = processor.process_data([1, 2, None, 3])
|
|
857
|
+
assert len(result) == 3
|
|
858
|
+
"#;
|
|
859
|
+
|
|
860
|
+
fs::write(&test_file, content)?;
|
|
861
|
+
|
|
862
|
+
let ctx = TestContext::new();
|
|
863
|
+
let output = ctx.run_probe(&[
|
|
864
|
+
"search",
|
|
865
|
+
"process", // Search for functions containing 'process'
|
|
866
|
+
temp_dir.path().to_str().unwrap(),
|
|
867
|
+
"--format",
|
|
868
|
+
"outline",
|
|
869
|
+
"--allow-tests",
|
|
870
|
+
])?;
|
|
871
|
+
|
|
872
|
+
// Should find symbols containing "process"
|
|
873
|
+
assert!(
|
|
874
|
+
output.contains("DataProcessor")
|
|
875
|
+
|| output.contains("process_data")
|
|
876
|
+
|| output.contains("process_file")
|
|
877
|
+
|| output.contains("process_async"),
|
|
878
|
+
"Should find process-related symbols - output: {}",
|
|
879
|
+
output
|
|
880
|
+
);
|
|
881
|
+
|
|
882
|
+
Ok(())
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
#[test]
|
|
886
|
+
fn test_python_outline_multiline_docstrings() -> Result<()> {
|
|
887
|
+
let temp_dir = TempDir::new()?;
|
|
888
|
+
let test_file = temp_dir.path().join("multiline_docstrings.py");
|
|
889
|
+
|
|
890
|
+
let content = r#"def function_with_long_docstring():
|
|
891
|
+
"""This is a function with a very long docstring.
|
|
892
|
+
|
|
893
|
+
The docstring spans multiple lines and contains detailed
|
|
894
|
+
information about the function's behavior, parameters,
|
|
895
|
+
return values, and examples.
|
|
896
|
+
|
|
897
|
+
Args:
|
|
898
|
+
None
|
|
899
|
+
|
|
900
|
+
Returns:
|
|
901
|
+
str: A simple string value
|
|
902
|
+
|
|
903
|
+
Examples:
|
|
904
|
+
>>> result = function_with_long_docstring()
|
|
905
|
+
>>> print(result)
|
|
906
|
+
'Hello from long docstring function'
|
|
907
|
+
|
|
908
|
+
Note:
|
|
909
|
+
This function demonstrates how multiline docstrings
|
|
910
|
+
should be handled in the outline format.
|
|
911
|
+
"""
|
|
912
|
+
return "Hello from long docstring function"
|
|
913
|
+
|
|
914
|
+
class ClassWithLongDocstring:
|
|
915
|
+
"""This is a class with a comprehensive docstring.
|
|
916
|
+
|
|
917
|
+
The class demonstrates various Python features and shows
|
|
918
|
+
how the outline format should handle classes with extensive
|
|
919
|
+
documentation.
|
|
920
|
+
|
|
921
|
+
Attributes:
|
|
922
|
+
name (str): The name of the instance
|
|
923
|
+
value (int): A numeric value
|
|
924
|
+
items (list): A list of items
|
|
925
|
+
|
|
926
|
+
Methods:
|
|
927
|
+
get_info(): Returns formatted information
|
|
928
|
+
process(data): Processes input data
|
|
929
|
+
|
|
930
|
+
Examples:
|
|
931
|
+
>>> obj = ClassWithLongDocstring("test", 42)
|
|
932
|
+
>>> info = obj.get_info()
|
|
933
|
+
>>> print(info)
|
|
934
|
+
'Name: test, Value: 42'
|
|
935
|
+
|
|
936
|
+
Raises:
|
|
937
|
+
ValueError: If invalid parameters are provided
|
|
938
|
+
TypeError: If wrong types are used
|
|
939
|
+
"""
|
|
940
|
+
|
|
941
|
+
def __init__(self, name: str, value: int):
|
|
942
|
+
"""Initialize the class instance.
|
|
943
|
+
|
|
944
|
+
Args:
|
|
945
|
+
name: The name for this instance
|
|
946
|
+
value: A numeric value to store
|
|
947
|
+
"""
|
|
948
|
+
self.name = name
|
|
949
|
+
self.value = value
|
|
950
|
+
self.items = []
|
|
951
|
+
|
|
952
|
+
def get_info(self) -> str:
|
|
953
|
+
"""Get formatted information about this instance.
|
|
954
|
+
|
|
955
|
+
Returns:
|
|
956
|
+
A formatted string containing name and value
|
|
957
|
+
"""
|
|
958
|
+
return f"Name: {self.name}, Value: {self.value}"
|
|
959
|
+
"#;
|
|
960
|
+
|
|
961
|
+
fs::write(&test_file, content)?;
|
|
962
|
+
|
|
963
|
+
let ctx = TestContext::new();
|
|
964
|
+
let output = ctx.run_probe(&[
|
|
965
|
+
"search",
|
|
966
|
+
"def|class", // Search for Python functions and classes
|
|
967
|
+
test_file.to_str().unwrap(),
|
|
968
|
+
"--format",
|
|
969
|
+
"outline",
|
|
970
|
+
"--max-results",
|
|
971
|
+
"20",
|
|
972
|
+
"--allow-tests",
|
|
973
|
+
])?;
|
|
974
|
+
|
|
975
|
+
// Verify top-level symbols are extracted - outline format shows only top-level structures
|
|
976
|
+
assert!(
|
|
977
|
+
output.contains("def function_with_long_docstring():"),
|
|
978
|
+
"Missing function with long docstring - output: {}",
|
|
979
|
+
output
|
|
980
|
+
);
|
|
981
|
+
assert!(
|
|
982
|
+
output.contains("class ClassWithLongDocstring:"),
|
|
983
|
+
"Missing class with long docstring - output: {}",
|
|
984
|
+
output
|
|
985
|
+
);
|
|
986
|
+
// Methods inside classes (like get_info) are not shown individually in outline format
|
|
987
|
+
assert!(
|
|
988
|
+
output.contains("..."),
|
|
989
|
+
"Missing ellipsis in outline format - output: {}",
|
|
990
|
+
output
|
|
991
|
+
);
|
|
992
|
+
|
|
993
|
+
Ok(())
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
#[test]
|
|
997
|
+
fn test_python_outline_smart_closing_brace_comments() -> Result<()> {
|
|
998
|
+
let temp_dir = TempDir::new()?;
|
|
999
|
+
let test_file = temp_dir.path().join("smart_braces.py");
|
|
1000
|
+
|
|
1001
|
+
let content = r#"def small_function(x: int) -> int:
|
|
1002
|
+
"""Small function that should NOT get closing brace comments."""
|
|
1003
|
+
result = x * 2
|
|
1004
|
+
return result + 1
|
|
1005
|
+
|
|
1006
|
+
def large_function_with_gaps(data: list) -> list:
|
|
1007
|
+
"""Large function that SHOULD get closing brace comments when there are gaps."""
|
|
1008
|
+
results = []
|
|
1009
|
+
processor = DataProcessor()
|
|
1010
|
+
|
|
1011
|
+
# First processing phase
|
|
1012
|
+
for item in data:
|
|
1013
|
+
if item is not None:
|
|
1014
|
+
processed_item = processor.process(item)
|
|
1015
|
+
if processed_item:
|
|
1016
|
+
results.append(processed_item)
|
|
1017
|
+
|
|
1018
|
+
# Second processing phase with validation
|
|
1019
|
+
validated_results = []
|
|
1020
|
+
for result in results:
|
|
1021
|
+
try:
|
|
1022
|
+
if validate_data(result):
|
|
1023
|
+
validated_results.append(result)
|
|
1024
|
+
except ValidationError as e:
|
|
1025
|
+
logger.warning(f"Validation failed for {result}: {e}")
|
|
1026
|
+
|
|
1027
|
+
# Final cleanup and formatting
|
|
1028
|
+
final_results = []
|
|
1029
|
+
for validated in validated_results:
|
|
1030
|
+
formatted = format_result(validated)
|
|
1031
|
+
final_results.append(formatted)
|
|
1032
|
+
|
|
1033
|
+
return final_results
|
|
1034
|
+
|
|
1035
|
+
def another_large_function(matrix: list) -> dict:
|
|
1036
|
+
"""Another large function with nested control structures."""
|
|
1037
|
+
summary = {"processed": 0, "errors": 0, "warnings": 0}
|
|
1038
|
+
|
|
1039
|
+
for row_idx, row in enumerate(matrix):
|
|
1040
|
+
for col_idx, cell in enumerate(row):
|
|
1041
|
+
try:
|
|
1042
|
+
if cell is not None:
|
|
1043
|
+
processed_cell = process_cell(cell)
|
|
1044
|
+
summary["processed"] += 1
|
|
1045
|
+
|
|
1046
|
+
if processed_cell.has_warning:
|
|
1047
|
+
summary["warnings"] += 1
|
|
1048
|
+
|
|
1049
|
+
matrix[row_idx][col_idx] = processed_cell
|
|
1050
|
+
|
|
1051
|
+
except ProcessingError as e:
|
|
1052
|
+
summary["errors"] += 1
|
|
1053
|
+
logger.error(f"Error processing cell at ({row_idx}, {col_idx}): {e}")
|
|
1054
|
+
|
|
1055
|
+
return summary
|
|
1056
|
+
"#;
|
|
1057
|
+
|
|
1058
|
+
fs::write(&test_file, content)?;
|
|
1059
|
+
|
|
1060
|
+
let ctx = TestContext::new();
|
|
1061
|
+
let output = ctx.run_probe(&[
|
|
1062
|
+
"search",
|
|
1063
|
+
"large_function", // Search for large functions specifically
|
|
1064
|
+
test_file.to_str().unwrap(),
|
|
1065
|
+
"--format",
|
|
1066
|
+
"outline",
|
|
1067
|
+
"--allow-tests",
|
|
1068
|
+
])?;
|
|
1069
|
+
|
|
1070
|
+
// Should have closing brace comments for large functions with gaps (using Python # syntax)
|
|
1071
|
+
// Python uses # for comments, not //
|
|
1072
|
+
let has_closing_brace_comment =
|
|
1073
|
+
output.contains("# function") || output.contains("# def") || output.contains("# end");
|
|
1074
|
+
assert!(
|
|
1075
|
+
has_closing_brace_comment || !output.contains("..."),
|
|
1076
|
+
"Large functions should have closing brace comments with Python # syntax when truncated - output: {}",
|
|
1077
|
+
output
|
|
1078
|
+
);
|
|
1079
|
+
|
|
1080
|
+
// Verify the functions are found
|
|
1081
|
+
assert!(
|
|
1082
|
+
output.contains("large_function_with_gaps") || output.contains("another_large_function"),
|
|
1083
|
+
"Should find large functions - output: {}",
|
|
1084
|
+
output
|
|
1085
|
+
);
|
|
1086
|
+
|
|
1087
|
+
Ok(())
|
|
1088
|
+
}
|
|
1089
|
+
|
|
1090
|
+
#[test]
|
|
1091
|
+
fn test_python_outline_small_functions_no_closing_brace_comments() -> Result<()> {
|
|
1092
|
+
let temp_dir = TempDir::new()?;
|
|
1093
|
+
let test_file = temp_dir.path().join("small_functions.py");
|
|
1094
|
+
|
|
1095
|
+
let content = r#"def small_helper(x: int) -> int:
|
|
1096
|
+
"""Small helper function - should not have closing brace comments."""
|
|
1097
|
+
return x * 2
|
|
1098
|
+
|
|
1099
|
+
def another_small_function(s: str) -> str:
|
|
1100
|
+
"""Another small function - also should not have closing brace comments."""
|
|
1101
|
+
return s.upper()
|
|
1102
|
+
|
|
1103
|
+
def small_with_few_lines(data: list) -> int:
|
|
1104
|
+
"""Small function with a few lines - still should not have closing brace comments."""
|
|
1105
|
+
total = sum(data)
|
|
1106
|
+
count = len(data)
|
|
1107
|
+
return total // count if count > 0 else 0
|
|
1108
|
+
|
|
1109
|
+
class SmallClass:
|
|
1110
|
+
"""Small class with minimal methods."""
|
|
1111
|
+
|
|
1112
|
+
def __init__(self, value: int):
|
|
1113
|
+
self.value = value
|
|
1114
|
+
|
|
1115
|
+
def get_value(self) -> int:
|
|
1116
|
+
"""Simple getter method."""
|
|
1117
|
+
return self.value
|
|
1118
|
+
|
|
1119
|
+
def test_small_functions():
|
|
1120
|
+
"""Test function for small functions."""
|
|
1121
|
+
helper = SmallClass(42)
|
|
1122
|
+
assert helper.get_value() == 42
|
|
1123
|
+
"#;
|
|
1124
|
+
|
|
1125
|
+
fs::write(&test_file, content)?;
|
|
1126
|
+
|
|
1127
|
+
let ctx = TestContext::new();
|
|
1128
|
+
let output = ctx.run_probe(&[
|
|
1129
|
+
"search",
|
|
1130
|
+
"small", // Search for small functions specifically
|
|
1131
|
+
test_file.to_str().unwrap(),
|
|
1132
|
+
"--format",
|
|
1133
|
+
"outline",
|
|
1134
|
+
"--allow-tests",
|
|
1135
|
+
])?;
|
|
1136
|
+
|
|
1137
|
+
// Small functions should NOT have closing brace comments when fully shown
|
|
1138
|
+
let has_closing_brace_comment =
|
|
1139
|
+
output.contains("# function") || output.contains("# def") || output.contains("# end");
|
|
1140
|
+
|
|
1141
|
+
// Either no closing brace comments (if complete) or has ellipsis (if truncated)
|
|
1142
|
+
let has_ellipsis = output.contains("...");
|
|
1143
|
+
assert!(
|
|
1144
|
+
!has_closing_brace_comment || has_ellipsis,
|
|
1145
|
+
"Small functions should not have closing brace comments unless truncated - output: {}",
|
|
1146
|
+
output
|
|
1147
|
+
);
|
|
1148
|
+
|
|
1149
|
+
// Should find the small functions
|
|
1150
|
+
assert!(
|
|
1151
|
+
output.contains("small_helper")
|
|
1152
|
+
|| output.contains("SmallClass")
|
|
1153
|
+
|| output.contains("small"),
|
|
1154
|
+
"Should find small functions - output: {}",
|
|
1155
|
+
output
|
|
1156
|
+
);
|
|
1157
|
+
|
|
1158
|
+
Ok(())
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1161
|
+
#[test]
|
|
1162
|
+
fn test_python_outline_keyword_highlighting() -> Result<()> {
|
|
1163
|
+
let temp_dir = TempDir::new()?;
|
|
1164
|
+
let test_file = temp_dir.path().join("keyword_highlighting.py");
|
|
1165
|
+
|
|
1166
|
+
let content = r#"# Python with various keywords for highlighting tests
|
|
1167
|
+
import asyncio
|
|
1168
|
+
from typing import async, await, yield
|
|
1169
|
+
from dataclasses import dataclass
|
|
1170
|
+
|
|
1171
|
+
@dataclass
|
|
1172
|
+
class AsyncConfig:
|
|
1173
|
+
"""Configuration for async operations."""
|
|
1174
|
+
timeout: float = 30.0
|
|
1175
|
+
max_retries: int = 3
|
|
1176
|
+
|
|
1177
|
+
async def async_function_with_await(url: str) -> str:
|
|
1178
|
+
"""Async function using await keyword."""
|
|
1179
|
+
async with httpx.AsyncClient() as client:
|
|
1180
|
+
response = await client.get(url)
|
|
1181
|
+
return response.text
|
|
1182
|
+
|
|
1183
|
+
def generator_with_yield(items: list):
|
|
1184
|
+
"""Generator function using yield keyword."""
|
|
1185
|
+
for item in items:
|
|
1186
|
+
if item is not None:
|
|
1187
|
+
yield item * 2
|
|
1188
|
+
|
|
1189
|
+
async def async_generator_with_yield():
|
|
1190
|
+
"""Async generator using both async and yield keywords."""
|
|
1191
|
+
for i in range(10):
|
|
1192
|
+
await asyncio.sleep(0.1)
|
|
1193
|
+
yield f"async item {i}"
|
|
1194
|
+
|
|
1195
|
+
class KeywordProcessor:
|
|
1196
|
+
"""Class demonstrating various Python keywords."""
|
|
1197
|
+
|
|
1198
|
+
async def async_method(self):
|
|
1199
|
+
"""Method using async keyword."""
|
|
1200
|
+
return await self.process_async()
|
|
1201
|
+
|
|
1202
|
+
@staticmethod
|
|
1203
|
+
def static_method_with_await():
|
|
1204
|
+
"""Static method mentioning await in comments."""
|
|
1205
|
+
# This method talks about await but doesn't use it
|
|
1206
|
+
pass
|
|
1207
|
+
|
|
1208
|
+
@classmethod
|
|
1209
|
+
async def async_class_method(cls):
|
|
1210
|
+
"""Class method that is also async."""
|
|
1211
|
+
instance = cls()
|
|
1212
|
+
return await instance.async_method()
|
|
1213
|
+
|
|
1214
|
+
def function_with_async_in_name():
|
|
1215
|
+
"""Function with async keyword in name for search testing."""
|
|
1216
|
+
return "async processing complete"
|
|
1217
|
+
|
|
1218
|
+
def test_async_keyword_search():
|
|
1219
|
+
"""Test function to find async-related functionality."""
|
|
1220
|
+
processor = KeywordProcessor()
|
|
1221
|
+
result = processor.function_with_async_in_name()
|
|
1222
|
+
assert "async" in result
|
|
1223
|
+
"#;
|
|
1224
|
+
|
|
1225
|
+
fs::write(&test_file, content)?;
|
|
1226
|
+
|
|
1227
|
+
let ctx = TestContext::new();
|
|
1228
|
+
|
|
1229
|
+
// Search for specific keywords and verify they're highlighted in outline
|
|
1230
|
+
let test_cases = vec![
|
|
1231
|
+
("async", "async def async_function_with_await"),
|
|
1232
|
+
("yield", "def generator_with_yield"),
|
|
1233
|
+
("await", "await"),
|
|
1234
|
+
("class", "class KeywordProcessor"),
|
|
1235
|
+
("dataclass", "@dataclass"),
|
|
1236
|
+
];
|
|
1237
|
+
|
|
1238
|
+
for (keyword, expected_content) in test_cases {
|
|
1239
|
+
let output = ctx.run_probe(&[
|
|
1240
|
+
"search",
|
|
1241
|
+
keyword, // Search for the specific keyword
|
|
1242
|
+
test_file.to_str().unwrap(),
|
|
1243
|
+
"--format",
|
|
1244
|
+
"outline",
|
|
1245
|
+
"--allow-tests",
|
|
1246
|
+
])?;
|
|
1247
|
+
|
|
1248
|
+
// Should find the keyword in the outline
|
|
1249
|
+
assert!(
|
|
1250
|
+
output.contains(expected_content) || output.contains(keyword),
|
|
1251
|
+
"Should find '{}' keyword in outline format - expected '{}' - output: {}",
|
|
1252
|
+
keyword,
|
|
1253
|
+
expected_content,
|
|
1254
|
+
output
|
|
1255
|
+
);
|
|
1256
|
+
|
|
1257
|
+
// Should preserve keyword highlighting - the keyword should appear multiple times
|
|
1258
|
+
let keyword_count = output.matches(keyword).count();
|
|
1259
|
+
assert!(
|
|
1260
|
+
keyword_count >= 1,
|
|
1261
|
+
"Should preserve '{}' keyword highlighting - found {}, output: {}",
|
|
1262
|
+
keyword,
|
|
1263
|
+
keyword_count,
|
|
1264
|
+
output
|
|
1265
|
+
);
|
|
1266
|
+
}
|
|
1267
|
+
|
|
1268
|
+
Ok(())
|
|
1269
|
+
}
|
|
1270
|
+
|
|
1271
|
+
#[test]
|
|
1272
|
+
fn test_python_outline_modern_features() -> Result<()> {
|
|
1273
|
+
let temp_dir = TempDir::new()?;
|
|
1274
|
+
let test_file = temp_dir.path().join("modern_features.py");
|
|
1275
|
+
|
|
1276
|
+
let content = r#"from dataclasses import dataclass
|
|
1277
|
+
from typing import TypeVar, Generic, Protocol, Union, Optional, Literal, Final
|
|
1278
|
+
from enum import Enum
|
|
1279
|
+
|
|
1280
|
+
# Python 3.10+ Pattern Matching
|
|
1281
|
+
def handle_data(value):
|
|
1282
|
+
match value:
|
|
1283
|
+
case {'type': 'user', 'name': str(name)} if len(name) > 0:
|
|
1284
|
+
return f"User: {name}"
|
|
1285
|
+
case {'type': 'admin', 'level': int(level)} if level > 5:
|
|
1286
|
+
return f"Admin level {level}"
|
|
1287
|
+
case list() if len(value) > 0:
|
|
1288
|
+
return f"List with {len(value)} items"
|
|
1289
|
+
case _:
|
|
1290
|
+
return "Unknown data type"
|
|
1291
|
+
|
|
1292
|
+
# Dataclasses with type hints
|
|
1293
|
+
@dataclass(frozen=True)
|
|
1294
|
+
class UserConfig:
|
|
1295
|
+
"""Configuration for user settings with modern Python features."""
|
|
1296
|
+
username: str
|
|
1297
|
+
email: str
|
|
1298
|
+
preferences: dict[str, Union[str, int, bool]]
|
|
1299
|
+
role: Literal['user', 'admin', 'moderator'] = 'user'
|
|
1300
|
+
is_active: bool = True
|
|
1301
|
+
|
|
1302
|
+
def to_dict(self) -> dict[str, Union[str, int, bool, dict]]:
|
|
1303
|
+
"""Convert to dictionary with type hints."""
|
|
1304
|
+
return {
|
|
1305
|
+
'username': self.username,
|
|
1306
|
+
'email': self.email,
|
|
1307
|
+
'preferences': self.preferences,
|
|
1308
|
+
'role': self.role,
|
|
1309
|
+
'is_active': self.is_active
|
|
1310
|
+
}
|
|
1311
|
+
|
|
1312
|
+
# Generic types and protocols
|
|
1313
|
+
T = TypeVar('T')
|
|
1314
|
+
U = TypeVar('U', bound='Serializable')
|
|
1315
|
+
|
|
1316
|
+
class Serializable(Protocol):
|
|
1317
|
+
"""Protocol for serializable objects."""
|
|
1318
|
+
def serialize(self) -> dict[str, Union[str, int, bool]]: ...
|
|
1319
|
+
|
|
1320
|
+
class DataProcessor(Generic[T]):
|
|
1321
|
+
"""Generic data processor with type variables."""
|
|
1322
|
+
|
|
1323
|
+
def __init__(self, data: list[T]):
|
|
1324
|
+
self.data: Final[list[T]] = data
|
|
1325
|
+
|
|
1326
|
+
async def process_async(self, transformer) -> list:
|
|
1327
|
+
"""Process data asynchronously with type safety."""
|
|
1328
|
+
results = []
|
|
1329
|
+
for item in self.data:
|
|
1330
|
+
processed = await asyncio.to_thread(transformer, item)
|
|
1331
|
+
results.append(processed)
|
|
1332
|
+
return results
|
|
1333
|
+
|
|
1334
|
+
def filter_data(self, predicate) -> 'DataProcessor':
|
|
1335
|
+
"""Filter data with type preservation."""
|
|
1336
|
+
filtered = [item for item in self.data if predicate(item)]
|
|
1337
|
+
return DataProcessor(filtered)
|
|
1338
|
+
|
|
1339
|
+
# Enum with modern features
|
|
1340
|
+
class Status(Enum):
|
|
1341
|
+
"""Status enumeration with string values."""
|
|
1342
|
+
PENDING = "pending"
|
|
1343
|
+
PROCESSING = "processing"
|
|
1344
|
+
COMPLETED = "completed"
|
|
1345
|
+
FAILED = "failed"
|
|
1346
|
+
|
|
1347
|
+
def is_terminal(self) -> bool:
|
|
1348
|
+
"""Check if status is terminal."""
|
|
1349
|
+
return self in (Status.COMPLETED, Status.FAILED)
|
|
1350
|
+
|
|
1351
|
+
def test_modern_python_features():
|
|
1352
|
+
"""Test modern Python features integration."""
|
|
1353
|
+
config = UserConfig(
|
|
1354
|
+
username="test_user",
|
|
1355
|
+
email="test@example.com",
|
|
1356
|
+
preferences={'theme': 'dark', 'notifications': True}
|
|
1357
|
+
)
|
|
1358
|
+
|
|
1359
|
+
processor = DataProcessor([1, 2, 3, 4, 5])
|
|
1360
|
+
filtered = processor.filter_data(lambda x: x % 2 == 0)
|
|
1361
|
+
|
|
1362
|
+
assert config.role == 'user'
|
|
1363
|
+
assert len(filtered.data) == 2
|
|
1364
|
+
assert Status.PENDING.is_terminal() is False
|
|
1365
|
+
"#;
|
|
1366
|
+
|
|
1367
|
+
fs::write(&test_file, content)?;
|
|
1368
|
+
|
|
1369
|
+
let ctx = TestContext::new();
|
|
1370
|
+
let output = ctx.run_probe(&[
|
|
1371
|
+
"search",
|
|
1372
|
+
"dataclass|match|async|Generic|Protocol", // Search for modern Python features
|
|
1373
|
+
test_file.to_str().unwrap(),
|
|
1374
|
+
"--format",
|
|
1375
|
+
"outline",
|
|
1376
|
+
"--max-results",
|
|
1377
|
+
"20",
|
|
1378
|
+
"--allow-tests",
|
|
1379
|
+
])?;
|
|
1380
|
+
|
|
1381
|
+
// Verify modern Python features are detected
|
|
1382
|
+
let has_dataclass = output.contains("@dataclass") || output.contains("UserConfig");
|
|
1383
|
+
let has_pattern_matching = output.contains("match") || output.contains("case");
|
|
1384
|
+
let has_generics = output.contains("Generic") || output.contains("DataProcessor");
|
|
1385
|
+
let has_protocol = output.contains("Protocol") || output.contains("Serializable");
|
|
1386
|
+
let has_async = output.contains("async") || output.contains("await");
|
|
1387
|
+
|
|
1388
|
+
assert!(
|
|
1389
|
+
has_dataclass || has_generics || has_protocol,
|
|
1390
|
+
"Missing modern Python features (dataclass, generics, or protocols) - output: {}",
|
|
1391
|
+
output
|
|
1392
|
+
);
|
|
1393
|
+
assert!(
|
|
1394
|
+
has_pattern_matching || has_async || output.len() > 10,
|
|
1395
|
+
"Missing pattern matching or async features, or no results - output: {}",
|
|
1396
|
+
output
|
|
1397
|
+
);
|
|
1398
|
+
|
|
1399
|
+
// Verify closing brace comments use Python # syntax when present
|
|
1400
|
+
if output.contains("...") {
|
|
1401
|
+
let has_python_comments =
|
|
1402
|
+
output.contains("# class") || output.contains("# def") || !output.contains("//");
|
|
1403
|
+
assert!(
|
|
1404
|
+
has_python_comments,
|
|
1405
|
+
"Should use Python # syntax for closing brace comments - output: {}",
|
|
1406
|
+
output
|
|
1407
|
+
);
|
|
1408
|
+
}
|
|
1409
|
+
|
|
1410
|
+
Ok(())
|
|
1411
|
+
}
|
|
1412
|
+
|
|
1413
|
+
#[test]
|
|
1414
|
+
fn test_python_outline_list_dict_truncation() -> Result<()> {
|
|
1415
|
+
let temp_dir = TempDir::new()?;
|
|
1416
|
+
let test_file = temp_dir.path().join("data_structures.py");
|
|
1417
|
+
|
|
1418
|
+
let content = r#"# Large data structures that should be truncated in outline format
|
|
1419
|
+
LARGE_CONFIG = {
|
|
1420
|
+
'database': {
|
|
1421
|
+
'host': 'localhost',
|
|
1422
|
+
'port': 5432,
|
|
1423
|
+
'username': 'admin',
|
|
1424
|
+
'password': 'secret',
|
|
1425
|
+
'ssl': True,
|
|
1426
|
+
'timeout': 30,
|
|
1427
|
+
'pool_size': 10,
|
|
1428
|
+
'retry_attempts': 3
|
|
1429
|
+
},
|
|
1430
|
+
'api': {
|
|
1431
|
+
'base_url': 'https://api.example.com',
|
|
1432
|
+
'version': 'v2',
|
|
1433
|
+
'key': 'api_key_here',
|
|
1434
|
+
'rate_limit': 1000,
|
|
1435
|
+
'cache_ttl': 300
|
|
1436
|
+
},
|
|
1437
|
+
'features': {
|
|
1438
|
+
'feature_a': True,
|
|
1439
|
+
'feature_b': False,
|
|
1440
|
+
'feature_c': True,
|
|
1441
|
+
'feature_d': {'nested': 'value'},
|
|
1442
|
+
'feature_e': [1, 2, 3, 4, 5]
|
|
1443
|
+
}
|
|
1444
|
+
}
|
|
1445
|
+
|
|
1446
|
+
def process_data_structures():
|
|
1447
|
+
"""Function that works with large data structures."""
|
|
1448
|
+
# Dictionary comprehension with keyword preservation
|
|
1449
|
+
active_items = {
|
|
1450
|
+
item['id']: item['name']
|
|
1451
|
+
for item in LONG_LIST
|
|
1452
|
+
if item['active'] == True
|
|
1453
|
+
}
|
|
1454
|
+
|
|
1455
|
+
# List comprehension with filtering
|
|
1456
|
+
filtered_list = [
|
|
1457
|
+
{'processed_id': item['id'], 'processed_name': item['name'].upper()}
|
|
1458
|
+
for item in LONG_LIST
|
|
1459
|
+
if item['active'] and item['id'] % 2 == 0
|
|
1460
|
+
]
|
|
1461
|
+
|
|
1462
|
+
return {
|
|
1463
|
+
'active_items': active_items,
|
|
1464
|
+
'filtered': filtered_list,
|
|
1465
|
+
'config': LARGE_CONFIG
|
|
1466
|
+
}
|
|
1467
|
+
|
|
1468
|
+
class DataManager:
|
|
1469
|
+
"""Class for managing large data structures."""
|
|
1470
|
+
|
|
1471
|
+
def __init__(self):
|
|
1472
|
+
self.cache = {}
|
|
1473
|
+
self.settings = {
|
|
1474
|
+
'max_cache_size': 1000,
|
|
1475
|
+
'cache_ttl': 3600,
|
|
1476
|
+
'compression': True,
|
|
1477
|
+
'encryption': False,
|
|
1478
|
+
'backup_interval': 86400,
|
|
1479
|
+
'cleanup_threshold': 0.8
|
|
1480
|
+
}
|
|
1481
|
+
|
|
1482
|
+
def get_nested_value(self, data: dict, path: list) -> any:
|
|
1483
|
+
"""Get nested dictionary value with keyword preservation."""
|
|
1484
|
+
current = data
|
|
1485
|
+
for key in path:
|
|
1486
|
+
if isinstance(current, dict) and key in current:
|
|
1487
|
+
current = current[key]
|
|
1488
|
+
else:
|
|
1489
|
+
return None
|
|
1490
|
+
return current
|
|
1491
|
+
|
|
1492
|
+
def test_data_structure_processing():
|
|
1493
|
+
"""Test data structure processing with keyword preservation."""
|
|
1494
|
+
manager = DataManager()
|
|
1495
|
+
result = manager.get_nested_value({'a': {'b': 1}}, ['a', 'b'])
|
|
1496
|
+
assert result == 1
|
|
1497
|
+
"#;
|
|
1498
|
+
|
|
1499
|
+
fs::write(&test_file, content)?;
|
|
1500
|
+
|
|
1501
|
+
let ctx = TestContext::new();
|
|
1502
|
+
let output = ctx.run_probe(&[
|
|
1503
|
+
"search",
|
|
1504
|
+
"dict|list|def|class", // Search for data structures and functions
|
|
1505
|
+
test_file.to_str().unwrap(),
|
|
1506
|
+
"--format",
|
|
1507
|
+
"outline",
|
|
1508
|
+
"--max-results",
|
|
1509
|
+
"20",
|
|
1510
|
+
"--allow-tests",
|
|
1511
|
+
])?;
|
|
1512
|
+
|
|
1513
|
+
// Verify data structures and functions are shown
|
|
1514
|
+
let has_large_config = output.contains("LARGE_CONFIG") || output.contains("database");
|
|
1515
|
+
let has_process_function = output.contains("process_data_structures") || output.contains("def");
|
|
1516
|
+
let has_data_manager = output.contains("DataManager") || output.contains("class");
|
|
1517
|
+
|
|
1518
|
+
assert!(
|
|
1519
|
+
has_large_config || has_process_function || has_data_manager,
|
|
1520
|
+
"Missing data structures, functions, or classes - output: {}",
|
|
1521
|
+
output
|
|
1522
|
+
);
|
|
1523
|
+
|
|
1524
|
+
// Verify keyword preservation in content
|
|
1525
|
+
let preserves_keywords = output.contains("dict")
|
|
1526
|
+
|| output.contains("list")
|
|
1527
|
+
|| output.contains("def")
|
|
1528
|
+
|| output.contains("class")
|
|
1529
|
+
|| output.contains("for")
|
|
1530
|
+
|| output.contains("if");
|
|
1531
|
+
assert!(
|
|
1532
|
+
preserves_keywords,
|
|
1533
|
+
"Should preserve important keywords - output: {}",
|
|
1534
|
+
output
|
|
1535
|
+
);
|
|
1536
|
+
|
|
1537
|
+
Ok(())
|
|
1538
|
+
}
|