autosnippet 1.1.13 → 1.1.14
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +36 -36
- package/bin/asnip.js +67 -8
- package/bin/cache.js +7 -8
- package/bin/config.js +89 -0
- package/bin/create.js +151 -41
- package/bin/findPath.js +290 -128
- package/bin/injection.js +45 -76
- package/bin/install.js +131 -13
- package/package.json +4 -4
package/bin/findPath.js
CHANGED
|
@@ -4,189 +4,351 @@ const fs = require('fs');
|
|
|
4
4
|
const path = require('path');
|
|
5
5
|
// 全局常量
|
|
6
6
|
const HOLDER_NAME = 'AutoSnippet.boxspec.json';
|
|
7
|
-
const
|
|
8
|
-
const POD_SPEC_NAME = '.podspec';
|
|
7
|
+
const PACKAGE_SWIFT = 'Package.swift';
|
|
9
8
|
const README_NAME = 'readme.md';
|
|
10
|
-
const PCH_NAME = '.pch';
|
|
11
9
|
|
|
12
|
-
//
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (err) {
|
|
16
|
-
console.log(err);
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
let isEnd = false;
|
|
21
|
-
files.forEach(function (filename) {
|
|
10
|
+
// 目录缓存(优化:减少重复读取)
|
|
11
|
+
const directoryCache = new Map();
|
|
12
|
+
const CACHE_TTL = 60000; // 缓存 60 秒
|
|
22
13
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
14
|
+
/**
|
|
15
|
+
* 获取目录内容(带缓存)
|
|
16
|
+
*/
|
|
17
|
+
async function getDirectoryEntries(dirPath) {
|
|
18
|
+
const cacheKey = path.resolve(dirPath);
|
|
19
|
+
const cached = directoryCache.get(cacheKey);
|
|
20
|
+
|
|
21
|
+
if (cached && Date.now() - cached.timestamp < CACHE_TTL) {
|
|
22
|
+
return cached.entries;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
try {
|
|
26
|
+
const entries = await fs.promises.readdir(dirPath, {
|
|
27
|
+
withFileTypes: true // 返回 Dirent 对象,减少 stat 调用
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
// 清理过期缓存(保持缓存大小合理)
|
|
31
|
+
if (directoryCache.size > 1000) {
|
|
32
|
+
const now = Date.now();
|
|
33
|
+
for (const [key, value] of directoryCache.entries()) {
|
|
34
|
+
if (now - value.timestamp >= CACHE_TTL) {
|
|
35
|
+
directoryCache.delete(key);
|
|
36
|
+
}
|
|
26
37
|
}
|
|
27
|
-
});
|
|
28
|
-
|
|
29
|
-
if (isEnd) {
|
|
30
|
-
return;
|
|
31
38
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
39
|
+
|
|
40
|
+
directoryCache.set(cacheKey, {
|
|
41
|
+
entries,
|
|
42
|
+
timestamp: Date.now()
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
return entries;
|
|
46
|
+
} catch (err) {
|
|
47
|
+
if (err.code === 'ENOENT' || err.code === 'EACCES') {
|
|
48
|
+
return null; // 路径不存在或权限不足
|
|
37
49
|
}
|
|
38
|
-
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
39
52
|
}
|
|
40
53
|
|
|
41
|
-
//
|
|
42
|
-
function
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
// 向上查找AutoSnippet配置文件(优化:找到配置文件后,最多再向上查找两层停止)
|
|
55
|
+
async function findASSpecPathAsync(filePath) {
|
|
56
|
+
let configPath = null;
|
|
57
|
+
let levelsUp = 0;
|
|
58
|
+
let currentPath = path.resolve(filePath);
|
|
59
|
+
|
|
60
|
+
while (currentPath) {
|
|
61
|
+
try {
|
|
62
|
+
const entries = await getDirectoryEntries(currentPath);
|
|
63
|
+
if (!entries) {
|
|
64
|
+
// 目录不存在,继续向上
|
|
65
|
+
const parentPath = path.dirname(currentPath);
|
|
66
|
+
if (parentPath === currentPath) {
|
|
67
|
+
break; // 已到达根目录
|
|
68
|
+
}
|
|
69
|
+
currentPath = parentPath;
|
|
70
|
+
continue;
|
|
55
71
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
72
|
+
|
|
73
|
+
// 查找 AutoSnippet.boxspec.json
|
|
74
|
+
for (const entry of entries) {
|
|
75
|
+
if (entry.isFile() && entry.name === HOLDER_NAME) {
|
|
76
|
+
if (!configPath) {
|
|
77
|
+
// 第一次找到配置文件
|
|
78
|
+
configPath = path.join(currentPath, entry.name);
|
|
79
|
+
}
|
|
80
|
+
// 找到后,标记为已找到,继续向上最多两层
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// 如果已经找到配置文件,检查是否已经向上查找了两层
|
|
85
|
+
if (configPath) {
|
|
86
|
+
if (path.resolve(currentPath) !== path.dirname(configPath)) {
|
|
87
|
+
// 当前目录不是配置文件所在目录,说明已经向上查找了
|
|
88
|
+
levelsUp++;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// 如果已经向上查找了两层,停止查找
|
|
92
|
+
if (levelsUp >= 2) {
|
|
93
|
+
return configPath;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
// 继续向上查找
|
|
98
|
+
const parentPath = path.dirname(currentPath);
|
|
99
|
+
if (parentPath === currentPath) {
|
|
100
|
+
// 已到达根目录
|
|
101
|
+
break;
|
|
102
|
+
}
|
|
103
|
+
currentPath = parentPath;
|
|
104
|
+
|
|
105
|
+
} catch (err) {
|
|
106
|
+
// 错误处理:权限错误继续查找
|
|
107
|
+
if (err.code === 'ENOENT' || err.code === 'EACCES') {
|
|
108
|
+
const parentPath = path.dirname(currentPath);
|
|
109
|
+
if (parentPath === currentPath) {
|
|
110
|
+
break;
|
|
111
|
+
}
|
|
112
|
+
currentPath = parentPath;
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
// 其他错误,抛出
|
|
116
|
+
throw err;
|
|
66
117
|
}
|
|
67
|
-
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
return configPath || null;
|
|
68
121
|
}
|
|
69
122
|
|
|
70
|
-
//
|
|
71
|
-
function
|
|
123
|
+
// 向上查找AutoSnippet配置文件(保留回调版本,兼容现有代码)
|
|
124
|
+
function findASSpecPath(filePath, callback, configPath, levelsUp) {
|
|
125
|
+
// 初始化参数
|
|
126
|
+
if (configPath === undefined) configPath = null;
|
|
127
|
+
if (levelsUp === undefined) levelsUp = 0;
|
|
128
|
+
|
|
72
129
|
fs.readdir(filePath, function (err, files) {
|
|
73
130
|
if (err) {
|
|
74
131
|
console.log(err);
|
|
75
132
|
return;
|
|
76
133
|
}
|
|
77
134
|
|
|
78
|
-
let
|
|
79
|
-
let
|
|
80
|
-
let readme = null;
|
|
81
|
-
let specName = null;
|
|
82
|
-
|
|
135
|
+
let isFound = false;
|
|
136
|
+
let foundConfigPath = configPath;
|
|
83
137
|
files.forEach(function (filename) {
|
|
84
138
|
if (filename === HOLDER_NAME) {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
const dotIndex = filename.lastIndexOf('.');
|
|
92
|
-
const ext = filename.substr(dotIndex);
|
|
93
|
-
|
|
94
|
-
if (ext === BOX_SPEC_NAME || ext === POD_SPEC_NAME) {
|
|
95
|
-
specName = filename;
|
|
96
|
-
isEnd = true;
|
|
97
|
-
}
|
|
139
|
+
isFound = true;
|
|
140
|
+
if (!foundConfigPath) {
|
|
141
|
+
// 第一次找到配置文件,记录路径并调用回调
|
|
142
|
+
foundConfigPath = path.resolve(filePath);
|
|
143
|
+
callback(path.join(filePath, filename));
|
|
144
|
+
}
|
|
98
145
|
}
|
|
99
146
|
});
|
|
100
147
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
148
|
+
// 如果已经找到配置文件,检查是否已经向上查找了两层
|
|
149
|
+
if (foundConfigPath) {
|
|
150
|
+
if (!isFound) {
|
|
151
|
+
// 当前目录不是配置文件所在目录,说明已经向上查找了
|
|
152
|
+
levelsUp++;
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
// 如果已经向上查找了两层,停止查找
|
|
156
|
+
if (levelsUp >= 2) {
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
104
159
|
}
|
|
105
160
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
161
|
+
// 如果还没找到配置文件,继续向上查找
|
|
162
|
+
if (!foundConfigPath) {
|
|
163
|
+
// 继续向上查找
|
|
164
|
+
const parentPath = path.join(filePath, '/..');
|
|
165
|
+
const parentResolvedPath = path.resolve(parentPath);
|
|
166
|
+
|
|
167
|
+
// 如果已经到达根目录,停止查找
|
|
168
|
+
if (parentResolvedPath === path.resolve(filePath)) {
|
|
169
|
+
console.log('未找到 AutoSnippet.boxspec.json 文件,请检查路径。');
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
110
172
|
|
|
111
|
-
|
|
112
|
-
findBPSpacPath(path.join(filePath, '/..'), callback);
|
|
173
|
+
findASSpecPath(parentPath, callback, foundConfigPath, 0);
|
|
113
174
|
} else {
|
|
114
|
-
|
|
175
|
+
// 已经找到配置文件,继续向上查找(最多两层)
|
|
176
|
+
const parentPath = path.join(filePath, '/..');
|
|
177
|
+
const parentResolvedPath = path.resolve(parentPath);
|
|
178
|
+
|
|
179
|
+
// 如果已经到达根目录,停止查找
|
|
180
|
+
if (parentResolvedPath === path.resolve(filePath)) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
findASSpecPath(parentPath, callback, foundConfigPath, levelsUp);
|
|
115
185
|
}
|
|
116
186
|
});
|
|
117
187
|
}
|
|
118
188
|
|
|
119
|
-
//
|
|
120
|
-
async function
|
|
121
|
-
let
|
|
189
|
+
// 向上查找 Package.swift 文件(SPM 模块规范文件)
|
|
190
|
+
async function findPackageSwiftPath(filePath) {
|
|
191
|
+
let currentPath = path.resolve(filePath);
|
|
192
|
+
|
|
193
|
+
while (currentPath) {
|
|
194
|
+
try {
|
|
195
|
+
const entries = await getDirectoryEntries(currentPath);
|
|
196
|
+
if (!entries) {
|
|
197
|
+
const parentPath = path.dirname(currentPath);
|
|
198
|
+
if (parentPath === currentPath) {
|
|
199
|
+
break;
|
|
200
|
+
}
|
|
201
|
+
currentPath = parentPath;
|
|
202
|
+
continue;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// 查找 Package.swift 文件
|
|
206
|
+
for (const entry of entries) {
|
|
207
|
+
if (entry.isFile() && entry.name === PACKAGE_SWIFT) {
|
|
208
|
+
return path.join(currentPath, entry.name);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// 继续向上查找
|
|
213
|
+
const parentPath = path.dirname(currentPath);
|
|
214
|
+
if (parentPath === currentPath) {
|
|
215
|
+
break;
|
|
216
|
+
}
|
|
217
|
+
currentPath = parentPath;
|
|
218
|
+
|
|
219
|
+
} catch (err) {
|
|
220
|
+
if (err.code === 'ENOENT' || err.code === 'EACCES') {
|
|
221
|
+
const parentPath = path.dirname(currentPath);
|
|
222
|
+
if (parentPath === currentPath) {
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
currentPath = parentPath;
|
|
226
|
+
continue;
|
|
227
|
+
}
|
|
228
|
+
throw err;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
return null;
|
|
233
|
+
}
|
|
122
234
|
|
|
235
|
+
/**
|
|
236
|
+
* 解析 Package.swift 文件,提取模块信息
|
|
237
|
+
*/
|
|
238
|
+
async function parsePackageSwift(packagePath) {
|
|
123
239
|
try {
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
240
|
+
const content = await fs.promises.readFile(packagePath, 'utf8');
|
|
241
|
+
|
|
242
|
+
// 简单解析 Package.swift(实际可以使用 Swift AST 解析器)
|
|
243
|
+
const packageNameMatch = content.match(/name:\s*"([^"]+)"/);
|
|
244
|
+
const targetsMatch = content.match(/\.target\s*\([^)]+name:\s*"([^"]+)"/g);
|
|
245
|
+
|
|
246
|
+
const packageName = packageNameMatch ? packageNameMatch[1] : null;
|
|
247
|
+
const targets = [];
|
|
248
|
+
|
|
249
|
+
if (targetsMatch) {
|
|
250
|
+
targetsMatch.forEach(match => {
|
|
251
|
+
const targetMatch = match.match(/name:\s*"([^"]+)"/);
|
|
252
|
+
if (targetMatch) {
|
|
253
|
+
targets.push(targetMatch[1]);
|
|
254
|
+
}
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
return {
|
|
259
|
+
name: packageName,
|
|
260
|
+
targets: targets,
|
|
261
|
+
path: path.dirname(packagePath)
|
|
262
|
+
};
|
|
263
|
+
} catch (err) {
|
|
264
|
+
console.error('Error parsing Package.swift:', err);
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
129
268
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
269
|
+
// 向下查找模块头文件(优化:适配 SPM 结构,优先查找 include/ModuleName/ 目录)
|
|
270
|
+
async function findSubHeaderPath(filePath, headerName, moduleName) {
|
|
271
|
+
// ✅ 优先查找 include/ModuleName/ 目录(SPM 结构)
|
|
272
|
+
if (moduleName) {
|
|
273
|
+
const includePath = path.join(filePath, 'include', moduleName);
|
|
274
|
+
try {
|
|
275
|
+
const stats = await fs.promises.stat(includePath);
|
|
276
|
+
if (stats.isDirectory()) {
|
|
277
|
+
const headerPath = path.join(includePath, `${headerName}.h`);
|
|
134
278
|
try {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
279
|
+
await fs.promises.access(headerPath);
|
|
280
|
+
return headerPath;
|
|
281
|
+
} catch {
|
|
282
|
+
// 头文件不存在,继续查找
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
} catch {
|
|
286
|
+
// include 目录不存在,继续查找
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// ✅ 降级:在整个模块目录中查找(深度限制)
|
|
291
|
+
try {
|
|
292
|
+
const entries = await getDirectoryEntries(filePath);
|
|
293
|
+
if (!entries) {
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
for (const entry of entries) {
|
|
298
|
+
if (entry.isFile() && entry.name === `${headerName}.h`) {
|
|
299
|
+
return path.join(filePath, entry.name);
|
|
300
|
+
} else if (entry.isDirectory()) {
|
|
301
|
+
// 跳过 node_modules、.git 等目录
|
|
302
|
+
if (entry.name.startsWith('.') || entry.name === 'node_modules') {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
const result = await findSubHeaderPath(path.join(filePath, entry.name), headerName, null);
|
|
307
|
+
if (result) {
|
|
308
|
+
return result;
|
|
146
309
|
}
|
|
147
310
|
}
|
|
148
311
|
}
|
|
149
312
|
} catch (err) {
|
|
150
|
-
console.
|
|
313
|
+
console.error(err);
|
|
151
314
|
}
|
|
152
|
-
|
|
315
|
+
|
|
316
|
+
return null;
|
|
153
317
|
}
|
|
154
318
|
|
|
155
|
-
// 向下查找AutoSnippet
|
|
319
|
+
// 向下查找AutoSnippet配置文件(优化:异步 I/O)
|
|
156
320
|
async function findSubASSpecPath(filePath) {
|
|
157
321
|
let resultArray = [];
|
|
158
322
|
|
|
159
323
|
try {
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const filedir = path.join(filePath, filename);
|
|
324
|
+
const entries = await getDirectoryEntries(filePath);
|
|
325
|
+
if (!entries) {
|
|
326
|
+
return resultArray;
|
|
327
|
+
}
|
|
165
328
|
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
if (isDirectory) {
|
|
174
|
-
const array = await findSubASSpecPath(filedir);
|
|
175
|
-
resultArray = resultArray.concat(array);
|
|
176
|
-
}
|
|
177
|
-
} catch (err) {
|
|
178
|
-
console.error(err);
|
|
329
|
+
for (const entry of entries) {
|
|
330
|
+
if (entry.isFile() && entry.name === HOLDER_NAME) {
|
|
331
|
+
resultArray.push(path.join(filePath, entry.name));
|
|
332
|
+
} else if (entry.isDirectory()) {
|
|
333
|
+
// 跳过 node_modules、.git 等目录
|
|
334
|
+
if (entry.name.startsWith('.') || entry.name === 'node_modules') {
|
|
335
|
+
continue;
|
|
179
336
|
}
|
|
337
|
+
|
|
338
|
+
const array = await findSubASSpecPath(path.join(filePath, entry.name));
|
|
339
|
+
resultArray = resultArray.concat(array);
|
|
180
340
|
}
|
|
181
341
|
}
|
|
182
342
|
} catch (err) {
|
|
183
343
|
console.log(err);
|
|
184
344
|
}
|
|
345
|
+
|
|
185
346
|
return resultArray;
|
|
186
347
|
}
|
|
187
348
|
|
|
188
349
|
exports.findASSpecPath = findASSpecPath;
|
|
189
|
-
exports.
|
|
190
|
-
exports.
|
|
350
|
+
exports.findASSpecPathAsync = findASSpecPathAsync;
|
|
351
|
+
exports.findPackageSwiftPath = findPackageSwiftPath;
|
|
352
|
+
exports.parsePackageSwift = parsePackageSwift;
|
|
191
353
|
exports.findSubHeaderPath = findSubHeaderPath;
|
|
192
|
-
exports.findSubASSpecPath = findSubASSpecPath;
|
|
354
|
+
exports.findSubASSpecPath = findSubASSpecPath;
|
package/bin/injection.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
const fs = require('fs');
|
|
4
|
+
const fsPromises = require('fs').promises;
|
|
4
5
|
const path = require('path');
|
|
5
6
|
const readline = require('readline');
|
|
6
7
|
const findPath = require('./findPath.js');
|
|
@@ -86,65 +87,23 @@ function handleModuleHeader(specFile, updateFile, header, importArray, isOuter)
|
|
|
86
87
|
const headName = isOuter ? header.name : header.headerStrName;
|
|
87
88
|
const moduleName = isOuter ? header.specName : header.moduleStrName;
|
|
88
89
|
|
|
89
|
-
|
|
90
|
-
|
|
90
|
+
// 检查是否已经引入头文件
|
|
91
91
|
for (let i = 0; i < importArray.length; i++) {
|
|
92
92
|
const importHeader = importArray[i].split(importMark)[1].trim();
|
|
93
93
|
|
|
94
94
|
if (importHeader === headName) {
|
|
95
95
|
// 已经引入头文件
|
|
96
96
|
handelAddHeaderStatus(specFile, updateFile, header, true, false);
|
|
97
|
-
|
|
98
|
-
break;
|
|
97
|
+
return;
|
|
99
98
|
} else if (importHeader === moduleName) {
|
|
100
99
|
// 已经引入spec头文件
|
|
101
100
|
handelAddHeaderStatus(specFile, updateFile, header, false, true);
|
|
102
|
-
|
|
103
|
-
break;
|
|
101
|
+
return;
|
|
104
102
|
}
|
|
105
103
|
}
|
|
106
104
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
const slashIndex = updateFile.lastIndexOf('/');
|
|
110
|
-
const thePath = updateFile.substring(0, slashIndex + 1);
|
|
111
|
-
|
|
112
|
-
findPath.findPCHPath(thePath, function (success, pchName) {
|
|
113
|
-
if (success) {
|
|
114
|
-
try {
|
|
115
|
-
// 读取.pch文件
|
|
116
|
-
const data = fs.readFileSync(pchName, 'utf8');
|
|
117
|
-
const lineArray = data.split('\n');
|
|
118
|
-
|
|
119
|
-
let isAddedHeader = false;
|
|
120
|
-
let isAddedSpecHeader = false;
|
|
121
|
-
|
|
122
|
-
lineArray.forEach(element => {
|
|
123
|
-
const lineVal = element.trim();
|
|
124
|
-
|
|
125
|
-
if (importReg.test(lineVal)) {
|
|
126
|
-
const importHeader = lineVal.split(importMark)[1].trim();
|
|
127
|
-
|
|
128
|
-
if (importHeader === header.name
|
|
129
|
-
|| importHeader === header.headerStrName) {
|
|
130
|
-
isAddedHeader = true;
|
|
131
|
-
} else if (importHeader === header.specName
|
|
132
|
-
|| importHeader === header.moduleStrName) {
|
|
133
|
-
isAddedSpecHeader = true;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
handelAddHeaderStatus(specFile, updateFile, header, isAddedHeader, isAddedSpecHeader);
|
|
139
|
-
} catch (err) {
|
|
140
|
-
console.error(err);
|
|
141
|
-
}
|
|
142
|
-
} else {
|
|
143
|
-
// 没有找到pch文件
|
|
144
|
-
addHeaderToFile(updateFile, header);
|
|
145
|
-
}
|
|
146
|
-
});
|
|
147
|
-
}
|
|
105
|
+
// 没有找到已引入的头文件,直接添加
|
|
106
|
+
addHeaderToFile(updateFile, header);
|
|
148
107
|
}
|
|
149
108
|
|
|
150
109
|
function handelAddHeaderStatus(specFile, updateFile, header, isAddedHeader, isAddedSpecHeader) {
|
|
@@ -204,47 +163,57 @@ function isAddedToSpecHeader(specFile, header, callback) {
|
|
|
204
163
|
|
|
205
164
|
function removeMarkFromFile(updateFile, header, string) {
|
|
206
165
|
readStream(updateFile, null, importMark);
|
|
207
|
-
checkDependency(updateFile, header.moduleName, string)
|
|
166
|
+
checkDependency(updateFile, header.moduleName, string).catch(err => {
|
|
167
|
+
console.error('Error checking dependency:', err);
|
|
168
|
+
});
|
|
208
169
|
}
|
|
209
170
|
|
|
210
171
|
function addHeaderToFile(updateFile, header) {
|
|
211
172
|
readStream(updateFile, importMark + ' ' + header.name, importMark);
|
|
212
|
-
checkDependency(updateFile, header.moduleName, '自动注入头文件完成。')
|
|
173
|
+
checkDependency(updateFile, header.moduleName, '自动注入头文件完成。').catch(err => {
|
|
174
|
+
console.error('Error checking dependency:', err);
|
|
175
|
+
});
|
|
213
176
|
}
|
|
214
177
|
|
|
215
|
-
function checkDependency(updateFile, moduleName, string) {
|
|
178
|
+
async function checkDependency(updateFile, moduleName, string) {
|
|
216
179
|
const slashIndex = updateFile.lastIndexOf('/');
|
|
217
180
|
const thePath = updateFile.substring(0, slashIndex + 1);
|
|
218
181
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
let isHaveDependency = false;
|
|
228
|
-
|
|
229
|
-
lineArray.forEach(element => {
|
|
230
|
-
const lineVal = element.trim();
|
|
182
|
+
try {
|
|
183
|
+
// ✅ 使用 SPM 的 Package.swift 查找(替代 .boxspec)
|
|
184
|
+
const packagePath = await findPath.findPackageSwiftPath(thePath);
|
|
185
|
+
if (!packagePath) {
|
|
186
|
+
displayNotification(string);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
231
189
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
190
|
+
// 解析 Package.swift 获取模块信息
|
|
191
|
+
const packageInfo = await findPath.parsePackageSwift(packagePath);
|
|
192
|
+
if (!packageInfo) {
|
|
193
|
+
displayNotification(string);
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
238
196
|
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
197
|
+
// 检查依赖关系(在 Package.swift 的 dependencies 中查找)
|
|
198
|
+
const packageContent = await fs.promises.readFile(packagePath, 'utf8');
|
|
199
|
+
|
|
200
|
+
// 检查是否在 dependencies 中
|
|
201
|
+
const dependencyPattern = new RegExp(`\\.package\\([^)]*"([^"]*${moduleName}[^"]*)"`, 'g');
|
|
202
|
+
const targetDependencyPattern = new RegExp(`\\.product\\([^)]*name:\\s*"([^"]*${moduleName}[^"]*)"`, 'g');
|
|
203
|
+
|
|
204
|
+
const hasDependency = dependencyPattern.test(packageContent) ||
|
|
205
|
+
targetDependencyPattern.test(packageContent) ||
|
|
206
|
+
packageInfo.targets.includes(moduleName);
|
|
207
|
+
|
|
208
|
+
if (hasDependency) {
|
|
209
|
+
displayNotification(string);
|
|
210
|
+
} else {
|
|
211
|
+
displayNotification(string + '\nPackage.swift 未发现依赖项,请检查模块是否引入。');
|
|
246
212
|
}
|
|
247
|
-
})
|
|
213
|
+
} catch (err) {
|
|
214
|
+
console.error(err);
|
|
215
|
+
displayNotification(string);
|
|
216
|
+
}
|
|
248
217
|
}
|
|
249
218
|
|
|
250
219
|
function readStream(filePath, headerName, currImportMark) {
|