@appthen/cli 1.2.7 → 1.2.10
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/dist/index.js +339 -913
- package/package.json +1 -2
package/dist/index.js
CHANGED
|
@@ -29,7 +29,6 @@ var prettier = require('prettier');
|
|
|
29
29
|
var fs$2 = require('fs-extra');
|
|
30
30
|
var io = require('socket.io-client');
|
|
31
31
|
var fs$3 = require('fs/promises');
|
|
32
|
-
var chokidar = require('chokidar');
|
|
33
32
|
var whatwgUrl = require('whatwg-url');
|
|
34
33
|
|
|
35
34
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
@@ -81,7 +80,6 @@ var fs__default$1 = /*#__PURE__*/_interopDefaultLegacy(fs$2);
|
|
|
81
80
|
var fs__namespace$1 = /*#__PURE__*/_interopNamespace(fs$2);
|
|
82
81
|
var io__default = /*#__PURE__*/_interopDefaultLegacy(io);
|
|
83
82
|
var fs__default$2 = /*#__PURE__*/_interopDefaultLegacy(fs$3);
|
|
84
|
-
var chokidar__default = /*#__PURE__*/_interopDefaultLegacy(chokidar);
|
|
85
83
|
var whatwgUrl__default = /*#__PURE__*/_interopDefaultLegacy(whatwgUrl);
|
|
86
84
|
|
|
87
85
|
/******************************************************************************
|
|
@@ -18821,8 +18819,9 @@ var request = function (url, params, _a) {
|
|
|
18821
18819
|
};
|
|
18822
18820
|
return [4 /*yield*/, axios({
|
|
18823
18821
|
method: method,
|
|
18824
|
-
url: (process.env.DEV
|
|
18825
|
-
|
|
18822
|
+
url: (process.env.DEV
|
|
18823
|
+
? 'http://127.0.0.1:1626'
|
|
18824
|
+
: 'https://editor.appthen.com') + url,
|
|
18826
18825
|
data: params,
|
|
18827
18826
|
headers: headers,
|
|
18828
18827
|
})];
|
|
@@ -37940,7 +37939,9 @@ var SocketStore = /** @class */ (function () {
|
|
|
37940
37939
|
var _this = this;
|
|
37941
37940
|
var _a = this.config, token = _a.token, onconnect = _a.onconnect, onlogined = _a.onlogined, onreconnect = _a.onreconnect; _a.onmsg;
|
|
37942
37941
|
console.log('token: ', token);
|
|
37943
|
-
var
|
|
37942
|
+
var SOCKET_SERVER = DEV_MODE$1 ? devServer : server;
|
|
37943
|
+
console.log('SOCKET_SERVER: ', SOCKET_SERVER);
|
|
37944
|
+
var socket = io__default["default"](SOCKET_SERVER, {
|
|
37944
37945
|
transports: ['websocket'],
|
|
37945
37946
|
query: {
|
|
37946
37947
|
token: token,
|
|
@@ -40667,6 +40668,8 @@ function regExpEscape (s) {
|
|
|
40667
40668
|
return s.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&')
|
|
40668
40669
|
}
|
|
40669
40670
|
|
|
40671
|
+
// import chokidar, { FSWatcher } from 'chokidar';
|
|
40672
|
+
var logger = function () { };
|
|
40670
40673
|
/**
|
|
40671
40674
|
* 影子空间管理器
|
|
40672
40675
|
* 维护编辑器状态的本地镜像,用于检测文件变更
|
|
@@ -40764,34 +40767,13 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40764
40767
|
// 尝试迁移旧的状态文件
|
|
40765
40768
|
_a.sent();
|
|
40766
40769
|
// 初始化时扫描并同步项目文件
|
|
40767
|
-
|
|
40768
|
-
|
|
40769
|
-
// 初始化时扫描并同步项目文件
|
|
40770
|
-
_a.sent();
|
|
40771
|
-
console.log("\u5F71\u5B50\u7A7A\u95F4 [".concat(this.config.spaceId, "] \u5DF2\u521D\u59CB\u5316"));
|
|
40770
|
+
// await this.initialSync();
|
|
40771
|
+
logger("\u5F71\u5B50\u7A7A\u95F4 [".concat(this.config.spaceId, "] \u5DF2\u521D\u59CB\u5316"));
|
|
40772
40772
|
return [2 /*return*/];
|
|
40773
40773
|
}
|
|
40774
40774
|
});
|
|
40775
40775
|
});
|
|
40776
40776
|
};
|
|
40777
|
-
/**
|
|
40778
|
-
* 初始化时扫描项目目录并同步文件
|
|
40779
|
-
*/
|
|
40780
|
-
ShadowSpace.prototype.initialSync = function () {
|
|
40781
|
-
return __awaiter(this, void 0, void 0, function () {
|
|
40782
|
-
return __generator(this, function (_a) {
|
|
40783
|
-
try {
|
|
40784
|
-
console.log('开始初始化文件同步...');
|
|
40785
|
-
// 暂时跳过初始化文件扫描,避免glob相关错误
|
|
40786
|
-
console.log('跳过初始化文件扫描(功能开发中)');
|
|
40787
|
-
}
|
|
40788
|
-
catch (error) {
|
|
40789
|
-
console.warn('初始化文件同步失败:', error);
|
|
40790
|
-
}
|
|
40791
|
-
return [2 /*return*/];
|
|
40792
|
-
});
|
|
40793
|
-
});
|
|
40794
|
-
};
|
|
40795
40777
|
// 暂时移除scanProjectFiles方法,避免glob相关错误
|
|
40796
40778
|
/**
|
|
40797
40779
|
* 从编辑器同步项目文件到影子空间
|
|
@@ -40804,7 +40786,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40804
40786
|
return __generator(this, function (_g) {
|
|
40805
40787
|
switch (_g.label) {
|
|
40806
40788
|
case 0:
|
|
40807
|
-
|
|
40789
|
+
logger("\u5F00\u59CB\u4ECE\u7F16\u8F91\u5668\u540C\u6B65 ".concat(projectFiles.length, " \u4E2A\u6587\u4EF6..."));
|
|
40808
40790
|
newFiles = {};
|
|
40809
40791
|
_g.label = 1;
|
|
40810
40792
|
case 1:
|
|
@@ -40815,15 +40797,11 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40815
40797
|
if (!!projectFiles_1_1.done) return [3 /*break*/, 6];
|
|
40816
40798
|
file = projectFiles_1_1.value;
|
|
40817
40799
|
if (this.shouldIgnoreFile(file.path)) {
|
|
40818
|
-
|
|
40800
|
+
logger("[ShadowSpace] \u6587\u4EF6\u88AB\u5FFD\u7565: ".concat(file.path));
|
|
40819
40801
|
return [3 /*break*/, 5];
|
|
40820
40802
|
}
|
|
40821
40803
|
size = Buffer.byteLength(file.content, 'utf8');
|
|
40822
40804
|
now = Date.now();
|
|
40823
|
-
// 记录空内容文件
|
|
40824
|
-
if (file.content === '') {
|
|
40825
|
-
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u7A7A\u5185\u5BB9\u6587\u4EF6: ".concat(file.path, " (size: ").concat(size, ")"));
|
|
40826
|
-
}
|
|
40827
40805
|
// 写入本地文件
|
|
40828
40806
|
return [4 /*yield*/, this.writeLocalFile(file.path, file.content)];
|
|
40829
40807
|
case 3:
|
|
@@ -40834,31 +40812,9 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40834
40812
|
case 4:
|
|
40835
40813
|
writtenContent = _g.sent();
|
|
40836
40814
|
localHash = this.calculateHash(writtenContent);
|
|
40837
|
-
console.log('localHash: ', localHash);
|
|
40838
40815
|
remoteHash = file.hash || localHash;
|
|
40839
40816
|
// 🔍 检测哈希差异,帮助诊断编码问题
|
|
40840
|
-
if (file.hash && file.hash !== localHash)
|
|
40841
|
-
console.warn("[ShadowSpace] \u68C0\u6D4B\u5230\u54C8\u5E0C\u4E0D\u4E00\u81F4: ".concat(file.path), {
|
|
40842
|
-
editorHash: file.hash.substring(0, 16),
|
|
40843
|
-
localHash: localHash.substring(0, 16),
|
|
40844
|
-
editorHashFull: file.hash,
|
|
40845
|
-
localHashFull: localHash,
|
|
40846
|
-
contentLength: file.content.length,
|
|
40847
|
-
writtenLength: writtenContent.length,
|
|
40848
|
-
contentSame: file.content === writtenContent,
|
|
40849
|
-
filePath: file.path,
|
|
40850
|
-
});
|
|
40851
|
-
// 如果内容相同但哈希不同,可能是编码问题
|
|
40852
|
-
if (file.content === writtenContent) {
|
|
40853
|
-
console.error("[ShadowSpace] \u26A0\uFE0F \u5185\u5BB9\u76F8\u540C\u4F46\u54C8\u5E0C\u4E0D\u540C\uFF0C\u53EF\u80FD\u5B58\u5728\u7F16\u7801\u95EE\u9898: ".concat(file.path));
|
|
40854
|
-
}
|
|
40855
|
-
else {
|
|
40856
|
-
console.error("[ShadowSpace] \u26A0\uFE0F \u5185\u5BB9\u4E0D\u540C\uFF0C\u53EF\u80FD\u662F\u6587\u4EF6\u5199\u5165\u8FC7\u7A0B\u4E2D\u7684\u8F6C\u6362\u95EE\u9898: ".concat(file.path));
|
|
40857
|
-
// 显示前100个字符的差异
|
|
40858
|
-
console.log("\u7F16\u8F91\u5668\u5185\u5BB9\u524D100\u5B57\u7B26: ".concat(JSON.stringify(file.content.substring(0, 100))));
|
|
40859
|
-
console.log("\u5199\u5165\u5185\u5BB9\u524D100\u5B57\u7B26: ".concat(JSON.stringify(writtenContent.substring(0, 100))));
|
|
40860
|
-
}
|
|
40861
|
-
}
|
|
40817
|
+
if (file.hash && file.hash !== localHash) ;
|
|
40862
40818
|
newFiles[file.path] = {
|
|
40863
40819
|
path: file.path,
|
|
40864
40820
|
hash: localHash,
|
|
@@ -40871,12 +40827,6 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40871
40827
|
remoteModified: true,
|
|
40872
40828
|
remoteModifiedTime: now,
|
|
40873
40829
|
};
|
|
40874
|
-
console.log("[ShadowSpace] \u540C\u6B65\u6587\u4EF6: ".concat(file.path), {
|
|
40875
|
-
remoteHash: remoteHash.substring(0, 16),
|
|
40876
|
-
localHash: localHash.substring(0, 16),
|
|
40877
|
-
size: size,
|
|
40878
|
-
version: newFiles[file.path].version,
|
|
40879
|
-
});
|
|
40880
40830
|
// 缓存内容用于diff
|
|
40881
40831
|
this.contentCache.set(file.path, writtenContent);
|
|
40882
40832
|
_g.label = 5;
|
|
@@ -40917,16 +40867,16 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40917
40867
|
totalSize: totalSizeSum,
|
|
40918
40868
|
lastSyncWithEditor: Date.now(),
|
|
40919
40869
|
};
|
|
40920
|
-
|
|
40921
|
-
|
|
40922
|
-
|
|
40923
|
-
|
|
40924
|
-
});
|
|
40870
|
+
// logger('[ShadowSpace] 更新后的文件统计:', {
|
|
40871
|
+
// totalFiles: totalFilesCount,
|
|
40872
|
+
// totalSize: totalSizeSum,
|
|
40873
|
+
// // fileList: Object.keys(this.state.files),
|
|
40874
|
+
// });
|
|
40925
40875
|
this.state.lastUpdateTime = Date.now();
|
|
40926
40876
|
return [4 /*yield*/, this.saveState()];
|
|
40927
40877
|
case 10:
|
|
40928
40878
|
_g.sent();
|
|
40929
|
-
|
|
40879
|
+
logger("\u5F71\u5B50\u7A7A\u95F4\u540C\u6B65\u5B8C\u6210: ".concat(this.state.metadata.totalFiles, " \u4E2A\u6587\u4EF6"));
|
|
40930
40880
|
return [2 /*return*/];
|
|
40931
40881
|
}
|
|
40932
40882
|
});
|
|
@@ -40972,7 +40922,9 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40972
40922
|
return [4 /*yield*/, this.saveState()];
|
|
40973
40923
|
case 2:
|
|
40974
40924
|
_a.sent();
|
|
40975
|
-
|
|
40925
|
+
// logger(
|
|
40926
|
+
// `影子空间文件已更新: ${filePath} (v${this.state.files[filePath].version})`
|
|
40927
|
+
// );
|
|
40976
40928
|
return [2 /*return*/, true];
|
|
40977
40929
|
}
|
|
40978
40930
|
});
|
|
@@ -40999,7 +40951,6 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
40999
40951
|
return [4 /*yield*/, fs__default$1["default"].unlink(fullPath)];
|
|
41000
40952
|
case 2:
|
|
41001
40953
|
_a.sent();
|
|
41002
|
-
console.log("\u672C\u5730\u6587\u4EF6\u5DF2\u5220\u9664: ".concat(fullPath));
|
|
41003
40954
|
return [3 /*break*/, 4];
|
|
41004
40955
|
case 3:
|
|
41005
40956
|
error_1 = _a.sent();
|
|
@@ -41013,7 +40964,6 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41013
40964
|
return [4 /*yield*/, this.saveState()];
|
|
41014
40965
|
case 5:
|
|
41015
40966
|
_a.sent();
|
|
41016
|
-
console.log("\u5F71\u5B50\u7A7A\u95F4\u6587\u4EF6\u5DF2\u5220\u9664: ".concat(filePath));
|
|
41017
40967
|
return [2 /*return*/, true];
|
|
41018
40968
|
}
|
|
41019
40969
|
});
|
|
@@ -41024,64 +40974,57 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41024
40974
|
* 注意:跳过 remoteModified 标记的文件,避免与编辑器检测冲突
|
|
41025
40975
|
*/
|
|
41026
40976
|
ShadowSpace.prototype.detectChanges = function () {
|
|
41027
|
-
var _a;
|
|
41028
40977
|
return __awaiter(this, void 0, void 0, function () {
|
|
41029
|
-
var changes, _b, _c,
|
|
41030
|
-
var e_3,
|
|
41031
|
-
return __generator(this, function (
|
|
41032
|
-
switch (
|
|
40978
|
+
var changes, _a, _b, _c, filePath, shadowEntry, localFilePath, localContent, localHash, fileStat, fileModifyTime, shadowContent, _d, _e, error_2, shadowContent, e_3_1, localFiles, localFiles_1, localFiles_1_1, localFile;
|
|
40979
|
+
var e_3, _f, _g, e_4, _h;
|
|
40980
|
+
return __generator(this, function (_j) {
|
|
40981
|
+
switch (_j.label) {
|
|
41033
40982
|
case 0:
|
|
41034
40983
|
changes = [];
|
|
41035
|
-
|
|
40984
|
+
_j.label = 1;
|
|
41036
40985
|
case 1:
|
|
41037
|
-
|
|
41038
|
-
|
|
41039
|
-
|
|
40986
|
+
_j.trys.push([1, 16, 17, 18]);
|
|
40987
|
+
_a = __values(Object.entries(this.state.files)), _b = _a.next();
|
|
40988
|
+
_j.label = 2;
|
|
41040
40989
|
case 2:
|
|
41041
|
-
if (!!
|
|
41042
|
-
|
|
40990
|
+
if (!!_b.done) return [3 /*break*/, 15];
|
|
40991
|
+
_c = __read(_b.value, 2), filePath = _c[0], shadowEntry = _c[1];
|
|
41043
40992
|
localFilePath = path__default["default"].join(this.config.projectRoot, filePath);
|
|
41044
|
-
|
|
40993
|
+
_j.label = 3;
|
|
41045
40994
|
case 3:
|
|
41046
|
-
|
|
40995
|
+
_j.trys.push([3, 11, , 14]);
|
|
41047
40996
|
return [4 /*yield*/, fs__default$1["default"].readFile(localFilePath, 'utf8')];
|
|
41048
40997
|
case 4:
|
|
41049
|
-
localContent =
|
|
40998
|
+
localContent = _j.sent();
|
|
41050
40999
|
localHash = this.calculateHash(localContent);
|
|
41051
41000
|
if (!(localHash !== shadowEntry.hash)) return [3 /*break*/, 10];
|
|
41052
|
-
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(filePath), {
|
|
41053
|
-
localHash: localHash.substring(0, 16),
|
|
41054
|
-
shadowHash: shadowEntry.hash.substring(0, 16),
|
|
41055
|
-
remoteHash: ((_a = shadowEntry.remoteHash) === null || _a === void 0 ? void 0 : _a.substring(0, 16)) || 'undefined',
|
|
41056
|
-
remoteModified: shadowEntry.remoteModified || false,
|
|
41057
|
-
version: shadowEntry.version,
|
|
41058
|
-
});
|
|
41059
41001
|
if (!shadowEntry.remoteModified) return [3 /*break*/, 7];
|
|
41060
|
-
console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u4FEE\u6539\u6587\u4EF6\u7684\u672C\u5730\u68C0\u6D4B: ".concat(filePath, "\uFF0C\u5C06\u7531\u65F6\u95F4\u6233\u6BD4\u5BF9\u51B3\u5B9A\u65B9\u5411"));
|
|
41061
41002
|
return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
|
|
41062
41003
|
case 5:
|
|
41063
|
-
fileStat =
|
|
41004
|
+
fileStat = _j.sent();
|
|
41064
41005
|
fileModifyTime = fileStat.mtimeMs;
|
|
41065
|
-
|
|
41066
|
-
|
|
41067
|
-
|
|
41068
|
-
|
|
41069
|
-
|
|
41070
|
-
|
|
41006
|
+
// logger(`[ShadowSpace] 🔍 更新文件时间戳: ${filePath}`, {
|
|
41007
|
+
// 旧lastModified: new Date(
|
|
41008
|
+
// shadowEntry.lastModified || 0
|
|
41009
|
+
// ).toISOString(),
|
|
41010
|
+
// 旧mtime: new Date(shadowEntry.mtime || 0).toISOString(),
|
|
41011
|
+
// 新fileModifyTime: new Date(fileModifyTime).toISOString(),
|
|
41012
|
+
// 时间戳是否变化: fileModifyTime !== shadowEntry.lastModified,
|
|
41013
|
+
// });
|
|
41071
41014
|
// 更新影子空间记录,清除远程修改标记
|
|
41072
41015
|
this.state.files[filePath] = __assign(__assign({}, shadowEntry), { hash: localHash, size: fileStat.size, lastSyncTime: Date.now(), version: shadowEntry.version + 1, mtime: fileModifyTime, lastModified: fileModifyTime, remoteModified: false });
|
|
41073
41016
|
// 保存状态
|
|
41074
41017
|
return [4 /*yield*/, this.saveState()];
|
|
41075
41018
|
case 6:
|
|
41076
41019
|
// 保存状态
|
|
41077
|
-
|
|
41020
|
+
_j.sent();
|
|
41078
41021
|
// 🔥 跳过,不添加到 changes
|
|
41079
41022
|
return [3 /*break*/, 14];
|
|
41080
41023
|
case 7: return [4 /*yield*/, this.getShadowContent(filePath)];
|
|
41081
41024
|
case 8:
|
|
41082
|
-
shadowContent =
|
|
41083
|
-
|
|
41084
|
-
|
|
41025
|
+
shadowContent = _j.sent();
|
|
41026
|
+
_e = (_d = changes).push;
|
|
41027
|
+
_g = {
|
|
41085
41028
|
id: this.generateId(),
|
|
41086
41029
|
action: 'modify',
|
|
41087
41030
|
path: filePath,
|
|
@@ -41089,21 +41032,21 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41089
41032
|
};
|
|
41090
41033
|
return [4 /*yield*/, fs__default$1["default"].stat(localFilePath)];
|
|
41091
41034
|
case 9:
|
|
41092
|
-
|
|
41093
|
-
|
|
41035
|
+
_e.apply(_d, [(_g.timestamp = (_j.sent()).mtime.getTime(),
|
|
41036
|
+
_g.diff = {
|
|
41094
41037
|
before: shadowContent,
|
|
41095
41038
|
after: localContent,
|
|
41096
41039
|
},
|
|
41097
|
-
|
|
41098
|
-
|
|
41099
|
-
|
|
41040
|
+
_g.projectId = this.state.projectId,
|
|
41041
|
+
_g)]);
|
|
41042
|
+
_j.label = 10;
|
|
41100
41043
|
case 10: return [3 /*break*/, 14];
|
|
41101
41044
|
case 11:
|
|
41102
|
-
error_2 =
|
|
41045
|
+
error_2 = _j.sent();
|
|
41103
41046
|
if (!(error_2.code === 'ENOENT')) return [3 /*break*/, 13];
|
|
41104
41047
|
return [4 /*yield*/, this.getShadowContent(filePath)];
|
|
41105
41048
|
case 12:
|
|
41106
|
-
shadowContent =
|
|
41049
|
+
shadowContent = _j.sent();
|
|
41107
41050
|
changes.push({
|
|
41108
41051
|
id: this.generateId(),
|
|
41109
41052
|
action: 'delete',
|
|
@@ -41116,25 +41059,25 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41116
41059
|
},
|
|
41117
41060
|
projectId: this.state.projectId,
|
|
41118
41061
|
});
|
|
41119
|
-
|
|
41062
|
+
_j.label = 13;
|
|
41120
41063
|
case 13: return [3 /*break*/, 14];
|
|
41121
41064
|
case 14:
|
|
41122
|
-
|
|
41065
|
+
_b = _a.next();
|
|
41123
41066
|
return [3 /*break*/, 2];
|
|
41124
41067
|
case 15: return [3 /*break*/, 18];
|
|
41125
41068
|
case 16:
|
|
41126
|
-
e_3_1 =
|
|
41069
|
+
e_3_1 = _j.sent();
|
|
41127
41070
|
e_3 = { error: e_3_1 };
|
|
41128
41071
|
return [3 /*break*/, 18];
|
|
41129
41072
|
case 17:
|
|
41130
41073
|
try {
|
|
41131
|
-
if (
|
|
41074
|
+
if (_b && !_b.done && (_f = _a.return)) _f.call(_a);
|
|
41132
41075
|
}
|
|
41133
41076
|
finally { if (e_3) throw e_3.error; }
|
|
41134
41077
|
return [7 /*endfinally*/];
|
|
41135
41078
|
case 18: return [4 /*yield*/, this.scanLocalFiles()];
|
|
41136
41079
|
case 19:
|
|
41137
|
-
localFiles =
|
|
41080
|
+
localFiles = _j.sent();
|
|
41138
41081
|
try {
|
|
41139
41082
|
for (localFiles_1 = __values(localFiles), localFiles_1_1 = localFiles_1.next(); !localFiles_1_1.done; localFiles_1_1 = localFiles_1.next()) {
|
|
41140
41083
|
localFile = localFiles_1_1.value;
|
|
@@ -41157,7 +41100,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41157
41100
|
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
41158
41101
|
finally {
|
|
41159
41102
|
try {
|
|
41160
|
-
if (localFiles_1_1 && !localFiles_1_1.done && (
|
|
41103
|
+
if (localFiles_1_1 && !localFiles_1_1.done && (_h = localFiles_1.return)) _h.call(localFiles_1);
|
|
41161
41104
|
}
|
|
41162
41105
|
finally { if (e_4) throw e_4.error; }
|
|
41163
41106
|
}
|
|
@@ -41215,7 +41158,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41215
41158
|
finally { if (e_5) throw e_5.error; }
|
|
41216
41159
|
return [7 /*endfinally*/];
|
|
41217
41160
|
case 11:
|
|
41218
|
-
|
|
41161
|
+
logger("\u5F71\u5B50\u7A7A\u95F4\u5DF2\u5E94\u7528 ".concat(changes.length, " \u4E2A\u53D8\u66F4"));
|
|
41219
41162
|
return [2 /*return*/];
|
|
41220
41163
|
}
|
|
41221
41164
|
});
|
|
@@ -41227,7 +41170,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41227
41170
|
ShadowSpace.prototype.getSpaceInfo = function () {
|
|
41228
41171
|
var actualFileCount = Object.keys(this.state.files).length;
|
|
41229
41172
|
var metadataFileCount = this.state.metadata.totalFiles;
|
|
41230
|
-
|
|
41173
|
+
logger("[ShadowSpace] getSpaceInfo: spaceId=".concat(this.state.spaceId, ", metadata.totalFiles=").concat(metadataFileCount, ", actual files=").concat(actualFileCount));
|
|
41231
41174
|
return {
|
|
41232
41175
|
spaceId: this.state.spaceId,
|
|
41233
41176
|
projectId: this.state.projectId,
|
|
@@ -41262,7 +41205,6 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41262
41205
|
case 0:
|
|
41263
41206
|
// 检查文件是否在影子空间中
|
|
41264
41207
|
if (!this.hasFile(filePath)) {
|
|
41265
|
-
console.log("[ShadowSpace] \u6587\u4EF6\u4E0D\u5728\u5F71\u5B50\u7A7A\u95F4\u4E2D: ".concat(filePath));
|
|
41266
41208
|
return [2 /*return*/, null];
|
|
41267
41209
|
}
|
|
41268
41210
|
_a.label = 1;
|
|
@@ -41271,7 +41213,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41271
41213
|
return [4 /*yield*/, this.getShadowContent(filePath)];
|
|
41272
41214
|
case 2:
|
|
41273
41215
|
content = _a.sent();
|
|
41274
|
-
|
|
41216
|
+
logger("[ShadowSpace] \u6210\u529F\u8BFB\u53D6\u6587\u4EF6: ".concat(filePath, ", \u957F\u5EA6: ").concat(content.length));
|
|
41275
41217
|
return [2 /*return*/, content];
|
|
41276
41218
|
case 3:
|
|
41277
41219
|
error_3 = _a.sent();
|
|
@@ -41301,7 +41243,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41301
41243
|
return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
|
|
41302
41244
|
case 2:
|
|
41303
41245
|
content = _a.sent();
|
|
41304
|
-
|
|
41246
|
+
logger("[ShadowSpace] \u5B9E\u65F6\u8BFB\u53D6\u6587\u4EF6\u6210\u529F: ".concat(filePath, ", \u957F\u5EA6: ").concat(content.length));
|
|
41305
41247
|
// 可选:更新内存缓存以确保一致性
|
|
41306
41248
|
this.contentCache.set(filePath, content);
|
|
41307
41249
|
return [2 /*return*/, content];
|
|
@@ -41319,33 +41261,32 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41319
41261
|
* 当编辑器通过WebSocket修改文件后调用此方法
|
|
41320
41262
|
*/
|
|
41321
41263
|
ShadowSpace.prototype.markAsRemoteModified = function (filePaths) {
|
|
41322
|
-
var _a;
|
|
41323
41264
|
return __awaiter(this, void 0, void 0, function () {
|
|
41324
41265
|
var now, hasChanges, filePaths_1, filePaths_1_1, filePath, fullPath, stats, content, hash, existingFile, remoteHash, error_5, e_6_1;
|
|
41325
|
-
var e_6,
|
|
41326
|
-
return __generator(this, function (
|
|
41327
|
-
switch (
|
|
41266
|
+
var e_6, _a;
|
|
41267
|
+
return __generator(this, function (_b) {
|
|
41268
|
+
switch (_b.label) {
|
|
41328
41269
|
case 0:
|
|
41329
41270
|
now = Date.now();
|
|
41330
41271
|
hasChanges = false;
|
|
41331
|
-
|
|
41272
|
+
_b.label = 1;
|
|
41332
41273
|
case 1:
|
|
41333
|
-
|
|
41274
|
+
_b.trys.push([1, 9, 10, 11]);
|
|
41334
41275
|
filePaths_1 = __values(filePaths), filePaths_1_1 = filePaths_1.next();
|
|
41335
|
-
|
|
41276
|
+
_b.label = 2;
|
|
41336
41277
|
case 2:
|
|
41337
41278
|
if (!!filePaths_1_1.done) return [3 /*break*/, 8];
|
|
41338
41279
|
filePath = filePaths_1_1.value;
|
|
41339
41280
|
fullPath = path__default["default"].resolve(this.config.projectRoot, filePath);
|
|
41340
|
-
|
|
41281
|
+
_b.label = 3;
|
|
41341
41282
|
case 3:
|
|
41342
|
-
|
|
41283
|
+
_b.trys.push([3, 6, , 7]);
|
|
41343
41284
|
return [4 /*yield*/, fs__default$1["default"].stat(fullPath)];
|
|
41344
41285
|
case 4:
|
|
41345
|
-
stats =
|
|
41286
|
+
stats = _b.sent();
|
|
41346
41287
|
return [4 /*yield*/, fs__default$1["default"].readFile(fullPath, 'utf8')];
|
|
41347
41288
|
case 5:
|
|
41348
|
-
content =
|
|
41289
|
+
content = _b.sent();
|
|
41349
41290
|
hash = this.calculateHash(content);
|
|
41350
41291
|
existingFile = this.state.files[filePath];
|
|
41351
41292
|
remoteHash = (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) || hash;
|
|
@@ -41362,16 +41303,9 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41362
41303
|
remoteModifiedTime: now,
|
|
41363
41304
|
};
|
|
41364
41305
|
hasChanges = true;
|
|
41365
|
-
console.log("[ShadowSpace] \u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539: ".concat(filePath), {
|
|
41366
|
-
版本: this.state.files[filePath].version,
|
|
41367
|
-
hash: hash.substring(0, 16),
|
|
41368
|
-
remoteHash: remoteHash.substring(0, 16),
|
|
41369
|
-
旧remoteHash: ((_a = existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) === null || _a === void 0 ? void 0 : _a.substring(0, 16)) || 'undefined',
|
|
41370
|
-
remoteHashChanged: (existingFile === null || existingFile === void 0 ? void 0 : existingFile.remoteHash) !== remoteHash,
|
|
41371
|
-
});
|
|
41372
41306
|
return [3 /*break*/, 7];
|
|
41373
41307
|
case 6:
|
|
41374
|
-
error_5 =
|
|
41308
|
+
error_5 = _b.sent();
|
|
41375
41309
|
console.warn("\u6807\u8BB0\u8FDC\u7A0B\u4FEE\u6539\u5931\u8D25 ".concat(filePath, ":"), error_5);
|
|
41376
41310
|
return [3 /*break*/, 7];
|
|
41377
41311
|
case 7:
|
|
@@ -41379,12 +41313,12 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41379
41313
|
return [3 /*break*/, 2];
|
|
41380
41314
|
case 8: return [3 /*break*/, 11];
|
|
41381
41315
|
case 9:
|
|
41382
|
-
e_6_1 =
|
|
41316
|
+
e_6_1 = _b.sent();
|
|
41383
41317
|
e_6 = { error: e_6_1 };
|
|
41384
41318
|
return [3 /*break*/, 11];
|
|
41385
41319
|
case 10:
|
|
41386
41320
|
try {
|
|
41387
|
-
if (filePaths_1_1 && !filePaths_1_1.done && (
|
|
41321
|
+
if (filePaths_1_1 && !filePaths_1_1.done && (_a = filePaths_1.return)) _a.call(filePaths_1);
|
|
41388
41322
|
}
|
|
41389
41323
|
finally { if (e_6) throw e_6.error; }
|
|
41390
41324
|
return [7 /*endfinally*/];
|
|
@@ -41393,9 +41327,8 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41393
41327
|
this.updateMetadata();
|
|
41394
41328
|
return [4 /*yield*/, this.saveState()];
|
|
41395
41329
|
case 12:
|
|
41396
|
-
|
|
41397
|
-
|
|
41398
|
-
_c.label = 13;
|
|
41330
|
+
_b.sent();
|
|
41331
|
+
_b.label = 13;
|
|
41399
41332
|
case 13: return [2 /*return*/];
|
|
41400
41333
|
}
|
|
41401
41334
|
});
|
|
@@ -41436,7 +41369,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41436
41369
|
return [4 /*yield*/, this.saveState()];
|
|
41437
41370
|
case 1:
|
|
41438
41371
|
_c.sent();
|
|
41439
|
-
|
|
41372
|
+
logger("\u5DF2\u6E05\u9664 ".concat(pathsToProcess.length, " \u4E2A\u6587\u4EF6\u7684\u8FDC\u7A0B\u4FEE\u6539\u6807\u8BB0"));
|
|
41440
41373
|
_c.label = 2;
|
|
41441
41374
|
case 2: return [2 /*return*/];
|
|
41442
41375
|
}
|
|
@@ -41448,34 +41381,23 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41448
41381
|
* 用于与编辑器快照进行比对
|
|
41449
41382
|
*/
|
|
41450
41383
|
ShadowSpace.prototype.getSpaceSnapshots = function (_spaceId) {
|
|
41451
|
-
var _a, _b;
|
|
41452
41384
|
return __awaiter(this, void 0, void 0, function () {
|
|
41453
|
-
var snapshots,
|
|
41454
|
-
var e_8,
|
|
41455
|
-
return __generator(this, function (
|
|
41456
|
-
switch (
|
|
41385
|
+
var snapshots, _a, _b, _c, filePath, shadowEntry, modifyTime, error_6;
|
|
41386
|
+
var e_8, _d;
|
|
41387
|
+
return __generator(this, function (_e) {
|
|
41388
|
+
switch (_e.label) {
|
|
41457
41389
|
case 0:
|
|
41458
|
-
|
|
41390
|
+
_e.trys.push([0, 2, , 3]);
|
|
41459
41391
|
// 确保状态已加载
|
|
41460
41392
|
return [4 /*yield*/, this.loadState()];
|
|
41461
41393
|
case 1:
|
|
41462
41394
|
// 确保状态已加载
|
|
41463
|
-
|
|
41395
|
+
_e.sent();
|
|
41464
41396
|
snapshots = [];
|
|
41465
41397
|
try {
|
|
41466
41398
|
// 遍历影子空间中的所有文件
|
|
41467
|
-
for (
|
|
41468
|
-
|
|
41469
|
-
// 🔍 调试哈希差异
|
|
41470
|
-
if (shadowEntry.hash !== shadowEntry.remoteHash) {
|
|
41471
|
-
console.log("[ShadowSpace] \u5FEB\u7167\u4E2D\u7684\u54C8\u5E0C\u5DEE\u5F02: ".concat(filePath), {
|
|
41472
|
-
localHash: (_a = shadowEntry.hash) === null || _a === void 0 ? void 0 : _a.substring(0, 16),
|
|
41473
|
-
remoteHash: (_b = shadowEntry.remoteHash) === null || _b === void 0 ? void 0 : _b.substring(0, 16),
|
|
41474
|
-
localHashFull: shadowEntry.hash,
|
|
41475
|
-
remoteHashFull: shadowEntry.remoteHash,
|
|
41476
|
-
remoteModified: shadowEntry.remoteModified,
|
|
41477
|
-
});
|
|
41478
|
-
}
|
|
41399
|
+
for (_a = __values(Object.entries(this.state.files)), _b = _a.next(); !_b.done; _b = _a.next()) {
|
|
41400
|
+
_c = __read(_b.value, 2), filePath = _c[0], shadowEntry = _c[1];
|
|
41479
41401
|
modifyTime = shadowEntry.mtime ||
|
|
41480
41402
|
shadowEntry.lastModified ||
|
|
41481
41403
|
shadowEntry.lastSyncTime ||
|
|
@@ -41494,15 +41416,15 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41494
41416
|
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
|
41495
41417
|
finally {
|
|
41496
41418
|
try {
|
|
41497
|
-
if (
|
|
41419
|
+
if (_b && !_b.done && (_d = _a.return)) _d.call(_a);
|
|
41498
41420
|
}
|
|
41499
41421
|
finally { if (e_8) throw e_8.error; }
|
|
41500
41422
|
}
|
|
41501
|
-
|
|
41423
|
+
logger("[ShadowSpace] \u83B7\u53D6\u7A7A\u95F4\u5FEB\u7167: ".concat(snapshots.length, " \u4E2A\u6587\u4EF6"));
|
|
41502
41424
|
return [2 /*return*/, snapshots];
|
|
41503
41425
|
case 2:
|
|
41504
|
-
error_6 =
|
|
41505
|
-
console.error(
|
|
41426
|
+
error_6 = _e.sent();
|
|
41427
|
+
console.error('[ShadowSpace] 获取空间快照失败:', error_6);
|
|
41506
41428
|
return [2 /*return*/, []]; // 返回空数组而不是 undefined
|
|
41507
41429
|
case 3: return [2 /*return*/];
|
|
41508
41430
|
}
|
|
@@ -41529,7 +41451,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41529
41451
|
_a.sent();
|
|
41530
41452
|
return [3 /*break*/, 4];
|
|
41531
41453
|
case 4:
|
|
41532
|
-
|
|
41454
|
+
logger("\u5F71\u5B50\u7A7A\u95F4 [".concat(this.config.spaceId, "] \u5DF2\u6E05\u7406"));
|
|
41533
41455
|
return [2 /*return*/];
|
|
41534
41456
|
}
|
|
41535
41457
|
});
|
|
@@ -41555,7 +41477,6 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41555
41477
|
var dirName = path__default["default"].basename(absolutePath);
|
|
41556
41478
|
// 组合生成空间ID: 目录名-路径hash
|
|
41557
41479
|
var spaceId = "".concat(dirName, "-").concat(pathHash);
|
|
41558
|
-
console.log("[ShadowSpace] \u751F\u6210\u7A7A\u95F4ID: ".concat(spaceId, " (\u8DEF\u5F84: ").concat(absolutePath, ")"));
|
|
41559
41480
|
return spaceId;
|
|
41560
41481
|
};
|
|
41561
41482
|
/**
|
|
@@ -41585,11 +41506,10 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41585
41506
|
return [4 /*yield*/, fs__default$1["default"].writeFile(configFile, JSON.stringify(config, null, 2))];
|
|
41586
41507
|
case 3:
|
|
41587
41508
|
_a.sent();
|
|
41588
|
-
console.log("[ShadowSpace] \u7A7A\u95F4\u914D\u7F6E\u5DF2\u4FDD\u5B58: ".concat(configFile));
|
|
41589
41509
|
return [3 /*break*/, 5];
|
|
41590
41510
|
case 4:
|
|
41591
41511
|
error_8 = _a.sent();
|
|
41592
|
-
console.warn(
|
|
41512
|
+
console.warn('[ShadowSpace] 保存空间配置失败:', error_8);
|
|
41593
41513
|
return [3 /*break*/, 5];
|
|
41594
41514
|
case 5: return [2 /*return*/];
|
|
41595
41515
|
}
|
|
@@ -41609,15 +41529,14 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41609
41529
|
case 0:
|
|
41610
41530
|
_b.trys.push([0, 12, , 13]);
|
|
41611
41531
|
appthenDir = path__default["default"].join(this.config.projectRoot, '.appthen');
|
|
41612
|
-
console.log("[ShadowSpace] \u68C0\u67E5\u8FC1\u79FB: ".concat(appthenDir));
|
|
41613
41532
|
return [4 /*yield*/, fs__default$1["default"].readdir(appthenDir)];
|
|
41614
41533
|
case 1:
|
|
41615
41534
|
files = _b.sent();
|
|
41616
|
-
|
|
41535
|
+
logger("[ShadowSpace] .appthen\u76EE\u5F55\u6587\u4EF6: ".concat(files.join(', ')));
|
|
41617
41536
|
oldStateFiles = files.filter(function (file) {
|
|
41618
41537
|
return file.startsWith('shadow-space-') &&
|
|
41619
41538
|
file.endsWith('.json') &&
|
|
41620
|
-
!file.includes(_this.config.spaceId);
|
|
41539
|
+
!file.includes(_this.config.spaceId || '');
|
|
41621
41540
|
});
|
|
41622
41541
|
_b.label = 2;
|
|
41623
41542
|
case 2:
|
|
@@ -41634,7 +41553,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41634
41553
|
if (!(oldState.projectId === this.config.projectId &&
|
|
41635
41554
|
oldState.userId === this.config.userId &&
|
|
41636
41555
|
Object.keys(oldState.files || {}).length > 0)) return [3 /*break*/, 7];
|
|
41637
|
-
|
|
41556
|
+
logger("[ShadowSpace] \u53D1\u73B0\u65E7\u72B6\u6001\u6587\u4EF6: ".concat(oldFile, "\uFF0C\u5305\u542B ").concat(Object.keys(oldState.files).length, " \u4E2A\u6587\u4EF6"));
|
|
41638
41557
|
// 更新状态文件的spaceId
|
|
41639
41558
|
oldState.spaceId = this.config.spaceId;
|
|
41640
41559
|
// 合并到当前状态(优先使用旧状态的数据)
|
|
@@ -41648,8 +41567,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41648
41567
|
return [4 /*yield*/, fs__default$1["default"].move(oldFilePath, backupFile)];
|
|
41649
41568
|
case 6:
|
|
41650
41569
|
_b.sent();
|
|
41651
|
-
|
|
41652
|
-
console.log("[ShadowSpace] \u65E7\u6587\u4EF6\u5DF2\u5907\u4EFD\u4E3A: ".concat(backupFile));
|
|
41570
|
+
logger("[ShadowSpace] \u5DF2\u8FC1\u79FB ".concat(Object.keys(this.state.files).length, " \u4E2A\u6587\u4EF6\u5230\u65B0\u7A7A\u95F4 ").concat(this.config.spaceId));
|
|
41653
41571
|
return [3 /*break*/, 8]; // 只迁移第一个匹配的文件
|
|
41654
41572
|
case 7:
|
|
41655
41573
|
oldStateFiles_1_1 = oldStateFiles_1.next();
|
|
@@ -41668,7 +41586,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41668
41586
|
case 11: return [3 /*break*/, 13];
|
|
41669
41587
|
case 12:
|
|
41670
41588
|
error_9 = _b.sent();
|
|
41671
|
-
console.warn(
|
|
41589
|
+
console.warn('[ShadowSpace] 迁移旧状态文件失败:', error_9);
|
|
41672
41590
|
return [3 /*break*/, 13];
|
|
41673
41591
|
case 13: return [2 /*return*/];
|
|
41674
41592
|
}
|
|
@@ -41714,7 +41632,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41714
41632
|
return "change_".concat(Date.now(), "_").concat(Math.random().toString(36).substr(2, 9));
|
|
41715
41633
|
};
|
|
41716
41634
|
ShadowSpace.prototype.shouldIgnoreFile = function (filePath) {
|
|
41717
|
-
//
|
|
41635
|
+
// logger(`[ShadowSpace] shouldIgnoreFile 检查: "${filePath}"`);
|
|
41718
41636
|
var e_10, _a;
|
|
41719
41637
|
// 特殊处理:过滤掉特定的系统文件
|
|
41720
41638
|
var fileName = filePath.split('/').pop() || '';
|
|
@@ -41724,9 +41642,6 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41724
41642
|
if (fileName === 'assets.json') {
|
|
41725
41643
|
return true;
|
|
41726
41644
|
}
|
|
41727
|
-
if (fileName === 'project.json') {
|
|
41728
|
-
return true;
|
|
41729
|
-
}
|
|
41730
41645
|
if (fileName.endsWith('.doc')) {
|
|
41731
41646
|
return true;
|
|
41732
41647
|
}
|
|
@@ -41735,12 +41650,10 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41735
41650
|
var isInDocs = filePath.startsWith('docs/');
|
|
41736
41651
|
var isRootConfig = filePath.match(/^[^\/]+\.(json|md|yml|yaml|toml|js|ts|py|go|rs)$/);
|
|
41737
41652
|
if (!isInSrc && !isInDocs && !isRootConfig) {
|
|
41738
|
-
console.log("[ShadowSpace] \u6587\u4EF6\u4E0D\u5728\u767D\u540D\u5355\u76EE\u5F55\u4E2D: ".concat(filePath));
|
|
41739
41653
|
return true;
|
|
41740
41654
|
}
|
|
41741
41655
|
// 特殊处理:不忽略其他 .json 文件(即使以 . 开头)
|
|
41742
41656
|
if (filePath.endsWith('.json')) {
|
|
41743
|
-
console.log("[ShadowSpace] JSON\u6587\u4EF6\u4E0D\u5FFD\u7565: ".concat(filePath));
|
|
41744
41657
|
return false;
|
|
41745
41658
|
}
|
|
41746
41659
|
try {
|
|
@@ -41748,7 +41661,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41748
41661
|
for (var _b = __values(this.config.ignorePatterns || []), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
41749
41662
|
var pattern = _c.value;
|
|
41750
41663
|
if (minimatch_1(filePath, pattern)) {
|
|
41751
|
-
|
|
41664
|
+
logger("[ShadowSpace] \u6587\u4EF6\u5339\u914D\u5FFD\u7565\u6A21\u5F0F: ".concat(filePath, " -> ").concat(pattern));
|
|
41752
41665
|
return true;
|
|
41753
41666
|
}
|
|
41754
41667
|
}
|
|
@@ -41765,11 +41678,10 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41765
41678
|
this.config.includeExtensions.length > 0) {
|
|
41766
41679
|
var ext = path__default["default"].extname(filePath).toLowerCase();
|
|
41767
41680
|
if (!this.config.includeExtensions.includes(ext)) {
|
|
41768
|
-
console.log("[ShadowSpace] \u6587\u4EF6\u6269\u5C55\u540D\u4E0D\u5728\u767D\u540D\u5355: ".concat(filePath, " -> ").concat(ext));
|
|
41769
41681
|
return true;
|
|
41770
41682
|
}
|
|
41771
41683
|
}
|
|
41772
|
-
//
|
|
41684
|
+
// logger(`[ShadowSpace] 文件通过忽略检查: ${filePath}`);
|
|
41773
41685
|
return false;
|
|
41774
41686
|
};
|
|
41775
41687
|
ShadowSpace.prototype.writeLocalFile = function (filePath, content) {
|
|
@@ -41779,7 +41691,7 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41779
41691
|
switch (_a.label) {
|
|
41780
41692
|
case 0:
|
|
41781
41693
|
fullPath = path__default["default"].join(this.config.projectRoot, filePath);
|
|
41782
|
-
|
|
41694
|
+
logger('[ShadowSpace] 写入文件:', {
|
|
41783
41695
|
filePath: filePath,
|
|
41784
41696
|
fullPath: fullPath,
|
|
41785
41697
|
projectRoot: this.config.projectRoot,
|
|
@@ -41794,7 +41706,6 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41794
41706
|
return [4 /*yield*/, fs__default$1["default"].writeFile(fullPath, content, 'utf8')];
|
|
41795
41707
|
case 3:
|
|
41796
41708
|
_a.sent();
|
|
41797
|
-
console.log("[ShadowSpace] \u6587\u4EF6\u5199\u5165\u6210\u529F: ".concat(fullPath));
|
|
41798
41709
|
return [3 /*break*/, 5];
|
|
41799
41710
|
case 4:
|
|
41800
41711
|
error_11 = _a.sent();
|
|
@@ -41918,8 +41829,6 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41918
41829
|
return [3 /*break*/, 3];
|
|
41919
41830
|
case 2:
|
|
41920
41831
|
_a.sent();
|
|
41921
|
-
// 文件不存在或解析失败,使用默认状态
|
|
41922
|
-
console.log("\u5F71\u5B50\u7A7A\u95F4\u72B6\u6001\u6587\u4EF6\u4E0D\u5B58\u5728\uFF0C\u4F7F\u7528\u9ED8\u8BA4\u72B6\u6001");
|
|
41923
41832
|
return [3 /*break*/, 3];
|
|
41924
41833
|
case 3: return [2 /*return*/];
|
|
41925
41834
|
}
|
|
@@ -41939,60 +41848,60 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
41939
41848
|
* 启动文件监听
|
|
41940
41849
|
*/
|
|
41941
41850
|
ShadowSpace.prototype.startWatching = function () {
|
|
41942
|
-
var _this = this;
|
|
41943
41851
|
if (this.isWatching) {
|
|
41944
|
-
console.log('[ShadowSpace] 文件监听已经在运行中');
|
|
41945
41852
|
return;
|
|
41946
41853
|
}
|
|
41947
|
-
|
|
41948
|
-
console.log('[ShadowSpace] 监听目录:', this.config.projectRoot);
|
|
41854
|
+
logger('[ShadowSpace] 监听目录:', this.config.projectRoot);
|
|
41949
41855
|
try {
|
|
41950
41856
|
// 🔥 使用轮询模式 + ignored 函数过滤
|
|
41951
|
-
this.watcher =
|
|
41952
|
-
|
|
41953
|
-
|
|
41954
|
-
|
|
41955
|
-
|
|
41956
|
-
|
|
41957
|
-
|
|
41958
|
-
|
|
41959
|
-
|
|
41960
|
-
|
|
41961
|
-
|
|
41962
|
-
|
|
41963
|
-
|
|
41964
|
-
|
|
41965
|
-
|
|
41966
|
-
|
|
41967
|
-
|
|
41968
|
-
|
|
41969
|
-
|
|
41970
|
-
|
|
41971
|
-
});
|
|
41972
|
-
|
|
41857
|
+
// this.watcher = chokidar.watch(this.config.projectRoot, {
|
|
41858
|
+
// ignored: (filePath: string) => {
|
|
41859
|
+
// const relativePath = path.relative(this.config.projectRoot, filePath);
|
|
41860
|
+
// // 忽略根目录本身
|
|
41861
|
+
// if (!relativePath || relativePath === '.') {
|
|
41862
|
+
// return true;
|
|
41863
|
+
// }
|
|
41864
|
+
// // 使用白名单过滤
|
|
41865
|
+
// return this.shouldIgnoreFile(relativePath);
|
|
41866
|
+
// },
|
|
41867
|
+
// persistent: true,
|
|
41868
|
+
// ignoreInitial: true, // 忽略初始扫描
|
|
41869
|
+
// usePolling: true, // 🔥 macOS 上使用轮询模式(fsevents 在某些环境下不可靠)
|
|
41870
|
+
// interval: 2000, // 轮询间隔 2 秒(降低 CPU 占用)
|
|
41871
|
+
// binaryInterval: 3000, // 二进制文件轮询间隔 3 秒
|
|
41872
|
+
// depth: 99, // 监听所有子目录
|
|
41873
|
+
// awaitWriteFinish: {
|
|
41874
|
+
// stabilityThreshold: 500, // 文件稳定后 500ms 才触发
|
|
41875
|
+
// pollInterval: 100,
|
|
41876
|
+
// },
|
|
41877
|
+
// });
|
|
41878
|
+
logger('[ShadowSpace] chokidar.watch 已调用,等待 ready 事件...');
|
|
41973
41879
|
}
|
|
41974
41880
|
catch (error) {
|
|
41975
41881
|
console.error('[ShadowSpace] 创建文件监听器失败:', error);
|
|
41976
41882
|
return;
|
|
41977
41883
|
}
|
|
41978
|
-
this.watcher
|
|
41979
|
-
|
|
41980
|
-
|
|
41981
|
-
})
|
|
41982
|
-
|
|
41983
|
-
|
|
41984
|
-
})
|
|
41985
|
-
|
|
41986
|
-
|
|
41987
|
-
})
|
|
41988
|
-
|
|
41989
|
-
|
|
41990
|
-
})
|
|
41991
|
-
|
|
41992
|
-
|
|
41993
|
-
|
|
41994
|
-
|
|
41995
|
-
|
|
41884
|
+
// this.watcher
|
|
41885
|
+
// .on('change', (filePath: string) => {
|
|
41886
|
+
// this.onFileChanged(filePath);
|
|
41887
|
+
// })
|
|
41888
|
+
// .on('add', (filePath: string) => {
|
|
41889
|
+
// this.onFileAdded(filePath);
|
|
41890
|
+
// })
|
|
41891
|
+
// .on('unlink', (filePath: string) => {
|
|
41892
|
+
// this.onFileDeleted(filePath);
|
|
41893
|
+
// })
|
|
41894
|
+
// .on('error', (error) => {
|
|
41895
|
+
// console.error('[ShadowSpace] 文件监听错误:', error);
|
|
41896
|
+
// })
|
|
41897
|
+
// .on('ready', () => {
|
|
41898
|
+
// this.isWatching = true;
|
|
41899
|
+
// logger(
|
|
41900
|
+
// '[ShadowSpace] 文件监听已启动,正在监听:',
|
|
41901
|
+
// this.config.projectRoot
|
|
41902
|
+
// );
|
|
41903
|
+
// logger('[ShadowSpace] 监听配置: 轮询模式 (interval: 2s)');
|
|
41904
|
+
// });
|
|
41996
41905
|
};
|
|
41997
41906
|
/**
|
|
41998
41907
|
* 停止文件监听
|
|
@@ -42000,21 +41909,13 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
42000
41909
|
ShadowSpace.prototype.stopWatching = function () {
|
|
42001
41910
|
return __awaiter(this, void 0, void 0, function () {
|
|
42002
41911
|
return __generator(this, function (_a) {
|
|
42003
|
-
|
|
42004
|
-
|
|
42005
|
-
if (!this.isWatching || !this.watcher) {
|
|
42006
|
-
console.log('[ShadowSpace] 文件监听未运行');
|
|
42007
|
-
return [2 /*return*/];
|
|
42008
|
-
}
|
|
42009
|
-
console.log('[ShadowSpace] 停止文件监听...');
|
|
42010
|
-
return [4 /*yield*/, this.watcher.close()];
|
|
42011
|
-
case 1:
|
|
42012
|
-
_a.sent();
|
|
42013
|
-
this.watcher = null;
|
|
42014
|
-
this.isWatching = false;
|
|
42015
|
-
console.log('[ShadowSpace] 文件监听已停止');
|
|
42016
|
-
return [2 /*return*/];
|
|
41912
|
+
if (!this.isWatching || !this.watcher) {
|
|
41913
|
+
return [2 /*return*/];
|
|
42017
41914
|
}
|
|
41915
|
+
// await this.watcher.close();
|
|
41916
|
+
this.watcher = null;
|
|
41917
|
+
this.isWatching = false;
|
|
41918
|
+
return [2 /*return*/];
|
|
42018
41919
|
});
|
|
42019
41920
|
});
|
|
42020
41921
|
};
|
|
@@ -42034,7 +41935,6 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
42034
41935
|
* 触发变更事件
|
|
42035
41936
|
*/
|
|
42036
41937
|
ShadowSpace.prototype.emitChangeEvent = function (event) {
|
|
42037
|
-
console.log('[ShadowSpace] 触发变更事件:', event);
|
|
42038
41938
|
this.changeListeners.forEach(function (listener) {
|
|
42039
41939
|
try {
|
|
42040
41940
|
listener(event);
|
|
@@ -42054,10 +41954,8 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
42054
41954
|
switch (_a.label) {
|
|
42055
41955
|
case 0:
|
|
42056
41956
|
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42057
|
-
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u53D8\u66F4: ".concat(relativePath));
|
|
42058
41957
|
shadowEntry = this.state.files[relativePath];
|
|
42059
41958
|
if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
|
|
42060
|
-
console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u4FEE\u6539\u7684\u6587\u4EF6: ".concat(relativePath));
|
|
42061
41959
|
shadowEntry.remoteModified = false; // 清除标记
|
|
42062
41960
|
return [4 /*yield*/, this.saveState()];
|
|
42063
41961
|
case 1:
|
|
@@ -42101,7 +41999,6 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
42101
41999
|
switch (_a.label) {
|
|
42102
42000
|
case 0:
|
|
42103
42001
|
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42104
|
-
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u65B0\u589E: ".concat(relativePath));
|
|
42105
42002
|
_a.label = 1;
|
|
42106
42003
|
case 1:
|
|
42107
42004
|
_a.trys.push([1, 4, , 5]);
|
|
@@ -42141,10 +42038,8 @@ var ShadowSpace = /** @class */ (function () {
|
|
|
42141
42038
|
switch (_a.label) {
|
|
42142
42039
|
case 0:
|
|
42143
42040
|
relativePath = path__default["default"].relative(this.config.projectRoot, filePath);
|
|
42144
|
-
console.log("[ShadowSpace] \u68C0\u6D4B\u5230\u6587\u4EF6\u5220\u9664: ".concat(relativePath));
|
|
42145
42041
|
shadowEntry = this.state.files[relativePath];
|
|
42146
42042
|
if (!(shadowEntry === null || shadowEntry === void 0 ? void 0 : shadowEntry.remoteModified)) return [3 /*break*/, 2];
|
|
42147
|
-
console.log("[ShadowSpace] \u8DF3\u8FC7\u8FDC\u7A0B\u5220\u9664\u7684\u6587\u4EF6: ".concat(relativePath));
|
|
42148
42043
|
shadowEntry.remoteModified = false; // 清除标记
|
|
42149
42044
|
return [4 /*yield*/, this.saveState()];
|
|
42150
42045
|
case 1:
|
|
@@ -42359,7 +42254,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42359
42254
|
case 13:
|
|
42360
42255
|
result = _j.sent();
|
|
42361
42256
|
return [3 /*break*/, 27];
|
|
42362
|
-
case 14: return [4 /*yield*/, this.syncFromEditor(message.
|
|
42257
|
+
case 14: return [4 /*yield*/, this.syncFromEditor(message.files)];
|
|
42363
42258
|
case 15:
|
|
42364
42259
|
result = _j.sent();
|
|
42365
42260
|
return [3 /*break*/, 27];
|
|
@@ -42776,19 +42671,22 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42776
42671
|
*/
|
|
42777
42672
|
ShadowSpaceCommandHandler.prototype.deleteFile = function (filePath) {
|
|
42778
42673
|
return __awaiter(this, void 0, void 0, function () {
|
|
42779
|
-
var allFiles, deleted, result;
|
|
42674
|
+
var normalizedPath, allFiles, deleted, result;
|
|
42780
42675
|
return __generator(this, function (_a) {
|
|
42781
42676
|
switch (_a.label) {
|
|
42782
42677
|
case 0:
|
|
42783
42678
|
if (!filePath) {
|
|
42784
42679
|
throw new Error('File path is required');
|
|
42785
42680
|
}
|
|
42786
|
-
|
|
42681
|
+
normalizedPath = filePath.startsWith('/')
|
|
42682
|
+
? filePath.substring(1)
|
|
42683
|
+
: filePath;
|
|
42684
|
+
console.log("[ShadowSpace] \u5220\u9664\u6587\u4EF6: ".concat(filePath, " -> \u6807\u51C6\u5316\u4E3A: ").concat(normalizedPath));
|
|
42787
42685
|
allFiles = this.shadowSpace.getAllFilePaths();
|
|
42788
42686
|
console.log('[ShadowSpace] 当前影子空间中的文件: ', allFiles);
|
|
42789
|
-
console.log("[ShadowSpace] \u8981\u5220\u9664\u7684\u6587\u4EF6\u8DEF\u5F84: \"".concat(
|
|
42790
|
-
console.log('[ShadowSpace] 文件是否存在:', this.shadowSpace.hasFile(
|
|
42791
|
-
return [4 /*yield*/, this.shadowSpace.deleteFile(
|
|
42687
|
+
console.log("[ShadowSpace] \u8981\u5220\u9664\u7684\u6587\u4EF6\u8DEF\u5F84: \"".concat(normalizedPath, "\""));
|
|
42688
|
+
console.log('[ShadowSpace] 文件是否存在:', this.shadowSpace.hasFile(normalizedPath) ? '是' : '否');
|
|
42689
|
+
return [4 /*yield*/, this.shadowSpace.deleteFile(normalizedPath)];
|
|
42792
42690
|
case 1:
|
|
42793
42691
|
deleted = _a.sent();
|
|
42794
42692
|
result = {
|
|
@@ -42797,7 +42695,7 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
42797
42695
|
deleted: deleted,
|
|
42798
42696
|
timestamp: Date.now(),
|
|
42799
42697
|
};
|
|
42800
|
-
console.log("[ShadowSpace] \u6587\u4EF6\u5220\u9664".concat(deleted ? '成功' : '失败', ": ").concat(
|
|
42698
|
+
console.log("[ShadowSpace] \u6587\u4EF6\u5220\u9664".concat(deleted ? '成功' : '失败', ": ").concat(normalizedPath));
|
|
42801
42699
|
return [2 /*return*/, result];
|
|
42802
42700
|
}
|
|
42803
42701
|
});
|
|
@@ -43222,13 +43120,13 @@ var ShadowSpaceCommandHandler = /** @class */ (function () {
|
|
|
43222
43120
|
_d = __read(spaceMap_1_1.value, 2), path = _d[0], spaceFile = _d[1];
|
|
43223
43121
|
editorFile = editorMap.get(path);
|
|
43224
43122
|
if (!editorFile) {
|
|
43225
|
-
//
|
|
43123
|
+
// 编辑器中没有但空间中有,说明编辑器删除了文件 → 从编辑器推送删除操作到空间
|
|
43226
43124
|
changes.push({
|
|
43227
43125
|
action: 'delete',
|
|
43228
43126
|
path: path,
|
|
43229
|
-
side: '
|
|
43230
|
-
sourceLabel: '
|
|
43231
|
-
targetLabel: '
|
|
43127
|
+
side: 'editor',
|
|
43128
|
+
sourceLabel: 'editor',
|
|
43129
|
+
targetLabel: 'shadow-space',
|
|
43232
43130
|
editorHash: null,
|
|
43233
43131
|
spaceHash: spaceFile.hash,
|
|
43234
43132
|
});
|
|
@@ -43608,7 +43506,8 @@ function startConnecting(options) {
|
|
|
43608
43506
|
else if ((_b = data === null || data === void 0 ? void 0 : data.message) === null || _b === void 0 ? void 0 : _b.action) {
|
|
43609
43507
|
// 嵌套格式(前端发送的格式)
|
|
43610
43508
|
action = data.message.action;
|
|
43611
|
-
|
|
43509
|
+
// 🆕 对于嵌套格式,需要提取内层的 message
|
|
43510
|
+
message = data.message.message;
|
|
43612
43511
|
}
|
|
43613
43512
|
else {
|
|
43614
43513
|
extracted = data || {};
|
|
@@ -47873,411 +47772,140 @@ function executeShadowSpaceDebug(options) {
|
|
|
47873
47772
|
});
|
|
47874
47773
|
}
|
|
47875
47774
|
|
|
47876
|
-
/**
|
|
47877
|
-
|
|
47878
|
-
* 同时支持CLI和编辑器使用
|
|
47879
|
-
*/
|
|
47880
|
-
var UnifiedTSXValidator = /** @class */ (function () {
|
|
47881
|
-
function UnifiedTSXValidator(debug) {
|
|
47882
|
-
if (debug === void 0) { debug = false; }
|
|
47883
|
-
this.debug = false;
|
|
47884
|
-
this.debug = debug;
|
|
47775
|
+
var TSXComplianceChecker = /** @class */ (function () {
|
|
47776
|
+
function TSXComplianceChecker() {
|
|
47885
47777
|
}
|
|
47886
47778
|
/**
|
|
47887
|
-
*
|
|
47779
|
+
* 使用 AST 检查 TSX 规范
|
|
47888
47780
|
*/
|
|
47889
|
-
|
|
47890
|
-
var _this = this;
|
|
47891
|
-
if (filename === void 0) { filename = 'unknown.tsx'; }
|
|
47892
|
-
this.content = content;
|
|
47893
|
-
this.filename = filename;
|
|
47781
|
+
TSXComplianceChecker.checkTSXCompliance = function (content, filename) {
|
|
47894
47782
|
var issues = [];
|
|
47895
47783
|
try {
|
|
47896
|
-
|
|
47784
|
+
// 使用 Babel 解析 TSX 代码
|
|
47785
|
+
var ast = parser$1.parse(content, {
|
|
47897
47786
|
sourceType: 'module',
|
|
47898
47787
|
plugins: ['jsx', 'typescript', 'decorators-legacy', 'classProperties'],
|
|
47899
47788
|
errorRecovery: true,
|
|
47900
|
-
allowReturnOutsideFunction: true,
|
|
47901
47789
|
});
|
|
47902
|
-
|
|
47903
|
-
|
|
47904
|
-
|
|
47905
|
-
|
|
47906
|
-
|
|
47907
|
-
|
|
47908
|
-
|
|
47909
|
-
|
|
47910
|
-
|
|
47911
|
-
|
|
47912
|
-
|
|
47913
|
-
|
|
47914
|
-
|
|
47915
|
-
|
|
47916
|
-
|
|
47917
|
-
|
|
47918
|
-
|
|
47790
|
+
// 遍历 AST 进行检查
|
|
47791
|
+
traverse__default["default"](ast, {
|
|
47792
|
+
// 检查变量声明
|
|
47793
|
+
VariableDeclarator: function (path) {
|
|
47794
|
+
TSXComplianceChecker.checkVariableDeclaration(path, content, issues);
|
|
47795
|
+
},
|
|
47796
|
+
// 检查方法定义
|
|
47797
|
+
ClassMethod: function (path) {
|
|
47798
|
+
TSXComplianceChecker.checkMethodDefinition(path, content, issues);
|
|
47799
|
+
},
|
|
47800
|
+
// 检查 JSX 使用
|
|
47801
|
+
JSXElement: function (path) {
|
|
47802
|
+
TSXComplianceChecker.checkJSXUsage(path, content, issues);
|
|
47803
|
+
},
|
|
47804
|
+
// 检查类型注解
|
|
47805
|
+
TSTypeAnnotation: function (path) {
|
|
47806
|
+
TSXComplianceChecker.checkTypeAnnotation(path, content, issues);
|
|
47807
|
+
},
|
|
47808
|
+
});
|
|
47809
|
+
// 检查必需的结构
|
|
47810
|
+
this.checkRequiredStructures(ast, content, issues);
|
|
47919
47811
|
}
|
|
47920
47812
|
catch (error) {
|
|
47921
|
-
|
|
47922
|
-
|
|
47923
|
-
|
|
47924
|
-
|
|
47925
|
-
|
|
47926
|
-
|
|
47927
|
-
message: "\u4EE3\u7801\u89E3\u6790\u5931\u8D25: ".concat(error.message),
|
|
47928
|
-
suggestion: '检查代码语法是否正确',
|
|
47929
|
-
line: 1,
|
|
47930
|
-
column: 0,
|
|
47931
|
-
}],
|
|
47932
|
-
};
|
|
47933
|
-
}
|
|
47934
|
-
};
|
|
47935
|
-
/**
|
|
47936
|
-
* 检查文件结构
|
|
47937
|
-
*/
|
|
47938
|
-
UnifiedTSXValidator.prototype.checkFileStructure = function (ast, issues) {
|
|
47939
|
-
var _this = this;
|
|
47940
|
-
this.log('开始检查文件结构');
|
|
47941
|
-
var hasReactComponent = false;
|
|
47942
|
-
traverse__default["default"](ast, {
|
|
47943
|
-
ClassDeclaration: function (path) {
|
|
47944
|
-
var _a;
|
|
47945
|
-
var className = (_a = path.node.id) === null || _a === void 0 ? void 0 : _a.name;
|
|
47946
|
-
_this.log("\u53D1\u73B0\u7C7B: ".concat(className));
|
|
47947
|
-
// 检查是否有继承自React.Component的类(支持 extends Component 和 extends React.Component)
|
|
47948
|
-
if (_this.isReactComponent(path.node.superClass)) {
|
|
47949
|
-
hasReactComponent = true;
|
|
47950
|
-
_this.log("\u53D1\u73B0React\u7EC4\u4EF6\u7C7B: ".concat(className));
|
|
47951
|
-
}
|
|
47952
|
-
},
|
|
47953
|
-
});
|
|
47954
|
-
// 不再强制要求Document类,只要有React组件类即可
|
|
47955
|
-
if (!hasReactComponent) {
|
|
47956
|
-
issues.push(this.createIssue('MISSING_REACT_COMPONENT', 'error', '缺少React组件类定义,必须定义一个继承自React.Component的类', '请定义组件类,如: class MyComponent extends React.Component 或 class MyComponent extends Component', 1));
|
|
47813
|
+
issues.push({
|
|
47814
|
+
type: 'error',
|
|
47815
|
+
code: 'PARSE_ERROR',
|
|
47816
|
+
message: "\u4EE3\u7801\u89E3\u6790\u5931\u8D25: ".concat(error.message),
|
|
47817
|
+
suggestion: '检查代码语法是否正确',
|
|
47818
|
+
});
|
|
47957
47819
|
}
|
|
47820
|
+
return {
|
|
47821
|
+
isCompliant: issues.filter(function (issue) { return issue.type === 'error'; }).length === 0,
|
|
47822
|
+
issues: issues,
|
|
47823
|
+
};
|
|
47958
47824
|
};
|
|
47959
47825
|
/**
|
|
47960
|
-
*
|
|
47961
|
-
*/
|
|
47962
|
-
UnifiedTSXValidator.prototype.checkComponentDefinition = function (ast, issues) {
|
|
47963
|
-
var _this = this;
|
|
47964
|
-
this.log('开始检查组件定义');
|
|
47965
|
-
traverse__default["default"](ast, {
|
|
47966
|
-
ClassDeclaration: function (path) {
|
|
47967
|
-
var e_1, _a;
|
|
47968
|
-
var _b;
|
|
47969
|
-
// 检查所有继承自React.Component的类
|
|
47970
|
-
if (_this.isReactComponent(path.node.superClass)) {
|
|
47971
|
-
var className = (_b = path.node.id) === null || _b === void 0 ? void 0 : _b.name;
|
|
47972
|
-
_this.log("\u68C0\u67E5React\u7EC4\u4EF6\u7C7B: ".concat(className));
|
|
47973
|
-
// 检查render方法
|
|
47974
|
-
var hasRender = false;
|
|
47975
|
-
try {
|
|
47976
|
-
for (var _c = __values(path.node.body.body), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
47977
|
-
var member = _d.value;
|
|
47978
|
-
if (member.type === 'ClassMethod' && member.key.name === 'render') {
|
|
47979
|
-
hasRender = true;
|
|
47980
|
-
}
|
|
47981
|
-
// 检查constructor
|
|
47982
|
-
if (member.type === 'ClassMethod' && member.key.name === 'constructor') {
|
|
47983
|
-
issues.push(_this.createIssueFromNode('CONSTRUCTOR_NOT_ALLOWED', 'error', "".concat(className, "\u7C7B\u4E2D\u4E0D\u5141\u8BB8\u4F7F\u7528constructor"), '请使用state属性直接定义状态,使用componentDidMount进行初始化', member));
|
|
47984
|
-
}
|
|
47985
|
-
}
|
|
47986
|
-
}
|
|
47987
|
-
catch (e_1_1) { e_1 = { error: e_1_1 }; }
|
|
47988
|
-
finally {
|
|
47989
|
-
try {
|
|
47990
|
-
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
47991
|
-
}
|
|
47992
|
-
finally { if (e_1) throw e_1.error; }
|
|
47993
|
-
}
|
|
47994
|
-
// 移除对state属性的强制检查,React组件可以不定义state
|
|
47995
|
-
if (!hasRender) {
|
|
47996
|
-
issues.push(_this.createIssueFromNode('MISSING_RENDER_METHOD', 'error', "".concat(className, "\u7C7B\u5FC5\u987B\u5B9A\u4E49render\u65B9\u6CD5"), '请添加: render() { return <View>...</View> }', path.node));
|
|
47997
|
-
}
|
|
47998
|
-
}
|
|
47999
|
-
},
|
|
48000
|
-
});
|
|
48001
|
-
};
|
|
48002
|
-
/**
|
|
48003
|
-
* 检查render方法
|
|
48004
|
-
*/
|
|
48005
|
-
UnifiedTSXValidator.prototype.checkRenderMethod = function (ast, issues) {
|
|
48006
|
-
var _this = this;
|
|
48007
|
-
this.log('开始检查render方法');
|
|
48008
|
-
traverse__default["default"](ast, {
|
|
48009
|
-
ClassMethod: function (path) {
|
|
48010
|
-
var e_2, _a, e_3, _b;
|
|
48011
|
-
if (path.node.key.name === 'render') {
|
|
48012
|
-
var body = path.node.body.body;
|
|
48013
|
-
try {
|
|
48014
|
-
// 检查变量声明
|
|
48015
|
-
for (var body_1 = __values(body), body_1_1 = body_1.next(); !body_1_1.done; body_1_1 = body_1.next()) {
|
|
48016
|
-
var statement = body_1_1.value;
|
|
48017
|
-
if (statement.type === 'VariableDeclaration') {
|
|
48018
|
-
// 检查是否在事件处理函数中
|
|
48019
|
-
if (!_this.isInEventHandler(path)) {
|
|
48020
|
-
issues.push(_this.createIssueFromNode('RENDER_VARIABLE_DECLARATION', 'error', 'render方法中不允许声明变量', '直接使用this.state访问状态', statement));
|
|
48021
|
-
}
|
|
48022
|
-
}
|
|
48023
|
-
// 检查函数声明
|
|
48024
|
-
if (statement.type === 'FunctionDeclaration') {
|
|
48025
|
-
issues.push(_this.createIssueFromNode('RENDER_FUNCTION_DECLARATION', 'error', 'render方法中不允许声明函数', '将函数声明移到render方法外部', statement));
|
|
48026
|
-
}
|
|
48027
|
-
// 检查if语句
|
|
48028
|
-
if (statement.type === 'IfStatement') {
|
|
48029
|
-
issues.push(_this.createIssueFromNode('RENDER_IF_STATEMENT', 'error', 'render方法中不允许使用if语句进行条件渲染', '请使用JSX中的条件渲染语法 {condition && <View>}', statement));
|
|
48030
|
-
}
|
|
48031
|
-
}
|
|
48032
|
-
}
|
|
48033
|
-
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
48034
|
-
finally {
|
|
48035
|
-
try {
|
|
48036
|
-
if (body_1_1 && !body_1_1.done && (_a = body_1.return)) _a.call(body_1);
|
|
48037
|
-
}
|
|
48038
|
-
finally { if (e_2) throw e_2.error; }
|
|
48039
|
-
}
|
|
48040
|
-
// 检查是否有return语句
|
|
48041
|
-
var hasReturn = false;
|
|
48042
|
-
try {
|
|
48043
|
-
for (var body_2 = __values(body), body_2_1 = body_2.next(); !body_2_1.done; body_2_1 = body_2.next()) {
|
|
48044
|
-
var statement = body_2_1.value;
|
|
48045
|
-
if (statement.type === 'ReturnStatement') {
|
|
48046
|
-
hasReturn = true;
|
|
48047
|
-
break;
|
|
48048
|
-
}
|
|
48049
|
-
}
|
|
48050
|
-
}
|
|
48051
|
-
catch (e_3_1) { e_3 = { error: e_3_1 }; }
|
|
48052
|
-
finally {
|
|
48053
|
-
try {
|
|
48054
|
-
if (body_2_1 && !body_2_1.done && (_b = body_2.return)) _b.call(body_2);
|
|
48055
|
-
}
|
|
48056
|
-
finally { if (e_3) throw e_3.error; }
|
|
48057
|
-
}
|
|
48058
|
-
if (!hasReturn) {
|
|
48059
|
-
issues.push(_this.createIssueFromNode('MISSING_RETURN', 'error', 'render方法必须返回JSX元素', '请在render方法末尾添加return语句', path.node));
|
|
48060
|
-
}
|
|
48061
|
-
}
|
|
48062
|
-
},
|
|
48063
|
-
});
|
|
48064
|
-
};
|
|
48065
|
-
/**
|
|
48066
|
-
* 检查变量声明 - 兼容TSXComplianceChecker的逻辑
|
|
48067
|
-
*/
|
|
48068
|
-
UnifiedTSXValidator.prototype.checkVariableDeclarations = function (ast, issues) {
|
|
48069
|
-
var _this = this;
|
|
48070
|
-
this.log('开始检查变量声明');
|
|
48071
|
-
traverse__default["default"](ast, {
|
|
48072
|
-
VariableDeclarator: function (path) {
|
|
48073
|
-
// 检查是否在 render 方法中
|
|
48074
|
-
var renderMethod = path.findParent(function (p) {
|
|
48075
|
-
return p.isClassMethod() &&
|
|
48076
|
-
t__namespace.isIdentifier(p.node.key) &&
|
|
48077
|
-
p.node.key.name === 'render';
|
|
48078
|
-
});
|
|
48079
|
-
if (!renderMethod)
|
|
48080
|
-
return;
|
|
48081
|
-
// 检查是否在事件处理函数中
|
|
48082
|
-
if (_this.isInEventHandler(path))
|
|
48083
|
-
return;
|
|
48084
|
-
// 检查是否在非JSX回调函数中
|
|
48085
|
-
if (_this.isInNonJSXCallback(path))
|
|
48086
|
-
return;
|
|
48087
|
-
// 检查是否在返回JSX的回调函数中
|
|
48088
|
-
if (_this.isInJSXCallback(path)) {
|
|
48089
|
-
issues.push(_this.createIssueFromNode('CALLBACK_VARIABLE_DECLARATION', 'error', '返回JSX的回调函数中不能包含变量声明', '将变量声明移到回调函数外部,或使用内联表达式', path.node));
|
|
48090
|
-
return;
|
|
48091
|
-
}
|
|
48092
|
-
// 其他在render方法中的变量声明都是错误的
|
|
48093
|
-
issues.push(_this.createIssueFromNode('RENDER_VARIABLE_DECLARATION', 'error', 'render()方法中不能包含变量声明', '移除所有const/let/var声明,直接使用this.state.xxx', path.node));
|
|
48094
|
-
},
|
|
48095
|
-
});
|
|
48096
|
-
};
|
|
48097
|
-
/**
|
|
48098
|
-
* 检查条件渲染
|
|
48099
|
-
*/
|
|
48100
|
-
UnifiedTSXValidator.prototype.checkConditionalRendering = function (ast, issues) {
|
|
48101
|
-
var _this = this;
|
|
48102
|
-
this.log('开始检查条件渲染');
|
|
48103
|
-
traverse__default["default"](ast, {
|
|
48104
|
-
JSXExpressionContainer: function (path) {
|
|
48105
|
-
var expression = path.node.expression;
|
|
48106
|
-
if (expression.type === 'LogicalExpression') {
|
|
48107
|
-
// 检查右侧是否包含JSX元素
|
|
48108
|
-
var hasJSXInRight = _this.hasJSXInNode(expression.right);
|
|
48109
|
-
if (hasJSXInRight && expression.operator !== '&&') {
|
|
48110
|
-
issues.push(_this.createIssueFromNode('INVALID_CONDITIONAL_OPERATOR', 'error', '条件渲染必须使用&&运算符,不支持其他运算符', '请使用 && 运算符进行条件渲染', path.node));
|
|
48111
|
-
}
|
|
48112
|
-
if (hasJSXInRight && expression.left.type === 'Identifier') {
|
|
48113
|
-
issues.push(_this.createIssueFromNode('VARIABLE_IN_CONDITIONAL', 'error', '条件渲染中不允许使用变量', '请直接使用this.state访问状态', path.node));
|
|
48114
|
-
}
|
|
48115
|
-
}
|
|
48116
|
-
},
|
|
48117
|
-
});
|
|
48118
|
-
};
|
|
48119
|
-
/**
|
|
48120
|
-
* 检查列表渲染
|
|
48121
|
-
*/
|
|
48122
|
-
UnifiedTSXValidator.prototype.checkListRendering = function (ast, issues) {
|
|
48123
|
-
var _this = this;
|
|
48124
|
-
this.log('开始检查列表渲染');
|
|
48125
|
-
traverse__default["default"](ast, {
|
|
48126
|
-
CallExpression: function (path) {
|
|
48127
|
-
if (path.node.callee.type === 'MemberExpression' &&
|
|
48128
|
-
path.node.callee.property.name === 'map') {
|
|
48129
|
-
// 检查是否在render方法的JSX中使用
|
|
48130
|
-
if (_this.isInRenderJSX(path)) {
|
|
48131
|
-
var parent_1 = path.parentPath;
|
|
48132
|
-
if (parent_1.node.type === 'VariableDeclaration') {
|
|
48133
|
-
issues.push(_this.createIssueFromNode('LIST_RENDER_VARIABLE', 'error', '列表渲染中不允许使用变量', '请直接使用map方法渲染', path.node));
|
|
48134
|
-
}
|
|
48135
|
-
}
|
|
48136
|
-
}
|
|
48137
|
-
},
|
|
48138
|
-
});
|
|
48139
|
-
};
|
|
48140
|
-
/**
|
|
48141
|
-
* 检查样式使用
|
|
48142
|
-
*/
|
|
48143
|
-
UnifiedTSXValidator.prototype.checkStyleUsage = function (ast, issues) {
|
|
48144
|
-
var _this = this;
|
|
48145
|
-
this.log('开始检查样式使用');
|
|
48146
|
-
traverse__default["default"](ast, {
|
|
48147
|
-
JSXAttribute: function (path) {
|
|
48148
|
-
var _a;
|
|
48149
|
-
if (path.node.name.name === 'inlineStyle') {
|
|
48150
|
-
var parent_2 = path.parentPath.node;
|
|
48151
|
-
var componentName = (_a = parent_2.name) === null || _a === void 0 ? void 0 : _a.name;
|
|
48152
|
-
if (componentName !== 'View' && componentName !== 'Text') {
|
|
48153
|
-
issues.push(_this.createIssueFromNode('INVALID_INLINE_STYLE', 'error', 'inlineStyle属性仅支持View和Text组件使用', '请检查组件类型或使用其他样式属性', path.node));
|
|
48154
|
-
}
|
|
48155
|
-
}
|
|
48156
|
-
},
|
|
48157
|
-
});
|
|
48158
|
-
};
|
|
48159
|
-
/**
|
|
48160
|
-
* 检查状态管理
|
|
47826
|
+
* 检查变量声明
|
|
48161
47827
|
*/
|
|
48162
|
-
|
|
48163
|
-
|
|
48164
|
-
|
|
48165
|
-
|
|
48166
|
-
|
|
48167
|
-
if (_this.isDirectStateMutation(path.node.left)) {
|
|
48168
|
-
issues.push(_this.createIssueFromNode('DIRECT_STATE_MUTATION', 'error', '不允许直接修改state', '请使用this.setState方法', path.node));
|
|
48169
|
-
}
|
|
48170
|
-
},
|
|
48171
|
-
});
|
|
47828
|
+
TSXComplianceChecker.checkVariableDeclaration = function (path, content, issues) {
|
|
47829
|
+
// 现在的代码生成策略允许在 render 中声明变量(用于变量提升),
|
|
47830
|
+
// 也允许在 map 回调中声明变量(用于循环内部变量)。
|
|
47831
|
+
// 因此,不再对 render 方法内的变量声明进行限制。
|
|
47832
|
+
return;
|
|
48172
47833
|
};
|
|
48173
47834
|
/**
|
|
48174
|
-
*
|
|
47835
|
+
* 检查是否在事件处理函数中
|
|
48175
47836
|
*/
|
|
48176
|
-
|
|
48177
|
-
|
|
48178
|
-
this.log('开始检查数据源使用');
|
|
48179
|
-
traverse__default["default"](ast, {
|
|
48180
|
-
CallExpression: function (path) {
|
|
48181
|
-
var _a;
|
|
48182
|
-
if (_this.isDataSourceLoadCall(path.node)) {
|
|
48183
|
-
var isInRender = false;
|
|
48184
|
-
var isInCallback = false;
|
|
48185
|
-
var currentPath = path;
|
|
48186
|
-
while (currentPath) {
|
|
48187
|
-
var node = currentPath.node;
|
|
48188
|
-
if (node.type === 'ClassMethod' && ((_a = node.key) === null || _a === void 0 ? void 0 : _a.name) === 'render') {
|
|
48189
|
-
isInRender = true;
|
|
48190
|
-
}
|
|
48191
|
-
if ((node.type === 'ArrowFunctionExpression' || node.type === 'FunctionExpression')) {
|
|
48192
|
-
var parentPath = currentPath.parentPath;
|
|
48193
|
-
if ((parentPath === null || parentPath === void 0 ? void 0 : parentPath.node.type) === 'JSXExpressionContainer') {
|
|
48194
|
-
isInCallback = true;
|
|
48195
|
-
break;
|
|
48196
|
-
}
|
|
48197
|
-
}
|
|
48198
|
-
currentPath = currentPath.parentPath;
|
|
48199
|
-
}
|
|
48200
|
-
if (isInRender && !isInCallback) {
|
|
48201
|
-
issues.push(_this.createIssueFromNode('DATA_SOURCE_IN_RENDER', 'error', 'render方法中不允许直接调用数据源', '请在回调函数中调用数据源', path.node));
|
|
48202
|
-
}
|
|
48203
|
-
}
|
|
48204
|
-
},
|
|
48205
|
-
});
|
|
48206
|
-
};
|
|
48207
|
-
// ========== 辅助方法 ==========
|
|
48208
|
-
UnifiedTSXValidator.prototype.isReactComponent = function (superClass) {
|
|
48209
|
-
if (!superClass)
|
|
48210
|
-
return false;
|
|
48211
|
-
// 支持 extends React.Component
|
|
48212
|
-
if (superClass.type === 'MemberExpression' &&
|
|
48213
|
-
superClass.object.name === 'React' &&
|
|
48214
|
-
superClass.property.name === 'Component') {
|
|
48215
|
-
return true;
|
|
48216
|
-
}
|
|
48217
|
-
// 支持 extends Component 和 extends Component<IProps, IState>
|
|
48218
|
-
// 泛型参数不会影响标识符本身的识别
|
|
48219
|
-
if (superClass.type === 'Identifier' &&
|
|
48220
|
-
superClass.name === 'Component') {
|
|
48221
|
-
return true;
|
|
48222
|
-
}
|
|
48223
|
-
// 额外检查:如果父节点是TSExpressionWithTypeArguments,检查其expression
|
|
48224
|
-
// 这种情况出现在 extends Component<IProps, IState> 中
|
|
48225
|
-
if (superClass.type === 'TSExpressionWithTypeArguments' &&
|
|
48226
|
-
superClass.expression &&
|
|
48227
|
-
superClass.expression.type === 'Identifier' &&
|
|
48228
|
-
superClass.expression.name === 'Component') {
|
|
48229
|
-
return true;
|
|
48230
|
-
}
|
|
48231
|
-
return false;
|
|
48232
|
-
};
|
|
48233
|
-
UnifiedTSXValidator.prototype.isReactComponentSuperClass = function (path) {
|
|
48234
|
-
var superClass = path.node.superClass;
|
|
48235
|
-
return this.isReactComponent(superClass);
|
|
48236
|
-
};
|
|
48237
|
-
UnifiedTSXValidator.prototype.hasJSXInNode = function (node) {
|
|
48238
|
-
if (!node)
|
|
48239
|
-
return false;
|
|
48240
|
-
if (node.type === 'JSXElement' || node.type === 'JSXFragment')
|
|
48241
|
-
return true;
|
|
48242
|
-
if (node.type === 'ConditionalExpression') {
|
|
48243
|
-
return this.hasJSXInNode(node.consequent) || this.hasJSXInNode(node.alternate);
|
|
48244
|
-
}
|
|
48245
|
-
return false;
|
|
48246
|
-
};
|
|
48247
|
-
UnifiedTSXValidator.prototype.isInEventHandler = function (path) {
|
|
47837
|
+
TSXComplianceChecker.isInEventHandler = function (path) {
|
|
47838
|
+
// 查找父级 JSX 属性
|
|
48248
47839
|
var jsxAttribute = path.findParent(function (p) { return p.isJSXAttribute(); });
|
|
48249
47840
|
if (jsxAttribute && t__namespace.isJSXIdentifier(jsxAttribute.node.name)) {
|
|
48250
47841
|
var attrName = jsxAttribute.node.name.name;
|
|
47842
|
+
// 检查是否是事件处理属性(onXxx)
|
|
48251
47843
|
if (/^on[A-Z]/.test(attrName)) {
|
|
48252
47844
|
return true;
|
|
48253
47845
|
}
|
|
48254
47846
|
}
|
|
47847
|
+
// 检查是否在 addEventListener 回调中
|
|
47848
|
+
var callExpression = path.findParent(function (p) { return p.isCallExpression(); });
|
|
47849
|
+
if (callExpression && t__namespace.isMemberExpression(callExpression.node.callee)) {
|
|
47850
|
+
var memberExpr = callExpression.node.callee;
|
|
47851
|
+
if (t__namespace.isIdentifier(memberExpr.property) &&
|
|
47852
|
+
memberExpr.property.name === 'addEventListener') {
|
|
47853
|
+
return true;
|
|
47854
|
+
}
|
|
47855
|
+
}
|
|
48255
47856
|
return false;
|
|
48256
47857
|
};
|
|
48257
|
-
|
|
47858
|
+
/**
|
|
47859
|
+
* 检查是否在非 JSX 返回的回调函数中
|
|
47860
|
+
*/
|
|
47861
|
+
TSXComplianceChecker.isInNonJSXCallback = function (path) {
|
|
47862
|
+
// 查找父级函数
|
|
48258
47863
|
var parentFunction = path.findParent(function (p) { return p.isArrowFunctionExpression() || p.isFunctionExpression(); });
|
|
48259
47864
|
if (!parentFunction)
|
|
48260
47865
|
return false;
|
|
48261
|
-
|
|
47866
|
+
// 检查是否在 JSX 属性回调中(如 beforeUpload, customRequest 等)
|
|
47867
|
+
var jsxAttribute = parentFunction.findParent(function (p) {
|
|
47868
|
+
return p.isJSXAttribute();
|
|
47869
|
+
});
|
|
48262
47870
|
if (jsxAttribute && t__namespace.isJSXIdentifier(jsxAttribute.node.name)) {
|
|
48263
47871
|
var attrName = jsxAttribute.node.name.name;
|
|
47872
|
+
// 这些属性通常不返回 JSX
|
|
48264
47873
|
var nonJSXAttributes = [
|
|
48265
|
-
'beforeUpload',
|
|
48266
|
-
'
|
|
47874
|
+
'beforeUpload',
|
|
47875
|
+
'customRequest',
|
|
47876
|
+
'onChange',
|
|
47877
|
+
'onFinish',
|
|
47878
|
+
'onSubmit',
|
|
47879
|
+
'onSuccess',
|
|
47880
|
+
'onError',
|
|
47881
|
+
'onProgress',
|
|
47882
|
+
'request',
|
|
47883
|
+
'dataHandler',
|
|
48267
47884
|
];
|
|
48268
47885
|
if (nonJSXAttributes.includes(attrName)) {
|
|
48269
47886
|
return true;
|
|
48270
47887
|
}
|
|
48271
47888
|
}
|
|
48272
|
-
|
|
47889
|
+
// 检查函数是否返回 JSX
|
|
47890
|
+
var returnsJSX = this.functionReturnsJSX(parentFunction);
|
|
47891
|
+
// 如果不返回 JSX,则认为是非 JSX 回调
|
|
47892
|
+
return !returnsJSX;
|
|
48273
47893
|
};
|
|
48274
|
-
|
|
47894
|
+
/**
|
|
47895
|
+
* 检查是否在返回 JSX 的回调函数中
|
|
47896
|
+
*/
|
|
47897
|
+
TSXComplianceChecker.isInJSXCallback = function (path) {
|
|
47898
|
+
// 查找父级函数
|
|
48275
47899
|
var parentFunction = path.findParent(function (p) { return p.isArrowFunctionExpression() || p.isFunctionExpression(); });
|
|
48276
47900
|
if (!parentFunction)
|
|
48277
47901
|
return false;
|
|
47902
|
+
// 检查函数是否返回 JSX
|
|
48278
47903
|
return this.functionReturnsJSX(parentFunction);
|
|
48279
47904
|
};
|
|
48280
|
-
|
|
47905
|
+
/**
|
|
47906
|
+
* 检查函数是否返回 JSX
|
|
47907
|
+
*/
|
|
47908
|
+
TSXComplianceChecker.functionReturnsJSX = function (functionPath) {
|
|
48281
47909
|
var returnsJSX = false;
|
|
48282
47910
|
functionPath.traverse({
|
|
48283
47911
|
ReturnStatement: function (path) {
|
|
@@ -48286,6 +47914,7 @@ var UnifiedTSXValidator = /** @class */ (function () {
|
|
|
48286
47914
|
}
|
|
48287
47915
|
},
|
|
48288
47916
|
JSXElement: function (path) {
|
|
47917
|
+
// 如果函数体直接包含 JSX(箭头函数的隐式返回)
|
|
48289
47918
|
if (path.parent === functionPath.node.body) {
|
|
48290
47919
|
returnsJSX = true;
|
|
48291
47920
|
}
|
|
@@ -48293,280 +47922,76 @@ var UnifiedTSXValidator = /** @class */ (function () {
|
|
|
48293
47922
|
});
|
|
48294
47923
|
return returnsJSX;
|
|
48295
47924
|
};
|
|
48296
|
-
UnifiedTSXValidator.prototype.isInRenderJSX = function (path) {
|
|
48297
|
-
var isInRender = false;
|
|
48298
|
-
var isInJSX = false;
|
|
48299
|
-
var currentPath = path;
|
|
48300
|
-
while (currentPath) {
|
|
48301
|
-
if (currentPath.node.type === 'ClassMethod' && currentPath.node.key.name === 'render') {
|
|
48302
|
-
isInRender = true;
|
|
48303
|
-
}
|
|
48304
|
-
if (currentPath.node.type === 'JSXExpressionContainer') {
|
|
48305
|
-
isInJSX = true;
|
|
48306
|
-
}
|
|
48307
|
-
currentPath = currentPath.parentPath;
|
|
48308
|
-
}
|
|
48309
|
-
return isInRender && isInJSX;
|
|
48310
|
-
};
|
|
48311
|
-
UnifiedTSXValidator.prototype.isDirectStateMutation = function (left) {
|
|
48312
|
-
return (left.type === 'MemberExpression' &&
|
|
48313
|
-
left.object.type === 'MemberExpression' &&
|
|
48314
|
-
left.object.object.type === 'ThisExpression' &&
|
|
48315
|
-
left.object.property.name === 'state');
|
|
48316
|
-
};
|
|
48317
|
-
UnifiedTSXValidator.prototype.isDataSourceLoadCall = function (node) {
|
|
48318
|
-
return (node.callee.type === 'MemberExpression' &&
|
|
48319
|
-
node.callee.object.type === 'MemberExpression' &&
|
|
48320
|
-
node.callee.object.object.type === 'MemberExpression' &&
|
|
48321
|
-
node.callee.object.object.object.type === 'ThisExpression' &&
|
|
48322
|
-
node.callee.object.object.property.name === 'dataSourceMap' &&
|
|
48323
|
-
node.callee.property.name === 'load');
|
|
48324
|
-
};
|
|
48325
|
-
UnifiedTSXValidator.prototype.createIssueFromNode = function (code, type, message, suggestion, node) {
|
|
48326
|
-
var loc = node.loc;
|
|
48327
|
-
return {
|
|
48328
|
-
type: type,
|
|
48329
|
-
code: code,
|
|
48330
|
-
message: message,
|
|
48331
|
-
suggestion: suggestion,
|
|
48332
|
-
line: loc ? loc.start.line : 1,
|
|
48333
|
-
column: loc ? loc.start.column : 0,
|
|
48334
|
-
};
|
|
48335
|
-
};
|
|
48336
|
-
UnifiedTSXValidator.prototype.createIssue = function (code, type, message, suggestion, line, column) {
|
|
48337
|
-
if (column === void 0) { column = 0; }
|
|
48338
|
-
return {
|
|
48339
|
-
type: type,
|
|
48340
|
-
code: code,
|
|
48341
|
-
message: message,
|
|
48342
|
-
suggestion: suggestion,
|
|
48343
|
-
line: line,
|
|
48344
|
-
column: column,
|
|
48345
|
-
};
|
|
48346
|
-
};
|
|
48347
|
-
/**
|
|
48348
|
-
* 检查TypeScript语法在组件方法中
|
|
48349
|
-
*/
|
|
48350
|
-
UnifiedTSXValidator.prototype.checkTypeScriptSyntaxInMethods = function (ast, issues) {
|
|
48351
|
-
var _this = this;
|
|
48352
|
-
this.log('开始检查TypeScript语法在组件方法中');
|
|
48353
|
-
// 找到React组件类并检查方法
|
|
48354
|
-
traverse__default["default"](ast, {
|
|
48355
|
-
ClassDeclaration: function (path) {
|
|
48356
|
-
var _a;
|
|
48357
|
-
if (_this.isReactComponent(path.node.superClass)) {
|
|
48358
|
-
var className = (_a = path.node.id) === null || _a === void 0 ? void 0 : _a.name;
|
|
48359
|
-
_this.log("\u68C0\u67E5TypeScript\u8BED\u6CD5\u5728\u7EC4\u4EF6\u7C7B: ".concat(className));
|
|
48360
|
-
// 检查类中的所有方法
|
|
48361
|
-
path.node.body.body.forEach(function (member) {
|
|
48362
|
-
var _a;
|
|
48363
|
-
if (member.type === 'ClassMethod') {
|
|
48364
|
-
var methodName_1 = (_a = member.key) === null || _a === void 0 ? void 0 : _a.name;
|
|
48365
|
-
// 跳过render方法的TypeScript语法检查(render方法本身已经单独处理)
|
|
48366
|
-
if (methodName_1 === 'render')
|
|
48367
|
-
return;
|
|
48368
|
-
// 检查方法参数中的TypeScript语法
|
|
48369
|
-
member.params.forEach(function (param, index) {
|
|
48370
|
-
// 检查是否有类型注解
|
|
48371
|
-
if (param.typeAnnotation) {
|
|
48372
|
-
issues.push(_this.createIssueFromNode('TYPESCRIPT_IN_METHOD_PARAMS', 'error', "\u65B9\u6CD5 ".concat(methodName_1, " \u7684\u7B2C ").concat(index + 1, " \u4E2A\u53C2\u6570\u5305\u542BTypeScript\u7C7B\u578B\u6CE8\u89E3"), "\u8BF7\u79FB\u9664\u53C2\u6570\u7684\u7C7B\u578B\u6CE8\u89E3\uFF0C\u4F7F\u7528\u7EAFJavaScript\u8BED\u6CD5\uFF0C\u5982\u5C06 '".concat(param.name.name || param.name, ": string' \u6539\u4E3A '").concat(param.name.name || param.name, "'"), param));
|
|
48373
|
-
}
|
|
48374
|
-
});
|
|
48375
|
-
// 检查方法返回值的TypeScript语法
|
|
48376
|
-
if (member.returnType) {
|
|
48377
|
-
issues.push(_this.createIssueFromNode('TYPESCRIPT_IN_RETURN_TYPE', 'error', "\u65B9\u6CD5 ".concat(methodName_1, " \u5305\u542BTypeScript\u8FD4\u56DE\u503C\u7C7B\u578B\u6CE8\u89E3"), "\u8BF7\u79FB\u9664\u8FD4\u56DE\u503C\u7684\u7C7B\u578B\u6CE8\u89E3\uFF0C\u4F7F\u7528\u7EAFJavaScript\u8BED\u6CD5", member));
|
|
48378
|
-
}
|
|
48379
|
-
// 检查方法中是否包含JSX返回
|
|
48380
|
-
if (_this.methodContainsJSX(member)) {
|
|
48381
|
-
issues.push(_this.createIssueFromNode('METHOD_CONTAINS_JSX', 'error', "\u65B9\u6CD5 ".concat(methodName_1, " \u4E0D\u80FD\u5305\u542B JSX \u8BED\u6CD5"), '只有 render() 方法可以包含 JSX,其他方法只处理逻辑', member));
|
|
48382
|
-
}
|
|
48383
|
-
// 检查方法体中的变量声明的TypeScript语法
|
|
48384
|
-
// 直接遍历AST节点而不使用traverse
|
|
48385
|
-
_this.checkVariableTypeAnnotationsInNode(member, methodName_1, issues);
|
|
48386
|
-
}
|
|
48387
|
-
});
|
|
48388
|
-
}
|
|
48389
|
-
},
|
|
48390
|
-
});
|
|
48391
|
-
};
|
|
48392
47925
|
/**
|
|
48393
|
-
*
|
|
47926
|
+
* 检查方法定义
|
|
48394
47927
|
*/
|
|
48395
|
-
|
|
48396
|
-
var
|
|
48397
|
-
|
|
48398
|
-
|
|
48399
|
-
|
|
48400
|
-
|
|
48401
|
-
|
|
47928
|
+
TSXComplianceChecker.checkMethodDefinition = function (path, content, issues) {
|
|
47929
|
+
var node = path.node;
|
|
47930
|
+
// 跳过 render 方法和渲染相关方法
|
|
47931
|
+
if (t__namespace.isIdentifier(node.key)) {
|
|
47932
|
+
var methodName = node.key.name;
|
|
47933
|
+
var renderMethods = [
|
|
47934
|
+
'render',
|
|
47935
|
+
'renderItem',
|
|
47936
|
+
'renderContent',
|
|
47937
|
+
'renderHeader',
|
|
47938
|
+
'renderFooter',
|
|
47939
|
+
];
|
|
47940
|
+
if (renderMethods.includes(methodName))
|
|
48402
47941
|
return;
|
|
48403
|
-
|
|
48404
|
-
|
|
48405
|
-
|
|
48406
|
-
|
|
48407
|
-
|
|
48408
|
-
|
|
48409
|
-
if (node[key] && typeof node[key] === 'object') {
|
|
48410
|
-
if (checkJSX(node[key])) {
|
|
48411
|
-
return true;
|
|
48412
|
-
}
|
|
48413
|
-
}
|
|
48414
|
-
}
|
|
48415
|
-
return false;
|
|
48416
|
-
};
|
|
48417
|
-
// 检查方法体中的所有语句
|
|
48418
|
-
if (Array.isArray(methodNode.body.body)) {
|
|
48419
|
-
try {
|
|
48420
|
-
for (var _b = __values(methodNode.body.body), _c = _b.next(); !_c.done; _c = _b.next()) {
|
|
48421
|
-
var statement = _c.value;
|
|
48422
|
-
if (checkJSX(statement)) {
|
|
48423
|
-
return true;
|
|
48424
|
-
}
|
|
48425
|
-
}
|
|
48426
|
-
}
|
|
48427
|
-
catch (e_4_1) { e_4 = { error: e_4_1 }; }
|
|
48428
|
-
finally {
|
|
48429
|
-
try {
|
|
48430
|
-
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
48431
|
-
}
|
|
48432
|
-
finally { if (e_4) throw e_4.error; }
|
|
48433
|
-
}
|
|
48434
|
-
}
|
|
48435
|
-
else if (methodNode.body) {
|
|
48436
|
-
if (checkJSX(methodNode.body)) {
|
|
48437
|
-
return true;
|
|
48438
|
-
}
|
|
48439
|
-
}
|
|
48440
|
-
return containsJSX;
|
|
48441
|
-
};
|
|
48442
|
-
/**
|
|
48443
|
-
* 递归检查节点中的变量类型注解
|
|
48444
|
-
*/
|
|
48445
|
-
UnifiedTSXValidator.prototype.checkVariableTypeAnnotationsInNode = function (node, methodName, issues) {
|
|
48446
|
-
var _this = this;
|
|
48447
|
-
if (!node)
|
|
48448
|
-
return;
|
|
48449
|
-
// 如果是数组,遍历每个元素
|
|
48450
|
-
if (Array.isArray(node)) {
|
|
48451
|
-
node.forEach(function (item) { return _this.checkVariableTypeAnnotationsInNode(item, methodName, issues); });
|
|
48452
|
-
return;
|
|
48453
|
-
}
|
|
48454
|
-
// 检查变量声明
|
|
48455
|
-
if (node.type === 'VariableDeclaration') {
|
|
48456
|
-
node.declarations.forEach(function (declaration) {
|
|
48457
|
-
if (declaration.id && declaration.id.typeAnnotation) {
|
|
48458
|
-
issues.push(_this.createIssueFromNode('TYPESCRIPT_IN_VARIABLES', 'error', "\u65B9\u6CD5 ".concat(methodName, " \u4E2D\u7684\u53D8\u91CF\u58F0\u660E\u5305\u542BTypeScript\u7C7B\u578B\u6CE8\u89E3"), "\u8BF7\u79FB\u9664\u53D8\u91CF\u7684\u7C7B\u578B\u6CE8\u89E3\uFF0C\u4F7F\u7528\u7EAFJavaScript\u8BED\u6CD5\uFF0C\u5982\u5C06 'let name: string' \u6539\u4E3A 'let name'", declaration));
|
|
48459
|
-
}
|
|
47942
|
+
// 检查方法中是否包含 JSX
|
|
47943
|
+
var containsJSX_1 = false;
|
|
47944
|
+
path.traverse({
|
|
47945
|
+
JSXElement: function () {
|
|
47946
|
+
containsJSX_1 = true;
|
|
47947
|
+
},
|
|
48460
47948
|
});
|
|
48461
|
-
|
|
48462
|
-
|
|
48463
|
-
|
|
48464
|
-
|
|
48465
|
-
|
|
48466
|
-
|
|
48467
|
-
|
|
48468
|
-
|
|
48469
|
-
|
|
48470
|
-
|
|
48471
|
-
|
|
48472
|
-
|
|
48473
|
-
|
|
48474
|
-
|
|
48475
|
-
|
|
48476
|
-
this.checkVariableTypeAnnotationsInNode(node.expression, methodName, issues);
|
|
47949
|
+
if (containsJSX_1) {
|
|
47950
|
+
var _a = this.getLocation(path, content), line = _a.line, column = _a.column;
|
|
47951
|
+
var snippet = this.extractCodeSnippet(content, line);
|
|
47952
|
+
issues.push({
|
|
47953
|
+
type: 'error',
|
|
47954
|
+
code: 'METHOD_CONTAINS_JSX',
|
|
47955
|
+
message: "\u65B9\u6CD5 ".concat(methodName, " \u4E0D\u80FD\u5305\u542B JSX \u8BED\u6CD5"),
|
|
47956
|
+
suggestion: '只有 render() 方法可以包含 JSX,其他方法只处理逻辑',
|
|
47957
|
+
line: line,
|
|
47958
|
+
column: column,
|
|
47959
|
+
codeSnippet: snippet.snippet,
|
|
47960
|
+
snippetStartLine: snippet.startLine,
|
|
47961
|
+
snippetEndLine: snippet.endLine,
|
|
47962
|
+
});
|
|
47963
|
+
}
|
|
48477
47964
|
}
|
|
48478
47965
|
};
|
|
48479
47966
|
/**
|
|
48480
|
-
*
|
|
47967
|
+
* 检查 JSX 使用
|
|
48481
47968
|
*/
|
|
48482
|
-
|
|
48483
|
-
|
|
48484
|
-
checkFunction();
|
|
48485
|
-
}
|
|
48486
|
-
catch (error) {
|
|
48487
|
-
this.log("".concat(methodName, " \u68C0\u67E5\u65F6\u53D1\u751F\u9519\u8BEF: ").concat(error.message));
|
|
48488
|
-
// 不抛出异常,只记录日志
|
|
48489
|
-
}
|
|
48490
|
-
};
|
|
48491
|
-
UnifiedTSXValidator.prototype.log = function (message) {
|
|
48492
|
-
if (this.debug) {
|
|
48493
|
-
console.log("[UnifiedTSXValidator] ".concat(message));
|
|
48494
|
-
}
|
|
47969
|
+
TSXComplianceChecker.checkJSXUsage = function (path, content, issues) {
|
|
47970
|
+
// 暂时不实现,专注于变量声明检查
|
|
48495
47971
|
};
|
|
48496
47972
|
/**
|
|
48497
|
-
*
|
|
47973
|
+
* 检查类型注解
|
|
48498
47974
|
*/
|
|
48499
|
-
|
|
48500
|
-
|
|
48501
|
-
.filter(function (issue) { return issue.type === 'error'; })
|
|
48502
|
-
.map(function (issue) {
|
|
48503
|
-
var location = issue.line ? " (\u7B2C".concat(issue.line, "\u884C)") : '';
|
|
48504
|
-
return "[".concat(issue.code, "] ").concat(issue.message).concat(location);
|
|
48505
|
-
});
|
|
47975
|
+
TSXComplianceChecker.checkTypeAnnotation = function (path, content, issues) {
|
|
47976
|
+
// 暂时不实现,专注于变量声明检查
|
|
48506
47977
|
};
|
|
48507
47978
|
/**
|
|
48508
|
-
*
|
|
47979
|
+
* 检查必需的结构
|
|
48509
47980
|
*/
|
|
48510
|
-
|
|
48511
|
-
|
|
48512
|
-
|
|
48513
|
-
report += "\u6587\u4EF6: ".concat(this.filename, "\n");
|
|
48514
|
-
if (isCompliant) {
|
|
48515
|
-
report += '✅ 检查通过:文件符合 TSX 规范\n';
|
|
48516
|
-
}
|
|
48517
|
-
else {
|
|
48518
|
-
var errorCount = issues.filter(function (issue) { return issue.type === 'error'; }).length;
|
|
48519
|
-
report += "\u274C \u68C0\u67E5\u5931\u8D25\uFF1A\u53D1\u73B0 ".concat(errorCount, " \u4E2A\u9519\u8BEF\n\n");
|
|
48520
|
-
report += '--- 问题详情 ---\n';
|
|
48521
|
-
issues.forEach(function (issue, index) {
|
|
48522
|
-
var icon = issue.type === 'error' ? '❌' : '⚠️';
|
|
48523
|
-
report += "".concat(index + 1, ". ").concat(icon, " [").concat(issue.code, "] ").concat(issue.message, "\n");
|
|
48524
|
-
if (issue.line) {
|
|
48525
|
-
report += " \uD83D\uDCCD \u4F4D\u7F6E: \u7B2C ".concat(issue.line, " \u884C\n");
|
|
48526
|
-
}
|
|
48527
|
-
report += " \uD83D\uDCA1 \u5EFA\u8BAE: ".concat(issue.suggestion, "\n\n");
|
|
48528
|
-
});
|
|
48529
|
-
}
|
|
48530
|
-
return report;
|
|
47981
|
+
TSXComplianceChecker.checkRequiredStructures = function (ast, content, issues) {
|
|
47982
|
+
// 这里可以添加对必需结构的检查
|
|
47983
|
+
// 如 IProps, IState, Document 类等
|
|
48531
47984
|
};
|
|
48532
|
-
return UnifiedTSXValidator;
|
|
48533
|
-
}());
|
|
48534
|
-
|
|
48535
|
-
var TSXComplianceChecker = /** @class */ (function () {
|
|
48536
|
-
function TSXComplianceChecker() {
|
|
48537
|
-
}
|
|
48538
47985
|
/**
|
|
48539
|
-
*
|
|
47986
|
+
* 获取节点在源码中的位置
|
|
48540
47987
|
*/
|
|
48541
|
-
TSXComplianceChecker.
|
|
48542
|
-
var
|
|
48543
|
-
|
|
48544
|
-
|
|
48545
|
-
|
|
48546
|
-
|
|
48547
|
-
// 为CLI添加代码片段
|
|
48548
|
-
codeSnippet: issue.line ? _this.extractCodeSnippet(content, issue.line).snippet : undefined, snippetStartLine: issue.line ? _this.extractCodeSnippet(content, issue.line).startLine : undefined, snippetEndLine: issue.line ? _this.extractCodeSnippet(content, issue.line).endLine : undefined })); });
|
|
48549
|
-
return {
|
|
48550
|
-
isCompliant: result.isCompliant,
|
|
48551
|
-
issues: compliantIssues,
|
|
48552
|
-
};
|
|
48553
|
-
}
|
|
48554
|
-
catch (error) {
|
|
48555
|
-
// 捕获任何异常并返回合规结果,而不是让异常向上传播
|
|
48556
|
-
return {
|
|
48557
|
-
isCompliant: false,
|
|
48558
|
-
issues: [{
|
|
48559
|
-
type: 'error',
|
|
48560
|
-
code: 'VALIDATION_ERROR',
|
|
48561
|
-
message: "\u9A8C\u8BC1\u8FC7\u7A0B\u53D1\u751F\u9519\u8BEF: ".concat(error.message),
|
|
48562
|
-
suggestion: '请检查代码语法或联系开发团队',
|
|
48563
|
-
line: 1,
|
|
48564
|
-
column: 0,
|
|
48565
|
-
}],
|
|
48566
|
-
};
|
|
48567
|
-
}
|
|
47988
|
+
TSXComplianceChecker.getLocation = function (path, content) {
|
|
47989
|
+
var loc = path.node.loc;
|
|
47990
|
+
return {
|
|
47991
|
+
line: loc ? loc.start.line : 1,
|
|
47992
|
+
column: loc ? loc.start.column : 0,
|
|
47993
|
+
};
|
|
48568
47994
|
};
|
|
48569
|
-
// 移除了所有旧的检查方法,现在使用UnifiedTSXValidator
|
|
48570
47995
|
/**
|
|
48571
47996
|
* 提取代码片段
|
|
48572
47997
|
*/
|
|
@@ -48588,33 +48013,34 @@ var TSXComplianceChecker = /** @class */ (function () {
|
|
|
48588
48013
|
};
|
|
48589
48014
|
};
|
|
48590
48015
|
/**
|
|
48591
|
-
*
|
|
48016
|
+
* 生成检查报告
|
|
48592
48017
|
*/
|
|
48593
48018
|
TSXComplianceChecker.generateReport = function (result, filename) {
|
|
48594
|
-
|
|
48595
|
-
|
|
48596
|
-
|
|
48597
|
-
|
|
48598
|
-
|
|
48599
|
-
*/
|
|
48600
|
-
TSXComplianceChecker.extractCodeSnippet = function (content, lineNumber, contextLines) {
|
|
48601
|
-
if (contextLines === void 0) { contextLines = 3; }
|
|
48602
|
-
var lines = content.split('\n');
|
|
48603
|
-
var startLine = Math.max(1, lineNumber - contextLines);
|
|
48604
|
-
var endLine = Math.min(lines.length, lineNumber + contextLines);
|
|
48605
|
-
var snippetLines = [];
|
|
48606
|
-
for (var i = startLine; i <= endLine; i++) {
|
|
48607
|
-
var line = lines[i - 1] || '';
|
|
48608
|
-
var prefix = i === lineNumber ? '>>> ' : ' ';
|
|
48609
|
-
snippetLines.push("".concat(prefix).concat(i.toString().padStart(3), ": ").concat(line));
|
|
48019
|
+
var isCompliant = result.isCompliant, issues = result.issues;
|
|
48020
|
+
var report = '=== TSX 规范检查报告 ===\n';
|
|
48021
|
+
report += "\u6587\u4EF6: ".concat(filename, "\n");
|
|
48022
|
+
if (isCompliant) {
|
|
48023
|
+
report += '✅ 检查通过:文件符合 TSX 规范\n';
|
|
48610
48024
|
}
|
|
48611
|
-
|
|
48612
|
-
|
|
48613
|
-
|
|
48614
|
-
|
|
48615
|
-
|
|
48025
|
+
else {
|
|
48026
|
+
var errorCount = issues.filter(function (issue) { return issue.type === 'error'; }).length;
|
|
48027
|
+
report += "\u274C \u68C0\u67E5\u5931\u8D25\uFF1A\u53D1\u73B0 ".concat(errorCount, " \u4E2A\u9519\u8BEF\n\n");
|
|
48028
|
+
report += '--- 问题详情 ---\n';
|
|
48029
|
+
issues.forEach(function (issue, index) {
|
|
48030
|
+
var icon = issue.type === 'error' ? '❌' : '⚠️';
|
|
48031
|
+
report += "".concat(index + 1, ". ").concat(icon, " [").concat(issue.code, "] ").concat(issue.message, "\n");
|
|
48032
|
+
if (issue.line) {
|
|
48033
|
+
report += " \uD83D\uDCCD \u4F4D\u7F6E: \u7B2C ".concat(issue.line, " \u884C\n");
|
|
48034
|
+
}
|
|
48035
|
+
report += " \uD83D\uDCA1 \u5EFA\u8BAE: ".concat(issue.suggestion, "\n");
|
|
48036
|
+
if (issue.codeSnippet) {
|
|
48037
|
+
report += " \uD83D\uDCDD \u4EE3\u7801\u7247\u6BB5:\n".concat(issue.codeSnippet, "\n");
|
|
48038
|
+
}
|
|
48039
|
+
report += '\n';
|
|
48040
|
+
});
|
|
48041
|
+
}
|
|
48042
|
+
return report;
|
|
48616
48043
|
};
|
|
48617
|
-
TSXComplianceChecker.validator = new UnifiedTSXValidator(false);
|
|
48618
48044
|
return TSXComplianceChecker;
|
|
48619
48045
|
}());
|
|
48620
48046
|
|
|
@@ -48651,11 +48077,11 @@ function checkTSX(options) {
|
|
|
48651
48077
|
'**/.next/**',
|
|
48652
48078
|
],
|
|
48653
48079
|
absolute: false,
|
|
48654
|
-
}, function (err,
|
|
48080
|
+
}, function (err, validatedFiles) {
|
|
48655
48081
|
if (err)
|
|
48656
48082
|
reject(err);
|
|
48657
48083
|
else
|
|
48658
|
-
resolve(
|
|
48084
|
+
resolve(validatedFiles || []);
|
|
48659
48085
|
});
|
|
48660
48086
|
})];
|
|
48661
48087
|
case 1:
|