agent-ide 0.8.2 → 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/dist/core/change-signature/call-site-updater.d.ts +108 -0
  2. package/dist/core/change-signature/call-site-updater.d.ts.map +1 -0
  3. package/dist/core/change-signature/call-site-updater.js +347 -0
  4. package/dist/core/change-signature/call-site-updater.js.map +1 -0
  5. package/dist/core/change-signature/change-signature-service.d.ts +4 -55
  6. package/dist/core/change-signature/change-signature-service.d.ts.map +1 -1
  7. package/dist/core/change-signature/change-signature-service.js +17 -483
  8. package/dist/core/change-signature/change-signature-service.js.map +1 -1
  9. package/dist/core/change-signature/index.d.ts +4 -0
  10. package/dist/core/change-signature/index.d.ts.map +1 -1
  11. package/dist/core/change-signature/index.js +5 -0
  12. package/dist/core/change-signature/index.js.map +1 -1
  13. package/dist/core/change-signature/signature-transformer.d.ts +20 -0
  14. package/dist/core/change-signature/signature-transformer.d.ts.map +1 -0
  15. package/dist/core/change-signature/signature-transformer.js +91 -0
  16. package/dist/core/change-signature/signature-transformer.js.map +1 -0
  17. package/dist/core/change-signature/signature-validator.d.ts +30 -0
  18. package/dist/core/change-signature/signature-validator.d.ts.map +1 -0
  19. package/dist/core/change-signature/signature-validator.js +152 -0
  20. package/dist/core/change-signature/signature-validator.js.map +1 -0
  21. package/dist/core/change-signature/utils.d.ts +19 -0
  22. package/dist/core/change-signature/utils.d.ts.map +1 -0
  23. package/dist/core/change-signature/utils.js +23 -0
  24. package/dist/core/change-signature/utils.js.map +1 -0
  25. package/dist/core/cycles/cycle-detector.d.ts.map +1 -1
  26. package/dist/core/cycles/cycle-detector.js +16 -8
  27. package/dist/core/cycles/cycle-detector.js.map +1 -1
  28. package/dist/core/cycles/index.d.ts +1 -1
  29. package/dist/core/cycles/index.d.ts.map +1 -1
  30. package/dist/core/cycles/index.js +1 -1
  31. package/dist/core/cycles/index.js.map +1 -1
  32. package/dist/core/cycles/types.d.ts +20 -4
  33. package/dist/core/cycles/types.d.ts.map +1 -1
  34. package/dist/core/cycles/types.js +22 -4
  35. package/dist/core/cycles/types.js.map +1 -1
  36. package/dist/core/deadcode/dead-code-remover.js +4 -4
  37. package/dist/core/deadcode/dead-code-remover.js.map +1 -1
  38. package/dist/core/impact/dependency-extractor.d.ts +25 -0
  39. package/dist/core/impact/dependency-extractor.d.ts.map +1 -0
  40. package/dist/core/impact/dependency-extractor.js +65 -0
  41. package/dist/core/impact/dependency-extractor.js.map +1 -0
  42. package/dist/core/impact/file-scanner.d.ts +52 -0
  43. package/dist/core/impact/file-scanner.d.ts.map +1 -0
  44. package/dist/core/impact/file-scanner.js +131 -0
  45. package/dist/core/impact/file-scanner.js.map +1 -0
  46. package/dist/core/impact/impact-analyzer.d.ts +3 -64
  47. package/dist/core/impact/impact-analyzer.d.ts.map +1 -1
  48. package/dist/core/impact/impact-analyzer.js +13 -312
  49. package/dist/core/impact/impact-analyzer.js.map +1 -1
  50. package/dist/core/impact/index.d.ts +3 -0
  51. package/dist/core/impact/index.d.ts.map +1 -1
  52. package/dist/core/impact/index.js +3 -0
  53. package/dist/core/impact/index.js.map +1 -1
  54. package/dist/core/impact/path-resolver.d.ts +35 -0
  55. package/dist/core/impact/path-resolver.d.ts.map +1 -0
  56. package/dist/core/impact/path-resolver.js +166 -0
  57. package/dist/core/impact/path-resolver.js.map +1 -0
  58. package/dist/core/move/file-scanner.d.ts +48 -0
  59. package/dist/core/move/file-scanner.d.ts.map +1 -0
  60. package/dist/core/move/file-scanner.js +137 -0
  61. package/dist/core/move/file-scanner.js.map +1 -0
  62. package/dist/core/move/import-resolver.d.ts +5 -0
  63. package/dist/core/move/import-resolver.d.ts.map +1 -1
  64. package/dist/core/move/import-resolver.js +24 -6
  65. package/dist/core/move/import-resolver.js.map +1 -1
  66. package/dist/core/move/index.d.ts +7 -3
  67. package/dist/core/move/index.d.ts.map +1 -1
  68. package/dist/core/move/index.js +7 -2
  69. package/dist/core/move/index.js.map +1 -1
  70. package/dist/core/move/move-service.d.ts +11 -60
  71. package/dist/core/move/move-service.d.ts.map +1 -1
  72. package/dist/core/move/move-service.js +16 -352
  73. package/dist/core/move/move-service.js.map +1 -1
  74. package/dist/core/move/path-calculator.d.ts +49 -0
  75. package/dist/core/move/path-calculator.d.ts.map +1 -0
  76. package/dist/core/move/path-calculator.js +158 -0
  77. package/dist/core/move/path-calculator.js.map +1 -0
  78. package/dist/core/move/path-parser.d.ts +33 -0
  79. package/dist/core/move/path-parser.d.ts.map +1 -0
  80. package/dist/core/move/path-parser.js +53 -0
  81. package/dist/core/move/path-parser.js.map +1 -0
  82. package/dist/core/move/path-utils.d.ts +70 -0
  83. package/dist/core/move/path-utils.d.ts.map +1 -0
  84. package/dist/core/move/path-utils.js +201 -0
  85. package/dist/core/move/path-utils.js.map +1 -0
  86. package/dist/core/move/types.d.ts +81 -18
  87. package/dist/core/move/types.d.ts.map +1 -1
  88. package/dist/core/move/types.js +73 -5
  89. package/dist/core/move/types.js.map +1 -1
  90. package/dist/core/move-member/change-applier.d.ts +23 -0
  91. package/dist/core/move-member/change-applier.d.ts.map +1 -0
  92. package/dist/core/move-member/change-applier.js +51 -0
  93. package/dist/core/move-member/change-applier.js.map +1 -0
  94. package/dist/core/move-member/file-change-preparer.d.ts +49 -0
  95. package/dist/core/move-member/file-change-preparer.d.ts.map +1 -0
  96. package/dist/core/move-member/file-change-preparer.js +340 -0
  97. package/dist/core/move-member/file-change-preparer.js.map +1 -0
  98. package/dist/core/move-member/index.d.ts +4 -1
  99. package/dist/core/move-member/index.d.ts.map +1 -1
  100. package/dist/core/move-member/index.js +3 -0
  101. package/dist/core/move-member/index.js.map +1 -1
  102. package/dist/core/move-member/member-extractor.d.ts +11 -0
  103. package/dist/core/move-member/member-extractor.d.ts.map +1 -1
  104. package/dist/core/move-member/member-extractor.js +114 -22
  105. package/dist/core/move-member/member-extractor.js.map +1 -1
  106. package/dist/core/move-member/move-member-service.d.ts +3 -78
  107. package/dist/core/move-member/move-member-service.d.ts.map +1 -1
  108. package/dist/core/move-member/move-member-service.js +35 -419
  109. package/dist/core/move-member/move-member-service.js.map +1 -1
  110. package/dist/core/move-member/reference-updater.d.ts +73 -0
  111. package/dist/core/move-member/reference-updater.d.ts.map +1 -0
  112. package/dist/core/move-member/reference-updater.js +286 -0
  113. package/dist/core/move-member/reference-updater.js.map +1 -0
  114. package/dist/core/move-member/types.d.ts +17 -2
  115. package/dist/core/move-member/types.d.ts.map +1 -1
  116. package/dist/core/move-member/types.js.map +1 -1
  117. package/dist/core/rename/reference-updater.d.ts.map +1 -1
  118. package/dist/core/rename/reference-updater.js +4 -1
  119. package/dist/core/rename/reference-updater.js.map +1 -1
  120. package/dist/core/rename/rename-engine.d.ts +5 -3
  121. package/dist/core/rename/rename-engine.d.ts.map +1 -1
  122. package/dist/core/rename/rename-engine.js +29 -8
  123. package/dist/core/rename/rename-engine.js.map +1 -1
  124. package/dist/core/shared/symbol-finder/symbol-finder.d.ts.map +1 -1
  125. package/dist/core/shared/symbol-finder/symbol-finder.js +9 -1
  126. package/dist/core/shared/symbol-finder/symbol-finder.js.map +1 -1
  127. package/dist/infrastructure/changeset/change-applicator.d.ts +1 -1
  128. package/dist/infrastructure/changeset/change-applicator.d.ts.map +1 -1
  129. package/dist/infrastructure/changeset/change-applicator.js +22 -21
  130. package/dist/infrastructure/changeset/change-applicator.js.map +1 -1
  131. package/dist/infrastructure/changeset/changeset-builder.d.ts +2 -2
  132. package/dist/infrastructure/changeset/changeset-builder.d.ts.map +1 -1
  133. package/dist/infrastructure/changeset/changeset-builder.js +11 -6
  134. package/dist/infrastructure/changeset/changeset-builder.js.map +1 -1
  135. package/dist/infrastructure/changeset/changeset-converter.d.ts +1 -1
  136. package/dist/infrastructure/changeset/changeset-converter.d.ts.map +1 -1
  137. package/dist/infrastructure/changeset/changeset-converter.js +9 -8
  138. package/dist/infrastructure/changeset/changeset-converter.js.map +1 -1
  139. package/dist/infrastructure/changeset/index.d.ts +1 -0
  140. package/dist/infrastructure/changeset/index.d.ts.map +1 -1
  141. package/dist/infrastructure/changeset/index.js +2 -0
  142. package/dist/infrastructure/changeset/index.js.map +1 -1
  143. package/dist/infrastructure/changeset/types.d.ts +41 -4
  144. package/dist/infrastructure/changeset/types.d.ts.map +1 -1
  145. package/dist/infrastructure/changeset/types.js +41 -1
  146. package/dist/infrastructure/changeset/types.js.map +1 -1
  147. package/dist/interfaces/cli/cli.d.ts.map +1 -1
  148. package/dist/interfaces/cli/cli.js +1 -2
  149. package/dist/interfaces/cli/cli.js.map +1 -1
  150. package/dist/interfaces/cli/commands/index.d.ts +0 -1
  151. package/dist/interfaces/cli/commands/index.d.ts.map +1 -1
  152. package/dist/interfaces/cli/commands/index.js +0 -1
  153. package/dist/interfaces/cli/commands/index.js.map +1 -1
  154. package/dist/interfaces/cli/commands/move.command.d.ts +1 -0
  155. package/dist/interfaces/cli/commands/move.command.d.ts.map +1 -1
  156. package/dist/interfaces/cli/commands/move.command.js +127 -11
  157. package/dist/interfaces/cli/commands/move.command.js.map +1 -1
  158. package/dist/interfaces/cli/commands/rename.command.d.ts.map +1 -1
  159. package/dist/interfaces/cli/commands/rename.command.js +114 -6
  160. package/dist/interfaces/cli/commands/rename.command.js.map +1 -1
  161. package/dist/plugins/javascript/declaration-analyzer.d.ts.map +1 -1
  162. package/dist/plugins/javascript/declaration-analyzer.js +9 -0
  163. package/dist/plugins/javascript/declaration-analyzer.js.map +1 -1
  164. package/dist/plugins/typescript/declaration-analyzer.d.ts.map +1 -1
  165. package/dist/plugins/typescript/declaration-analyzer.js +4 -0
  166. package/dist/plugins/typescript/declaration-analyzer.js.map +1 -1
  167. package/dist/plugins/typescript/reference-finder.d.ts.map +1 -1
  168. package/dist/plugins/typescript/reference-finder.js +11 -2
  169. package/dist/plugins/typescript/reference-finder.js.map +1 -1
  170. package/dist/plugins/typescript/symbol-extractor.d.ts.map +1 -1
  171. package/dist/plugins/typescript/symbol-extractor.js +6 -2
  172. package/dist/plugins/typescript/symbol-extractor.js.map +1 -1
  173. package/package.json +1 -1
  174. package/dist/interfaces/cli/commands/move-member.command.d.ts +0 -11
  175. package/dist/interfaces/cli/commands/move-member.command.d.ts.map +0 -1
  176. package/dist/interfaces/cli/commands/move-member.command.js +0 -140
  177. package/dist/interfaces/cli/commands/move-member.command.js.map +0 -1
@@ -0,0 +1,340 @@
1
+ /**
2
+ * File Change Preparer
3
+ * 負責準備來源檔案和目標檔案的變更
4
+ */
5
+ import * as path from 'path';
6
+ import { MoveTargetType } from './types.js';
7
+ /**
8
+ * Import 類型
9
+ */
10
+ var ImportType;
11
+ (function (ImportType) {
12
+ ImportType["Named"] = "named";
13
+ ImportType["Namespace"] = "namespace";
14
+ ImportType["Default"] = "default";
15
+ })(ImportType || (ImportType = {}));
16
+ /**
17
+ * File Change Preparer
18
+ * 負責準備來源檔案和目標檔案的程式碼變更
19
+ */
20
+ export class FileChangePreparer {
21
+ fileSystem;
22
+ constructor(fileSystem) {
23
+ this.fileSystem = fileSystem;
24
+ }
25
+ /**
26
+ * 準備來源檔案變更
27
+ */
28
+ async prepareSourceFileChange(options, member) {
29
+ const content = await this.readFile(options.sourceFile);
30
+ if (!content) {
31
+ throw new Error(`無法讀取來源檔案: ${options.sourceFile}`);
32
+ }
33
+ const lines = content.split('\n');
34
+ const startLine = member.location.range.start.line - 1;
35
+ const endLine = member.location.range.end.line - 1;
36
+ // 移除成員(包含前面的文件註解)
37
+ let removeStartLine = startLine;
38
+ if (member.documentation) {
39
+ const docLines = member.documentation.split('\n').length;
40
+ removeStartLine = Math.max(0, startLine - docLines);
41
+ }
42
+ // 處理 re-export
43
+ let reexportStatement = '';
44
+ if (options.keepReexport) {
45
+ const relativePath = this.calculateRelativePath(options.sourceFile, options.target.filePath);
46
+ reexportStatement = `export { ${member.name} } from '${relativePath}';\n`;
47
+ }
48
+ const newLines = [
49
+ ...lines.slice(0, removeStartLine),
50
+ ...(options.keepReexport ? [reexportStatement] : []),
51
+ ...lines.slice(endLine + 1)
52
+ ];
53
+ return {
54
+ filePath: options.sourceFile,
55
+ originalCode: content,
56
+ newCode: newLines.join('\n')
57
+ };
58
+ }
59
+ /**
60
+ * 準備目標檔案變更
61
+ * 自動判斷目標檔案是否存在:存在則插入,不存在則創建新檔案
62
+ */
63
+ async prepareTargetFileChange(options, member) {
64
+ const { target } = options;
65
+ // 準備要插入的程式碼
66
+ let memberCode = member.sourceCode;
67
+ if (member.documentation) {
68
+ memberCode = member.documentation + '\n' + memberCode;
69
+ }
70
+ // 確保有 export(如果原本有)
71
+ if (!memberCode.includes('export') && member.modifiers.includes('export')) {
72
+ memberCode = 'export ' + memberCode;
73
+ }
74
+ // 分析成員依賴並生成需要的 import
75
+ const sourceContent = await this.readFile(options.sourceFile);
76
+ const dependencyImports = sourceContent
77
+ ? await this.generateDependencyImports(member, sourceContent, options.sourceFile, target.filePath)
78
+ : '';
79
+ // 自動判斷檔案是否存在
80
+ const content = await this.readFile(target.filePath);
81
+ const isNewFile = content === null;
82
+ if (isNewFile) {
83
+ // 新檔案:生成完整的檔案內容
84
+ const newCode = dependencyImports + (dependencyImports ? '\n\n' : '') + memberCode + '\n';
85
+ return {
86
+ filePath: target.filePath,
87
+ originalCode: null,
88
+ newCode,
89
+ isNewFile: true
90
+ };
91
+ }
92
+ // 現有檔案
93
+ const lines = content.split('\n');
94
+ let insertLine = target.insertPosition ?? -1;
95
+ if (target.type === MoveTargetType.ExistingClass && target.className) {
96
+ // 插入到類別內
97
+ insertLine = await this.findClassInsertPosition(content, target.className);
98
+ }
99
+ if (insertLine < 0) {
100
+ // 預設插入到檔案結尾
101
+ insertLine = lines.length;
102
+ }
103
+ // 現有檔案:將 import 插入到檔案開頭(在現有 import 之後)
104
+ let finalCode;
105
+ if (dependencyImports) {
106
+ const importInsertLine = this.findImportInsertPosition(lines);
107
+ const newLines = [
108
+ ...lines.slice(0, importInsertLine),
109
+ dependencyImports,
110
+ ...lines.slice(importInsertLine, insertLine),
111
+ '',
112
+ memberCode,
113
+ ...lines.slice(insertLine)
114
+ ];
115
+ finalCode = newLines.join('\n');
116
+ }
117
+ else {
118
+ const newLines = [
119
+ ...lines.slice(0, insertLine),
120
+ '',
121
+ memberCode,
122
+ ...lines.slice(insertLine)
123
+ ];
124
+ finalCode = newLines.join('\n');
125
+ }
126
+ return {
127
+ filePath: target.filePath,
128
+ originalCode: content,
129
+ newCode: finalCode,
130
+ isNewFile: false
131
+ };
132
+ }
133
+ /**
134
+ * 找到 import 插入位置(在最後一個 import 之後)
135
+ */
136
+ findImportInsertPosition(lines) {
137
+ let lastImportLine = 0;
138
+ for (let i = 0; i < lines.length; i++) {
139
+ const line = lines[i].trim();
140
+ if (line.startsWith('import ') || line.startsWith('import{')) {
141
+ lastImportLine = i + 1;
142
+ }
143
+ // 遇到非 import、非空行、非註解,停止搜尋
144
+ if (line && !line.startsWith('import') && !line.startsWith('//') && !line.startsWith('/*') && !line.startsWith('*')) {
145
+ break;
146
+ }
147
+ }
148
+ return lastImportLine;
149
+ }
150
+ /**
151
+ * 生成成員依賴的 import
152
+ */
153
+ async generateDependencyImports(member, sourceContent, sourceFile, targetFile) {
154
+ const symbolInfo = this.analyzeSourceSymbols(sourceContent);
155
+ // 按 modulePath 和 importType 分組
156
+ // key: `${modulePath}::${importType}`, value: Set<symbolName>
157
+ const neededImports = new Map();
158
+ // 分析成員依賴的符號
159
+ for (const dep of member.dependencies) {
160
+ // 跳過成員自己的名稱
161
+ if (dep === member.name) {
162
+ continue;
163
+ }
164
+ if (symbolInfo.localExports.has(dep)) {
165
+ // 依賴來自來源檔案的本地 export,需要從來源檔案 import(使用 named import)
166
+ const relativePath = this.calculateRelativePath(targetFile, sourceFile);
167
+ const key = `${relativePath}::${ImportType.Named}`;
168
+ if (!neededImports.has(key)) {
169
+ neededImports.set(key, { modulePath: relativePath, type: ImportType.Named, symbols: new Set() });
170
+ }
171
+ neededImports.get(key).symbols.add(dep);
172
+ }
173
+ else if (symbolInfo.importedSymbols.has(dep)) {
174
+ // 依賴來自外部模組,保持原本的 import 類型
175
+ const importInfo = symbolInfo.importedSymbols.get(dep);
176
+ const key = `${importInfo.modulePath}::${importInfo.type}`;
177
+ if (!neededImports.has(key)) {
178
+ neededImports.set(key, { modulePath: importInfo.modulePath, type: importInfo.type, symbols: new Set() });
179
+ }
180
+ neededImports.get(key).symbols.add(dep);
181
+ }
182
+ }
183
+ // 生成 import 語句
184
+ const importLines = [];
185
+ for (const { modulePath, type, symbols } of neededImports.values()) {
186
+ const symbolList = Array.from(symbols).sort();
187
+ switch (type) {
188
+ case ImportType.Namespace:
189
+ // import * as name from 'module' - 只取第一個符號作為 namespace 名稱
190
+ importLines.push(`import * as ${symbolList[0]} from '${modulePath}';`);
191
+ break;
192
+ case ImportType.Default:
193
+ // import name from 'module' - 只取第一個符號作為 default 名稱
194
+ importLines.push(`import ${symbolList[0]} from '${modulePath}';`);
195
+ break;
196
+ case ImportType.Named:
197
+ default:
198
+ // import { A, B } from 'module'
199
+ importLines.push(`import { ${symbolList.join(', ')} } from '${modulePath}';`);
200
+ break;
201
+ }
202
+ }
203
+ return importLines.join('\n');
204
+ }
205
+ /**
206
+ * 分析來源檔案的符號(本地 export 和 import)
207
+ */
208
+ analyzeSourceSymbols(content) {
209
+ const localExports = new Set();
210
+ const importedSymbols = new Map();
211
+ // 分析 import 語句
212
+ // import { A, B } from 'module'
213
+ const importPattern = /import\s+\{([^}]+)\}\s+from\s+['"]([^'"]+)['"]/g;
214
+ let match;
215
+ while ((match = importPattern.exec(content)) !== null) {
216
+ const symbols = match[1].split(',').map(s => s.trim().split(' as ')[0].trim());
217
+ const modulePath = match[2];
218
+ for (const symbol of symbols) {
219
+ if (symbol) {
220
+ importedSymbols.set(symbol, { modulePath, type: ImportType.Named });
221
+ }
222
+ }
223
+ }
224
+ // 分析 import * as name from 'module'
225
+ const namespaceImportPattern = /import\s+\*\s+as\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g;
226
+ while ((match = namespaceImportPattern.exec(content)) !== null) {
227
+ importedSymbols.set(match[1], { modulePath: match[2], type: ImportType.Namespace });
228
+ }
229
+ // 分析 import name from 'module' (default import)
230
+ const defaultImportPattern = /import\s+(\w+)\s+from\s+['"]([^'"]+)['"]/g;
231
+ while ((match = defaultImportPattern.exec(content)) !== null) {
232
+ // 排除已經被 namespace import 捕獲的(避免重複)
233
+ if (!importedSymbols.has(match[1])) {
234
+ importedSymbols.set(match[1], { modulePath: match[2], type: ImportType.Default });
235
+ }
236
+ }
237
+ // 分析本地 export
238
+ // export const/let/var NAME
239
+ const exportVarPattern = /export\s+(?:const|let|var)\s+(\w+)/g;
240
+ while ((match = exportVarPattern.exec(content)) !== null) {
241
+ localExports.add(match[1]);
242
+ }
243
+ // export function NAME
244
+ const exportFuncPattern = /export\s+(?:async\s+)?function\s+(\w+)/g;
245
+ while ((match = exportFuncPattern.exec(content)) !== null) {
246
+ localExports.add(match[1]);
247
+ }
248
+ // export class NAME
249
+ const exportClassPattern = /export\s+(?:abstract\s+)?class\s+(\w+)/g;
250
+ while ((match = exportClassPattern.exec(content)) !== null) {
251
+ localExports.add(match[1]);
252
+ }
253
+ // export interface NAME
254
+ const exportInterfacePattern = /export\s+interface\s+(\w+)/g;
255
+ while ((match = exportInterfacePattern.exec(content)) !== null) {
256
+ localExports.add(match[1]);
257
+ }
258
+ // export type NAME
259
+ const exportTypePattern = /export\s+type\s+(\w+)/g;
260
+ while ((match = exportTypePattern.exec(content)) !== null) {
261
+ localExports.add(match[1]);
262
+ }
263
+ // export enum NAME
264
+ const exportEnumPattern = /export\s+enum\s+(\w+)/g;
265
+ while ((match = exportEnumPattern.exec(content)) !== null) {
266
+ localExports.add(match[1]);
267
+ }
268
+ // export { A, B }(命名 re-export)
269
+ const exportListPattern = /export\s+\{([^}]+)\}(?!\s+from)/g;
270
+ while ((match = exportListPattern.exec(content)) !== null) {
271
+ const symbols = match[1].split(',').map(s => s.trim().split(' as ')[0].trim());
272
+ for (const symbol of symbols) {
273
+ if (symbol) {
274
+ localExports.add(symbol);
275
+ }
276
+ }
277
+ }
278
+ return { localExports, importedSymbols };
279
+ }
280
+ /**
281
+ * 找到類別內的插入位置
282
+ * 使用正則表達式嚴格匹配類別定義,避免匹配註解中的類別名稱
283
+ */
284
+ async findClassInsertPosition(content, className) {
285
+ const lines = content.split('\n');
286
+ let inClass = false;
287
+ let depth = 0;
288
+ // 嚴格匹配類別定義:可選的 export/abstract,後接 class 關鍵字和類別名稱
289
+ const classPattern = new RegExp(`^\\s*(export\\s+)?(abstract\\s+)?class\\s+${className}\\b`);
290
+ for (let i = 0; i < lines.length; i++) {
291
+ const line = lines[i];
292
+ // 使用正則表達式匹配,避免匹配註解
293
+ if (!inClass && classPattern.test(line)) {
294
+ inClass = true;
295
+ }
296
+ if (inClass) {
297
+ for (const char of line) {
298
+ if (char === '{') {
299
+ depth++;
300
+ }
301
+ else if (char === '}') {
302
+ depth--;
303
+ if (depth === 0) {
304
+ // 找到類別結尾,在結尾括號前插入
305
+ return i;
306
+ }
307
+ }
308
+ }
309
+ }
310
+ }
311
+ return -1;
312
+ }
313
+ /**
314
+ * 計算相對路徑
315
+ */
316
+ calculateRelativePath(from, to) {
317
+ const fromDir = path.dirname(from);
318
+ let relativePath = path.relative(fromDir, to);
319
+ // 移除副檔名
320
+ relativePath = relativePath.replace(/\.(ts|tsx|js|jsx)$/, '');
321
+ // 確保以 ./ 開頭
322
+ if (!relativePath.startsWith('.')) {
323
+ relativePath = './' + relativePath;
324
+ }
325
+ return relativePath;
326
+ }
327
+ /**
328
+ * 讀取檔案內容
329
+ */
330
+ async readFile(filePath) {
331
+ try {
332
+ const content = await this.fileSystem.readFile(filePath, 'utf-8');
333
+ return typeof content === 'string' ? content : content.toString('utf-8');
334
+ }
335
+ catch {
336
+ return null;
337
+ }
338
+ }
339
+ }
340
+ //# sourceMappingURL=file-change-preparer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file-change-preparer.js","sourceRoot":"","sources":["../../../src/core/move-member/file-change-preparer.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAG7B,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAE5C;;GAEG;AACH,IAAK,UAIJ;AAJD,WAAK,UAAU;IACb,6BAAe,CAAA;IACf,qCAAuB,CAAA;IACvB,iCAAmB,CAAA;AACrB,CAAC,EAJI,UAAU,KAAV,UAAU,QAId;AAoBD;;;GAGG;AACH,MAAM,OAAO,kBAAkB;IACA;IAA7B,YAA6B,UAAuB;QAAvB,eAAU,GAAV,UAAU,CAAa;IAAG,CAAC;IAExD;;OAEG;IACH,KAAK,CAAC,uBAAuB,CAC3B,OAA0B,EAC1B,MAAwB;QAExB,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QACxD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,aAAa,OAAO,CAAC,UAAU,EAAE,CAAC,CAAC;QACrD,CAAC;QAED,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,CAAC;QACvD,MAAM,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;QAEnD,kBAAkB;QAClB,IAAI,eAAe,GAAG,SAAS,CAAC;QAChC,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YACzB,MAAM,QAAQ,GAAG,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC;YACzD,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC,CAAC;QACtD,CAAC;QAED,eAAe;QACf,IAAI,iBAAiB,GAAG,EAAE,CAAC;QAC3B,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACzB,MAAM,YAAY,GAAG,IAAI,CAAC,qBAAqB,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;YAC7F,iBAAiB,GAAG,YAAY,MAAM,CAAC,IAAI,YAAY,YAAY,MAAM,CAAC;QAC5E,CAAC;QAED,MAAM,QAAQ,GAAG;YACf,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,eAAe,CAAC;YAClC,GAAG,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;YACpD,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC;SAC5B,CAAC;QAEF,OAAO;YACL,QAAQ,EAAE,OAAO,CAAC,UAAU;YAC5B,YAAY,EAAE,OAAO;YACrB,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC;SAC7B,CAAC;IACJ,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,uBAAuB,CAC3B,OAA0B,EAC1B,MAAwB;QAExB,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;QAE3B,YAAY;QACZ,IAAI,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;QACnC,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;YACzB,UAAU,GAAG,MAAM,CAAC,aAAa,GAAG,IAAI,GAAG,UAAU,CAAC;QACxD,CAAC;QAED,oBAAoB;QACpB,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC1E,UAAU,GAAG,SAAS,GAAG,UAAU,CAAC;QACtC,CAAC;QAED,sBAAsB;QACtB,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC9D,MAAM,iBAAiB,GAAG,aAAa;YACrC,CAAC,CAAC,MAAM,IAAI,CAAC,yBAAyB,CAClC,MAAM,EACN,aAAa,EACb,OAAO,CAAC,UAAU,EAClB,MAAM,CAAC,QAAQ,CAChB;YACH,CAAC,CAAC,EAAE,CAAC;QAEP,aAAa;QACb,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;QACrD,MAAM,SAAS,GAAG,OAAO,KAAK,IAAI,CAAC;QAEnC,IAAI,SAAS,EAAE,CAAC;YACd,gBAAgB;YAChB,MAAM,OAAO,GAAG,iBAAiB,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,UAAU,GAAG,IAAI,CAAC;YAE1F,OAAO;gBACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;gBACzB,YAAY,EAAE,IAAI;gBAClB,OAAO;gBACP,SAAS,EAAE,IAAI;aAChB,CAAC;QACJ,CAAC;QAED,OAAO;QACP,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,UAAU,GAAG,MAAM,CAAC,cAAc,IAAI,CAAC,CAAC,CAAC;QAE7C,IAAI,MAAM,CAAC,IAAI,KAAK,cAAc,CAAC,aAAa,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACrE,SAAS;YACT,UAAU,GAAG,MAAM,IAAI,CAAC,uBAAuB,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC;QAC7E,CAAC;QAED,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;YACnB,YAAY;YACZ,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC;QAC5B,CAAC;QAED,uCAAuC;QACvC,IAAI,SAAiB,CAAC;QACtB,IAAI,iBAAiB,EAAE,CAAC;YACtB,MAAM,gBAAgB,GAAG,IAAI,CAAC,wBAAwB,CAAC,KAAK,CAAC,CAAC;YAC9D,MAAM,QAAQ,GAAG;gBACf,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,gBAAgB,CAAC;gBACnC,iBAAiB;gBACjB,GAAG,KAAK,CAAC,KAAK,CAAC,gBAAgB,EAAE,UAAU,CAAC;gBAC5C,EAAE;gBACF,UAAU;gBACV,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC;aAC3B,CAAC;YACF,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;aAAM,CAAC;YACN,MAAM,QAAQ,GAAG;gBACf,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,UAAU,CAAC;gBAC7B,EAAE;gBACF,UAAU;gBACV,GAAG,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC;aAC3B,CAAC;YACF,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClC,CAAC;QAED,OAAO;YACL,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,YAAY,EAAE,OAAO;YACrB,OAAO,EAAE,SAAS;YAClB,SAAS,EAAE,KAAK;SACjB,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,wBAAwB,CAAC,KAAe;QAC9C,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAC7B,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBAC7D,cAAc,GAAG,CAAC,GAAG,CAAC,CAAC;YACzB,CAAC;YACD,0BAA0B;YAC1B,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;gBACpH,MAAM;YACR,CAAC;QACH,CAAC;QACD,OAAO,cAAc,CAAC;IACxB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,yBAAyB,CACrC,MAAwB,EACxB,aAAqB,EACrB,UAAkB,EAClB,UAAkB;QAElB,MAAM,UAAU,GAAG,IAAI,CAAC,oBAAoB,CAAC,aAAa,CAAC,CAAC;QAE5D,+BAA+B;QAC/B,8DAA8D;QAC9D,MAAM,aAAa,GAAgF,IAAI,GAAG,EAAE,CAAC;QAE7G,YAAY;QACZ,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACtC,YAAY;YACZ,IAAI,GAAG,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC;gBAAC,SAAS;YAAC,CAAC;YAEtC,IAAI,UAAU,CAAC,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBACrC,qDAAqD;gBACrD,MAAM,YAAY,GAAG,IAAI,CAAC,qBAAqB,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;gBACxE,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,UAAU,CAAC,KAAK,EAAE,CAAC;gBACnD,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC5B,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;gBACnG,CAAC;gBACD,aAAa,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC3C,CAAC;iBAAM,IAAI,UAAU,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;gBAC/C,2BAA2B;gBAC3B,MAAM,UAAU,GAAG,UAAU,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC;gBACxD,MAAM,GAAG,GAAG,GAAG,UAAU,CAAC,UAAU,KAAK,UAAU,CAAC,IAAI,EAAE,CAAC;gBAC3D,IAAI,CAAC,aAAa,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;oBAC5B,aAAa,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,UAAU,EAAE,UAAU,CAAC,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,GAAG,EAAE,EAAE,CAAC,CAAC;gBAC3G,CAAC;gBACD,aAAa,CAAC,GAAG,CAAC,GAAG,CAAE,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC3C,CAAC;QACH,CAAC;QAED,eAAe;QACf,MAAM,WAAW,GAAa,EAAE,CAAC;QACjC,KAAK,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,aAAa,CAAC,MAAM,EAAE,EAAE,CAAC;YACnE,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;YAE9C,QAAQ,IAAI,EAAE,CAAC;gBACb,KAAK,UAAU,CAAC,SAAS;oBACvB,0DAA0D;oBAC1D,WAAW,CAAC,IAAI,CAAC,eAAe,UAAU,CAAC,CAAC,CAAC,UAAU,UAAU,IAAI,CAAC,CAAC;oBACvE,MAAM;gBACR,KAAK,UAAU,CAAC,OAAO;oBACrB,mDAAmD;oBACnD,WAAW,CAAC,IAAI,CAAC,UAAU,UAAU,CAAC,CAAC,CAAC,UAAU,UAAU,IAAI,CAAC,CAAC;oBAClE,MAAM;gBACR,KAAK,UAAU,CAAC,KAAK,CAAC;gBACtB;oBACE,gCAAgC;oBAChC,WAAW,CAAC,IAAI,CAAC,YAAY,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,UAAU,IAAI,CAAC,CAAC;oBAC9E,MAAM;YACV,CAAC;QACH,CAAC;QAED,OAAO,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED;;OAEG;IACK,oBAAoB,CAAC,OAAe;QAC1C,MAAM,YAAY,GAAG,IAAI,GAAG,EAAU,CAAC;QACvC,MAAM,eAAe,GAAG,IAAI,GAAG,EAA4B,CAAC;QAE5D,eAAe;QACf,gCAAgC;QAChC,MAAM,aAAa,GAAG,iDAAiD,CAAC;QACxE,IAAI,KAAK,CAAC;QACV,OAAO,CAAC,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACtD,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC/E,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC5B,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,MAAM,EAAE,CAAC;oBACX,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,CAAC,KAAK,EAAE,CAAC,CAAC;gBACtE,CAAC;YACH,CAAC;QACH,CAAC;QAED,oCAAoC;QACpC,MAAM,sBAAsB,GAAG,qDAAqD,CAAC;QACrF,OAAO,CAAC,KAAK,GAAG,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC/D,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,SAAS,EAAE,CAAC,CAAC;QACtF,CAAC;QAED,gDAAgD;QAChD,MAAM,oBAAoB,GAAG,2CAA2C,CAAC;QACzE,OAAO,CAAC,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC7D,mCAAmC;YACnC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnC,eAAe,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,UAAU,CAAC,OAAO,EAAE,CAAC,CAAC;YACpF,CAAC;QACH,CAAC;QAED,cAAc;QACd,4BAA4B;QAC5B,MAAM,gBAAgB,GAAG,qCAAqC,CAAC;QAC/D,OAAO,CAAC,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACzD,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,uBAAuB;QACvB,MAAM,iBAAiB,GAAG,yCAAyC,CAAC;QACpE,OAAO,CAAC,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1D,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,oBAAoB;QACpB,MAAM,kBAAkB,GAAG,yCAAyC,CAAC;QACrE,OAAO,CAAC,KAAK,GAAG,kBAAkB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC3D,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,wBAAwB;QACxB,MAAM,sBAAsB,GAAG,6BAA6B,CAAC;QAC7D,OAAO,CAAC,KAAK,GAAG,sBAAsB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC/D,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,mBAAmB;QACnB,MAAM,iBAAiB,GAAG,wBAAwB,CAAC;QACnD,OAAO,CAAC,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1D,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,mBAAmB;QACnB,MAAM,iBAAiB,GAAG,wBAAwB,CAAC;QACnD,OAAO,CAAC,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1D,YAAY,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7B,CAAC;QAED,gCAAgC;QAChC,MAAM,iBAAiB,GAAG,kCAAkC,CAAC;QAC7D,OAAO,CAAC,KAAK,GAAG,iBAAiB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YAC1D,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAC/E,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,MAAM,EAAE,CAAC;oBACX,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;gBAC3B,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,CAAC;IAC3C,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,uBAAuB,CAAC,OAAe,EAAE,SAAiB;QACtE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,IAAI,OAAO,GAAG,KAAK,CAAC;QACpB,IAAI,KAAK,GAAG,CAAC,CAAC;QAEd,iDAAiD;QACjD,MAAM,YAAY,GAAG,IAAI,MAAM,CAC7B,6CAA6C,SAAS,KAAK,CAC5D,CAAC;QAEF,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAEtB,mBAAmB;YACnB,IAAI,CAAC,OAAO,IAAI,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBACxC,OAAO,GAAG,IAAI,CAAC;YACjB,CAAC;YAED,IAAI,OAAO,EAAE,CAAC;gBACZ,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,CAAC;oBACxB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;wBAAA,KAAK,EAAE,CAAC;oBAAA,CAAC;yBACvB,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;wBACtB,KAAK,EAAE,CAAC;wBACR,IAAI,KAAK,KAAK,CAAC,EAAE,CAAC;4BAChB,kBAAkB;4BAClB,OAAO,CAAC,CAAC;wBACX,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,CAAC,CAAC,CAAC;IACZ,CAAC;IAED;;OAEG;IACK,qBAAqB,CAAC,IAAY,EAAE,EAAU;QACpD,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAE9C,QAAQ;QACR,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,oBAAoB,EAAE,EAAE,CAAC,CAAC;QAE9D,YAAY;QACZ,IAAI,CAAC,YAAY,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YAClC,YAAY,GAAG,IAAI,GAAG,YAAY,CAAC;QACrC,CAAC;QAED,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,QAAQ,CAAC,QAAgB;QACrC,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAClE,OAAO,OAAO,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC3E,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;CACF"}
@@ -4,7 +4,10 @@
4
4
  */
5
5
  export { MoveMemberService, createMoveMemberService } from './move-member-service.js';
6
6
  export { MemberExtractor, createMemberExtractor } from './member-extractor.js';
7
- export type { MemberDefinition, MoveTarget, MoveMemberOptions, ReferenceUpdate, MoveMemberResult, MoveMemberSuccessResult, MoveMemberErrorResult, MoveMemberValidationError, FileChange, TargetFileChange, MoveMemberStats } from './types.js';
7
+ export { ReferenceUpdater } from './reference-updater.js';
8
+ export { FileChangePreparer } from './file-change-preparer.js';
9
+ export { ChangeApplier } from './change-applier.js';
10
+ export type { MemberDefinition, MoveTarget, MoveMemberOptions, SourcePosition, ReferenceUpdate, MoveMemberResult, MoveMemberSuccessResult, MoveMemberErrorResult, MoveMemberValidationError, FileChange, TargetFileChange, MoveMemberStats } from './types.js';
8
11
  export { MemberType, MoveTargetType, MoveMemberErrorCode } from './types.js';
9
12
  export { isMemberDefinition, isMoveMemberResult } from './types.js';
10
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/move-member/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAG/E,YAAY,EACV,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,qBAAqB,EACrB,yBAAyB,EACzB,UAAU,EACV,gBAAgB,EAChB,eAAe,EAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,UAAU,EACV,cAAc,EACd,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/move-member/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAGpD,YAAY,EACV,gBAAgB,EAChB,UAAU,EACV,iBAAiB,EACjB,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,uBAAuB,EACvB,qBAAqB,EACrB,yBAAyB,EACzB,UAAU,EACV,gBAAgB,EAChB,eAAe,EAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,UAAU,EACV,cAAc,EACd,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,YAAY,CAAC"}
@@ -5,6 +5,9 @@
5
5
  // 核心服務
6
6
  export { MoveMemberService, createMoveMemberService } from './move-member-service.js';
7
7
  export { MemberExtractor, createMemberExtractor } from './member-extractor.js';
8
+ export { ReferenceUpdater } from './reference-updater.js';
9
+ export { FileChangePreparer } from './file-change-preparer.js';
10
+ export { ChangeApplier } from './change-applier.js';
8
11
  // 列舉
9
12
  export { MemberType, MoveTargetType, MoveMemberErrorCode } from './types.js';
10
13
  // Type Guards
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/move-member/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO;AACP,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAiB/E,KAAK;AACL,OAAO,EACL,UAAU,EACV,cAAc,EACd,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,cAAc;AACd,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/core/move-member/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO;AACP,OAAO,EAAE,iBAAiB,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AACtF,OAAO,EAAE,eAAe,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAC/E,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAkBpD,KAAK;AACL,OAAO,EACL,UAAU,EACV,cAAc,EACd,mBAAmB,EACpB,MAAM,YAAY,CAAC;AAEpB,cAAc;AACd,OAAO,EACL,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,YAAY,CAAC"}
@@ -16,6 +16,15 @@ export declare class MemberExtractor {
16
16
  * 提取指定成員
17
17
  */
18
18
  extractMember(filePath: string, memberName: string, memberType?: MemberType, className?: string): Promise<MemberDefinition | null>;
19
+ /**
20
+ * 提取指定位置的成員
21
+ * 找到包含該位置的最小成員定義
22
+ *
23
+ * @param filePath 檔案路徑
24
+ * @param line 行號(1-based)
25
+ * @param column 欄位(1-based,可選)
26
+ */
27
+ extractMemberAtPosition(filePath: string, line: number, column?: number): Promise<MemberDefinition | null>;
19
28
  /**
20
29
  * 列出檔案中的所有成員
21
30
  */
@@ -58,6 +67,8 @@ export declare class MemberExtractor {
58
67
  private findTypeAliasEnd;
59
68
  /**
60
69
  * 找到陳述句結尾
70
+ *
71
+ * 處理多行箭頭函式:追蹤括號深度,避免將參數預設值的 `=` 誤判為語句結束
61
72
  */
62
73
  private findStatementEnd;
63
74
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"member-extractor.d.ts","sourceRoot":"","sources":["../../../src/core/move-member/member-extractor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE/D;;GAEG;AACH,qBAAa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU;gBADV,cAAc,EAAE,cAAc,EAC9B,UAAU,EAAE,WAAW;IAG1C;;OAEG;IACG,aAAa,CACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,UAAU,EACvB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAoBnC;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAoBpF;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAiB/B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAiJ7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA+D3B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAW/B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAI7B;;OAEG;IACH,OAAO,CAAC,YAAY;IA8BpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAqBpB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAqB3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IASxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAcxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAaxB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA+B5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA2B3B;;OAEG;YACW,QAAQ;IAStB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAIzB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,cAAc,EAC9B,UAAU,EAAE,WAAW,GACtB,eAAe,CAEjB"}
1
+ {"version":3,"file":"member-extractor.d.ts","sourceRoot":"","sources":["../../../src/core/move-member/member-extractor.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oCAAoC,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,kDAAkD,CAAC;AACpF,OAAO,EAAE,UAAU,EAAE,KAAK,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE/D;;GAEG;AACH,qBAAa,eAAe;IAExB,OAAO,CAAC,QAAQ,CAAC,cAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,UAAU;gBADV,cAAc,EAAE,cAAc,EAC9B,UAAU,EAAE,WAAW;IAG1C;;OAEG;IACG,aAAa,CACjB,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,UAAU,CAAC,EAAE,UAAU,EACvB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAoBnC;;;;;;;OAOG;IACG,uBAAuB,CAC3B,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAkCnC;;OAEG;IACG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAoBpF;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAiB/B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAiJ7B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA0E3B;;OAEG;IACH,OAAO,CAAC,uBAAuB;IAW/B;;OAEG;IACH,OAAO,CAAC,qBAAqB;IAI7B;;OAEG;IACH,OAAO,CAAC,YAAY;IA8BpB;;OAEG;IACH,OAAO,CAAC,YAAY;IAqBpB;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAqB3B;;OAEG;IACH,OAAO,CAAC,gBAAgB;IASxB;;;;OAIG;IACH,OAAO,CAAC,gBAAgB;IA+BxB;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAaxB;;OAEG;IACH,OAAO,CAAC,oBAAoB;IA+B5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IA0D3B;;OAEG;YACW,QAAQ;IAStB;;OAEG;IACH,OAAO,CAAC,gBAAgB;CAIzB;AAED;;GAEG;AACH,wBAAgB,qBAAqB,CACnC,cAAc,EAAE,cAAc,EAC9B,UAAU,EAAE,WAAW,GACtB,eAAe,CAEjB"}
@@ -33,6 +33,42 @@ export class MemberExtractor {
33
33
  return null;
34
34
  }
35
35
  }
36
+ /**
37
+ * 提取指定位置的成員
38
+ * 找到包含該位置的最小成員定義
39
+ *
40
+ * @param filePath 檔案路徑
41
+ * @param line 行號(1-based)
42
+ * @param column 欄位(1-based,可選)
43
+ */
44
+ async extractMemberAtPosition(filePath, line, column) {
45
+ const members = await this.listMembers(filePath);
46
+ if (members.length === 0) {
47
+ return null;
48
+ }
49
+ // 找到包含該行的所有成員
50
+ const containingMembers = members.filter(m => {
51
+ const start = m.location.range.start.line;
52
+ const end = m.location.range.end.line;
53
+ return line >= start && line <= end;
54
+ });
55
+ if (containingMembers.length === 0) {
56
+ return null;
57
+ }
58
+ // 如果只有一個,直接返回
59
+ if (containingMembers.length === 1) {
60
+ return containingMembers[0];
61
+ }
62
+ // 多個成員時,選擇範圍最小的(最內層)
63
+ // 但優先選擇非類別的成員(避免選到整個類別而不是類別內的方法)
64
+ const nonClassMembers = containingMembers.filter(m => m.type !== MemberType.Class);
65
+ const candidates = nonClassMembers.length > 0 ? nonClassMembers : containingMembers;
66
+ return candidates.reduce((smallest, current) => {
67
+ const smallestSize = smallest.location.range.end.line - smallest.location.range.start.line;
68
+ const currentSize = current.location.range.end.line - current.location.range.start.line;
69
+ return currentSize < smallestSize ? current : smallest;
70
+ });
71
+ }
36
72
  /**
37
73
  * 列出檔案中的所有成員
38
74
  */
@@ -137,32 +173,41 @@ export class MemberExtractor {
137
173
  extractClassMembers(classSource, filePath, className, classStartLine) {
138
174
  const members = [];
139
175
  const lines = classSource.split('\n');
176
+ // 跳過類別宣告行,只提取類別內部的成員
177
+ const firstBraceIndex = classSource.indexOf('{');
178
+ if (firstBraceIndex === -1) {
179
+ return members;
180
+ }
181
+ const classBody = classSource.substring(firstBraceIndex + 1);
182
+ const bodyStartLine = classSource.substring(0, firstBraceIndex).split('\n').length;
183
+ // 類別內部的 lines(從 { 之後開始)
184
+ const bodyLines = classBody.split('\n');
140
185
  // 方法
141
186
  const methodPattern = /^\s*(public|private|protected)?\s*(static)?\s*(async)?\s*(\w+)\s*\([^)]*\)/gm;
142
187
  let match;
143
- while ((match = methodPattern.exec(classSource)) !== null) {
188
+ while ((match = methodPattern.exec(classBody)) !== null) {
144
189
  // 跳過 constructor
145
190
  if (match[4] === 'constructor') {
146
191
  continue;
147
192
  }
148
- const relativeLineNumber = classSource.substring(0, match.index).split('\n').length;
149
- const lineNumber = classStartLine + relativeLineNumber - 1;
150
- const endLine = this.findBlockEndInClass(lines, relativeLineNumber - 1);
151
- const sourceCode = lines.slice(relativeLineNumber - 1, endLine + 1).join('\n');
152
- members.push(this.createMember(match[4], MemberType.Method, filePath, lineNumber, classStartLine + endLine, sourceCode, className, this.extractModifiers(match[0]), this.extractDocumentation(lines, relativeLineNumber - 1), this.extractDependencies(sourceCode)));
193
+ const relativeLineNumber = classBody.substring(0, match.index).split('\n').length;
194
+ const lineNumber = classStartLine + bodyStartLine - 1 + relativeLineNumber - 1;
195
+ const endLine = this.findBlockEndInClass(bodyLines, relativeLineNumber - 1);
196
+ const sourceCode = bodyLines.slice(relativeLineNumber - 1, endLine + 1).join('\n');
197
+ members.push(this.createMember(match[4], MemberType.Method, filePath, lineNumber, classStartLine + bodyStartLine - 1 + endLine, sourceCode, className, this.extractModifiers(match[0]), this.extractDocumentation(bodyLines, relativeLineNumber - 1), this.extractDependencies(sourceCode)));
153
198
  }
154
199
  // 屬性
155
200
  const propertyPattern = /^\s*(public|private|protected)?\s*(static)?\s*(readonly)?\s*(\w+)\s*[?:]?\s*[^(]/gm;
156
- while ((match = propertyPattern.exec(classSource)) !== null) {
201
+ while ((match = propertyPattern.exec(classBody)) !== null) {
157
202
  // 跳過方法和 constructor
158
- if (classSource.substring(match.index).match(/^\s*\w+\s*\(/)) {
203
+ if (classBody.substring(match.index).match(/^\s*\w+\s*\(/)) {
159
204
  continue;
160
205
  }
161
- const relativeLineNumber = classSource.substring(0, match.index).split('\n').length;
162
- const lineNumber = classStartLine + relativeLineNumber - 1;
163
- const endLine = this.findStatementEnd(lines, relativeLineNumber - 1);
164
- const sourceCode = lines.slice(relativeLineNumber - 1, endLine + 1).join('\n');
165
- members.push(this.createMember(match[4], MemberType.Property, filePath, lineNumber, classStartLine + endLine, sourceCode, className, this.extractModifiers(match[0]), this.extractDocumentation(lines, relativeLineNumber - 1), this.extractDependencies(sourceCode)));
206
+ const relativeLineNumber = classBody.substring(0, match.index).split('\n').length;
207
+ const lineNumber = classStartLine + bodyStartLine - 1 + relativeLineNumber - 1;
208
+ const endLine = this.findStatementEnd(bodyLines, relativeLineNumber - 1);
209
+ const sourceCode = bodyLines.slice(relativeLineNumber - 1, endLine + 1).join('\n');
210
+ members.push(this.createMember(match[4], MemberType.Property, filePath, lineNumber, classStartLine + bodyStartLine - 1 + endLine, sourceCode, className, this.extractModifiers(match[0]), this.extractDocumentation(bodyLines, relativeLineNumber - 1), this.extractDependencies(sourceCode)));
166
211
  }
167
212
  return members;
168
213
  }
@@ -257,15 +302,34 @@ export class MemberExtractor {
257
302
  }
258
303
  /**
259
304
  * 找到陳述句結尾
305
+ *
306
+ * 處理多行箭頭函式:追蹤括號深度,避免將參數預設值的 `=` 誤判為語句結束
260
307
  */
261
308
  findStatementEnd(lines, startLine) {
309
+ let parenDepth = 0;
262
310
  for (let i = startLine; i < lines.length; i++) {
263
311
  const line = lines[i];
264
- if (line.includes(';') || (line.includes('=') && !line.includes('=>') && i > startLine)) {
265
- return i;
312
+ // 追蹤括號深度
313
+ for (const char of line) {
314
+ if (char === '(') {
315
+ parenDepth++;
316
+ }
317
+ else if (char === ')') {
318
+ parenDepth--;
319
+ }
266
320
  }
267
- // 檢查是否是多行箭頭函式或物件
268
- if (line.includes('{')) {
321
+ // 只有括號外的 `;` 或 `=` 才是語句結束
322
+ if (parenDepth === 0) {
323
+ if (line.includes(';')) {
324
+ return i;
325
+ }
326
+ // 非箭頭函式的賦值(且不是起始行)
327
+ if (line.includes('=') && !line.includes('=>') && i > startLine) {
328
+ return i;
329
+ }
330
+ }
331
+ // 檢查是否是多行箭頭函式或物件(括號必須已閉合)
332
+ if (parenDepth === 0 && line.includes('{')) {
269
333
  return this.findBlockEnd(lines, i);
270
334
  }
271
335
  }
@@ -340,13 +404,25 @@ export class MemberExtractor {
340
404
  */
341
405
  extractDependencies(sourceCode) {
342
406
  const dependencies = [];
407
+ const keywords = new Set([
408
+ 'if', 'else', 'while', 'for', 'switch', 'case', 'break', 'continue',
409
+ 'function', 'async', 'await', 'return', 'new', 'typeof', 'instanceof',
410
+ 'const', 'let', 'var', 'class', 'interface', 'type', 'enum', 'export',
411
+ 'import', 'from', 'default', 'true', 'false', 'null', 'undefined',
412
+ 'this', 'super', 'extends', 'implements', 'static', 'readonly', 'private',
413
+ 'public', 'protected', 'abstract', 'get', 'set', 'in', 'of', 'as', 'is'
414
+ ]);
415
+ const basicTypes = new Set([
416
+ 'string', 'number', 'boolean', 'void', 'any', 'unknown', 'never',
417
+ 'null', 'undefined', 'object', 'symbol', 'bigint', 'Array', 'Object',
418
+ 'String', 'Number', 'Boolean', 'Function', 'Promise', 'Map', 'Set'
419
+ ]);
420
+ let match;
343
421
  // 提取型別引用
344
422
  const typePattern = /:\s*(\w+)(?:<|;|\s|,|\))/g;
345
- let match;
346
423
  while ((match = typePattern.exec(sourceCode)) !== null) {
347
424
  const typeName = match[1];
348
- // 排除基本類型
349
- if (!['string', 'number', 'boolean', 'void', 'any', 'unknown', 'never', 'null', 'undefined'].includes(typeName)) {
425
+ if (!basicTypes.has(typeName) && !keywords.has(typeName)) {
350
426
  dependencies.push(typeName);
351
427
  }
352
428
  }
@@ -354,11 +430,27 @@ export class MemberExtractor {
354
430
  const callPattern = /(\w+)\s*\(/g;
355
431
  while ((match = callPattern.exec(sourceCode)) !== null) {
356
432
  const funcName = match[1];
357
- // 排除關鍵字
358
- if (!['if', 'while', 'for', 'switch', 'function', 'async', 'await', 'return', 'new', 'typeof', 'instanceof'].includes(funcName)) {
433
+ if (!keywords.has(funcName) && !basicTypes.has(funcName)) {
359
434
  dependencies.push(funcName);
360
435
  }
361
436
  }
437
+ // 提取變數/常數引用(賦值右側、運算子右側、比較右側)
438
+ // 匹配 = IDENTIFIER, > IDENTIFIER, < IDENTIFIER 等
439
+ const varRefPattern = /[=><+\-*/%&|!]\s*([A-Z][A-Z0-9_]*)\b/g;
440
+ while ((match = varRefPattern.exec(sourceCode)) !== null) {
441
+ const varName = match[1];
442
+ if (!keywords.has(varName) && !basicTypes.has(varName)) {
443
+ dependencies.push(varName);
444
+ }
445
+ }
446
+ // 提取作為比較對象的識別符
447
+ const comparisonPattern = /\b([A-Z][A-Z0-9_]*)\s*[=!<>]/g;
448
+ while ((match = comparisonPattern.exec(sourceCode)) !== null) {
449
+ const varName = match[1];
450
+ if (!keywords.has(varName) && !basicTypes.has(varName)) {
451
+ dependencies.push(varName);
452
+ }
453
+ }
362
454
  return [...new Set(dependencies)];
363
455
  }
364
456
  /**