@simplysm/sd-cli 12.13.13 → 12.13.15

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 (87) hide show
  1. package/dist/entry/sd-cli-electron.js +1 -1
  2. package/dist/entry/sd-cli-electron.js.map +1 -1
  3. package/dist/entry/sd-cli-project.d.ts +2 -0
  4. package/dist/entry/sd-cli-project.js +11 -3
  5. package/dist/entry/sd-cli-project.js.map +1 -1
  6. package/dist/pkg-builders/client/sd-client.build-runner.d.ts +1 -1
  7. package/dist/pkg-builders/client/sd-client.build-runner.js +74 -50
  8. package/dist/pkg-builders/client/sd-client.build-runner.js.map +1 -1
  9. package/dist/pkg-builders/client/sd-ng.bundler.d.ts +2 -0
  10. package/dist/pkg-builders/client/sd-ng.bundler.js +19 -20
  11. package/dist/pkg-builders/client/sd-ng.bundler.js.map +1 -1
  12. package/dist/pkg-builders/client/sd-ng.plugin-creator.d.ts +2 -0
  13. package/dist/pkg-builders/client/sd-ng.plugin-creator.js +94 -33
  14. package/dist/pkg-builders/client/sd-ng.plugin-creator.js.map +1 -1
  15. package/dist/pkg-builders/commons/build-runner.base.d.ts +4 -2
  16. package/dist/pkg-builders/commons/build-runner.base.js +45 -25
  17. package/dist/pkg-builders/commons/build-runner.base.js.map +1 -1
  18. package/dist/pkg-builders/lib/sd-js-lib.build-runner.d.ts +1 -1
  19. package/dist/pkg-builders/lib/sd-js-lib.build-runner.js +14 -4
  20. package/dist/pkg-builders/lib/sd-js-lib.build-runner.js.map +1 -1
  21. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.d.ts +1 -1
  22. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js +21 -40
  23. package/dist/pkg-builders/lib/sd-ts-lib.build-runner.js.map +1 -1
  24. package/dist/pkg-builders/lib/sd-ts-lib.builder.d.ts +1 -1
  25. package/dist/pkg-builders/lib/sd-ts-lib.builder.js +3 -1
  26. package/dist/pkg-builders/lib/sd-ts-lib.builder.js.map +1 -1
  27. package/dist/pkg-builders/sd-multi.build-runner.js +116 -86
  28. package/dist/pkg-builders/sd-multi.build-runner.js.map +1 -1
  29. package/dist/pkg-builders/server/sd-server.build-runner.d.ts +1 -1
  30. package/dist/pkg-builders/server/sd-server.build-runner.js +9 -5
  31. package/dist/pkg-builders/server/sd-server.build-runner.js.map +1 -1
  32. package/dist/pkg-builders/server/sd-server.bundler.d.ts +2 -0
  33. package/dist/pkg-builders/server/sd-server.bundler.js +3 -1
  34. package/dist/pkg-builders/server/sd-server.bundler.js.map +1 -1
  35. package/dist/pkg-builders/server/sd-server.plugin-creator.d.ts +2 -0
  36. package/dist/pkg-builders/server/sd-server.plugin-creator.js +4 -1
  37. package/dist/pkg-builders/server/sd-server.plugin-creator.js.map +1 -1
  38. package/dist/sd-cli-entry.js +10 -0
  39. package/dist/sd-cli-entry.js.map +1 -1
  40. package/dist/sd-cli.js +8 -6
  41. package/dist/sd-cli.js.map +1 -1
  42. package/dist/ts-compiler/sd-dependency-analyzer.d.ts +8 -1
  43. package/dist/ts-compiler/sd-dependency-analyzer.js +128 -63
  44. package/dist/ts-compiler/sd-dependency-analyzer.js.map +1 -1
  45. package/dist/ts-compiler/sd-dependency-cache.d.ts +0 -34
  46. package/dist/ts-compiler/sd-dependency-cache.js +73 -119
  47. package/dist/ts-compiler/sd-dependency-cache.js.map +1 -1
  48. package/dist/ts-compiler/sd-style-bundler.d.ts +16 -0
  49. package/dist/ts-compiler/sd-style-bundler.js +118 -0
  50. package/dist/ts-compiler/sd-style-bundler.js.map +1 -0
  51. package/dist/ts-compiler/sd-ts-compiler.js +418 -235
  52. package/dist/ts-compiler/sd-ts-compiler.js.map +1 -1
  53. package/dist/types/build-runner.types.d.ts +2 -0
  54. package/dist/types/config.types.d.ts +2 -0
  55. package/dist/types/ts-compiler.types.d.ts +2 -0
  56. package/dist/types/worker.types.d.ts +1 -1
  57. package/dist/workers/build-runner.worker.js +1 -1
  58. package/dist/workers/build-runner.worker.js.map +1 -1
  59. package/dist/workers/server.worker.js +2 -2
  60. package/dist/workers/server.worker.js.map +1 -1
  61. package/package.json +13 -12
  62. package/src/entry/sd-cli-electron.ts +2 -1
  63. package/src/entry/sd-cli-project.ts +13 -3
  64. package/src/pkg-builders/client/sd-client.build-runner.ts +93 -54
  65. package/src/pkg-builders/client/sd-ng.bundler.ts +79 -85
  66. package/src/pkg-builders/client/sd-ng.plugin-creator.ts +119 -39
  67. package/src/pkg-builders/commons/build-runner.base.ts +78 -33
  68. package/src/pkg-builders/lib/sd-js-lib.build-runner.ts +24 -7
  69. package/src/pkg-builders/lib/sd-ts-lib.build-runner.ts +36 -42
  70. package/src/pkg-builders/lib/sd-ts-lib.builder.ts +4 -0
  71. package/src/pkg-builders/sd-multi.build-runner.ts +137 -108
  72. package/src/pkg-builders/server/sd-server.build-runner.ts +10 -4
  73. package/src/pkg-builders/server/sd-server.bundler.ts +5 -1
  74. package/src/pkg-builders/server/sd-server.plugin-creator.ts +10 -5
  75. package/src/sd-cli-entry.ts +10 -0
  76. package/src/sd-cli.ts +8 -6
  77. package/src/ts-compiler/sd-dependency-analyzer.ts +161 -86
  78. package/src/ts-compiler/sd-dependency-cache.ts +118 -99
  79. package/src/ts-compiler/sd-style-bundler.ts +150 -0
  80. package/src/ts-compiler/sd-ts-compiler.ts +559 -296
  81. package/src/types/build-runner.types.ts +2 -0
  82. package/src/types/config.types.ts +3 -0
  83. package/src/types/ts-compiler.types.ts +15 -11
  84. package/src/types/worker.types.ts +7 -10
  85. package/src/workers/build-runner.worker.ts +9 -5
  86. package/src/workers/server.worker.ts +2 -2
  87. package/tests/deps/sd-dependency-cache.spec.ts +1 -1
@@ -13,16 +13,20 @@ export class SdServerBuildRunner extends BuildRunnerBase<"server"> {
13
13
 
14
14
  protected override async _runAsync(
15
15
  dev: boolean,
16
+ emitOnly: boolean,
17
+ noEmit: boolean,
16
18
  modifiedFileSet?: Set<TNormPath>,
17
19
  ): Promise<IBuildRunnerRunResult> {
18
20
  if (!dev) {
19
21
  await this.#generateProductionFilesAsync();
20
22
  }
21
23
 
22
- if (!modifiedFileSet) {
23
- this._debug("GEN .config...");
24
- const confDistPath = path.resolve(this._pkgPath, "dist/.config.json");
25
- FsUtils.writeFile(confDistPath, JSON.stringify(this._pkgConf.configs ?? {}, undefined, 2));
24
+ if (!noEmit) {
25
+ if (!modifiedFileSet) {
26
+ this._debug("GEN .config...");
27
+ const confDistPath = path.resolve(this._pkgPath, "dist/.config.json");
28
+ FsUtils.writeFile(confDistPath, JSON.stringify(this._pkgConf.configs ?? {}, undefined, 2));
29
+ }
26
30
  }
27
31
 
28
32
  /*const localUpdatePaths = Object.keys(this._projConf.localUpdates ?? {}).mapMany((key) =>
@@ -36,6 +40,8 @@ export class SdServerBuildRunner extends BuildRunnerBase<"server"> {
36
40
  this.#serverBundler ??
37
41
  new SdServerBundler({
38
42
  dev,
43
+ emitOnly,
44
+ noEmit,
39
45
  pkgPath: this._pkgPath,
40
46
  entryPoints: tsConfig.files
41
47
  ? tsConfig.files.map((item) => path.resolve(this._pkgPath, item))
@@ -26,6 +26,8 @@ export class SdServerBundler {
26
26
  constructor(
27
27
  private readonly _opt: {
28
28
  dev: boolean;
29
+ emitOnly: boolean;
30
+ noEmit: boolean;
29
31
  pkgPath: TNormPath;
30
32
  entryPoints: string[];
31
33
  external?: string[];
@@ -108,6 +110,8 @@ const __dirname = __path__.dirname(__filename);`.trim(),
108
110
  createSdServerPlugin({
109
111
  modifiedFileSet: this.#modifiedFileSet,
110
112
  dev: this._opt.dev,
113
+ emitOnly: this._opt.emitOnly,
114
+ noEmit: this._opt.noEmit,
111
115
  pkgPath: this._opt.pkgPath,
112
116
  result: this.#resultCache,
113
117
  watchScopePathSet: this._opt.watchScopePathSet,
@@ -153,7 +157,7 @@ const __dirname = __path__.dirname(__filename);`.trim(),
153
157
  path.resolve(this._opt.pkgPath, "dist", assetFile.destination),
154
158
  );
155
159
  this.#outputHashCache.set(PathUtils.norm(assetFile.source), currHash);
156
- emitFileSet.add(PathUtils.norm(assetFile.destination));
160
+ emitFileSet.add(PathUtils.norm(this._opt.pkgPath, "dist", assetFile.destination));
157
161
  }
158
162
  }
159
163
  } catch (err) {
@@ -9,6 +9,8 @@ import { ScopePathSet } from "../commons/scope-path";
9
9
  export function createSdServerPlugin(conf: {
10
10
  pkgPath: TNormPath;
11
11
  dev: boolean;
12
+ emitOnly: boolean;
13
+ noEmit: boolean;
12
14
  modifiedFileSet: Set<TNormPath>;
13
15
  result: ISdCliServerPluginResultCache;
14
16
  watchScopePathSet: ScopePathSet;
@@ -20,6 +22,8 @@ export function createSdServerPlugin(conf: {
20
22
  pkgPath: conf.pkgPath,
21
23
  additionalOptions: { declaration: false },
22
24
  isDevMode: conf.dev,
25
+ isNoEmit: conf.noEmit,
26
+ isEmitOnly: conf.emitOnly,
23
27
  isForBundle: true,
24
28
  watchScopePathSet: conf.watchScopePathSet,
25
29
  });
@@ -40,7 +44,8 @@ export function createSdServerPlugin(conf: {
40
44
  });
41
45
 
42
46
  build.onLoad({ filter: /\.ts$/ }, (args) => {
43
- const emittedJsFile = tsCompileResult.emittedFilesCacheMap.get(PathUtils.norm(args.path))
47
+ const emittedJsFile = tsCompileResult.emittedFilesCacheMap
48
+ .get(PathUtils.norm(args.path))
44
49
  ?.last();
45
50
  if (!emittedJsFile) {
46
51
  return {
@@ -65,10 +70,10 @@ export function createSdServerPlugin(conf: {
65
70
  {
66
71
  filter: new RegExp(
67
72
  "(" +
68
- Object.keys(build.initialOptions.loader!)
69
- .map((item) => "\\" + item)
70
- .join("|") +
71
- ")$",
73
+ Object.keys(build.initialOptions.loader!)
74
+ .map((item) => "\\" + item)
75
+ .join("|") +
76
+ ")$",
72
77
  ),
73
78
  },
74
79
  (args) => {
@@ -93,6 +93,16 @@ await yargs(hideBin(process.argv))
93
93
  array: true,
94
94
  describe: "크롬 inspect를 수행할 패키지 설정",
95
95
  },
96
+ emitOnly: {
97
+ type: "boolean",
98
+ describe: "emit만 수행",
99
+ default: false,
100
+ },
101
+ noEmit: {
102
+ type: "boolean",
103
+ describe: "emit만 수행",
104
+ default: false,
105
+ },
96
106
  }),
97
107
  async (argv) => await SdCliProject.watchAsync(argv),
98
108
  )
package/src/sd-cli.ts CHANGED
@@ -21,12 +21,14 @@ if (path.extname(cliPath) === ".ts") {
21
21
  // .js 번들 실행 (배포본)
22
22
 
23
23
  // 로컬 업데이트
24
- if (!process.argv.slice(2).includes("local-update")) {
25
- await spawnWaitAsync(`node`, [
26
- "--import=specifier-resolution-node/register",
27
- fileURLToPath(cliPath),
28
- "local-update",
29
- ]);
24
+ if (!process.argv.includes("--noEmit")) {
25
+ if (!process.argv.slice(2).includes("local-update")) {
26
+ await spawnWaitAsync(`node`, [
27
+ "--import=specifier-resolution-node/register",
28
+ fileURLToPath(cliPath),
29
+ "local-update",
30
+ ]);
31
+ }
30
32
  }
31
33
 
32
34
  // 프로세스 실행
@@ -10,30 +10,40 @@ export class SdDependencyAnalyzer {
10
10
  program: ts.Program,
11
11
  compilerHost: ts.CompilerHost,
12
12
  scopePathSet: ScopePathSet,
13
- depCache: SdDependencyCache,
13
+ cache: {
14
+ dep: SdDependencyCache;
15
+ type: WeakMap<ts.Node, ts.Type | undefined>;
16
+ prop: WeakMap<ts.Type, Map<string, ts.Symbol | undefined>>;
17
+ declFiles: WeakMap<ts.Symbol, TNormPath[]>;
18
+ ngOrg: Map<TNormPath, ts.SourceFile>;
19
+ },
14
20
  ): void {
15
21
  const compilerOpts = program.getCompilerOptions();
16
22
  const typeChecker = program.getTypeChecker();
17
23
 
24
+ const moduleResolutionCache = ts.createModuleResolutionCache(
25
+ compilerHost.getCurrentDirectory(),
26
+ compilerHost.getCanonicalFileName.bind(compilerHost),
27
+ compilerOpts,
28
+ );
29
+
18
30
  const resolveModule = (text: string, base: string): TNormPath[] => {
19
31
  const res = ts.resolveModuleName(
20
32
  text,
21
33
  base,
22
34
  compilerOpts,
23
35
  compilerHost,
36
+ moduleResolutionCache,
24
37
  );
25
38
 
26
39
  if (res.resolvedModule) {
27
- return [
28
- PathUtils.norm(res.resolvedModule.resolvedFileName),
29
- ];
40
+ return [PathUtils.norm(res.resolvedModule.resolvedFileName)];
30
41
  }
31
42
 
32
43
  const absPath = path.resolve(path.dirname(base), text);
33
44
  if (!scopePathSet.inScope(absPath)) {
34
45
  return [];
35
- }
36
- else if (
46
+ } else if (
37
47
  // 지원되게할 .png등이면 그냥 가져오고 (bundling loader에 들어가는것들과 .ts, .json등)
38
48
  // fallback일때는 absPath에 .ts, .d.ts, .js, .json 등 다붙여서 가져와야함
39
49
  [
@@ -71,13 +81,10 @@ export class SdDependencyAnalyzer {
71
81
  ".pkl",
72
82
  ".mp3",
73
83
  ".ogg",
74
- ].some(ext => absPath.endsWith(ext))
84
+ ].some((ext) => absPath.endsWith(ext))
75
85
  ) {
76
- return [
77
- PathUtils.norm(absPath),
78
- ];
79
- }
80
- else {
86
+ return [PathUtils.norm(absPath)];
87
+ } else {
81
88
  return [
82
89
  PathUtils.norm(absPath + ".ts"),
83
90
  PathUtils.norm(absPath + ".js"),
@@ -88,61 +95,118 @@ export class SdDependencyAnalyzer {
88
95
  };
89
96
 
90
97
  const isInImportOrExport = (node: ts.Node) => {
91
- let curr = node as ts.Node | undefined;
92
- while (curr) {
93
- if (
94
- ts.isImportDeclaration(curr) ||
95
- ts.isExportDeclaration(curr) ||
96
- ts.isImportSpecifier(curr) ||
97
- ts.isExportSpecifier(curr) ||
98
- ts.isNamespaceImport(curr)
99
- ) {
100
- return true;
101
- }
102
- curr = curr.parent;
103
- }
104
- return false;
98
+ const p = node.parent;
99
+ return (
100
+ ts.isImportDeclaration(p) ||
101
+ ts.isExportDeclaration(p) ||
102
+ ts.isImportSpecifier(p) ||
103
+ ts.isExportSpecifier(p) ||
104
+ ts.isNamespaceImport(p)
105
+ );
105
106
  };
106
107
 
107
- const typeCache = new WeakMap<ts.Node, ts.Type>();
108
+ const isDeclarationIdentifier = (id: ts.Identifier): boolean => {
109
+ const p = id.parent;
110
+ return (
111
+ (ts.isParameter(p) && p.name === id) ||
112
+ (ts.isVariableDeclaration(p) && p.name === id) ||
113
+ (ts.isFunctionDeclaration(p) && p.name === id) ||
114
+ (ts.isClassDeclaration(p) && p.name === id) ||
115
+ (ts.isInterfaceDeclaration(p) && p.name === id) ||
116
+ (ts.isTypeAliasDeclaration(p) && p.name === id) ||
117
+ (ts.isEnumDeclaration(p) && p.name === id) ||
118
+ (ts.isPropertySignature(p) && p.name === id) ||
119
+ (ts.isPropertyDeclaration(p) && p.name === id) ||
120
+ (ts.isMethodSignature(p) && p.name === id) ||
121
+ (ts.isMethodDeclaration(p) && p.name === id)
122
+ );
123
+ };
124
+
125
+ // const typeCache = new WeakMap<ts.Node, ts.Type | undefined>();
108
126
 
109
127
  const getCachedType = (node: ts.Node) => {
110
- if (typeCache.has(node)) return typeCache.get(node);
128
+ if (cache.type.has(node)) return cache.type.get(node);
111
129
  const type = typeChecker.getTypeAtLocation(node) as ts.Type | undefined;
112
- if (type) typeCache.set(node, type);
113
- return type;
130
+ if (!type) return undefined;
131
+
132
+ const skipMask =
133
+ ts.TypeFlags.Any |
134
+ ts.TypeFlags.Unknown |
135
+ ts.TypeFlags.Never |
136
+ ts.TypeFlags.Null |
137
+ ts.TypeFlags.Undefined |
138
+ ts.TypeFlags.BooleanLike |
139
+ ts.TypeFlags.NumberLike |
140
+ ts.TypeFlags.StringLike |
141
+ ts.TypeFlags.BigIntLike |
142
+ ts.TypeFlags.ESSymbolLike;
143
+
144
+ const result = (type.flags & skipMask) !== 0 ? undefined : type;
145
+ cache.type.set(node, result);
146
+
147
+ return result;
148
+ };
149
+
150
+ // const propCache = new WeakMap<ts.Type, Map<string, ts.Symbol | undefined>>();
151
+
152
+ const getCachedProp = (type: ts.Type | undefined, name: string) => {
153
+ if (!type) return undefined;
154
+ let map = cache.prop.get(type);
155
+ if (!map) {
156
+ map = new Map();
157
+ cache.prop.set(type, map);
158
+ }
159
+ if (map.has(name)) return map.get(name);
160
+ const s = type.getProperty(name);
161
+ map.set(name, s);
162
+ return s;
163
+ };
164
+
165
+ // const declFilesCache = new WeakMap<ts.Symbol, TNormPath[]>();
166
+
167
+ const getDeclFileNPaths = (sym: ts.Symbol | undefined): TNormPath[] => {
168
+ if (!sym) return [];
169
+ const c = cache.declFiles.get(sym);
170
+ if (c) return c;
171
+ const paths = (sym.getDeclarations() ?? []).map((d) =>
172
+ PathUtils.norm(d.getSourceFile().fileName),
173
+ );
174
+ cache.declFiles.set(sym, paths);
175
+ return paths;
114
176
  };
115
177
 
116
178
  const collectDeps = (sf: ts.SourceFile) => {
117
179
  const sfNPath = PathUtils.norm(sf.fileName);
118
- if (depCache.hasCollected(sfNPath)) return;
119
- depCache.addCollected(sfNPath);
180
+ if (cache.dep.hasCollected(sfNPath)) return;
181
+ cache.dep.addCollected(sfNPath);
182
+ if (!scopePathSet.inScope(sfNPath)) return;
120
183
 
121
184
  const visit = (node: ts.Node) => {
122
185
  // --- import ... from '...'
123
- if (
124
- ts.isImportDeclaration(node) &&
125
- ts.isStringLiteral(node.moduleSpecifier)
126
- ) {
186
+ if (ts.isImportDeclaration(node) && ts.isStringLiteral(node.moduleSpecifier)) {
127
187
  const resolvedNPaths = resolveModule(node.moduleSpecifier.text, sf.fileName);
128
188
  for (const resolvedNPath of resolvedNPaths) {
189
+ if (!scopePathSet.inScope(resolvedNPath)) continue;
190
+
129
191
  if (
130
192
  node.importClause &&
131
193
  node.importClause.namedBindings &&
132
194
  ts.isNamedImports(node.importClause.namedBindings)
133
195
  ) {
196
+ // import ... from '...'
134
197
  for (const element of node.importClause.namedBindings.elements) {
135
- depCache.addImport(
198
+ cache.dep.addImport(
136
199
  sfNPath,
137
200
  resolvedNPath,
138
201
  element.propertyName?.text ?? element.name.text,
139
202
  );
140
203
  }
141
- }
142
- else {
143
- depCache.addImport(sfNPath, resolvedNPath, 0);
204
+ } else {
205
+ cache.dep.addImport(sfNPath, resolvedNPath, 0);
144
206
  }
145
207
  }
208
+
209
+ return;
146
210
  }
147
211
 
148
212
  // --- export * from '...'
@@ -154,12 +218,16 @@ export class SdDependencyAnalyzer {
154
218
  ) {
155
219
  const resolvedNPaths = resolveModule(node.moduleSpecifier.text, sf.fileName);
156
220
  for (const resolvedNPath of resolvedNPaths) {
157
- depCache.addReexport(sfNPath, resolvedNPath, 0);
221
+ if (!scopePathSet.inScope(resolvedNPath)) continue;
222
+
223
+ cache.dep.addReexport(sfNPath, resolvedNPath, 0);
158
224
  }
225
+
226
+ return;
159
227
  }
160
228
 
161
229
  // --- export { A as B } from '...'
162
- if (
230
+ else if (
163
231
  ts.isExportDeclaration(node) &&
164
232
  node.exportClause &&
165
233
  ts.isNamedExports(node.exportClause) &&
@@ -168,89 +236,87 @@ export class SdDependencyAnalyzer {
168
236
  ) {
169
237
  const resolvedNPaths = resolveModule(node.moduleSpecifier.text, sf.fileName);
170
238
  for (const resolvedNPath of resolvedNPaths) {
239
+ if (!scopePathSet.inScope(resolvedNPath)) continue;
240
+
171
241
  for (const element of node.exportClause.elements) {
172
242
  const local = element.propertyName?.text ?? element.name.text;
173
243
  const exported = element.name.text;
174
- depCache.addReexport(sfNPath, resolvedNPath, {
244
+ cache.dep.addReexport(sfNPath, resolvedNPath, {
175
245
  importSymbol: local,
176
246
  exportSymbol: exported,
177
247
  });
178
248
  }
179
249
  }
250
+
251
+ return;
180
252
  }
181
253
 
182
254
  // --- export const A = ...
183
255
  else if (
184
256
  ts.isVariableStatement(node) &&
185
- node.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword)
257
+ node.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword)
186
258
  ) {
187
259
  for (const decl of node.declarationList.declarations) {
188
260
  if (ts.isIdentifier(decl.name)) {
189
- depCache.addExport(sfNPath, decl.name.text);
261
+ cache.dep.addExport(sfNPath, decl.name.text);
190
262
  }
191
263
  }
192
264
  }
193
265
 
194
266
  // --- export function/class/interface A ...
195
- else if (
196
- (
197
- ts.isFunctionDeclaration(node) ||
267
+ if (
268
+ (ts.isFunctionDeclaration(node) ||
198
269
  ts.isClassDeclaration(node) ||
199
270
  ts.isInterfaceDeclaration(node) ||
200
271
  ts.isTypeAliasDeclaration(node) ||
201
- ts.isEnumDeclaration(node)
202
- ) &&
203
- node.modifiers?.some(mod => mod.kind === ts.SyntaxKind.ExportKeyword) &&
272
+ ts.isEnumDeclaration(node)) &&
273
+ node.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ExportKeyword) &&
204
274
  node.name
205
275
  ) {
206
- depCache.addExport(sfNPath, node.name.text);
207
- }
208
-
209
- else if (ts.isIdentifier(node) && !isInImportOrExport(node)) {
276
+ cache.dep.addExport(sfNPath, node.name.text);
277
+ } else if (
278
+ ts.isIdentifier(node) &&
279
+ isDeclarationIdentifier(node) &&
280
+ !isInImportOrExport(node)
281
+ ) {
210
282
  const orgValSymbol = typeChecker.getSymbolAtLocation(node);
283
+ let valSymbol = orgValSymbol;
284
+ if (orgValSymbol && orgValSymbol.flags & ts.SymbolFlags.Alias) {
285
+ // 현 파일 선언으로 확정되면 굳이 치환 불필요
286
+ const declNPaths = getDeclFileNPaths(orgValSymbol);
287
+ const external = declNPaths.some((declNPath) => declNPath !== sfNPath);
288
+ if (external) {
289
+ valSymbol = typeChecker.getAliasedSymbol(orgValSymbol);
290
+ }
291
+ }
211
292
 
212
- // alias (import된 심볼)일 경우, 원본 심볼로 치환
213
- const valSymbol = (orgValSymbol && (orgValSymbol.flags & ts.SymbolFlags.Alias))
214
- ? typeChecker.getAliasedSymbol(orgValSymbol)
215
- : undefined;
216
-
217
- for (const decl of valSymbol?.getDeclarations() ?? []) {
218
- const declFile = decl.getSourceFile();
219
- const declNPath = PathUtils.norm(declFile.fileName);
293
+ for (const declNPath of getDeclFileNPaths(valSymbol)) {
220
294
  if (declNPath !== sfNPath && scopePathSet.inScope(declNPath)) {
221
- depCache.addImport(sfNPath, declNPath, 0);
295
+ cache.dep.addImport(sfNPath, declNPath, 0);
222
296
  }
223
297
  }
224
- }
225
- else if (
226
- ts.isPropertyAccessExpression(node)
227
- ) {
298
+ } else if (ts.isPropertyAccessExpression(node)) {
228
299
  const type = getCachedType(node.expression);
229
- const propSymbol = type?.getProperty(node.name.text);
300
+ const propSymbol = getCachedProp(type, node.name.text);
230
301
 
231
302
  if (propSymbol) {
232
- for (const decl of propSymbol.getDeclarations() ?? []) {
233
- const declFile = decl.getSourceFile();
234
- const declNPath = PathUtils.norm(declFile.fileName);
303
+ for (const declNPath of getDeclFileNPaths(propSymbol)) {
235
304
  if (declNPath !== sfNPath && scopePathSet.inScope(declNPath)) {
236
- depCache.addImport(sfNPath, declNPath, 0);
305
+ cache.dep.addImport(sfNPath, declNPath, 0);
237
306
  }
238
307
  }
239
308
  }
240
- }
241
- else if (
309
+ } else if (
242
310
  ts.isElementAccessExpression(node) &&
243
311
  ts.isStringLiteral(node.argumentExpression)
244
312
  ) {
245
313
  const type = getCachedType(node.expression);
246
- const propSymbol = type?.getProperty(node.argumentExpression.text);
314
+ const propSymbol = getCachedProp(type, node.argumentExpression.text);
247
315
 
248
316
  if (propSymbol) {
249
- for (const decl of propSymbol.getDeclarations() ?? []) {
250
- const declFile = decl.getSourceFile();
251
- const declNPath = PathUtils.norm(declFile.fileName);
317
+ for (const declNPath of getDeclFileNPaths(propSymbol)) {
252
318
  if (declNPath !== sfNPath && scopePathSet.inScope(declNPath)) {
253
- depCache.addImport(sfNPath, declNPath, 0);
319
+ cache.dep.addImport(sfNPath, declNPath, 0);
254
320
  }
255
321
  }
256
322
  }
@@ -262,16 +328,27 @@ export class SdDependencyAnalyzer {
262
328
  ts.forEachChild(sf, visit);
263
329
  };
264
330
 
331
+ // const ngToOrgCache = new Map<TNormPath, ts.SourceFile>();
332
+
265
333
  const getOrgSourceFile = (sf: ts.SourceFile) => {
266
334
  if (sf.fileName.endsWith(".ngtypecheck.ts")) {
267
- const orgFileName = sf.fileName.slice(0, -15) + ".ts";
268
- return program.getSourceFile(orgFileName);
335
+ const sfNPath = PathUtils.norm(sf.fileName);
336
+ let org = cache.ngOrg.get(sfNPath);
337
+ if (!org) {
338
+ const orgPath = sf.fileName.slice(0, -15) + ".ts";
339
+ org = program.getSourceFile(orgPath) ?? sf;
340
+
341
+ const realOrg = program.getSourceFile(orgPath);
342
+ if (realOrg) cache.ngOrg.set(sfNPath, realOrg);
343
+ }
344
+ return org;
269
345
  }
270
346
  return sf;
271
347
  };
272
348
 
273
349
  const sourceFileSet = new Set(
274
- program.getSourceFiles()
350
+ program
351
+ .getSourceFiles()
275
352
  .filter((sf) => scopePathSet.inScope(sf.fileName))
276
353
  .map((sf) => getOrgSourceFile(sf))
277
354
  .filterExists(),
@@ -282,13 +359,11 @@ export class SdDependencyAnalyzer {
282
359
  }
283
360
  }
284
361
 
285
-
286
362
  static analyzeAngularResources(
287
363
  ngProgram: NgtscProgram,
288
364
  scopePathSet: ScopePathSet,
289
365
  depCache: SdDependencyCache,
290
366
  ) {
291
-
292
367
  for (const sf of ngProgram.getTsProgram().getSourceFiles()) {
293
368
  const fileNPath = PathUtils.norm(sf.fileName);
294
369
  if (!scopePathSet.inScope(fileNPath)) continue;
@@ -302,4 +377,4 @@ export class SdDependencyAnalyzer {
302
377
  }
303
378
  }
304
379
  }
305
- }
380
+ }