@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.
Files changed (444) hide show
  1. package/README.md +138 -0
  2. package/data/.env.example +22 -0
  3. package/data/.gitattributes +47 -0
  4. package/data/.glfrc.json +7 -0
  5. package/data/.husky/pre-commit +5 -0
  6. package/data/.nvmrc +1 -0
  7. package/data/CHANGELOG.md +75 -0
  8. package/data/CODE_OF_CONDUCT.md +129 -0
  9. package/data/CONTRIBUTING.md +203 -0
  10. package/data/DOCS-STRUCTURE.md +307 -0
  11. package/data/I18N.md +292 -0
  12. package/data/LICENSE +22 -0
  13. package/data/README.md +315 -0
  14. package/data/SECURITY.md +125 -0
  15. package/data/WIKI-DEPLOYMENT.md +348 -0
  16. package/data/docs/AI-FEATURES.md +610 -0
  17. package/data/docs/API-REFERENCE.md +1022 -0
  18. package/data/docs/AUTHENTICATION.md +301 -0
  19. package/data/docs/BACKEND-API.md +468 -0
  20. package/data/docs/DEVELOPMENT.md +375 -0
  21. package/data/docs/EXAMPLES.md +622 -0
  22. package/data/docs/MCP-SERVER.md +307 -0
  23. package/data/docs/MIGRATION-GUIDE.md +367 -0
  24. package/data/docs/NPM-PUBLISH.md +193 -0
  25. package/data/docs/QUICKSTART.md +206 -0
  26. package/data/docs/REDIS-SETUP.md +162 -0
  27. package/data/docs/SERVER.md +228 -0
  28. package/data/docs/TROUBLESHOOTING.md +657 -0
  29. package/data/docs/WIDGET-GUIDE.md +638 -0
  30. package/data/docs/WIKI-HOME.md +58 -0
  31. package/data/docs/WIKI-SIDEBAR.md +39 -0
  32. package/data/package.json +171 -0
  33. package/data/playwright.config.ts +64 -0
  34. package/data/probe/.cargo/config.toml +10 -0
  35. package/data/probe/.claude/commands/performance-review.md +15 -0
  36. package/data/probe/.clinerules +288 -0
  37. package/data/probe/.dockerignore +57 -0
  38. package/data/probe/.githooks/post-commit +11 -0
  39. package/data/probe/.githooks/pre-commit +99 -0
  40. package/data/probe/.githooks/pre-commit-vow +9 -0
  41. package/data/probe/.prompts/engineer.md +41 -0
  42. package/data/probe/.roomodes +28 -0
  43. package/data/probe/.windsurfrules +0 -0
  44. package/data/probe/BASH_TOOL_SUMMARY.md +148 -0
  45. package/data/probe/BENCHMARKING.md +256 -0
  46. package/data/probe/CLAUDE.md +226 -0
  47. package/data/probe/CODE_OF_CONDUCT.md +128 -0
  48. package/data/probe/CONTRIBUTING.md +193 -0
  49. package/data/probe/Cargo.toml +120 -0
  50. package/data/probe/Cross.toml +10 -0
  51. package/data/probe/DOCKER-README.md +224 -0
  52. package/data/probe/Dockerfile +32 -0
  53. package/data/probe/ENHANCED_DEBUG_TELEMETRY.md +188 -0
  54. package/data/probe/LICENSE +201 -0
  55. package/data/probe/Makefile +210 -0
  56. package/data/probe/README.md +824 -0
  57. package/data/probe/SECURITY.md +67 -0
  58. package/data/probe/WINDOWS-GUIDE.md +294 -0
  59. package/data/probe/benches/parsing_benchmarks.rs +370 -0
  60. package/data/probe/benches/search_benchmarks.rs +599 -0
  61. package/data/probe/benches/simd_benchmarks.rs +372 -0
  62. package/data/probe/benches/timing_benchmarks.rs +287 -0
  63. package/data/probe/build-windows.bat +229 -0
  64. package/data/probe/codex-config/config.toml +6 -0
  65. package/data/probe/docs/PERFORMANCE_OPTIMIZATION.md +161 -0
  66. package/data/probe/examples/cache_demo.rs +46 -0
  67. package/data/probe/examples/chat/.dockerignore +37 -0
  68. package/data/probe/examples/chat/ChatSessionManager.js +295 -0
  69. package/data/probe/examples/chat/Dockerfile +98 -0
  70. package/data/probe/examples/chat/LICENSE +201 -0
  71. package/data/probe/examples/chat/LOCAL_IMAGE_SUPPORT.md +195 -0
  72. package/data/probe/examples/chat/MCP_INTEGRATION.md +400 -0
  73. package/data/probe/examples/chat/README.md +338 -0
  74. package/data/probe/examples/chat/TRACING.md +226 -0
  75. package/data/probe/examples/chat/appTracer.js +968 -0
  76. package/data/probe/examples/chat/auth.js +76 -0
  77. package/data/probe/examples/chat/bin/probe-chat.js +13 -0
  78. package/data/probe/examples/chat/build.js +104 -0
  79. package/data/probe/examples/chat/cancelRequest.js +84 -0
  80. package/data/probe/examples/chat/demo-agentic-image-flow.js +88 -0
  81. package/data/probe/examples/chat/demo-local-images.js +128 -0
  82. package/data/probe/examples/chat/fileSpanExporter.js +181 -0
  83. package/data/probe/examples/chat/implement/README.md +228 -0
  84. package/data/probe/examples/chat/implement/backends/AiderBackend.js +750 -0
  85. package/data/probe/examples/chat/implement/backends/BaseBackend.js +276 -0
  86. package/data/probe/examples/chat/implement/backends/ClaudeCodeBackend.js +767 -0
  87. package/data/probe/examples/chat/implement/backends/MockBackend.js +237 -0
  88. package/data/probe/examples/chat/implement/backends/registry.js +85 -0
  89. package/data/probe/examples/chat/implement/core/BackendManager.js +567 -0
  90. package/data/probe/examples/chat/implement/core/ImplementTool.js +354 -0
  91. package/data/probe/examples/chat/implement/core/config.js +428 -0
  92. package/data/probe/examples/chat/implement/core/timeouts.js +58 -0
  93. package/data/probe/examples/chat/implement/core/utils.js +496 -0
  94. package/data/probe/examples/chat/implement/types/BackendTypes.js +126 -0
  95. package/data/probe/examples/chat/index.js +669 -0
  96. package/data/probe/examples/chat/mcpServer.js +341 -0
  97. package/data/probe/examples/chat/npm/LICENSE +15 -0
  98. package/data/probe/examples/chat/npm/README.md +168 -0
  99. package/data/probe/examples/chat/npm/bin/probe-chat.js +156 -0
  100. package/data/probe/examples/chat/npm/index.js +259 -0
  101. package/data/probe/examples/chat/npm/package.json +54 -0
  102. package/data/probe/examples/chat/package.json +102 -0
  103. package/data/probe/examples/chat/probeChat.js +456 -0
  104. package/data/probe/examples/chat/probeTool.js +491 -0
  105. package/data/probe/examples/chat/storage/JsonChatStorage.js +476 -0
  106. package/data/probe/examples/chat/telemetry.js +281 -0
  107. package/data/probe/examples/chat/test/integration/chatFlows.test.js +320 -0
  108. package/data/probe/examples/chat/test/integration/toolCalling.test.js +471 -0
  109. package/data/probe/examples/chat/test/mocks/mockLLMProvider.js +269 -0
  110. package/data/probe/examples/chat/test/test-backends.js +90 -0
  111. package/data/probe/examples/chat/test/testUtils.js +530 -0
  112. package/data/probe/examples/chat/test/unit/backendTimeout.test.js +161 -0
  113. package/data/probe/examples/chat/test/unit/packageFiles.test.js +120 -0
  114. package/data/probe/examples/chat/test/verify-tests.js +118 -0
  115. package/data/probe/examples/chat/test-agentic-image-loading.js +294 -0
  116. package/data/probe/examples/chat/test-ai-sdk-telemetry.js +204 -0
  117. package/data/probe/examples/chat/test-chat-tracing.js +38 -0
  118. package/data/probe/examples/chat/test-direct-function.js +49 -0
  119. package/data/probe/examples/chat/test-file-size-validation.js +103 -0
  120. package/data/probe/examples/chat/test-full-mcp-integration.js +258 -0
  121. package/data/probe/examples/chat/test-github-context.txt +12 -0
  122. package/data/probe/examples/chat/test-hierarchy.js +203 -0
  123. package/data/probe/examples/chat/test-image-spans.js +37 -0
  124. package/data/probe/examples/chat/test-local-image-reading.js +176 -0
  125. package/data/probe/examples/chat/test-mcp-integration.js +136 -0
  126. package/data/probe/examples/chat/test-mcp-probe-server.js +161 -0
  127. package/data/probe/examples/chat/test-mcp-with-ai.js +279 -0
  128. package/data/probe/examples/chat/test-multiple-allowed-dirs.js +111 -0
  129. package/data/probe/examples/chat/test-probe-mcp-server.js +110 -0
  130. package/data/probe/examples/chat/test-security-validation.js +145 -0
  131. package/data/probe/examples/chat/test-simple-tracing.js +32 -0
  132. package/data/probe/examples/chat/test-trace-verification.js +235 -0
  133. package/data/probe/examples/chat/test-tracing.js +114 -0
  134. package/data/probe/examples/chat/tokenCounter.js +419 -0
  135. package/data/probe/examples/chat/tokenUsageDisplay.js +134 -0
  136. package/data/probe/examples/chat/webServer.js +1103 -0
  137. package/data/probe/examples/reranker/Cargo.toml +33 -0
  138. package/data/probe/examples/reranker/DEBUG_OUTPUT_ANALYSIS.md +71 -0
  139. package/data/probe/examples/reranker/MODELS.md +66 -0
  140. package/data/probe/examples/reranker/MODEL_COMPARISON.md +60 -0
  141. package/data/probe/examples/reranker/MULTI_MODEL_ANALYSIS.md +176 -0
  142. package/data/probe/examples/reranker/PERFORMANCE_SUMMARY.md +156 -0
  143. package/data/probe/examples/reranker/README.md +347 -0
  144. package/data/probe/examples/reranker/RUST_BERT_COMPARISON.md +82 -0
  145. package/data/probe/examples/reranker/TOKENIZATION_GUIDE.md +120 -0
  146. package/data/probe/examples/reranker/check_rust_tokenizer.py +108 -0
  147. package/data/probe/examples/reranker/convert_to_torchscript.py +109 -0
  148. package/data/probe/examples/reranker/debug_scoring.py +189 -0
  149. package/data/probe/examples/reranker/debug_tokenization.py +154 -0
  150. package/data/probe/examples/reranker/download_models.sh +73 -0
  151. package/data/probe/examples/reranker/requirements.txt +13 -0
  152. package/data/probe/examples/reranker/run_comprehensive_benchmark.sh +83 -0
  153. package/data/probe/examples/reranker/rust_bert_test/Cargo.toml +12 -0
  154. package/data/probe/examples/reranker/rust_bert_test/README.md +54 -0
  155. package/data/probe/examples/reranker/simple_test.py +50 -0
  156. package/data/probe/examples/reranker/test_all_models.sh +63 -0
  157. package/data/probe/examples/reranker/test_bert_results.sh +44 -0
  158. package/data/probe/examples/reranker/test_cross_encoder.py +334 -0
  159. package/data/probe/examples/reranker/test_cross_encoder.sh +80 -0
  160. package/data/probe/examples/reranker/test_exact_comparison.py +151 -0
  161. package/data/probe/examples/reranker/test_parallel_performance.sh +56 -0
  162. package/data/probe/examples/reranker/test_scores.py +132 -0
  163. package/data/probe/install.ps1 +508 -0
  164. package/data/probe/install.sh +460 -0
  165. package/data/probe/npm/CLONE_METHOD_EXAMPLES.md +596 -0
  166. package/data/probe/npm/CONTEXT_COMPACTION.md +303 -0
  167. package/data/probe/npm/DELEGATE_TOOL_README.md +166 -0
  168. package/data/probe/npm/MAID_INTEGRATION.md +313 -0
  169. package/data/probe/npm/MCP_INTEGRATION_SUMMARY.md +241 -0
  170. package/data/probe/npm/README.md +824 -0
  171. package/data/probe/npm/bin/.gitignore +7 -0
  172. package/data/probe/npm/bin/.gitkeep +0 -0
  173. package/data/probe/npm/bin/README.md +12 -0
  174. package/data/probe/npm/bin/probe +167 -0
  175. package/data/probe/npm/docs/CLAUDE_CODE_INTEGRATION.md +414 -0
  176. package/data/probe/npm/docs/CODEX_INTEGRATION.md +502 -0
  177. package/data/probe/npm/docs/EDIT_CREATE_TOOLS.md +233 -0
  178. package/data/probe/npm/docs/RETRY_AND_FALLBACK.md +674 -0
  179. package/data/probe/npm/example-usage.js +335 -0
  180. package/data/probe/npm/examples/multi-engine-demo.js +117 -0
  181. package/data/probe/npm/examples/probe-agent-cli.js +113 -0
  182. package/data/probe/npm/examples/test-agent-edit.js +114 -0
  183. package/data/probe/npm/examples/test-edit-create.js +120 -0
  184. package/data/probe/npm/examples/test-edit-direct.js +114 -0
  185. package/data/probe/npm/index.d.ts +744 -0
  186. package/data/probe/npm/jest.config.js +52 -0
  187. package/data/probe/npm/package.json +117 -0
  188. package/data/probe/npm/scripts/build-agent.cjs +75 -0
  189. package/data/probe/npm/scripts/build-cjs.js +124 -0
  190. package/data/probe/npm/scripts/build-mcp.cjs +36 -0
  191. package/data/probe/npm/scripts/postinstall.js +216 -0
  192. package/data/probe/npm/test-codex-e2e.js +78 -0
  193. package/data/probe/npm/test-download-lock.js +109 -0
  194. package/data/probe/npm/test-grep-security.js +94 -0
  195. package/data/probe/npm/test-grep-simplified.js +63 -0
  196. package/data/probe/npm/test-grep.js +51 -0
  197. package/data/probe/npm/tests/README.md +96 -0
  198. package/data/probe/npm/tests/agent-compact-history.test.js +174 -0
  199. package/data/probe/npm/tests/allow-tests-default.test.js +151 -0
  200. package/data/probe/npm/tests/contextCompactor.test.js +498 -0
  201. package/data/probe/npm/tests/delegate-config.test.js +353 -0
  202. package/data/probe/npm/tests/delegate-integration.test.js +348 -0
  203. package/data/probe/npm/tests/extractor-integration.test.js +162 -0
  204. package/data/probe/npm/tests/extractor.test.js +317 -0
  205. package/data/probe/npm/tests/fixtures/sampleDiagrams.js +267 -0
  206. package/data/probe/npm/tests/integration/claude-code-auto-fallback.spec.js +148 -0
  207. package/data/probe/npm/tests/integration/claude-code-multi-step.spec.js +127 -0
  208. package/data/probe/npm/tests/integration/claude-code-tool-events.spec.js +163 -0
  209. package/data/probe/npm/tests/integration/codex-auto-fallback.spec.js +191 -0
  210. package/data/probe/npm/tests/integration/codex-tool-events.spec.js +147 -0
  211. package/data/probe/npm/tests/integration/examplesChatMcp.test.js +402 -0
  212. package/data/probe/npm/tests/integration/mcpDotenvSupport.test.js +174 -0
  213. package/data/probe/npm/tests/integration/mcpErrorHandling.test.js +566 -0
  214. package/data/probe/npm/tests/integration/mcpRobustness.test.js +564 -0
  215. package/data/probe/npm/tests/integration/mcpStdoutPurity.test.js +355 -0
  216. package/data/probe/npm/tests/integration/probeAgentMcp.test.js +398 -0
  217. package/data/probe/npm/tests/integration/retryFallback.test.js +368 -0
  218. package/data/probe/npm/tests/integration/schema-in-initial-message.test.js +318 -0
  219. package/data/probe/npm/tests/integration/schema-validation-loop-prevention.test.js +244 -0
  220. package/data/probe/npm/tests/integration/schemaRetryLogic.test.js +94 -0
  221. package/data/probe/npm/tests/integration/validationFlow.test.js +329 -0
  222. package/data/probe/npm/tests/manual/test-codex-basic.js +110 -0
  223. package/data/probe/npm/tests/mcp/mcpClientManager.test.js +614 -0
  224. package/data/probe/npm/tests/mcp/mcpConfig.test.js +359 -0
  225. package/data/probe/npm/tests/mcp/mcpXmlBridge.test.js +436 -0
  226. package/data/probe/npm/tests/mcp/mockMcpServer.js +510 -0
  227. package/data/probe/npm/tests/mcp-strict-syntax.test.js +319 -0
  228. package/data/probe/npm/tests/mermaidQuoteEscaping.test.js +214 -0
  229. package/data/probe/npm/tests/nestedQuoteFix.test.js +40 -0
  230. package/data/probe/npm/tests/setup.js +46 -0
  231. package/data/probe/npm/tests/unit/allowed-tools.test.js +513 -0
  232. package/data/probe/npm/tests/unit/attempt-completion-closing-tag-in-content.test.js +188 -0
  233. package/data/probe/npm/tests/unit/attemptCompletionJsonFix.test.js +238 -0
  234. package/data/probe/npm/tests/unit/attemptCompletionJsonIssue.test.js +128 -0
  235. package/data/probe/npm/tests/unit/backtickAutoFix.test.js +35 -0
  236. package/data/probe/npm/tests/unit/bash-probe-agent-integration.test.js +389 -0
  237. package/data/probe/npm/tests/unit/bash-simple-commands.test.js +324 -0
  238. package/data/probe/npm/tests/unit/bash-tool-comprehensive.test.js +371 -0
  239. package/data/probe/npm/tests/unit/bash-tool-integration.test.js +310 -0
  240. package/data/probe/npm/tests/unit/bash-tool.test.js +341 -0
  241. package/data/probe/npm/tests/unit/completion-prompt.test.js +379 -0
  242. package/data/probe/npm/tests/unit/cwd-path-options.test.js +287 -0
  243. package/data/probe/npm/tests/unit/delegate-limits.test.js +422 -0
  244. package/data/probe/npm/tests/unit/direct-content-attempt-completion.test.js +235 -0
  245. package/data/probe/npm/tests/unit/edit-create-tools.test.js +609 -0
  246. package/data/probe/npm/tests/unit/enhancedMermaidValidation.test.js +577 -0
  247. package/data/probe/npm/tests/unit/extract-content.test.js +83 -0
  248. package/data/probe/npm/tests/unit/extract-multiple-targets.test.js +89 -0
  249. package/data/probe/npm/tests/unit/fallbackManager.test.js +442 -0
  250. package/data/probe/npm/tests/unit/githubCompatibilityValidation.test.js +258 -0
  251. package/data/probe/npm/tests/unit/imageConfig.test.js +149 -0
  252. package/data/probe/npm/tests/unit/imagePathResolution.test.js +345 -0
  253. package/data/probe/npm/tests/unit/json-fixing-agent.test.js +238 -0
  254. package/data/probe/npm/tests/unit/json-validation-enhanced-errors.test.js +199 -0
  255. package/data/probe/npm/tests/unit/jsonValidationInfiniteLoopFix.test.js +228 -0
  256. package/data/probe/npm/tests/unit/maidIntegration.test.js +139 -0
  257. package/data/probe/npm/tests/unit/maxIterationsWarning.test.js +195 -0
  258. package/data/probe/npm/tests/unit/mermaidEdgeLabelFix.test.js +161 -0
  259. package/data/probe/npm/tests/unit/mermaidHtmlEntities.test.js +76 -0
  260. package/data/probe/npm/tests/unit/mermaidInfiniteLoopFix.test.js +64 -0
  261. package/data/probe/npm/tests/unit/mermaidValidation.test.js +723 -0
  262. package/data/probe/npm/tests/unit/mermaidValidationVisorExample.test.js +309 -0
  263. package/data/probe/npm/tests/unit/probe-agent-clone-realistic.test.js +643 -0
  264. package/data/probe/npm/tests/unit/probe-agent-clone.test.js +476 -0
  265. package/data/probe/npm/tests/unit/probe-agent-delegate.test.js +400 -0
  266. package/data/probe/npm/tests/unit/probe-agent-model-option.test.js +118 -0
  267. package/data/probe/npm/tests/unit/probeTool-security.test.js +283 -0
  268. package/data/probe/npm/tests/unit/readImageTool.test.js +418 -0
  269. package/data/probe/npm/tests/unit/retryManager.test.js +317 -0
  270. package/data/probe/npm/tests/unit/schema-aware-reminders.test.js +288 -0
  271. package/data/probe/npm/tests/unit/schemaDefinitionDetection.test.js +115 -0
  272. package/data/probe/npm/tests/unit/schemaUtils.test.js +1268 -0
  273. package/data/probe/npm/tests/unit/simpleTelemetry.test.js +282 -0
  274. package/data/probe/npm/tests/unit/simplified-attempt-completion.test.js +274 -0
  275. package/data/probe/npm/tests/unit/single-quote-json-bug.test.js +231 -0
  276. package/data/probe/npm/tests/unit/subgraphAutoFix.test.js +110 -0
  277. package/data/probe/npm/tests/unit/system-prompt.test.js +32 -0
  278. package/data/probe/npm/tests/unit/types-probe-agent-options.test.js +42 -0
  279. package/data/probe/npm/tests/unit/xmlParsing.test.js +720 -0
  280. package/data/probe/npm/tsconfig.json +21 -0
  281. package/data/probe/result1.txt +19 -0
  282. package/data/probe/result2.txt +26 -0
  283. package/data/probe/scripts/benchmark.sh +270 -0
  284. package/data/probe/scripts/cache_memory_analysis.rs +844 -0
  285. package/data/probe/scripts/claude-hook-wrapper.sh +56 -0
  286. package/data/probe/site/.env.example +10 -0
  287. package/data/probe/site/DEPLOYMENT.md +86 -0
  288. package/data/probe/site/README.md +183 -0
  289. package/data/probe/site/adding-languages.md +135 -0
  290. package/data/probe/site/ai-chat.md +427 -0
  291. package/data/probe/site/ai-integration.md +1488 -0
  292. package/data/probe/site/blog/agentic-flow-custom-xml-protocol.md +407 -0
  293. package/data/probe/site/blog/index.md +118 -0
  294. package/data/probe/site/blog/v0.6.0-release.md +426 -0
  295. package/data/probe/site/blog.md +8 -0
  296. package/data/probe/site/changelog.md +200 -0
  297. package/data/probe/site/cli-mode.md +437 -0
  298. package/data/probe/site/code-extraction.md +436 -0
  299. package/data/probe/site/contributing/README.md +9 -0
  300. package/data/probe/site/contributing/documentation-cross-references.md +215 -0
  301. package/data/probe/site/contributing/documentation-maintenance.md +275 -0
  302. package/data/probe/site/contributing/documentation-structure.md +75 -0
  303. package/data/probe/site/documentation-cross-references.md +215 -0
  304. package/data/probe/site/documentation-guide.md +132 -0
  305. package/data/probe/site/documentation-maintenance.md +275 -0
  306. package/data/probe/site/features.md +147 -0
  307. package/data/probe/site/how-it-works.md +118 -0
  308. package/data/probe/site/index.md +175 -0
  309. package/data/probe/site/index.md.bak +133 -0
  310. package/data/probe/site/installation.md +235 -0
  311. package/data/probe/site/integrations/docker.md +248 -0
  312. package/data/probe/site/integrations/github-actions.md +413 -0
  313. package/data/probe/site/language-support-overview.md +168 -0
  314. package/data/probe/site/mcp-integration.md +587 -0
  315. package/data/probe/site/mcp-server.md +304 -0
  316. package/data/probe/site/navigation-structure.md +76 -0
  317. package/data/probe/site/nodejs-sdk.md +798 -0
  318. package/data/probe/site/output-formats.md +625 -0
  319. package/data/probe/site/package.json +21 -0
  320. package/data/probe/site/public/_headers +28 -0
  321. package/data/probe/site/public/_redirects +11 -0
  322. package/data/probe/site/quick-start.md +289 -0
  323. package/data/probe/site/search-functionality.md +291 -0
  324. package/data/probe/site/search-reference.md +291 -0
  325. package/data/probe/site/supported-languages.md +215 -0
  326. package/data/probe/site/use-cases/README.md +8 -0
  327. package/data/probe/site/use-cases/advanced-cli.md +253 -0
  328. package/data/probe/site/use-cases/ai-code-editors.md +239 -0
  329. package/data/probe/site/use-cases/building-ai-tools.md +529 -0
  330. package/data/probe/site/use-cases/cli-ai-workflows.md +285 -0
  331. package/data/probe/site/use-cases/deploying-probe-web-interface.md +255 -0
  332. package/data/probe/site/use-cases/integrating-probe-into-ai-code-editors.md +161 -0
  333. package/data/probe/site/use-cases/nodejs-sdk.md +596 -0
  334. package/data/probe/site/use-cases/team-chat.md +350 -0
  335. package/data/probe/site/web-interface.md +434 -0
  336. package/data/probe/site/wrangler.toml +9 -0
  337. package/data/probe/test-api-key.sh +1 -0
  338. package/data/probe/test-probe-implementation/hello.js +7 -0
  339. package/data/probe/test_cases/demonstrate_early_termination_issues.sh +176 -0
  340. package/data/probe/test_cases/early_termination_issues.rs +533 -0
  341. package/data/probe/test_data/test_nested_struct.go +26 -0
  342. package/data/probe/tests/README.md +286 -0
  343. package/data/probe/tests/README_search_determinism_tests.md +116 -0
  344. package/data/probe/tests/adjacent_comment_test.rs +152 -0
  345. package/data/probe/tests/apostrophe_handling_tests.rs +132 -0
  346. package/data/probe/tests/block_filtering_with_ast_tests.rs +669 -0
  347. package/data/probe/tests/block_merging_tests.rs +396 -0
  348. package/data/probe/tests/c_outline_format_tests.rs +2179 -0
  349. package/data/probe/tests/cache_invalidation_issues.rs.disabled +682 -0
  350. package/data/probe/tests/cache_order_tests.rs +147 -0
  351. package/data/probe/tests/cache_query_scoping_tests.rs +221 -0
  352. package/data/probe/tests/cli_tests.rs +680 -0
  353. package/data/probe/tests/comment_context_integration_test.rs +240 -0
  354. package/data/probe/tests/common.rs +33 -0
  355. package/data/probe/tests/complex_block_merging_tests.rs +599 -0
  356. package/data/probe/tests/complex_query_block_filtering_tests.rs +422 -0
  357. package/data/probe/tests/control_flow_closing_braces_test.rs +91 -0
  358. package/data/probe/tests/cpp_outline_format_tests.rs +1507 -0
  359. package/data/probe/tests/csharp_outline_format_tests.rs +941 -0
  360. package/data/probe/tests/elastic_query_integration_tests.rs +922 -0
  361. package/data/probe/tests/extract_command_tests.rs +1848 -0
  362. package/data/probe/tests/extract_deduplication_tests.rs +146 -0
  363. package/data/probe/tests/extract_input_file_tests.rs +84 -0
  364. package/data/probe/tests/extract_prompt_tests.rs +102 -0
  365. package/data/probe/tests/filename_search_tests.rs +96 -0
  366. package/data/probe/tests/fixtures/user/AssemblyInfo.cs +3 -0
  367. package/data/probe/tests/github_extract_tests.rs +234 -0
  368. package/data/probe/tests/go_comment_test.rs +253 -0
  369. package/data/probe/tests/go_outline_format_tests.rs +2587 -0
  370. package/data/probe/tests/go_path_resolver_tests.rs +96 -0
  371. package/data/probe/tests/html_outline_format_tests.rs +637 -0
  372. package/data/probe/tests/integration_tests.rs +837 -0
  373. package/data/probe/tests/ip_whitelist_test.rs +148 -0
  374. package/data/probe/tests/java_outline_format_tests.rs +1611 -0
  375. package/data/probe/tests/javascript_extract_tests.rs +315 -0
  376. package/data/probe/tests/javascript_outline_format_tests.rs +1464 -0
  377. package/data/probe/tests/json_format_tests.rs +436 -0
  378. package/data/probe/tests/json_schema_validation_tests.rs +450 -0
  379. package/data/probe/tests/lib_usage.rs +60 -0
  380. package/data/probe/tests/line_comment_context_extension_test.rs +459 -0
  381. package/data/probe/tests/line_map_cache_tests.rs +114 -0
  382. package/data/probe/tests/markdown_integration_tests.rs +190 -0
  383. package/data/probe/tests/mocks/test_ip_whitelist.go +11 -0
  384. package/data/probe/tests/mocks/test_object.js +27 -0
  385. package/data/probe/tests/mocks/test_struct.go +50 -0
  386. package/data/probe/tests/multi_keyword_pattern_tests.rs +464 -0
  387. package/data/probe/tests/multi_language_syntax_integration_tests.rs +218 -0
  388. package/data/probe/tests/multiple_capture_groups_tests.rs +169 -0
  389. package/data/probe/tests/negative_compound_word_tests.rs +246 -0
  390. package/data/probe/tests/nested_symbol_extraction_tests.rs +99 -0
  391. package/data/probe/tests/outline_cross_file_interference_test.rs +335 -0
  392. package/data/probe/tests/outline_keyword_preservation_test.rs +67 -0
  393. package/data/probe/tests/output_format_edge_cases_tests.rs +693 -0
  394. package/data/probe/tests/parallel_extraction_tests.rs +178 -0
  395. package/data/probe/tests/parallel_search_tests.rs +355 -0
  396. package/data/probe/tests/path_resolver_tests.rs +698 -0
  397. package/data/probe/tests/php_outline_format_extended_tests.rs +928 -0
  398. package/data/probe/tests/php_outline_format_tests.rs +768 -0
  399. package/data/probe/tests/property_tests.proptest-regressions +9 -0
  400. package/data/probe/tests/property_tests.rs +118 -0
  401. package/data/probe/tests/python_outline_format_tests.rs +1538 -0
  402. package/data/probe/tests/query_command_json_tests.rs +438 -0
  403. package/data/probe/tests/query_command_tests.rs +232 -0
  404. package/data/probe/tests/query_command_xml_tests.rs +569 -0
  405. package/data/probe/tests/quoted_term_with_negative_keyword_tests.rs +216 -0
  406. package/data/probe/tests/required_terms_filename_tests.rs +116 -0
  407. package/data/probe/tests/ruby_outline_format_tests.rs +1011 -0
  408. package/data/probe/tests/rust_line_comment_context_test.rs +151 -0
  409. package/data/probe/tests/rust_outline_format_enhanced_tests.rs +725 -0
  410. package/data/probe/tests/rust_outline_format_tests.rs +843 -0
  411. package/data/probe/tests/schemas/xml_output_schema.xsd +38 -0
  412. package/data/probe/tests/search_determinism_tests.rs +451 -0
  413. package/data/probe/tests/search_hints_tests.rs +253 -0
  414. package/data/probe/tests/special_character_escaping_tests.rs +417 -0
  415. package/data/probe/tests/stemming_compound_word_filtering_tests.rs +535 -0
  416. package/data/probe/tests/strict_elastic_syntax_tests.rs +404 -0
  417. package/data/probe/tests/swift_outline_format_tests.rs +3319 -0
  418. package/data/probe/tests/symbols_tests.rs +166 -0
  419. package/data/probe/tests/test_file.rs +45 -0
  420. package/data/probe/tests/test_tokenize.rs +28 -0
  421. package/data/probe/tests/timeout_tests.rs +82 -0
  422. package/data/probe/tests/tokenization_tests.rs +195 -0
  423. package/data/probe/tests/tokenized_block_filtering_tests.rs +174 -0
  424. package/data/probe/tests/typescript_extract_tests.rs +214 -0
  425. package/data/probe/tests/typescript_outline_format_tests.rs +2188 -0
  426. package/data/probe/tests/xml_format_tests.rs +568 -0
  427. package/data/probe/tests/xml_schema_validation_tests.rs +497 -0
  428. package/data/scripts/postinstall.mjs +9 -0
  429. package/data/scripts/set-version.js +0 -0
  430. package/data/scripts/wiki-build.sh +111 -0
  431. package/data/scripts/wiki-deploy.sh +73 -0
  432. package/data/serve.json +12 -0
  433. package/data/test/demo-dynamic.html +134 -0
  434. package/data/test/demo-esm.html +105 -0
  435. package/data/test/demo-iife.html +78 -0
  436. package/data/tsconfig.json +7 -0
  437. package/data/vite.server.ts +483 -0
  438. package/data/vitest.config.ts +40 -0
  439. package/data/wiki/Home.md +58 -0
  440. package/data/wiki/_Sidebar.md +39 -0
  441. package/docs-mcp.config.json +20 -0
  442. package/package.json +56 -0
  443. package/src/config.js +111 -0
  444. package/src/index.js +395 -0
@@ -0,0 +1,3319 @@
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_swift_outline_basic_symbols() -> Result<()> {
10
+ let temp_dir = TempDir::new()?;
11
+ let test_file = temp_dir.path().join("Calculator.swift");
12
+
13
+ let content = r#"import Foundation
14
+
15
+ // Protocol for calculator operations
16
+ protocol CalculatorProtocol {
17
+ func add(_ x: Double, _ y: Double) -> Double
18
+ func subtract(_ x: Double, _ y: Double) -> Double
19
+ func multiply(_ x: Double, _ y: Double) -> Double
20
+ func divide(_ x: Double, _ y: Double) throws -> Double
21
+ var history: [Double] { get }
22
+ }
23
+
24
+ // Custom errors
25
+ enum CalculatorError: Error {
26
+ case divisionByZero
27
+ case invalidInput(String)
28
+ case operationFailed(String)
29
+ }
30
+
31
+ extension CalculatorError: LocalizedError {
32
+ var errorDescription: String? {
33
+ switch self {
34
+ case .divisionByZero:
35
+ return "Division by zero is not allowed"
36
+ case .invalidInput(let input):
37
+ return "Invalid input: \(input)"
38
+ case .operationFailed(let operation):
39
+ return "Operation failed: \(operation)"
40
+ }
41
+ }
42
+ }
43
+
44
+ // Base calculator class
45
+ class BaseCalculator: CalculatorProtocol {
46
+ private(set) var name: String
47
+ private(set) var history: [Double] = []
48
+ private let precision: Double
49
+
50
+ init(name: String, precision: Double = 0.001) {
51
+ self.name = name
52
+ self.precision = precision
53
+ }
54
+
55
+ func add(_ x: Double, _ y: Double) -> Double {
56
+ let result = x + y
57
+ recordOperation(result)
58
+ return result
59
+ }
60
+
61
+ func subtract(_ x: Double, _ y: Double) -> Double {
62
+ let result = x - y
63
+ recordOperation(result)
64
+ return result
65
+ }
66
+
67
+ func multiply(_ x: Double, _ y: Double) -> Double {
68
+ let result = x * y
69
+ recordOperation(result)
70
+ return result
71
+ }
72
+
73
+ func divide(_ x: Double, _ y: Double) throws -> Double {
74
+ guard abs(y) > precision else {
75
+ throw CalculatorError.divisionByZero
76
+ }
77
+
78
+ let result = x / y
79
+ recordOperation(result)
80
+ return result
81
+ }
82
+
83
+ func clearHistory() {
84
+ history.removeAll()
85
+ }
86
+
87
+ private func recordOperation(_ result: Double) {
88
+ history.append(result)
89
+ }
90
+ }
91
+
92
+ // Advanced calculator with generics and modern Swift features
93
+ class AdvancedCalculator: BaseCalculator {
94
+ typealias NumberProcessor<T> = (T) -> T where T: Numeric
95
+
96
+ private var constants: [String: Double] = [
97
+ "pi": Double.pi,
98
+ "e": M_E,
99
+ "goldenRatio": (1 + sqrt(5)) / 2
100
+ ]
101
+
102
+ private var operationsCount: Int = 0
103
+
104
+ override init(name: String, precision: Double = 0.001) {
105
+ super.init(name: name, precision: precision)
106
+ }
107
+
108
+ // Convenience initializer
109
+ convenience init(name: String) {
110
+ self.init(name: name, precision: 0.001)
111
+ }
112
+
113
+ // Override operations to add counting
114
+ override func add(_ x: Double, _ y: Double) -> Double {
115
+ operationsCount += 1
116
+ return super.add(x, y)
117
+ }
118
+
119
+ override func subtract(_ x: Double, _ y: Double) -> Double {
120
+ operationsCount += 1
121
+ return super.subtract(x, y)
122
+ }
123
+
124
+ override func multiply(_ x: Double, _ y: Double) -> Double {
125
+ operationsCount += 1
126
+ return super.multiply(x, y)
127
+ }
128
+
129
+ override func divide(_ x: Double, _ y: Double) throws -> Double {
130
+ operationsCount += 1
131
+ return try super.divide(x, y)
132
+ }
133
+
134
+ // Generic method with constraints
135
+ func processNumbers<T: Numeric>(_ numbers: [T], with processor: NumberProcessor<T>) -> [T] {
136
+ return numbers.map(processor)
137
+ }
138
+
139
+ // Method with closure parameter
140
+ func transformHistory(_ transformer: @escaping (Double) -> Double) -> [Double] {
141
+ return history.map(transformer)
142
+ }
143
+
144
+ // Computed properties
145
+ var averageResult: Double {
146
+ guard !history.isEmpty else { return 0 }
147
+ return history.reduce(0, +) / Double(history.count)
148
+ }
149
+
150
+ var operationsPerformed: Int {
151
+ return operationsCount
152
+ }
153
+
154
+ // Static factory method
155
+ static func createDefault(name: String) -> AdvancedCalculator {
156
+ return AdvancedCalculator(name: name)
157
+ }
158
+
159
+ // Subscript for accessing constants
160
+ subscript(constant: String) -> Double? {
161
+ get { return constants[constant] }
162
+ set { constants[constant] = newValue }
163
+ }
164
+
165
+ // Nested enum for operation types
166
+ enum OperationType: String, CaseIterable {
167
+ case addition = "add"
168
+ case subtraction = "subtract"
169
+ case multiplication = "multiply"
170
+ case division = "divide"
171
+
172
+ var description: String {
173
+ switch self {
174
+ case .addition: return "Addition"
175
+ case .subtraction: return "Subtraction"
176
+ case .multiplication: return "Multiplication"
177
+ case .division: return "Division"
178
+ }
179
+ }
180
+ }
181
+
182
+ // Nested struct for operation results
183
+ struct OperationResult {
184
+ let value: Double
185
+ let operation: OperationType
186
+ let timestamp: Date
187
+
188
+ init(value: Double, operation: OperationType) {
189
+ self.value = value
190
+ self.operation = operation
191
+ self.timestamp = Date()
192
+ }
193
+ }
194
+ }
195
+
196
+ // Scientific calculator with advanced mathematical functions
197
+ final class ScientificCalculator: AdvancedCalculator {
198
+
199
+ func sin(_ x: Double) -> Double {
200
+ let result = Foundation.sin(x)
201
+ recordOperation(result)
202
+ return result
203
+ }
204
+
205
+ func cos(_ x: Double) -> Double {
206
+ let result = Foundation.cos(x)
207
+ recordOperation(result)
208
+ return result
209
+ }
210
+
211
+ func tan(_ x: Double) -> Double {
212
+ let result = Foundation.tan(x)
213
+ recordOperation(result)
214
+ return result
215
+ }
216
+
217
+ func log(_ x: Double, base: Double = M_E) throws -> Double {
218
+ guard x > 0 else {
219
+ throw CalculatorError.invalidInput("Cannot take log of zero or negative number")
220
+ }
221
+
222
+ let result = Foundation.log(x) / Foundation.log(base)
223
+ recordOperation(result)
224
+ return result
225
+ }
226
+
227
+ func power(_ base: Double, _ exponent: Double) -> Double {
228
+ let result = pow(base, exponent)
229
+ recordOperation(result)
230
+ return result
231
+ }
232
+
233
+ func factorial(_ n: Int) throws -> Double {
234
+ guard n >= 0 else {
235
+ throw CalculatorError.invalidInput("Factorial of negative number")
236
+ }
237
+
238
+ let result = (1...max(1, n)).reduce(1) { $0 * $1 }
239
+ let doubleResult = Double(result)
240
+ recordOperation(doubleResult)
241
+ return doubleResult
242
+ }
243
+
244
+ // Computed property for statistics
245
+ var statistics: (mean: Double, median: Double, standardDeviation: Double) {
246
+ guard !history.isEmpty else {
247
+ return (0, 0, 0)
248
+ }
249
+
250
+ let mean = history.reduce(0, +) / Double(history.count)
251
+
252
+ let sortedHistory = history.sorted()
253
+ let median: Double
254
+ let count = sortedHistory.count
255
+
256
+ if count % 2 == 0 {
257
+ median = (sortedHistory[count / 2 - 1] + sortedHistory[count / 2]) / 2
258
+ } else {
259
+ median = sortedHistory[count / 2]
260
+ }
261
+
262
+ let variance = history.map { pow($0 - mean, 2) }.reduce(0, +) / Double(history.count)
263
+ let standardDeviation = sqrt(variance)
264
+
265
+ return (mean, median, standardDeviation)
266
+ }
267
+
268
+ private func recordOperation(_ result: Double) {
269
+ // Call parent's private method through a workaround
270
+ let _ = add(0, result) - result
271
+ }
272
+ }
273
+
274
+ // Extension for CustomStringConvertible
275
+ extension BaseCalculator: CustomStringConvertible {
276
+ var description: String {
277
+ return "Calculator '\(name)' with \(history.count) operations"
278
+ }
279
+ }
280
+
281
+ // Extension with default implementations
282
+ extension CalculatorProtocol {
283
+ var historyCount: Int {
284
+ return history.count
285
+ }
286
+
287
+ func lastResult() -> Double? {
288
+ return history.last
289
+ }
290
+ }
291
+
292
+ // Struct for calculator configuration
293
+ struct CalculatorConfiguration {
294
+ let name: String
295
+ let precision: Double
296
+ let enableHistory: Bool
297
+
298
+ static let `default` = CalculatorConfiguration(
299
+ name: "Default Calculator",
300
+ precision: 0.001,
301
+ enableHistory: true
302
+ )
303
+
304
+ // Factory method
305
+ static func scientific(name: String) -> CalculatorConfiguration {
306
+ return CalculatorConfiguration(
307
+ name: name,
308
+ precision: 0.0001,
309
+ enableHistory: true
310
+ )
311
+ }
312
+ }
313
+
314
+ // Utility functions
315
+ func createCalculator(with config: CalculatorConfiguration) -> BaseCalculator {
316
+ return BaseCalculator(name: config.name, precision: config.precision)
317
+ }
318
+
319
+ func performCalculations() {
320
+ let calc = ScientificCalculator.createDefault(name: "Demo Calculator")
321
+
322
+ do {
323
+ print("Calculator: \(calc.name)")
324
+
325
+ // Basic operations
326
+ let sum = calc.add(10, 5)
327
+ let product = calc.multiply(20, 3)
328
+ let quotient = try calc.divide(100, 4)
329
+
330
+ print("10 + 5 = \(sum)")
331
+ print("20 * 3 = \(product)")
332
+ print("100 / 4 = \(quotient)")
333
+
334
+ // Scientific operations
335
+ let sineResult = calc.sin(Double.pi / 2)
336
+ let factorialResult = try calc.factorial(5)
337
+
338
+ print("sin(π/2) = \(sineResult)")
339
+ print("5! = \(factorialResult)")
340
+
341
+ // Statistics
342
+ let stats = calc.statistics
343
+ print("Mean: \(stats.mean)")
344
+ print("Median: \(stats.median)")
345
+ print("Standard Deviation: \(stats.standardDeviation)")
346
+
347
+ // History
348
+ print("History: \(calc.history)")
349
+ print("Operations count: \(calc.operationsPerformed)")
350
+
351
+ } catch {
352
+ print("Error: \(error.localizedDescription)")
353
+ }
354
+ }
355
+
356
+ // Test functions
357
+ func testBasicCalculator() throws {
358
+ let calc = AdvancedCalculator(name: "Test Calculator")
359
+
360
+ let result1 = calc.add(2, 3)
361
+ guard result1 == 5 else {
362
+ throw CalculatorError.operationFailed("Add test failed")
363
+ }
364
+
365
+ let result2 = calc.multiply(4, 5)
366
+ guard result2 == 20 else {
367
+ throw CalculatorError.operationFailed("Multiply test failed")
368
+ }
369
+
370
+ print("Basic calculator tests passed")
371
+ }
372
+
373
+ func testScientificCalculator() throws {
374
+ let calc = ScientificCalculator(name: "Scientific Test")
375
+
376
+ let result1 = calc.power(2, 3)
377
+ guard result1 == 8 else {
378
+ throw CalculatorError.operationFailed("Power test failed")
379
+ }
380
+
381
+ let result2 = try calc.factorial(4)
382
+ guard result2 == 24 else {
383
+ throw CalculatorError.operationFailed("Factorial test failed")
384
+ }
385
+
386
+ print("Scientific calculator tests passed")
387
+ }
388
+
389
+ // Main execution
390
+ if CommandLine.arguments.contains("--demo") {
391
+ performCalculations()
392
+
393
+ do {
394
+ try testBasicCalculator()
395
+ try testScientificCalculator()
396
+ } catch {
397
+ print("Test failed: \(error)")
398
+ }
399
+ }
400
+ "#;
401
+
402
+ fs::write(&test_file, content)?;
403
+
404
+ let ctx = TestContext::new();
405
+ let output = ctx.run_probe(&[
406
+ "extract",
407
+ test_file.to_str().unwrap(),
408
+ "--format",
409
+ "outline",
410
+ "--allow-tests",
411
+ ])?;
412
+
413
+ // Verify Swift symbols are extracted
414
+ assert!(
415
+ output.contains("protocol CalculatorProtocol"),
416
+ "Missing CalculatorProtocol - output: {}",
417
+ output
418
+ );
419
+ assert!(
420
+ output.contains("enum CalculatorError") || output.contains("CalculatorError"),
421
+ "Missing CalculatorError enum - output: {}",
422
+ output
423
+ );
424
+ assert!(
425
+ output.contains("class BaseCalculator") || output.contains("BaseCalculator"),
426
+ "Missing BaseCalculator class - output: {}",
427
+ output
428
+ );
429
+ assert!(
430
+ output.contains("class AdvancedCalculator") || output.contains("AdvancedCalculator"),
431
+ "Missing AdvancedCalculator class - output: {}",
432
+ output
433
+ );
434
+ assert!(
435
+ output.contains("final class ScientificCalculator")
436
+ || output.contains("ScientificCalculator"),
437
+ "Missing ScientificCalculator class - output: {}",
438
+ output
439
+ );
440
+ assert!(
441
+ output.contains("func test") || output.contains("testBasicCalculator"),
442
+ "Missing test functions - output: {}",
443
+ output
444
+ );
445
+
446
+ Ok(())
447
+ }
448
+
449
+ #[test]
450
+ fn test_swift_outline_smart_closing_brace_comments() -> Result<()> {
451
+ let temp_dir = TempDir::new()?;
452
+ let test_file = temp_dir.path().join("ClosingBraceTest.swift");
453
+
454
+ let content = r#"import Foundation
455
+
456
+ // Small function that should NOT get closing brace comments
457
+ func smallFunction(_ x: Int) -> Int {
458
+ let result = x * 2
459
+ return result + 1
460
+ }
461
+
462
+ // Large function that SHOULD get closing brace comments with Swift // syntax
463
+ func largeFunctionWithGaps(data: [Int]) -> [String] {
464
+ var results: [String] = []
465
+ let processor = DataProcessor()
466
+
467
+ // Phase 1: Initial processing with nested control flow
468
+ for (index, value) in data.enumerated() {
469
+ if value > 100 {
470
+ processor.processLargeValue(value, at: index)
471
+ } else if value < 0 {
472
+ processor.processNegativeValue(value, at: index)
473
+ } else {
474
+ processor.processSmallValue(value, at: index)
475
+ }
476
+ }
477
+
478
+ // Phase 2: Complex transformation logic
479
+ let transformedData = processor.getTransformedData()
480
+ for item in transformedData {
481
+ switch item.category {
482
+ case .high:
483
+ results.append("HIGH: \(item.value)")
484
+ case .medium:
485
+ results.append("MED: \(item.value)")
486
+ case .low:
487
+ results.append("LOW: \(item.value)")
488
+ }
489
+ }
490
+
491
+ // Phase 3: Final validation and cleanup
492
+ var validatedResults: [String] = []
493
+ for result in results {
494
+ guard result.count > 5 else { continue }
495
+ validatedResults.append(result)
496
+ }
497
+
498
+ return validatedResults
499
+ }
500
+
501
+ // Another large function to test closing brace behavior
502
+ class LargeProcessorClass {
503
+ private var accumulator: Accumulator
504
+
505
+ init() {
506
+ self.accumulator = Accumulator()
507
+ }
508
+
509
+ func processItems(_ items: [Item]) -> ProcessedResult {
510
+ // Main processing with deeply nested control flow
511
+ for item in items {
512
+ switch item.itemType {
513
+ case .primary:
514
+ if item.weight > 50.0 {
515
+ accumulator.addHeavyPrimary(item)
516
+ } else {
517
+ accumulator.addLightPrimary(item)
518
+ }
519
+ case .secondary:
520
+ accumulator.addSecondary(item)
521
+ case .auxiliary:
522
+ accumulator.addAuxiliary(item)
523
+ }
524
+ }
525
+
526
+ return accumulator.finalize()
527
+ }
528
+ }
529
+
530
+ // Large extension with multiple methods
531
+ extension String {
532
+ func complexStringProcessor() -> ProcessedString {
533
+ let processor = StringProcessor()
534
+
535
+ // Multi-stage string processing
536
+ let stage1 = processor.initialCleanup(self)
537
+ let stage2 = processor.tokenization(stage1)
538
+ let stage3 = processor.normalization(stage2)
539
+
540
+ guard !stage3.isEmpty else {
541
+ return ProcessedString.empty
542
+ }
543
+
544
+ // Final processing with validation
545
+ let finalResult = processor.finalization(stage3)
546
+ return ProcessedString(content: finalResult)
547
+ }
548
+ }
549
+ "#;
550
+
551
+ fs::write(&test_file, content)?;
552
+
553
+ let ctx = TestContext::new();
554
+ let output = ctx.run_probe(&[
555
+ "search",
556
+ "large", // Search for large functions/classes
557
+ test_file.to_str().unwrap(),
558
+ "--format",
559
+ "outline",
560
+ ])?;
561
+
562
+ // Should find the large functions and classes
563
+ assert!(
564
+ output.contains("largeFunctionWithGaps") || output.contains("LargeProcessorClass"),
565
+ "Missing large functions/classes - output: {}",
566
+ output
567
+ );
568
+
569
+ // Should have closing brace comments with Swift // syntax (not /* */)
570
+ let has_swift_closing_brace_comment = output.contains("} //");
571
+ assert!(
572
+ has_swift_closing_brace_comment,
573
+ "Large functions should have closing brace comments with Swift // syntax - output: {}",
574
+ output
575
+ );
576
+
577
+ // Should NOT have closing braces for small functions
578
+ let small_func_lines: Vec<&str> = output
579
+ .lines()
580
+ .filter(|line| line.contains("smallFunction"))
581
+ .collect();
582
+
583
+ if !small_func_lines.is_empty() {
584
+ // If smallFunction appears in output, verify it doesn't have closing brace comments
585
+ let has_small_func_closing_comment = output.lines().any(|line| {
586
+ line.contains("smallFunction") && (line.contains("} //") || line.contains("} /*"))
587
+ });
588
+ assert!(
589
+ !has_small_func_closing_comment,
590
+ "Small functions should NOT have closing brace comments - output: {}",
591
+ output
592
+ );
593
+ }
594
+
595
+ // Should be in outline format
596
+ assert!(
597
+ output.contains("---\nFile:"),
598
+ "Missing file delimiter in outline format - output: {}",
599
+ output
600
+ );
601
+
602
+ Ok(())
603
+ }
604
+
605
+ #[test]
606
+ fn test_swift_outline_keyword_highlighting() -> Result<()> {
607
+ let temp_dir = TempDir::new()?;
608
+ let test_file = temp_dir.path().join("KeywordTest.swift");
609
+
610
+ let content = r#"import Foundation
611
+ import SwiftUI
612
+
613
+ // Protocol with associated types and where clauses
614
+ protocol Processable {
615
+ associatedtype InputType
616
+ associatedtype OutputType where OutputType: Codable
617
+
618
+ func process(_ input: InputType) async throws -> OutputType
619
+ var isReady: Bool { get }
620
+ }
621
+
622
+ // Generic class with constraints
623
+ class DataProcessor<T: Hashable & Codable>: Processable {
624
+ typealias InputType = T
625
+ typealias OutputType = ProcessedData<T>
626
+
627
+ private let queue: DispatchQueue
628
+ private var cache: [T: OutputType] = [:]
629
+
630
+ var isReady: Bool {
631
+ return !cache.isEmpty
632
+ }
633
+
634
+ init(queue: DispatchQueue = .main) {
635
+ self.queue = queue
636
+ }
637
+
638
+ // Async function with error handling
639
+ func process(_ input: T) async throws -> OutputType {
640
+ if let cached = cache[input] {
641
+ return cached
642
+ }
643
+
644
+ do {
645
+ let result = try await performProcessing(input)
646
+ cache[input] = result
647
+ return result
648
+ } catch {
649
+ throw ProcessingError.failedToProcess(input, error)
650
+ }
651
+ }
652
+
653
+ // Private async helper with guard statements
654
+ private func performProcessing(_ input: T) async throws -> OutputType {
655
+ guard isReady else {
656
+ throw ProcessingError.notReady
657
+ }
658
+
659
+ return try await withCheckedThrowingContinuation { continuation in
660
+ queue.async {
661
+ do {
662
+ let processed = ProcessedData(value: input, timestamp: Date())
663
+ continuation.resume(returning: processed)
664
+ } catch {
665
+ continuation.resume(throwing: error)
666
+ }
667
+ }
668
+ }
669
+ }
670
+ }
671
+
672
+ // Enum with associated values and computed properties
673
+ enum ProcessingError: Error, LocalizedError {
674
+ case notReady
675
+ case failedToProcess(Any, Error)
676
+ case invalidInput(String)
677
+
678
+ var errorDescription: String? {
679
+ switch self {
680
+ case .notReady:
681
+ return "Processor is not ready"
682
+ case .failedToProcess(let input, let error):
683
+ return "Failed to process \(input): \(error.localizedDescription)"
684
+ case .invalidInput(let input):
685
+ return "Invalid input: \(input)"
686
+ }
687
+ }
688
+ }
689
+
690
+ // Struct with property wrappers and computed properties
691
+ struct ProcessedData<T: Codable>: Codable {
692
+ @Published var value: T
693
+ let timestamp: Date
694
+
695
+ var age: TimeInterval {
696
+ return Date().timeIntervalSince(timestamp)
697
+ }
698
+
699
+ init(value: T, timestamp: Date) {
700
+ self._value = Published(initialValue: value)
701
+ self.timestamp = timestamp
702
+ }
703
+ }
704
+
705
+ // Extension with conditional conformance
706
+ extension ProcessedData: Equatable where T: Equatable {
707
+ static func == (lhs: ProcessedData<T>, rhs: ProcessedData<T>) -> Bool {
708
+ return lhs.value == rhs.value && lhs.timestamp == rhs.timestamp
709
+ }
710
+ }
711
+
712
+ // SwiftUI View with ViewBuilder and State
713
+ struct ContentView: View {
714
+ @State private var isLoading: Bool = false
715
+ @StateObject private var processor = DataProcessor<String>()
716
+
717
+ var body: some View {
718
+ VStack {
719
+ if isLoading {
720
+ ProgressView("Processing...")
721
+ } else {
722
+ Button("Start Processing") {
723
+ Task {
724
+ await startProcessing()
725
+ }
726
+ }
727
+ }
728
+ }
729
+ .padding()
730
+ }
731
+
732
+ @MainActor
733
+ private func startProcessing() async {
734
+ isLoading = true
735
+ defer { isLoading = false }
736
+
737
+ do {
738
+ let result = try await processor.process("test data")
739
+ print("Processed: \(result)")
740
+ } catch {
741
+ print("Error: \(error)")
742
+ }
743
+ }
744
+ }
745
+
746
+ // Actor for concurrent processing
747
+ actor ConcurrentProcessor {
748
+ private var tasks: [Task<Void, Never>] = []
749
+
750
+ func addTask(_ operation: @escaping () async -> Void) {
751
+ let task = Task {
752
+ await operation()
753
+ }
754
+ tasks.append(task)
755
+ }
756
+
757
+ func waitForAll() async {
758
+ for task in tasks {
759
+ await task.value
760
+ }
761
+ tasks.removeAll()
762
+ }
763
+ }
764
+ "#;
765
+
766
+ fs::write(&test_file, content)?;
767
+
768
+ let ctx = TestContext::new();
769
+ let output = ctx.run_probe(&[
770
+ "search",
771
+ "async", // Search for async keyword
772
+ test_file.to_str().unwrap(),
773
+ "--format",
774
+ "outline",
775
+ ])?;
776
+
777
+ // Should highlight Swift keywords in the search results
778
+ // Look for async, await, throws, guard, defer, etc.
779
+ let swift_keywords = [
780
+ "async",
781
+ "await",
782
+ "throws",
783
+ "guard",
784
+ "defer",
785
+ "actor",
786
+ "@Published",
787
+ "@State",
788
+ "@MainActor",
789
+ ];
790
+ let found_keywords: Vec<&str> = swift_keywords
791
+ .iter()
792
+ .filter(|&keyword| output.contains(keyword))
793
+ .copied()
794
+ .collect();
795
+
796
+ assert!(
797
+ !found_keywords.is_empty(),
798
+ "Should find and highlight Swift keywords. Found: {:?} - output: {}",
799
+ found_keywords,
800
+ output
801
+ );
802
+
803
+ // Should contain the searched term
804
+ assert!(
805
+ output.contains("async"),
806
+ "Should contain the searched async keyword - output: {}",
807
+ output
808
+ );
809
+
810
+ // Should be in outline format
811
+ assert!(
812
+ output.contains("---\nFile:"),
813
+ "Missing file delimiter in outline format - output: {}",
814
+ output
815
+ );
816
+
817
+ Ok(())
818
+ }
819
+
820
+ #[test]
821
+ fn test_swift_outline_array_dictionary_truncation_with_keyword_preservation() -> Result<()> {
822
+ let temp_dir = TempDir::new()?;
823
+ let test_file = temp_dir.path().join("ArrayDictTest.swift");
824
+
825
+ let content = r#"import Foundation
826
+
827
+ struct ConfigurationManager {
828
+ // Large array that should be truncated but preserve keywords
829
+ let supportedLanguages = [
830
+ "swift",
831
+ "objective-c",
832
+ "javascript",
833
+ "typescript",
834
+ "python",
835
+ "java",
836
+ "kotlin",
837
+ "dart",
838
+ "go",
839
+ "rust",
840
+ "c",
841
+ "cpp",
842
+ "csharp",
843
+ "php",
844
+ "ruby",
845
+ "perl",
846
+ "scala",
847
+ "clojure",
848
+ "haskell",
849
+ "erlang",
850
+ "elixir",
851
+ "lua",
852
+ "shell",
853
+ "powershell",
854
+ "dockerfile",
855
+ "yaml",
856
+ "json",
857
+ "xml",
858
+ "html",
859
+ "css",
860
+ "sass",
861
+ "less"
862
+ ]
863
+
864
+ // Large dictionary with keyword-rich content
865
+ private var configurationSettings: [String: Any] = [
866
+ "database_host": "localhost",
867
+ "database_port": 5432,
868
+ "database_name": "production_db",
869
+ "api_key_primary": "sk-test-1234567890",
870
+ "api_key_secondary": "sk-backup-0987654321",
871
+ "cache_timeout": 3600,
872
+ "retry_attempts": 3,
873
+ "batch_size": 1000,
874
+ "worker_threads": 8,
875
+ "memory_limit": "2GB",
876
+ "disk_space_threshold": "10GB",
877
+ "network_timeout": 30,
878
+ "authentication_enabled": true,
879
+ "ssl_verification": true,
880
+ "logging_level": "info",
881
+ "debug_mode": false,
882
+ "performance_monitoring": true,
883
+ "error_tracking": true,
884
+ "metrics_collection": true,
885
+ "backup_enabled": true,
886
+ "backup_frequency": "daily",
887
+ "retention_days": 30,
888
+ "compression_enabled": true,
889
+ "encryption_key": "aes-256-gcm",
890
+ "session_timeout": 1800,
891
+ "max_connections": 100,
892
+ "connection_pool_size": 20,
893
+ "query_timeout": 60,
894
+ "transaction_timeout": 120
895
+ ]
896
+
897
+ func processLargeDataSet() -> [String] {
898
+ // Large inline array in function
899
+ let processingPipeline = [
900
+ "data_validation",
901
+ "schema_verification",
902
+ "data_cleaning",
903
+ "duplicate_removal",
904
+ "format_standardization",
905
+ "type_conversion",
906
+ "null_handling",
907
+ "validation_rules",
908
+ "business_logic",
909
+ "transformation_rules",
910
+ "aggregation_logic",
911
+ "sorting_criteria",
912
+ "filtering_conditions",
913
+ "output_formatting",
914
+ "result_validation"
915
+ ]
916
+
917
+ return processingPipeline.compactMap { step in
918
+ return "processed_\(step)"
919
+ }
920
+ }
921
+
922
+ // Function with dictionary containing Swift keywords
923
+ func getSwiftKeywords() -> [String: String] {
924
+ return [
925
+ "async": "Asynchronous function modifier",
926
+ "await": "Suspend execution until async call completes",
927
+ "actor": "Reference type for concurrent programming",
928
+ "guard": "Early exit statement with condition",
929
+ "defer": "Execute code when leaving current scope",
930
+ "throws": "Function can throw errors",
931
+ "rethrows": "Function rethrows callers errors",
932
+ "inout": "Parameter passed by reference",
933
+ "weak": "Weak reference to avoid retain cycles",
934
+ "unowned": "Unowned reference (unsafe)",
935
+ "lazy": "Property initialized on first access",
936
+ "mutating": "Method can modify struct properties",
937
+ "nonmutating": "Explicitly non-mutating method",
938
+ "override": "Override superclass method",
939
+ "final": "Prevent inheritance/overriding",
940
+ "required": "Required initializer",
941
+ "convenience": "Convenience initializer",
942
+ "subscript": "Custom subscript access"
943
+ ]
944
+ }
945
+ }
946
+ "#;
947
+
948
+ fs::write(&test_file, content)?;
949
+
950
+ let ctx = TestContext::new();
951
+ let output = ctx.run_probe(&[
952
+ "search",
953
+ "array", // Search for arrays/collections
954
+ test_file.to_str().unwrap(),
955
+ "--format",
956
+ "outline",
957
+ ])?;
958
+
959
+ // Should find the large arrays and dictionaries
960
+ assert!(
961
+ output.contains("supportedLanguages")
962
+ || output.contains("configurationSettings")
963
+ || output.contains("processLargeDataSet"),
964
+ "Missing large arrays/dictionaries - output: {}",
965
+ output
966
+ );
967
+
968
+ // Should have array/dictionary truncation markers
969
+ let has_truncation = output.contains("...")
970
+ || output.contains("/* truncated */")
971
+ || output.contains("// truncated");
972
+ assert!(
973
+ has_truncation,
974
+ "Large arrays/dictionaries should show truncation markers - output: {}",
975
+ output
976
+ );
977
+
978
+ // Should preserve important keywords even in truncated content
979
+ let important_keywords = [
980
+ "async", "await", "guard", "defer", "throws", "actor", "database", "api_key",
981
+ ];
982
+ let preserved_keywords: Vec<&str> = important_keywords
983
+ .iter()
984
+ .filter(|&keyword| output.contains(keyword))
985
+ .copied()
986
+ .collect();
987
+
988
+ assert!(
989
+ !preserved_keywords.is_empty(),
990
+ "Should preserve important keywords in truncated arrays/dicts. Found: {:?} - output: {}",
991
+ preserved_keywords,
992
+ output
993
+ );
994
+
995
+ // Should be in outline format
996
+ assert!(
997
+ output.contains("---\nFile:"),
998
+ "Missing file delimiter in outline format - output: {}",
999
+ output
1000
+ );
1001
+
1002
+ Ok(())
1003
+ }
1004
+
1005
+ #[test]
1006
+ fn test_swift_outline_specific_constructs() -> Result<()> {
1007
+ let temp_dir = TempDir::new()?;
1008
+ let test_file = temp_dir.path().join("SwiftConstructs.swift");
1009
+
1010
+ let content = r#"import Foundation
1011
+ import SwiftUI
1012
+
1013
+ // MARK: - Protocols with Associated Types and Generic Constraints
1014
+
1015
+ protocol DataTransformable {
1016
+ associatedtype InputType
1017
+ associatedtype OutputType: Codable
1018
+
1019
+ func transform(_ input: InputType) throws -> OutputType
1020
+ var transformationId: String { get }
1021
+ }
1022
+
1023
+ protocol Repository {
1024
+ associatedtype Entity: Identifiable
1025
+ associatedtype ID where ID == Entity.ID
1026
+
1027
+ func find(by id: ID) async throws -> Entity?
1028
+ func save(_ entity: Entity) async throws
1029
+ func delete(by id: ID) async throws
1030
+ }
1031
+
1032
+ // MARK: - Generic Classes with Inheritance and Constraints
1033
+
1034
+ class BaseDataProcessor<T: Hashable>: NSObject {
1035
+ private let processingQueue: DispatchQueue
1036
+ private var cache: [T: ProcessingResult] = [:]
1037
+
1038
+ override init() {
1039
+ self.processingQueue = DispatchQueue(label: "processing.queue", qos: .background)
1040
+ super.init()
1041
+ }
1042
+
1043
+ func process(_ data: T) -> ProcessingResult {
1044
+ if let cached = cache[data] {
1045
+ return cached
1046
+ }
1047
+
1048
+ let result = ProcessingResult(data: data, timestamp: Date())
1049
+ cache[data] = result
1050
+ return result
1051
+ }
1052
+ }
1053
+
1054
+ final class NetworkDataProcessor<T: Codable & Hashable>: BaseDataProcessor<T>, DataTransformable {
1055
+ typealias InputType = T
1056
+ typealias OutputType = NetworkResponse<T>
1057
+
1058
+ let transformationId = "network-processor"
1059
+ private let session: URLSession
1060
+
1061
+ override init() {
1062
+ self.session = URLSession.shared
1063
+ super.init()
1064
+ }
1065
+
1066
+ func transform(_ input: T) throws -> OutputType {
1067
+ // Complex transformation logic here
1068
+ let jsonData = try JSONEncoder().encode(input)
1069
+ return NetworkResponse(data: input, rawData: jsonData)
1070
+ }
1071
+ }
1072
+
1073
+ // MARK: - Structs with Property Wrappers and Computed Properties
1074
+
1075
+ struct UserProfile: Codable, Identifiable {
1076
+ let id: UUID
1077
+ @Published var name: String
1078
+ @Published var email: String
1079
+ @UserDefault(key: "user_preferences", defaultValue: UserPreferences())
1080
+ var preferences: UserPreferences
1081
+
1082
+ private let createdAt: Date
1083
+ private var lastUpdated: Date = Date()
1084
+
1085
+ var displayName: String {
1086
+ return name.isEmpty ? "Anonymous User" : name
1087
+ }
1088
+
1089
+ var isValid: Bool {
1090
+ return !name.isEmpty && email.contains("@")
1091
+ }
1092
+
1093
+ init(name: String, email: String) {
1094
+ self.id = UUID()
1095
+ self.name = name
1096
+ self.email = email
1097
+ self.createdAt = Date()
1098
+ }
1099
+
1100
+ mutating func updateProfile(name: String? = nil, email: String? = nil) {
1101
+ if let newName = name {
1102
+ self.name = newName
1103
+ }
1104
+ if let newEmail = email {
1105
+ self.email = newEmail
1106
+ }
1107
+ self.lastUpdated = Date()
1108
+ }
1109
+ }
1110
+
1111
+ // MARK: - Enums with Associated Values and Methods
1112
+
1113
+ enum APIResponse<T: Codable> {
1114
+ case success(data: T, metadata: ResponseMetadata)
1115
+ case failure(error: APIError, retryAfter: TimeInterval?)
1116
+ case loading(progress: Double)
1117
+ case cached(data: T, cacheTimestamp: Date)
1118
+
1119
+ var isSuccessful: Bool {
1120
+ switch self {
1121
+ case .success, .cached:
1122
+ return true
1123
+ case .failure, .loading:
1124
+ return false
1125
+ }
1126
+ }
1127
+
1128
+ func map<U: Codable>(_ transform: (T) -> U) -> APIResponse<U> {
1129
+ switch self {
1130
+ case .success(let data, let metadata):
1131
+ return .success(data: transform(data), metadata: metadata)
1132
+ case .cached(let data, let timestamp):
1133
+ return .cached(data: transform(data), cacheTimestamp: timestamp)
1134
+ case .failure(let error, let retryAfter):
1135
+ return .failure(error: error, retryAfter: retryAfter)
1136
+ case .loading(let progress):
1137
+ return .loading(progress: progress)
1138
+ }
1139
+ }
1140
+ }
1141
+
1142
+ enum APIError: Error, LocalizedError, CaseIterable {
1143
+ case networkUnavailable
1144
+ case invalidCredentials
1145
+ case serverError(code: Int)
1146
+ case dataCorrupted(description: String)
1147
+ case rateLimitExceeded(resetTime: Date)
1148
+
1149
+ var errorDescription: String? {
1150
+ switch self {
1151
+ case .networkUnavailable:
1152
+ return "Network connection is unavailable"
1153
+ case .invalidCredentials:
1154
+ return "Invalid authentication credentials"
1155
+ case .serverError(let code):
1156
+ return "Server error with code: \(code)"
1157
+ case .dataCorrupted(let description):
1158
+ return "Data corruption: \(description)"
1159
+ case .rateLimitExceeded(let resetTime):
1160
+ return "Rate limit exceeded. Try again after \(resetTime)"
1161
+ }
1162
+ }
1163
+ }
1164
+
1165
+ // MARK: - Extensions with Conditional Conformance
1166
+
1167
+ extension Array where Element: Numeric {
1168
+ func sum() -> Element {
1169
+ return reduce(0, +)
1170
+ }
1171
+
1172
+ func average() -> Double where Element: BinaryInteger {
1173
+ guard !isEmpty else { return 0 }
1174
+ let total = sum()
1175
+ return Double(total) / Double(count)
1176
+ }
1177
+ }
1178
+
1179
+ extension Dictionary where Key == String, Value: Codable {
1180
+ func toJSON() throws -> Data {
1181
+ return try JSONSerialization.data(withJSONObject: self)
1182
+ }
1183
+
1184
+ static func fromJSON(_ data: Data) throws -> [String: Value] {
1185
+ let decoded = try JSONSerialization.jsonObject(with: data) as? [String: Any] ?? [:]
1186
+ // Complex conversion logic would go here
1187
+ return [:] // Simplified for testing
1188
+ }
1189
+ }
1190
+
1191
+ extension APIResponse: Equatable where T: Equatable {
1192
+ static func == (lhs: APIResponse<T>, rhs: APIResponse<T>) -> Bool {
1193
+ switch (lhs, rhs) {
1194
+ case (.success(let lData, _), .success(let rData, _)):
1195
+ return lData == rData
1196
+ case (.cached(let lData, _), .cached(let rData, _)):
1197
+ return lData == rData
1198
+ case (.loading(let lProgress), .loading(let rProgress)):
1199
+ return lProgress == rProgress
1200
+ case (.failure(_, _), .failure(_, _)):
1201
+ return true
1202
+ default:
1203
+ return false
1204
+ }
1205
+ }
1206
+ }
1207
+
1208
+ // MARK: - Property Wrappers
1209
+
1210
+ @propertyWrapper
1211
+ struct UserDefault<T: Codable> {
1212
+ let key: String
1213
+ let defaultValue: T
1214
+
1215
+ var wrappedValue: T {
1216
+ get {
1217
+ guard let data = UserDefaults.standard.data(forKey: key) else {
1218
+ return defaultValue
1219
+ }
1220
+
1221
+ do {
1222
+ return try JSONDecoder().decode(T.self, from: data)
1223
+ } catch {
1224
+ return defaultValue
1225
+ }
1226
+ }
1227
+ set {
1228
+ do {
1229
+ let data = try JSONEncoder().encode(newValue)
1230
+ UserDefaults.standard.set(data, forKey: key)
1231
+ } catch {
1232
+ print("Failed to encode value for key \(key): \(error)")
1233
+ }
1234
+ }
1235
+ }
1236
+ }
1237
+
1238
+ @propertyWrapper
1239
+ struct Clamped<T: Comparable> {
1240
+ private var value: T
1241
+ private let range: ClosedRange<T>
1242
+
1243
+ var wrappedValue: T {
1244
+ get { return value }
1245
+ set { value = min(max(range.lowerBound, newValue), range.upperBound) }
1246
+ }
1247
+
1248
+ init(wrappedValue: T, _ range: ClosedRange<T>) {
1249
+ self.range = range
1250
+ self.value = min(max(range.lowerBound, wrappedValue), range.upperBound)
1251
+ }
1252
+ }
1253
+
1254
+ // MARK: - Nested Types and Namespacing
1255
+
1256
+ struct NetworkManager {
1257
+ enum RequestMethod: String, CaseIterable {
1258
+ case get = "GET"
1259
+ case post = "POST"
1260
+ case put = "PUT"
1261
+ case delete = "DELETE"
1262
+ case patch = "PATCH"
1263
+ }
1264
+
1265
+ struct Configuration {
1266
+ let baseURL: URL
1267
+ let timeout: TimeInterval
1268
+ let headers: [String: String]
1269
+
1270
+ static let development = Configuration(
1271
+ baseURL: URL(string: "https://dev.api.example.com")!,
1272
+ timeout: 30,
1273
+ headers: ["Content-Type": "application/json"]
1274
+ )
1275
+
1276
+ static let production = Configuration(
1277
+ baseURL: URL(string: "https://api.example.com")!,
1278
+ timeout: 60,
1279
+ headers: ["Content-Type": "application/json"]
1280
+ )
1281
+ }
1282
+
1283
+ class RequestBuilder {
1284
+ private var method: RequestMethod = .get
1285
+ private var path: String = ""
1286
+ private var queryItems: [URLQueryItem] = []
1287
+ private var body: Data?
1288
+
1289
+ func method(_ method: RequestMethod) -> Self {
1290
+ self.method = method
1291
+ return self
1292
+ }
1293
+
1294
+ func path(_ path: String) -> Self {
1295
+ self.path = path
1296
+ return self
1297
+ }
1298
+
1299
+ func query(_ name: String, value: String) -> Self {
1300
+ queryItems.append(URLQueryItem(name: name, value: value))
1301
+ return self
1302
+ }
1303
+
1304
+ func body(_ data: Data) -> Self {
1305
+ self.body = data
1306
+ return self
1307
+ }
1308
+
1309
+ func build(config: Configuration) throws -> URLRequest {
1310
+ guard var components = URLComponents(url: config.baseURL, resolvingAgainstBaseURL: true) else {
1311
+ throw APIError.serverError(code: 0)
1312
+ }
1313
+
1314
+ components.path = path
1315
+ components.queryItems = queryItems.isEmpty ? nil : queryItems
1316
+
1317
+ guard let url = components.url else {
1318
+ throw APIError.serverError(code: 0)
1319
+ }
1320
+
1321
+ var request = URLRequest(url: url)
1322
+ request.httpMethod = method.rawValue
1323
+ request.timeoutInterval = config.timeout
1324
+ request.httpBody = body
1325
+
1326
+ for (key, value) in config.headers {
1327
+ request.setValue(value, forHTTPHeaderField: key)
1328
+ }
1329
+
1330
+ return request
1331
+ }
1332
+ }
1333
+ }
1334
+ "#;
1335
+
1336
+ fs::write(&test_file, content)?;
1337
+
1338
+ let ctx = TestContext::new();
1339
+ let output = ctx.run_probe(&[
1340
+ "search",
1341
+ "protocol", // Search for protocols
1342
+ test_file.to_str().unwrap(),
1343
+ "--format",
1344
+ "outline",
1345
+ ])?;
1346
+
1347
+ // Should find Swift-specific constructs
1348
+ let swift_constructs = [
1349
+ "protocol",
1350
+ "class",
1351
+ "struct",
1352
+ "enum",
1353
+ "extension",
1354
+ "@propertyWrapper",
1355
+ ];
1356
+ let found_constructs: Vec<&str> = swift_constructs
1357
+ .iter()
1358
+ .filter(|&construct| output.contains(construct))
1359
+ .copied()
1360
+ .collect();
1361
+
1362
+ assert!(
1363
+ !found_constructs.is_empty(),
1364
+ "Should find Swift-specific constructs. Found: {:?} - output: {}",
1365
+ found_constructs,
1366
+ output
1367
+ );
1368
+
1369
+ // Should find specific Swift constructs
1370
+ assert!(
1371
+ output.contains("DataTransformable") || output.contains("Repository"),
1372
+ "Should find protocol definitions - output: {}",
1373
+ output
1374
+ );
1375
+
1376
+ assert!(
1377
+ output.contains("BaseDataProcessor") || output.contains("NetworkDataProcessor"),
1378
+ "Should find class definitions - output: {}",
1379
+ output
1380
+ );
1381
+
1382
+ assert!(
1383
+ output.contains("UserProfile") || output.contains("NetworkManager"),
1384
+ "Should find struct definitions - output: {}",
1385
+ output
1386
+ );
1387
+
1388
+ assert!(
1389
+ output.contains("APIResponse") || output.contains("APIError"),
1390
+ "Should find enum definitions - output: {}",
1391
+ output
1392
+ );
1393
+
1394
+ // Should be in outline format
1395
+ assert!(
1396
+ output.contains("---\nFile:"),
1397
+ "Missing file delimiter in outline format - output: {}",
1398
+ output
1399
+ );
1400
+
1401
+ Ok(())
1402
+ }
1403
+
1404
+ #[test]
1405
+ fn test_swift_outline_control_flow_statements() -> Result<()> {
1406
+ let temp_dir = TempDir::new()?;
1407
+ let test_file = temp_dir.path().join("ControlFlow.swift");
1408
+
1409
+ let content = r#"import Foundation
1410
+
1411
+ struct DataValidator {
1412
+ enum ValidationError: Error {
1413
+ case invalidInput
1414
+ case processingFailed
1415
+ case timeout
1416
+ }
1417
+
1418
+ // Function with comprehensive control flow patterns
1419
+ func validateAndProcessData(_ input: [Any]) async throws -> [String] {
1420
+ var results: [String] = []
1421
+
1422
+ // Guard statement for early exit
1423
+ guard !input.isEmpty else {
1424
+ throw ValidationError.invalidInput
1425
+ }
1426
+
1427
+ // Defer statement for cleanup
1428
+ defer {
1429
+ print("Cleaning up validation resources")
1430
+ cleanup()
1431
+ }
1432
+
1433
+ // For loop with enumerated values
1434
+ for (index, item) in input.enumerated() {
1435
+ // Nested if-else statements
1436
+ if let stringItem = item as? String {
1437
+ if stringItem.count > 100 {
1438
+ results.append("LONG_STRING[\(index)]: \(stringItem.prefix(50))...")
1439
+ } else if stringItem.isEmpty {
1440
+ results.append("EMPTY_STRING[\(index)]")
1441
+ } else {
1442
+ results.append("STRING[\(index)]: \(stringItem)")
1443
+ }
1444
+ } else if let numberItem = item as? NSNumber {
1445
+ let value = numberItem.doubleValue
1446
+ if value > 1000 {
1447
+ results.append("LARGE_NUMBER[\(index)]: \(value)")
1448
+ } else if value < 0 {
1449
+ results.append("NEGATIVE_NUMBER[\(index)]: \(value)")
1450
+ } else {
1451
+ results.append("NUMBER[\(index)]: \(value)")
1452
+ }
1453
+ } else if let arrayItem = item as? [Any] {
1454
+ // Recursive processing with do-catch
1455
+ do {
1456
+ let nestedResults = try await validateAndProcessData(arrayItem)
1457
+ results.append("NESTED_ARRAY[\(index)]: [\(nestedResults.joined(separator: ", "))]")
1458
+ } catch {
1459
+ results.append("NESTED_ARRAY_ERROR[\(index)]: \(error.localizedDescription)")
1460
+ }
1461
+ } else {
1462
+ results.append("UNKNOWN_TYPE[\(index)]: \(type(of: item))")
1463
+ }
1464
+ }
1465
+
1466
+ // While loop with complex condition
1467
+ var retryCount = 0
1468
+ while retryCount < 3 && !results.isEmpty {
1469
+ let success = await performValidation(results)
1470
+ if success {
1471
+ break
1472
+ }
1473
+
1474
+ retryCount += 1
1475
+
1476
+ // Nested switch statement
1477
+ switch retryCount {
1478
+ case 1:
1479
+ await Task.sleep(nanoseconds: 1_000_000_000) // 1 second
1480
+ case 2:
1481
+ await Task.sleep(nanoseconds: 2_000_000_000) // 2 seconds
1482
+ case 3:
1483
+ throw ValidationError.timeout
1484
+ default:
1485
+ break
1486
+ }
1487
+ }
1488
+
1489
+ // Switch statement with associated values and where clauses
1490
+ for result in results {
1491
+ switch result {
1492
+ case let str where str.hasPrefix("LONG_STRING"):
1493
+ print("Processing long string: \(str)")
1494
+ case let str where str.contains("ERROR"):
1495
+ print("Error found: \(str)")
1496
+ case let str where str.hasPrefix("NUMBER"):
1497
+ print("Number processing: \(str)")
1498
+ default:
1499
+ print("Standard processing: \(result)")
1500
+ }
1501
+ }
1502
+
1503
+ return results
1504
+ }
1505
+
1506
+ // Function demonstrating repeat-while loop
1507
+ func processUntilComplete(_ data: inout [String]) {
1508
+ repeat {
1509
+ // Complex nested control flow
1510
+ for (index, item) in data.enumerated() {
1511
+ if item.isEmpty {
1512
+ data.remove(at: index)
1513
+ continue
1514
+ }
1515
+
1516
+ // Nested switch with fallthrough
1517
+ switch item.first {
1518
+ case "A":
1519
+ data[index] = "PROCESSED_A_" + item
1520
+ case "B":
1521
+ data[index] = "PROCESSED_B_" + item
1522
+ case "C":
1523
+ data[index] = "PROCESSED_C_" + item
1524
+ fallthrough
1525
+ case "D":
1526
+ data[index] += "_SPECIAL"
1527
+ default:
1528
+ data[index] = "DEFAULT_" + item
1529
+ }
1530
+ }
1531
+ } while data.contains { $0.hasPrefix("UNPROCESSED") }
1532
+ }
1533
+
1534
+ // Function with complex guard statements and early returns
1535
+ func complexGuardValidation(_ input: Any?) -> String? {
1536
+ guard let input = input else {
1537
+ return nil
1538
+ }
1539
+
1540
+ guard let stringInput = input as? String else {
1541
+ return "NOT_STRING"
1542
+ }
1543
+
1544
+ guard !stringInput.isEmpty else {
1545
+ return "EMPTY"
1546
+ }
1547
+
1548
+ guard stringInput.count >= 5 else {
1549
+ return "TOO_SHORT"
1550
+ }
1551
+
1552
+ guard stringInput.count <= 100 else {
1553
+ return "TOO_LONG"
1554
+ }
1555
+
1556
+ // Nested if with multiple conditions
1557
+ if stringInput.hasPrefix("SPECIAL_") && stringInput.hasSuffix("_END") {
1558
+ if stringInput.contains("IMPORTANT") {
1559
+ return "SPECIAL_IMPORTANT"
1560
+ } else if stringInput.contains("URGENT") {
1561
+ return "SPECIAL_URGENT"
1562
+ } else {
1563
+ return "SPECIAL_NORMAL"
1564
+ }
1565
+ }
1566
+
1567
+ return "VALID"
1568
+ }
1569
+
1570
+ // Function with do-catch blocks and error handling
1571
+ func processWithErrorHandling(_ items: [String]) throws -> [String] {
1572
+ var processedItems: [String] = []
1573
+
1574
+ for item in items {
1575
+ do {
1576
+ // First processing step
1577
+ let step1 = try validateItem(item)
1578
+
1579
+ do {
1580
+ // Nested processing with different error handling
1581
+ let step2 = try transformItem(step1)
1582
+ processedItems.append(step2)
1583
+ } catch ValidationError.processingFailed {
1584
+ // Handle specific error type
1585
+ processedItems.append("PROCESSING_FAILED: \(item)")
1586
+ } catch {
1587
+ // Handle other errors
1588
+ processedItems.append("UNKNOWN_ERROR: \(item) - \(error)")
1589
+ }
1590
+ } catch ValidationError.invalidInput {
1591
+ // Skip invalid inputs
1592
+ continue
1593
+ } catch ValidationError.timeout {
1594
+ // Propagate timeout errors
1595
+ throw ValidationError.timeout
1596
+ } catch {
1597
+ // Log and continue with other errors
1598
+ print("Unexpected error processing \(item): \(error)")
1599
+ processedItems.append("ERROR: \(item)")
1600
+ }
1601
+ }
1602
+
1603
+ return processedItems
1604
+ }
1605
+
1606
+ // Private helper functions
1607
+ private func cleanup() {
1608
+ print("Performing cleanup")
1609
+ }
1610
+
1611
+ private func performValidation(_ results: [String]) async -> Bool {
1612
+ // Simulate async validation
1613
+ await Task.sleep(nanoseconds: 100_000_000) // 0.1 second
1614
+ return !results.isEmpty
1615
+ }
1616
+
1617
+ private func validateItem(_ item: String) throws -> String {
1618
+ if item.isEmpty {
1619
+ throw ValidationError.invalidInput
1620
+ }
1621
+ return "VALIDATED_\(item)"
1622
+ }
1623
+
1624
+ private func transformItem(_ item: String) throws -> String {
1625
+ if item.contains("FAIL") {
1626
+ throw ValidationError.processingFailed
1627
+ }
1628
+ return "TRANSFORMED_\(item)"
1629
+ }
1630
+ }
1631
+
1632
+ // Extension with additional control flow patterns
1633
+ extension DataValidator {
1634
+ func processWithComplexSwitchStatement(_ value: Any) -> String {
1635
+ switch value {
1636
+ case let str as String where str.count > 10:
1637
+ return "LONG_STRING: \(str.prefix(10))..."
1638
+
1639
+ case let str as String where str.isEmpty:
1640
+ return "EMPTY_STRING"
1641
+
1642
+ case let str as String:
1643
+ return "STRING: \(str)"
1644
+
1645
+ case let num as Int where num > 100:
1646
+ return "LARGE_INT: \(num)"
1647
+
1648
+ case let num as Int where num < 0:
1649
+ return "NEGATIVE_INT: \(num)"
1650
+
1651
+ case let num as Int:
1652
+ return "INT: \(num)"
1653
+
1654
+ case let array as [Any] where array.count > 5:
1655
+ return "LARGE_ARRAY: \(array.count) items"
1656
+
1657
+ case let array as [Any]:
1658
+ return "ARRAY: \(array.count) items"
1659
+
1660
+ case Optional<Any>.none:
1661
+ return "NIL_VALUE"
1662
+
1663
+ case Optional<Any>.some(let unwrapped):
1664
+ return "OPTIONAL: \(processWithComplexSwitchStatement(unwrapped))"
1665
+
1666
+ default:
1667
+ return "UNKNOWN_TYPE: \(type(of: value))"
1668
+ }
1669
+ }
1670
+ }
1671
+ "#;
1672
+
1673
+ fs::write(&test_file, content)?;
1674
+
1675
+ let ctx = TestContext::new();
1676
+ let output = ctx.run_probe(&[
1677
+ "search",
1678
+ "guard", // Search for guard statements
1679
+ test_file.to_str().unwrap(),
1680
+ "--format",
1681
+ "outline",
1682
+ ])?;
1683
+
1684
+ // Should find Swift control flow statements
1685
+ let control_flow_keywords = [
1686
+ "guard", "defer", "if", "while", "for", "switch", "do", "catch", "repeat",
1687
+ ];
1688
+ let found_keywords: Vec<&str> = control_flow_keywords
1689
+ .iter()
1690
+ .filter(|&keyword| output.contains(keyword))
1691
+ .copied()
1692
+ .collect();
1693
+
1694
+ assert!(
1695
+ !found_keywords.is_empty(),
1696
+ "Should find Swift control flow keywords. Found: {:?} - output: {}",
1697
+ found_keywords,
1698
+ output
1699
+ );
1700
+
1701
+ // Should find guard statements specifically
1702
+ assert!(
1703
+ output.contains("guard"),
1704
+ "Should find guard statements - output: {}",
1705
+ output
1706
+ );
1707
+
1708
+ // Should find nested control structures
1709
+ let nested_patterns = ["nested", "if", "switch", "case", "while"];
1710
+ let found_nested: Vec<&str> = nested_patterns
1711
+ .iter()
1712
+ .filter(|&pattern| output.contains(pattern))
1713
+ .copied()
1714
+ .collect();
1715
+
1716
+ assert!(
1717
+ found_nested.len() >= 2,
1718
+ "Should find nested control flow patterns. Found: {:?} - output: {}",
1719
+ found_nested,
1720
+ output
1721
+ );
1722
+
1723
+ // Should show closing braces for large control blocks
1724
+ let has_closing_braces = output.contains("} //") || output.contains("} /*");
1725
+ assert!(
1726
+ has_closing_braces,
1727
+ "Large control flow blocks should have closing brace comments - output: {}",
1728
+ output
1729
+ );
1730
+
1731
+ // Should be in outline format
1732
+ assert!(
1733
+ output.contains("---\nFile:"),
1734
+ "Missing file delimiter in outline format - output: {}",
1735
+ output
1736
+ );
1737
+
1738
+ Ok(())
1739
+ }
1740
+
1741
+ #[test]
1742
+ fn test_swift_outline_test_detection_patterns() -> Result<()> {
1743
+ let temp_dir = TempDir::new()?;
1744
+ let test_file = temp_dir.path().join("SwiftTests.swift");
1745
+
1746
+ let content = r#"import XCTest
1747
+ @testable import MyApp
1748
+ import Foundation
1749
+
1750
+ // MARK: - XCTest Framework Tests
1751
+
1752
+ class CalculatorTests: XCTestCase {
1753
+ var calculator: Calculator!
1754
+
1755
+ override func setUpWithError() throws {
1756
+ calculator = Calculator()
1757
+ }
1758
+
1759
+ override func tearDownWithError() throws {
1760
+ calculator = nil
1761
+ }
1762
+
1763
+ func testAddition() {
1764
+ let result = calculator.add(2, 3)
1765
+ XCTAssertEqual(result, 5, "Addition should work correctly")
1766
+ }
1767
+
1768
+ func testSubtraction() throws {
1769
+ let result = calculator.subtract(5, 3)
1770
+ XCTAssertEqual(result, 2)
1771
+
1772
+ // Test with negative result
1773
+ let negativeResult = calculator.subtract(3, 5)
1774
+ XCTAssertEqual(negativeResult, -2)
1775
+ }
1776
+
1777
+ func testMultiplication() {
1778
+ XCTAssertEqual(calculator.multiply(4, 5), 20)
1779
+ XCTAssertEqual(calculator.multiply(-2, 3), -6)
1780
+ XCTAssertEqual(calculator.multiply(0, 100), 0)
1781
+ }
1782
+
1783
+ func testDivision() throws {
1784
+ let result = try calculator.divide(10, 2)
1785
+ XCTAssertEqual(result, 5.0, accuracy: 0.001)
1786
+
1787
+ // Test division by zero throws error
1788
+ XCTAssertThrowsError(try calculator.divide(10, 0)) { error in
1789
+ XCTAssertTrue(error is CalculatorError)
1790
+ }
1791
+ }
1792
+
1793
+ func testPerformance() {
1794
+ measure {
1795
+ for i in 0..<1000 {
1796
+ _ = calculator.add(Double(i), Double(i + 1))
1797
+ }
1798
+ }
1799
+ }
1800
+
1801
+ func testAsyncOperation() async throws {
1802
+ let result = try await calculator.asyncCalculation(5, 10)
1803
+ XCTAssertEqual(result, 15)
1804
+
1805
+ await XCTAssertThrowsErrorAsync(try await calculator.asyncCalculation(0, 0))
1806
+ }
1807
+
1808
+ func testExpectation() {
1809
+ let expectation = expectation(description: "Async calculation completed")
1810
+
1811
+ calculator.performAsyncCalculation { result in
1812
+ XCTAssertNotNil(result)
1813
+ expectation.fulfill()
1814
+ }
1815
+
1816
+ waitForExpectations(timeout: 5.0)
1817
+ }
1818
+ }
1819
+
1820
+ // MARK: - Performance Tests
1821
+
1822
+ class PerformanceTests: XCTestCase {
1823
+
1824
+ func testCalculatorPerformance() {
1825
+ let calculator = Calculator()
1826
+
1827
+ measure {
1828
+ for _ in 0..<10000 {
1829
+ _ = calculator.add(1.0, 2.0)
1830
+ }
1831
+ }
1832
+ }
1833
+
1834
+ func testMemoryUsage() {
1835
+ measureMetrics([.wallClockTime, .peakMemoryUsage]) {
1836
+ let largeArray = Array(0..<100000)
1837
+ _ = largeArray.map { $0 * 2 }
1838
+ }
1839
+ }
1840
+ }
1841
+
1842
+ // MARK: - UI Tests
1843
+
1844
+ class AppUITests: XCTestCase {
1845
+ let app = XCUIApplication()
1846
+
1847
+ override func setUpWithError() throws {
1848
+ continueAfterFailure = false
1849
+ app.launch()
1850
+ }
1851
+
1852
+ func testBasicNavigation() throws {
1853
+ let tabBar = app.tabBars.firstMatch
1854
+ XCTAssertTrue(tabBar.exists)
1855
+
1856
+ app.buttons["Calculator"].tap()
1857
+
1858
+ let calculatorView = app.otherElements["CalculatorView"]
1859
+ XCTAssertTrue(calculatorView.waitForExistence(timeout: 5))
1860
+ }
1861
+
1862
+ func testCalculatorInput() {
1863
+ app.buttons["5"].tap()
1864
+ app.buttons["+"].tap()
1865
+ app.buttons["3"].tap()
1866
+ app.buttons["="].tap()
1867
+
1868
+ let result = app.staticTexts["8"]
1869
+ XCTAssertTrue(result.exists)
1870
+ }
1871
+
1872
+ func testScreenshots() {
1873
+ takeScreenshot(name: "main_screen")
1874
+
1875
+ app.buttons["Settings"].tap()
1876
+ takeScreenshot(name: "settings_screen")
1877
+ }
1878
+
1879
+ private func takeScreenshot(name: String) {
1880
+ let screenshot = app.screenshot()
1881
+ let attachment = XCTAttachment(screenshot: screenshot)
1882
+ attachment.name = name
1883
+ attachment.lifetime = .keepAlways
1884
+ add(attachment)
1885
+ }
1886
+ }
1887
+
1888
+ // MARK: - Simple Test Functions (Non-XCTest)
1889
+
1890
+ struct SimpleTests {
1891
+ // Simple test functions that should be detected
1892
+ static func testStringOperations() -> Bool {
1893
+ let str = "Hello, World!"
1894
+
1895
+ // Test string length
1896
+ guard str.count == 13 else {
1897
+ print("String length test failed")
1898
+ return false
1899
+ }
1900
+
1901
+ // Test string contains
1902
+ guard str.contains("World") else {
1903
+ print("String contains test failed")
1904
+ return false
1905
+ }
1906
+
1907
+ // Test string prefix
1908
+ guard str.hasPrefix("Hello") else {
1909
+ print("String prefix test failed")
1910
+ return false
1911
+ }
1912
+
1913
+ print("All string tests passed")
1914
+ return true
1915
+ }
1916
+
1917
+ static func testArrayOperations() -> Bool {
1918
+ let numbers = [1, 2, 3, 4, 5]
1919
+
1920
+ // Test array count
1921
+ guard numbers.count == 5 else {
1922
+ print("Array count test failed")
1923
+ return false
1924
+ }
1925
+
1926
+ // Test array contains
1927
+ guard numbers.contains(3) else {
1928
+ print("Array contains test failed")
1929
+ return false
1930
+ }
1931
+
1932
+ // Test array sum
1933
+ let sum = numbers.reduce(0, +)
1934
+ guard sum == 15 else {
1935
+ print("Array sum test failed: expected 15, got \(sum)")
1936
+ return false
1937
+ }
1938
+
1939
+ print("All array tests passed")
1940
+ return true
1941
+ }
1942
+
1943
+ static func testMathOperations() -> Bool {
1944
+ // Test basic arithmetic
1945
+ guard 2 + 2 == 4 else {
1946
+ print("Addition test failed")
1947
+ return false
1948
+ }
1949
+
1950
+ guard 10 - 3 == 7 else {
1951
+ print("Subtraction test failed")
1952
+ return false
1953
+ }
1954
+
1955
+ guard 4 * 5 == 20 else {
1956
+ print("Multiplication test failed")
1957
+ return false
1958
+ }
1959
+
1960
+ guard 15 / 3 == 5 else {
1961
+ print("Division test failed")
1962
+ return false
1963
+ }
1964
+
1965
+ print("All math tests passed")
1966
+ return true
1967
+ }
1968
+
1969
+ static func runAllTests() {
1970
+ print("Running simple tests...")
1971
+
1972
+ let stringTestPassed = testStringOperations()
1973
+ let arrayTestPassed = testArrayOperations()
1974
+ let mathTestPassed = testMathOperations()
1975
+
1976
+ if stringTestPassed && arrayTestPassed && mathTestPassed {
1977
+ print("All simple tests passed!")
1978
+ } else {
1979
+ print("Some tests failed.")
1980
+ }
1981
+ }
1982
+ }
1983
+
1984
+ // MARK: - Mock and Stub Test Helpers
1985
+
1986
+ class MockNetworkService {
1987
+ var shouldReturnError = false
1988
+
1989
+ func fetchData() async throws -> Data {
1990
+ if shouldReturnError {
1991
+ throw NetworkError.connectionFailed
1992
+ }
1993
+
1994
+ let jsonString = "{\"message\": \"Hello, World!\"}"
1995
+ return jsonString.data(using: .utf8)!
1996
+ }
1997
+ }
1998
+
1999
+ enum NetworkError: Error {
2000
+ case connectionFailed
2001
+ case invalidResponse
2002
+ }
2003
+
2004
+ // MARK: - Integration Tests
2005
+
2006
+ class IntegrationTests: XCTestCase {
2007
+ var mockService: MockNetworkService!
2008
+ var dataProcessor: DataProcessor!
2009
+
2010
+ override func setUp() {
2011
+ super.setUp()
2012
+ mockService = MockNetworkService()
2013
+ dataProcessor = DataProcessor(networkService: mockService)
2014
+ }
2015
+
2016
+ func testDataProcessingFlow() async throws {
2017
+ // Test successful flow
2018
+ mockService.shouldReturnError = false
2019
+ let result = try await dataProcessor.processData()
2020
+
2021
+ XCTAssertNotNil(result)
2022
+ XCTAssertEqual(result.message, "Hello, World!")
2023
+ }
2024
+
2025
+ func testErrorHandling() async {
2026
+ // Test error flow
2027
+ mockService.shouldReturnError = true
2028
+
2029
+ do {
2030
+ _ = try await dataProcessor.processData()
2031
+ XCTFail("Expected error to be thrown")
2032
+ } catch {
2033
+ XCTAssertTrue(error is NetworkError)
2034
+ }
2035
+ }
2036
+
2037
+ func testRetryLogic() async throws {
2038
+ var attemptCount = 0
2039
+ mockService.shouldReturnError = true
2040
+
2041
+ // Mock will fail first two attempts, succeed on third
2042
+ dataProcessor.retryHandler = {
2043
+ attemptCount += 1
2044
+ if attemptCount >= 3 {
2045
+ self.mockService.shouldReturnError = false
2046
+ }
2047
+ }
2048
+
2049
+ let result = try await dataProcessor.processDataWithRetry(maxAttempts: 3)
2050
+ XCTAssertNotNil(result)
2051
+ XCTAssertEqual(attemptCount, 3)
2052
+ }
2053
+ }
2054
+ "#;
2055
+
2056
+ fs::write(&test_file, content)?;
2057
+
2058
+ let ctx = TestContext::new();
2059
+ let output = ctx.run_probe(&[
2060
+ "search",
2061
+ "test", // Search for test-related content
2062
+ test_file.to_str().unwrap(),
2063
+ "--format",
2064
+ "outline",
2065
+ "--allow-tests", // Enable test detection
2066
+ ])?;
2067
+
2068
+ // Should find XCTest framework test classes
2069
+ assert!(
2070
+ output.contains("XCTestCase")
2071
+ || output.contains("CalculatorTests")
2072
+ || output.contains("PerformanceTests"),
2073
+ "Should find XCTest framework test classes - output: {}",
2074
+ output
2075
+ );
2076
+
2077
+ // Should find XCTest methods
2078
+ let xctest_methods = [
2079
+ "testAddition",
2080
+ "testSubtraction",
2081
+ "testMultiplication",
2082
+ "testDivision",
2083
+ "testPerformance",
2084
+ ];
2085
+ let found_xctest_methods: Vec<&str> = xctest_methods
2086
+ .iter()
2087
+ .filter(|&method| output.contains(method))
2088
+ .copied()
2089
+ .collect();
2090
+
2091
+ assert!(
2092
+ !found_xctest_methods.is_empty(),
2093
+ "Should find XCTest methods. Found: {:?} - output: {}",
2094
+ found_xctest_methods,
2095
+ output
2096
+ );
2097
+
2098
+ // Should find simple test functions (non-XCTest)
2099
+ let simple_test_functions = [
2100
+ "testStringOperations",
2101
+ "testArrayOperations",
2102
+ "testMathOperations",
2103
+ ];
2104
+ let found_simple_tests: Vec<&str> = simple_test_functions
2105
+ .iter()
2106
+ .filter(|&func| output.contains(func))
2107
+ .copied()
2108
+ .collect();
2109
+
2110
+ assert!(
2111
+ !found_simple_tests.is_empty(),
2112
+ "Should find simple test functions. Found: {:?} - output: {}",
2113
+ found_simple_tests,
2114
+ output
2115
+ );
2116
+
2117
+ // Should find XCTest assertions and patterns
2118
+ let xctest_patterns = [
2119
+ "XCTAssert",
2120
+ "XCTAssertEqual",
2121
+ "XCTAssertThrowsError",
2122
+ "expectation",
2123
+ "measure",
2124
+ ];
2125
+ let found_patterns: Vec<&str> = xctest_patterns
2126
+ .iter()
2127
+ .filter(|&pattern| output.contains(pattern))
2128
+ .copied()
2129
+ .collect();
2130
+
2131
+ assert!(
2132
+ !found_patterns.is_empty(),
2133
+ "Should find XCTest assertion patterns. Found: {:?} - output: {}",
2134
+ found_patterns,
2135
+ output
2136
+ );
2137
+
2138
+ // Should find test setup and teardown methods
2139
+ let setup_teardown = ["setUp", "tearDown", "setUpWithError", "tearDownWithError"];
2140
+ let found_setup: Vec<&str> = setup_teardown
2141
+ .iter()
2142
+ .filter(|&method| output.contains(method))
2143
+ .copied()
2144
+ .collect();
2145
+
2146
+ // Note: This is optional since setup/teardown might not always be in search results
2147
+ if !found_setup.is_empty() {
2148
+ println!("Found setup/teardown methods: {:?}", found_setup);
2149
+ }
2150
+
2151
+ // Should find async test patterns
2152
+ let async_patterns = ["async", "await", "XCTAssertThrowsErrorAsync"];
2153
+ let found_async: Vec<&str> = async_patterns
2154
+ .iter()
2155
+ .filter(|&pattern| output.contains(pattern))
2156
+ .copied()
2157
+ .collect();
2158
+
2159
+ assert!(
2160
+ !found_async.is_empty(),
2161
+ "Should find async test patterns. Found: {:?} - output: {}",
2162
+ found_async,
2163
+ output
2164
+ );
2165
+
2166
+ // Should be in outline format
2167
+ assert!(
2168
+ output.contains("---\nFile:"),
2169
+ "Missing file delimiter in outline format - output: {}",
2170
+ output
2171
+ );
2172
+
2173
+ Ok(())
2174
+ }
2175
+
2176
+ #[test]
2177
+ fn test_swift_outline_modern_features() -> Result<()> {
2178
+ let temp_dir = TempDir::new()?;
2179
+ let test_file = temp_dir.path().join("ModernSwift.swift");
2180
+
2181
+ let content = r#"import SwiftUI
2182
+ import Combine
2183
+ import Foundation
2184
+
2185
+ // MARK: - Actors for Concurrency
2186
+
2187
+ actor DataManager {
2188
+ private var cache: [String: Any] = [:]
2189
+ private var subscribers: [AnyCancellable] = []
2190
+
2191
+ func store(key: String, value: Any) {
2192
+ cache[key] = value
2193
+ }
2194
+
2195
+ func retrieve(key: String) -> Any? {
2196
+ return cache[key]
2197
+ }
2198
+
2199
+ func clearCache() {
2200
+ cache.removeAll()
2201
+ }
2202
+
2203
+ // Async function within actor
2204
+ func processData(_ data: [String]) async throws -> [String] {
2205
+ var results: [String] = []
2206
+
2207
+ for item in data {
2208
+ // Simulate async processing
2209
+ try await Task.sleep(nanoseconds: 1_000_000) // 1ms
2210
+ results.append("PROCESSED_\(item)")
2211
+ }
2212
+
2213
+ return results
2214
+ }
2215
+ }
2216
+
2217
+ // MARK: - Async/Await Functions
2218
+
2219
+ class AsyncNetworkService {
2220
+ private let session = URLSession.shared
2221
+
2222
+ func fetchData(from url: URL) async throws -> Data {
2223
+ let (data, response) = try await session.data(from: url)
2224
+
2225
+ guard let httpResponse = response as? HTTPURLResponse,
2226
+ 200...299 ~= httpResponse.statusCode else {
2227
+ throw NetworkError.invalidResponse
2228
+ }
2229
+
2230
+ return data
2231
+ }
2232
+
2233
+ func fetchMultipleResources(urls: [URL]) async throws -> [Data] {
2234
+ // Concurrent execution using async let
2235
+ async let firstData = fetchData(from: urls[0])
2236
+ async let secondData = fetchData(from: urls[1])
2237
+ async let thirdData = fetchData(from: urls[2])
2238
+
2239
+ return try await [firstData, secondData, thirdData]
2240
+ }
2241
+
2242
+ func processWithTaskGroup(urls: [URL]) async throws -> [String] {
2243
+ return try await withThrowingTaskGroup(of: String.self) { group in
2244
+ for url in urls {
2245
+ group.addTask {
2246
+ let data = try await self.fetchData(from: url)
2247
+ return String(data: data, encoding: .utf8) ?? "EMPTY"
2248
+ }
2249
+ }
2250
+
2251
+ var results: [String] = []
2252
+ for try await result in group {
2253
+ results.append(result)
2254
+ }
2255
+ return results
2256
+ }
2257
+ }
2258
+ }
2259
+
2260
+ // MARK: - SwiftUI Views with State Management
2261
+
2262
+ struct ContentView: View {
2263
+ @StateObject private var viewModel = ContentViewModel()
2264
+ @Environment(\.colorScheme) var colorScheme
2265
+ @AppStorage("user_preference") var userPreference: String = "default"
2266
+
2267
+ var body: some View {
2268
+ NavigationStack {
2269
+ VStack(spacing: 20) {
2270
+ HeaderView(title: "Modern Swift Demo")
2271
+
2272
+ AsyncButton("Load Data") {
2273
+ await viewModel.loadData()
2274
+ }
2275
+ .disabled(viewModel.isLoading)
2276
+
2277
+ if viewModel.isLoading {
2278
+ ProgressView("Loading...")
2279
+ .progressViewStyle(CircularProgressViewStyle())
2280
+ } else {
2281
+ DataListView(items: viewModel.items)
2282
+ }
2283
+
2284
+ Spacer()
2285
+ }
2286
+ .padding()
2287
+ .navigationTitle("Demo")
2288
+ .task {
2289
+ await viewModel.initializeData()
2290
+ }
2291
+ .refreshable {
2292
+ await viewModel.refreshData()
2293
+ }
2294
+ }
2295
+ .preferredColorScheme(colorScheme)
2296
+ }
2297
+ }
2298
+
2299
+ // MARK: - SwiftUI Components with ViewBuilder
2300
+
2301
+ struct HeaderView: View {
2302
+ let title: String
2303
+ @State private var isAnimated = false
2304
+
2305
+ var body: some View {
2306
+ Text(title)
2307
+ .font(.largeTitle)
2308
+ .fontWeight(.bold)
2309
+ .scaleEffect(isAnimated ? 1.1 : 1.0)
2310
+ .animation(.spring(response: 0.5, dampingFraction: 0.8), value: isAnimated)
2311
+ .onAppear {
2312
+ withAnimation {
2313
+ isAnimated = true
2314
+ }
2315
+ }
2316
+ }
2317
+ }
2318
+
2319
+ struct AsyncButton<Label: View>: View {
2320
+ let label: Label
2321
+ let action: () async -> Void
2322
+ @State private var isPerforming = false
2323
+
2324
+ init(_ titleKey: LocalizedStringKey, action: @escaping () async -> Void) where Label == Text {
2325
+ self.label = Text(titleKey)
2326
+ self.action = action
2327
+ }
2328
+
2329
+ init(action: @escaping () async -> Void, @ViewBuilder label: () -> Label) {
2330
+ self.label = label()
2331
+ self.action = action
2332
+ }
2333
+
2334
+ var body: some View {
2335
+ Button {
2336
+ Task {
2337
+ isPerforming = true
2338
+ defer { isPerforming = false }
2339
+ await action()
2340
+ }
2341
+ } label: {
2342
+ if isPerforming {
2343
+ ProgressView()
2344
+ .progressViewStyle(CircularProgressViewStyle(tint: .white))
2345
+ .scaleEffect(0.8)
2346
+ } else {
2347
+ label
2348
+ }
2349
+ }
2350
+ .disabled(isPerforming)
2351
+ }
2352
+ }
2353
+
2354
+ struct DataListView: View {
2355
+ let items: [DataItem]
2356
+ @State private var selectedItem: DataItem?
2357
+
2358
+ var body: some View {
2359
+ LazyVStack(spacing: 12) {
2360
+ ForEach(items) { item in
2361
+ DataRowView(item: item)
2362
+ .onTapGesture {
2363
+ selectedItem = item
2364
+ }
2365
+ .contextMenu {
2366
+ Button("Share") {
2367
+ shareItem(item)
2368
+ }
2369
+ Button("Delete", role: .destructive) {
2370
+ deleteItem(item)
2371
+ }
2372
+ }
2373
+ }
2374
+ }
2375
+ .sheet(item: $selectedItem) { item in
2376
+ DataDetailView(item: item)
2377
+ }
2378
+ }
2379
+
2380
+ private func shareItem(_ item: DataItem) {
2381
+ // Share implementation
2382
+ }
2383
+
2384
+ private func deleteItem(_ item: DataItem) {
2385
+ // Delete implementation
2386
+ }
2387
+ }
2388
+
2389
+ // MARK: - Observable Pattern with Combine
2390
+
2391
+ @MainActor
2392
+ class ContentViewModel: ObservableObject {
2393
+ @Published var items: [DataItem] = []
2394
+ @Published var isLoading = false
2395
+ @Published var errorMessage: String?
2396
+
2397
+ private let dataManager = DataManager()
2398
+ private let networkService = AsyncNetworkService()
2399
+ private var cancellables = Set<AnyCancellable>()
2400
+
2401
+ func initializeData() async {
2402
+ await loadData()
2403
+ setupSubscriptions()
2404
+ }
2405
+
2406
+ func loadData() async {
2407
+ isLoading = true
2408
+ defer { isLoading = false }
2409
+
2410
+ do {
2411
+ // Simulate network delay
2412
+ try await Task.sleep(nanoseconds: 2_000_000_000) // 2 seconds
2413
+
2414
+ let urls = [
2415
+ URL(string: "https://api.example.com/data1")!,
2416
+ URL(string: "https://api.example.com/data2")!,
2417
+ URL(string: "https://api.example.com/data3")!
2418
+ ]
2419
+
2420
+ let results = try await networkService.processWithTaskGroup(urls: urls)
2421
+
2422
+ items = results.enumerated().map { index, content in
2423
+ DataItem(id: UUID(), title: "Item \(index + 1)", content: content)
2424
+ }
2425
+
2426
+ // Store in actor-managed cache
2427
+ await dataManager.store(key: "cached_items", value: items)
2428
+
2429
+ } catch {
2430
+ errorMessage = error.localizedDescription
2431
+ }
2432
+ }
2433
+
2434
+ func refreshData() async {
2435
+ await loadData()
2436
+ }
2437
+
2438
+ private func setupSubscriptions() {
2439
+ // Combine reactive programming
2440
+ $items
2441
+ .debounce(for: .milliseconds(300), scheduler: RunLoop.main)
2442
+ .sink { items in
2443
+ print("Items updated: \(items.count)")
2444
+ }
2445
+ .store(in: &cancellables)
2446
+
2447
+ $errorMessage
2448
+ .compactMap { $0 }
2449
+ .sink { error in
2450
+ print("Error occurred: \(error)")
2451
+ }
2452
+ .store(in: &cancellables)
2453
+ }
2454
+ }
2455
+
2456
+ // MARK: - Data Models with Property Wrappers
2457
+
2458
+ struct DataItem: Identifiable, Codable {
2459
+ let id: UUID
2460
+ let title: String
2461
+ let content: String
2462
+ @CodingKey("created_at") let createdAt: Date = Date()
2463
+
2464
+ enum CodingKeys: String, CodingKey {
2465
+ case id, title, content
2466
+ case createdAt = "created_at"
2467
+ }
2468
+ }
2469
+
2470
+ // MARK: - Custom Property Wrappers
2471
+
2472
+ @propertyWrapper
2473
+ struct Capitalized {
2474
+ private var value: String
2475
+
2476
+ var wrappedValue: String {
2477
+ get { value }
2478
+ set { value = newValue.capitalized }
2479
+ }
2480
+
2481
+ init(wrappedValue: String) {
2482
+ self.value = wrappedValue.capitalized
2483
+ }
2484
+ }
2485
+
2486
+ @propertyWrapper
2487
+ struct UserDefaultsBacked<T: Codable> {
2488
+ let key: String
2489
+ let defaultValue: T
2490
+
2491
+ var wrappedValue: T {
2492
+ get {
2493
+ guard let data = UserDefaults.standard.data(forKey: key),
2494
+ let value = try? JSONDecoder().decode(T.self, from: data) else {
2495
+ return defaultValue
2496
+ }
2497
+ return value
2498
+ }
2499
+ set {
2500
+ guard let data = try? JSONEncoder().encode(newValue) else { return }
2501
+ UserDefaults.standard.set(data, forKey: key)
2502
+ }
2503
+ }
2504
+ }
2505
+
2506
+ // MARK: - Structured Concurrency Example
2507
+
2508
+ class ConcurrentDataProcessor {
2509
+ private let dataManager = DataManager()
2510
+
2511
+ func processLargeDataSet(_ data: [String]) async throws -> ProcessingResult {
2512
+ // Use structured concurrency for parallel processing
2513
+ return try await withThrowingTaskGroup(of: ProcessedChunk.self) { group in
2514
+ let chunks = data.chunked(into: 100) // Assume we have this extension
2515
+
2516
+ for (index, chunk) in chunks.enumerated() {
2517
+ group.addTask { [weak self] in
2518
+ guard let self = self else { throw ProcessingError.cancelled }
2519
+
2520
+ let processedData = try await self.dataManager.processData(chunk)
2521
+ return ProcessedChunk(index: index, data: processedData)
2522
+ }
2523
+ }
2524
+
2525
+ var results: [ProcessedChunk] = []
2526
+ for try await chunk in group {
2527
+ results.append(chunk)
2528
+ }
2529
+
2530
+ // Sort by index to maintain order
2531
+ results.sort { $0.index < $1.index }
2532
+ let finalData = results.flatMap { $0.data }
2533
+
2534
+ return ProcessingResult(
2535
+ totalItems: data.count,
2536
+ processedItems: finalData.count,
2537
+ data: finalData
2538
+ )
2539
+ }
2540
+ }
2541
+ }
2542
+
2543
+ // MARK: - Result Builders (Function Builders)
2544
+
2545
+ @resultBuilder
2546
+ struct ViewConfigBuilder {
2547
+ static func buildBlock(_ components: ViewConfig...) -> [ViewConfig] {
2548
+ components
2549
+ }
2550
+
2551
+ static func buildIf(_ component: ViewConfig?) -> ViewConfig? {
2552
+ component
2553
+ }
2554
+
2555
+ static func buildEither(first: ViewConfig) -> ViewConfig {
2556
+ first
2557
+ }
2558
+
2559
+ static func buildEither(second: ViewConfig) -> ViewConfig {
2560
+ second
2561
+ }
2562
+ }
2563
+
2564
+ struct ViewConfig {
2565
+ let name: String
2566
+ let properties: [String: Any]
2567
+
2568
+ init(name: String, properties: [String: Any] = [:]) {
2569
+ self.name = name
2570
+ self.properties = properties
2571
+ }
2572
+ }
2573
+
2574
+ func createView(@ViewConfigBuilder _ builder: () -> [ViewConfig]) -> UIView {
2575
+ let configs = builder()
2576
+ let view = UIView()
2577
+ // Apply configurations to view
2578
+ return view
2579
+ }
2580
+
2581
+ // MARK: - Supporting Types
2582
+
2583
+ struct ProcessedChunk {
2584
+ let index: Int
2585
+ let data: [String]
2586
+ }
2587
+
2588
+ struct ProcessingResult {
2589
+ let totalItems: Int
2590
+ let processedItems: Int
2591
+ let data: [String]
2592
+ }
2593
+
2594
+ enum ProcessingError: Error {
2595
+ case cancelled
2596
+ case invalidData
2597
+ case timeout
2598
+ }
2599
+
2600
+ enum NetworkError: Error {
2601
+ case invalidResponse
2602
+ case noData
2603
+ }
2604
+
2605
+ // MARK: - Extensions
2606
+
2607
+ extension Array {
2608
+ func chunked(into size: Int) -> [[Element]] {
2609
+ return stride(from: 0, to: count, by: size).map {
2610
+ Array(self[$0..<Swift.min($0 + size, count)])
2611
+ }
2612
+ }
2613
+ }
2614
+
2615
+ // MARK: - Protocol with Async Requirements
2616
+
2617
+ protocol AsyncDataProvider {
2618
+ associatedtype DataType: Codable
2619
+
2620
+ func fetchData() async throws -> [DataType]
2621
+ func updateData(_ data: [DataType]) async throws
2622
+ func deleteData(matching predicate: @escaping (DataType) -> Bool) async throws
2623
+ }
2624
+
2625
+ // MARK: - Generic Async Iterator
2626
+
2627
+ struct AsyncDataIterator<T>: AsyncIteratorProtocol, AsyncSequence {
2628
+ typealias Element = T
2629
+
2630
+ private let data: [T]
2631
+ private var index = 0
2632
+
2633
+ init(_ data: [T]) {
2634
+ self.data = data
2635
+ }
2636
+
2637
+ mutating func next() async -> T? {
2638
+ guard index < data.count else { return nil }
2639
+ defer { index += 1 }
2640
+
2641
+ // Simulate async delay
2642
+ try? await Task.sleep(nanoseconds: 10_000_000) // 10ms
2643
+ return data[index]
2644
+ }
2645
+
2646
+ func makeAsyncIterator() -> AsyncDataIterator<T> {
2647
+ return self
2648
+ }
2649
+ }
2650
+ "#;
2651
+
2652
+ fs::write(&test_file, content)?;
2653
+
2654
+ let ctx = TestContext::new();
2655
+ let output = ctx.run_probe(&[
2656
+ "search",
2657
+ "async", // Search for modern async features
2658
+ test_file.to_str().unwrap(),
2659
+ "--format",
2660
+ "outline",
2661
+ ])?;
2662
+
2663
+ // Should find modern Swift keywords and features
2664
+ let modern_features = [
2665
+ "async",
2666
+ "await",
2667
+ "actor",
2668
+ "@MainActor",
2669
+ "@Published",
2670
+ "@StateObject",
2671
+ "@State",
2672
+ ];
2673
+ let found_modern: Vec<&str> = modern_features
2674
+ .iter()
2675
+ .filter(|&feature| output.contains(feature))
2676
+ .copied()
2677
+ .collect();
2678
+
2679
+ assert!(
2680
+ !found_modern.is_empty(),
2681
+ "Should find modern Swift features. Found: {:?} - output: {}",
2682
+ found_modern,
2683
+ output
2684
+ );
2685
+
2686
+ // Should find SwiftUI-specific constructs
2687
+ let swiftui_features = [
2688
+ "View",
2689
+ "VStack",
2690
+ "NavigationStack",
2691
+ "Button",
2692
+ "@ViewBuilder",
2693
+ ];
2694
+ let found_swiftui: Vec<&str> = swiftui_features
2695
+ .iter()
2696
+ .filter(|&feature| output.contains(feature))
2697
+ .copied()
2698
+ .collect();
2699
+
2700
+ assert!(
2701
+ !found_swiftui.is_empty(),
2702
+ "Should find SwiftUI constructs. Found: {:?} - output: {}",
2703
+ found_swiftui,
2704
+ output
2705
+ );
2706
+
2707
+ // Should find structured concurrency patterns
2708
+ let concurrency_patterns = [
2709
+ "TaskGroup",
2710
+ "withThrowingTaskGroup",
2711
+ "Task.sleep",
2712
+ "async let",
2713
+ ];
2714
+ let found_concurrency: Vec<&str> = concurrency_patterns
2715
+ .iter()
2716
+ .filter(|&pattern| output.contains(pattern))
2717
+ .copied()
2718
+ .collect();
2719
+
2720
+ assert!(
2721
+ !found_concurrency.is_empty(),
2722
+ "Should find structured concurrency patterns. Found: {:?} - output: {}",
2723
+ found_concurrency,
2724
+ output
2725
+ );
2726
+
2727
+ // Should find property wrapper usage
2728
+ let property_wrapper_patterns = ["@propertyWrapper", "@UserDefaultsBacked", "@Capitalized"];
2729
+ let found_property_wrappers: Vec<&str> = property_wrapper_patterns
2730
+ .iter()
2731
+ .filter(|&pattern| output.contains(pattern))
2732
+ .copied()
2733
+ .collect();
2734
+
2735
+ assert!(
2736
+ !found_property_wrappers.is_empty(),
2737
+ "Should find property wrapper patterns. Found: {:?} - output: {}",
2738
+ found_property_wrappers,
2739
+ output
2740
+ );
2741
+
2742
+ // Should find Combine framework usage
2743
+ let combine_patterns = ["@Published", "AnyCancellable", "sink", "debounce"];
2744
+ let found_combine: Vec<&str> = combine_patterns
2745
+ .iter()
2746
+ .filter(|&pattern| output.contains(pattern))
2747
+ .copied()
2748
+ .collect();
2749
+
2750
+ // Note: Combine patterns might not always appear in outline search results
2751
+ if !found_combine.is_empty() {
2752
+ println!("Found Combine patterns: {:?}", found_combine);
2753
+ }
2754
+
2755
+ // Should find result builder usage
2756
+ let result_builder_patterns = ["@resultBuilder", "buildBlock", "ViewConfigBuilder"];
2757
+ let found_result_builders: Vec<&str> = result_builder_patterns
2758
+ .iter()
2759
+ .filter(|&pattern| output.contains(pattern))
2760
+ .copied()
2761
+ .collect();
2762
+
2763
+ // Note: Result builders might not always appear in outline search results
2764
+ if !found_result_builders.is_empty() {
2765
+ println!("Found result builder patterns: {:?}", found_result_builders);
2766
+ }
2767
+
2768
+ // Should be in outline format
2769
+ assert!(
2770
+ output.contains("---\nFile:"),
2771
+ "Missing file delimiter in outline format - output: {}",
2772
+ output
2773
+ );
2774
+
2775
+ Ok(())
2776
+ }
2777
+
2778
+ #[test]
2779
+ fn test_swift_outline_small_vs_large_functions_closing_braces() -> Result<()> {
2780
+ let temp_dir = TempDir::new()?;
2781
+ let test_file = temp_dir.path().join("FunctionSizes.swift");
2782
+
2783
+ let content = r#"import Foundation
2784
+
2785
+ // MARK: - Small Functions (should NOT get closing brace comments)
2786
+
2787
+ func simpleAdd(_ a: Int, _ b: Int) -> Int {
2788
+ return a + b
2789
+ }
2790
+
2791
+ func quickCheck(_ value: String) -> Bool {
2792
+ return !value.isEmpty
2793
+ }
2794
+
2795
+ func shortGreeting(_ name: String) -> String {
2796
+ return "Hello, \(name)!"
2797
+ }
2798
+
2799
+ func basicValidation(_ input: String) -> Bool {
2800
+ guard !input.isEmpty else { return false }
2801
+ return input.count >= 3
2802
+ }
2803
+
2804
+ func smallCalculation(_ numbers: [Int]) -> Int {
2805
+ return numbers.reduce(0, +)
2806
+ }
2807
+
2808
+ // MARK: - Medium Functions (might get closing brace comments depending on gaps)
2809
+
2810
+ func mediumProcessing(_ data: [String]) -> [String] {
2811
+ var results: [String] = []
2812
+
2813
+ for item in data {
2814
+ if item.hasPrefix("PROCESS_") {
2815
+ results.append(item.uppercased())
2816
+ } else if item.hasPrefix("SKIP_") {
2817
+ continue
2818
+ } else {
2819
+ results.append(item.lowercased())
2820
+ }
2821
+ }
2822
+
2823
+ return results.sorted()
2824
+ }
2825
+
2826
+ func mediumValidation(_ input: Any) -> ValidationResult {
2827
+ if let stringInput = input as? String {
2828
+ if stringInput.isEmpty {
2829
+ return .invalid("Empty string")
2830
+ } else if stringInput.count < 3 {
2831
+ return .invalid("Too short")
2832
+ } else {
2833
+ return .valid
2834
+ }
2835
+ } else if let numberInput = input as? NSNumber {
2836
+ let value = numberInput.doubleValue
2837
+ return value > 0 ? .valid : .invalid("Negative number")
2838
+ } else {
2839
+ return .invalid("Unsupported type")
2840
+ }
2841
+ }
2842
+
2843
+ // MARK: - Large Functions (should get closing brace comments with Swift // syntax)
2844
+
2845
+ func complexDataProcessing(_ dataset: [Any]) -> ProcessingResult {
2846
+ var processedItems: [ProcessedItem] = []
2847
+ var errors: [ProcessingError] = []
2848
+ var statistics = ProcessingStatistics()
2849
+
2850
+ // Phase 1: Initial validation and categorization
2851
+ for (index, item) in dataset.enumerated() {
2852
+ do {
2853
+ let validatedItem = try validateDataItem(item, at: index)
2854
+
2855
+ switch validatedItem.category {
2856
+ case .highPriority:
2857
+ statistics.highPriorityCount += 1
2858
+ processedItems.append(ProcessedItem(
2859
+ id: UUID(),
2860
+ originalIndex: index,
2861
+ data: validatedItem.data,
2862
+ priority: .high,
2863
+ processingTime: Date()
2864
+ ))
2865
+
2866
+ case .mediumPriority:
2867
+ statistics.mediumPriorityCount += 1
2868
+ processedItems.append(ProcessedItem(
2869
+ id: UUID(),
2870
+ originalIndex: index,
2871
+ data: validatedItem.data,
2872
+ priority: .medium,
2873
+ processingTime: Date()
2874
+ ))
2875
+
2876
+ case .lowPriority:
2877
+ statistics.lowPriorityCount += 1
2878
+ processedItems.append(ProcessedItem(
2879
+ id: UUID(),
2880
+ originalIndex: index,
2881
+ data: validatedItem.data,
2882
+ priority: .low,
2883
+ processingTime: Date()
2884
+ ))
2885
+
2886
+ case .deferred:
2887
+ statistics.deferredCount += 1
2888
+ // Deferred items are processed later
2889
+ continue
2890
+ }
2891
+ } catch {
2892
+ errors.append(ProcessingError(
2893
+ index: index,
2894
+ item: item,
2895
+ error: error,
2896
+ timestamp: Date()
2897
+ ))
2898
+ statistics.errorCount += 1
2899
+ }
2900
+ }
2901
+
2902
+ // Phase 2: Advanced processing for complex items
2903
+ var complexProcessedItems: [ProcessedItem] = []
2904
+ for item in processedItems {
2905
+ if item.priority == .high {
2906
+ // Complex processing for high priority items
2907
+ let enhancedData = performComplexTransformation(item.data)
2908
+ let analysisResult = performDeepAnalysis(enhancedData)
2909
+
2910
+ var updatedItem = item
2911
+ updatedItem.data = enhancedData
2912
+ updatedItem.analysisScore = analysisResult.score
2913
+ updatedItem.confidence = analysisResult.confidence
2914
+ updatedItem.metadata = analysisResult.metadata
2915
+
2916
+ complexProcessedItems.append(updatedItem)
2917
+ statistics.complexProcessingCount += 1
2918
+ } else {
2919
+ // Standard processing for lower priority items
2920
+ complexProcessedItems.append(item)
2921
+ }
2922
+ }
2923
+
2924
+ // Phase 3: Final validation and result compilation
2925
+ let finalResults = complexProcessedItems.compactMap { item -> ProcessedItem? in
2926
+ guard item.analysisScore > 0.5 else {
2927
+ statistics.rejectedCount += 1
2928
+ return nil
2929
+ }
2930
+
2931
+ statistics.acceptedCount += 1
2932
+ return item
2933
+ }
2934
+
2935
+ // Phase 4: Generate comprehensive report
2936
+ let processingReport = ProcessingReport(
2937
+ totalItemsProcessed: dataset.count,
2938
+ successfulItems: finalResults.count,
2939
+ errorCount: errors.count,
2940
+ statistics: statistics,
2941
+ processingDuration: Date().timeIntervalSince(statistics.startTime),
2942
+ qualityScore: calculateQualityScore(finalResults)
2943
+ )
2944
+
2945
+ return ProcessingResult(
2946
+ processedItems: finalResults,
2947
+ errors: errors,
2948
+ statistics: statistics,
2949
+ report: processingReport
2950
+ )
2951
+ }
2952
+
2953
+ func massiveDataTransformation(_ input: [ComplexDataStructure]) async throws -> [TransformedData] {
2954
+ var transformedResults: [TransformedData] = []
2955
+ let processor = AsyncDataProcessor()
2956
+ let validator = DataValidator()
2957
+ let enhancer = DataEnhancer()
2958
+
2959
+ // Batch processing configuration
2960
+ let batchSize = 100
2961
+ let maxConcurrentTasks = 4
2962
+ let timeout: TimeInterval = 300 // 5 minutes
2963
+
2964
+ // Initialize monitoring and logging
2965
+ let processingMonitor = ProcessingMonitor()
2966
+ await processingMonitor.startMonitoring()
2967
+
2968
+ defer {
2969
+ Task {
2970
+ await processingMonitor.stopMonitoring()
2971
+ }
2972
+ }
2973
+
2974
+ // Phase 1: Preprocessing and validation
2975
+ for (batchIndex, batch) in input.chunked(into: batchSize).enumerated() {
2976
+ await processingMonitor.logBatchStart(batchIndex, itemCount: batch.count)
2977
+
2978
+ do {
2979
+ // Parallel validation of batch items
2980
+ let validationResults = try await withThrowingTaskGroup(of: ValidationResult.self) { group in
2981
+ for item in batch {
2982
+ group.addTask {
2983
+ return try await validator.validateAsync(item)
2984
+ }
2985
+ }
2986
+
2987
+ var results: [ValidationResult] = []
2988
+ for try await result in group {
2989
+ results.append(result)
2990
+ }
2991
+ return results
2992
+ }
2993
+
2994
+ // Process validated items
2995
+ for (itemIndex, validationResult) in validationResults.enumerated() {
2996
+ let originalItem = batch[itemIndex]
2997
+
2998
+ switch validationResult.status {
2999
+ case .valid:
3000
+ // Transform valid items
3001
+ let transformedItem = try await processor.transform(originalItem)
3002
+ let enhancedItem = try await enhancer.enhance(transformedItem)
3003
+ transformedResults.append(enhancedItem)
3004
+
3005
+ case .validWithWarnings:
3006
+ // Handle items with warnings
3007
+ let transformedItem = try await processor.transformWithWarnings(originalItem, warnings: validationResult.warnings)
3008
+ transformedResults.append(transformedItem)
3009
+
3010
+ case .invalid:
3011
+ // Log invalid items for manual review
3012
+ await processingMonitor.logInvalidItem(originalItem, reason: validationResult.reason)
3013
+ continue
3014
+
3015
+ case .requiresManualReview:
3016
+ // Queue for manual review
3017
+ await processingMonitor.queueForManualReview(originalItem, notes: validationResult.notes)
3018
+ continue
3019
+ }
3020
+ }
3021
+
3022
+ await processingMonitor.logBatchCompletion(batchIndex, successCount: validationResults.count)
3023
+
3024
+ } catch {
3025
+ await processingMonitor.logBatchError(batchIndex, error: error)
3026
+ throw ProcessingError.batchProcessingFailed(batchIndex: batchIndex, underlyingError: error)
3027
+ }
3028
+
3029
+ // Rate limiting between batches
3030
+ if batchIndex < input.chunked(into: batchSize).count - 1 {
3031
+ try await Task.sleep(nanoseconds: 100_000_000) // 100ms delay
3032
+ }
3033
+ }
3034
+
3035
+ // Phase 2: Post-processing optimization
3036
+ let optimizedResults = try await optimizeTransformedData(transformedResults)
3037
+
3038
+ // Phase 3: Quality assurance
3039
+ let qualityResults = try await performQualityAssurance(optimizedResults)
3040
+
3041
+ // Phase 4: Final reporting
3042
+ let finalReport = await generateProcessingReport(
3043
+ originalCount: input.count,
3044
+ transformedCount: qualityResults.count,
3045
+ monitor: processingMonitor
3046
+ )
3047
+
3048
+ await processingMonitor.saveFinalReport(finalReport)
3049
+
3050
+ return qualityResults
3051
+ }
3052
+
3053
+ // MARK: - Helper Functions and Supporting Types
3054
+
3055
+ private func validateDataItem(_ item: Any, at index: Int) throws -> ValidatedDataItem {
3056
+ // Validation logic here
3057
+ return ValidatedDataItem(data: item, category: .mediumPriority)
3058
+ }
3059
+
3060
+ private func performComplexTransformation(_ data: Any) -> Any {
3061
+ // Complex transformation logic
3062
+ return data
3063
+ }
3064
+
3065
+ private func performDeepAnalysis(_ data: Any) -> AnalysisResult {
3066
+ return AnalysisResult(score: 0.8, confidence: 0.9, metadata: [:])
3067
+ }
3068
+
3069
+ private func calculateQualityScore(_ items: [ProcessedItem]) -> Double {
3070
+ guard !items.isEmpty else { return 0.0 }
3071
+ return items.map(\.analysisScore).reduce(0, +) / Double(items.count)
3072
+ }
3073
+
3074
+ private func optimizeTransformedData(_ data: [TransformedData]) async throws -> [TransformedData] {
3075
+ // Optimization logic
3076
+ return data
3077
+ }
3078
+
3079
+ private func performQualityAssurance(_ data: [TransformedData]) async throws -> [TransformedData] {
3080
+ // Quality assurance logic
3081
+ return data
3082
+ }
3083
+
3084
+ private func generateProcessingReport(originalCount: Int, transformedCount: Int, monitor: ProcessingMonitor) async -> ProcessingReport {
3085
+ return ProcessingReport(
3086
+ totalItemsProcessed: originalCount,
3087
+ successfulItems: transformedCount,
3088
+ errorCount: 0,
3089
+ statistics: ProcessingStatistics(),
3090
+ processingDuration: 0,
3091
+ qualityScore: 1.0
3092
+ )
3093
+ }
3094
+
3095
+ // MARK: - Supporting Data Structures
3096
+
3097
+ struct ProcessedItem {
3098
+ var id: UUID
3099
+ let originalIndex: Int
3100
+ var data: Any
3101
+ let priority: Priority
3102
+ let processingTime: Date
3103
+ var analysisScore: Double = 0.0
3104
+ var confidence: Double = 0.0
3105
+ var metadata: [String: Any] = [:]
3106
+ }
3107
+
3108
+ struct ProcessingResult {
3109
+ let processedItems: [ProcessedItem]
3110
+ let errors: [ProcessingError]
3111
+ let statistics: ProcessingStatistics
3112
+ let report: ProcessingReport
3113
+ }
3114
+
3115
+ struct ProcessingStatistics {
3116
+ var highPriorityCount = 0
3117
+ var mediumPriorityCount = 0
3118
+ var lowPriorityCount = 0
3119
+ var deferredCount = 0
3120
+ var errorCount = 0
3121
+ var complexProcessingCount = 0
3122
+ var rejectedCount = 0
3123
+ var acceptedCount = 0
3124
+ let startTime = Date()
3125
+ }
3126
+
3127
+ struct ProcessingReport {
3128
+ let totalItemsProcessed: Int
3129
+ let successfulItems: Int
3130
+ let errorCount: Int
3131
+ let statistics: ProcessingStatistics
3132
+ let processingDuration: TimeInterval
3133
+ let qualityScore: Double
3134
+ }
3135
+
3136
+ enum Priority {
3137
+ case high, medium, low
3138
+ }
3139
+
3140
+ enum ValidationStatus {
3141
+ case valid, validWithWarnings, invalid, requiresManualReview
3142
+ }
3143
+
3144
+ struct ValidationResult {
3145
+ let status: ValidationStatus
3146
+ let warnings: [String] = []
3147
+ let reason: String = ""
3148
+ let notes: [String] = []
3149
+ }
3150
+
3151
+ struct ValidatedDataItem {
3152
+ let data: Any
3153
+ let category: DataCategory
3154
+ }
3155
+
3156
+ enum DataCategory {
3157
+ case highPriority, mediumPriority, lowPriority, deferred
3158
+ }
3159
+
3160
+ struct ProcessingError: Error {
3161
+ let index: Int
3162
+ let item: Any
3163
+ let error: Error
3164
+ let timestamp: Date
3165
+
3166
+ static func batchProcessingFailed(batchIndex: Int, underlyingError: Error) -> ProcessingError {
3167
+ return ProcessingError(
3168
+ index: batchIndex,
3169
+ item: "Batch \(batchIndex)",
3170
+ error: underlyingError,
3171
+ timestamp: Date()
3172
+ )
3173
+ }
3174
+ }
3175
+
3176
+ struct ComplexDataStructure {
3177
+ let id: String
3178
+ let data: [String: Any]
3179
+ }
3180
+
3181
+ struct TransformedData {
3182
+ let id: String
3183
+ let transformedData: [String: Any]
3184
+ }
3185
+
3186
+ struct AnalysisResult {
3187
+ let score: Double
3188
+ let confidence: Double
3189
+ let metadata: [String: Any]
3190
+ }
3191
+
3192
+ // Mock classes for compilation
3193
+ class AsyncDataProcessor {
3194
+ func transform(_ item: ComplexDataStructure) async throws -> TransformedData {
3195
+ return TransformedData(id: item.id, transformedData: item.data)
3196
+ }
3197
+
3198
+ func transformWithWarnings(_ item: ComplexDataStructure, warnings: [String]) async throws -> TransformedData {
3199
+ return TransformedData(id: item.id, transformedData: item.data)
3200
+ }
3201
+ }
3202
+
3203
+ class DataValidator {
3204
+ func validateAsync(_ item: ComplexDataStructure) async throws -> ValidationResult {
3205
+ return ValidationResult(status: .valid)
3206
+ }
3207
+ }
3208
+
3209
+ class DataEnhancer {
3210
+ func enhance(_ item: TransformedData) async throws -> TransformedData {
3211
+ return item
3212
+ }
3213
+ }
3214
+
3215
+ actor ProcessingMonitor {
3216
+ func startMonitoring() async { }
3217
+ func stopMonitoring() async { }
3218
+ func logBatchStart(_ index: Int, itemCount: Int) async { }
3219
+ func logBatchCompletion(_ index: Int, successCount: Int) async { }
3220
+ func logBatchError(_ index: Int, error: Error) async { }
3221
+ func logInvalidItem(_ item: ComplexDataStructure, reason: String) async { }
3222
+ func queueForManualReview(_ item: ComplexDataStructure, notes: [String]) async { }
3223
+ func saveFinalReport(_ report: ProcessingReport) async { }
3224
+ }
3225
+ "#;
3226
+
3227
+ fs::write(&test_file, content)?;
3228
+
3229
+ let ctx = TestContext::new();
3230
+ let output = ctx.run_probe(&[
3231
+ "search",
3232
+ "function", // Search for functions
3233
+ test_file.to_str().unwrap(),
3234
+ "--format",
3235
+ "outline",
3236
+ ])?;
3237
+
3238
+ // Should find both small and large functions
3239
+ let small_functions = [
3240
+ "simpleAdd",
3241
+ "quickCheck",
3242
+ "shortGreeting",
3243
+ "basicValidation",
3244
+ "smallCalculation",
3245
+ ];
3246
+ let found_small: Vec<&str> = small_functions
3247
+ .iter()
3248
+ .filter(|&func| output.contains(func))
3249
+ .copied()
3250
+ .collect();
3251
+
3252
+ let large_functions = ["complexDataProcessing", "massiveDataTransformation"];
3253
+ let found_large: Vec<&str> = large_functions
3254
+ .iter()
3255
+ .filter(|&func| output.contains(func))
3256
+ .copied()
3257
+ .collect();
3258
+
3259
+ // Should find functions of various sizes
3260
+ assert!(
3261
+ !found_small.is_empty() || !found_large.is_empty(),
3262
+ "Should find functions of various sizes. Small: {:?}, Large: {:?} - output: {}",
3263
+ found_small,
3264
+ found_large,
3265
+ output
3266
+ );
3267
+
3268
+ // Check closing brace behavior - large functions should have them
3269
+ let has_closing_brace_comments = output.contains("} //");
3270
+ if !found_large.is_empty() {
3271
+ assert!(
3272
+ has_closing_brace_comments,
3273
+ "Large functions should have closing brace comments with Swift // syntax - output: {}",
3274
+ output
3275
+ );
3276
+ }
3277
+
3278
+ // Verify small functions do NOT have closing brace comments if they appear in output
3279
+ if !found_small.is_empty() {
3280
+ let small_func_lines: Vec<&str> = output
3281
+ .lines()
3282
+ .filter(|line| small_functions.iter().any(|&func| line.contains(func)))
3283
+ .collect();
3284
+
3285
+ // Check if any small function lines have closing brace comments
3286
+ let small_func_has_closing_comments = small_func_lines
3287
+ .iter()
3288
+ .any(|line| line.contains("} //") || line.contains("} /*"));
3289
+
3290
+ // Small functions should NOT have closing brace comments
3291
+ if small_func_has_closing_comments {
3292
+ println!("Warning: Small functions appear to have closing brace comments");
3293
+ }
3294
+ }
3295
+
3296
+ // Should detect different function complexity levels
3297
+ let complexity_indicators = ["Phase", "batch", "async", "await", "complex", "validation"];
3298
+ let found_complexity: Vec<&str> = complexity_indicators
3299
+ .iter()
3300
+ .filter(|&indicator| output.contains(indicator))
3301
+ .copied()
3302
+ .collect();
3303
+
3304
+ assert!(
3305
+ !found_complexity.is_empty(),
3306
+ "Should detect function complexity indicators. Found: {:?} - output: {}",
3307
+ found_complexity,
3308
+ output
3309
+ );
3310
+
3311
+ // Should be in outline format
3312
+ assert!(
3313
+ output.contains("---\nFile:"),
3314
+ "Missing file delimiter in outline format - output: {}",
3315
+ output
3316
+ );
3317
+
3318
+ Ok(())
3319
+ }