@simplysm/sd-cli 12.11.8 → 12.11.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/pkg-builders/client/sd-cli-ng-routes.file-generator.d.ts +3 -2
- package/dist/pkg-builders/client/sd-cli-ng-routes.file-generator.js +12 -10
- package/dist/pkg-builders/client/sd-cli-ng-routes.file-generator.js.map +1 -1
- package/dist/pkg-builders/client/sd-client.build-runner.js +7 -5
- package/dist/pkg-builders/client/sd-client.build-runner.js.map +1 -1
- package/dist/pkg-builders/client/sd-ng.bundler.js +1 -1
- package/dist/pkg-builders/client/sd-ng.bundler.js.map +1 -1
- package/dist/pkg-builders/commons/build-runner.base.js +4 -5
- package/dist/pkg-builders/commons/build-runner.base.js.map +1 -1
- package/dist/pkg-builders/lib/sd-cli-db-context.file-generator.d.ts +3 -2
- package/dist/pkg-builders/lib/sd-cli-db-context.file-generator.js +10 -9
- package/dist/pkg-builders/lib/sd-cli-db-context.file-generator.js.map +1 -1
- package/dist/pkg-builders/lib/sd-cli-index.file-generator.d.ts +3 -2
- package/dist/pkg-builders/lib/sd-cli-index.file-generator.js +14 -9
- package/dist/pkg-builders/lib/sd-cli-index.file-generator.js.map +1 -1
- package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js +8 -4
- package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js.map +1 -1
- package/dist/pkg-builders/lib/sd-ts-lib.builder.js +19 -10
- package/dist/pkg-builders/lib/sd-ts-lib.builder.js.map +1 -1
- package/dist/pkg-builders/server/sd-server.build-runner.js +1 -1
- package/dist/pkg-builders/server/sd-server.bundler.js +1 -1
- package/dist/pkg-builders/server/sd-server.bundler.js.map +1 -1
- package/dist/ts-compiler/sd-dependency-cache.d.ts +56 -0
- package/dist/ts-compiler/sd-dependency-cache.js +183 -118
- package/dist/ts-compiler/sd-dependency-cache.js.map +1 -1
- package/package.json +5 -5
- package/src/pkg-builders/client/sd-cli-ng-routes.file-generator.ts +20 -15
- package/src/pkg-builders/client/sd-client.build-runner.ts +15 -10
- package/src/pkg-builders/client/sd-ng.bundler.ts +1 -1
- package/src/pkg-builders/commons/build-runner.base.ts +19 -16
- package/src/pkg-builders/lib/sd-cli-db-context.file-generator.ts +12 -9
- package/src/pkg-builders/lib/sd-cli-index.file-generator.ts +18 -10
- package/src/pkg-builders/lib/sd-ts-lib.build-runner.ts +7 -6
- package/src/pkg-builders/lib/sd-ts-lib.builder.ts +22 -12
- package/src/pkg-builders/server/sd-server.build-runner.ts +1 -1
- package/src/pkg-builders/server/sd-server.bundler.ts +11 -11
- package/src/ts-compiler/sd-dependency-cache.ts +208 -171
- package/tests/deps/sd-dependency-cache.spec.ts +12 -0
|
@@ -1,138 +1,184 @@
|
|
|
1
1
|
import { TNormPath } from "@simplysm/sd-core-node";
|
|
2
2
|
|
|
3
3
|
export class SdDependencyCache {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
/**
|
|
5
|
+
* 각 파일이 export한 심볼 집합 (예: export const A → "A")
|
|
6
|
+
*/
|
|
7
|
+
private _exportCache = new Map<TNormPath, Set<string>>();
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* import한 타겟과 그 심볼 정보
|
|
11
|
+
* - 값이 0이면 전체 import(import * 또는 리소스 import)
|
|
12
|
+
* - 값이 Set이면 선택적 심볼 import (예: import { A } ...)
|
|
13
|
+
*/
|
|
14
|
+
private _importCache = new Map<TNormPath, Map<TNormPath, Set<string> | 0>>();
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* re-export한 타겟과 그 심볼 정보
|
|
18
|
+
* - export * from ...
|
|
19
|
+
* - export { A as B } from ...
|
|
20
|
+
* - 값이 0이면 전체 reexport(export * from ...)
|
|
21
|
+
*/
|
|
22
|
+
private _reexportCache = new Map<
|
|
23
|
+
TNormPath,
|
|
11
24
|
Map<
|
|
12
|
-
|
|
13
|
-
|
|
25
|
+
TNormPath,
|
|
26
|
+
| {
|
|
27
|
+
importSymbol: string;
|
|
28
|
+
exportSymbol: string;
|
|
29
|
+
}[]
|
|
30
|
+
| 0
|
|
14
31
|
>
|
|
15
32
|
>();
|
|
16
33
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
/**
|
|
35
|
+
* 역의존 정보 (revDep)
|
|
36
|
+
* - 특정 파일이 어떤 파일에게 의존(참조)되는지
|
|
37
|
+
* - symbol 기반 추적
|
|
38
|
+
*/
|
|
39
|
+
private _revDepCache = new Map<TNormPath, Map<TNormPath, Set<string> | 0>>();
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* 분석이 완료된 파일 경로
|
|
43
|
+
*/
|
|
44
|
+
private _collectedCache = new Set<TNormPath>();
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* .d.ts 또는 .js가 입력되었을 때 쌍으로 존재하는 파일 경로를 반환
|
|
48
|
+
* 예: "/a.d.ts" → ["/a.d.ts", "/a.js"]
|
|
49
|
+
*/
|
|
50
|
+
#getRelatedNPaths(nPath: TNormPath): TNormPath[] {
|
|
51
|
+
if (nPath.endsWith(".d.ts")) {
|
|
52
|
+
return [nPath, nPath.replace(/\.d\.ts$/, ".js") as TNormPath];
|
|
53
|
+
}
|
|
54
|
+
if (nPath.endsWith(".js")) {
|
|
55
|
+
return [nPath, nPath.replace(/\.js$/, ".d.ts") as TNormPath];
|
|
56
|
+
}
|
|
57
|
+
return [nPath];
|
|
58
|
+
}
|
|
37
59
|
|
|
60
|
+
/**
|
|
61
|
+
* 전체 추적된 파일 경로를 반환
|
|
62
|
+
*/
|
|
38
63
|
getFiles(): Set<TNormPath> {
|
|
39
|
-
return new Set<TNormPath>([
|
|
40
|
-
...this.#collectedCache.keys(),
|
|
41
|
-
...this.#revDepCache.keys(),
|
|
42
|
-
]);
|
|
64
|
+
return new Set<TNormPath>([...this._collectedCache.keys(), ...this._revDepCache.keys()]);
|
|
43
65
|
}
|
|
44
66
|
|
|
67
|
+
/**
|
|
68
|
+
* 분석이 완료된 파일로 표시
|
|
69
|
+
*/
|
|
45
70
|
addCollected(fileNPath: TNormPath) {
|
|
46
|
-
this.#
|
|
71
|
+
for (const path of this.#getRelatedNPaths(fileNPath)) {
|
|
72
|
+
this._collectedCache.add(path);
|
|
73
|
+
}
|
|
47
74
|
}
|
|
48
75
|
|
|
49
76
|
hasCollected(fileNPath: TNormPath) {
|
|
50
|
-
return this
|
|
77
|
+
return this._collectedCache.has(fileNPath);
|
|
51
78
|
}
|
|
52
79
|
|
|
53
|
-
|
|
54
|
-
|
|
80
|
+
/**
|
|
81
|
+
* export한 심볼 등록
|
|
82
|
+
* 예: export const A → "A"
|
|
83
|
+
*/
|
|
55
84
|
addExport(fileNPath: TNormPath, exportSymbol: string) {
|
|
56
|
-
const
|
|
57
|
-
|
|
85
|
+
for (const path of this.#getRelatedNPaths(fileNPath)) {
|
|
86
|
+
const exportSymbolSet = this._exportCache.getOrCreate(path, new Set());
|
|
87
|
+
exportSymbolSet.add(exportSymbol);
|
|
88
|
+
}
|
|
58
89
|
}
|
|
59
90
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
91
|
+
/**
|
|
92
|
+
* import 구문 등록
|
|
93
|
+
* - import * from ... → symbol = 0
|
|
94
|
+
* - import { A } from ... → symbol = "A"
|
|
95
|
+
*/
|
|
64
96
|
addImport(fileNPath: TNormPath, targetNPath: TNormPath, targetSymbol: string | 0) {
|
|
65
|
-
const
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
97
|
+
for (const filePath of this.#getRelatedNPaths(fileNPath)) {
|
|
98
|
+
for (const targetPath of this.#getRelatedNPaths(targetNPath)) {
|
|
99
|
+
const importTargetMap = this._importCache.getOrCreate(filePath, new Map());
|
|
100
|
+
|
|
101
|
+
if (targetSymbol === 0) {
|
|
102
|
+
importTargetMap.set(targetPath, 0);
|
|
103
|
+
this.#addRevDep(targetPath, filePath, 0);
|
|
104
|
+
} else {
|
|
105
|
+
const importTargetSymbolSet = importTargetMap.getOrCreate(targetPath, new Set());
|
|
106
|
+
if (importTargetSymbolSet === 0) return;
|
|
107
|
+
|
|
108
|
+
importTargetSymbolSet.add(targetSymbol);
|
|
109
|
+
this.#addRevDep(targetPath, filePath, targetSymbol);
|
|
110
|
+
}
|
|
74
111
|
}
|
|
75
|
-
|
|
76
|
-
importTargetSymbolSet.add(targetSymbol);
|
|
77
|
-
this.#addRevDep(targetNPath, fileNPath, targetSymbol);
|
|
78
112
|
}
|
|
79
113
|
}
|
|
80
114
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
// 차후 계산시 모든 캐시가 사용되므로,
|
|
86
|
-
// 이 클래스를 사용하는 곳에서는 따로따로 입력하면됨
|
|
115
|
+
/**
|
|
116
|
+
* export * or export { A as B } from ... 구문 등록
|
|
117
|
+
* ※ export/import에 자동 등록되지 않으므로 외부에서 명시적으로 따로 입력해야 함
|
|
118
|
+
*/
|
|
87
119
|
addReexport(
|
|
88
120
|
fileNPath: TNormPath,
|
|
89
121
|
targetNPath: TNormPath,
|
|
90
|
-
targetSymbolInfo:
|
|
122
|
+
targetSymbolInfo:
|
|
123
|
+
| {
|
|
124
|
+
importSymbol: string;
|
|
125
|
+
exportSymbol: string;
|
|
126
|
+
}
|
|
127
|
+
| 0,
|
|
91
128
|
) {
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
129
|
+
for (const filePath of this.#getRelatedNPaths(fileNPath)) {
|
|
130
|
+
for (const targetPath of this.#getRelatedNPaths(targetNPath)) {
|
|
131
|
+
const reexportTargetMap = this._reexportCache.getOrCreate(filePath, new Map());
|
|
132
|
+
|
|
133
|
+
if (targetSymbolInfo === 0) {
|
|
134
|
+
reexportTargetMap.set(targetPath, 0);
|
|
135
|
+
this.#addRevDep(targetPath, filePath, 0);
|
|
136
|
+
} else {
|
|
137
|
+
const reexportTargetSymbolInfos = reexportTargetMap.getOrCreate(targetPath, []);
|
|
138
|
+
if (reexportTargetSymbolInfos === 0) return;
|
|
139
|
+
|
|
140
|
+
if (
|
|
141
|
+
!reexportTargetSymbolInfos.some(
|
|
142
|
+
(item) =>
|
|
143
|
+
item.importSymbol === targetSymbolInfo.importSymbol &&
|
|
144
|
+
item.exportSymbol === targetSymbolInfo.exportSymbol,
|
|
145
|
+
)
|
|
146
|
+
) {
|
|
147
|
+
reexportTargetSymbolInfos.push(targetSymbolInfo);
|
|
148
|
+
this.#addRevDep(targetPath, filePath, targetSymbolInfo.importSymbol);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
111
151
|
}
|
|
112
152
|
}
|
|
113
153
|
}
|
|
114
154
|
|
|
155
|
+
/**
|
|
156
|
+
* 역의존 관계 등록 (revDep)
|
|
157
|
+
*/
|
|
115
158
|
#addRevDep(targetNPath: TNormPath, fileNPath: TNormPath, exportSymbol: string | 0) {
|
|
116
|
-
const
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
159
|
+
for (const targetPath of this.#getRelatedNPaths(targetNPath)) {
|
|
160
|
+
for (const filePath of this.#getRelatedNPaths(fileNPath)) {
|
|
161
|
+
const revDepInfoMap = this._revDepCache.getOrCreate(targetPath, new Map());
|
|
162
|
+
if (exportSymbol === 0) {
|
|
163
|
+
revDepInfoMap.set(filePath, 0);
|
|
164
|
+
} else {
|
|
165
|
+
const exportSymbolSet = revDepInfoMap.getOrCreate(filePath, new Set());
|
|
166
|
+
if (exportSymbolSet === 0) return;
|
|
167
|
+
|
|
168
|
+
exportSymbolSet.add(exportSymbol);
|
|
169
|
+
}
|
|
124
170
|
}
|
|
125
|
-
|
|
126
|
-
exportSymbolSet.add(exportSymbol);
|
|
127
171
|
}
|
|
128
172
|
}
|
|
129
173
|
|
|
174
|
+
/**
|
|
175
|
+
* 변경된 파일 경로 집합으로부터 영향을 받는 전체 파일 집합을 계산
|
|
176
|
+
*/
|
|
130
177
|
getAffectedFileSet(modifiedNPathSet: Set<TNormPath>): Set<TNormPath> {
|
|
131
178
|
const visited = new Set<string>();
|
|
179
|
+
const result = new Set<TNormPath>();
|
|
132
180
|
|
|
133
|
-
const
|
|
134
|
-
|
|
135
|
-
const queue: { fileNPath: TNormPath, exportSymbol: string | undefined }[] = [];
|
|
181
|
+
const queue: { fileNPath: TNormPath; exportSymbol: string | undefined }[] = [];
|
|
136
182
|
|
|
137
183
|
const enqueue = (fileNPath: TNormPath, exportSymbol: string | undefined) => {
|
|
138
184
|
const key = `${fileNPath}#${exportSymbol}`;
|
|
@@ -143,45 +189,37 @@ export class SdDependencyCache {
|
|
|
143
189
|
};
|
|
144
190
|
|
|
145
191
|
for (const modifiedNPath of modifiedNPathSet) {
|
|
146
|
-
const
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
192
|
+
for (const path of this.#getRelatedNPaths(modifiedNPath)) {
|
|
193
|
+
result.add(path);
|
|
194
|
+
const exportSymbols = this.#getExportSymbols(path);
|
|
195
|
+
if (exportSymbols.size === 0) {
|
|
196
|
+
enqueue(path, undefined);
|
|
197
|
+
} else {
|
|
198
|
+
for (const symbol of exportSymbols) {
|
|
199
|
+
enqueue(path, symbol);
|
|
200
|
+
}
|
|
153
201
|
}
|
|
154
202
|
}
|
|
155
203
|
}
|
|
156
204
|
|
|
157
205
|
while (queue.length > 0) {
|
|
158
206
|
const curr = queue.shift()!;
|
|
159
|
-
|
|
160
|
-
/*const key = curr.fileNPath + "#" + curr.exportSymbol;
|
|
161
|
-
if (visited.has(key)) continue;
|
|
162
|
-
visited.add(key);*/
|
|
163
|
-
|
|
164
|
-
const revDepInfoMap = this.#revDepCache.get(curr.fileNPath);
|
|
207
|
+
const revDepInfoMap = this._revDepCache.get(curr.fileNPath);
|
|
165
208
|
if (!revDepInfoMap) continue;
|
|
166
209
|
|
|
167
210
|
for (const [revDepFileNPath, revDepInfo] of revDepInfoMap) {
|
|
168
211
|
if (curr.exportSymbol != null) {
|
|
169
|
-
// curr의 export를 토대로 revDep이 사용하고 있는지 체크
|
|
170
|
-
// curr.exportSymbol 와 revDev의 importSymbol은 같다
|
|
171
212
|
const hasImportSymbol = revDepInfo === 0 || revDepInfo.has(curr.exportSymbol);
|
|
172
213
|
if (hasImportSymbol) {
|
|
173
214
|
result.add(revDepFileNPath);
|
|
174
|
-
|
|
175
|
-
// 하위 Deps를 queue에 넣기전 export명칭 변환 (이름을 변경한 reexport일 경우 필요)
|
|
176
215
|
const exportSymbol = this.#convertImportSymbolToExportSymbol(
|
|
177
216
|
revDepFileNPath,
|
|
178
217
|
curr.fileNPath,
|
|
179
|
-
curr.exportSymbol,
|
|
218
|
+
curr.exportSymbol,
|
|
180
219
|
);
|
|
181
220
|
enqueue(revDepFileNPath, exportSymbol);
|
|
182
221
|
}
|
|
183
|
-
}
|
|
184
|
-
else { // Resource
|
|
222
|
+
} else {
|
|
185
223
|
result.add(revDepFileNPath);
|
|
186
224
|
}
|
|
187
225
|
}
|
|
@@ -190,61 +228,64 @@ export class SdDependencyCache {
|
|
|
190
228
|
return result;
|
|
191
229
|
}
|
|
192
230
|
|
|
231
|
+
/**
|
|
232
|
+
* 주어진 파일들 및 그 영향 범위에 해당하는 모든 캐시를 무효화
|
|
233
|
+
*/
|
|
193
234
|
invalidates(fileNPathSet: Set<TNormPath>) {
|
|
194
235
|
const affectedFiles = this.getAffectedFileSet(fileNPathSet);
|
|
195
236
|
|
|
196
237
|
for (const fileNPath of affectedFiles) {
|
|
197
|
-
this
|
|
198
|
-
this
|
|
199
|
-
this
|
|
200
|
-
this
|
|
201
|
-
this
|
|
238
|
+
this._exportCache.delete(fileNPath);
|
|
239
|
+
this._importCache.delete(fileNPath);
|
|
240
|
+
this._reexportCache.delete(fileNPath);
|
|
241
|
+
this._collectedCache.delete(fileNPath);
|
|
242
|
+
this._revDepCache.delete(fileNPath); // 자신이 key인 경우
|
|
202
243
|
}
|
|
203
244
|
|
|
204
|
-
|
|
205
|
-
for (const [targetNPath, infoMap] of this.#revDepCache) {
|
|
245
|
+
for (const [targetNPath, infoMap] of this._revDepCache) {
|
|
206
246
|
for (const fileNPath of affectedFiles) {
|
|
207
247
|
infoMap.delete(fileNPath);
|
|
208
248
|
}
|
|
209
|
-
|
|
210
249
|
if (infoMap.size === 0) {
|
|
211
|
-
this
|
|
250
|
+
this._revDepCache.delete(targetNPath);
|
|
212
251
|
}
|
|
213
252
|
}
|
|
214
253
|
}
|
|
215
254
|
|
|
255
|
+
/**
|
|
256
|
+
* reexport된 경우 importSymbol → exportSymbol로 변환
|
|
257
|
+
*/
|
|
216
258
|
#convertImportSymbolToExportSymbol(
|
|
217
259
|
fileNPath: TNormPath,
|
|
218
260
|
targetNPath: TNormPath,
|
|
219
261
|
importSymbol: string,
|
|
220
262
|
) {
|
|
221
|
-
const symbolInfos = this
|
|
263
|
+
const symbolInfos = this._reexportCache.get(fileNPath)?.get(targetNPath);
|
|
222
264
|
if (symbolInfos != null && symbolInfos !== 0 && symbolInfos.length > 0) {
|
|
223
|
-
const symbolInfo = symbolInfos.single(item => item.importSymbol === importSymbol);
|
|
224
|
-
if (symbolInfo)
|
|
225
|
-
return symbolInfo.exportSymbol;
|
|
226
|
-
}
|
|
265
|
+
const symbolInfo = symbolInfos.single((item) => item.importSymbol === importSymbol);
|
|
266
|
+
if (symbolInfo) return symbolInfo.exportSymbol;
|
|
227
267
|
}
|
|
228
|
-
|
|
229
268
|
return importSymbol;
|
|
230
269
|
}
|
|
231
270
|
|
|
271
|
+
/**
|
|
272
|
+
* 해당 파일에서 export된 모든 심볼 (직접 + 재export 포함)
|
|
273
|
+
*/
|
|
232
274
|
#getExportSymbols(fileNPath: TNormPath): Set<string> {
|
|
233
275
|
const result = new Set<string>();
|
|
234
276
|
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
result.adds(...set);
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
result.adds(...val.map(item => item.exportSymbol));
|
|
277
|
+
for (const path of this.#getRelatedNPaths(fileNPath)) {
|
|
278
|
+
const set = this._exportCache.get(path);
|
|
279
|
+
if (set) result.adds(...set);
|
|
280
|
+
|
|
281
|
+
const map = this._reexportCache.get(path);
|
|
282
|
+
if (map) {
|
|
283
|
+
for (const [key, val] of map) {
|
|
284
|
+
if (val === 0) {
|
|
285
|
+
result.adds(...this.#getExportSymbols(key));
|
|
286
|
+
} else {
|
|
287
|
+
result.adds(...val.map(item => item.exportSymbol));
|
|
288
|
+
}
|
|
248
289
|
}
|
|
249
290
|
}
|
|
250
291
|
}
|
|
@@ -252,32 +293,30 @@ export class SdDependencyCache {
|
|
|
252
293
|
return result;
|
|
253
294
|
}
|
|
254
295
|
|
|
255
|
-
|
|
256
|
-
|
|
296
|
+
/**
|
|
297
|
+
* 변경된 파일로부터 영향을 받는 전체 트리를 반환
|
|
298
|
+
* - 의존 관계를 시각화 및 구조적으로 추적할 수 있도록 트리 형태로 구성
|
|
299
|
+
*/
|
|
257
300
|
getAffectedFileTree(modifiedNPathSet: Set<TNormPath>): ISdAffectedFileTreeNode[] {
|
|
258
|
-
const visited = new Set<string>();
|
|
259
|
-
const nodeMap = new Map<string, ISdAffectedFileTreeNode>();
|
|
301
|
+
const visited = new Set<string>();
|
|
302
|
+
const nodeMap = new Map<string, ISdAffectedFileTreeNode>();
|
|
260
303
|
|
|
261
304
|
const buildTree = (
|
|
262
305
|
fileNPath: TNormPath,
|
|
263
|
-
exportSymbol: string | undefined
|
|
306
|
+
exportSymbol: string | undefined,
|
|
264
307
|
): ISdAffectedFileTreeNode => {
|
|
265
308
|
const key = `${fileNPath}#${exportSymbol ?? "*"}`;
|
|
266
|
-
|
|
267
|
-
// 동일 노드가 이미 만들어졌다면 재사용
|
|
268
309
|
if (nodeMap.has(key)) return nodeMap.get(key)!;
|
|
269
310
|
|
|
270
|
-
// 방문 기록
|
|
271
311
|
visited.add(key);
|
|
272
312
|
|
|
273
|
-
// 노드 생성 및 캐싱
|
|
274
313
|
const node: ISdAffectedFileTreeNode = {
|
|
275
314
|
fileNPath,
|
|
276
|
-
children: []
|
|
315
|
+
children: [],
|
|
277
316
|
};
|
|
278
317
|
nodeMap.set(key, node);
|
|
279
318
|
|
|
280
|
-
const revDepInfoMap = this
|
|
319
|
+
const revDepInfoMap = this._revDepCache.get(fileNPath);
|
|
281
320
|
if (!revDepInfoMap) return node;
|
|
282
321
|
|
|
283
322
|
for (const [revDepFileNPath, revDepInfo] of revDepInfoMap.entries()) {
|
|
@@ -285,16 +324,13 @@ export class SdDependencyCache {
|
|
|
285
324
|
exportSymbol == null || revDepInfo === 0 || revDepInfo.has(exportSymbol);
|
|
286
325
|
if (!hasImportSymbol) continue;
|
|
287
326
|
|
|
288
|
-
const nextExportSymbol =
|
|
289
|
-
|
|
290
|
-
revDepFileNPath,
|
|
291
|
-
|
|
292
|
-
exportSymbol
|
|
293
|
-
)
|
|
294
|
-
: undefined;
|
|
327
|
+
const nextExportSymbol =
|
|
328
|
+
exportSymbol != null
|
|
329
|
+
? this.#convertImportSymbolToExportSymbol(revDepFileNPath, fileNPath, exportSymbol)
|
|
330
|
+
: undefined;
|
|
295
331
|
|
|
296
332
|
const childKey = `${revDepFileNPath}#${nextExportSymbol ?? "*"}`;
|
|
297
|
-
if (visited.has(childKey)) continue;
|
|
333
|
+
if (visited.has(childKey)) continue;
|
|
298
334
|
|
|
299
335
|
const childNode = buildTree(revDepFileNPath, nextExportSymbol);
|
|
300
336
|
node.children.push(childNode);
|
|
@@ -306,15 +342,16 @@ export class SdDependencyCache {
|
|
|
306
342
|
const result: ISdAffectedFileTreeNode[] = [];
|
|
307
343
|
|
|
308
344
|
for (const modifiedNPath of modifiedNPathSet) {
|
|
309
|
-
const
|
|
310
|
-
|
|
311
|
-
const
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
const
|
|
316
|
-
|
|
317
|
-
|
|
345
|
+
for (const path of this.#getRelatedNPaths(modifiedNPath)) {
|
|
346
|
+
result.push(buildTree(path, undefined)); // root는 symbol상관없이
|
|
347
|
+
/*const exportSymbols = this.#getExportSymbols(path);
|
|
348
|
+
if (exportSymbols.size === 0) {
|
|
349
|
+
result.push(buildTree(path, undefined));
|
|
350
|
+
} else {
|
|
351
|
+
for (const symbol of exportSymbols) {
|
|
352
|
+
result.push(buildTree(path, symbol));
|
|
353
|
+
}
|
|
354
|
+
}*/
|
|
318
355
|
}
|
|
319
356
|
}
|
|
320
357
|
|
|
@@ -325,4 +362,4 @@ export class SdDependencyCache {
|
|
|
325
362
|
export interface ISdAffectedFileTreeNode {
|
|
326
363
|
fileNPath: TNormPath;
|
|
327
364
|
children: ISdAffectedFileTreeNode[];
|
|
328
|
-
}
|
|
365
|
+
}
|
|
@@ -141,4 +141,16 @@ describe("SdDependencyCache", () => {
|
|
|
141
141
|
|
|
142
142
|
console.log(printTree(trees[0]));
|
|
143
143
|
});
|
|
144
|
+
|
|
145
|
+
it("d.ts를 입력하면 js도 함께 영향을 받는다", () => {
|
|
146
|
+
const dts = PathUtils.norm("/mod.d.ts");
|
|
147
|
+
const js = PathUtils.norm("/mod.js");
|
|
148
|
+
const consumer = PathUtils.norm("/consumer.ts");
|
|
149
|
+
|
|
150
|
+
depCache.addExport(dts, "Foo");
|
|
151
|
+
depCache.addImport(consumer, js, "Foo"); // js 경로로 import
|
|
152
|
+
|
|
153
|
+
const result = depCache.getAffectedFileSet(new Set([dts]));
|
|
154
|
+
expect(result).toEqual(new Set([dts, js, consumer]));
|
|
155
|
+
});
|
|
144
156
|
});
|