autosnippet 3.2.22 → 3.3.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 (102) hide show
  1. package/dashboard/dist/assets/{icons-C1dUryS-.js → icons-BofcEZ3f.js} +1 -1
  2. package/dashboard/dist/assets/index-SiN1GChm.js +128 -0
  3. package/dashboard/dist/index.html +2 -2
  4. package/dist/bin/cli.d.ts +0 -1
  5. package/dist/bin/cli.js +0 -133
  6. package/dist/lib/cli/SetupService.d.ts +46 -2
  7. package/dist/lib/cli/SetupService.js +2 -27
  8. package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.d.ts +2 -5
  9. package/dist/lib/{platform/ios/spm → core/discovery}/SpmDiscoverer.js +159 -44
  10. package/dist/lib/core/discovery/index.d.ts +1 -1
  11. package/dist/lib/core/discovery/index.js +2 -2
  12. package/dist/lib/external/mcp/handlers/guard.js +6 -3
  13. package/dist/lib/http/HttpServer.js +0 -6
  14. package/dist/lib/http/routes/commands.d.ts +1 -1
  15. package/dist/lib/http/routes/commands.js +1 -66
  16. package/dist/lib/http/routes/remote.js +0 -5
  17. package/dist/lib/injection/ServiceMap.d.ts +0 -9
  18. package/dist/lib/injection/modules/AppModule.d.ts +2 -3
  19. package/dist/lib/injection/modules/AppModule.js +3 -30
  20. package/dist/lib/service/module/ModuleService.js +3 -13
  21. package/dist/lib/service/search/SearchEngine.js +1 -1
  22. package/dist/lib/shared/constants.d.ts +0 -15
  23. package/dist/lib/shared/constants.js +0 -10
  24. package/dist/scripts/release.js +2 -10
  25. package/package.json +4 -19
  26. package/dashboard/dist/assets/index-DdvZE4Yd.js +0 -128
  27. package/dist/lib/http/routes/snippets.d.ts +0 -6
  28. package/dist/lib/http/routes/snippets.js +0 -49
  29. package/dist/lib/platform/ClipboardManager.d.ts +0 -24
  30. package/dist/lib/platform/ClipboardManager.js +0 -142
  31. package/dist/lib/platform/NativeUi.d.ts +0 -53
  32. package/dist/lib/platform/NativeUi.js +0 -284
  33. package/dist/lib/platform/ios/index.d.ts +0 -38
  34. package/dist/lib/platform/ios/index.js +0 -42
  35. package/dist/lib/platform/ios/routes/spm.d.ts +0 -9
  36. package/dist/lib/platform/ios/routes/spm.js +0 -371
  37. package/dist/lib/platform/ios/snippet/PlaceholderConverter.d.ts +0 -21
  38. package/dist/lib/platform/ios/snippet/PlaceholderConverter.js +0 -48
  39. package/dist/lib/platform/ios/snippet/XcodeCodec.d.ts +0 -23
  40. package/dist/lib/platform/ios/snippet/XcodeCodec.js +0 -96
  41. package/dist/lib/platform/ios/spm/DependencyGraph.d.ts +0 -56
  42. package/dist/lib/platform/ios/spm/DependencyGraph.js +0 -195
  43. package/dist/lib/platform/ios/spm/PackageSwiftParser.d.ts +0 -69
  44. package/dist/lib/platform/ios/spm/PackageSwiftParser.js +0 -231
  45. package/dist/lib/platform/ios/spm/PathFinder.d.ts +0 -28
  46. package/dist/lib/platform/ios/spm/PathFinder.js +0 -117
  47. package/dist/lib/platform/ios/spm/PolicyEngine.d.ts +0 -44
  48. package/dist/lib/platform/ios/spm/PolicyEngine.js +0 -79
  49. package/dist/lib/platform/ios/spm/SpmHelper.d.ts +0 -102
  50. package/dist/lib/platform/ios/spm/SpmHelper.js +0 -464
  51. package/dist/lib/platform/ios/xcode/HeaderResolver.d.ts +0 -33
  52. package/dist/lib/platform/ios/xcode/HeaderResolver.js +0 -90
  53. package/dist/lib/platform/ios/xcode/SaveEventFilter.d.ts +0 -66
  54. package/dist/lib/platform/ios/xcode/SaveEventFilter.js +0 -142
  55. package/dist/lib/platform/ios/xcode/XcodeAutomation.d.ts +0 -71
  56. package/dist/lib/platform/ios/xcode/XcodeAutomation.js +0 -327
  57. package/dist/lib/platform/ios/xcode/XcodeImportResolver.d.ts +0 -130
  58. package/dist/lib/platform/ios/xcode/XcodeImportResolver.js +0 -404
  59. package/dist/lib/platform/ios/xcode/XcodeIntegration.d.ts +0 -89
  60. package/dist/lib/platform/ios/xcode/XcodeIntegration.js +0 -588
  61. package/dist/lib/platform/ios/xcode/XcodeWriteUtils.d.ts +0 -99
  62. package/dist/lib/platform/ios/xcode/XcodeWriteUtils.js +0 -190
  63. package/dist/lib/service/automation/ActionPipeline.d.ts +0 -34
  64. package/dist/lib/service/automation/ActionPipeline.js +0 -53
  65. package/dist/lib/service/automation/AutomationOrchestrator.d.ts +0 -86
  66. package/dist/lib/service/automation/AutomationOrchestrator.js +0 -57
  67. package/dist/lib/service/automation/ContextCollector.d.ts +0 -24
  68. package/dist/lib/service/automation/ContextCollector.js +0 -35
  69. package/dist/lib/service/automation/DirectiveDetector.d.ts +0 -51
  70. package/dist/lib/service/automation/DirectiveDetector.js +0 -112
  71. package/dist/lib/service/automation/FileWatcher.d.ts +0 -51
  72. package/dist/lib/service/automation/FileWatcher.js +0 -366
  73. package/dist/lib/service/automation/TriggerResolver.d.ts +0 -36
  74. package/dist/lib/service/automation/TriggerResolver.js +0 -62
  75. package/dist/lib/service/automation/handlers/AlinkHandler.d.ts +0 -7
  76. package/dist/lib/service/automation/handlers/AlinkHandler.js +0 -80
  77. package/dist/lib/service/automation/handlers/CreateHandler.d.ts +0 -11
  78. package/dist/lib/service/automation/handlers/CreateHandler.js +0 -170
  79. package/dist/lib/service/automation/handlers/GuardHandler.d.ts +0 -17
  80. package/dist/lib/service/automation/handlers/GuardHandler.js +0 -218
  81. package/dist/lib/service/automation/handlers/HeaderHandler.d.ts +0 -2
  82. package/dist/lib/service/automation/handlers/HeaderHandler.js +0 -32
  83. package/dist/lib/service/automation/handlers/SearchHandler.d.ts +0 -11
  84. package/dist/lib/service/automation/handlers/SearchHandler.js +0 -278
  85. package/dist/lib/service/snippet/SnippetFactory.d.ts +0 -101
  86. package/dist/lib/service/snippet/SnippetFactory.js +0 -145
  87. package/dist/lib/service/snippet/SnippetInstaller.d.ts +0 -91
  88. package/dist/lib/service/snippet/SnippetInstaller.js +0 -276
  89. package/dist/lib/service/snippet/codecs/SnippetCodec.d.ts +0 -44
  90. package/dist/lib/service/snippet/codecs/SnippetCodec.js +0 -35
  91. package/dist/lib/service/snippet/codecs/VSCodeCodec.d.ts +0 -27
  92. package/dist/lib/service/snippet/codecs/VSCodeCodec.js +0 -82
  93. package/dist/scripts/build-native-ui.d.ts +0 -3
  94. package/dist/scripts/build-native-ui.js +0 -62
  95. package/dist/scripts/init-snippets.d.ts +0 -30
  96. package/dist/scripts/init-snippets.js +0 -298
  97. package/dist/scripts/install-full.d.ts +0 -7
  98. package/dist/scripts/install-full.js +0 -38
  99. package/resources/native-ui/README.md +0 -29
  100. package/resources/native-ui/combined-window.swift +0 -494
  101. package/resources/native-ui/main.swift +0 -598
  102. package/scripts/postinstall-safe.mjs +0 -89
@@ -1,130 +0,0 @@
1
- /**
2
- * XcodeImportResolver — import 语句解析、头文件搜索与三级去重
3
- *
4
- * 从 XcodeIntegration.js 拆分,负责:
5
- * - import 语句解析(ObjC / Swift)
6
- * - 头文件物理路径搜索
7
- * - import 格式化(同 target / 跨 target)
8
- * - 三级去重(精确 → 模块 → 相似文件名)
9
- * - 模块名推断
10
- */
11
- /**
12
- * 解析原始 header 字符串,提取 moduleName 和 headerName
13
- *
14
- * 支持格式:
15
- * #import <Module/Header.h> → { moduleName: 'Module', headerName: 'Header.h', isAngle: true }
16
- * #import "Header.h" → { moduleName: '', headerName: 'Header.h', isAngle: false }
17
- * @import Module; → { moduleName: 'Module', headerName: '', isAngle: false, isAtImport: true }
18
- * import Module (Swift) → { moduleName: 'Module', headerName: '', isAngle: false, isSwiftImport: true }
19
- * Header.h → { moduleName: '', headerName: 'Header.h', isAngle: false, isRaw: true }
20
- */
21
- export declare function parseHeaderString(header: string): {
22
- moduleName: string;
23
- headerName: string;
24
- isAngle: boolean;
25
- quotedPath?: undefined;
26
- isAtImport?: undefined;
27
- isSwiftImport?: undefined;
28
- isRaw?: undefined;
29
- } | {
30
- moduleName: string;
31
- headerName: string;
32
- isAngle: boolean;
33
- quotedPath: string;
34
- isAtImport?: undefined;
35
- isSwiftImport?: undefined;
36
- isRaw?: undefined;
37
- } | {
38
- moduleName: string;
39
- headerName: string;
40
- isAngle: boolean;
41
- isAtImport: boolean;
42
- quotedPath?: undefined;
43
- isSwiftImport?: undefined;
44
- isRaw?: undefined;
45
- } | {
46
- moduleName: string;
47
- headerName: string;
48
- isAngle: boolean;
49
- isSwiftImport: boolean;
50
- quotedPath?: undefined;
51
- isAtImport?: undefined;
52
- isRaw?: undefined;
53
- } | {
54
- moduleName: string;
55
- headerName: string;
56
- isAngle: boolean;
57
- isRaw: boolean;
58
- quotedPath?: undefined;
59
- isAtImport?: undefined;
60
- isSwiftImport?: undefined;
61
- };
62
- /**
63
- * 在 target 源目录中搜索头文件,返回相对于当前文件的路径
64
- *
65
- * 搜索策略:
66
- * 1. 当前文件同目录
67
- * 2. 从项目根目录递归查找(最多深度 6 层,优先 Sources/ 下)
68
- * 3. 找到后计算相对于当前文件目录的路径
69
- *
70
- * @param headerName 头文件名 (如 "Foo.h")
71
- * @param currentFilePath 当前正在编辑的文件绝对路径
72
- * @param [projectRoot] 项目根目录
73
- * @returns 相对路径 (如 "Foo.h" 或 "../SubDir/Foo.h"),null 表示未找到
74
- */
75
- export declare function findHeaderRelativePath(headerName: string, currentFilePath: string, projectRoot: string | null): string | null;
76
- /** 递归查找文件(限最大深度) */
77
- export declare function findFileRecursive(dir: string, fileName: string, maxDepth: number): string | null;
78
- /**
79
- * 根据当前文件 target 和 header 的 module 关系,生成正确格式的 import 行
80
- *
81
- * 规则:
82
- * Swift: 始终 `import Module`
83
- * ObjC 同 target: `#import "Header.h"` (quoted format)
84
- * ObjC 跨 target: `#import <Module/Header.h>` (angle-bracket format)
85
- * @import 格式保持原样
86
- *
87
- * @param rawHeader 原始 header 字符串
88
- * @param ctx { currentTarget, headerModuleName, isSwift, fullPath, projectRoot }
89
- * - currentTarget: 当前文件所属的 target 名
90
- * - headerModuleName: header 所属的 module/target 名(来自 recipe.moduleName 或推断)
91
- * - isSwift: 目标文件是否是 Swift
92
- * - fullPath: 当前编辑文件的绝对路径(用于计算同 target 相对路径)
93
- * - projectRoot: 项目根目录(用于搜索头文件物理位置)
94
- * @returns 格式化后的完整 import 行
95
- */
96
- export declare function resolveHeaderFormat(rawHeader: string, ctx: {
97
- currentTarget: string | null;
98
- headerModuleName: string | null;
99
- isSwift: boolean;
100
- fullPath: string;
101
- projectRoot: string | null;
102
- }): string;
103
- /** 从文件中收集已有的 import 语句 */
104
- export declare function collectImportsFromFile(filePath: string, isSwift: boolean): string[];
105
- /** 收集 .m 文件对应 .h 文件中的 imports(ObjC 接口/实现配对去重) */
106
- export declare function collectImportsFromHeaderFile(sourcePath: string, importArray: string[]): void;
107
- /**
108
- * 三级 import 去重检查
109
- *
110
- * hasHeader 精确匹配(同一 import 行)
111
- * hasModule 模块级匹配(同模块不同头文件,或 @import)
112
- * hasSimilarHeader 文件名 case-insensitive 匹配
113
- *
114
- * @param importArray 已有的 import 行
115
- * @param headerLine 待插入的 import 行
116
- */
117
- export declare function checkImportStatus(importArray: string[], headerLine: string, isSwift: boolean): {
118
- hasHeader: boolean;
119
- hasModule: boolean;
120
- hasSimilarHeader: boolean;
121
- };
122
- /**
123
- * 从 import 语句推断模块名
124
- *
125
- * #import <Module/Header.h> → Module
126
- * @import Module; → Module
127
- * import Module (Swift) → Module
128
- * #import "Local.h" → null
129
- */
130
- export declare function inferModulesFromHeaders(headers: string[]): string[];
@@ -1,404 +0,0 @@
1
- /**
2
- * XcodeImportResolver — import 语句解析、头文件搜索与三级去重
3
- *
4
- * 从 XcodeIntegration.js 拆分,负责:
5
- * - import 语句解析(ObjC / Swift)
6
- * - 头文件物理路径搜索
7
- * - import 格式化(同 target / 跨 target)
8
- * - 三级去重(精确 → 模块 → 相似文件名)
9
- * - 模块名推断
10
- */
11
- import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
12
- import { basename, dirname, resolve as pathResolve, relative, sep } from 'node:path';
13
- /**
14
- * 解析原始 header 字符串,提取 moduleName 和 headerName
15
- *
16
- * 支持格式:
17
- * #import <Module/Header.h> → { moduleName: 'Module', headerName: 'Header.h', isAngle: true }
18
- * #import "Header.h" → { moduleName: '', headerName: 'Header.h', isAngle: false }
19
- * @import Module; → { moduleName: 'Module', headerName: '', isAngle: false, isAtImport: true }
20
- * import Module (Swift) → { moduleName: 'Module', headerName: '', isAngle: false, isSwiftImport: true }
21
- * Header.h → { moduleName: '', headerName: 'Header.h', isAngle: false, isRaw: true }
22
- */
23
- export function parseHeaderString(header) {
24
- const t = header.trim();
25
- // #import <Module/Header.h>
26
- let m = t.match(/^#(?:import|include)\s+<([^/> ]+)\/([^>]+)>/);
27
- if (m) {
28
- return { moduleName: m[1], headerName: m[2], isAngle: true };
29
- }
30
- // #import <Module> (framework umbrella)
31
- m = t.match(/^#(?:import|include)\s+<([^>]+)>/);
32
- if (m) {
33
- return { moduleName: m[1], headerName: '', isAngle: true };
34
- }
35
- // #import "Header.h" or #import "Dir/Header.h"
36
- m = t.match(/^#(?:import|include)\s+"([^"]+)"/);
37
- if (m) {
38
- const parts = m[1].split('/');
39
- return {
40
- moduleName: '',
41
- headerName: parts[parts.length - 1],
42
- isAngle: false,
43
- quotedPath: m[1],
44
- };
45
- }
46
- // @import Module;
47
- m = t.match(/^@import\s+(\w+)/);
48
- if (m) {
49
- return { moduleName: m[1], headerName: '', isAngle: false, isAtImport: true };
50
- }
51
- // import Module (Swift)
52
- m = t.match(/^import\s+(\w+)/);
53
- if (m && !['class', 'struct', 'enum', 'protocol', 'func', 'var', 'let'].includes(m[1])) {
54
- return { moduleName: m[1], headerName: '', isAngle: false, isSwiftImport: true };
55
- }
56
- // 裸 header 名: Header.h
57
- if (/\.(h|hpp|hh)$/i.test(t)) {
58
- return { moduleName: '', headerName: t, isAngle: false, isRaw: true };
59
- }
60
- return { moduleName: '', headerName: t, isAngle: false, isRaw: true };
61
- }
62
- /**
63
- * 在 target 源目录中搜索头文件,返回相对于当前文件的路径
64
- *
65
- * 搜索策略:
66
- * 1. 当前文件同目录
67
- * 2. 从项目根目录递归查找(最多深度 6 层,优先 Sources/ 下)
68
- * 3. 找到后计算相对于当前文件目录的路径
69
- *
70
- * @param headerName 头文件名 (如 "Foo.h")
71
- * @param currentFilePath 当前正在编辑的文件绝对路径
72
- * @param [projectRoot] 项目根目录
73
- * @returns 相对路径 (如 "Foo.h" 或 "../SubDir/Foo.h"),null 表示未找到
74
- */
75
- export function findHeaderRelativePath(headerName, currentFilePath, projectRoot) {
76
- if (!headerName || !currentFilePath) {
77
- return null;
78
- }
79
- try {
80
- const currentDir = dirname(currentFilePath);
81
- // 1. 同目录检查
82
- const sameDir = pathResolve(currentDir, headerName);
83
- if (existsSync(sameDir)) {
84
- return headerName;
85
- }
86
- // 2. 向上找 Sources/ 或 target 根目录,在其下递归搜索
87
- const searchRoots = [];
88
- if (projectRoot) {
89
- const sourcesDir = pathResolve(projectRoot, 'Sources');
90
- if (existsSync(sourcesDir)) {
91
- searchRoots.push(sourcesDir);
92
- }
93
- searchRoots.push(projectRoot);
94
- }
95
- // 也从当前文件向上找 Sources 目录
96
- let dir = currentDir;
97
- for (let i = 0; i < 8; i++) {
98
- const base = basename(dir);
99
- if (base === 'Sources' || base === 'Source' || base === 'src') {
100
- searchRoots.unshift(dir);
101
- break;
102
- }
103
- const parent = dirname(dir);
104
- if (parent === dir) {
105
- break;
106
- }
107
- dir = parent;
108
- }
109
- // 在 searchRoots 中递归查找 headerName(限深度 6)
110
- for (const root of searchRoots) {
111
- const found = findFileRecursive(root, headerName, 6);
112
- if (found) {
113
- let rel = relative(currentDir, found);
114
- // 统一用 / 分隔
115
- rel = rel.split(sep).join('/');
116
- return rel;
117
- }
118
- }
119
- return null;
120
- }
121
- catch {
122
- return null;
123
- }
124
- }
125
- /** 递归查找文件(限最大深度) */
126
- export function findFileRecursive(dir, fileName, maxDepth) {
127
- if (maxDepth <= 0) {
128
- return null;
129
- }
130
- try {
131
- const entries = readdirSync(dir);
132
- // 先在当前层查找
133
- for (const e of entries) {
134
- if (e === fileName) {
135
- return pathResolve(dir, e);
136
- }
137
- }
138
- // 再递归子目录(跳过隐藏目录和常见无关目录)
139
- for (const e of entries) {
140
- if (e.startsWith('.') || e === 'node_modules' || e === 'build' || e === 'DerivedData') {
141
- continue;
142
- }
143
- const full = pathResolve(dir, e);
144
- try {
145
- if (statSync(full).isDirectory()) {
146
- const found = findFileRecursive(full, fileName, maxDepth - 1);
147
- if (found) {
148
- return found;
149
- }
150
- }
151
- }
152
- catch {
153
- /* 跳过不可访问的目录 */
154
- }
155
- }
156
- }
157
- catch {
158
- /* 跳过不可读目录 */
159
- }
160
- return null;
161
- }
162
- /**
163
- * 根据当前文件 target 和 header 的 module 关系,生成正确格式的 import 行
164
- *
165
- * 规则:
166
- * Swift: 始终 `import Module`
167
- * ObjC 同 target: `#import "Header.h"` (quoted format)
168
- * ObjC 跨 target: `#import <Module/Header.h>` (angle-bracket format)
169
- * @import 格式保持原样
170
- *
171
- * @param rawHeader 原始 header 字符串
172
- * @param ctx { currentTarget, headerModuleName, isSwift, fullPath, projectRoot }
173
- * - currentTarget: 当前文件所属的 target 名
174
- * - headerModuleName: header 所属的 module/target 名(来自 recipe.moduleName 或推断)
175
- * - isSwift: 目标文件是否是 Swift
176
- * - fullPath: 当前编辑文件的绝对路径(用于计算同 target 相对路径)
177
- * - projectRoot: 项目根目录(用于搜索头文件物理位置)
178
- * @returns 格式化后的完整 import 行
179
- */
180
- export function resolveHeaderFormat(rawHeader, ctx) {
181
- const { currentTarget, headerModuleName, isSwift, fullPath, projectRoot } = ctx;
182
- const parsed = parseHeaderString(rawHeader);
183
- // Swift: 始终 `import Module`
184
- if (isSwift || parsed.isSwiftImport) {
185
- // 已经是完整 swift import 语句
186
- if (parsed.isSwiftImport) {
187
- return rawHeader.trim();
188
- }
189
- // 从 ObjC 格式推断 swift import
190
- const mod = parsed.moduleName || headerModuleName || '';
191
- if (mod) {
192
- return `import ${mod}`;
193
- }
194
- return rawHeader.trim(); // 无法推断,原样返回
195
- }
196
- // @import 保持原样(模块级引用不受 target 影响)
197
- if (parsed.isAtImport) {
198
- return rawHeader.trim();
199
- }
200
- // 已经是尖括号格式 → 保持(明确的跨模块引用)
201
- if (parsed.isAngle) {
202
- return rawHeader.trim();
203
- }
204
- // ── ObjC: 判断同 target vs 跨 target ──
205
- const effectiveModule = parsed.moduleName || headerModuleName || '';
206
- // 如果没有 target 信息,无法判断,保持原样
207
- if (!currentTarget || !effectiveModule) {
208
- return rawHeader.trim();
209
- }
210
- const isSameTarget = currentTarget === effectiveModule;
211
- if (isSameTarget) {
212
- // 同 target → 引号格式,计算相对路径
213
- if (parsed.headerName && fullPath) {
214
- const relPath = findHeaderRelativePath(parsed.headerName, fullPath, projectRoot);
215
- if (relPath) {
216
- return `#import "${relPath}"`;
217
- }
218
- }
219
- if (parsed.quotedPath) {
220
- return `#import "${parsed.quotedPath}"`;
221
- }
222
- if (parsed.headerName) {
223
- return `#import "${parsed.headerName}"`;
224
- }
225
- return rawHeader.trim();
226
- }
227
- // 跨 target → 尖括号格式 <Module/Header.h>
228
- if (parsed.headerName) {
229
- return `#import <${effectiveModule}/${parsed.headerName}>`;
230
- }
231
- // 没有 headerName(裸模块名),用 @import
232
- return `@import ${effectiveModule};`;
233
- }
234
- // ═══════════════════════════════════════════════════════════════
235
- // 三级 import 去重
236
- // ═══════════════════════════════════════════════════════════════
237
- /** 从文件中收集已有的 import 语句 */
238
- export function collectImportsFromFile(filePath, isSwift) {
239
- try {
240
- if (!existsSync(filePath)) {
241
- return [];
242
- }
243
- const content = readFileSync(filePath, 'utf8');
244
- const lines = content.split(/\r?\n/);
245
- const imports = [];
246
- for (const line of lines) {
247
- const t = line.trim();
248
- if (isSwift) {
249
- if (t.startsWith('import ')) {
250
- imports.push(t);
251
- }
252
- }
253
- else {
254
- if (t.startsWith('#import ') || t.startsWith('@import ') || t.startsWith('#include ')) {
255
- imports.push(t);
256
- }
257
- }
258
- }
259
- return imports;
260
- }
261
- catch {
262
- return [];
263
- }
264
- }
265
- /** 收集 .m 文件对应 .h 文件中的 imports(ObjC 接口/实现配对去重) */
266
- export function collectImportsFromHeaderFile(sourcePath, importArray) {
267
- const dotIndex = sourcePath.lastIndexOf('.');
268
- if (dotIndex <= 0) {
269
- return;
270
- }
271
- const headerPath = `${sourcePath.substring(0, dotIndex)}.h`;
272
- const importReg = /^#import\s*<[A-Za-z0-9_]+\/[A-Za-z0-9_+.-]+\.h>$/;
273
- try {
274
- if (!existsSync(headerPath)) {
275
- return;
276
- }
277
- const data = readFileSync(headerPath, 'utf8');
278
- for (const line of data.split('\n')) {
279
- const t = line.trim();
280
- if (importReg.test(t) && !importArray.includes(t)) {
281
- importArray.push(t);
282
- }
283
- }
284
- }
285
- catch {
286
- /* ignore */
287
- }
288
- }
289
- /**
290
- * 三级 import 去重检查
291
- *
292
- * hasHeader 精确匹配(同一 import 行)
293
- * hasModule 模块级匹配(同模块不同头文件,或 @import)
294
- * hasSimilarHeader 文件名 case-insensitive 匹配
295
- *
296
- * @param importArray 已有的 import 行
297
- * @param headerLine 待插入的 import 行
298
- */
299
- export function checkImportStatus(importArray, headerLine, isSwift) {
300
- const trimmed = headerLine.trim();
301
- // 提取 module / headerFileName
302
- let moduleName = '';
303
- let headerFileName = '';
304
- if (isSwift) {
305
- const m = trimmed.match(/^import\s+(\w+)/);
306
- if (m) {
307
- moduleName = m[1];
308
- }
309
- headerFileName = moduleName;
310
- }
311
- else {
312
- const angle = trimmed.match(/<([^/]+)\/([^>]+)>/);
313
- if (angle) {
314
- moduleName = angle[1];
315
- headerFileName = angle[2];
316
- }
317
- const quote = trimmed.match(/"([^"]+)"/);
318
- if (quote) {
319
- headerFileName = basename(quote[1]);
320
- }
321
- }
322
- const headerFileNameLower = headerFileName.toLowerCase();
323
- for (const imp of importArray) {
324
- const impT = imp.trim();
325
- // ── 级别 1: 精确匹配 ──
326
- if (impT === trimmed) {
327
- return { hasHeader: true, hasModule: false, hasSimilarHeader: false };
328
- }
329
- // 去掉可能的 AutoSnippet 注释后缀再比较
330
- const impTClean = impT.replace(/\s*\/\/\s*AutoSnippet.*$/, '').trim();
331
- if (impTClean === trimmed) {
332
- return { hasHeader: true, hasModule: false, hasSimilarHeader: false };
333
- }
334
- if (isSwift) {
335
- // ── 级别 2: Swift 模块匹配 ──
336
- const m2 = impT.match(/^import\s+(\w+)/);
337
- if (m2 && m2[1] === moduleName) {
338
- return { hasHeader: false, hasModule: true, hasSimilarHeader: false };
339
- }
340
- }
341
- else {
342
- // ── 级别 2: ObjC 模块匹配(<Module/xxx> 或 @import Module) ──
343
- if (moduleName) {
344
- const impAngle = impT.match(/<([^/]+)\//);
345
- if (impAngle && impAngle[1] === moduleName) {
346
- return { hasHeader: false, hasModule: true, hasSimilarHeader: false };
347
- }
348
- const impAt = impT.match(/@import\s+(\w+)/);
349
- if (impAt && impAt[1] === moduleName) {
350
- return { hasHeader: false, hasModule: true, hasSimilarHeader: false };
351
- }
352
- }
353
- // ── 级别 3: 相似头文件名匹配(case-insensitive) ──
354
- if (headerFileNameLower) {
355
- let importedFileName = null;
356
- const a = impT.match(/<[^/]+\/([^>]+)>/);
357
- if (a) {
358
- importedFileName = a[1].toLowerCase();
359
- }
360
- const q = impT.match(/"([^"]+)"/);
361
- if (q) {
362
- importedFileName = basename(q[1]).toLowerCase();
363
- }
364
- if (importedFileName && importedFileName === headerFileNameLower) {
365
- return { hasHeader: false, hasModule: false, hasSimilarHeader: true };
366
- }
367
- }
368
- }
369
- }
370
- return { hasHeader: false, hasModule: false, hasSimilarHeader: false };
371
- }
372
- // ═══════════════════════════════════════════════════════════════
373
- // 模块名推断
374
- // ═══════════════════════════════════════════════════════════════
375
- /**
376
- * 从 import 语句推断模块名
377
- *
378
- * #import <Module/Header.h> → Module
379
- * @import Module; → Module
380
- * import Module (Swift) → Module
381
- * #import "Local.h" → null
382
- */
383
- export function inferModulesFromHeaders(headers) {
384
- const modules = new Set();
385
- for (const h of headers) {
386
- const t = h.trim();
387
- let m;
388
- m = t.match(/^#import\s+<([^/> ]+)/);
389
- if (m) {
390
- modules.add(m[1]);
391
- continue;
392
- }
393
- m = t.match(/^@import\s+(\w+)/);
394
- if (m) {
395
- modules.add(m[1]);
396
- continue;
397
- }
398
- m = t.match(/^import\s+(\w+)/);
399
- if (m && !['class', 'struct', 'enum', 'protocol'].includes(m[1])) {
400
- modules.add(m[1]);
401
- }
402
- }
403
- return [...modules];
404
- }
@@ -1,89 +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
- /** FileWatcher 接口(仅用到的属性) */
16
- interface FileWatcherLike {
17
- projectRoot?: string;
18
- }
19
- /** 插入选项 */
20
- interface InsertHeadersOpts {
21
- depWarnings?: Map<string, string>;
22
- isSwift?: boolean;
23
- skipDepCheck?: boolean;
24
- moduleName?: string | null;
25
- _spmService?: SpmServiceLike | null;
26
- _currentTarget?: string | null;
27
- }
28
- /** 代码片段选择结果 */
29
- interface SelectedSnippet {
30
- code?: string;
31
- headers?: string[];
32
- moduleName?: string | null;
33
- title?: string;
34
- name?: string;
35
- trigger?: string;
36
- }
37
- /** SPM 服务接口 */
38
- interface SpmServiceLike {
39
- getFixMode(): string;
40
- load(): Promise<void>;
41
- resolveCurrentTarget(filePath: string): string | null;
42
- ensureDependency(from: string, to: string): {
43
- exists: boolean;
44
- canAdd: boolean;
45
- reason?: string;
46
- crossPackage?: boolean;
47
- };
48
- addDependency(from: string, to: string): {
49
- ok: boolean;
50
- error?: string;
51
- };
52
- }
53
- /**
54
- * 统一的头文件插入方法
55
- *
56
- * 逐条处理:
57
- * 1. 三级去重
58
- * 2. SPM 依赖检查(block/review/continue 决策)
59
- * 3. Xcode osascript 自动插入,失败则文件写入回退
60
- * 4. 附加 AutoSnippet 注释后缀
61
- *
62
- * @param fullPath 目标文件绝对路径
63
- * @param headers 待插入的 import 行数组
64
- * @returns >}
65
- */
66
- export declare function insertHeaders(watcher: FileWatcherLike | null, fullPath: string, headers: string[], opts?: InsertHeadersOpts): Promise<{
67
- inserted: string[];
68
- skipped: string[];
69
- cancelled: boolean;
70
- }>;
71
- /**
72
- * 将选中的搜索结果代码插入 Xcode
73
- *
74
- * 流程:
75
- * 1. 找到触发行号
76
- * 2. Preflight — 预检依赖决策(不实际写入)
77
- * 3. Cut 触发行内容(Xcode 剪切,不写文件)
78
- * 4. 构建带缩进 + 注释标记的代码块
79
- * 5. 插入 Headers(Xcode osascript / 文件写入)
80
- * 6. 计算偏移后的粘贴行号(computePasteLineNumber)
81
- * 7. Jump 到粘贴行 → 选中行内容 → Cmd+V 粘贴替换
82
- * 8. 任一步失败 → 降级到纯文件写入
83
- */
84
- export declare function insertCodeToXcode(watcher: FileWatcherLike | null, fullPath: string, selected: SelectedSnippet, triggerLine: string): Promise<void>;
85
- /** 查找触发行的行号(1-based,-1 表示未找到) */
86
- export declare function findTriggerLineNumber(content: string, triggerLine: string): number;
87
- /** 查找 import 语句的插入位置(0-based 行索引,在最后一个 import 之后) */
88
- export declare function findImportInsertLine(content: string, isSwift: boolean): number;
89
- export {};