autosnippet 3.2.21 → 3.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dashboard/dist/assets/icons-BJ2mUBi8.js +1 -0
- package/dashboard/dist/assets/index-B659K9t5.js +128 -0
- package/dashboard/dist/assets/index-NCm40PMD.css +1 -0
- package/dashboard/dist/index.html +3 -3
- package/dist/bin/cli.d.ts +1 -1
- package/dist/bin/cli.js +244 -261
- package/dist/lib/agent/context/ExplorationTracker.d.ts +2 -0
- package/dist/lib/agent/context/ExplorationTracker.js +21 -3
- package/dist/lib/agent/core/ToolExecutionPipeline.d.ts +3 -1
- package/dist/lib/agent/core/ToolExecutionPipeline.js +8 -1
- package/dist/lib/agent/forge/DynamicComposer.d.ts +58 -0
- package/dist/lib/agent/forge/DynamicComposer.js +99 -0
- package/dist/lib/agent/forge/SandboxRunner.d.ts +60 -0
- package/dist/lib/agent/forge/SandboxRunner.js +251 -0
- package/dist/lib/agent/forge/TemporaryToolRegistry.d.ts +76 -0
- package/dist/lib/agent/forge/TemporaryToolRegistry.js +154 -0
- package/dist/lib/agent/forge/ToolForge.d.ts +92 -0
- package/dist/lib/agent/forge/ToolForge.js +239 -0
- package/dist/lib/agent/forge/ToolRequirementAnalyzer.d.ts +44 -0
- package/dist/lib/agent/forge/ToolRequirementAnalyzer.js +119 -0
- package/dist/lib/agent/tools/ToolRegistry.d.ts +2 -0
- package/dist/lib/agent/tools/ToolRegistry.js +4 -0
- package/dist/lib/agent/tools/composite.js +0 -1
- package/dist/lib/agent/tools/index.d.ts +2 -50
- package/dist/lib/agent/tools/index.js +2 -3
- package/dist/lib/agent/tools/lifecycle.d.ts +1 -58
- package/dist/lib/agent/tools/lifecycle.js +2 -75
- package/dist/lib/cli/SetupService.d.ts +46 -2
- package/dist/lib/cli/SetupService.js +2 -27
- package/dist/lib/cli/deploy/FileManifest.d.ts +0 -21
- package/dist/lib/cli/deploy/FileManifest.js +0 -11
- package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.d.ts +2 -5
- package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.js +159 -44
- package/dist/lib/core/discovery/index.d.ts +1 -1
- package/dist/lib/core/discovery/index.js +2 -2
- package/dist/lib/domain/knowledge/KnowledgeEntry.d.ts +10 -0
- package/dist/lib/domain/knowledge/KnowledgeEntry.js +2 -0
- package/dist/lib/domain/knowledge/Lifecycle.d.ts +19 -2
- package/dist/lib/domain/knowledge/Lifecycle.js +32 -6
- package/dist/lib/domain/knowledge/UnifiedValidator.d.ts +1 -5
- package/dist/lib/domain/knowledge/UnifiedValidator.js +7 -44
- package/dist/lib/domain/knowledge/values/Stats.d.ts +29 -0
- package/dist/lib/domain/knowledge/values/Stats.js +41 -0
- package/dist/lib/external/mcp/McpServer.d.ts +19 -38
- package/dist/lib/external/mcp/McpServer.js +145 -117
- package/dist/lib/external/mcp/autoApproveInjector.js +0 -2
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.d.ts +26 -1
- package/dist/lib/external/mcp/handlers/bootstrap/MissionBriefingBuilder.js +41 -0
- package/dist/lib/external/mcp/handlers/bootstrap/pipeline/orchestrator.js +49 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.d.ts +3 -0
- package/dist/lib/external/mcp/handlers/bootstrap/shared/bootstrap-phases.js +27 -0
- package/dist/lib/external/mcp/handlers/bootstrap/skills.js +1 -1
- package/dist/lib/external/mcp/handlers/bootstrap-external.js +1 -0
- package/dist/lib/external/mcp/handlers/bootstrap-internal.js +2 -0
- package/dist/lib/external/mcp/handlers/consolidated.d.ts +116 -6
- package/dist/lib/external/mcp/handlers/consolidated.js +251 -71
- package/dist/lib/external/mcp/handlers/guard.d.ts +150 -0
- package/dist/lib/external/mcp/handlers/guard.js +245 -8
- package/dist/lib/external/mcp/handlers/knowledge.d.ts +0 -29
- package/dist/lib/external/mcp/handlers/knowledge.js +1 -76
- package/dist/lib/external/mcp/handlers/panorama.d.ts +36 -0
- package/dist/lib/external/mcp/handlers/panorama.js +156 -0
- package/dist/lib/external/mcp/handlers/system.d.ts +2 -54
- package/dist/lib/external/mcp/handlers/system.js +3 -113
- package/dist/lib/external/mcp/handlers/task.d.ts +13 -24
- package/dist/lib/external/mcp/handlers/task.js +217 -557
- package/dist/lib/external/mcp/handlers/types.d.ts +91 -8
- package/dist/lib/external/mcp/handlers/types.js +18 -1
- package/dist/lib/external/mcp/handlers/wiki-external.d.ts +18 -1
- package/dist/lib/external/mcp/handlers/wiki-external.js +16 -1
- package/dist/lib/external/mcp/tools.d.ts +14 -20
- package/dist/lib/external/mcp/tools.js +62 -91
- package/dist/lib/http/HttpServer.js +52 -6
- package/dist/lib/http/routes/{snippets.d.ts → audit.d.ts} +4 -2
- package/dist/lib/http/routes/audit.js +51 -0
- package/dist/lib/http/routes/commands.d.ts +1 -1
- package/dist/lib/http/routes/commands.js +1 -66
- package/dist/lib/http/routes/guardReport.d.ts +10 -0
- package/dist/lib/http/routes/guardReport.js +143 -0
- package/dist/lib/http/routes/knowledge.js +32 -1
- package/dist/lib/http/routes/panorama.d.ts +11 -0
- package/dist/lib/http/routes/panorama.js +322 -0
- package/dist/lib/http/routes/remote.js +0 -5
- package/dist/lib/http/routes/signals.d.ts +10 -0
- package/dist/lib/http/routes/signals.js +104 -0
- package/dist/lib/http/routes/task.d.ts +2 -3
- package/dist/lib/http/routes/task.js +17 -347
- package/dist/lib/http/routes/violations.js +1 -1
- package/dist/lib/infrastructure/audit/AuditLogger.d.ts +6 -1
- package/dist/lib/infrastructure/audit/AuditLogger.js +14 -1
- package/dist/lib/infrastructure/database/drizzle/schema.d.ts +181 -583
- package/dist/lib/infrastructure/database/drizzle/schema.js +28 -69
- package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.d.ts +8 -0
- package/dist/lib/infrastructure/database/migrations/004_evolution_proposals.js +43 -0
- package/dist/lib/infrastructure/logging/Logger.d.ts +2 -0
- package/dist/lib/infrastructure/logging/Logger.js +34 -7
- package/dist/lib/infrastructure/monitoring/ErrorTracker.js +3 -1
- package/dist/lib/infrastructure/monitoring/PerformanceMonitor.d.ts +2 -2
- package/dist/lib/infrastructure/monitoring/PerformanceMonitor.js +12 -10
- package/dist/lib/infrastructure/notification/LarkNotifier.d.ts +24 -0
- package/dist/lib/infrastructure/notification/LarkNotifier.js +97 -0
- package/dist/lib/infrastructure/report/ReportStore.d.ts +45 -0
- package/dist/lib/infrastructure/report/ReportStore.js +133 -0
- package/dist/lib/infrastructure/signal/SignalAggregator.d.ts +18 -0
- package/dist/lib/infrastructure/signal/SignalAggregator.js +84 -0
- package/dist/lib/infrastructure/signal/SignalBridge.d.ts +13 -0
- package/dist/lib/infrastructure/signal/SignalBridge.js +20 -0
- package/dist/lib/infrastructure/signal/SignalBus.d.ts +63 -0
- package/dist/lib/infrastructure/signal/SignalBus.js +106 -0
- package/dist/lib/infrastructure/signal/SignalTraceWriter.d.ts +36 -0
- package/dist/lib/infrastructure/signal/SignalTraceWriter.js +130 -0
- package/dist/lib/injection/ServiceContainer.js +6 -0
- package/dist/lib/injection/ServiceMap.d.ts +16 -19
- package/dist/lib/injection/modules/AgentModule.d.ts +1 -1
- package/dist/lib/injection/modules/AgentModule.js +7 -1
- package/dist/lib/injection/modules/AppModule.d.ts +3 -4
- package/dist/lib/injection/modules/AppModule.js +7 -43
- package/dist/lib/injection/modules/GuardModule.js +59 -2
- package/dist/lib/injection/modules/InfraModule.d.ts +0 -1
- package/dist/lib/injection/modules/InfraModule.js +9 -7
- package/dist/lib/injection/modules/KnowledgeModule.js +51 -0
- package/dist/lib/injection/modules/PanoramaModule.d.ts +18 -0
- package/dist/lib/injection/modules/PanoramaModule.js +76 -0
- package/dist/lib/injection/modules/SignalModule.d.ts +10 -0
- package/dist/lib/injection/modules/SignalModule.js +84 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.d.ts +1 -0
- package/dist/lib/repository/knowledge/KnowledgeRepository.impl.js +6 -0
- package/dist/lib/service/bootstrap/BootstrapTaskManager.d.ts +3 -1
- package/dist/lib/service/bootstrap/BootstrapTaskManager.js +20 -1
- package/dist/lib/service/delivery/AgentInstructionsGenerator.js +4 -5
- package/dist/lib/service/delivery/CursorDeliveryPipeline.d.ts +3 -1
- package/dist/lib/service/delivery/CursorDeliveryPipeline.js +13 -10
- package/dist/lib/service/delivery/RulesGenerator.js +3 -2
- package/dist/lib/service/evolution/ConsolidationAdvisor.d.ts +114 -0
- package/dist/lib/service/evolution/ConsolidationAdvisor.js +542 -0
- package/dist/lib/service/evolution/ContradictionDetector.d.ts +54 -0
- package/dist/lib/service/evolution/ContradictionDetector.js +253 -0
- package/dist/lib/service/evolution/DecayDetector.d.ts +71 -0
- package/dist/lib/service/evolution/DecayDetector.js +244 -0
- package/dist/lib/service/evolution/EnhancementSuggester.d.ts +38 -0
- package/dist/lib/service/evolution/EnhancementSuggester.js +220 -0
- package/dist/lib/service/evolution/KnowledgeMetabolism.d.ts +82 -0
- package/dist/lib/service/evolution/KnowledgeMetabolism.js +167 -0
- package/dist/lib/service/evolution/RedundancyAnalyzer.d.ts +53 -0
- package/dist/lib/service/evolution/RedundancyAnalyzer.js +210 -0
- package/dist/lib/service/evolution/StagingManager.d.ts +57 -0
- package/dist/lib/service/evolution/StagingManager.js +201 -0
- package/dist/lib/service/guard/ComplianceReporter.d.ts +42 -2
- package/dist/lib/service/guard/ComplianceReporter.js +43 -5
- package/dist/lib/service/guard/CoverageAnalyzer.d.ts +54 -0
- package/dist/lib/service/guard/CoverageAnalyzer.js +149 -0
- package/dist/lib/service/guard/GuardCheckEngine.d.ts +55 -1
- package/dist/lib/service/guard/GuardCheckEngine.js +508 -15
- package/dist/lib/service/guard/GuardFeedbackLoop.d.ts +3 -0
- package/dist/lib/service/guard/GuardFeedbackLoop.js +9 -0
- package/dist/lib/service/guard/ReverseGuard.d.ts +73 -0
- package/dist/lib/service/guard/ReverseGuard.js +256 -0
- package/dist/lib/service/guard/RuleLearner.d.ts +12 -0
- package/dist/lib/service/guard/RuleLearner.js +38 -0
- package/dist/lib/service/guard/UncertaintyCollector.d.ts +83 -0
- package/dist/lib/service/guard/UncertaintyCollector.js +149 -0
- package/dist/lib/service/guard/ViolationsStore.d.ts +1 -0
- package/dist/lib/service/guard/ViolationsStore.js +33 -3
- package/dist/lib/service/knowledge/ConfidenceRouter.d.ts +13 -0
- package/dist/lib/service/knowledge/ConfidenceRouter.js +14 -0
- package/dist/lib/service/knowledge/KnowledgeService.js +22 -4
- package/dist/lib/service/module/ModuleService.js +3 -13
- package/dist/lib/service/panorama/CouplingAnalyzer.d.ts +27 -0
- package/dist/lib/service/panorama/CouplingAnalyzer.js +192 -0
- package/dist/lib/service/panorama/DimensionAnalyzer.d.ts +28 -0
- package/dist/lib/service/panorama/DimensionAnalyzer.js +320 -0
- package/dist/lib/service/panorama/LayerInferrer.d.ts +19 -0
- package/dist/lib/service/panorama/LayerInferrer.js +182 -0
- package/dist/lib/service/panorama/ModuleDiscoverer.d.ts +24 -0
- package/dist/lib/service/panorama/ModuleDiscoverer.js +185 -0
- package/dist/lib/service/panorama/PanoramaAggregator.d.ts +29 -0
- package/dist/lib/service/panorama/PanoramaAggregator.js +228 -0
- package/dist/lib/service/panorama/PanoramaScanner.d.ts +52 -0
- package/dist/lib/service/panorama/PanoramaScanner.js +188 -0
- package/dist/lib/service/panorama/PanoramaService.d.ts +108 -0
- package/dist/lib/service/panorama/PanoramaService.js +220 -0
- package/dist/lib/service/panorama/PanoramaTypes.d.ts +134 -0
- package/dist/lib/service/panorama/PanoramaTypes.js +6 -0
- package/dist/lib/service/panorama/RoleRefiner.d.ts +48 -0
- package/dist/lib/service/panorama/RoleRefiner.js +535 -0
- package/dist/lib/service/search/MultiSignalRanker.d.ts +1 -0
- package/dist/lib/service/search/MultiSignalRanker.js +16 -0
- package/dist/lib/service/search/SearchEngine.d.ts +1 -0
- package/dist/lib/service/search/SearchEngine.js +9 -1
- package/dist/lib/service/search/SearchTypes.d.ts +2 -0
- package/dist/lib/service/signal/HitRecorder.d.ts +68 -0
- package/dist/lib/service/signal/HitRecorder.js +173 -0
- package/dist/lib/service/skills/SignalCollector.d.ts +3 -1
- package/dist/lib/service/skills/SignalCollector.js +31 -1
- package/dist/lib/service/task/IntentExtractor.d.ts +58 -0
- package/dist/lib/service/task/IntentExtractor.js +142 -0
- package/dist/lib/service/task/PrimeSearchPipeline.d.ts +54 -0
- package/dist/lib/service/task/PrimeSearchPipeline.js +98 -0
- package/dist/lib/shared/constants.d.ts +0 -15
- package/dist/lib/shared/constants.js +0 -10
- package/dist/lib/shared/schemas/config.d.ts +4 -1
- package/dist/lib/shared/schemas/config.js +8 -1
- package/dist/lib/shared/schemas/mcp-tools.d.ts +41 -96
- package/dist/lib/shared/schemas/mcp-tools.js +59 -119
- package/dist/scripts/analyze-signals.d.ts +20 -0
- package/dist/scripts/analyze-signals.js +155 -0
- package/dist/scripts/diagnose-mcp.js +1 -1
- package/dist/scripts/release.js +2 -10
- package/package.json +4 -19
- package/skills/autosnippet-devdocs/SKILL.md +11 -8
- package/templates/claude-code/hooks/autosnippet-session.sh +10 -15
- package/templates/cursor-hooks/hooks/session-start.sh +1 -1
- package/templates/instructions/agent-static.md +2 -1
- package/templates/instructions/conventions.md +5 -6
- package/templates/recipes-setup/README.md +1 -2
- package/dashboard/dist/assets/icons-C1dUryS-.js +0 -1
- package/dashboard/dist/assets/index-D0whuycy.css +0 -1
- package/dashboard/dist/assets/index-DdvZE4Yd.js +0 -128
- package/dist/lib/domain/task/Task.d.ts +0 -140
- package/dist/lib/domain/task/Task.js +0 -254
- package/dist/lib/domain/task/TaskDependency.d.ts +0 -23
- package/dist/lib/domain/task/TaskDependency.js +0 -34
- package/dist/lib/domain/task/TaskIdGenerator.d.ts +0 -40
- package/dist/lib/domain/task/TaskIdGenerator.js +0 -75
- package/dist/lib/domain/task/index.d.ts +0 -4
- package/dist/lib/domain/task/index.js +0 -4
- package/dist/lib/http/routes/snippets.js +0 -49
- package/dist/lib/infrastructure/database/migrations/002_add_tasks.d.ts +0 -11
- package/dist/lib/infrastructure/database/migrations/002_add_tasks.js +0 -86
- package/dist/lib/platform/ClipboardManager.d.ts +0 -24
- package/dist/lib/platform/ClipboardManager.js +0 -142
- package/dist/lib/platform/NativeUi.d.ts +0 -53
- package/dist/lib/platform/NativeUi.js +0 -284
- package/dist/lib/platform/ios/index.d.ts +0 -38
- package/dist/lib/platform/ios/index.js +0 -42
- package/dist/lib/platform/ios/routes/spm.d.ts +0 -9
- package/dist/lib/platform/ios/routes/spm.js +0 -371
- package/dist/lib/platform/ios/snippet/PlaceholderConverter.d.ts +0 -21
- package/dist/lib/platform/ios/snippet/PlaceholderConverter.js +0 -48
- package/dist/lib/platform/ios/snippet/XcodeCodec.d.ts +0 -23
- package/dist/lib/platform/ios/snippet/XcodeCodec.js +0 -96
- package/dist/lib/platform/ios/spm/DependencyGraph.d.ts +0 -56
- package/dist/lib/platform/ios/spm/DependencyGraph.js +0 -195
- package/dist/lib/platform/ios/spm/PackageSwiftParser.d.ts +0 -69
- package/dist/lib/platform/ios/spm/PackageSwiftParser.js +0 -231
- package/dist/lib/platform/ios/spm/PathFinder.d.ts +0 -28
- package/dist/lib/platform/ios/spm/PathFinder.js +0 -117
- package/dist/lib/platform/ios/spm/PolicyEngine.d.ts +0 -44
- package/dist/lib/platform/ios/spm/PolicyEngine.js +0 -79
- package/dist/lib/platform/ios/spm/SpmHelper.d.ts +0 -102
- package/dist/lib/platform/ios/spm/SpmHelper.js +0 -464
- package/dist/lib/platform/ios/xcode/HeaderResolver.d.ts +0 -33
- package/dist/lib/platform/ios/xcode/HeaderResolver.js +0 -90
- package/dist/lib/platform/ios/xcode/SaveEventFilter.d.ts +0 -66
- package/dist/lib/platform/ios/xcode/SaveEventFilter.js +0 -142
- package/dist/lib/platform/ios/xcode/XcodeAutomation.d.ts +0 -71
- package/dist/lib/platform/ios/xcode/XcodeAutomation.js +0 -327
- package/dist/lib/platform/ios/xcode/XcodeImportResolver.d.ts +0 -130
- package/dist/lib/platform/ios/xcode/XcodeImportResolver.js +0 -404
- package/dist/lib/platform/ios/xcode/XcodeIntegration.d.ts +0 -89
- package/dist/lib/platform/ios/xcode/XcodeIntegration.js +0 -588
- package/dist/lib/platform/ios/xcode/XcodeWriteUtils.d.ts +0 -99
- package/dist/lib/platform/ios/xcode/XcodeWriteUtils.js +0 -190
- package/dist/lib/repository/task/TaskRepository.impl.d.ts +0 -171
- package/dist/lib/repository/task/TaskRepository.impl.js +0 -347
- package/dist/lib/service/automation/ActionPipeline.d.ts +0 -34
- package/dist/lib/service/automation/ActionPipeline.js +0 -53
- package/dist/lib/service/automation/AutomationOrchestrator.d.ts +0 -86
- package/dist/lib/service/automation/AutomationOrchestrator.js +0 -57
- package/dist/lib/service/automation/ContextCollector.d.ts +0 -24
- package/dist/lib/service/automation/ContextCollector.js +0 -35
- package/dist/lib/service/automation/DirectiveDetector.d.ts +0 -51
- package/dist/lib/service/automation/DirectiveDetector.js +0 -112
- package/dist/lib/service/automation/FileWatcher.d.ts +0 -51
- package/dist/lib/service/automation/FileWatcher.js +0 -366
- package/dist/lib/service/automation/TriggerResolver.d.ts +0 -36
- package/dist/lib/service/automation/TriggerResolver.js +0 -62
- package/dist/lib/service/automation/handlers/AlinkHandler.d.ts +0 -7
- package/dist/lib/service/automation/handlers/AlinkHandler.js +0 -80
- package/dist/lib/service/automation/handlers/CreateHandler.d.ts +0 -11
- package/dist/lib/service/automation/handlers/CreateHandler.js +0 -170
- package/dist/lib/service/automation/handlers/GuardHandler.d.ts +0 -17
- package/dist/lib/service/automation/handlers/GuardHandler.js +0 -218
- package/dist/lib/service/automation/handlers/HeaderHandler.d.ts +0 -2
- package/dist/lib/service/automation/handlers/HeaderHandler.js +0 -32
- package/dist/lib/service/automation/handlers/SearchHandler.d.ts +0 -11
- package/dist/lib/service/automation/handlers/SearchHandler.js +0 -278
- package/dist/lib/service/snippet/SnippetFactory.d.ts +0 -101
- package/dist/lib/service/snippet/SnippetFactory.js +0 -145
- package/dist/lib/service/snippet/SnippetInstaller.d.ts +0 -91
- package/dist/lib/service/snippet/SnippetInstaller.js +0 -276
- package/dist/lib/service/snippet/codecs/SnippetCodec.d.ts +0 -44
- package/dist/lib/service/snippet/codecs/SnippetCodec.js +0 -35
- package/dist/lib/service/snippet/codecs/VSCodeCodec.d.ts +0 -27
- package/dist/lib/service/snippet/codecs/VSCodeCodec.js +0 -82
- package/dist/lib/service/task/TaskGraphService.d.ts +0 -222
- package/dist/lib/service/task/TaskGraphService.js +0 -597
- package/dist/lib/service/task/TaskKnowledgeBridge.d.ts +0 -95
- package/dist/lib/service/task/TaskKnowledgeBridge.js +0 -298
- package/dist/lib/service/task/TaskReadyEngine.d.ts +0 -84
- package/dist/lib/service/task/TaskReadyEngine.js +0 -115
- package/dist/scripts/build-native-ui.d.ts +0 -3
- package/dist/scripts/build-native-ui.js +0 -62
- package/dist/scripts/init-snippets.d.ts +0 -30
- package/dist/scripts/init-snippets.js +0 -298
- package/dist/scripts/install-full.d.ts +0 -7
- package/dist/scripts/install-full.js +0 -38
- package/resources/native-ui/README.md +0 -29
- package/resources/native-ui/combined-window.swift +0 -494
- package/resources/native-ui/main.swift +0 -598
- package/scripts/postinstall-safe.mjs +0 -89
|
@@ -1,588 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* XcodeIntegration — Xcode IDE 代码自动插入服务
|
|
3
|
-
*
|
|
4
|
-
* 核心能力:
|
|
5
|
-
* §1 import 语句解析 — 支持 ObjC (#import/#include/@import) 和 Swift (import)
|
|
6
|
-
* §2 头文件搜索 — 在 target 源目录中递归查找头文件并计算相对路径
|
|
7
|
-
* §3 import 格式化 — 根据 同target/跨target 关系生成正确的引号/尖括号格式
|
|
8
|
-
* §4 三级去重 — 精确匹配 → 模块匹配 → 相似头文件名匹配
|
|
9
|
-
* §5 SPM 依赖决策 — block(循环依赖) / review(缺失可补) / continue(已存在)
|
|
10
|
-
* §6 Xcode 自动插入 — osascript 跳转+粘贴,保持 Undo 可用
|
|
11
|
-
* §7 文件写入回退 — Xcode 失败时直接写文件,Xcode 自动 reload
|
|
12
|
-
* §8 粘贴行号偏移 — headers 插入后自动修正代码粘贴位置
|
|
13
|
-
* §9 完整插入流程 — cut 触发行 → preflight → headers → offset → paste
|
|
14
|
-
*/
|
|
15
|
-
import { readFileSync, writeFileSync } from 'node:fs';
|
|
16
|
-
import { saveEventFilter } from './SaveEventFilter.js';
|
|
17
|
-
import { checkImportStatus, collectImportsFromFile, collectImportsFromHeaderFile, inferModulesFromHeaders, resolveHeaderFormat, } from './XcodeImportResolver.js';
|
|
18
|
-
import { computePasteLineNumber, evaluateDepResult, handleDepReview, sleep, withAutoSnippetNote, writeImportLineFile, writeImportLineXcode, } from './XcodeWriteUtils.js';
|
|
19
|
-
/** 常见 Apple 系统框架(无需 SPM 依赖检查) */
|
|
20
|
-
const _SYSTEM_FRAMEWORKS = new Set([
|
|
21
|
-
'Foundation',
|
|
22
|
-
'UIKit',
|
|
23
|
-
'AppKit',
|
|
24
|
-
'SwiftUI',
|
|
25
|
-
'Combine',
|
|
26
|
-
'CoreFoundation',
|
|
27
|
-
'CoreGraphics',
|
|
28
|
-
'CoreData',
|
|
29
|
-
'CoreAnimation',
|
|
30
|
-
'CoreLocation',
|
|
31
|
-
'CoreMedia',
|
|
32
|
-
'CoreImage',
|
|
33
|
-
'CoreText',
|
|
34
|
-
'CoreVideo',
|
|
35
|
-
'QuartzCore',
|
|
36
|
-
'AVFoundation',
|
|
37
|
-
'AVKit',
|
|
38
|
-
'WebKit',
|
|
39
|
-
'MapKit',
|
|
40
|
-
'Metal',
|
|
41
|
-
'MetalKit',
|
|
42
|
-
'ARKit',
|
|
43
|
-
'SceneKit',
|
|
44
|
-
'SpriteKit',
|
|
45
|
-
'GameKit',
|
|
46
|
-
'GameplayKit',
|
|
47
|
-
'HealthKit',
|
|
48
|
-
'HomeKit',
|
|
49
|
-
'CloudKit',
|
|
50
|
-
'StoreKit',
|
|
51
|
-
'PhotosUI',
|
|
52
|
-
'Photos',
|
|
53
|
-
'Contacts',
|
|
54
|
-
'ContactsUI',
|
|
55
|
-
'EventKit',
|
|
56
|
-
'UserNotifications',
|
|
57
|
-
'MessageUI',
|
|
58
|
-
'MultipeerConnectivity',
|
|
59
|
-
'NetworkExtension',
|
|
60
|
-
'SafariServices',
|
|
61
|
-
'AuthenticationServices',
|
|
62
|
-
'LocalAuthentication',
|
|
63
|
-
'Security',
|
|
64
|
-
'CryptoKit',
|
|
65
|
-
'Accelerate',
|
|
66
|
-
'os',
|
|
67
|
-
'Darwin',
|
|
68
|
-
'ObjectiveC',
|
|
69
|
-
'Dispatch',
|
|
70
|
-
'XCTest',
|
|
71
|
-
]);
|
|
72
|
-
// ═══════════════════════════════════════════════════════════════
|
|
73
|
-
// §10 导出:insertHeaders
|
|
74
|
-
// ═══════════════════════════════════════════════════════════════
|
|
75
|
-
/**
|
|
76
|
-
* 统一的头文件插入方法
|
|
77
|
-
*
|
|
78
|
-
* 逐条处理:
|
|
79
|
-
* 1. 三级去重
|
|
80
|
-
* 2. SPM 依赖检查(block/review/continue 决策)
|
|
81
|
-
* 3. Xcode osascript 自动插入,失败则文件写入回退
|
|
82
|
-
* 4. 附加 AutoSnippet 注释后缀
|
|
83
|
-
*
|
|
84
|
-
* @param fullPath 目标文件绝对路径
|
|
85
|
-
* @param headers 待插入的 import 行数组
|
|
86
|
-
* @returns >}
|
|
87
|
-
*/
|
|
88
|
-
export async function insertHeaders(watcher, fullPath, headers, opts = {}) {
|
|
89
|
-
const XA = await import('./XcodeAutomation.js');
|
|
90
|
-
const CM = await import('../../ClipboardManager.js');
|
|
91
|
-
const NU = (await import('../../NativeUi.js'));
|
|
92
|
-
const result = { inserted: [], skipped: [], cancelled: false };
|
|
93
|
-
/** 模块名 → 提示注释('提示操作插入'按钮选择时记录) */
|
|
94
|
-
const depWarnings = opts.depWarnings instanceof Map ? new Map(opts.depWarnings) : new Map();
|
|
95
|
-
if (!headers || headers.length === 0) {
|
|
96
|
-
return result;
|
|
97
|
-
}
|
|
98
|
-
const isSwift = opts.isSwift ?? fullPath.endsWith('.swift');
|
|
99
|
-
// ── Step 1: 收集已有 imports ──
|
|
100
|
-
const importArray = collectImportsFromFile(fullPath, isSwift);
|
|
101
|
-
// .m 文件还要收集对应 .h 的 imports
|
|
102
|
-
if (!isSwift && !fullPath.endsWith('.h')) {
|
|
103
|
-
collectImportsFromHeaderFile(fullPath, importArray);
|
|
104
|
-
}
|
|
105
|
-
// ── Step 2: SPM/模块 服务准备 ──
|
|
106
|
-
// 优先复用 opts 传入的 spmService/currentTarget(避免与 _preflightDeps 重复 load)
|
|
107
|
-
let spmService = opts._spmService || null;
|
|
108
|
-
let currentTarget = opts._currentTarget || null;
|
|
109
|
-
if (!spmService && !opts.skipDepCheck) {
|
|
110
|
-
const inferredModules = inferModulesFromHeaders(headers);
|
|
111
|
-
if (opts.moduleName && !inferredModules.includes(opts.moduleName)) {
|
|
112
|
-
inferredModules.push(opts.moduleName);
|
|
113
|
-
}
|
|
114
|
-
const thirdPartyModules = inferredModules.filter((m) => !_SYSTEM_FRAMEWORKS.has(m));
|
|
115
|
-
if (thirdPartyModules.length > 0) {
|
|
116
|
-
try {
|
|
117
|
-
const { ServiceContainer } = await import('../../../injection/ServiceContainer.js');
|
|
118
|
-
const container = ServiceContainer.getInstance();
|
|
119
|
-
spmService = container.get('spmService');
|
|
120
|
-
if (spmService) {
|
|
121
|
-
if (spmService.getFixMode() === 'off') {
|
|
122
|
-
spmService = null;
|
|
123
|
-
}
|
|
124
|
-
else {
|
|
125
|
-
try {
|
|
126
|
-
await spmService.load();
|
|
127
|
-
}
|
|
128
|
-
catch {
|
|
129
|
-
/* Package.swift 不存在则跳过 */
|
|
130
|
-
}
|
|
131
|
-
currentTarget = spmService.resolveCurrentTarget(fullPath);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
catch {
|
|
136
|
-
/* SPM 检查异常不阻断 */
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
// ── Step 3: Xcode 自动化准备 ──
|
|
141
|
-
const xcodeReady = XA.isXcodeRunning();
|
|
142
|
-
// 从当前文件内容计算 import 插入基准行(1-based)
|
|
143
|
-
let content;
|
|
144
|
-
try {
|
|
145
|
-
content = readFileSync(fullPath, 'utf8');
|
|
146
|
-
}
|
|
147
|
-
catch {
|
|
148
|
-
return result;
|
|
149
|
-
}
|
|
150
|
-
const baseInsertLine = findImportInsertLine(content, isSwift) + 1; // 0-based → 1-based
|
|
151
|
-
let xcodeOffset = 0; // 每次 Xcode 插入成功后 +1(修正多条 header 行号偏移)
|
|
152
|
-
let fileWriteUsed = false; // 一旦使用文件写入,后续全部走文件写入(避免 Xcode reload 冲突)
|
|
153
|
-
// ── Step 4: 逐条处理 ──
|
|
154
|
-
for (const header of headers) {
|
|
155
|
-
const headerTrimmed = header.trim();
|
|
156
|
-
if (!headerTrimmed) {
|
|
157
|
-
continue;
|
|
158
|
-
}
|
|
159
|
-
// ── 三级去重 ──
|
|
160
|
-
// 先按原始格式检查,再按解析后格式检查(同一 header 可能格式不同)
|
|
161
|
-
const preResolvedHeader = resolveHeaderFormat(headerTrimmed, {
|
|
162
|
-
currentTarget,
|
|
163
|
-
headerModuleName: opts.moduleName || null,
|
|
164
|
-
isSwift,
|
|
165
|
-
fullPath,
|
|
166
|
-
projectRoot: watcher?.projectRoot || null,
|
|
167
|
-
});
|
|
168
|
-
const status = checkImportStatus(importArray, headerTrimmed, isSwift);
|
|
169
|
-
const statusResolved = preResolvedHeader !== headerTrimmed
|
|
170
|
-
? checkImportStatus(importArray, preResolvedHeader, isSwift)
|
|
171
|
-
: status;
|
|
172
|
-
if (status.hasHeader || statusResolved.hasHeader) {
|
|
173
|
-
result.skipped.push(preResolvedHeader);
|
|
174
|
-
continue;
|
|
175
|
-
}
|
|
176
|
-
if (status.hasModule || statusResolved.hasModule) {
|
|
177
|
-
result.skipped.push(preResolvedHeader);
|
|
178
|
-
continue;
|
|
179
|
-
}
|
|
180
|
-
if (status.hasSimilarHeader || statusResolved.hasSimilarHeader) {
|
|
181
|
-
result.skipped.push(preResolvedHeader);
|
|
182
|
-
continue;
|
|
183
|
-
}
|
|
184
|
-
// ── SPM 依赖检查 ──
|
|
185
|
-
const headerModules = inferModulesFromHeaders([headerTrimmed]);
|
|
186
|
-
if (spmService && currentTarget && !opts.skipDepCheck) {
|
|
187
|
-
for (const mod of headerModules) {
|
|
188
|
-
if (_SYSTEM_FRAMEWORKS.has(mod) || mod === currentTarget) {
|
|
189
|
-
continue;
|
|
190
|
-
}
|
|
191
|
-
const ensureResult = spmService.ensureDependency(currentTarget, mod);
|
|
192
|
-
const decision = evaluateDepResult(ensureResult, currentTarget, mod);
|
|
193
|
-
if (decision.action === 'block') {
|
|
194
|
-
console.warn(` ⛔ 依赖被阻止: ${currentTarget} -> ${mod} (${decision.reason})`);
|
|
195
|
-
NU.notify(`已阻止依赖注入\n${currentTarget} -> ${mod}\n${decision.reason}`, 'AutoSnippet SPM 依赖策略');
|
|
196
|
-
result.cancelled = true;
|
|
197
|
-
return result;
|
|
198
|
-
}
|
|
199
|
-
if (decision.action === 'review') {
|
|
200
|
-
const reviewResult = handleDepReview({
|
|
201
|
-
spmService,
|
|
202
|
-
currentTarget,
|
|
203
|
-
mod,
|
|
204
|
-
ensureResult,
|
|
205
|
-
NU,
|
|
206
|
-
depWarnings,
|
|
207
|
-
});
|
|
208
|
-
if (reviewResult.blocked) {
|
|
209
|
-
result.cancelled = true;
|
|
210
|
-
return result;
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
}
|
|
215
|
-
// ── 构建带注释后缀的 import 行 ──
|
|
216
|
-
// 复用 dedup 阶段已计算的 preResolvedHeader
|
|
217
|
-
const resolvedHeader = preResolvedHeader;
|
|
218
|
-
const depHint = headerModules.find((m) => depWarnings.has(m));
|
|
219
|
-
const importLine = depHint
|
|
220
|
-
? `${withAutoSnippetNote(resolvedHeader)} // ⚠️ 依赖缺失: ${depWarnings.get(depHint)},需手动补齐 Package.swift`
|
|
221
|
-
: withAutoSnippetNote(resolvedHeader);
|
|
222
|
-
// ── 写入:Xcode 自动化优先 → 文件写入回退 ──
|
|
223
|
-
let inserted = false;
|
|
224
|
-
if (xcodeReady && !fileWriteUsed) {
|
|
225
|
-
// 逐条 osascript 跳转 + 粘贴
|
|
226
|
-
inserted = writeImportLineXcode(importLine, baseInsertLine + xcodeOffset, XA, CM);
|
|
227
|
-
if (inserted) {
|
|
228
|
-
xcodeOffset++;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
|
-
if (!inserted) {
|
|
232
|
-
writeImportLineFile(fullPath, importLine, isSwift);
|
|
233
|
-
fileWriteUsed = true;
|
|
234
|
-
}
|
|
235
|
-
result.inserted.push(resolvedHeader);
|
|
236
|
-
importArray.push(resolvedHeader); // 添加到去重列表(用解析后格式)
|
|
237
|
-
}
|
|
238
|
-
if (result.inserted.length > 0) {
|
|
239
|
-
}
|
|
240
|
-
return result;
|
|
241
|
-
}
|
|
242
|
-
// ═══════════════════════════════════════════════════════════════
|
|
243
|
-
// §11 导出:insertCodeToXcode
|
|
244
|
-
// ═══════════════════════════════════════════════════════════════
|
|
245
|
-
/**
|
|
246
|
-
* 将选中的搜索结果代码插入 Xcode
|
|
247
|
-
*
|
|
248
|
-
* 流程:
|
|
249
|
-
* 1. 找到触发行号
|
|
250
|
-
* 2. Preflight — 预检依赖决策(不实际写入)
|
|
251
|
-
* 3. Cut 触发行内容(Xcode 剪切,不写文件)
|
|
252
|
-
* 4. 构建带缩进 + 注释标记的代码块
|
|
253
|
-
* 5. 插入 Headers(Xcode osascript / 文件写入)
|
|
254
|
-
* 6. 计算偏移后的粘贴行号(computePasteLineNumber)
|
|
255
|
-
* 7. Jump 到粘贴行 → 选中行内容 → Cmd+V 粘贴替换
|
|
256
|
-
* 8. 任一步失败 → 降级到纯文件写入
|
|
257
|
-
*/
|
|
258
|
-
export async function insertCodeToXcode(watcher, fullPath, selected, triggerLine) {
|
|
259
|
-
const XA = await import('./XcodeAutomation.js');
|
|
260
|
-
const CM = await import('../../ClipboardManager.js');
|
|
261
|
-
const NU = (await import('../../NativeUi.js'));
|
|
262
|
-
const code = selected.code || '';
|
|
263
|
-
if (!code) {
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
const headersToInsert = (selected.headers || []).filter((h) => h?.trim());
|
|
267
|
-
const isSwift = fullPath.endsWith('.swift');
|
|
268
|
-
// ═══════════════════════════════════════════════════════
|
|
269
|
-
// 主路径:Xcode 自动化
|
|
270
|
-
// ═══════════════════════════════════════════════════════
|
|
271
|
-
if (XA.isXcodeRunning()) {
|
|
272
|
-
// ── 窗口上下文验证 ──
|
|
273
|
-
if (!XA.isXcodeFrontmost()) {
|
|
274
|
-
console.warn(` ⚠️ Xcode 不是前台应用,自动化操作可能不准确`);
|
|
275
|
-
// 宽松模式:仅警告,不阻断
|
|
276
|
-
// 如需严格模式,可设置 ASD_XCODE_STRICT_FOCUS=1
|
|
277
|
-
if (process.env.ASD_XCODE_STRICT_FOCUS === '1') {
|
|
278
|
-
console.warn(` ⏹️ ASD_XCODE_STRICT_FOCUS=1, 跳过自动化`);
|
|
279
|
-
return _fileInsertFallback(fullPath, selected, triggerLine, headersToInsert, watcher);
|
|
280
|
-
}
|
|
281
|
-
}
|
|
282
|
-
// ── Step 1: 找到触发行号 ──
|
|
283
|
-
let content;
|
|
284
|
-
try {
|
|
285
|
-
content = readFileSync(fullPath, 'utf8');
|
|
286
|
-
}
|
|
287
|
-
catch {
|
|
288
|
-
return _fileInsertFallback(fullPath, selected, triggerLine, headersToInsert, watcher);
|
|
289
|
-
}
|
|
290
|
-
const triggerLineNumber = findTriggerLineNumber(content, triggerLine);
|
|
291
|
-
if (triggerLineNumber < 0) {
|
|
292
|
-
console.warn(` ⚠️ 未在文件中找到触发行,降级为文件写入`);
|
|
293
|
-
return _fileInsertFallback(fullPath, selected, triggerLine, headersToInsert, watcher);
|
|
294
|
-
}
|
|
295
|
-
// 计算触发行缩进
|
|
296
|
-
const lines = content.split(/\r?\n/);
|
|
297
|
-
const triggerContent = lines[triggerLineNumber - 1] || '';
|
|
298
|
-
const indentMatch = triggerContent.match(/^(\s*)/);
|
|
299
|
-
const indent = indentMatch ? indentMatch[1] : '';
|
|
300
|
-
// ── Step 2: Preflight 预检依赖 ──
|
|
301
|
-
let preflightDepWarnings = null;
|
|
302
|
-
let _spmServiceCached = null;
|
|
303
|
-
let _currentTargetCached = null;
|
|
304
|
-
if (headersToInsert.length > 0) {
|
|
305
|
-
const preflight = await _preflightDeps(fullPath, headersToInsert, selected, NU);
|
|
306
|
-
if (preflight.blocked) {
|
|
307
|
-
return;
|
|
308
|
-
}
|
|
309
|
-
if (preflight.depWarnings && preflight.depWarnings.size > 0) {
|
|
310
|
-
preflightDepWarnings = preflight.depWarnings;
|
|
311
|
-
}
|
|
312
|
-
// 缓存 spmService/currentTarget 供 insertHeaders 复用(避免重复 load)
|
|
313
|
-
_spmServiceCached = preflight._spmService || null;
|
|
314
|
-
_currentTargetCached = preflight._currentTarget || null;
|
|
315
|
-
}
|
|
316
|
-
// ── Step 3: 剪切触发行内容 ──
|
|
317
|
-
const cutOk = XA.cutLineInXcode(triggerLineNumber);
|
|
318
|
-
if (!cutOk) {
|
|
319
|
-
console.warn(` ⚠️ 自动剪切失败,降级为文件写入`);
|
|
320
|
-
// Preflight 已通过,skipDepCheck 避免重复弹窗
|
|
321
|
-
return _fileInsertFallback(fullPath, selected, triggerLine, headersToInsert, watcher, {
|
|
322
|
-
skipDepCheck: true,
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
await sleep(300);
|
|
326
|
-
// ── Step 4: 构建带缩进的代码块 ──
|
|
327
|
-
const codeLines = code.split(/\r?\n/);
|
|
328
|
-
// 移除末尾空行
|
|
329
|
-
while (codeLines.length > 0 && !codeLines[codeLines.length - 1].trim()) {
|
|
330
|
-
codeLines.pop();
|
|
331
|
-
}
|
|
332
|
-
const indentedLines = codeLines.map((line) => (line ? indent + line : line));
|
|
333
|
-
const indentedCode = indentedLines.join('\n');
|
|
334
|
-
// ── Step 5: 插入 Headers ──
|
|
335
|
-
let headerInsertCount = 0;
|
|
336
|
-
if (headersToInsert.length > 0) {
|
|
337
|
-
const headerResult = await insertHeaders(watcher, fullPath, headersToInsert, {
|
|
338
|
-
moduleName: selected.moduleName || null,
|
|
339
|
-
isSwift,
|
|
340
|
-
skipDepCheck: true, // Preflight 已检查过
|
|
341
|
-
depWarnings: preflightDepWarnings ?? undefined,
|
|
342
|
-
_spmService: _spmServiceCached,
|
|
343
|
-
_currentTarget: _currentTargetCached,
|
|
344
|
-
});
|
|
345
|
-
if (headerResult.cancelled) {
|
|
346
|
-
return;
|
|
347
|
-
}
|
|
348
|
-
headerInsertCount = headerResult.inserted.length;
|
|
349
|
-
}
|
|
350
|
-
// ── Step 6: 计算偏移后的粘贴行号 ──
|
|
351
|
-
// 使用实际插入的 header 数量计算偏移,而非期望数量
|
|
352
|
-
// 当 headers 全部重复被跳过时,headerInsertCount = 0,不应偏移
|
|
353
|
-
const pasteLineNumber = computePasteLineNumber(triggerLineNumber, headerInsertCount, fullPath, {
|
|
354
|
-
forceOffset: headerInsertCount > 0,
|
|
355
|
-
expectedHeaderCount: headerInsertCount,
|
|
356
|
-
});
|
|
357
|
-
// 如果 headers 通过文件写入,等待 Xcode reload
|
|
358
|
-
if (headerInsertCount > 0) {
|
|
359
|
-
await sleep(600);
|
|
360
|
-
}
|
|
361
|
-
// ── Step 7: Jump + 选中行内容 + 粘贴替换 ──
|
|
362
|
-
await CM.withClipboardSave(async () => {
|
|
363
|
-
const wrote = CM.write(indentedCode);
|
|
364
|
-
if (!wrote) {
|
|
365
|
-
console.warn(` ⚠️ 剪贴板写入失败`);
|
|
366
|
-
return;
|
|
367
|
-
}
|
|
368
|
-
await sleep(100);
|
|
369
|
-
XA.jumpToLineInXcode(pasteLineNumber);
|
|
370
|
-
await sleep(500);
|
|
371
|
-
XA.selectAndPasteInXcode();
|
|
372
|
-
await sleep(300);
|
|
373
|
-
});
|
|
374
|
-
NU.notify(`已插入「${selected.title || '代码片段'}」`, 'AutoSnippet');
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
377
|
-
// ═══════════════════════════════════════════════════════
|
|
378
|
-
// 降级路径:纯文件写入
|
|
379
|
-
// ═══════════════════════════════════════════════════════
|
|
380
|
-
return _fileInsertFallback(fullPath, selected, triggerLine, headersToInsert, watcher);
|
|
381
|
-
}
|
|
382
|
-
// ═══════════════════════════════════════════════════════════════
|
|
383
|
-
// §12 Preflight 依赖预检
|
|
384
|
-
// ═══════════════════════════════════════════════════════════════
|
|
385
|
-
/**
|
|
386
|
-
* 预检所有 headers 的 SPM 依赖状态
|
|
387
|
-
*
|
|
388
|
-
* 不实际写入文件,只检查并弹窗确认。
|
|
389
|
-
* 返回 { blocked: true } 表示有依赖被阻止或用户取消。
|
|
390
|
-
*/
|
|
391
|
-
async function _preflightDeps(fullPath, headers, selected, NU) {
|
|
392
|
-
const result = { blocked: false };
|
|
393
|
-
// 始终从所有 headers 推断模块(不仅依赖 selected.moduleName)
|
|
394
|
-
const inferredModules = inferModulesFromHeaders(headers);
|
|
395
|
-
if (selected.moduleName && !inferredModules.includes(selected.moduleName)) {
|
|
396
|
-
inferredModules.push(selected.moduleName);
|
|
397
|
-
}
|
|
398
|
-
const thirdPartyModules = inferredModules.filter((m) => !_SYSTEM_FRAMEWORKS.has(m));
|
|
399
|
-
if (thirdPartyModules.length === 0) {
|
|
400
|
-
return result;
|
|
401
|
-
}
|
|
402
|
-
try {
|
|
403
|
-
const { ServiceContainer } = await import('../../../injection/ServiceContainer.js');
|
|
404
|
-
const container = ServiceContainer.getInstance();
|
|
405
|
-
const spmService = container.get('spmService');
|
|
406
|
-
if (!spmService) {
|
|
407
|
-
return result;
|
|
408
|
-
}
|
|
409
|
-
// Fix Mode 检查:off 模式完全跳过
|
|
410
|
-
if (spmService.getFixMode() === 'off') {
|
|
411
|
-
return result;
|
|
412
|
-
}
|
|
413
|
-
try {
|
|
414
|
-
await spmService.load();
|
|
415
|
-
}
|
|
416
|
-
catch {
|
|
417
|
-
return result;
|
|
418
|
-
}
|
|
419
|
-
const currentTarget = spmService.resolveCurrentTarget(fullPath);
|
|
420
|
-
if (!currentTarget) {
|
|
421
|
-
return result;
|
|
422
|
-
}
|
|
423
|
-
for (const mod of thirdPartyModules) {
|
|
424
|
-
if (mod === currentTarget) {
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
const ensureResult = spmService.ensureDependency(currentTarget, mod);
|
|
428
|
-
const decision = evaluateDepResult(ensureResult, currentTarget, mod);
|
|
429
|
-
if (decision.action === 'block') {
|
|
430
|
-
console.warn(` ⛔ [Preflight] 依赖被阻止: ${currentTarget} -> ${mod} (${decision.reason})`);
|
|
431
|
-
NU.notify(`已阻止依赖注入\n${currentTarget} -> ${mod}\n${decision.reason}`, 'AutoSnippet SPM 依赖策略');
|
|
432
|
-
result.blocked = true;
|
|
433
|
-
return result;
|
|
434
|
-
}
|
|
435
|
-
if (decision.action === 'review') {
|
|
436
|
-
if (!result.depWarnings) {
|
|
437
|
-
result.depWarnings = new Map();
|
|
438
|
-
}
|
|
439
|
-
const reviewResult = handleDepReview({
|
|
440
|
-
spmService,
|
|
441
|
-
currentTarget,
|
|
442
|
-
mod,
|
|
443
|
-
ensureResult,
|
|
444
|
-
NU,
|
|
445
|
-
depWarnings: result.depWarnings,
|
|
446
|
-
label: 'Preflight',
|
|
447
|
-
});
|
|
448
|
-
if (reviewResult.blocked) {
|
|
449
|
-
result.blocked = true;
|
|
450
|
-
return result;
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
}
|
|
454
|
-
// 缓存 spmService/currentTarget 供下游 insertHeaders 复用
|
|
455
|
-
result._spmService = spmService;
|
|
456
|
-
result._currentTarget = currentTarget;
|
|
457
|
-
}
|
|
458
|
-
catch (err) {
|
|
459
|
-
console.warn(` ⚠️ Preflight 依赖检查异常: ${err instanceof Error ? err.message : String(err)}`);
|
|
460
|
-
}
|
|
461
|
-
return result;
|
|
462
|
-
}
|
|
463
|
-
// ═══════════════════════════════════════════════════════════════
|
|
464
|
-
// §13 文件写入降级
|
|
465
|
-
// ═══════════════════════════════════════════════════════════════
|
|
466
|
-
async function _fileInsertFallback(fullPath, selected, triggerLine, headersToInsert, watcher, opts = {}) {
|
|
467
|
-
// 先写 headers
|
|
468
|
-
if (headersToInsert.length > 0) {
|
|
469
|
-
const headerResult = await insertHeaders(watcher, fullPath, headersToInsert, {
|
|
470
|
-
moduleName: selected.moduleName || null,
|
|
471
|
-
skipDepCheck: opts.skipDepCheck || false, // Preflight 已通过时跳过重复检查
|
|
472
|
-
});
|
|
473
|
-
if (headerResult.cancelled) {
|
|
474
|
-
return;
|
|
475
|
-
}
|
|
476
|
-
}
|
|
477
|
-
// 再替换触发行为代码
|
|
478
|
-
const code = selected.code || '';
|
|
479
|
-
try {
|
|
480
|
-
const content = readFileSync(fullPath, 'utf8');
|
|
481
|
-
const lines = content.split(/\r?\n/);
|
|
482
|
-
const triggerTrimmed = triggerLine.trim();
|
|
483
|
-
// 从后往前查找触发行
|
|
484
|
-
let found = -1;
|
|
485
|
-
for (let i = lines.length - 1; i >= 0; i--) {
|
|
486
|
-
if (lines[i].trim() === triggerTrimmed) {
|
|
487
|
-
found = i;
|
|
488
|
-
break;
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
if (found >= 0) {
|
|
492
|
-
// 计算缩进 → 对齐 → 替换
|
|
493
|
-
const triggerContent = lines[found];
|
|
494
|
-
const indentMatch = triggerContent.match(/^(\s*)/);
|
|
495
|
-
const indent = indentMatch ? indentMatch[1] : '';
|
|
496
|
-
const codeLines = code.split(/\r?\n/);
|
|
497
|
-
while (codeLines.length > 0 && !codeLines[codeLines.length - 1].trim()) {
|
|
498
|
-
codeLines.pop();
|
|
499
|
-
}
|
|
500
|
-
const indentedLines = codeLines.map((line) => (line ? indent + line : line));
|
|
501
|
-
while (indentedLines.length > 0 && !indentedLines[indentedLines.length - 1].trim()) {
|
|
502
|
-
indentedLines.pop();
|
|
503
|
-
}
|
|
504
|
-
const newLines = [...lines.slice(0, found), ...indentedLines, ...lines.slice(found + 1)];
|
|
505
|
-
const newContent = newLines.join('\n');
|
|
506
|
-
saveEventFilter.markWrite(fullPath, newContent);
|
|
507
|
-
writeFileSync(fullPath, newContent, 'utf8');
|
|
508
|
-
}
|
|
509
|
-
else {
|
|
510
|
-
const appendContent = `${content}\n${code}\n`;
|
|
511
|
-
saveEventFilter.markWrite(fullPath, appendContent);
|
|
512
|
-
writeFileSync(fullPath, appendContent, 'utf8');
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
catch (err) {
|
|
516
|
-
console.warn(` ⚠️ 文件写入失败: ${err instanceof Error ? err.message : String(err)}`);
|
|
517
|
-
}
|
|
518
|
-
}
|
|
519
|
-
// ═══════════════════════════════════════════════════════════════
|
|
520
|
-
// §14 注释标记生成
|
|
521
|
-
// ═══════════════════════════════════════════════════════════════
|
|
522
|
-
function _generateInsertMarker(filePath, selected) {
|
|
523
|
-
try {
|
|
524
|
-
const ext = (filePath.match(/\.[^.]+$/) || [''])[0].toLowerCase();
|
|
525
|
-
const trigger = selected.trigger ? `[${selected.trigger}]` : '';
|
|
526
|
-
const recipeName = selected.name ? ` from ${selected.name}` : '';
|
|
527
|
-
const timestamp = new Date().toLocaleString('zh-CN', {
|
|
528
|
-
year: 'numeric',
|
|
529
|
-
month: '2-digit',
|
|
530
|
-
day: '2-digit',
|
|
531
|
-
hour: '2-digit',
|
|
532
|
-
minute: '2-digit',
|
|
533
|
-
});
|
|
534
|
-
const marker = `🤖 AutoSnippet${trigger}${recipeName} @ ${timestamp}`;
|
|
535
|
-
if (['.py', '.rb'].includes(ext)) {
|
|
536
|
-
return `# ${marker}`;
|
|
537
|
-
}
|
|
538
|
-
if (['.lua', '.sql'].includes(ext)) {
|
|
539
|
-
return `-- ${marker}`;
|
|
540
|
-
}
|
|
541
|
-
if (['.html', '.xml', '.svg'].includes(ext)) {
|
|
542
|
-
return `<!-- ${marker} -->`;
|
|
543
|
-
}
|
|
544
|
-
if (['.css', '.scss', '.less'].includes(ext)) {
|
|
545
|
-
return `/* ${marker} */`;
|
|
546
|
-
}
|
|
547
|
-
return `// ${marker}`;
|
|
548
|
-
}
|
|
549
|
-
catch {
|
|
550
|
-
return null;
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
// ═══════════════════════════════════════════════════════════════
|
|
554
|
-
// §15 工具函数
|
|
555
|
-
// ═══════════════════════════════════════════════════════════════
|
|
556
|
-
/** 查找触发行的行号(1-based,-1 表示未找到) */
|
|
557
|
-
export function findTriggerLineNumber(content, triggerLine) {
|
|
558
|
-
if (!content || !triggerLine) {
|
|
559
|
-
return -1;
|
|
560
|
-
}
|
|
561
|
-
const needle = triggerLine.trim();
|
|
562
|
-
const lines = content.split(/\r?\n/);
|
|
563
|
-
for (let i = 0; i < lines.length; i++) {
|
|
564
|
-
if (lines[i].trim() === needle) {
|
|
565
|
-
return i + 1;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
return -1;
|
|
569
|
-
}
|
|
570
|
-
/** 查找 import 语句的插入位置(0-based 行索引,在最后一个 import 之后) */
|
|
571
|
-
export function findImportInsertLine(content, isSwift) {
|
|
572
|
-
const lines = content.split('\n');
|
|
573
|
-
let lastImportLine = -1;
|
|
574
|
-
for (let i = 0; i < lines.length; i++) {
|
|
575
|
-
const t = lines[i].trim();
|
|
576
|
-
if (isSwift) {
|
|
577
|
-
if (t.startsWith('import ') && !t.startsWith('import (')) {
|
|
578
|
-
lastImportLine = i;
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
else {
|
|
582
|
-
if (t.startsWith('#import') || t.startsWith('@import')) {
|
|
583
|
-
lastImportLine = i;
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
return lastImportLine >= 0 ? lastImportLine + 1 : 0;
|
|
588
|
-
}
|
|
@@ -1,99 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* XcodeWriteUtils — Xcode 写入与插入工具函数
|
|
3
|
-
*
|
|
4
|
-
* 从 XcodeIntegration.js 拆分,负责:
|
|
5
|
-
* - 通用工具函数(sleep, withAutoSnippetNote)
|
|
6
|
-
* - SPM 依赖决策逻辑
|
|
7
|
-
* - Xcode osascript 写入
|
|
8
|
-
* - 文件写入回退
|
|
9
|
-
* - 粘贴行号偏移计算
|
|
10
|
-
*/
|
|
11
|
-
export declare function sleep(ms: number): Promise<unknown>;
|
|
12
|
-
/** 在 import 行末尾附加来源标记注释 */
|
|
13
|
-
export declare function withAutoSnippetNote(importLine: string): string;
|
|
14
|
-
/** 依赖检查结果 */
|
|
15
|
-
interface EnsureResult {
|
|
16
|
-
exists: boolean;
|
|
17
|
-
canAdd: boolean;
|
|
18
|
-
reason?: string;
|
|
19
|
-
crossPackage?: boolean;
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* 将 SpmHelper.ensureDependency 返回值映射为三种动作:
|
|
23
|
-
* continue — 依赖已存在
|
|
24
|
-
* block — 循环/反向依赖,禁止插入
|
|
25
|
-
* review — 依赖缺失但可添加,需用户确认
|
|
26
|
-
*/
|
|
27
|
-
export declare function evaluateDepResult(ensureResult: EnsureResult, from: string, to: string): {
|
|
28
|
-
action: string;
|
|
29
|
-
reason?: undefined;
|
|
30
|
-
from?: undefined;
|
|
31
|
-
to?: undefined;
|
|
32
|
-
} | {
|
|
33
|
-
action: string;
|
|
34
|
-
reason: string;
|
|
35
|
-
from: string;
|
|
36
|
-
to: string;
|
|
37
|
-
};
|
|
38
|
-
/** 依赖审查上下文 */
|
|
39
|
-
interface DepReviewContext {
|
|
40
|
-
spmService: {
|
|
41
|
-
getFixMode(): string;
|
|
42
|
-
addDependency(from: string, to: string): {
|
|
43
|
-
ok: boolean;
|
|
44
|
-
error?: string;
|
|
45
|
-
};
|
|
46
|
-
};
|
|
47
|
-
currentTarget: string;
|
|
48
|
-
mod: string;
|
|
49
|
-
ensureResult: EnsureResult;
|
|
50
|
-
NU: {
|
|
51
|
-
promptWithButtons(msg: string, buttons: string[], title: string): string;
|
|
52
|
-
notify(msg: string, title: string): void;
|
|
53
|
-
};
|
|
54
|
-
depWarnings: Map<string, string>;
|
|
55
|
-
label?: string;
|
|
56
|
-
}
|
|
57
|
-
/**
|
|
58
|
-
* 公共依赖审查弹窗逻辑(insertHeaders 和 _preflightDeps 共享)
|
|
59
|
-
*
|
|
60
|
-
* @param ctx { spmService, currentTarget, mod, ensureResult, NU, depWarnings, label }
|
|
61
|
-
* @returns }
|
|
62
|
-
*/
|
|
63
|
-
export declare function handleDepReview(ctx: DepReviewContext): {
|
|
64
|
-
blocked: boolean;
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* 通过 Xcode 自动化插入一条 import,保持 Xcode Undo 可用。
|
|
68
|
-
*
|
|
69
|
-
* 流程:保存剪贴板 → 写入 import 内容 → osascript 跳转+粘贴 → 恢复剪贴板
|
|
70
|
-
*
|
|
71
|
-
* @param importLine 完整的 import 文本
|
|
72
|
-
* @param insertLine 1-based 行号
|
|
73
|
-
* @param XA XcodeAutomation 模块
|
|
74
|
-
* @param CM ClipboardManager 模块
|
|
75
|
-
*/
|
|
76
|
-
export declare function writeImportLineXcode(importLine: string, insertLine: number, XA: {
|
|
77
|
-
isXcodeRunning(): boolean;
|
|
78
|
-
insertAtLineStartInXcode(line: number): boolean;
|
|
79
|
-
}, CM: {
|
|
80
|
-
read(): string;
|
|
81
|
-
write(content: string): boolean;
|
|
82
|
-
}): boolean;
|
|
83
|
-
/**
|
|
84
|
-
* 纯文件写入插入单条 import。
|
|
85
|
-
* Xcode 会因文件变更而自动 reload。
|
|
86
|
-
*/
|
|
87
|
-
export declare function writeImportLineFile(filePath: string, importLine: string, isSwift: boolean): boolean;
|
|
88
|
-
/** 查找文件中最后一个 import 行的行号(1-based,0 表示无 import) */
|
|
89
|
-
export declare function getLastImportLine(filePath: string): number;
|
|
90
|
-
/**
|
|
91
|
-
* 计算代码粘贴行号
|
|
92
|
-
*
|
|
93
|
-
* 如果 headers 插入在 trigger 行之前(import 区),trigger 行号需要向下偏移。
|
|
94
|
-
*/
|
|
95
|
-
export declare function computePasteLineNumber(triggerLineNumber: number, headerInsertCount: number, filePath: string, options?: {
|
|
96
|
-
expectedHeaderCount?: number;
|
|
97
|
-
forceOffset?: boolean;
|
|
98
|
-
}): number;
|
|
99
|
-
export {};
|