@angular/core 19.1.0-next.4 → 19.1.0-rc.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.
- package/LICENSE +1 -1
- package/fesm2022/core.mjs +190 -162
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/primitives/event-dispatch.mjs +1 -24
- package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
- package/fesm2022/primitives/signals.mjs +1 -1
- package/fesm2022/rxjs-interop.mjs +1 -1
- package/fesm2022/testing.mjs +5 -5
- package/index.d.ts +17 -11
- package/package.json +1 -1
- package/primitives/event-dispatch/index.d.ts +1 -1
- package/primitives/signals/index.d.ts +1 -1
- package/rxjs-interop/index.d.ts +1 -1
- package/schematics/bundles/apply_import_manager-6508401d.js +732 -0
- package/schematics/bundles/{checker-884633eb.js → checker-24b68d23.js} +33 -9
- package/schematics/bundles/cleanup-unused-imports.js +295 -0
- package/schematics/bundles/{compiler_host-22f6513d.js → compiler_host-5f693799.js} +2 -2
- package/schematics/bundles/control-flow-migration.js +3 -3
- package/schematics/bundles/explicit-standalone-flag.js +3 -3
- package/schematics/bundles/imports-abe29092.js +1 -1
- package/schematics/bundles/{combine_units-4a95b1b9.js → index-767e341d.js} +10 -723
- package/schematics/bundles/index-b1033cf0.js +30 -0
- package/schematics/bundles/inject-migration.js +3 -3
- package/schematics/bundles/leading_space-d190b83b.js +1 -1
- package/schematics/bundles/{migrate_ts_type_references-4b11f3f2.js → migrate_ts_type_references-bc7d8784.js} +29 -28
- package/schematics/bundles/nodes-a9f0b985.js +1 -1
- package/schematics/bundles/output-migration.js +26 -25
- package/schematics/bundles/pending-tasks.js +3 -3
- package/schematics/bundles/{program-094352ba.js → program-c810a4c2.js} +81 -40
- package/schematics/bundles/project_tsconfig_paths-e9ccccbf.js +1 -1
- package/schematics/bundles/provide-initializer.js +3 -3
- package/schematics/bundles/route-lazy-loading.js +3 -3
- package/schematics/bundles/signal-input-migration.js +31 -30
- package/schematics/bundles/signal-queries-migration.js +48 -47
- package/schematics/bundles/signals.js +6 -5
- package/schematics/bundles/standalone-migration.js +9 -25
- package/schematics/collection.json +5 -0
- package/schematics/ng-generate/cleanup-unused-imports/schema.json +7 -0
- package/testing/index.d.ts +1 -1
|
@@ -1,702 +1,22 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v19.1.0-
|
|
3
|
+
* @license Angular v19.1.0-rc.0
|
|
4
4
|
* (c) 2010-2024 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
var core = require('@angular-devkit/core');
|
|
10
|
-
var posixPath = require('node:path/posix');
|
|
11
|
-
var os = require('os');
|
|
12
9
|
var ts = require('typescript');
|
|
13
|
-
|
|
14
|
-
var
|
|
10
|
+
require('os');
|
|
11
|
+
var checker = require('./checker-24b68d23.js');
|
|
12
|
+
var program = require('./program-c810a4c2.js');
|
|
15
13
|
require('path');
|
|
14
|
+
var apply_import_manager = require('./apply_import_manager-6508401d.js');
|
|
16
15
|
|
|
17
16
|
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
18
17
|
|
|
19
|
-
function _interopNamespace(e) {
|
|
20
|
-
if (e && e.__esModule) return e;
|
|
21
|
-
var n = Object.create(null);
|
|
22
|
-
if (e) {
|
|
23
|
-
Object.keys(e).forEach(function (k) {
|
|
24
|
-
if (k !== 'default') {
|
|
25
|
-
var d = Object.getOwnPropertyDescriptor(e, k);
|
|
26
|
-
Object.defineProperty(n, k, d.get ? d : {
|
|
27
|
-
enumerable: true,
|
|
28
|
-
get: function () { return e[k]; }
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
});
|
|
32
|
-
}
|
|
33
|
-
n["default"] = e;
|
|
34
|
-
return Object.freeze(n);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
var posixPath__namespace = /*#__PURE__*/_interopNamespace(posixPath);
|
|
38
|
-
var os__namespace = /*#__PURE__*/_interopNamespace(os);
|
|
39
18
|
var ts__default = /*#__PURE__*/_interopDefaultLegacy(ts);
|
|
40
19
|
|
|
41
|
-
/// <reference types="node" />
|
|
42
|
-
class NgtscCompilerHost {
|
|
43
|
-
fs;
|
|
44
|
-
options;
|
|
45
|
-
constructor(fs, options = {}) {
|
|
46
|
-
this.fs = fs;
|
|
47
|
-
this.options = options;
|
|
48
|
-
}
|
|
49
|
-
getSourceFile(fileName, languageVersion) {
|
|
50
|
-
const text = this.readFile(fileName);
|
|
51
|
-
return text !== undefined
|
|
52
|
-
? ts__default["default"].createSourceFile(fileName, text, languageVersion, true)
|
|
53
|
-
: undefined;
|
|
54
|
-
}
|
|
55
|
-
getDefaultLibFileName(options) {
|
|
56
|
-
return this.fs.join(this.getDefaultLibLocation(), ts__default["default"].getDefaultLibFileName(options));
|
|
57
|
-
}
|
|
58
|
-
getDefaultLibLocation() {
|
|
59
|
-
return this.fs.getDefaultLibLocation();
|
|
60
|
-
}
|
|
61
|
-
writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles) {
|
|
62
|
-
const path = checker.absoluteFrom(fileName);
|
|
63
|
-
this.fs.ensureDir(this.fs.dirname(path));
|
|
64
|
-
this.fs.writeFile(path, data);
|
|
65
|
-
}
|
|
66
|
-
getCurrentDirectory() {
|
|
67
|
-
return this.fs.pwd();
|
|
68
|
-
}
|
|
69
|
-
getCanonicalFileName(fileName) {
|
|
70
|
-
return this.useCaseSensitiveFileNames() ? fileName : fileName.toLowerCase();
|
|
71
|
-
}
|
|
72
|
-
useCaseSensitiveFileNames() {
|
|
73
|
-
return this.fs.isCaseSensitive();
|
|
74
|
-
}
|
|
75
|
-
getNewLine() {
|
|
76
|
-
switch (this.options.newLine) {
|
|
77
|
-
case ts__default["default"].NewLineKind.CarriageReturnLineFeed:
|
|
78
|
-
return '\r\n';
|
|
79
|
-
case ts__default["default"].NewLineKind.LineFeed:
|
|
80
|
-
return '\n';
|
|
81
|
-
default:
|
|
82
|
-
return os__namespace.EOL;
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
fileExists(fileName) {
|
|
86
|
-
const absPath = this.fs.resolve(fileName);
|
|
87
|
-
return this.fs.exists(absPath) && this.fs.stat(absPath).isFile();
|
|
88
|
-
}
|
|
89
|
-
readFile(fileName) {
|
|
90
|
-
const absPath = this.fs.resolve(fileName);
|
|
91
|
-
if (!this.fileExists(absPath)) {
|
|
92
|
-
return undefined;
|
|
93
|
-
}
|
|
94
|
-
return this.fs.readFile(absPath);
|
|
95
|
-
}
|
|
96
|
-
realpath(path) {
|
|
97
|
-
return this.fs.realpath(this.fs.resolve(path));
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// We use TypeScript's native `ts.matchFiles` utility for the virtual file systems
|
|
102
|
-
/**
|
|
103
|
-
* Creates a {@link ts.CompilerHost#readDirectory} implementation function,
|
|
104
|
-
* that leverages the specified file system (that may be e.g. virtual).
|
|
105
|
-
*/
|
|
106
|
-
function createFileSystemTsReadDirectoryFn(fs) {
|
|
107
|
-
if (ts__default["default"].matchFiles === undefined) {
|
|
108
|
-
throw Error('Unable to read directory in configured file system. This means that ' +
|
|
109
|
-
'TypeScript changed its file matching internals.\n\nPlease consider downgrading your ' +
|
|
110
|
-
'TypeScript version, and report an issue in the Angular framework repository.');
|
|
111
|
-
}
|
|
112
|
-
const matchFilesFn = ts__default["default"].matchFiles.bind(ts__default["default"]);
|
|
113
|
-
return (rootDir, extensions, excludes, includes, depth) => {
|
|
114
|
-
const directoryExists = (p) => {
|
|
115
|
-
const resolvedPath = fs.resolve(p);
|
|
116
|
-
return fs.exists(resolvedPath) && fs.stat(resolvedPath).isDirectory();
|
|
117
|
-
};
|
|
118
|
-
return matchFilesFn(rootDir, extensions, excludes, includes, fs.isCaseSensitive(), fs.pwd(), depth, (p) => {
|
|
119
|
-
const resolvedPath = fs.resolve(p);
|
|
120
|
-
// TS also gracefully returns an empty file set.
|
|
121
|
-
if (!directoryExists(resolvedPath)) {
|
|
122
|
-
return { directories: [], files: [] };
|
|
123
|
-
}
|
|
124
|
-
const children = fs.readdir(resolvedPath);
|
|
125
|
-
const files = [];
|
|
126
|
-
const directories = [];
|
|
127
|
-
for (const child of children) {
|
|
128
|
-
if (fs.stat(fs.join(resolvedPath, child))?.isDirectory()) {
|
|
129
|
-
directories.push(child);
|
|
130
|
-
}
|
|
131
|
-
else {
|
|
132
|
-
files.push(child);
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
return { files, directories };
|
|
136
|
-
}, (p) => fs.resolve(p), (p) => directoryExists(p));
|
|
137
|
-
};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
function calcProjectFileAndBasePath(project, host = checker.getFileSystem()) {
|
|
141
|
-
const absProject = host.resolve(project);
|
|
142
|
-
const projectIsDir = host.lstat(absProject).isDirectory();
|
|
143
|
-
const projectFile = projectIsDir ? host.join(absProject, 'tsconfig.json') : absProject;
|
|
144
|
-
const projectDir = projectIsDir ? absProject : host.dirname(absProject);
|
|
145
|
-
const basePath = host.resolve(projectDir);
|
|
146
|
-
return { projectFile, basePath };
|
|
147
|
-
}
|
|
148
|
-
function readConfiguration(project, existingOptions, host = checker.getFileSystem()) {
|
|
149
|
-
try {
|
|
150
|
-
const fs = checker.getFileSystem();
|
|
151
|
-
const readConfigFile = (configFile) => ts__default["default"].readConfigFile(configFile, (file) => host.readFile(host.resolve(file)));
|
|
152
|
-
const readAngularCompilerOptions = (configFile, parentOptions = {}) => {
|
|
153
|
-
const { config, error } = readConfigFile(configFile);
|
|
154
|
-
if (error) {
|
|
155
|
-
// Errors are handled later on by 'parseJsonConfigFileContent'
|
|
156
|
-
return parentOptions;
|
|
157
|
-
}
|
|
158
|
-
// Note: In Google, `angularCompilerOptions` are stored in `bazelOptions`.
|
|
159
|
-
// This function typically doesn't run for actual Angular compilations, but
|
|
160
|
-
// tooling like Tsurge, or schematics may leverage this helper, so we account
|
|
161
|
-
// for this here.
|
|
162
|
-
const angularCompilerOptions = config.angularCompilerOptions ?? config.bazelOptions?.angularCompilerOptions;
|
|
163
|
-
// we are only interested into merging 'angularCompilerOptions' as
|
|
164
|
-
// other options like 'compilerOptions' are merged by TS
|
|
165
|
-
let existingNgCompilerOptions = { ...angularCompilerOptions, ...parentOptions };
|
|
166
|
-
if (!config.extends) {
|
|
167
|
-
return existingNgCompilerOptions;
|
|
168
|
-
}
|
|
169
|
-
const extendsPaths = typeof config.extends === 'string' ? [config.extends] : config.extends;
|
|
170
|
-
// Call readAngularCompilerOptions recursively to merge NG Compiler options
|
|
171
|
-
// Reverse the array so the overrides happen from right to left.
|
|
172
|
-
return [...extendsPaths].reverse().reduce((prevOptions, extendsPath) => {
|
|
173
|
-
const extendedConfigPath = getExtendedConfigPath(configFile, extendsPath, host, fs);
|
|
174
|
-
return extendedConfigPath === null
|
|
175
|
-
? prevOptions
|
|
176
|
-
: readAngularCompilerOptions(extendedConfigPath, prevOptions);
|
|
177
|
-
}, existingNgCompilerOptions);
|
|
178
|
-
};
|
|
179
|
-
const { projectFile, basePath } = calcProjectFileAndBasePath(project, host);
|
|
180
|
-
const configFileName = host.resolve(host.pwd(), projectFile);
|
|
181
|
-
const { config, error } = readConfigFile(projectFile);
|
|
182
|
-
if (error) {
|
|
183
|
-
return {
|
|
184
|
-
project,
|
|
185
|
-
errors: [error],
|
|
186
|
-
rootNames: [],
|
|
187
|
-
options: {},
|
|
188
|
-
emitFlags: program.EmitFlags.Default,
|
|
189
|
-
};
|
|
190
|
-
}
|
|
191
|
-
const existingCompilerOptions = {
|
|
192
|
-
genDir: basePath,
|
|
193
|
-
basePath,
|
|
194
|
-
...readAngularCompilerOptions(configFileName),
|
|
195
|
-
...existingOptions,
|
|
196
|
-
};
|
|
197
|
-
const parseConfigHost = createParseConfigHost(host, fs);
|
|
198
|
-
const { options, errors, fileNames: rootNames, projectReferences, } = ts__default["default"].parseJsonConfigFileContent(config, parseConfigHost, basePath, existingCompilerOptions, configFileName);
|
|
199
|
-
let emitFlags = program.EmitFlags.Default;
|
|
200
|
-
if (!(options['skipMetadataEmit'] || options['flatModuleOutFile'])) {
|
|
201
|
-
emitFlags |= program.EmitFlags.Metadata;
|
|
202
|
-
}
|
|
203
|
-
if (options['skipTemplateCodegen']) {
|
|
204
|
-
emitFlags = emitFlags & ~program.EmitFlags.Codegen;
|
|
205
|
-
}
|
|
206
|
-
return { project: projectFile, rootNames, projectReferences, options, errors, emitFlags };
|
|
207
|
-
}
|
|
208
|
-
catch (e) {
|
|
209
|
-
const errors = [
|
|
210
|
-
{
|
|
211
|
-
category: ts__default["default"].DiagnosticCategory.Error,
|
|
212
|
-
messageText: e.stack ?? e.message,
|
|
213
|
-
file: undefined,
|
|
214
|
-
start: undefined,
|
|
215
|
-
length: undefined,
|
|
216
|
-
source: 'angular',
|
|
217
|
-
code: program.UNKNOWN_ERROR_CODE,
|
|
218
|
-
},
|
|
219
|
-
];
|
|
220
|
-
return { project: '', errors, rootNames: [], options: {}, emitFlags: program.EmitFlags.Default };
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
function createParseConfigHost(host, fs = checker.getFileSystem()) {
|
|
224
|
-
return {
|
|
225
|
-
fileExists: host.exists.bind(host),
|
|
226
|
-
readDirectory: createFileSystemTsReadDirectoryFn(fs),
|
|
227
|
-
readFile: host.readFile.bind(host),
|
|
228
|
-
useCaseSensitiveFileNames: fs.isCaseSensitive(),
|
|
229
|
-
};
|
|
230
|
-
}
|
|
231
|
-
function getExtendedConfigPath(configFile, extendsValue, host, fs) {
|
|
232
|
-
const result = getExtendedConfigPathWorker(configFile, extendsValue, host, fs);
|
|
233
|
-
if (result !== null) {
|
|
234
|
-
return result;
|
|
235
|
-
}
|
|
236
|
-
// Try to resolve the paths with a json extension append a json extension to the file in case if
|
|
237
|
-
// it is missing and the resolution failed. This is to replicate TypeScript behaviour, see:
|
|
238
|
-
// https://github.com/microsoft/TypeScript/blob/294a5a7d784a5a95a8048ee990400979a6bc3a1c/src/compiler/commandLineParser.ts#L2806
|
|
239
|
-
return getExtendedConfigPathWorker(configFile, `${extendsValue}.json`, host, fs);
|
|
240
|
-
}
|
|
241
|
-
function getExtendedConfigPathWorker(configFile, extendsValue, host, fs) {
|
|
242
|
-
if (extendsValue.startsWith('.') || fs.isRooted(extendsValue)) {
|
|
243
|
-
const extendedConfigPath = host.resolve(host.dirname(configFile), extendsValue);
|
|
244
|
-
if (host.exists(extendedConfigPath)) {
|
|
245
|
-
return extendedConfigPath;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
const parseConfigHost = createParseConfigHost(host, fs);
|
|
250
|
-
// Path isn't a rooted or relative path, resolve like a module.
|
|
251
|
-
const { resolvedModule } = ts__default["default"].nodeModuleNameResolver(extendsValue, configFile, { moduleResolution: ts__default["default"].ModuleResolutionKind.Node10, resolveJsonModule: true }, parseConfigHost);
|
|
252
|
-
if (resolvedModule) {
|
|
253
|
-
return checker.absoluteFrom(resolvedModule.resolvedFileName);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
return null;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
/**
|
|
260
|
-
* Angular compiler file system implementation that leverages an
|
|
261
|
-
* CLI schematic virtual file tree.
|
|
262
|
-
*/
|
|
263
|
-
class DevkitMigrationFilesystem {
|
|
264
|
-
tree;
|
|
265
|
-
constructor(tree) {
|
|
266
|
-
this.tree = tree;
|
|
267
|
-
}
|
|
268
|
-
extname(path) {
|
|
269
|
-
return core.extname(path);
|
|
270
|
-
}
|
|
271
|
-
isRoot(path) {
|
|
272
|
-
return path === core.normalize('/');
|
|
273
|
-
}
|
|
274
|
-
isRooted(path) {
|
|
275
|
-
return this.normalize(path).startsWith('/');
|
|
276
|
-
}
|
|
277
|
-
dirname(file) {
|
|
278
|
-
return this.normalize(core.dirname(file));
|
|
279
|
-
}
|
|
280
|
-
join(basePath, ...paths) {
|
|
281
|
-
return this.normalize(core.join(basePath, ...paths));
|
|
282
|
-
}
|
|
283
|
-
relative(from, to) {
|
|
284
|
-
return this.normalize(core.relative(from, to));
|
|
285
|
-
}
|
|
286
|
-
basename(filePath, extension) {
|
|
287
|
-
return posixPath__namespace.basename(filePath, extension);
|
|
288
|
-
}
|
|
289
|
-
normalize(path) {
|
|
290
|
-
return core.normalize(path);
|
|
291
|
-
}
|
|
292
|
-
resolve(...paths) {
|
|
293
|
-
const normalizedPaths = paths.map((p) => core.normalize(p));
|
|
294
|
-
// In dev-kit, the NodeJS working directory should never be
|
|
295
|
-
// considered, so `/` is the last resort over `cwd`.
|
|
296
|
-
return this.normalize(posixPath__namespace.resolve(core.normalize('/'), ...normalizedPaths));
|
|
297
|
-
}
|
|
298
|
-
pwd() {
|
|
299
|
-
return '/';
|
|
300
|
-
}
|
|
301
|
-
isCaseSensitive() {
|
|
302
|
-
return true;
|
|
303
|
-
}
|
|
304
|
-
exists(path) {
|
|
305
|
-
return statPath(this.tree, path) !== null;
|
|
306
|
-
}
|
|
307
|
-
readFile(path) {
|
|
308
|
-
return this.tree.readText(path);
|
|
309
|
-
}
|
|
310
|
-
readFileBuffer(path) {
|
|
311
|
-
const buffer = this.tree.read(path);
|
|
312
|
-
if (buffer === null) {
|
|
313
|
-
throw new Error(`File does not exist: ${path}`);
|
|
314
|
-
}
|
|
315
|
-
return buffer;
|
|
316
|
-
}
|
|
317
|
-
readdir(path) {
|
|
318
|
-
const dir = this.tree.getDir(path);
|
|
319
|
-
return [
|
|
320
|
-
...dir.subdirs,
|
|
321
|
-
...dir.subfiles,
|
|
322
|
-
];
|
|
323
|
-
}
|
|
324
|
-
lstat(path) {
|
|
325
|
-
const stat = statPath(this.tree, path);
|
|
326
|
-
if (stat === null) {
|
|
327
|
-
throw new Error(`File does not exist for "lstat": ${path}`);
|
|
328
|
-
}
|
|
329
|
-
return stat;
|
|
330
|
-
}
|
|
331
|
-
stat(path) {
|
|
332
|
-
const stat = statPath(this.tree, path);
|
|
333
|
-
if (stat === null) {
|
|
334
|
-
throw new Error(`File does not exist for "stat": ${path}`);
|
|
335
|
-
}
|
|
336
|
-
return stat;
|
|
337
|
-
}
|
|
338
|
-
realpath(filePath) {
|
|
339
|
-
return filePath;
|
|
340
|
-
}
|
|
341
|
-
getDefaultLibLocation() {
|
|
342
|
-
return 'node_modules/typescript/lib';
|
|
343
|
-
}
|
|
344
|
-
ensureDir(path) {
|
|
345
|
-
// Migrations should compute replacements and not write directly.
|
|
346
|
-
throw new Error('DevkitFilesystem#ensureDir is not supported.');
|
|
347
|
-
}
|
|
348
|
-
writeFile(path, data) {
|
|
349
|
-
// Migrations should compute replacements and not write directly.
|
|
350
|
-
throw new Error('DevkitFilesystem#writeFile is not supported.');
|
|
351
|
-
}
|
|
352
|
-
removeFile(path) {
|
|
353
|
-
// Migrations should compute replacements and not write directly.
|
|
354
|
-
throw new Error('DevkitFilesystem#removeFile is not supported.');
|
|
355
|
-
}
|
|
356
|
-
copyFile(from, to) {
|
|
357
|
-
// Migrations should compute replacements and not write directly.
|
|
358
|
-
throw new Error('DevkitFilesystem#copyFile is not supported.');
|
|
359
|
-
}
|
|
360
|
-
moveFile(from, to) {
|
|
361
|
-
// Migrations should compute replacements and not write directly.
|
|
362
|
-
throw new Error('DevkitFilesystem#moveFile is not supported.');
|
|
363
|
-
}
|
|
364
|
-
removeDeep(path) {
|
|
365
|
-
// Migrations should compute replacements and not write directly.
|
|
366
|
-
throw new Error('DevkitFilesystem#removeDeep is not supported.');
|
|
367
|
-
}
|
|
368
|
-
chdir(_path) {
|
|
369
|
-
throw new Error('FileSystem#chdir is not supported.');
|
|
370
|
-
}
|
|
371
|
-
symlink() {
|
|
372
|
-
throw new Error('FileSystem#symlink is not supported.');
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
/** Stats the given path in the virtual tree. */
|
|
376
|
-
function statPath(tree, path) {
|
|
377
|
-
let fileInfo = null;
|
|
378
|
-
let dirInfo = null;
|
|
379
|
-
try {
|
|
380
|
-
fileInfo = tree.get(path);
|
|
381
|
-
}
|
|
382
|
-
catch (e) {
|
|
383
|
-
if (e.constructor.name === 'PathIsDirectoryException') {
|
|
384
|
-
dirInfo = tree.getDir(path);
|
|
385
|
-
}
|
|
386
|
-
else {
|
|
387
|
-
throw e;
|
|
388
|
-
}
|
|
389
|
-
}
|
|
390
|
-
if (fileInfo !== null || dirInfo !== null) {
|
|
391
|
-
return {
|
|
392
|
-
isDirectory: () => dirInfo !== null,
|
|
393
|
-
isFile: () => fileInfo !== null,
|
|
394
|
-
isSymbolicLink: () => false,
|
|
395
|
-
};
|
|
396
|
-
}
|
|
397
|
-
return null;
|
|
398
|
-
}
|
|
399
|
-
|
|
400
|
-
/**
|
|
401
|
-
* Groups the given replacements per project relative
|
|
402
|
-
* file path.
|
|
403
|
-
*
|
|
404
|
-
* This allows for simple execution of the replacements
|
|
405
|
-
* against a given file. E.g. via {@link applyTextUpdates}.
|
|
406
|
-
*/
|
|
407
|
-
function groupReplacementsByFile(replacements) {
|
|
408
|
-
const result = new Map();
|
|
409
|
-
for (const { projectFile, update } of replacements) {
|
|
410
|
-
if (!result.has(projectFile.rootRelativePath)) {
|
|
411
|
-
result.set(projectFile.rootRelativePath, []);
|
|
412
|
-
}
|
|
413
|
-
result.get(projectFile.rootRelativePath).push(update);
|
|
414
|
-
}
|
|
415
|
-
return result;
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
/**
|
|
419
|
-
* By default, Tsurge will always create an Angular compiler program
|
|
420
|
-
* for projects analyzed and migrated. This works perfectly fine in
|
|
421
|
-
* third-party where Tsurge migrations run in Angular CLI projects.
|
|
422
|
-
*
|
|
423
|
-
* In first party, when running against full Google3, creating an Angular
|
|
424
|
-
* program for e.g. plain `ts_library` targets is overly expensive and
|
|
425
|
-
* can result in out of memory issues for large TS targets. In 1P we can
|
|
426
|
-
* reliably distinguish between TS and Angular targets via the `angularCompilerOptions`.
|
|
427
|
-
*/
|
|
428
|
-
function google3UsePlainTsProgramIfNoKnownAngularOption() {
|
|
429
|
-
return process.env['GOOGLE3_TSURGE'] === '1';
|
|
430
|
-
}
|
|
431
|
-
|
|
432
|
-
/** Options that are good defaults for Tsurge migrations. */
|
|
433
|
-
const defaultMigrationTsOptions = {
|
|
434
|
-
// Avoid checking libraries to speed up migrations.
|
|
435
|
-
skipLibCheck: true,
|
|
436
|
-
skipDefaultLibCheck: true,
|
|
437
|
-
noEmit: true,
|
|
438
|
-
// Does not apply to g3 and externally is enforced when the app is built by the compiler.
|
|
439
|
-
disableTypeScriptVersionCheck: true,
|
|
440
|
-
};
|
|
441
|
-
/**
|
|
442
|
-
* Creates an instance of a TypeScript program for the given project.
|
|
443
|
-
*/
|
|
444
|
-
function createPlainTsProgram(tsHost, tsconfig, optionOverrides) {
|
|
445
|
-
const program = ts__default["default"].createProgram({
|
|
446
|
-
rootNames: tsconfig.rootNames,
|
|
447
|
-
options: {
|
|
448
|
-
...tsconfig.options,
|
|
449
|
-
...defaultMigrationTsOptions,
|
|
450
|
-
...optionOverrides,
|
|
451
|
-
},
|
|
452
|
-
});
|
|
453
|
-
return {
|
|
454
|
-
ngCompiler: null,
|
|
455
|
-
program,
|
|
456
|
-
userOptions: tsconfig.options,
|
|
457
|
-
programAbsoluteRootFileNames: tsconfig.rootNames,
|
|
458
|
-
host: tsHost,
|
|
459
|
-
};
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* Parses the configuration of the given TypeScript project and creates
|
|
464
|
-
* an instance of the Angular compiler for the project.
|
|
465
|
-
*/
|
|
466
|
-
function createNgtscProgram(tsHost, tsconfig, optionOverrides) {
|
|
467
|
-
const ngtscProgram = new program.NgtscProgram(tsconfig.rootNames, {
|
|
468
|
-
...tsconfig.options,
|
|
469
|
-
...defaultMigrationTsOptions,
|
|
470
|
-
...optionOverrides,
|
|
471
|
-
}, tsHost);
|
|
472
|
-
// Expose an easy way to debug-print ng semantic diagnostics.
|
|
473
|
-
if (process.env['DEBUG_NG_SEMANTIC_DIAGNOSTICS'] === '1') {
|
|
474
|
-
console.error(ts__default["default"].formatDiagnosticsWithColorAndContext(ngtscProgram.getNgSemanticDiagnostics(), tsHost));
|
|
475
|
-
}
|
|
476
|
-
return {
|
|
477
|
-
ngCompiler: ngtscProgram.compiler,
|
|
478
|
-
program: ngtscProgram.getTsProgram(),
|
|
479
|
-
userOptions: tsconfig.options,
|
|
480
|
-
programAbsoluteRootFileNames: tsconfig.rootNames,
|
|
481
|
-
host: tsHost,
|
|
482
|
-
};
|
|
483
|
-
}
|
|
484
|
-
|
|
485
|
-
/** Code of the error raised by TypeScript when a tsconfig doesn't match any files. */
|
|
486
|
-
const NO_INPUTS_ERROR_CODE = 18003;
|
|
487
|
-
/** Parses the given tsconfig file, supporting Angular compiler options. */
|
|
488
|
-
function parseTsconfigOrDie(absoluteTsconfigPath, fs) {
|
|
489
|
-
const tsconfig = readConfiguration(absoluteTsconfigPath, {}, fs);
|
|
490
|
-
// Skip the "No inputs found..." error since we don't want to interrupt the migration if a
|
|
491
|
-
// tsconfig doesn't match a file. This will result in an empty `Program` which is still valid.
|
|
492
|
-
const errors = tsconfig.errors.filter((diag) => diag.code !== NO_INPUTS_ERROR_CODE);
|
|
493
|
-
if (errors.length) {
|
|
494
|
-
throw new Error(`Tsconfig could not be parsed or is invalid:\n\n` + `${errors.map((e) => e.messageText)}`);
|
|
495
|
-
}
|
|
496
|
-
return tsconfig;
|
|
497
|
-
}
|
|
498
|
-
|
|
499
|
-
/** Creates the base program info for the given tsconfig path. */
|
|
500
|
-
function createBaseProgramInfo(absoluteTsconfigPath, fs, optionOverrides = {}) {
|
|
501
|
-
if (fs === undefined) {
|
|
502
|
-
fs = new checker.NodeJSFileSystem();
|
|
503
|
-
checker.setFileSystem(fs);
|
|
504
|
-
}
|
|
505
|
-
const tsconfig = parseTsconfigOrDie(absoluteTsconfigPath, fs);
|
|
506
|
-
const tsHost = new NgtscCompilerHost(fs, tsconfig.options);
|
|
507
|
-
// When enabled, use a plain TS program if we are sure it's not
|
|
508
|
-
// an Angular project based on the `tsconfig.json`.
|
|
509
|
-
if (google3UsePlainTsProgramIfNoKnownAngularOption() &&
|
|
510
|
-
tsconfig.options['_useHostForImportGeneration'] === undefined) {
|
|
511
|
-
return createPlainTsProgram(tsHost, tsconfig, optionOverrides);
|
|
512
|
-
}
|
|
513
|
-
return createNgtscProgram(tsHost, tsconfig, optionOverrides);
|
|
514
|
-
}
|
|
515
|
-
|
|
516
|
-
/**
|
|
517
|
-
* @private
|
|
518
|
-
*
|
|
519
|
-
* Base class for the possible Tsurge migration variants.
|
|
520
|
-
*
|
|
521
|
-
* For example, this class exposes methods to conveniently create
|
|
522
|
-
* TypeScript programs, while also allowing migration authors to override.
|
|
523
|
-
*/
|
|
524
|
-
class TsurgeBaseMigration {
|
|
525
|
-
/**
|
|
526
|
-
* Advanced Tsurge users can override this method, but most of the time,
|
|
527
|
-
* overriding {@link prepareProgram} is more desirable.
|
|
528
|
-
*
|
|
529
|
-
* By default:
|
|
530
|
-
* - In 3P: Ngtsc programs are being created.
|
|
531
|
-
* - In 1P: Ngtsc or TS programs are created based on the Blaze target.
|
|
532
|
-
*/
|
|
533
|
-
createProgram(tsconfigAbsPath, fs) {
|
|
534
|
-
return createBaseProgramInfo(tsconfigAbsPath, fs);
|
|
535
|
-
}
|
|
536
|
-
// Optional function to prepare the base `ProgramInfo` even further,
|
|
537
|
-
// for the analyze and migrate phases. E.g. determining source files.
|
|
538
|
-
prepareProgram(info) {
|
|
539
|
-
const fullProgramSourceFiles = [...info.program.getSourceFiles()];
|
|
540
|
-
const sourceFiles = fullProgramSourceFiles.filter((f) => !f.isDeclarationFile &&
|
|
541
|
-
// Note `isShim` will work for the initial program, but for TCB programs, the shims are no longer annotated.
|
|
542
|
-
!checker.isShim(f) &&
|
|
543
|
-
!f.fileName.endsWith('.ngtypecheck.ts'));
|
|
544
|
-
// Sort it by length in reverse order (longest first). This speeds up lookups,
|
|
545
|
-
// since there's no need to keep going through the array once a match is found.
|
|
546
|
-
const sortedRootDirs = checker.getRootDirs(info.host, info.userOptions).sort((a, b) => b.length - a.length);
|
|
547
|
-
// TODO: Consider also following TS's logic here, finding the common source root.
|
|
548
|
-
// See: Program#getCommonSourceDirectory.
|
|
549
|
-
const primaryRoot = checker.absoluteFrom(info.userOptions.rootDir ?? sortedRootDirs.at(-1) ?? info.program.getCurrentDirectory());
|
|
550
|
-
return {
|
|
551
|
-
...info,
|
|
552
|
-
sourceFiles,
|
|
553
|
-
fullProgramSourceFiles,
|
|
554
|
-
sortedRootDirs,
|
|
555
|
-
projectRoot: primaryRoot,
|
|
556
|
-
};
|
|
557
|
-
}
|
|
558
|
-
}
|
|
559
|
-
|
|
560
|
-
/**
|
|
561
|
-
* A simpler variant of a {@link TsurgeComplexMigration} that does not
|
|
562
|
-
* fan-out into multiple workers per compilation unit to compute
|
|
563
|
-
* the final migration replacements.
|
|
564
|
-
*
|
|
565
|
-
* This is faster and less resource intensive as workers and TS programs
|
|
566
|
-
* are only ever created once.
|
|
567
|
-
*
|
|
568
|
-
* This is commonly the case when migrations are refactored to eagerly
|
|
569
|
-
* compute replacements in the analyze stage, and then leverage the
|
|
570
|
-
* global unit data to filter replacements that turned out to be "invalid".
|
|
571
|
-
*/
|
|
572
|
-
class TsurgeFunnelMigration extends TsurgeBaseMigration {
|
|
573
|
-
}
|
|
574
|
-
/**
|
|
575
|
-
* Complex variant of a `Tsurge` migration.
|
|
576
|
-
*
|
|
577
|
-
* For example, every analyze worker may contribute to a list of TS
|
|
578
|
-
* references that are later combined. The migrate phase can then compute actual
|
|
579
|
-
* file updates for all individual compilation units, leveraging the global metadata
|
|
580
|
-
* to e.g. see if there are any references from other compilation units that may be
|
|
581
|
-
* problematic and prevent migration of a given file.
|
|
582
|
-
*/
|
|
583
|
-
class TsurgeComplexMigration extends TsurgeBaseMigration {
|
|
584
|
-
}
|
|
585
|
-
|
|
586
|
-
/** A text replacement for the given file. */
|
|
587
|
-
class Replacement {
|
|
588
|
-
projectFile;
|
|
589
|
-
update;
|
|
590
|
-
constructor(projectFile, update) {
|
|
591
|
-
this.projectFile = projectFile;
|
|
592
|
-
this.update = update;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
/** An isolated text update that may be applied to a file. */
|
|
596
|
-
class TextUpdate {
|
|
597
|
-
data;
|
|
598
|
-
constructor(data) {
|
|
599
|
-
this.data = data;
|
|
600
|
-
}
|
|
601
|
-
}
|
|
602
|
-
|
|
603
|
-
/** Confirms that the given data `T` is serializable. */
|
|
604
|
-
function confirmAsSerializable(data) {
|
|
605
|
-
return data;
|
|
606
|
-
}
|
|
607
|
-
|
|
608
|
-
/**
|
|
609
|
-
* Gets a project file instance for the given file.
|
|
610
|
-
*
|
|
611
|
-
* Use this helper for dealing with project paths throughout your
|
|
612
|
-
* migration. The return type is serializable.
|
|
613
|
-
*
|
|
614
|
-
* See {@link ProjectFile}.
|
|
615
|
-
*/
|
|
616
|
-
function projectFile(file, { sortedRootDirs, projectRoot }) {
|
|
617
|
-
const fs = checker.getFileSystem();
|
|
618
|
-
const filePath = fs.resolve(typeof file === 'string' ? file : file.fileName);
|
|
619
|
-
// Sorted root directories are sorted longest to shortest. First match
|
|
620
|
-
// is the appropriate root directory for ID computation.
|
|
621
|
-
for (const rootDir of sortedRootDirs) {
|
|
622
|
-
if (!isWithinBasePath(fs, rootDir, filePath)) {
|
|
623
|
-
continue;
|
|
624
|
-
}
|
|
625
|
-
return {
|
|
626
|
-
id: fs.relative(rootDir, filePath),
|
|
627
|
-
rootRelativePath: fs.relative(projectRoot, filePath),
|
|
628
|
-
};
|
|
629
|
-
}
|
|
630
|
-
// E.g. project directory may be `src/`, but files may be looked up
|
|
631
|
-
// from `node_modules/`. This is fine, but in those cases, no root
|
|
632
|
-
// directory matches.
|
|
633
|
-
const rootRelativePath = fs.relative(projectRoot, filePath);
|
|
634
|
-
return {
|
|
635
|
-
id: rootRelativePath,
|
|
636
|
-
rootRelativePath: rootRelativePath,
|
|
637
|
-
};
|
|
638
|
-
}
|
|
639
|
-
/**
|
|
640
|
-
* Whether `path` is a descendant of the `base`?
|
|
641
|
-
* E.g. `a/b/c` is within `a/b` but not within `a/x`.
|
|
642
|
-
*/
|
|
643
|
-
function isWithinBasePath(fs, base, path) {
|
|
644
|
-
return checker.isLocalRelativePath(fs.relative(base, path));
|
|
645
|
-
}
|
|
646
|
-
|
|
647
|
-
/**
|
|
648
|
-
* Applies import manager changes, and writes them as replacements the
|
|
649
|
-
* given result array.
|
|
650
|
-
*/
|
|
651
|
-
function applyImportManagerChanges(importManager, replacements, sourceFiles, info) {
|
|
652
|
-
const { newImports, updatedImports, deletedImports } = importManager.finalize();
|
|
653
|
-
const printer = ts__default["default"].createPrinter({});
|
|
654
|
-
const pathToFile = new Map(sourceFiles.map((s) => [s.fileName, s]));
|
|
655
|
-
// Capture new imports
|
|
656
|
-
newImports.forEach((newImports, fileName) => {
|
|
657
|
-
newImports.forEach((newImport) => {
|
|
658
|
-
const printedImport = printer.printNode(ts__default["default"].EmitHint.Unspecified, newImport, pathToFile.get(fileName));
|
|
659
|
-
replacements.push(new Replacement(projectFile(checker.absoluteFrom(fileName), info), new TextUpdate({ position: 0, end: 0, toInsert: `${printedImport}\n` })));
|
|
660
|
-
});
|
|
661
|
-
});
|
|
662
|
-
// Capture updated imports
|
|
663
|
-
for (const [oldBindings, newBindings] of updatedImports.entries()) {
|
|
664
|
-
// The import will be generated as multi-line if it already is multi-line,
|
|
665
|
-
// or if the number of elements significantly increased and it previously
|
|
666
|
-
// consisted of very few specifiers.
|
|
667
|
-
const isMultiline = oldBindings.getText().includes('\n') ||
|
|
668
|
-
(newBindings.elements.length >= 6 && oldBindings.elements.length <= 3);
|
|
669
|
-
const hasSpaceBetweenBraces = oldBindings.getText().startsWith('{ ');
|
|
670
|
-
let formatFlags = ts__default["default"].ListFormat.NamedImportsOrExportsElements |
|
|
671
|
-
ts__default["default"].ListFormat.Indented |
|
|
672
|
-
ts__default["default"].ListFormat.Braces |
|
|
673
|
-
ts__default["default"].ListFormat.PreserveLines |
|
|
674
|
-
(isMultiline ? ts__default["default"].ListFormat.MultiLine : ts__default["default"].ListFormat.SingleLine);
|
|
675
|
-
if (hasSpaceBetweenBraces) {
|
|
676
|
-
formatFlags |= ts__default["default"].ListFormat.SpaceBetweenBraces;
|
|
677
|
-
}
|
|
678
|
-
else {
|
|
679
|
-
formatFlags &= ~ts__default["default"].ListFormat.SpaceBetweenBraces;
|
|
680
|
-
}
|
|
681
|
-
const printedBindings = printer.printList(formatFlags, newBindings.elements, oldBindings.getSourceFile());
|
|
682
|
-
replacements.push(new Replacement(projectFile(oldBindings.getSourceFile(), info), new TextUpdate({
|
|
683
|
-
position: oldBindings.getStart(),
|
|
684
|
-
end: oldBindings.getEnd(),
|
|
685
|
-
// TS uses four spaces as indent. We migrate to two spaces as we
|
|
686
|
-
// assume this to be more common.
|
|
687
|
-
toInsert: printedBindings.replace(/^ {4}/gm, ' '),
|
|
688
|
-
})));
|
|
689
|
-
}
|
|
690
|
-
// Update removed imports
|
|
691
|
-
for (const removedImport of deletedImports) {
|
|
692
|
-
replacements.push(new Replacement(projectFile(removedImport.getSourceFile(), info), new TextUpdate({
|
|
693
|
-
position: removedImport.getStart(),
|
|
694
|
-
end: removedImport.getEnd(),
|
|
695
|
-
toInsert: '',
|
|
696
|
-
})));
|
|
697
|
-
}
|
|
698
|
-
}
|
|
699
|
-
|
|
700
20
|
function getMemberName(member) {
|
|
701
21
|
if (member.name === undefined) {
|
|
702
22
|
return null;
|
|
@@ -1295,7 +615,7 @@ function identifyHostBindingReferences(node, programInfo, checker$1, reflector,
|
|
|
1295
615
|
readAstPath: ref.readAstPath,
|
|
1296
616
|
isObjectShorthandExpression: ref.isObjectShorthandExpression,
|
|
1297
617
|
isWrite: ref.isWrite,
|
|
1298
|
-
file: projectFile(ref.context.getSourceFile(), programInfo),
|
|
618
|
+
file: apply_import_manager.projectFile(ref.context.getSourceFile(), programInfo),
|
|
1299
619
|
hostPropertyNode: ref.context,
|
|
1300
620
|
},
|
|
1301
621
|
target: ref.targetField,
|
|
@@ -1395,8 +715,8 @@ function identifyTemplateReferences(programInfo, node, reflector, checker$1, eva
|
|
|
1395
715
|
readAstPath: res.readAstPath,
|
|
1396
716
|
node: res.context,
|
|
1397
717
|
isObjectShorthandExpression: res.isObjectShorthandExpression,
|
|
1398
|
-
originatingTsFile: projectFile(node.getSourceFile(), programInfo),
|
|
1399
|
-
templateFile: projectFile(checker.absoluteFrom(templateFilePath), programInfo),
|
|
718
|
+
originatingTsFile: apply_import_manager.projectFile(node.getSourceFile(), programInfo),
|
|
719
|
+
templateFile: apply_import_manager.projectFile(checker.absoluteFrom(templateFilePath), programInfo),
|
|
1400
720
|
isLikelyPartOfNarrowing: res.isLikelyNarrowed,
|
|
1401
721
|
isWrite: res.isWrite,
|
|
1402
722
|
},
|
|
@@ -1578,7 +898,7 @@ function identifyPotentialTypeScriptReference(node, programInfo, checker, knownF
|
|
|
1578
898
|
kind: exports.ReferenceKind.TsReference,
|
|
1579
899
|
from: {
|
|
1580
900
|
node,
|
|
1581
|
-
file: projectFile(node.getSourceFile(), programInfo),
|
|
901
|
+
file: apply_import_manager.projectFile(node.getSourceFile(), programInfo),
|
|
1582
902
|
isWrite: isWriteReference,
|
|
1583
903
|
isPartOfElementBinding: ts__default["default"].isBindingElement(node.parent),
|
|
1584
904
|
},
|
|
@@ -1642,7 +962,7 @@ function createFindAllSourceFileReferencesVisitor(programInfo, checker, reflecto
|
|
|
1642
962
|
result.references.push({
|
|
1643
963
|
kind: exports.ReferenceKind.TsClassTypeReference,
|
|
1644
964
|
from: {
|
|
1645
|
-
file: projectFile(partialDirectiveInCatalyst.referenceNode.getSourceFile(), programInfo),
|
|
965
|
+
file: apply_import_manager.projectFile(partialDirectiveInCatalyst.referenceNode.getSourceFile(), programInfo),
|
|
1646
966
|
node: partialDirectiveInCatalyst.referenceNode,
|
|
1647
967
|
},
|
|
1648
968
|
isPartialReference: true,
|
|
@@ -1660,46 +980,13 @@ function createFindAllSourceFileReferencesVisitor(programInfo, checker, reflecto
|
|
|
1660
980
|
};
|
|
1661
981
|
}
|
|
1662
982
|
|
|
1663
|
-
/**
|
|
1664
|
-
* Synchronously combines unit data for the given migration.
|
|
1665
|
-
*
|
|
1666
|
-
* Note: This helper is useful for testing and execution of
|
|
1667
|
-
* Tsurge migrations in non-batchable environments. In general,
|
|
1668
|
-
* prefer parallel execution of combining via e.g. Beam combiners.
|
|
1669
|
-
*/
|
|
1670
|
-
async function synchronouslyCombineUnitData(migration, unitDatas) {
|
|
1671
|
-
if (unitDatas.length === 0) {
|
|
1672
|
-
return null;
|
|
1673
|
-
}
|
|
1674
|
-
if (unitDatas.length === 1) {
|
|
1675
|
-
return unitDatas[0];
|
|
1676
|
-
}
|
|
1677
|
-
let combined = unitDatas[0];
|
|
1678
|
-
for (let i = 1; i < unitDatas.length; i++) {
|
|
1679
|
-
const other = unitDatas[i];
|
|
1680
|
-
combined = await migration.combine(combined, other);
|
|
1681
|
-
}
|
|
1682
|
-
return combined;
|
|
1683
|
-
}
|
|
1684
|
-
|
|
1685
|
-
exports.DevkitMigrationFilesystem = DevkitMigrationFilesystem;
|
|
1686
|
-
exports.Replacement = Replacement;
|
|
1687
|
-
exports.TextUpdate = TextUpdate;
|
|
1688
|
-
exports.TsurgeComplexMigration = TsurgeComplexMigration;
|
|
1689
|
-
exports.TsurgeFunnelMigration = TsurgeFunnelMigration;
|
|
1690
|
-
exports.applyImportManagerChanges = applyImportManagerChanges;
|
|
1691
|
-
exports.confirmAsSerializable = confirmAsSerializable;
|
|
1692
|
-
exports.createBaseProgramInfo = createBaseProgramInfo;
|
|
1693
983
|
exports.createFindAllSourceFileReferencesVisitor = createFindAllSourceFileReferencesVisitor;
|
|
1694
984
|
exports.getBindingElementDeclaration = getBindingElementDeclaration;
|
|
1695
985
|
exports.getMemberName = getMemberName;
|
|
1696
|
-
exports.groupReplacementsByFile = groupReplacementsByFile;
|
|
1697
986
|
exports.isHostBindingReference = isHostBindingReference;
|
|
1698
987
|
exports.isInputContainerNode = isInputContainerNode;
|
|
1699
988
|
exports.isTemplateReference = isTemplateReference;
|
|
1700
989
|
exports.isTsClassTypeReference = isTsClassTypeReference;
|
|
1701
990
|
exports.isTsReference = isTsReference;
|
|
1702
|
-
exports.projectFile = projectFile;
|
|
1703
|
-
exports.synchronouslyCombineUnitData = synchronouslyCombineUnitData;
|
|
1704
991
|
exports.traverseAccess = traverseAccess;
|
|
1705
992
|
exports.unwrapParent = unwrapParent;
|