@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,1611 @@
|
|
|
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_java_outline_basic_symbols() -> Result<()> {
|
|
10
|
+
let temp_dir = TempDir::new()?;
|
|
11
|
+
let test_file = temp_dir.path().join("Calculator.java");
|
|
12
|
+
|
|
13
|
+
let content = r#"package com.example.calculator;
|
|
14
|
+
|
|
15
|
+
import java.util.*;
|
|
16
|
+
import java.util.stream.Collectors;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Calculator interface defining basic arithmetic operations
|
|
20
|
+
*/
|
|
21
|
+
public interface CalculatorInterface {
|
|
22
|
+
double add(double x, double y);
|
|
23
|
+
double subtract(double x, double y);
|
|
24
|
+
double multiply(double x, double y);
|
|
25
|
+
double divide(double x, double y) throws ArithmeticException;
|
|
26
|
+
List<Double> getHistory();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Abstract base calculator with common functionality
|
|
31
|
+
*/
|
|
32
|
+
public abstract class BaseCalculator implements CalculatorInterface {
|
|
33
|
+
protected String name;
|
|
34
|
+
protected List<Double> history;
|
|
35
|
+
protected int precision;
|
|
36
|
+
|
|
37
|
+
public BaseCalculator(String name, int precision) {
|
|
38
|
+
this.name = name;
|
|
39
|
+
this.precision = precision;
|
|
40
|
+
this.history = new ArrayList<>();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
protected void recordOperation(double result) {
|
|
44
|
+
history.add(result);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
@Override
|
|
48
|
+
public List<Double> getHistory() {
|
|
49
|
+
return new ArrayList<>(history);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
public abstract void clearHistory();
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Advanced calculator implementation with generics and lambdas
|
|
57
|
+
*/
|
|
58
|
+
public class AdvancedCalculator extends BaseCalculator {
|
|
59
|
+
private final Map<String, Double> constants;
|
|
60
|
+
private static final double DEFAULT_PRECISION = 0.001;
|
|
61
|
+
|
|
62
|
+
public AdvancedCalculator(String name) {
|
|
63
|
+
super(name, 2);
|
|
64
|
+
this.constants = new HashMap<>();
|
|
65
|
+
initializeConstants();
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
private void initializeConstants() {
|
|
69
|
+
constants.put("PI", Math.PI);
|
|
70
|
+
constants.put("E", Math.E);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
@Override
|
|
74
|
+
public double add(double x, double y) {
|
|
75
|
+
double result = x + y;
|
|
76
|
+
recordOperation(result);
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
@Override
|
|
81
|
+
public double subtract(double x, double y) {
|
|
82
|
+
double result = x - y;
|
|
83
|
+
recordOperation(result);
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
@Override
|
|
88
|
+
public double multiply(double x, double y) {
|
|
89
|
+
double result = x * y;
|
|
90
|
+
recordOperation(result);
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@Override
|
|
95
|
+
public double divide(double x, double y) throws ArithmeticException {
|
|
96
|
+
if (Math.abs(y) < DEFAULT_PRECISION) {
|
|
97
|
+
throw new ArithmeticException("Division by zero");
|
|
98
|
+
}
|
|
99
|
+
double result = x / y;
|
|
100
|
+
recordOperation(result);
|
|
101
|
+
return result;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
@Override
|
|
105
|
+
public void clearHistory() {
|
|
106
|
+
history.clear();
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// Generic method with wildcards
|
|
110
|
+
public <T extends Number> List<Double> processNumbers(List<T> numbers) {
|
|
111
|
+
return numbers.stream()
|
|
112
|
+
.map(Number::doubleValue)
|
|
113
|
+
.filter(x -> x != 0.0)
|
|
114
|
+
.collect(Collectors.toList());
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// Method with lambda parameter
|
|
118
|
+
public List<Double> transformHistory(java.util.function.Function<Double, Double> transformer) {
|
|
119
|
+
return history.stream()
|
|
120
|
+
.map(transformer)
|
|
121
|
+
.collect(Collectors.toList());
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Static factory method
|
|
125
|
+
public static AdvancedCalculator createWithDefaults(String name) {
|
|
126
|
+
return new AdvancedCalculator(name);
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// Inner class
|
|
130
|
+
public static class CalculationResult {
|
|
131
|
+
private final double value;
|
|
132
|
+
private final String operation;
|
|
133
|
+
private final long timestamp;
|
|
134
|
+
|
|
135
|
+
public CalculationResult(double value, String operation) {
|
|
136
|
+
this.value = value;
|
|
137
|
+
this.operation = operation;
|
|
138
|
+
this.timestamp = System.currentTimeMillis();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
public double getValue() { return value; }
|
|
142
|
+
public String getOperation() { return operation; }
|
|
143
|
+
public long getTimestamp() { return timestamp; }
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Enum for operation types
|
|
149
|
+
*/
|
|
150
|
+
public enum OperationType {
|
|
151
|
+
ADD("Addition"),
|
|
152
|
+
SUBTRACT("Subtraction"),
|
|
153
|
+
MULTIPLY("Multiplication"),
|
|
154
|
+
DIVIDE("Division");
|
|
155
|
+
|
|
156
|
+
private final String description;
|
|
157
|
+
|
|
158
|
+
OperationType(String description) {
|
|
159
|
+
this.description = description;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
public String getDescription() {
|
|
163
|
+
return description;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Main class demonstrating calculator usage
|
|
169
|
+
*/
|
|
170
|
+
public class CalculatorDemo {
|
|
171
|
+
private static final Logger logger = LoggerFactory.getLogger(CalculatorDemo.class);
|
|
172
|
+
|
|
173
|
+
public static void main(String[] args) {
|
|
174
|
+
AdvancedCalculator calc = AdvancedCalculator.createWithDefaults("Demo Calculator");
|
|
175
|
+
|
|
176
|
+
try {
|
|
177
|
+
double result = calc.add(10.5, 20.3);
|
|
178
|
+
System.out.println("Result: " + result);
|
|
179
|
+
|
|
180
|
+
List<Double> history = calc.getHistory();
|
|
181
|
+
history.forEach(System.out::println);
|
|
182
|
+
|
|
183
|
+
} catch (ArithmeticException e) {
|
|
184
|
+
logger.error("Calculation error: " + e.getMessage());
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
// Test method
|
|
189
|
+
public static void testCalculator() {
|
|
190
|
+
AdvancedCalculator calc = new AdvancedCalculator("Test");
|
|
191
|
+
assert calc.add(2, 3) == 5;
|
|
192
|
+
assert calc.multiply(4, 5) == 20;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
"#;
|
|
196
|
+
|
|
197
|
+
fs::write(&test_file, content)?;
|
|
198
|
+
|
|
199
|
+
let ctx = TestContext::new();
|
|
200
|
+
let output = ctx.run_probe(&[
|
|
201
|
+
"search",
|
|
202
|
+
"Calculator",
|
|
203
|
+
test_file.to_str().unwrap(),
|
|
204
|
+
"--format",
|
|
205
|
+
"outline",
|
|
206
|
+
"--allow-tests",
|
|
207
|
+
])?;
|
|
208
|
+
|
|
209
|
+
// Verify Java symbols are found in outline format
|
|
210
|
+
assert!(
|
|
211
|
+
output.contains("CalculatorInterface") || output.contains("interface"),
|
|
212
|
+
"Missing CalculatorInterface - output: {}",
|
|
213
|
+
output
|
|
214
|
+
);
|
|
215
|
+
assert!(
|
|
216
|
+
output.contains("BaseCalculator") || output.contains("abstract"),
|
|
217
|
+
"Missing BaseCalculator - output: {}",
|
|
218
|
+
output
|
|
219
|
+
);
|
|
220
|
+
assert!(
|
|
221
|
+
output.contains("AdvancedCalculator") || output.contains("class"),
|
|
222
|
+
"Missing AdvancedCalculator - output: {}",
|
|
223
|
+
output
|
|
224
|
+
);
|
|
225
|
+
assert!(
|
|
226
|
+
output.contains("CalculatorDemo") || output.contains("public"),
|
|
227
|
+
"Missing CalculatorDemo - output: {}",
|
|
228
|
+
output
|
|
229
|
+
);
|
|
230
|
+
assert!(
|
|
231
|
+
output.contains("main"),
|
|
232
|
+
"Missing main method - output: {}",
|
|
233
|
+
output
|
|
234
|
+
);
|
|
235
|
+
|
|
236
|
+
// Test outline format specific features
|
|
237
|
+
assert!(
|
|
238
|
+
output.contains("..."),
|
|
239
|
+
"Missing ellipsis in outline format - output: {}",
|
|
240
|
+
output
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
// Search separately for enum to test different constructs
|
|
244
|
+
let enum_output = ctx.run_probe(&[
|
|
245
|
+
"search",
|
|
246
|
+
"enum",
|
|
247
|
+
test_file.to_str().unwrap(),
|
|
248
|
+
"--format",
|
|
249
|
+
"outline",
|
|
250
|
+
"--allow-tests",
|
|
251
|
+
])?;
|
|
252
|
+
|
|
253
|
+
assert!(
|
|
254
|
+
enum_output.contains("OperationType") || enum_output.contains("enum"),
|
|
255
|
+
"Missing OperationType enum - output: {}",
|
|
256
|
+
enum_output
|
|
257
|
+
);
|
|
258
|
+
|
|
259
|
+
Ok(())
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
#[test]
|
|
263
|
+
fn test_java_outline_smart_closing_brace_comments() -> Result<()> {
|
|
264
|
+
let temp_dir = TempDir::new()?;
|
|
265
|
+
let test_file = temp_dir.path().join("smart_braces.java");
|
|
266
|
+
|
|
267
|
+
let content = r#"// Small function that should NOT get closing brace comments.
|
|
268
|
+
public class SmallFunctionTest {
|
|
269
|
+
public static int smallFunction(int x) {
|
|
270
|
+
int result = x * 2;
|
|
271
|
+
return result + 1;
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Large function that SHOULD get closing brace comments with Java // syntax.
|
|
276
|
+
public class LargeFunctionTest {
|
|
277
|
+
public static List<String> largeFunctionWithGaps(List<Integer> data) {
|
|
278
|
+
List<String> results = new ArrayList<>();
|
|
279
|
+
DataProcessor processor = new DataProcessor();
|
|
280
|
+
|
|
281
|
+
// Phase 1: Initial processing with nested control flow
|
|
282
|
+
for (int i = 0; i < data.size(); i++) {
|
|
283
|
+
if (data.get(i) > 100) {
|
|
284
|
+
processor.processLargeValue(data.get(i), i);
|
|
285
|
+
if (data.get(i) > 1000) {
|
|
286
|
+
processor.markAsExceptional(i);
|
|
287
|
+
try {
|
|
288
|
+
processor.validateValue(data.get(i));
|
|
289
|
+
} catch (ValidationException e) {
|
|
290
|
+
logger.warn("Validation failed for value: " + data.get(i), e);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
} else if (data.get(i) < 0) {
|
|
294
|
+
processor.processNegativeValue(data.get(i), i);
|
|
295
|
+
} else {
|
|
296
|
+
processor.processSmallValue(data.get(i), i);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
// Phase 2: Complex transformation logic with switch
|
|
301
|
+
List<TransformedItem> transformedData = processor.getTransformedData();
|
|
302
|
+
for (TransformedItem item : transformedData) {
|
|
303
|
+
switch (item.getCategory()) {
|
|
304
|
+
case HIGH:
|
|
305
|
+
results.add("HIGH: " + item.getValue());
|
|
306
|
+
break;
|
|
307
|
+
case MEDIUM:
|
|
308
|
+
results.add("MED: " + item.getValue());
|
|
309
|
+
break;
|
|
310
|
+
case LOW:
|
|
311
|
+
results.add("LOW: " + item.getValue());
|
|
312
|
+
break;
|
|
313
|
+
default:
|
|
314
|
+
results.add("UNKNOWN: " + item.getValue());
|
|
315
|
+
break;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
// Phase 3: Final validation and cleanup with try-catch
|
|
320
|
+
List<String> validatedResults = new ArrayList<>();
|
|
321
|
+
for (String result : results) {
|
|
322
|
+
try {
|
|
323
|
+
if (processor.validateResult(result)) {
|
|
324
|
+
validatedResults.add(result.toUpperCase());
|
|
325
|
+
processor.logSuccess(result);
|
|
326
|
+
}
|
|
327
|
+
} catch (ProcessingException e) {
|
|
328
|
+
logger.error("Processing failed for result: " + result, e);
|
|
329
|
+
validatedResults.add("ERROR: " + result);
|
|
330
|
+
} finally {
|
|
331
|
+
processor.cleanup();
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Phase 4: Stream processing with lambda expressions
|
|
336
|
+
return validatedResults.stream()
|
|
337
|
+
.filter(s -> !s.startsWith("ERROR"))
|
|
338
|
+
.map(s -> s.trim())
|
|
339
|
+
.distinct()
|
|
340
|
+
.collect(Collectors.toList());
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
"#;
|
|
344
|
+
|
|
345
|
+
fs::write(&test_file, content)?;
|
|
346
|
+
|
|
347
|
+
let ctx = TestContext::new();
|
|
348
|
+
let output = ctx.run_probe(&[
|
|
349
|
+
"search",
|
|
350
|
+
"Calculator",
|
|
351
|
+
test_file.to_str().unwrap(),
|
|
352
|
+
"--format",
|
|
353
|
+
"outline",
|
|
354
|
+
"--allow-tests",
|
|
355
|
+
])?;
|
|
356
|
+
|
|
357
|
+
// Large functions/classes should have closing brace comments with Java // syntax
|
|
358
|
+
assert!(
|
|
359
|
+
output.contains("} //") || output.contains("}"),
|
|
360
|
+
"Large Java functions should have closing brace comments with // syntax. Output:\n{}",
|
|
361
|
+
output
|
|
362
|
+
);
|
|
363
|
+
|
|
364
|
+
// Large functions/classes should have closing brace comments with Java // syntax
|
|
365
|
+
// Check for the main function we're testing to have closing brace comments
|
|
366
|
+
let closing_brace_comment_count = output.matches("} //").count();
|
|
367
|
+
assert!(
|
|
368
|
+
closing_brace_comment_count >= 1 || output.contains("..."),
|
|
369
|
+
"Should have at least one closing brace comment for large Java functions. Found: {}. Output:\n{}",
|
|
370
|
+
closing_brace_comment_count, output
|
|
371
|
+
);
|
|
372
|
+
|
|
373
|
+
// Verify the closing brace comments use Java style (//) not C style (/* */)
|
|
374
|
+
assert!(
|
|
375
|
+
!output.contains("} /*"),
|
|
376
|
+
"Closing brace comments should use Java style (//) not C style (/* */). Output:\n{}",
|
|
377
|
+
output
|
|
378
|
+
);
|
|
379
|
+
|
|
380
|
+
Ok(())
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
#[test]
|
|
384
|
+
fn test_java_outline_keyword_highlighting() -> Result<()> {
|
|
385
|
+
let temp_dir = TempDir::new()?;
|
|
386
|
+
let test_file = temp_dir.path().join("keyword_test.java");
|
|
387
|
+
|
|
388
|
+
let content = r#"package com.example.keywords;
|
|
389
|
+
|
|
390
|
+
import java.util.concurrent.CompletableFuture;
|
|
391
|
+
import java.util.stream.Stream;
|
|
392
|
+
|
|
393
|
+
public class KeywordHighlightingTest {
|
|
394
|
+
private static final String CONSTANT = "test";
|
|
395
|
+
private volatile boolean flag = false;
|
|
396
|
+
private transient Object cache;
|
|
397
|
+
|
|
398
|
+
public static void main(String[] args) {
|
|
399
|
+
KeywordHighlightingTest instance = new KeywordHighlightingTest();
|
|
400
|
+
instance.demonstrateKeywords();
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
public synchronized void demonstrateKeywords() {
|
|
404
|
+
// Control flow keywords
|
|
405
|
+
if (flag) {
|
|
406
|
+
while (!Thread.currentThread().isInterrupted()) {
|
|
407
|
+
for (int i = 0; i < 10; i++) {
|
|
408
|
+
switch (i % 3) {
|
|
409
|
+
case 0:
|
|
410
|
+
continue;
|
|
411
|
+
case 1:
|
|
412
|
+
break;
|
|
413
|
+
default:
|
|
414
|
+
return;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
// Exception handling keywords
|
|
421
|
+
try {
|
|
422
|
+
throw new RuntimeException("test");
|
|
423
|
+
} catch (RuntimeException e) {
|
|
424
|
+
assert e != null;
|
|
425
|
+
} finally {
|
|
426
|
+
System.out.println("cleanup");
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
public abstract class AbstractProcessor implements Runnable {
|
|
431
|
+
protected abstract void process();
|
|
432
|
+
|
|
433
|
+
@Override
|
|
434
|
+
public final void run() {
|
|
435
|
+
process();
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
public static class ConcreteProcessor extends AbstractProcessor {
|
|
440
|
+
@Override
|
|
441
|
+
protected void process() {
|
|
442
|
+
// Implementation
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
public native void nativeMethod();
|
|
447
|
+
|
|
448
|
+
public strictfp double strictFloatingPoint(double x, double y) {
|
|
449
|
+
return x * y;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
"#;
|
|
453
|
+
|
|
454
|
+
fs::write(&test_file, content)?;
|
|
455
|
+
|
|
456
|
+
let ctx = TestContext::new();
|
|
457
|
+
let output = ctx.run_probe(&[
|
|
458
|
+
"search",
|
|
459
|
+
"public",
|
|
460
|
+
test_file.to_str().unwrap(),
|
|
461
|
+
"--format",
|
|
462
|
+
"outline",
|
|
463
|
+
"--allow-tests",
|
|
464
|
+
])?;
|
|
465
|
+
|
|
466
|
+
// Verify Java keywords are highlighted/preserved in outline format
|
|
467
|
+
assert!(
|
|
468
|
+
output.contains("public"),
|
|
469
|
+
"Missing 'public' keyword in outline - output: {}",
|
|
470
|
+
output
|
|
471
|
+
);
|
|
472
|
+
assert!(
|
|
473
|
+
output.contains("class") || output.contains("interface"),
|
|
474
|
+
"Missing class/interface keywords in outline - output: {}",
|
|
475
|
+
output
|
|
476
|
+
);
|
|
477
|
+
|
|
478
|
+
// Test with different keyword searches
|
|
479
|
+
let abstract_output = ctx.run_probe(&[
|
|
480
|
+
"search",
|
|
481
|
+
"abstract",
|
|
482
|
+
test_file.to_str().unwrap(),
|
|
483
|
+
"--format",
|
|
484
|
+
"outline",
|
|
485
|
+
"--allow-tests",
|
|
486
|
+
])?;
|
|
487
|
+
|
|
488
|
+
assert!(
|
|
489
|
+
abstract_output.contains("abstract"),
|
|
490
|
+
"Missing 'abstract' keyword highlighting - output: {}",
|
|
491
|
+
abstract_output
|
|
492
|
+
);
|
|
493
|
+
|
|
494
|
+
// Test with control flow keywords
|
|
495
|
+
let if_output = ctx.run_probe(&[
|
|
496
|
+
"search",
|
|
497
|
+
"if",
|
|
498
|
+
test_file.to_str().unwrap(),
|
|
499
|
+
"--format",
|
|
500
|
+
"outline",
|
|
501
|
+
"--allow-tests",
|
|
502
|
+
])?;
|
|
503
|
+
|
|
504
|
+
assert!(
|
|
505
|
+
if_output.contains("if"),
|
|
506
|
+
"Missing 'if' keyword in control flow outline - output: {}",
|
|
507
|
+
if_output
|
|
508
|
+
);
|
|
509
|
+
|
|
510
|
+
Ok(())
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
#[test]
|
|
514
|
+
fn test_java_outline_array_collection_truncation() -> Result<()> {
|
|
515
|
+
let temp_dir = TempDir::new()?;
|
|
516
|
+
let test_file = temp_dir.path().join("array_test.java");
|
|
517
|
+
|
|
518
|
+
let content = r#"package com.example.collections;
|
|
519
|
+
|
|
520
|
+
import java.util.*;
|
|
521
|
+
import java.util.stream.Collectors;
|
|
522
|
+
|
|
523
|
+
public class ArrayCollectionTruncationTest {
|
|
524
|
+
// Large arrays that should be truncated but preserve keywords
|
|
525
|
+
private static final int[] LARGE_INT_ARRAY = {
|
|
526
|
+
1, 2, 3, 4, 5, 6, 7, 8, 9, 10,
|
|
527
|
+
11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
|
|
528
|
+
21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
|
|
529
|
+
31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
|
|
530
|
+
41, 42, 43, 44, 45, 46, 47, 48, 49, 50
|
|
531
|
+
};
|
|
532
|
+
|
|
533
|
+
private static final String[] LARGE_STRING_ARRAY = {
|
|
534
|
+
"first", "second", "third", "fourth", "fifth",
|
|
535
|
+
"sixth", "seventh", "eighth", "ninth", "tenth",
|
|
536
|
+
"eleventh", "twelfth", "thirteenth", "fourteenth", "fifteenth",
|
|
537
|
+
"sixteenth", "seventeenth", "eighteenth", "nineteenth", "twentieth"
|
|
538
|
+
};
|
|
539
|
+
|
|
540
|
+
// Method with large collection initialization
|
|
541
|
+
public List<Map<String, Object>> createLargeCollection() {
|
|
542
|
+
List<Map<String, Object>> result = new ArrayList<>();
|
|
543
|
+
|
|
544
|
+
// Adding many elements to test truncation
|
|
545
|
+
for (int i = 0; i < 100; i++) {
|
|
546
|
+
Map<String, Object> item = new HashMap<>();
|
|
547
|
+
item.put("id", i);
|
|
548
|
+
item.put("name", "Item " + i);
|
|
549
|
+
item.put("value", Math.random() * 100);
|
|
550
|
+
item.put("active", i % 2 == 0);
|
|
551
|
+
item.put("category", Arrays.asList("cat1", "cat2", "cat3"));
|
|
552
|
+
result.add(item);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
return result;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
// Method with complex nested collections
|
|
559
|
+
public Map<String, List<Set<Integer>>> createNestedCollections() {
|
|
560
|
+
Map<String, List<Set<Integer>>> complex = new HashMap<>();
|
|
561
|
+
|
|
562
|
+
for (String key : Arrays.asList("group1", "group2", "group3", "group4", "group5")) {
|
|
563
|
+
List<Set<Integer>> listOfSets = new ArrayList<>();
|
|
564
|
+
|
|
565
|
+
for (int i = 0; i < 10; i++) {
|
|
566
|
+
Set<Integer> set = new HashSet<>();
|
|
567
|
+
for (int j = 0; j < 20; j++) {
|
|
568
|
+
set.add(i * 20 + j);
|
|
569
|
+
}
|
|
570
|
+
listOfSets.add(set);
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
complex.put(key, listOfSets);
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
return complex;
|
|
577
|
+
}
|
|
578
|
+
|
|
579
|
+
// Method with stream operations on large collections
|
|
580
|
+
public List<String> processLargeCollection(List<Integer> input) {
|
|
581
|
+
return input.stream()
|
|
582
|
+
.filter(x -> x > 10)
|
|
583
|
+
.filter(x -> x < 1000)
|
|
584
|
+
.map(x -> "processed_" + x)
|
|
585
|
+
.map(String::toUpperCase)
|
|
586
|
+
.distinct()
|
|
587
|
+
.sorted()
|
|
588
|
+
.limit(50)
|
|
589
|
+
.collect(Collectors.toList());
|
|
590
|
+
}
|
|
591
|
+
}
|
|
592
|
+
"#;
|
|
593
|
+
|
|
594
|
+
fs::write(&test_file, content)?;
|
|
595
|
+
|
|
596
|
+
let ctx = TestContext::new();
|
|
597
|
+
let output = ctx.run_probe(&[
|
|
598
|
+
"search",
|
|
599
|
+
"Calculator",
|
|
600
|
+
test_file.to_str().unwrap(),
|
|
601
|
+
"--format",
|
|
602
|
+
"outline",
|
|
603
|
+
"--allow-tests",
|
|
604
|
+
])?;
|
|
605
|
+
|
|
606
|
+
// Verify arrays/collections are shown in outline
|
|
607
|
+
assert!(
|
|
608
|
+
output.contains("LARGE_INT_ARRAY") || output.contains("int[]"),
|
|
609
|
+
"Missing array declaration in outline - output: {}",
|
|
610
|
+
output
|
|
611
|
+
);
|
|
612
|
+
|
|
613
|
+
// Verify keywords are preserved even with truncation
|
|
614
|
+
assert!(
|
|
615
|
+
output.contains("static") && output.contains("final"),
|
|
616
|
+
"Missing 'static final' keywords with arrays - output: {}",
|
|
617
|
+
output
|
|
618
|
+
);
|
|
619
|
+
|
|
620
|
+
assert!(
|
|
621
|
+
output.contains("public") && output.contains("List"),
|
|
622
|
+
"Missing 'public' keyword and 'List' type with collections - output: {}",
|
|
623
|
+
output
|
|
624
|
+
);
|
|
625
|
+
|
|
626
|
+
// Test specifically searching for collection-related keywords
|
|
627
|
+
let list_output = ctx.run_probe(&[
|
|
628
|
+
"search",
|
|
629
|
+
"List",
|
|
630
|
+
test_file.to_str().unwrap(),
|
|
631
|
+
"--format",
|
|
632
|
+
"outline",
|
|
633
|
+
"--allow-tests",
|
|
634
|
+
])?;
|
|
635
|
+
|
|
636
|
+
assert!(
|
|
637
|
+
list_output.contains("List"),
|
|
638
|
+
"Missing 'List' keyword in collection search - output: {}",
|
|
639
|
+
list_output
|
|
640
|
+
);
|
|
641
|
+
|
|
642
|
+
// Test Map keyword search
|
|
643
|
+
let map_output = ctx.run_probe(&[
|
|
644
|
+
"search",
|
|
645
|
+
"Map",
|
|
646
|
+
test_file.to_str().unwrap(),
|
|
647
|
+
"--format",
|
|
648
|
+
"outline",
|
|
649
|
+
"--allow-tests",
|
|
650
|
+
])?;
|
|
651
|
+
|
|
652
|
+
assert!(
|
|
653
|
+
map_output.contains("Map"),
|
|
654
|
+
"Missing 'Map' keyword in collection search - output: {}",
|
|
655
|
+
map_output
|
|
656
|
+
);
|
|
657
|
+
|
|
658
|
+
Ok(())
|
|
659
|
+
}
|
|
660
|
+
|
|
661
|
+
#[test]
|
|
662
|
+
fn test_java_outline_modern_features() -> Result<()> {
|
|
663
|
+
let temp_dir = TempDir::new()?;
|
|
664
|
+
let test_file = temp_dir.path().join("modern_java.java");
|
|
665
|
+
|
|
666
|
+
let content = r#"package com.example.modern;
|
|
667
|
+
|
|
668
|
+
import java.util.*;
|
|
669
|
+
import java.util.stream.Stream;
|
|
670
|
+
import java.util.concurrent.CompletableFuture;
|
|
671
|
+
import java.util.function.*;
|
|
672
|
+
|
|
673
|
+
// Modern Java features (Java 14+)
|
|
674
|
+
public sealed class Shape permits Circle, Rectangle, Triangle {
|
|
675
|
+
protected final String color;
|
|
676
|
+
|
|
677
|
+
public Shape(String color) {
|
|
678
|
+
this.color = color;
|
|
679
|
+
}
|
|
680
|
+
|
|
681
|
+
public abstract double area();
|
|
682
|
+
}
|
|
683
|
+
|
|
684
|
+
final class Circle extends Shape {
|
|
685
|
+
private final double radius;
|
|
686
|
+
|
|
687
|
+
public Circle(String color, double radius) {
|
|
688
|
+
super(color);
|
|
689
|
+
this.radius = radius;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
@Override
|
|
693
|
+
public double area() {
|
|
694
|
+
return Math.PI * radius * radius;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
final class Rectangle extends Shape {
|
|
699
|
+
private final double width, height;
|
|
700
|
+
|
|
701
|
+
public Rectangle(String color, double width, double height) {
|
|
702
|
+
super(color);
|
|
703
|
+
this.width = width;
|
|
704
|
+
this.height = height;
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
@Override
|
|
708
|
+
public double area() {
|
|
709
|
+
return width * height;
|
|
710
|
+
}
|
|
711
|
+
}
|
|
712
|
+
|
|
713
|
+
final class Triangle extends Shape {
|
|
714
|
+
private final double base, height;
|
|
715
|
+
|
|
716
|
+
public Triangle(String color, double base, double height) {
|
|
717
|
+
super(color);
|
|
718
|
+
this.base = base;
|
|
719
|
+
this.height = height;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
@Override
|
|
723
|
+
public double area() {
|
|
724
|
+
return 0.5 * base * height;
|
|
725
|
+
}
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// Record class (Java 14+)
|
|
729
|
+
public record Point(double x, double y) {
|
|
730
|
+
// Compact constructor
|
|
731
|
+
public Point {
|
|
732
|
+
if (x < 0 || y < 0) {
|
|
733
|
+
throw new IllegalArgumentException("Coordinates must be positive");
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
// Additional methods
|
|
738
|
+
public double distanceFromOrigin() {
|
|
739
|
+
return Math.sqrt(x * x + y * y);
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
public Point translate(double dx, double dy) {
|
|
743
|
+
return new Point(x + dx, y + dy);
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
|
|
747
|
+
// Another record with more complex features
|
|
748
|
+
public record Person(String name, int age, List<String> hobbies) {
|
|
749
|
+
// Static factory method
|
|
750
|
+
public static Person of(String name, int age) {
|
|
751
|
+
return new Person(name, age, new ArrayList<>());
|
|
752
|
+
}
|
|
753
|
+
|
|
754
|
+
// Validation in compact constructor
|
|
755
|
+
public Person {
|
|
756
|
+
if (name == null || name.isBlank()) {
|
|
757
|
+
throw new IllegalArgumentException("Name cannot be null or blank");
|
|
758
|
+
}
|
|
759
|
+
if (age < 0) {
|
|
760
|
+
throw new IllegalArgumentException("Age cannot be negative");
|
|
761
|
+
}
|
|
762
|
+
hobbies = List.copyOf(hobbies); // Defensive copy
|
|
763
|
+
}
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
// Modern stream and lambda usage
|
|
767
|
+
public class ModernJavaProcessor {
|
|
768
|
+
// Using streams with complex lambda expressions
|
|
769
|
+
public List<String> processData(List<Person> people) {
|
|
770
|
+
return people.stream()
|
|
771
|
+
.filter(person -> person.age() >= 18)
|
|
772
|
+
.filter(person -> !person.hobbies().isEmpty())
|
|
773
|
+
.map(person -> person.name().toUpperCase())
|
|
774
|
+
.sorted()
|
|
775
|
+
.distinct()
|
|
776
|
+
.collect(Collectors.toList());
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
// Using Optional (Java 8+)
|
|
780
|
+
public Optional<Person> findOldestPerson(List<Person> people) {
|
|
781
|
+
return people.stream()
|
|
782
|
+
.max(Comparator.comparing(Person::age));
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
// Using CompletableFuture (Java 8+)
|
|
786
|
+
public CompletableFuture<String> processAsyncData(List<Integer> data) {
|
|
787
|
+
return CompletableFuture.supplyAsync(() -> {
|
|
788
|
+
return data.stream()
|
|
789
|
+
.parallel()
|
|
790
|
+
.mapToInt(Integer::intValue)
|
|
791
|
+
.filter(x -> x > 0)
|
|
792
|
+
.map(x -> x * x)
|
|
793
|
+
.sum();
|
|
794
|
+
}).thenApply(result -> "Result: " + result);
|
|
795
|
+
}
|
|
796
|
+
|
|
797
|
+
// Method references and functional interfaces
|
|
798
|
+
public List<Double> calculateAreas(List<Shape> shapes) {
|
|
799
|
+
return shapes.stream()
|
|
800
|
+
.map(Shape::area)
|
|
801
|
+
.sorted(Double::compareTo)
|
|
802
|
+
.collect(Collectors.toList());
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
// Pattern matching with instanceof (Java 14+)
|
|
806
|
+
public String describeShape(Shape shape) {
|
|
807
|
+
if (shape instanceof Circle c) {
|
|
808
|
+
return "Circle with radius: " + c.radius;
|
|
809
|
+
} else if (shape instanceof Rectangle r) {
|
|
810
|
+
return "Rectangle: " + r.width + "x" + r.height;
|
|
811
|
+
} else if (shape instanceof Triangle t) {
|
|
812
|
+
return "Triangle: base=" + t.base + ", height=" + t.height;
|
|
813
|
+
} else {
|
|
814
|
+
return "Unknown shape";
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
}
|
|
818
|
+
"#;
|
|
819
|
+
|
|
820
|
+
fs::write(&test_file, content)?;
|
|
821
|
+
|
|
822
|
+
let ctx = TestContext::new();
|
|
823
|
+
let output = ctx.run_probe(&[
|
|
824
|
+
"search",
|
|
825
|
+
"Calculator",
|
|
826
|
+
test_file.to_str().unwrap(),
|
|
827
|
+
"--format",
|
|
828
|
+
"outline",
|
|
829
|
+
"--allow-tests",
|
|
830
|
+
])?;
|
|
831
|
+
|
|
832
|
+
// Test sealed class detection
|
|
833
|
+
assert!(
|
|
834
|
+
output.contains("sealed") || output.contains("Shape"),
|
|
835
|
+
"Missing sealed class in outline - output: {}",
|
|
836
|
+
output
|
|
837
|
+
);
|
|
838
|
+
|
|
839
|
+
// Test record detection
|
|
840
|
+
assert!(
|
|
841
|
+
output.contains("record") || output.contains("Point") || output.contains("Person"),
|
|
842
|
+
"Missing record class in outline - output: {}",
|
|
843
|
+
output
|
|
844
|
+
);
|
|
845
|
+
|
|
846
|
+
// Test modern features are recognized
|
|
847
|
+
assert!(
|
|
848
|
+
output.contains("Optional")
|
|
849
|
+
|| output.contains("CompletableFuture")
|
|
850
|
+
|| output.contains("stream"),
|
|
851
|
+
"Missing modern Java features in outline - output: {}",
|
|
852
|
+
output
|
|
853
|
+
);
|
|
854
|
+
|
|
855
|
+
// Search specifically for modern keywords
|
|
856
|
+
let record_output = ctx.run_probe(&[
|
|
857
|
+
"search",
|
|
858
|
+
"record",
|
|
859
|
+
test_file.to_str().unwrap(),
|
|
860
|
+
"--format",
|
|
861
|
+
"outline",
|
|
862
|
+
"--allow-tests",
|
|
863
|
+
])?;
|
|
864
|
+
|
|
865
|
+
assert!(
|
|
866
|
+
record_output.contains("record"),
|
|
867
|
+
"Missing 'record' keyword search in outline - output: {}",
|
|
868
|
+
record_output
|
|
869
|
+
);
|
|
870
|
+
|
|
871
|
+
// Search for sealed keyword
|
|
872
|
+
let sealed_output = ctx.run_probe(&[
|
|
873
|
+
"search",
|
|
874
|
+
"sealed",
|
|
875
|
+
test_file.to_str().unwrap(),
|
|
876
|
+
"--format",
|
|
877
|
+
"outline",
|
|
878
|
+
"--allow-tests",
|
|
879
|
+
])?;
|
|
880
|
+
|
|
881
|
+
assert!(
|
|
882
|
+
sealed_output.contains("sealed"),
|
|
883
|
+
"Missing 'sealed' keyword search in outline - output: {}",
|
|
884
|
+
sealed_output
|
|
885
|
+
);
|
|
886
|
+
|
|
887
|
+
// Search for stream operations
|
|
888
|
+
let stream_output = ctx.run_probe(&[
|
|
889
|
+
"search",
|
|
890
|
+
"stream",
|
|
891
|
+
test_file.to_str().unwrap(),
|
|
892
|
+
"--format",
|
|
893
|
+
"outline",
|
|
894
|
+
"--allow-tests",
|
|
895
|
+
])?;
|
|
896
|
+
|
|
897
|
+
assert!(
|
|
898
|
+
stream_output.contains("stream"),
|
|
899
|
+
"Missing 'stream' keyword in modern features outline - output: {}",
|
|
900
|
+
stream_output
|
|
901
|
+
);
|
|
902
|
+
|
|
903
|
+
Ok(())
|
|
904
|
+
}
|
|
905
|
+
|
|
906
|
+
#[test]
|
|
907
|
+
fn test_java_outline_test_detection_patterns() -> Result<()> {
|
|
908
|
+
let temp_dir = TempDir::new()?;
|
|
909
|
+
let test_file = temp_dir.path().join("test_patterns.java");
|
|
910
|
+
|
|
911
|
+
let content = r#"package com.example.tests;
|
|
912
|
+
|
|
913
|
+
import org.junit.jupiter.api.Test;
|
|
914
|
+
import org.junit.jupiter.api.BeforeEach;
|
|
915
|
+
import org.junit.jupiter.api.AfterEach;
|
|
916
|
+
import org.junit.jupiter.api.DisplayName;
|
|
917
|
+
import org.junit.jupiter.api.ParameterizedTest;
|
|
918
|
+
import org.junit.jupiter.api.ValueSource;
|
|
919
|
+
import org.junit.jupiter.api.TestMethodOrder;
|
|
920
|
+
import org.junit.jupiter.api.MethodOrderer;
|
|
921
|
+
import org.testng.annotations.DataProvider;
|
|
922
|
+
import org.testng.annotations.BeforeMethod;
|
|
923
|
+
import org.testng.annotations.AfterMethod;
|
|
924
|
+
import static org.junit.jupiter.api.Assertions.*;
|
|
925
|
+
import static org.testng.Assert.*;
|
|
926
|
+
|
|
927
|
+
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
|
|
928
|
+
public class JavaTestDetectionTest {
|
|
929
|
+
private Calculator calculator;
|
|
930
|
+
private List<String> testData;
|
|
931
|
+
|
|
932
|
+
@BeforeEach
|
|
933
|
+
public void setUp() {
|
|
934
|
+
calculator = new Calculator();
|
|
935
|
+
testData = Arrays.asList("test1", "test2", "test3");
|
|
936
|
+
}
|
|
937
|
+
|
|
938
|
+
@AfterEach
|
|
939
|
+
public void tearDown() {
|
|
940
|
+
calculator = null;
|
|
941
|
+
testData.clear();
|
|
942
|
+
}
|
|
943
|
+
|
|
944
|
+
// JUnit 5 test methods
|
|
945
|
+
@Test
|
|
946
|
+
@DisplayName("Test basic addition functionality")
|
|
947
|
+
public void testBasicAddition() {
|
|
948
|
+
double result = calculator.add(2.0, 3.0);
|
|
949
|
+
assertEquals(5.0, result, 0.001);
|
|
950
|
+
assertNotNull(result);
|
|
951
|
+
assertTrue(result > 0);
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
@Test
|
|
955
|
+
public void testSubtraction() {
|
|
956
|
+
double result = calculator.subtract(10.0, 4.0);
|
|
957
|
+
assertEquals(6.0, result);
|
|
958
|
+
assertFalse(result < 0);
|
|
959
|
+
}
|
|
960
|
+
|
|
961
|
+
@Test
|
|
962
|
+
public void testMultiplication() {
|
|
963
|
+
double result = calculator.multiply(3.0, 4.0);
|
|
964
|
+
assertEquals(12.0, result);
|
|
965
|
+
assertThat(result, greaterThan(10.0));
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
@Test
|
|
969
|
+
public void testDivision() {
|
|
970
|
+
double result = calculator.divide(15.0, 3.0);
|
|
971
|
+
assertEquals(5.0, result);
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
@Test
|
|
975
|
+
public void testDivisionByZero() {
|
|
976
|
+
ArithmeticException exception = assertThrows(
|
|
977
|
+
ArithmeticException.class,
|
|
978
|
+
() -> calculator.divide(10.0, 0.0)
|
|
979
|
+
);
|
|
980
|
+
assertThat(exception.getMessage(), containsString("zero"));
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
// Parameterized test
|
|
984
|
+
@ParameterizedTest
|
|
985
|
+
@ValueSource(ints = {1, 2, 3, 5, 8, 13})
|
|
986
|
+
public void testPositiveNumbers(int number) {
|
|
987
|
+
assertTrue(number > 0);
|
|
988
|
+
assertNotEquals(0, number);
|
|
989
|
+
}
|
|
990
|
+
|
|
991
|
+
@ParameterizedTest
|
|
992
|
+
@ValueSource(strings = {"hello", "world", "test"})
|
|
993
|
+
public void testStringLength(String input) {
|
|
994
|
+
assertNotNull(input);
|
|
995
|
+
assertTrue(input.length() > 0);
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
// TestNG style tests
|
|
999
|
+
@org.testng.annotations.Test
|
|
1000
|
+
public void testNGBasicTest() {
|
|
1001
|
+
int result = 2 + 2;
|
|
1002
|
+
org.testng.Assert.assertEquals(result, 4);
|
|
1003
|
+
org.testng.Assert.assertTrue(result > 0);
|
|
1004
|
+
}
|
|
1005
|
+
|
|
1006
|
+
@org.testng.annotations.Test(groups = "integration")
|
|
1007
|
+
public void testNGIntegrationTest() {
|
|
1008
|
+
String message = "Hello World";
|
|
1009
|
+
org.testng.Assert.assertNotNull(message);
|
|
1010
|
+
org.testng.Assert.assertTrue(message.contains("World"));
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
@DataProvider(name = "testData")
|
|
1014
|
+
public Object[][] createTestData() {
|
|
1015
|
+
return new Object[][] {
|
|
1016
|
+
{"test1", 5},
|
|
1017
|
+
{"test2", 10},
|
|
1018
|
+
{"test3", 15}
|
|
1019
|
+
};
|
|
1020
|
+
}
|
|
1021
|
+
|
|
1022
|
+
@org.testng.annotations.Test(dataProvider = "testData")
|
|
1023
|
+
public void testNGWithDataProvider(String name, int value) {
|
|
1024
|
+
org.testng.Assert.assertNotNull(name);
|
|
1025
|
+
org.testng.Assert.assertTrue(value > 0);
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
@BeforeMethod
|
|
1029
|
+
public void testNGSetUp() {
|
|
1030
|
+
System.out.println("TestNG setup");
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
@AfterMethod
|
|
1034
|
+
public void testNGTearDown() {
|
|
1035
|
+
System.out.println("TestNG teardown");
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
// Traditional assert-based testing
|
|
1039
|
+
public void testTraditionalAsserts() {
|
|
1040
|
+
String message = "test message";
|
|
1041
|
+
assert message != null : "Message should not be null";
|
|
1042
|
+
assert message.length() > 0 : "Message should not be empty";
|
|
1043
|
+
assert message.contains("test") : "Message should contain 'test'";
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
// Mock testing patterns
|
|
1047
|
+
@Test
|
|
1048
|
+
public void testWithMocks() {
|
|
1049
|
+
// Arrange
|
|
1050
|
+
Calculator mockCalculator = mock(Calculator.class);
|
|
1051
|
+
when(mockCalculator.add(2.0, 3.0)).thenReturn(5.0);
|
|
1052
|
+
|
|
1053
|
+
// Act
|
|
1054
|
+
double result = mockCalculator.add(2.0, 3.0);
|
|
1055
|
+
|
|
1056
|
+
// Assert
|
|
1057
|
+
assertEquals(5.0, result);
|
|
1058
|
+
verify(mockCalculator, times(1)).add(2.0, 3.0);
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
// Nested test class
|
|
1062
|
+
@Nested
|
|
1063
|
+
@DisplayName("Tests for negative numbers")
|
|
1064
|
+
class NegativeNumberTests {
|
|
1065
|
+
@Test
|
|
1066
|
+
public void testNegativeAddition() {
|
|
1067
|
+
double result = calculator.add(-2.0, -3.0);
|
|
1068
|
+
assertEquals(-5.0, result);
|
|
1069
|
+
}
|
|
1070
|
+
|
|
1071
|
+
@Test
|
|
1072
|
+
public void testNegativeSubtraction() {
|
|
1073
|
+
double result = calculator.subtract(-10.0, -4.0);
|
|
1074
|
+
assertEquals(-6.0, result);
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
}
|
|
1078
|
+
"#;
|
|
1079
|
+
|
|
1080
|
+
fs::write(&test_file, content)?;
|
|
1081
|
+
|
|
1082
|
+
let ctx = TestContext::new();
|
|
1083
|
+
let output = ctx.run_probe(&[
|
|
1084
|
+
"search",
|
|
1085
|
+
"Calculator",
|
|
1086
|
+
test_file.to_str().unwrap(),
|
|
1087
|
+
"--format",
|
|
1088
|
+
"outline",
|
|
1089
|
+
"--allow-tests",
|
|
1090
|
+
])?;
|
|
1091
|
+
|
|
1092
|
+
// Test JUnit pattern detection
|
|
1093
|
+
assert!(
|
|
1094
|
+
output.contains("@Test") || output.contains("test"),
|
|
1095
|
+
"Missing JUnit @Test annotation or test methods in outline - output: {}",
|
|
1096
|
+
output
|
|
1097
|
+
);
|
|
1098
|
+
|
|
1099
|
+
// Test method naming patterns
|
|
1100
|
+
assert!(
|
|
1101
|
+
output.contains("testBasicAddition") || output.contains("testSubtraction"),
|
|
1102
|
+
"Missing test method names in outline - output: {}",
|
|
1103
|
+
output
|
|
1104
|
+
);
|
|
1105
|
+
|
|
1106
|
+
// Test assertion patterns
|
|
1107
|
+
assert!(
|
|
1108
|
+
output.contains("assert")
|
|
1109
|
+
|| output.contains("assertEquals")
|
|
1110
|
+
|| output.contains("assertTrue"),
|
|
1111
|
+
"Missing assertion patterns in outline - output: {}",
|
|
1112
|
+
output
|
|
1113
|
+
);
|
|
1114
|
+
|
|
1115
|
+
// Search for JUnit specific patterns
|
|
1116
|
+
let junit_output = ctx.run_probe(&[
|
|
1117
|
+
"search",
|
|
1118
|
+
"@Test",
|
|
1119
|
+
test_file.to_str().unwrap(),
|
|
1120
|
+
"--format",
|
|
1121
|
+
"outline",
|
|
1122
|
+
"--allow-tests",
|
|
1123
|
+
])?;
|
|
1124
|
+
|
|
1125
|
+
assert!(
|
|
1126
|
+
junit_output.contains("@Test"),
|
|
1127
|
+
"Missing '@Test' annotation search in outline - output: {}",
|
|
1128
|
+
junit_output
|
|
1129
|
+
);
|
|
1130
|
+
|
|
1131
|
+
// Search for TestNG patterns
|
|
1132
|
+
let testng_output = ctx.run_probe(&[
|
|
1133
|
+
"search",
|
|
1134
|
+
"testng",
|
|
1135
|
+
test_file.to_str().unwrap(),
|
|
1136
|
+
"--format",
|
|
1137
|
+
"outline",
|
|
1138
|
+
"--allow-tests",
|
|
1139
|
+
])?;
|
|
1140
|
+
|
|
1141
|
+
assert!(
|
|
1142
|
+
testng_output.contains("testng") || testng_output.contains("TestNG"),
|
|
1143
|
+
"Missing 'testng' pattern search in outline - output: {}",
|
|
1144
|
+
testng_output
|
|
1145
|
+
);
|
|
1146
|
+
|
|
1147
|
+
// Search for assertion keywords
|
|
1148
|
+
let assert_output = ctx.run_probe(&[
|
|
1149
|
+
"search",
|
|
1150
|
+
"assert",
|
|
1151
|
+
test_file.to_str().unwrap(),
|
|
1152
|
+
"--format",
|
|
1153
|
+
"outline",
|
|
1154
|
+
"--allow-tests",
|
|
1155
|
+
])?;
|
|
1156
|
+
|
|
1157
|
+
assert!(
|
|
1158
|
+
assert_output.contains("assert"),
|
|
1159
|
+
"Missing 'assert' keyword in test assertion outline - output: {}",
|
|
1160
|
+
assert_output
|
|
1161
|
+
);
|
|
1162
|
+
|
|
1163
|
+
Ok(())
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
#[test]
|
|
1167
|
+
fn test_java_outline_nested_control_flow() -> Result<()> {
|
|
1168
|
+
let temp_dir = TempDir::new()?;
|
|
1169
|
+
let test_file = temp_dir.path().join("nested_control_flow.java");
|
|
1170
|
+
|
|
1171
|
+
let content = r#"package com.example.controlflow;
|
|
1172
|
+
|
|
1173
|
+
import java.util.*;
|
|
1174
|
+
|
|
1175
|
+
public class NestedControlFlowTest {
|
|
1176
|
+
// Large method with deeply nested control flow that should get closing brace comments
|
|
1177
|
+
public static Map<String, Object> processComplexData(
|
|
1178
|
+
List<Map<String, Object>> dataList,
|
|
1179
|
+
Map<String, String> config,
|
|
1180
|
+
Set<String> validKeys) {
|
|
1181
|
+
|
|
1182
|
+
Map<String, Object> result = new HashMap<>();
|
|
1183
|
+
List<String> errors = new ArrayList<>();
|
|
1184
|
+
int processedCount = 0;
|
|
1185
|
+
|
|
1186
|
+
// Main processing loop with nested conditions
|
|
1187
|
+
for (Map<String, Object> dataItem : dataList) {
|
|
1188
|
+
if (dataItem == null || dataItem.isEmpty()) {
|
|
1189
|
+
errors.add("Empty data item at index " + processedCount);
|
|
1190
|
+
continue;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// Validate all keys in the data item
|
|
1194
|
+
for (String key : dataItem.keySet()) {
|
|
1195
|
+
if (!validKeys.contains(key)) {
|
|
1196
|
+
errors.add("Invalid key: " + key + " at index " + processedCount);
|
|
1197
|
+
continue;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
Object value = dataItem.get(key);
|
|
1201
|
+
if (value == null) {
|
|
1202
|
+
continue;
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
// Process different types of values
|
|
1206
|
+
if (value instanceof String) {
|
|
1207
|
+
String stringValue = (String) value;
|
|
1208
|
+
if (stringValue.trim().isEmpty()) {
|
|
1209
|
+
errors.add("Empty string value for key: " + key);
|
|
1210
|
+
continue;
|
|
1211
|
+
}
|
|
1212
|
+
|
|
1213
|
+
// Process string with configuration-based transformations
|
|
1214
|
+
switch (config.getOrDefault(key + "_transform", "none")) {
|
|
1215
|
+
case "uppercase":
|
|
1216
|
+
result.put(key + "_processed", stringValue.toUpperCase());
|
|
1217
|
+
break;
|
|
1218
|
+
case "lowercase":
|
|
1219
|
+
result.put(key + "_processed", stringValue.toLowerCase());
|
|
1220
|
+
break;
|
|
1221
|
+
case "reverse":
|
|
1222
|
+
result.put(key + "_processed", new StringBuilder(stringValue).reverse().toString());
|
|
1223
|
+
break;
|
|
1224
|
+
case "length":
|
|
1225
|
+
result.put(key + "_processed", stringValue.length());
|
|
1226
|
+
break;
|
|
1227
|
+
default:
|
|
1228
|
+
result.put(key + "_processed", stringValue.trim());
|
|
1229
|
+
break;
|
|
1230
|
+
}
|
|
1231
|
+
} else if (value instanceof Number) {
|
|
1232
|
+
Number numberValue = (Number) value;
|
|
1233
|
+
double doubleVal = numberValue.doubleValue();
|
|
1234
|
+
|
|
1235
|
+
// Apply mathematical transformations based on config
|
|
1236
|
+
if (config.containsKey(key + "_math")) {
|
|
1237
|
+
String mathOp = config.get(key + "_math");
|
|
1238
|
+
switch (mathOp) {
|
|
1239
|
+
case "square":
|
|
1240
|
+
result.put(key + "_processed", doubleVal * doubleVal);
|
|
1241
|
+
break;
|
|
1242
|
+
case "sqrt":
|
|
1243
|
+
if (doubleVal >= 0) {
|
|
1244
|
+
result.put(key + "_processed", Math.sqrt(doubleVal));
|
|
1245
|
+
} else {
|
|
1246
|
+
errors.add("Cannot take sqrt of negative number: " + doubleVal);
|
|
1247
|
+
}
|
|
1248
|
+
break;
|
|
1249
|
+
case "log":
|
|
1250
|
+
if (doubleVal > 0) {
|
|
1251
|
+
result.put(key + "_processed", Math.log(doubleVal));
|
|
1252
|
+
} else {
|
|
1253
|
+
errors.add("Cannot take log of non-positive number: " + doubleVal);
|
|
1254
|
+
}
|
|
1255
|
+
break;
|
|
1256
|
+
case "abs":
|
|
1257
|
+
result.put(key + "_processed", Math.abs(doubleVal));
|
|
1258
|
+
break;
|
|
1259
|
+
default:
|
|
1260
|
+
result.put(key + "_processed", doubleVal);
|
|
1261
|
+
break;
|
|
1262
|
+
}
|
|
1263
|
+
} else {
|
|
1264
|
+
result.put(key + "_processed", doubleVal);
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
}
|
|
1268
|
+
|
|
1269
|
+
processedCount++;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
result.put("_meta_processed_count", processedCount);
|
|
1273
|
+
result.put("_meta_error_count", errors.size());
|
|
1274
|
+
if (!errors.isEmpty()) {
|
|
1275
|
+
result.put("_meta_errors", errors);
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
return result;
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// Method with try-catch-finally and nested loops
|
|
1282
|
+
public void processWithExceptionHandling(List<String> data) {
|
|
1283
|
+
for (String item : data) {
|
|
1284
|
+
try {
|
|
1285
|
+
if (item == null) {
|
|
1286
|
+
continue;
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
for (int i = 0; i < item.length(); i++) {
|
|
1290
|
+
char c = item.charAt(i);
|
|
1291
|
+
if (Character.isDigit(c)) {
|
|
1292
|
+
int digit = Character.getNumericValue(c);
|
|
1293
|
+
for (int j = 0; j < digit; j++) {
|
|
1294
|
+
try {
|
|
1295
|
+
processDigit(digit, j);
|
|
1296
|
+
} catch (NumberFormatException e) {
|
|
1297
|
+
System.err.println("Number format error: " + e.getMessage());
|
|
1298
|
+
continue;
|
|
1299
|
+
} catch (ArithmeticException e) {
|
|
1300
|
+
System.err.println("Arithmetic error: " + e.getMessage());
|
|
1301
|
+
break;
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
} else if (Character.isLetter(c)) {
|
|
1305
|
+
processLetter(c);
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
} catch (StringIndexOutOfBoundsException e) {
|
|
1309
|
+
System.err.println("String index error: " + e.getMessage());
|
|
1310
|
+
} catch (Exception e) {
|
|
1311
|
+
System.err.println("Unexpected error: " + e.getMessage());
|
|
1312
|
+
} finally {
|
|
1313
|
+
System.out.println("Finished processing item: " + item);
|
|
1314
|
+
}
|
|
1315
|
+
}
|
|
1316
|
+
}
|
|
1317
|
+
|
|
1318
|
+
private void processDigit(int digit, int position) {
|
|
1319
|
+
// Implementation
|
|
1320
|
+
}
|
|
1321
|
+
|
|
1322
|
+
private void processLetter(char letter) {
|
|
1323
|
+
// Implementation
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
"#;
|
|
1327
|
+
|
|
1328
|
+
fs::write(&test_file, content)?;
|
|
1329
|
+
|
|
1330
|
+
let ctx = TestContext::new();
|
|
1331
|
+
let output = ctx.run_probe(&[
|
|
1332
|
+
"search",
|
|
1333
|
+
"Calculator",
|
|
1334
|
+
test_file.to_str().unwrap(),
|
|
1335
|
+
"--format",
|
|
1336
|
+
"outline",
|
|
1337
|
+
"--allow-tests",
|
|
1338
|
+
])?;
|
|
1339
|
+
|
|
1340
|
+
// Verify nested control flow structures are shown
|
|
1341
|
+
assert!(
|
|
1342
|
+
output.contains("for") || output.contains("if") || output.contains("switch"),
|
|
1343
|
+
"Missing nested control flow keywords in outline - output: {}",
|
|
1344
|
+
output
|
|
1345
|
+
);
|
|
1346
|
+
|
|
1347
|
+
// Verify exception handling structures
|
|
1348
|
+
assert!(
|
|
1349
|
+
output.contains("try") || output.contains("catch") || output.contains("finally"),
|
|
1350
|
+
"Missing exception handling keywords in outline - output: {}",
|
|
1351
|
+
output
|
|
1352
|
+
);
|
|
1353
|
+
|
|
1354
|
+
// Large methods should have closing brace comments (Java // style)
|
|
1355
|
+
let has_closing_brace_comments = output.contains("} //");
|
|
1356
|
+
let has_ellipsis = output.contains("...");
|
|
1357
|
+
|
|
1358
|
+
// Either we should see closing brace comments (if there are gaps) or the method should be truncated
|
|
1359
|
+
assert!(
|
|
1360
|
+
has_closing_brace_comments || has_ellipsis,
|
|
1361
|
+
"Large nested method should either have closing brace comments or be truncated - output: {}",
|
|
1362
|
+
output
|
|
1363
|
+
);
|
|
1364
|
+
|
|
1365
|
+
// Test searching for specific control flow patterns
|
|
1366
|
+
let switch_output = ctx.run_probe(&[
|
|
1367
|
+
"search",
|
|
1368
|
+
"switch",
|
|
1369
|
+
test_file.to_str().unwrap(),
|
|
1370
|
+
"--format",
|
|
1371
|
+
"outline",
|
|
1372
|
+
"--allow-tests",
|
|
1373
|
+
])?;
|
|
1374
|
+
|
|
1375
|
+
assert!(
|
|
1376
|
+
switch_output.contains("switch"),
|
|
1377
|
+
"Missing 'switch' keyword in nested control flow outline - output: {}",
|
|
1378
|
+
switch_output
|
|
1379
|
+
);
|
|
1380
|
+
|
|
1381
|
+
Ok(())
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1384
|
+
#[test]
|
|
1385
|
+
fn test_java_outline_small_vs_large_functions() -> Result<()> {
|
|
1386
|
+
let temp_dir = TempDir::new()?;
|
|
1387
|
+
let test_file = temp_dir.path().join("function_sizes.java");
|
|
1388
|
+
|
|
1389
|
+
let content = r#"package com.example.sizes;
|
|
1390
|
+
|
|
1391
|
+
import java.util.*;
|
|
1392
|
+
|
|
1393
|
+
public class FunctionSizeTest {
|
|
1394
|
+
// Small function - should NOT get closing brace comments (under 20 lines)
|
|
1395
|
+
public static int smallFunction(int x, int y) {
|
|
1396
|
+
int result = x + y;
|
|
1397
|
+
if (result > 100) {
|
|
1398
|
+
result = 100;
|
|
1399
|
+
}
|
|
1400
|
+
return result * 2;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
// Another small function
|
|
1404
|
+
public String formatString(String input) {
|
|
1405
|
+
if (input == null) {
|
|
1406
|
+
return "";
|
|
1407
|
+
}
|
|
1408
|
+
return input.trim().toUpperCase();
|
|
1409
|
+
}
|
|
1410
|
+
|
|
1411
|
+
// Small helper method
|
|
1412
|
+
private boolean isValid(Object obj) {
|
|
1413
|
+
return obj != null;
|
|
1414
|
+
}
|
|
1415
|
+
|
|
1416
|
+
// Large function - SHOULD get closing brace comments (over 20 lines with gaps)
|
|
1417
|
+
public static List<Map<String, Object>> largeFunctionWithManyLines(
|
|
1418
|
+
List<String> inputData,
|
|
1419
|
+
Map<String, String> configuration,
|
|
1420
|
+
boolean enableProcessing) {
|
|
1421
|
+
|
|
1422
|
+
List<Map<String, Object>> results = new ArrayList<>();
|
|
1423
|
+
Map<String, Integer> counters = new HashMap<>();
|
|
1424
|
+
Set<String> processedKeys = new HashSet<>();
|
|
1425
|
+
|
|
1426
|
+
// Initialize counters
|
|
1427
|
+
counters.put("total", 0);
|
|
1428
|
+
counters.put("processed", 0);
|
|
1429
|
+
counters.put("skipped", 0);
|
|
1430
|
+
counters.put("errors", 0);
|
|
1431
|
+
|
|
1432
|
+
// Main processing logic
|
|
1433
|
+
for (String item : inputData) {
|
|
1434
|
+
counters.put("total", counters.get("total") + 1);
|
|
1435
|
+
|
|
1436
|
+
if (item == null || item.trim().isEmpty()) {
|
|
1437
|
+
counters.put("skipped", counters.get("skipped") + 1);
|
|
1438
|
+
continue;
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
try {
|
|
1442
|
+
Map<String, Object> processedItem = new HashMap<>();
|
|
1443
|
+
String key = "item_" + counters.get("total");
|
|
1444
|
+
|
|
1445
|
+
if (enableProcessing) {
|
|
1446
|
+
// Complex processing logic
|
|
1447
|
+
String[] parts = item.split(",");
|
|
1448
|
+
for (int i = 0; i < parts.length; i++) {
|
|
1449
|
+
String part = parts[i].trim();
|
|
1450
|
+
if (!part.isEmpty()) {
|
|
1451
|
+
String partKey = key + "_part_" + i;
|
|
1452
|
+
|
|
1453
|
+
// Apply configuration-based transformations
|
|
1454
|
+
if (configuration.containsKey("transform_" + i)) {
|
|
1455
|
+
String transform = configuration.get("transform_" + i);
|
|
1456
|
+
switch (transform) {
|
|
1457
|
+
case "uppercase":
|
|
1458
|
+
part = part.toUpperCase();
|
|
1459
|
+
break;
|
|
1460
|
+
case "lowercase":
|
|
1461
|
+
part = part.toLowerCase();
|
|
1462
|
+
break;
|
|
1463
|
+
case "reverse":
|
|
1464
|
+
part = new StringBuilder(part).reverse().toString();
|
|
1465
|
+
break;
|
|
1466
|
+
default:
|
|
1467
|
+
// No transformation
|
|
1468
|
+
break;
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
|
|
1472
|
+
processedItem.put(partKey, part);
|
|
1473
|
+
processedKeys.add(partKey);
|
|
1474
|
+
}
|
|
1475
|
+
}
|
|
1476
|
+
|
|
1477
|
+
// Additional metadata
|
|
1478
|
+
processedItem.put("original", item);
|
|
1479
|
+
processedItem.put("parts_count", parts.length);
|
|
1480
|
+
processedItem.put("processed_at", System.currentTimeMillis());
|
|
1481
|
+
|
|
1482
|
+
} else {
|
|
1483
|
+
// Simple processing
|
|
1484
|
+
processedItem.put("value", item);
|
|
1485
|
+
processedItem.put("length", item.length());
|
|
1486
|
+
processedKeys.add(key);
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
results.add(processedItem);
|
|
1490
|
+
counters.put("processed", counters.get("processed") + 1);
|
|
1491
|
+
|
|
1492
|
+
} catch (Exception e) {
|
|
1493
|
+
counters.put("errors", counters.get("errors") + 1);
|
|
1494
|
+
System.err.println("Error processing item: " + item + " - " + e.getMessage());
|
|
1495
|
+
}
|
|
1496
|
+
}
|
|
1497
|
+
|
|
1498
|
+
// Add summary information
|
|
1499
|
+
Map<String, Object> summary = new HashMap<>();
|
|
1500
|
+
summary.put("counters", counters);
|
|
1501
|
+
summary.put("processed_keys_count", processedKeys.size());
|
|
1502
|
+
summary.put("results_count", results.size());
|
|
1503
|
+
results.add(0, summary);
|
|
1504
|
+
|
|
1505
|
+
return results;
|
|
1506
|
+
}
|
|
1507
|
+
|
|
1508
|
+
// Another large function with different patterns
|
|
1509
|
+
public void anotherLargeFunctionWithLoops(int n) {
|
|
1510
|
+
System.out.println("Starting processing for n = " + n);
|
|
1511
|
+
|
|
1512
|
+
// Outer loop
|
|
1513
|
+
for (int i = 0; i < n; i++) {
|
|
1514
|
+
System.out.println("Outer loop iteration: " + i);
|
|
1515
|
+
|
|
1516
|
+
// Inner loop with conditions
|
|
1517
|
+
for (int j = 0; j < i; j++) {
|
|
1518
|
+
if (j % 2 == 0) {
|
|
1519
|
+
System.out.println(" Even j: " + j);
|
|
1520
|
+
|
|
1521
|
+
// Nested processing
|
|
1522
|
+
for (int k = 0; k < j; k++) {
|
|
1523
|
+
if (k % 3 == 0) {
|
|
1524
|
+
System.out.println(" k divisible by 3: " + k);
|
|
1525
|
+
} else if (k % 3 == 1) {
|
|
1526
|
+
System.out.println(" k mod 3 = 1: " + k);
|
|
1527
|
+
} else {
|
|
1528
|
+
System.out.println(" k mod 3 = 2: " + k);
|
|
1529
|
+
}
|
|
1530
|
+
}
|
|
1531
|
+
} else {
|
|
1532
|
+
System.out.println(" Odd j: " + j);
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
|
|
1536
|
+
// Additional processing based on i
|
|
1537
|
+
if (i < n / 2) {
|
|
1538
|
+
System.out.println("First half processing");
|
|
1539
|
+
} else {
|
|
1540
|
+
System.out.println("Second half processing");
|
|
1541
|
+
}
|
|
1542
|
+
}
|
|
1543
|
+
|
|
1544
|
+
System.out.println("Completed processing");
|
|
1545
|
+
}
|
|
1546
|
+
}
|
|
1547
|
+
"#;
|
|
1548
|
+
|
|
1549
|
+
fs::write(&test_file, content)?;
|
|
1550
|
+
|
|
1551
|
+
let ctx = TestContext::new();
|
|
1552
|
+
let output = ctx.run_probe(&[
|
|
1553
|
+
"search",
|
|
1554
|
+
"Calculator",
|
|
1555
|
+
test_file.to_str().unwrap(),
|
|
1556
|
+
"--format",
|
|
1557
|
+
"outline",
|
|
1558
|
+
"--allow-tests",
|
|
1559
|
+
])?;
|
|
1560
|
+
|
|
1561
|
+
// Verify small functions are present
|
|
1562
|
+
assert!(
|
|
1563
|
+
output.contains("smallFunction")
|
|
1564
|
+
|| output.contains("formatString")
|
|
1565
|
+
|| output.contains("isValid"),
|
|
1566
|
+
"Missing small function names in outline - output: {}",
|
|
1567
|
+
output
|
|
1568
|
+
);
|
|
1569
|
+
|
|
1570
|
+
// Verify large functions are present
|
|
1571
|
+
assert!(
|
|
1572
|
+
output.contains("largeFunctionWithManyLines")
|
|
1573
|
+
|| output.contains("anotherLargeFunctionWithLoops"),
|
|
1574
|
+
"Missing large function names in outline - output: {}",
|
|
1575
|
+
output
|
|
1576
|
+
);
|
|
1577
|
+
|
|
1578
|
+
// Small functions should NOT have closing brace comments when shown completely
|
|
1579
|
+
let small_func_closing_braces = output.matches("} // smallFunction").count()
|
|
1580
|
+
+ output.matches("} // formatString").count()
|
|
1581
|
+
+ output.matches("} // isValid").count();
|
|
1582
|
+
|
|
1583
|
+
// Small functions should have few or no closing brace comments
|
|
1584
|
+
assert!(
|
|
1585
|
+
small_func_closing_braces <= 1,
|
|
1586
|
+
"Small functions should not have many closing brace comments - found: {} - output: {}",
|
|
1587
|
+
small_func_closing_braces,
|
|
1588
|
+
output
|
|
1589
|
+
);
|
|
1590
|
+
|
|
1591
|
+
// Large functions should either have closing brace comments or be truncated
|
|
1592
|
+
let has_large_func_closing_braces = output.contains("} // largeFunctionWithManyLines")
|
|
1593
|
+
|| output.contains("} // anotherLargeFunctionWithLoops")
|
|
1594
|
+
|| output.contains("} //");
|
|
1595
|
+
let has_ellipsis = output.contains("...");
|
|
1596
|
+
|
|
1597
|
+
assert!(
|
|
1598
|
+
has_large_func_closing_braces || has_ellipsis,
|
|
1599
|
+
"Large functions should either have closing brace comments or ellipsis truncation - output: {}",
|
|
1600
|
+
output
|
|
1601
|
+
);
|
|
1602
|
+
|
|
1603
|
+
// Verify the outline shows function structure appropriately
|
|
1604
|
+
assert!(
|
|
1605
|
+
output.contains("public static") && output.contains("private"),
|
|
1606
|
+
"Missing access modifiers in function outline - output: {}",
|
|
1607
|
+
output
|
|
1608
|
+
);
|
|
1609
|
+
|
|
1610
|
+
Ok(())
|
|
1611
|
+
}
|