@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,2179 @@
|
|
|
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_c_outline_basic_symbols() -> Result<()> {
|
|
10
|
+
let temp_dir = TempDir::new()?;
|
|
11
|
+
let test_file = temp_dir.path().join("basic.c");
|
|
12
|
+
|
|
13
|
+
let content = r#"// Basic C functions and structures for testing
|
|
14
|
+
#include <stdio.h>
|
|
15
|
+
#include <stdlib.h>
|
|
16
|
+
#include <string.h>
|
|
17
|
+
#include <math.h>
|
|
18
|
+
|
|
19
|
+
// Constants and macros
|
|
20
|
+
#define MAX_SIZE 100
|
|
21
|
+
#define PI 3.14159
|
|
22
|
+
#define SQUARE(x) ((x) * (x))
|
|
23
|
+
|
|
24
|
+
// Type definitions
|
|
25
|
+
typedef struct {
|
|
26
|
+
char name[50];
|
|
27
|
+
double* history;
|
|
28
|
+
int count;
|
|
29
|
+
int capacity;
|
|
30
|
+
} Calculator;
|
|
31
|
+
|
|
32
|
+
typedef enum {
|
|
33
|
+
OPERATION_ADD,
|
|
34
|
+
OPERATION_SUBTRACT,
|
|
35
|
+
OPERATION_MULTIPLY,
|
|
36
|
+
OPERATION_DIVIDE
|
|
37
|
+
} OperationType;
|
|
38
|
+
|
|
39
|
+
// Global variables
|
|
40
|
+
static Calculator* global_calculator = NULL;
|
|
41
|
+
const double DEFAULT_PRECISION = 0.01;
|
|
42
|
+
|
|
43
|
+
// Function prototypes
|
|
44
|
+
Calculator* create_calculator(const char* name);
|
|
45
|
+
void destroy_calculator(Calculator* calc);
|
|
46
|
+
double add_numbers(Calculator* calc, double x, double y);
|
|
47
|
+
double subtract_numbers(Calculator* calc, double x, double y);
|
|
48
|
+
double multiply_numbers(Calculator* calc, double x, double y);
|
|
49
|
+
double divide_numbers(Calculator* calc, double x, double y);
|
|
50
|
+
int get_history_count(const Calculator* calc);
|
|
51
|
+
double* get_history(const Calculator* calc);
|
|
52
|
+
|
|
53
|
+
// Function implementations
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Creates a new calculator instance
|
|
57
|
+
* @param name The name of the calculator
|
|
58
|
+
* @return Pointer to the new calculator or NULL on failure
|
|
59
|
+
*/
|
|
60
|
+
Calculator* create_calculator(const char* name) {
|
|
61
|
+
Calculator* calc = malloc(sizeof(Calculator));
|
|
62
|
+
if (calc == NULL) {
|
|
63
|
+
return NULL;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Initialize name
|
|
67
|
+
strncpy(calc->name, name, sizeof(calc->name) - 1);
|
|
68
|
+
calc->name[sizeof(calc->name) - 1] = '\0';
|
|
69
|
+
|
|
70
|
+
// Initialize history
|
|
71
|
+
calc->capacity = 10;
|
|
72
|
+
calc->history = malloc(calc->capacity * sizeof(double));
|
|
73
|
+
if (calc->history == NULL) {
|
|
74
|
+
free(calc);
|
|
75
|
+
return NULL;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
calc->count = 0;
|
|
79
|
+
return calc;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Destroys a calculator instance and frees memory
|
|
84
|
+
* @param calc Pointer to the calculator to destroy
|
|
85
|
+
*/
|
|
86
|
+
void destroy_calculator(Calculator* calc) {
|
|
87
|
+
if (calc != NULL) {
|
|
88
|
+
if (calc->history != NULL) {
|
|
89
|
+
free(calc->history);
|
|
90
|
+
}
|
|
91
|
+
free(calc);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Records an operation result in the calculator's history
|
|
97
|
+
* @param calc Pointer to the calculator
|
|
98
|
+
* @param result The result to record
|
|
99
|
+
* @return 0 on success, -1 on failure
|
|
100
|
+
*/
|
|
101
|
+
static int record_operation(Calculator* calc, double result) {
|
|
102
|
+
if (calc == NULL) {
|
|
103
|
+
return -1;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Expand history if needed
|
|
107
|
+
if (calc->count >= calc->capacity) {
|
|
108
|
+
calc->capacity *= 2;
|
|
109
|
+
double* new_history = realloc(calc->history, calc->capacity * sizeof(double));
|
|
110
|
+
if (new_history == NULL) {
|
|
111
|
+
return -1;
|
|
112
|
+
}
|
|
113
|
+
calc->history = new_history;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
calc->history[calc->count++] = result;
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* Adds two numbers and records the result
|
|
122
|
+
* @param calc Pointer to the calculator
|
|
123
|
+
* @param x First number
|
|
124
|
+
* @param y Second number
|
|
125
|
+
* @return The sum of x and y
|
|
126
|
+
*/
|
|
127
|
+
double add_numbers(Calculator* calc, double x, double y) {
|
|
128
|
+
double result = x + y;
|
|
129
|
+
if (calc != NULL) {
|
|
130
|
+
record_operation(calc, result);
|
|
131
|
+
}
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Subtracts y from x and records the result
|
|
137
|
+
* @param calc Pointer to the calculator
|
|
138
|
+
* @param x First number
|
|
139
|
+
* @param y Second number
|
|
140
|
+
* @return The difference x - y
|
|
141
|
+
*/
|
|
142
|
+
double subtract_numbers(Calculator* calc, double x, double y) {
|
|
143
|
+
double result = x - y;
|
|
144
|
+
if (calc != NULL) {
|
|
145
|
+
record_operation(calc, result);
|
|
146
|
+
}
|
|
147
|
+
return result;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Multiplies two numbers and records the result
|
|
152
|
+
* @param calc Pointer to the calculator
|
|
153
|
+
* @param x First number
|
|
154
|
+
* @param y Second number
|
|
155
|
+
* @return The product of x and y
|
|
156
|
+
*/
|
|
157
|
+
double multiply_numbers(Calculator* calc, double x, double y) {
|
|
158
|
+
double result = x * y;
|
|
159
|
+
if (calc != NULL) {
|
|
160
|
+
record_operation(calc, result);
|
|
161
|
+
}
|
|
162
|
+
return result;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Divides x by y and records the result
|
|
167
|
+
* @param calc Pointer to the calculator
|
|
168
|
+
* @param x Dividend
|
|
169
|
+
* @param y Divisor
|
|
170
|
+
* @return The quotient x / y, or NAN if y is zero
|
|
171
|
+
*/
|
|
172
|
+
double divide_numbers(Calculator* calc, double x, double y) {
|
|
173
|
+
double result;
|
|
174
|
+
if (fabs(y) < DEFAULT_PRECISION) {
|
|
175
|
+
result = NAN;
|
|
176
|
+
} else {
|
|
177
|
+
result = x / y;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
if (calc != NULL && !isnan(result)) {
|
|
181
|
+
record_operation(calc, result);
|
|
182
|
+
}
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
/**
|
|
187
|
+
* Gets the number of operations in history
|
|
188
|
+
* @param calc Pointer to the calculator
|
|
189
|
+
* @return Number of operations or -1 if calc is NULL
|
|
190
|
+
*/
|
|
191
|
+
int get_history_count(const Calculator* calc) {
|
|
192
|
+
if (calc == NULL) {
|
|
193
|
+
return -1;
|
|
194
|
+
}
|
|
195
|
+
return calc->count;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Gets a pointer to the calculator's history array
|
|
200
|
+
* @param calc Pointer to the calculator
|
|
201
|
+
* @return Pointer to history array or NULL if calc is NULL
|
|
202
|
+
*/
|
|
203
|
+
double* get_history(const Calculator* calc) {
|
|
204
|
+
if (calc == NULL) {
|
|
205
|
+
return NULL;
|
|
206
|
+
}
|
|
207
|
+
return calc->history;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
/**
|
|
211
|
+
* Prints the calculator's history to stdout
|
|
212
|
+
* @param calc Pointer to the calculator
|
|
213
|
+
*/
|
|
214
|
+
void print_history(const Calculator* calc) {
|
|
215
|
+
if (calc == NULL) {
|
|
216
|
+
printf("Calculator is NULL\n");
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
printf("History for calculator '%s':\n", calc->name);
|
|
221
|
+
for (int i = 0; i < calc->count; i++) {
|
|
222
|
+
printf(" %d: %.2f\n", i + 1, calc->history[i]);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Clears the calculator's history
|
|
228
|
+
* @param calc Pointer to the calculator
|
|
229
|
+
*/
|
|
230
|
+
void clear_history(Calculator* calc) {
|
|
231
|
+
if (calc != NULL) {
|
|
232
|
+
calc->count = 0;
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Main function demonstrating calculator usage
|
|
238
|
+
*/
|
|
239
|
+
int main(int argc, char* argv[]) {
|
|
240
|
+
Calculator* calc = create_calculator("Main Calculator");
|
|
241
|
+
if (calc == NULL) {
|
|
242
|
+
fprintf(stderr, "Failed to create calculator\n");
|
|
243
|
+
return 1;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// Perform some calculations
|
|
247
|
+
double result1 = add_numbers(calc, 10.5, 20.3);
|
|
248
|
+
double result2 = multiply_numbers(calc, 5.0, 7.0);
|
|
249
|
+
double result3 = divide_numbers(calc, 100.0, 4.0);
|
|
250
|
+
|
|
251
|
+
printf("Results: %.2f, %.2f, %.2f\n", result1, result2, result3);
|
|
252
|
+
|
|
253
|
+
// Print history
|
|
254
|
+
print_history(calc);
|
|
255
|
+
|
|
256
|
+
// Cleanup
|
|
257
|
+
destroy_calculator(calc);
|
|
258
|
+
|
|
259
|
+
return 0;
|
|
260
|
+
}
|
|
261
|
+
"#;
|
|
262
|
+
|
|
263
|
+
fs::write(&test_file, content)?;
|
|
264
|
+
|
|
265
|
+
let ctx = TestContext::new();
|
|
266
|
+
let output = ctx.run_probe(&[
|
|
267
|
+
"search",
|
|
268
|
+
"Calculator",
|
|
269
|
+
test_file.to_str().unwrap(),
|
|
270
|
+
"--format",
|
|
271
|
+
"outline",
|
|
272
|
+
"--allow-tests",
|
|
273
|
+
])?;
|
|
274
|
+
|
|
275
|
+
// Verify C outline format features
|
|
276
|
+
assert!(
|
|
277
|
+
output.contains("Calculator"),
|
|
278
|
+
"Missing Calculator in search results - output: {}",
|
|
279
|
+
output
|
|
280
|
+
);
|
|
281
|
+
assert!(
|
|
282
|
+
output.contains("..."),
|
|
283
|
+
"Missing truncation ellipsis in outline format - output: {}",
|
|
284
|
+
output
|
|
285
|
+
);
|
|
286
|
+
// Look for C-specific comment syntax in closing braces or structure
|
|
287
|
+
let has_c_syntax = output.contains("typedef struct")
|
|
288
|
+
|| output.contains("Calculator*")
|
|
289
|
+
|| output.contains("void destroy_calculator")
|
|
290
|
+
|| output.contains("//");
|
|
291
|
+
assert!(
|
|
292
|
+
has_c_syntax,
|
|
293
|
+
"Missing C-specific syntax in outline format - output: {}",
|
|
294
|
+
output
|
|
295
|
+
);
|
|
296
|
+
|
|
297
|
+
Ok(())
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
#[test]
|
|
301
|
+
fn test_c_outline_control_flow_statements() -> Result<()> {
|
|
302
|
+
let temp_dir = TempDir::new()?;
|
|
303
|
+
let test_file = temp_dir.path().join("control_flow.c");
|
|
304
|
+
|
|
305
|
+
let content = r#"#include <stdio.h>
|
|
306
|
+
#include <stdlib.h>
|
|
307
|
+
#include <string.h>
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Complex algorithm demonstrating various control flow statements with gaps
|
|
311
|
+
*/
|
|
312
|
+
int* complex_algorithm(int* data, int size, int threshold, int* result_size) {
|
|
313
|
+
if (data == NULL || size <= 0) {
|
|
314
|
+
*result_size = 0;
|
|
315
|
+
return NULL;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
int* result = malloc(size * sizeof(int));
|
|
319
|
+
if (result == NULL) {
|
|
320
|
+
*result_size = 0;
|
|
321
|
+
return NULL;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
int count = 0;
|
|
325
|
+
int counter = 0;
|
|
326
|
+
|
|
327
|
+
// First processing phase with for loop
|
|
328
|
+
for (int i = 0; i < size; i++) {
|
|
329
|
+
int item = data[i];
|
|
330
|
+
|
|
331
|
+
if (item > threshold) {
|
|
332
|
+
counter++;
|
|
333
|
+
|
|
334
|
+
// Complex nested conditions
|
|
335
|
+
if (counter % 2 == 0) {
|
|
336
|
+
result[count++] = item * 2;
|
|
337
|
+
} else {
|
|
338
|
+
result[count++] = item + 10;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Additional processing with switch
|
|
342
|
+
switch (item % 4) {
|
|
343
|
+
case 0:
|
|
344
|
+
result[count - 1] += 100;
|
|
345
|
+
break;
|
|
346
|
+
case 1:
|
|
347
|
+
result[count - 1] += 10;
|
|
348
|
+
break;
|
|
349
|
+
case 2:
|
|
350
|
+
result[count - 1] += 1;
|
|
351
|
+
break;
|
|
352
|
+
default:
|
|
353
|
+
result[count - 1] -= 5;
|
|
354
|
+
break;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// Second processing phase with while loop
|
|
360
|
+
int index = 0;
|
|
361
|
+
while (index < count) {
|
|
362
|
+
int value = result[index];
|
|
363
|
+
|
|
364
|
+
if (value < 0) {
|
|
365
|
+
// Remove negative values by shifting
|
|
366
|
+
for (int j = index; j < count - 1; j++) {
|
|
367
|
+
result[j] = result[j + 1];
|
|
368
|
+
}
|
|
369
|
+
count--;
|
|
370
|
+
} else if (value > 1000) {
|
|
371
|
+
// Cap large values
|
|
372
|
+
result[index] = 1000;
|
|
373
|
+
index++;
|
|
374
|
+
} else {
|
|
375
|
+
index++;
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
*result_size = count;
|
|
380
|
+
return result;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Process matrix with nested loops demonstrating closing brace comments
|
|
385
|
+
*/
|
|
386
|
+
int** process_matrix(int** matrix, int rows, int cols) {
|
|
387
|
+
if (matrix == NULL || rows <= 0 || cols <= 0) {
|
|
388
|
+
return NULL;
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// Allocate result matrix
|
|
392
|
+
int** processed = malloc(rows * sizeof(int*));
|
|
393
|
+
if (processed == NULL) {
|
|
394
|
+
return NULL;
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
for (int i = 0; i < rows; i++) {
|
|
398
|
+
processed[i] = malloc(cols * sizeof(int));
|
|
399
|
+
if (processed[i] == NULL) {
|
|
400
|
+
// Cleanup on failure
|
|
401
|
+
for (int j = 0; j < i; j++) {
|
|
402
|
+
free(processed[j]);
|
|
403
|
+
}
|
|
404
|
+
free(processed);
|
|
405
|
+
return NULL;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// Process each row
|
|
409
|
+
for (int j = 0; j < cols; j++) {
|
|
410
|
+
int cell = matrix[i][j];
|
|
411
|
+
int processed_cell;
|
|
412
|
+
|
|
413
|
+
if (cell > 0) {
|
|
414
|
+
processed_cell = cell * 2;
|
|
415
|
+
} else if (cell < 0) {
|
|
416
|
+
processed_cell = abs(cell);
|
|
417
|
+
} else {
|
|
418
|
+
processed_cell = 1;
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
processed[i][j] = processed_cell;
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
return processed;
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/**
|
|
429
|
+
* Analyze data with complex switch statement and error handling
|
|
430
|
+
*/
|
|
431
|
+
const char* analyze_data(int value, char* buffer, size_t buffer_size) {
|
|
432
|
+
if (buffer == NULL || buffer_size == 0) {
|
|
433
|
+
return "ERROR: Invalid buffer";
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
const char* result;
|
|
437
|
+
|
|
438
|
+
switch (value) {
|
|
439
|
+
case 0:
|
|
440
|
+
result = "ZERO";
|
|
441
|
+
break;
|
|
442
|
+
|
|
443
|
+
case 1:
|
|
444
|
+
case 2:
|
|
445
|
+
case 3:
|
|
446
|
+
case 4:
|
|
447
|
+
case 5:
|
|
448
|
+
result = "SMALL_POSITIVE";
|
|
449
|
+
break;
|
|
450
|
+
|
|
451
|
+
case -1:
|
|
452
|
+
case -2:
|
|
453
|
+
case -3:
|
|
454
|
+
case -4:
|
|
455
|
+
case -5:
|
|
456
|
+
result = "SMALL_NEGATIVE";
|
|
457
|
+
break;
|
|
458
|
+
|
|
459
|
+
default:
|
|
460
|
+
if (value > 5 && value <= 100) {
|
|
461
|
+
result = "MEDIUM_POSITIVE";
|
|
462
|
+
} else if (value > 100 && value <= 1000) {
|
|
463
|
+
result = "LARGE_POSITIVE";
|
|
464
|
+
} else if (value < -5 && value >= -100) {
|
|
465
|
+
result = "MEDIUM_NEGATIVE";
|
|
466
|
+
} else if (value < -100) {
|
|
467
|
+
result = "LARGE_NEGATIVE";
|
|
468
|
+
} else {
|
|
469
|
+
result = "VERY_LARGE_POSITIVE";
|
|
470
|
+
}
|
|
471
|
+
break;
|
|
472
|
+
}
|
|
473
|
+
|
|
474
|
+
// Copy result to buffer with bounds checking
|
|
475
|
+
size_t result_len = strlen(result);
|
|
476
|
+
if (result_len >= buffer_size) {
|
|
477
|
+
strncpy(buffer, result, buffer_size - 1);
|
|
478
|
+
buffer[buffer_size - 1] = '\0';
|
|
479
|
+
} else {
|
|
480
|
+
strcpy(buffer, result);
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
return buffer;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Recursive function with complex termination conditions
|
|
488
|
+
*/
|
|
489
|
+
long factorial_with_memoization(int n, long* memo, int memo_size) {
|
|
490
|
+
// Base cases
|
|
491
|
+
if (n < 0) {
|
|
492
|
+
return -1; // Error case
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
if (n == 0 || n == 1) {
|
|
496
|
+
return 1;
|
|
497
|
+
}
|
|
498
|
+
|
|
499
|
+
// Check memoization
|
|
500
|
+
if (n < memo_size && memo[n] != 0) {
|
|
501
|
+
return memo[n];
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
// Recursive calculation with loop for large values
|
|
505
|
+
long result = 1;
|
|
506
|
+
if (n > 20) {
|
|
507
|
+
// Use iterative approach for large values to avoid stack overflow
|
|
508
|
+
for (int i = 2; i <= n; i++) {
|
|
509
|
+
result *= i;
|
|
510
|
+
|
|
511
|
+
// Check for overflow
|
|
512
|
+
if (result < 0) {
|
|
513
|
+
return -1;
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
} else {
|
|
517
|
+
// Use recursion for smaller values
|
|
518
|
+
result = n * factorial_with_memoization(n - 1, memo, memo_size);
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
// Store in memo if space available
|
|
522
|
+
if (n < memo_size) {
|
|
523
|
+
memo[n] = result;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
return result;
|
|
527
|
+
}
|
|
528
|
+
"#;
|
|
529
|
+
|
|
530
|
+
fs::write(&test_file, content)?;
|
|
531
|
+
|
|
532
|
+
let ctx = TestContext::new();
|
|
533
|
+
let output = ctx.run_probe(&[
|
|
534
|
+
"search",
|
|
535
|
+
"complex_algorithm",
|
|
536
|
+
test_file.to_str().unwrap(),
|
|
537
|
+
"--format",
|
|
538
|
+
"outline",
|
|
539
|
+
"--allow-tests",
|
|
540
|
+
])?;
|
|
541
|
+
|
|
542
|
+
// Verify outline format for complex algorithm with control flow
|
|
543
|
+
assert!(
|
|
544
|
+
output.contains("complex_algorithm"),
|
|
545
|
+
"Missing complex_algorithm function - output: {}",
|
|
546
|
+
output
|
|
547
|
+
);
|
|
548
|
+
assert!(
|
|
549
|
+
output.contains("..."),
|
|
550
|
+
"Missing truncation ellipsis in outline format - output: {}",
|
|
551
|
+
output
|
|
552
|
+
);
|
|
553
|
+
// Should contain closing brace comment for function
|
|
554
|
+
assert!(
|
|
555
|
+
output.contains("} //") || output.contains("}//") || output.contains("} /*"),
|
|
556
|
+
"Missing closing brace comment for function - output: {}",
|
|
557
|
+
output
|
|
558
|
+
);
|
|
559
|
+
// Should show C function signature patterns
|
|
560
|
+
let has_c_function_pattern = output.contains("int*")
|
|
561
|
+
|| output.contains("char**")
|
|
562
|
+
|| output.contains("(")
|
|
563
|
+
|| output.contains(")");
|
|
564
|
+
assert!(
|
|
565
|
+
has_c_function_pattern,
|
|
566
|
+
"Missing C function signature patterns - output: {}",
|
|
567
|
+
output
|
|
568
|
+
);
|
|
569
|
+
|
|
570
|
+
Ok(())
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
#[test]
|
|
574
|
+
fn test_c_outline_structs_and_unions() -> Result<()> {
|
|
575
|
+
let temp_dir = TempDir::new()?;
|
|
576
|
+
let test_file = temp_dir.path().join("structs_unions.c");
|
|
577
|
+
|
|
578
|
+
let content = r#"#include <stdio.h>
|
|
579
|
+
#include <stdlib.h>
|
|
580
|
+
#include <string.h>
|
|
581
|
+
#include <stdint.h>
|
|
582
|
+
|
|
583
|
+
// Complex struct definitions with various member types
|
|
584
|
+
typedef struct Point {
|
|
585
|
+
double x;
|
|
586
|
+
double y;
|
|
587
|
+
} Point;
|
|
588
|
+
|
|
589
|
+
typedef struct Rectangle {
|
|
590
|
+
Point top_left;
|
|
591
|
+
Point bottom_right;
|
|
592
|
+
char label[32];
|
|
593
|
+
uint32_t color;
|
|
594
|
+
} Rectangle;
|
|
595
|
+
|
|
596
|
+
typedef struct Circle {
|
|
597
|
+
Point center;
|
|
598
|
+
double radius;
|
|
599
|
+
char label[32];
|
|
600
|
+
uint32_t color;
|
|
601
|
+
} Circle;
|
|
602
|
+
|
|
603
|
+
// Union for different shape types
|
|
604
|
+
typedef union ShapeData {
|
|
605
|
+
Rectangle rect;
|
|
606
|
+
Circle circle;
|
|
607
|
+
} ShapeData;
|
|
608
|
+
|
|
609
|
+
typedef enum {
|
|
610
|
+
SHAPE_RECTANGLE,
|
|
611
|
+
SHAPE_CIRCLE,
|
|
612
|
+
SHAPE_TRIANGLE
|
|
613
|
+
} ShapeType;
|
|
614
|
+
|
|
615
|
+
// Complex struct with nested structures and function pointers
|
|
616
|
+
typedef struct Shape {
|
|
617
|
+
ShapeType type;
|
|
618
|
+
ShapeData data;
|
|
619
|
+
double (*area_func)(const struct Shape* shape);
|
|
620
|
+
double (*perimeter_func)(const struct Shape* shape);
|
|
621
|
+
void (*print_func)(const struct Shape* shape);
|
|
622
|
+
struct Shape* next; // For linked list
|
|
623
|
+
} Shape;
|
|
624
|
+
|
|
625
|
+
// Function pointer typedef
|
|
626
|
+
typedef void (*ProcessFunc)(void* data, size_t size);
|
|
627
|
+
|
|
628
|
+
// Complex data structure
|
|
629
|
+
typedef struct DataProcessor {
|
|
630
|
+
char name[64];
|
|
631
|
+
ProcessFunc process_func;
|
|
632
|
+
void* context;
|
|
633
|
+
size_t buffer_size;
|
|
634
|
+
uint8_t* buffer;
|
|
635
|
+
struct {
|
|
636
|
+
uint64_t total_processed;
|
|
637
|
+
uint32_t operations_count;
|
|
638
|
+
double average_time;
|
|
639
|
+
} stats;
|
|
640
|
+
} DataProcessor;
|
|
641
|
+
|
|
642
|
+
// Bit field structure
|
|
643
|
+
typedef struct StatusFlags {
|
|
644
|
+
unsigned int initialized : 1;
|
|
645
|
+
unsigned int error : 1;
|
|
646
|
+
unsigned int processing : 1;
|
|
647
|
+
unsigned int completed : 1;
|
|
648
|
+
unsigned int reserved : 28;
|
|
649
|
+
} StatusFlags;
|
|
650
|
+
|
|
651
|
+
// Forward declarations
|
|
652
|
+
double rectangle_area(const Shape* shape);
|
|
653
|
+
double rectangle_perimeter(const Shape* shape);
|
|
654
|
+
void print_rectangle(const Shape* shape);
|
|
655
|
+
double circle_area(const Shape* shape);
|
|
656
|
+
double circle_perimeter(const Shape* shape);
|
|
657
|
+
void print_circle(const Shape* shape);
|
|
658
|
+
|
|
659
|
+
// Function implementations
|
|
660
|
+
|
|
661
|
+
/**
|
|
662
|
+
* Creates a new rectangle shape
|
|
663
|
+
*/
|
|
664
|
+
Shape* create_rectangle(double x1, double y1, double x2, double y2, const char* label, uint32_t color) {
|
|
665
|
+
Shape* shape = malloc(sizeof(Shape));
|
|
666
|
+
if (shape == NULL) {
|
|
667
|
+
return NULL;
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
shape->type = SHAPE_RECTANGLE;
|
|
671
|
+
shape->data.rect.top_left.x = x1 < x2 ? x1 : x2;
|
|
672
|
+
shape->data.rect.top_left.y = y1 > y2 ? y1 : y2;
|
|
673
|
+
shape->data.rect.bottom_right.x = x1 > x2 ? x1 : x2;
|
|
674
|
+
shape->data.rect.bottom_right.y = y1 < y2 ? y1 : y2;
|
|
675
|
+
|
|
676
|
+
strncpy(shape->data.rect.label, label, sizeof(shape->data.rect.label) - 1);
|
|
677
|
+
shape->data.rect.label[sizeof(shape->data.rect.label) - 1] = '\0';
|
|
678
|
+
shape->data.rect.color = color;
|
|
679
|
+
|
|
680
|
+
shape->area_func = rectangle_area;
|
|
681
|
+
shape->perimeter_func = rectangle_perimeter;
|
|
682
|
+
shape->print_func = print_rectangle;
|
|
683
|
+
shape->next = NULL;
|
|
684
|
+
|
|
685
|
+
return shape;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Creates a new circle shape
|
|
690
|
+
*/
|
|
691
|
+
Shape* create_circle(double cx, double cy, double radius, const char* label, uint32_t color) {
|
|
692
|
+
Shape* shape = malloc(sizeof(Shape));
|
|
693
|
+
if (shape == NULL) {
|
|
694
|
+
return NULL;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
shape->type = SHAPE_CIRCLE;
|
|
698
|
+
shape->data.circle.center.x = cx;
|
|
699
|
+
shape->data.circle.center.y = cy;
|
|
700
|
+
shape->data.circle.radius = radius > 0 ? radius : 1.0;
|
|
701
|
+
|
|
702
|
+
strncpy(shape->data.circle.label, label, sizeof(shape->data.circle.label) - 1);
|
|
703
|
+
shape->data.circle.label[sizeof(shape->data.circle.label) - 1] = '\0';
|
|
704
|
+
shape->data.circle.color = color;
|
|
705
|
+
|
|
706
|
+
shape->area_func = circle_area;
|
|
707
|
+
shape->perimeter_func = circle_perimeter;
|
|
708
|
+
shape->print_func = print_circle;
|
|
709
|
+
shape->next = NULL;
|
|
710
|
+
|
|
711
|
+
return shape;
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
/**
|
|
715
|
+
* Calculates rectangle area
|
|
716
|
+
*/
|
|
717
|
+
double rectangle_area(const Shape* shape) {
|
|
718
|
+
if (shape == NULL || shape->type != SHAPE_RECTANGLE) {
|
|
719
|
+
return 0.0;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
const Rectangle* rect = &shape->data.rect;
|
|
723
|
+
double width = rect->bottom_right.x - rect->top_left.x;
|
|
724
|
+
double height = rect->top_left.y - rect->bottom_right.y;
|
|
725
|
+
|
|
726
|
+
return width * height;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
/**
|
|
730
|
+
* Calculates rectangle perimeter
|
|
731
|
+
*/
|
|
732
|
+
double rectangle_perimeter(const Shape* shape) {
|
|
733
|
+
if (shape == NULL || shape->type != SHAPE_RECTANGLE) {
|
|
734
|
+
return 0.0;
|
|
735
|
+
}
|
|
736
|
+
|
|
737
|
+
const Rectangle* rect = &shape->data.rect;
|
|
738
|
+
double width = rect->bottom_right.x - rect->top_left.x;
|
|
739
|
+
double height = rect->top_left.y - rect->bottom_right.y;
|
|
740
|
+
|
|
741
|
+
return 2.0 * (width + height);
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Prints rectangle information
|
|
746
|
+
*/
|
|
747
|
+
void print_rectangle(const Shape* shape) {
|
|
748
|
+
if (shape == NULL || shape->type != SHAPE_RECTANGLE) {
|
|
749
|
+
printf("Invalid rectangle\n");
|
|
750
|
+
return;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
const Rectangle* rect = &shape->data.rect;
|
|
754
|
+
printf("Rectangle '%s': (%.2f,%.2f) to (%.2f,%.2f), Color: 0x%08X\n",
|
|
755
|
+
rect->label,
|
|
756
|
+
rect->top_left.x, rect->top_left.y,
|
|
757
|
+
rect->bottom_right.x, rect->bottom_right.y,
|
|
758
|
+
rect->color);
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
/**
|
|
762
|
+
* Calculates circle area
|
|
763
|
+
*/
|
|
764
|
+
double circle_area(const Shape* shape) {
|
|
765
|
+
if (shape == NULL || shape->type != SHAPE_CIRCLE) {
|
|
766
|
+
return 0.0;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
const Circle* circle = &shape->data.circle;
|
|
770
|
+
return 3.14159 * circle->radius * circle->radius;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* Calculates circle perimeter
|
|
775
|
+
*/
|
|
776
|
+
double circle_perimeter(const Shape* shape) {
|
|
777
|
+
if (shape == NULL || shape->type != SHAPE_CIRCLE) {
|
|
778
|
+
return 0.0;
|
|
779
|
+
}
|
|
780
|
+
|
|
781
|
+
const Circle* circle = &shape->data.circle;
|
|
782
|
+
return 2.0 * 3.14159 * circle->radius;
|
|
783
|
+
}
|
|
784
|
+
|
|
785
|
+
/**
|
|
786
|
+
* Prints circle information
|
|
787
|
+
*/
|
|
788
|
+
void print_circle(const Shape* shape) {
|
|
789
|
+
if (shape == NULL || shape->type != SHAPE_CIRCLE) {
|
|
790
|
+
printf("Invalid circle\n");
|
|
791
|
+
return;
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
const Circle* circle = &shape->data.circle;
|
|
795
|
+
printf("Circle '%s': Center (%.2f,%.2f), Radius %.2f, Color: 0x%08X\n",
|
|
796
|
+
circle->label,
|
|
797
|
+
circle->center.x, circle->center.y,
|
|
798
|
+
circle->radius,
|
|
799
|
+
circle->color);
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
/**
|
|
803
|
+
* Creates a data processor with specified parameters
|
|
804
|
+
*/
|
|
805
|
+
DataProcessor* create_data_processor(const char* name, ProcessFunc func, size_t buffer_size) {
|
|
806
|
+
DataProcessor* processor = malloc(sizeof(DataProcessor));
|
|
807
|
+
if (processor == NULL) {
|
|
808
|
+
return NULL;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
strncpy(processor->name, name, sizeof(processor->name) - 1);
|
|
812
|
+
processor->name[sizeof(processor->name) - 1] = '\0';
|
|
813
|
+
|
|
814
|
+
processor->process_func = func;
|
|
815
|
+
processor->context = NULL;
|
|
816
|
+
processor->buffer_size = buffer_size;
|
|
817
|
+
|
|
818
|
+
if (buffer_size > 0) {
|
|
819
|
+
processor->buffer = malloc(buffer_size);
|
|
820
|
+
if (processor->buffer == NULL) {
|
|
821
|
+
free(processor);
|
|
822
|
+
return NULL;
|
|
823
|
+
}
|
|
824
|
+
} else {
|
|
825
|
+
processor->buffer = NULL;
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
// Initialize stats
|
|
829
|
+
processor->stats.total_processed = 0;
|
|
830
|
+
processor->stats.operations_count = 0;
|
|
831
|
+
processor->stats.average_time = 0.0;
|
|
832
|
+
|
|
833
|
+
return processor;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
/**
|
|
837
|
+
* Destroys a data processor and frees memory
|
|
838
|
+
*/
|
|
839
|
+
void destroy_data_processor(DataProcessor* processor) {
|
|
840
|
+
if (processor != NULL) {
|
|
841
|
+
if (processor->buffer != NULL) {
|
|
842
|
+
free(processor->buffer);
|
|
843
|
+
}
|
|
844
|
+
free(processor);
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
|
|
848
|
+
/**
|
|
849
|
+
* Destroys a shape and frees memory
|
|
850
|
+
*/
|
|
851
|
+
void destroy_shape(Shape* shape) {
|
|
852
|
+
if (shape != NULL) {
|
|
853
|
+
free(shape);
|
|
854
|
+
}
|
|
855
|
+
}
|
|
856
|
+
"#;
|
|
857
|
+
|
|
858
|
+
fs::write(&test_file, content)?;
|
|
859
|
+
|
|
860
|
+
let ctx = TestContext::new();
|
|
861
|
+
let output = ctx.run_probe(&[
|
|
862
|
+
"search",
|
|
863
|
+
"Shape",
|
|
864
|
+
test_file.to_str().unwrap(),
|
|
865
|
+
"--format",
|
|
866
|
+
"outline",
|
|
867
|
+
"--allow-tests",
|
|
868
|
+
])?;
|
|
869
|
+
|
|
870
|
+
// Verify outline format for struct and union patterns
|
|
871
|
+
assert!(
|
|
872
|
+
output.contains("Shape"),
|
|
873
|
+
"Missing Shape-related symbols - output: {}",
|
|
874
|
+
output
|
|
875
|
+
);
|
|
876
|
+
assert!(
|
|
877
|
+
output.contains("..."),
|
|
878
|
+
"Missing truncation ellipsis in outline format - output: {}",
|
|
879
|
+
output
|
|
880
|
+
);
|
|
881
|
+
// Should show C struct/union/typedef patterns
|
|
882
|
+
let has_c_type_patterns = output.contains("typedef")
|
|
883
|
+
|| output.contains("struct")
|
|
884
|
+
|| output.contains("union")
|
|
885
|
+
|| output.contains("*")
|
|
886
|
+
|| output.contains("Rectangle")
|
|
887
|
+
|| output.contains("Circle");
|
|
888
|
+
assert!(
|
|
889
|
+
has_c_type_patterns,
|
|
890
|
+
"Missing C type definition patterns - output: {}",
|
|
891
|
+
output
|
|
892
|
+
);
|
|
893
|
+
|
|
894
|
+
Ok(())
|
|
895
|
+
}
|
|
896
|
+
|
|
897
|
+
#[test]
|
|
898
|
+
fn test_c_outline_preprocessor_and_macros() -> Result<()> {
|
|
899
|
+
let temp_dir = TempDir::new()?;
|
|
900
|
+
let test_file = temp_dir.path().join("preprocessor.c");
|
|
901
|
+
|
|
902
|
+
let content = r#"// Complex C preprocessor directives and macros
|
|
903
|
+
#include <stdio.h>
|
|
904
|
+
#include <stdlib.h>
|
|
905
|
+
#include <stdint.h>
|
|
906
|
+
|
|
907
|
+
// Configuration macros
|
|
908
|
+
#define VERSION_MAJOR 2
|
|
909
|
+
#define VERSION_MINOR 1
|
|
910
|
+
#define VERSION_PATCH 0
|
|
911
|
+
#define VERSION_STRING "2.1.0"
|
|
912
|
+
|
|
913
|
+
#ifdef DEBUG
|
|
914
|
+
#define DBG_PRINT(fmt, ...) printf("[DEBUG] " fmt "\n", ##__VA_ARGS__)
|
|
915
|
+
#else
|
|
916
|
+
#define DBG_PRINT(fmt, ...) do {} while(0)
|
|
917
|
+
#endif
|
|
918
|
+
|
|
919
|
+
// Utility macros
|
|
920
|
+
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
921
|
+
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
922
|
+
#define CLAMP(value, min_val, max_val) MIN(MAX(value, min_val), max_val)
|
|
923
|
+
|
|
924
|
+
// Array size calculation
|
|
925
|
+
#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
|
|
926
|
+
|
|
927
|
+
// Bit manipulation macros
|
|
928
|
+
#define SET_BIT(value, bit) ((value) |= (1 << (bit)))
|
|
929
|
+
#define CLEAR_BIT(value, bit) ((value) &= ~(1 << (bit)))
|
|
930
|
+
#define TEST_BIT(value, bit) ((value) & (1 << (bit)))
|
|
931
|
+
|
|
932
|
+
// Complex macro with multiple statements
|
|
933
|
+
#define SAFE_FREE(ptr) do { \
|
|
934
|
+
if ((ptr) != NULL) { \
|
|
935
|
+
free(ptr); \
|
|
936
|
+
(ptr) = NULL; \
|
|
937
|
+
} \
|
|
938
|
+
} while(0)
|
|
939
|
+
|
|
940
|
+
// Conditional compilation for different platforms
|
|
941
|
+
#ifdef _WIN32
|
|
942
|
+
#define PLATFORM "Windows"
|
|
943
|
+
#define PATH_SEPARATOR '\\'
|
|
944
|
+
#elif defined(__linux__)
|
|
945
|
+
#define PLATFORM "Linux"
|
|
946
|
+
#define PATH_SEPARATOR '/'
|
|
947
|
+
#elif defined(__APPLE__)
|
|
948
|
+
#define PLATFORM "macOS"
|
|
949
|
+
#define PATH_SEPARATOR '/'
|
|
950
|
+
#else
|
|
951
|
+
#define PLATFORM "Unknown"
|
|
952
|
+
#define PATH_SEPARATOR '/'
|
|
953
|
+
#endif
|
|
954
|
+
|
|
955
|
+
// Feature flags
|
|
956
|
+
#if VERSION_MAJOR >= 2
|
|
957
|
+
#define FEATURE_ADVANCED_MATH 1
|
|
958
|
+
#define FEATURE_LOGGING 1
|
|
959
|
+
#else
|
|
960
|
+
#define FEATURE_ADVANCED_MATH 0
|
|
961
|
+
#define FEATURE_LOGGING 0
|
|
962
|
+
#endif
|
|
963
|
+
|
|
964
|
+
// Compiler-specific attributes
|
|
965
|
+
#if defined(__GNUC__) || defined(__clang__)
|
|
966
|
+
#define FORCE_INLINE __attribute__((always_inline)) inline
|
|
967
|
+
#define NO_RETURN __attribute__((noreturn))
|
|
968
|
+
#define UNUSED __attribute__((unused))
|
|
969
|
+
#elif defined(_MSC_VER)
|
|
970
|
+
#define FORCE_INLINE __forceinline
|
|
971
|
+
#define NO_RETURN __declspec(noreturn)
|
|
972
|
+
#define UNUSED
|
|
973
|
+
#else
|
|
974
|
+
#define FORCE_INLINE inline
|
|
975
|
+
#define NO_RETURN
|
|
976
|
+
#define UNUSED
|
|
977
|
+
#endif
|
|
978
|
+
|
|
979
|
+
// Type definitions with macros
|
|
980
|
+
typedef struct {
|
|
981
|
+
uint32_t flags;
|
|
982
|
+
char platform[16];
|
|
983
|
+
int version_major;
|
|
984
|
+
int version_minor;
|
|
985
|
+
int version_patch;
|
|
986
|
+
} SystemInfo;
|
|
987
|
+
|
|
988
|
+
/**
|
|
989
|
+
* Function using preprocessor features
|
|
990
|
+
*/
|
|
991
|
+
SystemInfo* get_system_info(void) {
|
|
992
|
+
static SystemInfo info = {0};
|
|
993
|
+
static int initialized = 0;
|
|
994
|
+
|
|
995
|
+
if (!initialized) {
|
|
996
|
+
strcpy(info.platform, PLATFORM);
|
|
997
|
+
info.version_major = VERSION_MAJOR;
|
|
998
|
+
info.version_minor = VERSION_MINOR;
|
|
999
|
+
info.version_patch = VERSION_PATCH;
|
|
1000
|
+
|
|
1001
|
+
#if FEATURE_ADVANCED_MATH
|
|
1002
|
+
SET_BIT(info.flags, 0); // Math feature flag
|
|
1003
|
+
#endif
|
|
1004
|
+
|
|
1005
|
+
#if FEATURE_LOGGING
|
|
1006
|
+
SET_BIT(info.flags, 1); // Logging feature flag
|
|
1007
|
+
#endif
|
|
1008
|
+
|
|
1009
|
+
initialized = 1;
|
|
1010
|
+
DBG_PRINT("System info initialized for %s", PLATFORM);
|
|
1011
|
+
}
|
|
1012
|
+
|
|
1013
|
+
return &info;
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
/**
|
|
1017
|
+
* Function demonstrating macro usage
|
|
1018
|
+
*/
|
|
1019
|
+
int* process_array(int* array, size_t size) {
|
|
1020
|
+
if (array == NULL || size == 0) {
|
|
1021
|
+
DBG_PRINT("Invalid array parameters");
|
|
1022
|
+
return NULL;
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
int* result = malloc(size * sizeof(int));
|
|
1026
|
+
if (result == NULL) {
|
|
1027
|
+
DBG_PRINT("Failed to allocate memory for %zu elements", size);
|
|
1028
|
+
return NULL;
|
|
1029
|
+
}
|
|
1030
|
+
|
|
1031
|
+
// Process using macros
|
|
1032
|
+
for (size_t i = 0; i < size; i++) {
|
|
1033
|
+
int value = array[i];
|
|
1034
|
+
|
|
1035
|
+
// Clamp value between 0 and 100
|
|
1036
|
+
result[i] = CLAMP(value, 0, 100);
|
|
1037
|
+
|
|
1038
|
+
DBG_PRINT("Processed array[%zu]: %d -> %d", i, value, result[i]);
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
return result;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
/**
|
|
1045
|
+
* Utility function with inline optimization
|
|
1046
|
+
*/
|
|
1047
|
+
FORCE_INLINE int fast_multiply(int a, int b) {
|
|
1048
|
+
return a * b;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
/**
|
|
1052
|
+
* Function that never returns
|
|
1053
|
+
*/
|
|
1054
|
+
NO_RETURN void fatal_error(const char* message) {
|
|
1055
|
+
fprintf(stderr, "FATAL ERROR: %s\n", message);
|
|
1056
|
+
exit(1);
|
|
1057
|
+
}
|
|
1058
|
+
|
|
1059
|
+
/**
|
|
1060
|
+
* Function with conditional compilation
|
|
1061
|
+
*/
|
|
1062
|
+
void print_features(void) {
|
|
1063
|
+
printf("Application Version: %s\n", VERSION_STRING);
|
|
1064
|
+
printf("Platform: %s\n", PLATFORM);
|
|
1065
|
+
printf("Path Separator: %c\n", PATH_SEPARATOR);
|
|
1066
|
+
|
|
1067
|
+
#if FEATURE_ADVANCED_MATH
|
|
1068
|
+
printf("Advanced Math: Enabled\n");
|
|
1069
|
+
#else
|
|
1070
|
+
printf("Advanced Math: Disabled\n");
|
|
1071
|
+
#endif
|
|
1072
|
+
|
|
1073
|
+
#if FEATURE_LOGGING
|
|
1074
|
+
printf("Logging: Enabled\n");
|
|
1075
|
+
#else
|
|
1076
|
+
printf("Logging: Disabled\n");
|
|
1077
|
+
#endif
|
|
1078
|
+
|
|
1079
|
+
SystemInfo* info = get_system_info();
|
|
1080
|
+
printf("System Flags: 0x%08X\n", info->flags);
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
/**
|
|
1084
|
+
* Main function demonstrating all features
|
|
1085
|
+
*/
|
|
1086
|
+
int main(void) {
|
|
1087
|
+
print_features();
|
|
1088
|
+
|
|
1089
|
+
int test_array[] = {-10, 25, 150, 75, -5, 200};
|
|
1090
|
+
size_t array_size = ARRAY_SIZE(test_array);
|
|
1091
|
+
|
|
1092
|
+
printf("\nOriginal array size: %zu\n", array_size);
|
|
1093
|
+
|
|
1094
|
+
int* processed = process_array(test_array, array_size);
|
|
1095
|
+
if (processed != NULL) {
|
|
1096
|
+
printf("Processed array: ");
|
|
1097
|
+
for (size_t i = 0; i < array_size; i++) {
|
|
1098
|
+
printf("%d ", processed[i]);
|
|
1099
|
+
}
|
|
1100
|
+
printf("\n");
|
|
1101
|
+
|
|
1102
|
+
SAFE_FREE(processed);
|
|
1103
|
+
}
|
|
1104
|
+
|
|
1105
|
+
// Test inline function
|
|
1106
|
+
int product = fast_multiply(7, 8);
|
|
1107
|
+
printf("Fast multiply result: %d\n", product);
|
|
1108
|
+
|
|
1109
|
+
return 0;
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
// Clean up macros if needed
|
|
1113
|
+
#undef DBG_PRINT
|
|
1114
|
+
#undef SAFE_FREE
|
|
1115
|
+
"#;
|
|
1116
|
+
|
|
1117
|
+
fs::write(&test_file, content)?;
|
|
1118
|
+
|
|
1119
|
+
let ctx = TestContext::new();
|
|
1120
|
+
let output = ctx.run_probe(&[
|
|
1121
|
+
"search",
|
|
1122
|
+
"get_system_info",
|
|
1123
|
+
test_file.to_str().unwrap(),
|
|
1124
|
+
"--format",
|
|
1125
|
+
"outline",
|
|
1126
|
+
"--allow-tests",
|
|
1127
|
+
])?;
|
|
1128
|
+
|
|
1129
|
+
// Verify outline format for preprocessor and macros
|
|
1130
|
+
assert!(
|
|
1131
|
+
output.contains("get_system_info"),
|
|
1132
|
+
"Missing get_system_info function - output: {}",
|
|
1133
|
+
output
|
|
1134
|
+
);
|
|
1135
|
+
assert!(
|
|
1136
|
+
output.contains("..."),
|
|
1137
|
+
"Missing truncation ellipsis in outline format - output: {}",
|
|
1138
|
+
output
|
|
1139
|
+
);
|
|
1140
|
+
// Should show C preprocessor patterns and function signatures
|
|
1141
|
+
let has_c_preprocessor_patterns = output.contains("SystemInfo")
|
|
1142
|
+
|| output.contains("#if")
|
|
1143
|
+
|| output.contains("void")
|
|
1144
|
+
|| output.contains("*")
|
|
1145
|
+
|| output.contains("printf");
|
|
1146
|
+
assert!(
|
|
1147
|
+
has_c_preprocessor_patterns,
|
|
1148
|
+
"Missing C preprocessor and function patterns - output: {}",
|
|
1149
|
+
output
|
|
1150
|
+
);
|
|
1151
|
+
|
|
1152
|
+
Ok(())
|
|
1153
|
+
}
|
|
1154
|
+
|
|
1155
|
+
#[test]
|
|
1156
|
+
fn test_c_outline_large_function_closing_braces() -> Result<()> {
|
|
1157
|
+
let temp_dir = TempDir::new()?;
|
|
1158
|
+
let test_file = temp_dir.path().join("large_function.c");
|
|
1159
|
+
|
|
1160
|
+
let content = r#"#include <stdio.h>
|
|
1161
|
+
#include <stdlib.h>
|
|
1162
|
+
#include <string.h>
|
|
1163
|
+
#include <ctype.h>
|
|
1164
|
+
|
|
1165
|
+
/**
|
|
1166
|
+
* Large function with multiple nested blocks to test closing brace comments
|
|
1167
|
+
*/
|
|
1168
|
+
char** complex_text_processor(char** input, int input_count, int* output_count) {
|
|
1169
|
+
if (input == NULL || input_count <= 0 || output_count == NULL) {
|
|
1170
|
+
*output_count = 0;
|
|
1171
|
+
return NULL;
|
|
1172
|
+
}
|
|
1173
|
+
|
|
1174
|
+
// Initialize output array
|
|
1175
|
+
char** output = malloc(input_count * 2 * sizeof(char*));
|
|
1176
|
+
if (output == NULL) {
|
|
1177
|
+
*output_count = 0;
|
|
1178
|
+
return NULL;
|
|
1179
|
+
}
|
|
1180
|
+
|
|
1181
|
+
int current_output = 0;
|
|
1182
|
+
char* categories[10] = {"short", "medium", "long", "email", "url", "number",
|
|
1183
|
+
"uppercase", "lowercase", "mixed", "special"};
|
|
1184
|
+
|
|
1185
|
+
// Phase 1: Categorize and validate input
|
|
1186
|
+
for (int i = 0; i < input_count; i++) {
|
|
1187
|
+
char* text = input[i];
|
|
1188
|
+
if (text == NULL || strlen(text) == 0) {
|
|
1189
|
+
printf("Warning: empty text at index %d\n", i);
|
|
1190
|
+
continue;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
size_t len = strlen(text);
|
|
1194
|
+
char* processed = malloc(len + 100); // Extra space for modifications
|
|
1195
|
+
if (processed == NULL) {
|
|
1196
|
+
printf("Memory allocation failed for index %d\n", i);
|
|
1197
|
+
continue;
|
|
1198
|
+
}
|
|
1199
|
+
|
|
1200
|
+
// Determine category and process accordingly
|
|
1201
|
+
if (len <= 10) {
|
|
1202
|
+
// Short text processing
|
|
1203
|
+
strcpy(processed, "SHORT: ");
|
|
1204
|
+
|
|
1205
|
+
// Check if numeric
|
|
1206
|
+
int is_numeric = 1;
|
|
1207
|
+
for (size_t j = 0; j < len; j++) {
|
|
1208
|
+
if (!isdigit(text[j])) {
|
|
1209
|
+
is_numeric = 0;
|
|
1210
|
+
break;
|
|
1211
|
+
}
|
|
1212
|
+
}
|
|
1213
|
+
|
|
1214
|
+
if (is_numeric) {
|
|
1215
|
+
strcat(processed, "NUM_");
|
|
1216
|
+
strcat(processed, text);
|
|
1217
|
+
} else {
|
|
1218
|
+
// Convert to uppercase
|
|
1219
|
+
for (size_t j = 0; j < len; j++) {
|
|
1220
|
+
if (islower(text[j])) {
|
|
1221
|
+
processed[7 + j] = toupper(text[j]);
|
|
1222
|
+
} else {
|
|
1223
|
+
processed[7 + j] = text[j];
|
|
1224
|
+
}
|
|
1225
|
+
}
|
|
1226
|
+
processed[7 + len] = '\0';
|
|
1227
|
+
}
|
|
1228
|
+
|
|
1229
|
+
} else if (len <= 50) {
|
|
1230
|
+
// Medium text processing
|
|
1231
|
+
strcpy(processed, "MEDIUM: ");
|
|
1232
|
+
|
|
1233
|
+
// Check for email pattern
|
|
1234
|
+
if (strchr(text, '@') != NULL && strchr(text, '.') != NULL) {
|
|
1235
|
+
strcat(processed, "EMAIL_");
|
|
1236
|
+
strncat(processed, text, 30); // Truncate long emails
|
|
1237
|
+
} else if (strncmp(text, "http", 4) == 0) {
|
|
1238
|
+
strcat(processed, "URL_");
|
|
1239
|
+
strncat(processed, text, 30); // Truncate long URLs
|
|
1240
|
+
} else {
|
|
1241
|
+
// Title case conversion
|
|
1242
|
+
int capitalize_next = 1;
|
|
1243
|
+
size_t processed_len = strlen(processed);
|
|
1244
|
+
|
|
1245
|
+
for (size_t j = 0; j < len && processed_len + j < len + 99; j++) {
|
|
1246
|
+
if (isspace(text[j])) {
|
|
1247
|
+
processed[processed_len + j] = text[j];
|
|
1248
|
+
capitalize_next = 1;
|
|
1249
|
+
} else if (capitalize_next && isalpha(text[j])) {
|
|
1250
|
+
processed[processed_len + j] = toupper(text[j]);
|
|
1251
|
+
capitalize_next = 0;
|
|
1252
|
+
} else {
|
|
1253
|
+
processed[processed_len + j] = tolower(text[j]);
|
|
1254
|
+
}
|
|
1255
|
+
}
|
|
1256
|
+
processed[processed_len + len] = '\0';
|
|
1257
|
+
}
|
|
1258
|
+
|
|
1259
|
+
} else {
|
|
1260
|
+
// Long text processing
|
|
1261
|
+
strcpy(processed, "LONG: ");
|
|
1262
|
+
|
|
1263
|
+
// Count character types
|
|
1264
|
+
int uppercase_count = 0, lowercase_count = 0, digit_count = 0, special_count = 0;
|
|
1265
|
+
|
|
1266
|
+
for (size_t j = 0; j < len; j++) {
|
|
1267
|
+
if (isupper(text[j])) {
|
|
1268
|
+
uppercase_count++;
|
|
1269
|
+
} else if (islower(text[j])) {
|
|
1270
|
+
lowercase_count++;
|
|
1271
|
+
} else if (isdigit(text[j])) {
|
|
1272
|
+
digit_count++;
|
|
1273
|
+
} else {
|
|
1274
|
+
special_count++;
|
|
1275
|
+
}
|
|
1276
|
+
}
|
|
1277
|
+
|
|
1278
|
+
// Determine dominant character type
|
|
1279
|
+
if (uppercase_count > lowercase_count && uppercase_count > digit_count) {
|
|
1280
|
+
strcat(processed, "UPPER_DOM: ");
|
|
1281
|
+
} else if (lowercase_count > uppercase_count && lowercase_count > digit_count) {
|
|
1282
|
+
strcat(processed, "LOWER_DOM: ");
|
|
1283
|
+
} else if (digit_count > uppercase_count && digit_count > lowercase_count) {
|
|
1284
|
+
strcat(processed, "DIGIT_DOM: ");
|
|
1285
|
+
} else {
|
|
1286
|
+
strcat(processed, "MIXED_DOM: ");
|
|
1287
|
+
}
|
|
1288
|
+
|
|
1289
|
+
// Truncate and add summary
|
|
1290
|
+
size_t current_len = strlen(processed);
|
|
1291
|
+
if (len > 30) {
|
|
1292
|
+
strncat(processed, text, 30);
|
|
1293
|
+
strcat(processed, "...");
|
|
1294
|
+
sprintf(processed + strlen(processed), " (len=%zu)", len);
|
|
1295
|
+
} else {
|
|
1296
|
+
strcat(processed, text);
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
|
|
1300
|
+
output[current_output++] = processed;
|
|
1301
|
+
}
|
|
1302
|
+
|
|
1303
|
+
// Phase 2: Sort results by category
|
|
1304
|
+
for (int i = 0; i < current_output - 1; i++) {
|
|
1305
|
+
for (int j = i + 1; j < current_output; j++) {
|
|
1306
|
+
if (strcmp(output[i], output[j]) > 0) {
|
|
1307
|
+
char* temp = output[i];
|
|
1308
|
+
output[i] = output[j];
|
|
1309
|
+
output[j] = temp;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
|
|
1314
|
+
// Phase 3: Final validation and cleanup
|
|
1315
|
+
int final_count = 0;
|
|
1316
|
+
for (int i = 0; i < current_output; i++) {
|
|
1317
|
+
if (output[i] != NULL && strlen(output[i]) > 0) {
|
|
1318
|
+
if (final_count != i) {
|
|
1319
|
+
output[final_count] = output[i];
|
|
1320
|
+
}
|
|
1321
|
+
final_count++;
|
|
1322
|
+
} else {
|
|
1323
|
+
free(output[i]);
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
*output_count = final_count;
|
|
1328
|
+
return output;
|
|
1329
|
+
}
|
|
1330
|
+
"#;
|
|
1331
|
+
|
|
1332
|
+
fs::write(&test_file, content)?;
|
|
1333
|
+
|
|
1334
|
+
let ctx = TestContext::new();
|
|
1335
|
+
let output = ctx.run_probe(&[
|
|
1336
|
+
"search",
|
|
1337
|
+
"complex_text_processor",
|
|
1338
|
+
test_file.to_str().unwrap(),
|
|
1339
|
+
"--format",
|
|
1340
|
+
"outline",
|
|
1341
|
+
"--allow-tests",
|
|
1342
|
+
])?;
|
|
1343
|
+
|
|
1344
|
+
// Verify outline format for large function with closing brace comments
|
|
1345
|
+
assert!(
|
|
1346
|
+
output.contains("complex_text_processor"),
|
|
1347
|
+
"Missing complex_text_processor function - output: {}",
|
|
1348
|
+
output
|
|
1349
|
+
);
|
|
1350
|
+
assert!(
|
|
1351
|
+
output.contains("..."),
|
|
1352
|
+
"Missing truncation ellipsis in outline format - output: {}",
|
|
1353
|
+
output
|
|
1354
|
+
);
|
|
1355
|
+
// Should have closing brace comment for the large function
|
|
1356
|
+
assert!(
|
|
1357
|
+
output.contains("} //") || output.contains("}//") || output.contains("} /*"),
|
|
1358
|
+
"Missing closing brace comment for large function - output: {}",
|
|
1359
|
+
output
|
|
1360
|
+
);
|
|
1361
|
+
// Should show C-specific patterns for large functions
|
|
1362
|
+
let has_c_patterns =
|
|
1363
|
+
output.contains("char**") || output.contains("int*") || output.contains("function");
|
|
1364
|
+
assert!(
|
|
1365
|
+
has_c_patterns,
|
|
1366
|
+
"Missing C-specific patterns for large function - output: {}",
|
|
1367
|
+
output
|
|
1368
|
+
);
|
|
1369
|
+
|
|
1370
|
+
Ok(())
|
|
1371
|
+
}
|
|
1372
|
+
|
|
1373
|
+
#[test]
|
|
1374
|
+
fn test_c_outline_search_command() -> Result<()> {
|
|
1375
|
+
let temp_dir = TempDir::new()?;
|
|
1376
|
+
let test_file = temp_dir.path().join("search_test.c");
|
|
1377
|
+
|
|
1378
|
+
let content = r#"#include <stdio.h>
|
|
1379
|
+
#include <stdlib.h>
|
|
1380
|
+
|
|
1381
|
+
typedef struct DataProcessor {
|
|
1382
|
+
int processed_count;
|
|
1383
|
+
double* data;
|
|
1384
|
+
size_t capacity;
|
|
1385
|
+
} DataProcessor;
|
|
1386
|
+
|
|
1387
|
+
DataProcessor* create_processor(size_t initial_capacity) {
|
|
1388
|
+
DataProcessor* processor = malloc(sizeof(DataProcessor));
|
|
1389
|
+
if (processor == NULL) return NULL;
|
|
1390
|
+
|
|
1391
|
+
processor->processed_count = 0;
|
|
1392
|
+
processor->capacity = initial_capacity;
|
|
1393
|
+
processor->data = malloc(initial_capacity * sizeof(double));
|
|
1394
|
+
|
|
1395
|
+
if (processor->data == NULL) {
|
|
1396
|
+
free(processor);
|
|
1397
|
+
return NULL;
|
|
1398
|
+
}
|
|
1399
|
+
|
|
1400
|
+
return processor;
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1403
|
+
int process_data(DataProcessor* processor, double* input, size_t count) {
|
|
1404
|
+
if (processor == NULL || input == NULL) return -1;
|
|
1405
|
+
|
|
1406
|
+
for (size_t i = 0; i < count; i++) {
|
|
1407
|
+
if (input[i] != 0.0) {
|
|
1408
|
+
processor->data[processor->processed_count++] = input[i];
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
|
|
1412
|
+
return processor->processed_count;
|
|
1413
|
+
}
|
|
1414
|
+
|
|
1415
|
+
char* process_file(const char* filename) {
|
|
1416
|
+
if (filename == NULL) return NULL;
|
|
1417
|
+
|
|
1418
|
+
size_t len = strlen(filename) + 20;
|
|
1419
|
+
char* result = malloc(len);
|
|
1420
|
+
if (result == NULL) return NULL;
|
|
1421
|
+
|
|
1422
|
+
snprintf(result, len, "Processed %s", filename);
|
|
1423
|
+
return result;
|
|
1424
|
+
}
|
|
1425
|
+
|
|
1426
|
+
void process_async(DataProcessor* processor, void (*callback)(int)) {
|
|
1427
|
+
if (processor == NULL || callback == NULL) return;
|
|
1428
|
+
|
|
1429
|
+
// Simulate async processing
|
|
1430
|
+
int result = processor->processed_count * 2;
|
|
1431
|
+
callback(result);
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
void test_data_processing() {
|
|
1435
|
+
DataProcessor* processor = create_processor(100);
|
|
1436
|
+
if (processor == NULL) return;
|
|
1437
|
+
|
|
1438
|
+
double test_data[] = {1.0, 2.0, 0.0, 3.0};
|
|
1439
|
+
int count = process_data(processor, test_data, 4);
|
|
1440
|
+
|
|
1441
|
+
printf("Processed %d items\n", count);
|
|
1442
|
+
|
|
1443
|
+
free(processor->data);
|
|
1444
|
+
free(processor);
|
|
1445
|
+
}
|
|
1446
|
+
"#;
|
|
1447
|
+
|
|
1448
|
+
fs::write(&test_file, content)?;
|
|
1449
|
+
|
|
1450
|
+
let ctx = TestContext::new();
|
|
1451
|
+
let output = ctx.run_probe(&[
|
|
1452
|
+
"search",
|
|
1453
|
+
"process",
|
|
1454
|
+
temp_dir.path().to_str().unwrap(),
|
|
1455
|
+
"--format",
|
|
1456
|
+
"outline",
|
|
1457
|
+
"--allow-tests",
|
|
1458
|
+
])?;
|
|
1459
|
+
|
|
1460
|
+
// Should find symbols containing "process"
|
|
1461
|
+
assert!(
|
|
1462
|
+
output.contains("DataProcessor")
|
|
1463
|
+
|| output.contains("process_data")
|
|
1464
|
+
|| output.contains("process_file")
|
|
1465
|
+
|| output.contains("process_async"),
|
|
1466
|
+
"Should find process-related symbols - output: {}",
|
|
1467
|
+
output
|
|
1468
|
+
);
|
|
1469
|
+
|
|
1470
|
+
Ok(())
|
|
1471
|
+
}
|
|
1472
|
+
#[test]
|
|
1473
|
+
fn test_c_outline_closing_brace_comments_syntax() -> Result<()> {
|
|
1474
|
+
let temp_dir = TempDir::new()?;
|
|
1475
|
+
let test_file = temp_dir.path().join("closing_braces.c");
|
|
1476
|
+
|
|
1477
|
+
let content = r#"#include <stdio.h>
|
|
1478
|
+
#include <stdlib.h>
|
|
1479
|
+
|
|
1480
|
+
/**
|
|
1481
|
+
* Large function that should get C-style closing brace comment with // syntax
|
|
1482
|
+
*/
|
|
1483
|
+
int large_function_with_nested_blocks(int param1, int param2, int param3) {
|
|
1484
|
+
if (param1 > 0) {
|
|
1485
|
+
for (int i = 0; i < param1; i++) {
|
|
1486
|
+
if (param2 % 2 == 0) {
|
|
1487
|
+
switch (param3) {
|
|
1488
|
+
case 1:
|
|
1489
|
+
printf("Case 1\n");
|
|
1490
|
+
break;
|
|
1491
|
+
case 2:
|
|
1492
|
+
printf("Case 2\n");
|
|
1493
|
+
break;
|
|
1494
|
+
default:
|
|
1495
|
+
printf("Default case\n");
|
|
1496
|
+
break;
|
|
1497
|
+
}
|
|
1498
|
+
} else {
|
|
1499
|
+
while (param2 > 0) {
|
|
1500
|
+
param2--;
|
|
1501
|
+
if (param2 == 10) {
|
|
1502
|
+
break;
|
|
1503
|
+
}
|
|
1504
|
+
}
|
|
1505
|
+
}
|
|
1506
|
+
}
|
|
1507
|
+
}
|
|
1508
|
+
|
|
1509
|
+
// More code to make this function large
|
|
1510
|
+
int result = 0;
|
|
1511
|
+
for (int j = 0; j < 10; j++) {
|
|
1512
|
+
result += j * param1;
|
|
1513
|
+
}
|
|
1514
|
+
|
|
1515
|
+
return result;
|
|
1516
|
+
}
|
|
1517
|
+
|
|
1518
|
+
/**
|
|
1519
|
+
* Small function that should NOT get closing brace comments
|
|
1520
|
+
*/
|
|
1521
|
+
int small_function(int x) {
|
|
1522
|
+
return x * 2;
|
|
1523
|
+
}
|
|
1524
|
+
|
|
1525
|
+
/**
|
|
1526
|
+
* Medium function to test threshold behavior
|
|
1527
|
+
*/
|
|
1528
|
+
void medium_function(int count) {
|
|
1529
|
+
for (int i = 0; i < count; i++) {
|
|
1530
|
+
printf("Iteration: %d\n", i);
|
|
1531
|
+
if (i % 2 == 0) {
|
|
1532
|
+
printf("Even number\n");
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
}
|
|
1536
|
+
"#;
|
|
1537
|
+
|
|
1538
|
+
fs::write(&test_file, content)?;
|
|
1539
|
+
|
|
1540
|
+
let ctx = TestContext::new();
|
|
1541
|
+
let output = ctx.run_probe(&[
|
|
1542
|
+
"search",
|
|
1543
|
+
"large_function",
|
|
1544
|
+
test_file.to_str().unwrap(),
|
|
1545
|
+
"--format",
|
|
1546
|
+
"outline",
|
|
1547
|
+
"--allow-tests",
|
|
1548
|
+
])?;
|
|
1549
|
+
|
|
1550
|
+
// Should contain C-style closing brace comments with // syntax (not /* */)
|
|
1551
|
+
assert!(
|
|
1552
|
+
output.contains("} //"),
|
|
1553
|
+
"Missing C-style closing brace comments with // syntax - output: {}",
|
|
1554
|
+
output
|
|
1555
|
+
);
|
|
1556
|
+
|
|
1557
|
+
// Should not contain /* */ style comments for closing braces
|
|
1558
|
+
assert!(
|
|
1559
|
+
!output.contains("} /*") || !output.contains("*/"),
|
|
1560
|
+
"Should not use /* */ style for C closing brace comments - output: {}",
|
|
1561
|
+
output
|
|
1562
|
+
);
|
|
1563
|
+
|
|
1564
|
+
// Should show function keyword in closing brace comment
|
|
1565
|
+
assert!(
|
|
1566
|
+
output.contains("function") || output.contains("Function"),
|
|
1567
|
+
"Missing function keyword in closing brace comment - output: {}",
|
|
1568
|
+
output
|
|
1569
|
+
);
|
|
1570
|
+
|
|
1571
|
+
Ok(())
|
|
1572
|
+
}
|
|
1573
|
+
|
|
1574
|
+
#[test]
|
|
1575
|
+
fn test_c_outline_header_file_support() -> Result<()> {
|
|
1576
|
+
let temp_dir = TempDir::new()?;
|
|
1577
|
+
let test_file = temp_dir.path().join("header_test.h");
|
|
1578
|
+
|
|
1579
|
+
let content = r#"#ifndef HEADER_TEST_H
|
|
1580
|
+
#define HEADER_TEST_H
|
|
1581
|
+
|
|
1582
|
+
#include <stdint.h>
|
|
1583
|
+
#include <stdbool.h>
|
|
1584
|
+
|
|
1585
|
+
// Forward declarations
|
|
1586
|
+
typedef struct Point Point;
|
|
1587
|
+
typedef struct Vector Vector;
|
|
1588
|
+
|
|
1589
|
+
/**
|
|
1590
|
+
* Point structure with coordinates
|
|
1591
|
+
*/
|
|
1592
|
+
typedef struct Point {
|
|
1593
|
+
double x;
|
|
1594
|
+
double y;
|
|
1595
|
+
double z;
|
|
1596
|
+
} Point;
|
|
1597
|
+
|
|
1598
|
+
/**
|
|
1599
|
+
* Vector structure with direction and magnitude
|
|
1600
|
+
*/
|
|
1601
|
+
typedef struct Vector {
|
|
1602
|
+
Point start;
|
|
1603
|
+
Point end;
|
|
1604
|
+
double magnitude;
|
|
1605
|
+
bool normalized;
|
|
1606
|
+
} Vector;
|
|
1607
|
+
|
|
1608
|
+
/**
|
|
1609
|
+
* Function prototypes - typical header file pattern
|
|
1610
|
+
*/
|
|
1611
|
+
Point* create_point(double x, double y, double z);
|
|
1612
|
+
void destroy_point(Point* point);
|
|
1613
|
+
Vector* create_vector(Point* start, Point* end);
|
|
1614
|
+
void destroy_vector(Vector* vector);
|
|
1615
|
+
double calculate_distance(const Point* p1, const Point* p2);
|
|
1616
|
+
Vector* normalize_vector(Vector* vector);
|
|
1617
|
+
bool points_equal(const Point* p1, const Point* p2, double tolerance);
|
|
1618
|
+
|
|
1619
|
+
/**
|
|
1620
|
+
* Inline function definition in header
|
|
1621
|
+
*/
|
|
1622
|
+
static inline double point_magnitude(const Point* point) {
|
|
1623
|
+
if (point == NULL) {
|
|
1624
|
+
return 0.0;
|
|
1625
|
+
}
|
|
1626
|
+
return sqrt(point->x * point->x + point->y * point->y + point->z * point->z);
|
|
1627
|
+
}
|
|
1628
|
+
|
|
1629
|
+
/**
|
|
1630
|
+
* Macro definitions
|
|
1631
|
+
*/
|
|
1632
|
+
#define POINT_ZERO {0.0, 0.0, 0.0}
|
|
1633
|
+
#define VECTOR_ZERO {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, 0.0, false}
|
|
1634
|
+
#define MAX_POINTS 1000
|
|
1635
|
+
#define EPSILON 1e-10
|
|
1636
|
+
|
|
1637
|
+
/**
|
|
1638
|
+
* Conditional compilation for different platforms
|
|
1639
|
+
*/
|
|
1640
|
+
#ifdef __cplusplus
|
|
1641
|
+
extern "C" {
|
|
1642
|
+
#endif
|
|
1643
|
+
|
|
1644
|
+
// Additional C++ compatible declarations would go here
|
|
1645
|
+
|
|
1646
|
+
#ifdef __cplusplus
|
|
1647
|
+
}
|
|
1648
|
+
#endif
|
|
1649
|
+
|
|
1650
|
+
#endif // HEADER_TEST_H
|
|
1651
|
+
"#;
|
|
1652
|
+
|
|
1653
|
+
fs::write(&test_file, content)?;
|
|
1654
|
+
|
|
1655
|
+
let ctx = TestContext::new();
|
|
1656
|
+
let output = ctx.run_probe(&[
|
|
1657
|
+
"search",
|
|
1658
|
+
"typedef",
|
|
1659
|
+
test_file.to_str().unwrap(),
|
|
1660
|
+
"--format",
|
|
1661
|
+
"outline",
|
|
1662
|
+
"--allow-tests",
|
|
1663
|
+
])?;
|
|
1664
|
+
|
|
1665
|
+
// Should parse and format .h files correctly
|
|
1666
|
+
assert!(
|
|
1667
|
+
output.contains("Point") || output.contains("typedef"),
|
|
1668
|
+
"Missing Point struct in header file - output: {}",
|
|
1669
|
+
output
|
|
1670
|
+
);
|
|
1671
|
+
|
|
1672
|
+
// Should show header-specific patterns
|
|
1673
|
+
let has_header_patterns = output.contains("#ifndef")
|
|
1674
|
+
|| output.contains("#define")
|
|
1675
|
+
|| output.contains("typedef struct")
|
|
1676
|
+
|| output.contains("extern")
|
|
1677
|
+
|| output.contains("inline")
|
|
1678
|
+
|| output.contains("struct");
|
|
1679
|
+
assert!(
|
|
1680
|
+
has_header_patterns,
|
|
1681
|
+
"Missing header file specific patterns - output: {}",
|
|
1682
|
+
output
|
|
1683
|
+
);
|
|
1684
|
+
|
|
1685
|
+
// Should have outline formatting - search might not be long enough for truncation
|
|
1686
|
+
let has_outline_features =
|
|
1687
|
+
output.contains("...") || output.contains("typedef") || output.contains("Point");
|
|
1688
|
+
assert!(
|
|
1689
|
+
has_outline_features,
|
|
1690
|
+
"Missing outline format features in header file - output: {}",
|
|
1691
|
+
output
|
|
1692
|
+
);
|
|
1693
|
+
|
|
1694
|
+
Ok(())
|
|
1695
|
+
}
|
|
1696
|
+
|
|
1697
|
+
#[test]
|
|
1698
|
+
fn test_c_outline_test_detection() -> Result<()> {
|
|
1699
|
+
let temp_dir = TempDir::new()?;
|
|
1700
|
+
let test_file = temp_dir.path().join("test_functions.c");
|
|
1701
|
+
|
|
1702
|
+
let content = r#"#include <stdio.h>
|
|
1703
|
+
#include <assert.h>
|
|
1704
|
+
#include <string.h>
|
|
1705
|
+
|
|
1706
|
+
/**
|
|
1707
|
+
* Regular function - not a test
|
|
1708
|
+
*/
|
|
1709
|
+
int calculate_sum(int a, int b) {
|
|
1710
|
+
return a + b;
|
|
1711
|
+
}
|
|
1712
|
+
|
|
1713
|
+
/**
|
|
1714
|
+
* Test function with test_ prefix - should be detected as test
|
|
1715
|
+
*/
|
|
1716
|
+
void test_calculate_sum() {
|
|
1717
|
+
int result = calculate_sum(2, 3);
|
|
1718
|
+
assert(result == 5);
|
|
1719
|
+
printf("test_calculate_sum passed\n");
|
|
1720
|
+
}
|
|
1721
|
+
|
|
1722
|
+
/**
|
|
1723
|
+
* Another test function with test_ prefix
|
|
1724
|
+
*/
|
|
1725
|
+
void test_string_operations() {
|
|
1726
|
+
char buffer[100];
|
|
1727
|
+
strcpy(buffer, "Hello");
|
|
1728
|
+
strcat(buffer, " World");
|
|
1729
|
+
|
|
1730
|
+
assert(strcmp(buffer, "Hello World") == 0);
|
|
1731
|
+
assert(strlen(buffer) == 11);
|
|
1732
|
+
|
|
1733
|
+
printf("test_string_operations passed\n");
|
|
1734
|
+
}
|
|
1735
|
+
|
|
1736
|
+
/**
|
|
1737
|
+
* Test function with assert statements - should be detected
|
|
1738
|
+
*/
|
|
1739
|
+
int test_array_operations() {
|
|
1740
|
+
int arr[] = {1, 2, 3, 4, 5};
|
|
1741
|
+
int sum = 0;
|
|
1742
|
+
|
|
1743
|
+
for (int i = 0; i < 5; i++) {
|
|
1744
|
+
sum += arr[i];
|
|
1745
|
+
}
|
|
1746
|
+
|
|
1747
|
+
assert(sum == 15);
|
|
1748
|
+
assert(arr[0] == 1);
|
|
1749
|
+
assert(arr[4] == 5);
|
|
1750
|
+
|
|
1751
|
+
return 0;
|
|
1752
|
+
}
|
|
1753
|
+
|
|
1754
|
+
/**
|
|
1755
|
+
* Function with assert but not a test name - might be detected
|
|
1756
|
+
*/
|
|
1757
|
+
void validate_input(int input) {
|
|
1758
|
+
assert(input > 0);
|
|
1759
|
+
assert(input < 1000);
|
|
1760
|
+
printf("Input %d is valid\n", input);
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
/**
|
|
1764
|
+
* Unit test style function
|
|
1765
|
+
*/
|
|
1766
|
+
void test_memory_allocation() {
|
|
1767
|
+
int* ptr = malloc(sizeof(int) * 10);
|
|
1768
|
+
assert(ptr != NULL);
|
|
1769
|
+
|
|
1770
|
+
for (int i = 0; i < 10; i++) {
|
|
1771
|
+
ptr[i] = i * 2;
|
|
1772
|
+
}
|
|
1773
|
+
|
|
1774
|
+
assert(ptr[5] == 10);
|
|
1775
|
+
free(ptr);
|
|
1776
|
+
|
|
1777
|
+
printf("test_memory_allocation passed\n");
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
/**
|
|
1781
|
+
* Main function to run tests
|
|
1782
|
+
*/
|
|
1783
|
+
int main() {
|
|
1784
|
+
test_calculate_sum();
|
|
1785
|
+
test_string_operations();
|
|
1786
|
+
test_array_operations();
|
|
1787
|
+
test_memory_allocation();
|
|
1788
|
+
validate_input(42);
|
|
1789
|
+
|
|
1790
|
+
printf("All tests passed!\n");
|
|
1791
|
+
return 0;
|
|
1792
|
+
}
|
|
1793
|
+
"#;
|
|
1794
|
+
|
|
1795
|
+
fs::write(&test_file, content)?;
|
|
1796
|
+
|
|
1797
|
+
let ctx = TestContext::new();
|
|
1798
|
+
let output = ctx.run_probe(&[
|
|
1799
|
+
"search",
|
|
1800
|
+
"assert",
|
|
1801
|
+
test_file.to_str().unwrap(),
|
|
1802
|
+
"--format",
|
|
1803
|
+
"outline",
|
|
1804
|
+
"--allow-tests",
|
|
1805
|
+
])?;
|
|
1806
|
+
|
|
1807
|
+
// Should find test-related functions or patterns
|
|
1808
|
+
let has_test_content = output.contains("test_calculate_sum")
|
|
1809
|
+
|| output.contains("test_string_operations")
|
|
1810
|
+
|| output.contains("assert")
|
|
1811
|
+
|| output.contains("calculate_sum");
|
|
1812
|
+
assert!(
|
|
1813
|
+
has_test_content,
|
|
1814
|
+
"Missing test-related content - output: {}",
|
|
1815
|
+
output
|
|
1816
|
+
);
|
|
1817
|
+
|
|
1818
|
+
// Should show C test patterns
|
|
1819
|
+
let has_c_test_patterns = output.contains("assert")
|
|
1820
|
+
|| output.contains("int")
|
|
1821
|
+
|| output.contains("void")
|
|
1822
|
+
|| output.contains("printf")
|
|
1823
|
+
|| output.contains("malloc");
|
|
1824
|
+
assert!(
|
|
1825
|
+
has_c_test_patterns,
|
|
1826
|
+
"Missing C test-related patterns - output: {}",
|
|
1827
|
+
output
|
|
1828
|
+
);
|
|
1829
|
+
|
|
1830
|
+
// Should have outline formatting features
|
|
1831
|
+
let has_outline_features = output.contains("...")
|
|
1832
|
+
|| output.contains("assert")
|
|
1833
|
+
|| output.contains("test_")
|
|
1834
|
+
|| output.contains("void");
|
|
1835
|
+
assert!(
|
|
1836
|
+
has_outline_features,
|
|
1837
|
+
"Missing outline format features in test detection - output: {}",
|
|
1838
|
+
output
|
|
1839
|
+
);
|
|
1840
|
+
|
|
1841
|
+
Ok(())
|
|
1842
|
+
}
|
|
1843
|
+
|
|
1844
|
+
#[test]
|
|
1845
|
+
fn test_c_outline_pointer_and_advanced_constructs() -> Result<()> {
|
|
1846
|
+
let temp_dir = TempDir::new()?;
|
|
1847
|
+
let test_file = temp_dir.path().join("advanced_c.c");
|
|
1848
|
+
|
|
1849
|
+
let content = r#"#include <stdio.h>
|
|
1850
|
+
#include <stdlib.h>
|
|
1851
|
+
#include <string.h>
|
|
1852
|
+
|
|
1853
|
+
/**
|
|
1854
|
+
* Function pointer typedef
|
|
1855
|
+
*/
|
|
1856
|
+
typedef int (*CompareFunc)(const void* a, const void* b);
|
|
1857
|
+
typedef void (*CallbackFunc)(int result, void* user_data);
|
|
1858
|
+
|
|
1859
|
+
/**
|
|
1860
|
+
* Complex struct with function pointers
|
|
1861
|
+
*/
|
|
1862
|
+
typedef struct Processor {
|
|
1863
|
+
char name[64];
|
|
1864
|
+
CompareFunc compare_func;
|
|
1865
|
+
CallbackFunc callback_func;
|
|
1866
|
+
void* user_data;
|
|
1867
|
+
int (*process_func)(struct Processor* self, void* data, size_t size);
|
|
1868
|
+
void (*cleanup_func)(struct Processor* self);
|
|
1869
|
+
} Processor;
|
|
1870
|
+
|
|
1871
|
+
/**
|
|
1872
|
+
* Function that takes function pointer as parameter
|
|
1873
|
+
*/
|
|
1874
|
+
void process_array_with_callback(int* array, size_t length,
|
|
1875
|
+
int (*transform_func)(int value),
|
|
1876
|
+
void (*result_callback)(int index, int result)) {
|
|
1877
|
+
if (array == NULL || transform_func == NULL) {
|
|
1878
|
+
return;
|
|
1879
|
+
}
|
|
1880
|
+
|
|
1881
|
+
for (size_t i = 0; i < length; i++) {
|
|
1882
|
+
int result = transform_func(array[i]);
|
|
1883
|
+
if (result_callback != NULL) {
|
|
1884
|
+
result_callback((int)i, result);
|
|
1885
|
+
}
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
|
|
1889
|
+
/**
|
|
1890
|
+
* Function returning pointer to pointer
|
|
1891
|
+
*/
|
|
1892
|
+
char** create_string_array(int count, const char* prefix) {
|
|
1893
|
+
char** strings = malloc(count * sizeof(char*));
|
|
1894
|
+
if (strings == NULL) {
|
|
1895
|
+
return NULL;
|
|
1896
|
+
}
|
|
1897
|
+
|
|
1898
|
+
for (int i = 0; i < count; i++) {
|
|
1899
|
+
size_t len = strlen(prefix) + 20;
|
|
1900
|
+
strings[i] = malloc(len);
|
|
1901
|
+
if (strings[i] != NULL) {
|
|
1902
|
+
snprintf(strings[i], len, "%s_%d", prefix, i);
|
|
1903
|
+
}
|
|
1904
|
+
}
|
|
1905
|
+
|
|
1906
|
+
return strings;
|
|
1907
|
+
}
|
|
1908
|
+
|
|
1909
|
+
/**
|
|
1910
|
+
* Function with complex pointer arithmetic
|
|
1911
|
+
*/
|
|
1912
|
+
void reverse_array_pointers(int* start, int* end) {
|
|
1913
|
+
while (start < end) {
|
|
1914
|
+
int temp = *start;
|
|
1915
|
+
*start = *end;
|
|
1916
|
+
*end = temp;
|
|
1917
|
+
start++;
|
|
1918
|
+
end--;
|
|
1919
|
+
}
|
|
1920
|
+
}
|
|
1921
|
+
|
|
1922
|
+
/**
|
|
1923
|
+
* Function with void pointer and casting
|
|
1924
|
+
*/
|
|
1925
|
+
void generic_swap(void* a, void* b, size_t size) {
|
|
1926
|
+
unsigned char* byte_a = (unsigned char*)a;
|
|
1927
|
+
unsigned char* byte_b = (unsigned char*)b;
|
|
1928
|
+
|
|
1929
|
+
for (size_t i = 0; i < size; i++) {
|
|
1930
|
+
unsigned char temp = byte_a[i];
|
|
1931
|
+
byte_a[i] = byte_b[i];
|
|
1932
|
+
byte_b[i] = temp;
|
|
1933
|
+
}
|
|
1934
|
+
}
|
|
1935
|
+
|
|
1936
|
+
/**
|
|
1937
|
+
* Preprocessor macro with function-like behavior
|
|
1938
|
+
*/
|
|
1939
|
+
#define SAFE_DELETE(ptr) do { \
|
|
1940
|
+
if ((ptr) != NULL) { \
|
|
1941
|
+
free(ptr); \
|
|
1942
|
+
(ptr) = NULL; \
|
|
1943
|
+
} \
|
|
1944
|
+
} while(0)
|
|
1945
|
+
|
|
1946
|
+
#define MAX(a, b) ((a) > (b) ? (a) : (b))
|
|
1947
|
+
#define MIN(a, b) ((a) < (b) ? (a) : (b))
|
|
1948
|
+
|
|
1949
|
+
/**
|
|
1950
|
+
* Function using the macros
|
|
1951
|
+
*/
|
|
1952
|
+
void cleanup_processor(Processor** processor_ptr) {
|
|
1953
|
+
if (processor_ptr == NULL || *processor_ptr == NULL) {
|
|
1954
|
+
return;
|
|
1955
|
+
}
|
|
1956
|
+
|
|
1957
|
+
Processor* proc = *processor_ptr;
|
|
1958
|
+
|
|
1959
|
+
if (proc->cleanup_func != NULL) {
|
|
1960
|
+
proc->cleanup_func(proc);
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
SAFE_DELETE(proc->user_data);
|
|
1964
|
+
SAFE_DELETE(*processor_ptr);
|
|
1965
|
+
}
|
|
1966
|
+
"#;
|
|
1967
|
+
|
|
1968
|
+
fs::write(&test_file, content)?;
|
|
1969
|
+
|
|
1970
|
+
let ctx = TestContext::new();
|
|
1971
|
+
let output = ctx.run_probe(&[
|
|
1972
|
+
"search",
|
|
1973
|
+
"typedef",
|
|
1974
|
+
test_file.to_str().unwrap(),
|
|
1975
|
+
"--format",
|
|
1976
|
+
"outline",
|
|
1977
|
+
"--allow-tests",
|
|
1978
|
+
])?;
|
|
1979
|
+
|
|
1980
|
+
// Should show function pointer and pointer-related patterns
|
|
1981
|
+
let has_pointer_patterns = output.contains("*")
|
|
1982
|
+
|| output.contains("CompareFunc")
|
|
1983
|
+
|| output.contains("CallbackFunc")
|
|
1984
|
+
|| output.contains("void*")
|
|
1985
|
+
|| output.contains("char**")
|
|
1986
|
+
|| output.contains("int*")
|
|
1987
|
+
|| output.contains("typedef");
|
|
1988
|
+
assert!(
|
|
1989
|
+
has_pointer_patterns,
|
|
1990
|
+
"Missing pointer-related patterns - output: {}",
|
|
1991
|
+
output
|
|
1992
|
+
);
|
|
1993
|
+
|
|
1994
|
+
// Should have outline formatting features
|
|
1995
|
+
let has_outline_features = output.contains("...")
|
|
1996
|
+
|| output.contains("typedef")
|
|
1997
|
+
|| output.contains("CompareFunc")
|
|
1998
|
+
|| output.contains("struct");
|
|
1999
|
+
assert!(
|
|
2000
|
+
has_outline_features,
|
|
2001
|
+
"Missing outline format features in advanced C constructs - output: {}",
|
|
2002
|
+
output
|
|
2003
|
+
);
|
|
2004
|
+
|
|
2005
|
+
// Should show C-specific advanced constructs
|
|
2006
|
+
let has_advanced_c = output.contains("typedef")
|
|
2007
|
+
|| output.contains("struct")
|
|
2008
|
+
|| output.contains("malloc")
|
|
2009
|
+
|| output.contains("sizeof")
|
|
2010
|
+
|| output.contains("#define")
|
|
2011
|
+
|| output.contains("Processor");
|
|
2012
|
+
assert!(
|
|
2013
|
+
has_advanced_c,
|
|
2014
|
+
"Missing advanced C constructs - output: {}",
|
|
2015
|
+
output
|
|
2016
|
+
);
|
|
2017
|
+
|
|
2018
|
+
Ok(())
|
|
2019
|
+
}
|
|
2020
|
+
|
|
2021
|
+
#[test]
|
|
2022
|
+
fn test_c_outline_keyword_highlighting() -> Result<()> {
|
|
2023
|
+
let temp_dir = TempDir::new()?;
|
|
2024
|
+
let test_file = temp_dir.path().join("keyword_test.c");
|
|
2025
|
+
|
|
2026
|
+
let content = r#"#include <stdio.h>
|
|
2027
|
+
#include <stdlib.h>
|
|
2028
|
+
#include <stdbool.h>
|
|
2029
|
+
|
|
2030
|
+
/**
|
|
2031
|
+
* Function demonstrating various C keywords for highlighting
|
|
2032
|
+
*/
|
|
2033
|
+
int demonstrate_keywords(int count, const char* message, bool verbose) {
|
|
2034
|
+
// Static local variable
|
|
2035
|
+
static int call_count = 0;
|
|
2036
|
+
call_count++;
|
|
2037
|
+
|
|
2038
|
+
// Register variable (though rarely used in modern C)
|
|
2039
|
+
register int fast_counter;
|
|
2040
|
+
|
|
2041
|
+
// Volatile variable
|
|
2042
|
+
volatile int shared_flag = 0;
|
|
2043
|
+
|
|
2044
|
+
// Const pointer to const data
|
|
2045
|
+
const char* const constant_message = "Hello, World!";
|
|
2046
|
+
|
|
2047
|
+
// Auto keyword (implicit in C99+)
|
|
2048
|
+
auto int automatic_var = 42;
|
|
2049
|
+
|
|
2050
|
+
// Extern declaration
|
|
2051
|
+
extern int global_variable;
|
|
2052
|
+
|
|
2053
|
+
// Different loop types with keywords
|
|
2054
|
+
for (fast_counter = 0; fast_counter < count; fast_counter++) {
|
|
2055
|
+
if (verbose && fast_counter % 2 == 0) {
|
|
2056
|
+
printf("Processing item %d: %s\n", fast_counter, message);
|
|
2057
|
+
}
|
|
2058
|
+
|
|
2059
|
+
switch (fast_counter % 4) {
|
|
2060
|
+
case 0:
|
|
2061
|
+
if (shared_flag == 0) {
|
|
2062
|
+
shared_flag = 1;
|
|
2063
|
+
}
|
|
2064
|
+
break;
|
|
2065
|
+
case 1:
|
|
2066
|
+
while (shared_flag > 0) {
|
|
2067
|
+
shared_flag--;
|
|
2068
|
+
if (shared_flag <= 0) break;
|
|
2069
|
+
}
|
|
2070
|
+
break;
|
|
2071
|
+
case 2:
|
|
2072
|
+
do {
|
|
2073
|
+
shared_flag++;
|
|
2074
|
+
} while (shared_flag < 3);
|
|
2075
|
+
break;
|
|
2076
|
+
default:
|
|
2077
|
+
goto cleanup;
|
|
2078
|
+
}
|
|
2079
|
+
}
|
|
2080
|
+
|
|
2081
|
+
cleanup:
|
|
2082
|
+
// Return with appropriate value
|
|
2083
|
+
return call_count;
|
|
2084
|
+
}
|
|
2085
|
+
|
|
2086
|
+
/**
|
|
2087
|
+
* Function with different storage classes and type qualifiers
|
|
2088
|
+
*/
|
|
2089
|
+
static inline void storage_class_demo(void) {
|
|
2090
|
+
// Different storage classes
|
|
2091
|
+
static const int static_const_var = 100;
|
|
2092
|
+
extern volatile int extern_volatile_var;
|
|
2093
|
+
register unsigned int register_var = 0;
|
|
2094
|
+
|
|
2095
|
+
// Type qualifiers
|
|
2096
|
+
const int* const_ptr;
|
|
2097
|
+
volatile int* volatile_ptr;
|
|
2098
|
+
restrict int* restrict_ptr; // C99 feature
|
|
2099
|
+
|
|
2100
|
+
// Compound types
|
|
2101
|
+
struct {
|
|
2102
|
+
union {
|
|
2103
|
+
int int_val;
|
|
2104
|
+
float float_val;
|
|
2105
|
+
} data;
|
|
2106
|
+
enum {
|
|
2107
|
+
STATE_INIT,
|
|
2108
|
+
STATE_RUNNING,
|
|
2109
|
+
STATE_STOPPED
|
|
2110
|
+
} state;
|
|
2111
|
+
} compound_var;
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
/**
|
|
2115
|
+
* Function using sizeof, typeof (GCC extension), and other operators
|
|
2116
|
+
*/
|
|
2117
|
+
void operator_keyword_demo(void) {
|
|
2118
|
+
int array[10];
|
|
2119
|
+
size_t array_size = sizeof(array);
|
|
2120
|
+
size_t element_size = sizeof(array[0]);
|
|
2121
|
+
size_t num_elements = array_size / element_size;
|
|
2122
|
+
|
|
2123
|
+
// Typeof is a GCC extension
|
|
2124
|
+
#ifdef __GNUC__
|
|
2125
|
+
typeof(array[0]) another_int = 42;
|
|
2126
|
+
#endif
|
|
2127
|
+
|
|
2128
|
+
// Alignment specifier (C11)
|
|
2129
|
+
#if __STDC_VERSION__ >= 201112L
|
|
2130
|
+
_Alignas(16) int aligned_var;
|
|
2131
|
+
size_t alignment = _Alignof(int);
|
|
2132
|
+
#endif
|
|
2133
|
+
}
|
|
2134
|
+
"#;
|
|
2135
|
+
|
|
2136
|
+
fs::write(&test_file, content)?;
|
|
2137
|
+
|
|
2138
|
+
let ctx = TestContext::new();
|
|
2139
|
+
let output = ctx.run_probe(&[
|
|
2140
|
+
"search",
|
|
2141
|
+
"demonstrate_keywords",
|
|
2142
|
+
test_file.to_str().unwrap(),
|
|
2143
|
+
"--format",
|
|
2144
|
+
"outline",
|
|
2145
|
+
"--allow-tests",
|
|
2146
|
+
])?;
|
|
2147
|
+
|
|
2148
|
+
// Should find functions with keyword in their name or content
|
|
2149
|
+
assert!(
|
|
2150
|
+
output.contains("keyword") || output.contains("demonstrate_keywords"),
|
|
2151
|
+
"Missing keyword-related functions - output: {}",
|
|
2152
|
+
output
|
|
2153
|
+
);
|
|
2154
|
+
|
|
2155
|
+
// Should show C keywords in the outline format
|
|
2156
|
+
let has_c_keywords = output.contains("static")
|
|
2157
|
+
|| output.contains("const")
|
|
2158
|
+
|| output.contains("volatile")
|
|
2159
|
+
|| output.contains("int")
|
|
2160
|
+
|| output.contains("void")
|
|
2161
|
+
|| output.contains("for")
|
|
2162
|
+
|| output.contains("while")
|
|
2163
|
+
|| output.contains("if")
|
|
2164
|
+
|| output.contains("switch");
|
|
2165
|
+
assert!(
|
|
2166
|
+
has_c_keywords,
|
|
2167
|
+
"Missing C keywords in outline format - output: {}",
|
|
2168
|
+
output
|
|
2169
|
+
);
|
|
2170
|
+
|
|
2171
|
+
// Should have outline formatting with truncation
|
|
2172
|
+
assert!(
|
|
2173
|
+
output.contains("..."),
|
|
2174
|
+
"Missing truncation in keyword demonstration outline - output: {}",
|
|
2175
|
+
output
|
|
2176
|
+
);
|
|
2177
|
+
|
|
2178
|
+
Ok(())
|
|
2179
|
+
}
|