@angular/core 20.0.0-next.1 → 20.0.0-next.3
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/fesm2022/core.mjs +770 -2144
- package/fesm2022/core.mjs.map +1 -1
- package/fesm2022/primitives/di.mjs +3 -2
- package/fesm2022/primitives/di.mjs.map +1 -1
- package/fesm2022/primitives/event-dispatch.mjs +2 -589
- package/fesm2022/primitives/event-dispatch.mjs.map +1 -1
- package/fesm2022/primitives/signals.mjs +44 -13
- package/fesm2022/primitives/signals.mjs.map +1 -1
- package/fesm2022/rxjs-interop.mjs +7 -39
- package/fesm2022/rxjs-interop.mjs.map +1 -1
- package/fesm2022/testing.mjs +116 -143
- package/fesm2022/testing.mjs.map +1 -1
- package/fesm2022/weak_ref-DrMdAIDh.mjs +12 -0
- package/fesm2022/weak_ref-DrMdAIDh.mjs.map +1 -0
- package/index.d.ts +14366 -15214
- package/navigation_types.d-u4EOrrdZ.d.ts +121 -0
- package/package.json +2 -2
- package/primitives/di/index.d.ts +66 -59
- package/primitives/event-dispatch/index.d.ts +205 -309
- package/primitives/signals/index.d.ts +161 -195
- package/rxjs-interop/index.d.ts +71 -100
- package/schematics/bundles/{apply_import_manager-e2a7fe5b.js → apply_import_manager-BXQEjo09.js} +15 -19
- package/schematics/bundles/{checker-af521da6.js → checker-BHb19MHt.js} +3695 -1175
- package/schematics/bundles/cleanup-unused-imports.js +56 -89
- package/schematics/bundles/{compiler_host-5a29293c.js → compiler_host-Bk3repE2.js} +19 -23
- package/schematics/bundles/control-flow-migration.js +81 -38
- package/schematics/bundles/{imports-047fbbc8.js → imports-CIX-JgAN.js} +9 -14
- package/schematics/bundles/{index-1bef3025.js → index-BL9kAIe5.js} +62 -66
- package/schematics/bundles/{program-a449f9bf.js → index-I8VbxQcO.js} +1508 -3178
- package/schematics/bundles/inject-flags.js +147 -0
- package/schematics/bundles/inject-migration.js +121 -127
- package/schematics/bundles/{leading_space-f8944434.js → leading_space-D9nQ8UQC.js} +1 -1
- package/schematics/bundles/{migrate_ts_type_references-2a3e9e6b.js → migrate_ts_type_references-KlOTWeDl.js} +121 -126
- package/schematics/bundles/{ng_decorators-b0d8b324.js → ng_decorators-DznZ5jMl.js} +4 -8
- package/schematics/bundles/{nodes-7758dbf6.js → nodes-B16H9JUd.js} +2 -6
- package/schematics/bundles/output-migration.js +94 -128
- package/schematics/bundles/{project_tsconfig_paths-b558633b.js → project_tsconfig_paths-CDVxT6Ov.js} +1 -1
- package/schematics/bundles/{property_name-ac18447e.js → property_name-BBwFuqMe.js} +3 -7
- package/schematics/bundles/route-lazy-loading.js +35 -41
- package/schematics/bundles/{project_paths-17dc204d.js → run_in_devkit-C0JPtK2u.js} +283 -216
- package/schematics/bundles/self-closing-tags-migration.js +55 -91
- package/schematics/bundles/signal-input-migration.js +121 -156
- package/schematics/bundles/signal-queries-migration.js +119 -154
- package/schematics/bundles/signals.js +12 -14
- package/schematics/bundles/standalone-migration.js +180 -200
- package/schematics/bundles/symbol-VPWguRxr.js +25 -0
- package/schematics/bundles/test-bed-get.js +98 -0
- package/schematics/migrations.json +8 -14
- package/testing/index.d.ts +289 -471
- package/weak_ref.d-ttyj86RV.d.ts +9 -0
- package/schematics/bundles/explicit-standalone-flag.js +0 -184
- package/schematics/bundles/index-ef1bffbb.js +0 -30
- package/schematics/bundles/pending-tasks.js +0 -103
- package/schematics/bundles/provide-initializer.js +0 -186
|
@@ -1,31 +1,25 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
/**
|
|
3
|
-
* @license Angular v20.0.0-next.
|
|
3
|
+
* @license Angular v20.0.0-next.3
|
|
4
4
|
* (c) 2010-2025 Google LLC. https://angular.io/
|
|
5
5
|
* License: MIT
|
|
6
6
|
*/
|
|
7
7
|
'use strict';
|
|
8
8
|
|
|
9
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
10
|
-
|
|
11
9
|
var schematics = require('@angular-devkit/schematics');
|
|
12
10
|
var p = require('path');
|
|
13
|
-
var compiler_host = require('./compiler_host-
|
|
11
|
+
var compiler_host = require('./compiler_host-Bk3repE2.js');
|
|
14
12
|
var ts = require('typescript');
|
|
15
|
-
var ng_decorators = require('./ng_decorators-
|
|
16
|
-
var imports = require('./imports-
|
|
17
|
-
var nodes = require('./nodes-
|
|
18
|
-
var leading_space = require('./leading_space-
|
|
19
|
-
require('./checker-
|
|
13
|
+
var ng_decorators = require('./ng_decorators-DznZ5jMl.js');
|
|
14
|
+
var imports = require('./imports-CIX-JgAN.js');
|
|
15
|
+
var nodes = require('./nodes-B16H9JUd.js');
|
|
16
|
+
var leading_space = require('./leading_space-D9nQ8UQC.js');
|
|
17
|
+
require('./checker-BHb19MHt.js');
|
|
20
18
|
require('os');
|
|
21
19
|
require('fs');
|
|
22
20
|
require('module');
|
|
23
21
|
require('url');
|
|
24
22
|
|
|
25
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
26
|
-
|
|
27
|
-
var ts__default = /*#__PURE__*/_interopDefaultLegacy(ts);
|
|
28
|
-
|
|
29
23
|
/*!
|
|
30
24
|
* @license
|
|
31
25
|
* Copyright Google LLC All Rights Reserved.
|
|
@@ -53,12 +47,12 @@ const DI_PARAM_SYMBOLS = new Set([
|
|
|
53
47
|
]);
|
|
54
48
|
/** Kinds of nodes which aren't injectable when set as a type of a parameter. */
|
|
55
49
|
const UNINJECTABLE_TYPE_KINDS = new Set([
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
50
|
+
ts.SyntaxKind.TrueKeyword,
|
|
51
|
+
ts.SyntaxKind.FalseKeyword,
|
|
52
|
+
ts.SyntaxKind.NumberKeyword,
|
|
53
|
+
ts.SyntaxKind.StringKeyword,
|
|
54
|
+
ts.SyntaxKind.NullKeyword,
|
|
55
|
+
ts.SyntaxKind.VoidKeyword,
|
|
62
56
|
]);
|
|
63
57
|
/**
|
|
64
58
|
* Finds the necessary information for the `inject` migration in a file.
|
|
@@ -83,11 +77,11 @@ function analyzeFile(sourceFile, localTypeChecker, options) {
|
|
|
83
77
|
sourceFile.forEachChild(function walk(node) {
|
|
84
78
|
// Skip import declarations since they can throw off the identifier
|
|
85
79
|
// could below and we don't care about them in this migration.
|
|
86
|
-
if (
|
|
80
|
+
if (ts.isImportDeclaration(node)) {
|
|
87
81
|
return;
|
|
88
82
|
}
|
|
89
|
-
if (
|
|
90
|
-
const closestConstructor = nodes.closestNode(node,
|
|
83
|
+
if (ts.isParameter(node)) {
|
|
84
|
+
const closestConstructor = nodes.closestNode(node, ts.isConstructorDeclaration);
|
|
91
85
|
// Visiting the same parameters that we're about to remove can throw off the reference
|
|
92
86
|
// counting logic below. If we run into an initializer, we always visit its initializer
|
|
93
87
|
// and optionally visit the modifiers/decorators if it's not due to be deleted. Note that
|
|
@@ -105,7 +99,7 @@ function analyzeFile(sourceFile, localTypeChecker, options) {
|
|
|
105
99
|
}
|
|
106
100
|
return;
|
|
107
101
|
}
|
|
108
|
-
if (
|
|
102
|
+
if (ts.isIdentifier(node) && importsToSpecifiers.size > 0) {
|
|
109
103
|
let symbol;
|
|
110
104
|
for (const [name, specifier] of importsToSpecifiers) {
|
|
111
105
|
const localName = (specifier.propertyName || specifier.name).text;
|
|
@@ -125,11 +119,11 @@ function analyzeFile(sourceFile, localTypeChecker, options) {
|
|
|
125
119
|
}
|
|
126
120
|
}
|
|
127
121
|
}
|
|
128
|
-
else if (
|
|
129
|
-
const decorators = ng_decorators.getAngularDecorators(localTypeChecker,
|
|
130
|
-
const isAbstract = !!node.modifiers?.some((m) => m.kind ===
|
|
122
|
+
else if (ts.isClassDeclaration(node)) {
|
|
123
|
+
const decorators = ng_decorators.getAngularDecorators(localTypeChecker, ts.getDecorators(node) || []);
|
|
124
|
+
const isAbstract = !!node.modifiers?.some((m) => m.kind === ts.SyntaxKind.AbstractKeyword);
|
|
131
125
|
const supportsDI = decorators.some((dec) => DECORATORS_SUPPORTING_DI.has(dec.name));
|
|
132
|
-
const constructorNode = node.members.find((member) =>
|
|
126
|
+
const constructorNode = node.members.find((member) => ts.isConstructorDeclaration(member) &&
|
|
133
127
|
member.body != null &&
|
|
134
128
|
member.parameters.length > 0);
|
|
135
129
|
// Basic check to determine if all parameters are injectable. This isn't exhaustive, but it
|
|
@@ -139,7 +133,7 @@ function analyzeFile(sourceFile, localTypeChecker, options) {
|
|
|
139
133
|
if (!param.type || !UNINJECTABLE_TYPE_KINDS.has(param.type.kind)) {
|
|
140
134
|
return true;
|
|
141
135
|
}
|
|
142
|
-
return ng_decorators.getAngularDecorators(localTypeChecker,
|
|
136
|
+
return ng_decorators.getAngularDecorators(localTypeChecker, ts.getDecorators(param) || []).some((dec) => dec.name === 'Inject' || dec.name === 'Attribute');
|
|
143
137
|
});
|
|
144
138
|
// Don't migrate abstract classes by default, because
|
|
145
139
|
// their parameters aren't guaranteed to be injectable.
|
|
@@ -171,7 +165,7 @@ function getConstructorUnusedParameters(declaration, localTypeChecker, removedSt
|
|
|
171
165
|
const unusedParams = new Set();
|
|
172
166
|
// Prepare the parameters for quicker checks further down.
|
|
173
167
|
for (const param of declaration.parameters) {
|
|
174
|
-
if (
|
|
168
|
+
if (ts.isIdentifier(param.name)) {
|
|
175
169
|
topLevelParameters.add(param);
|
|
176
170
|
topLevelParameterNames.add(param.name.text);
|
|
177
171
|
}
|
|
@@ -181,10 +175,10 @@ function getConstructorUnusedParameters(declaration, localTypeChecker, removedSt
|
|
|
181
175
|
}
|
|
182
176
|
const analyze = (node) => {
|
|
183
177
|
// Don't descend into statements that were removed already.
|
|
184
|
-
if (
|
|
178
|
+
if (ts.isStatement(node) && removedStatements.has(node)) {
|
|
185
179
|
return;
|
|
186
180
|
}
|
|
187
|
-
if (!
|
|
181
|
+
if (!ts.isIdentifier(node) || !topLevelParameterNames.has(node.text)) {
|
|
188
182
|
node.forEachChild(analyze);
|
|
189
183
|
return;
|
|
190
184
|
}
|
|
@@ -194,12 +188,12 @@ function getConstructorUnusedParameters(declaration, localTypeChecker, removedSt
|
|
|
194
188
|
return;
|
|
195
189
|
}
|
|
196
190
|
localTypeChecker.getSymbolAtLocation(node)?.declarations?.forEach((decl) => {
|
|
197
|
-
if (
|
|
191
|
+
if (ts.isParameter(decl) && topLevelParameters.has(decl)) {
|
|
198
192
|
accessedTopLevelParameters.add(decl);
|
|
199
193
|
}
|
|
200
|
-
if (
|
|
194
|
+
if (ts.isShorthandPropertyAssignment(decl)) {
|
|
201
195
|
const symbol = localTypeChecker.getShorthandAssignmentValueSymbol(decl);
|
|
202
|
-
if (symbol && symbol.valueDeclaration &&
|
|
196
|
+
if (symbol && symbol.valueDeclaration && ts.isParameter(symbol.valueDeclaration)) {
|
|
203
197
|
accessedTopLevelParameters.add(symbol.valueDeclaration);
|
|
204
198
|
}
|
|
205
199
|
}
|
|
@@ -230,15 +224,15 @@ function getSuperParameters(declaration, superCall, localTypeChecker) {
|
|
|
230
224
|
const topLevelParameterNames = new Set();
|
|
231
225
|
// Prepare the parameters for quicker checks further down.
|
|
232
226
|
for (const param of declaration.parameters) {
|
|
233
|
-
if (
|
|
227
|
+
if (ts.isIdentifier(param.name)) {
|
|
234
228
|
topLevelParameters.add(param);
|
|
235
229
|
topLevelParameterNames.add(param.name.text);
|
|
236
230
|
}
|
|
237
231
|
}
|
|
238
232
|
superCall.forEachChild(function walk(node) {
|
|
239
|
-
if (
|
|
233
|
+
if (ts.isIdentifier(node) && topLevelParameterNames.has(node.text)) {
|
|
240
234
|
localTypeChecker.getSymbolAtLocation(node)?.declarations?.forEach((decl) => {
|
|
241
|
-
if (
|
|
235
|
+
if (ts.isParameter(decl) && topLevelParameters.has(decl)) {
|
|
242
236
|
usedParams.add(decl);
|
|
243
237
|
}
|
|
244
238
|
});
|
|
@@ -262,13 +256,13 @@ function parameterReferencesOtherParameters(param, allParameters, localTypeCheck
|
|
|
262
256
|
}
|
|
263
257
|
const paramNames = new Set();
|
|
264
258
|
for (const current of allParameters) {
|
|
265
|
-
if (current !== param &&
|
|
259
|
+
if (current !== param && ts.isIdentifier(current.name)) {
|
|
266
260
|
paramNames.add(current.name.text);
|
|
267
261
|
}
|
|
268
262
|
}
|
|
269
263
|
let result = false;
|
|
270
264
|
const analyze = (node) => {
|
|
271
|
-
if (
|
|
265
|
+
if (ts.isIdentifier(node) && paramNames.has(node.text) && !isAccessedViaThis(node)) {
|
|
272
266
|
const symbol = localTypeChecker.getSymbolAtLocation(node);
|
|
273
267
|
const referencesOtherParam = symbol?.declarations?.some((decl) => {
|
|
274
268
|
return allParameters.includes(decl);
|
|
@@ -286,47 +280,47 @@ function parameterReferencesOtherParameters(param, allParameters, localTypeCheck
|
|
|
286
280
|
}
|
|
287
281
|
/** Checks whether a parameter node declares a property on its class. */
|
|
288
282
|
function parameterDeclaresProperty(node) {
|
|
289
|
-
return !!node.modifiers?.some(({ kind }) => kind ===
|
|
290
|
-
kind ===
|
|
291
|
-
kind ===
|
|
292
|
-
kind ===
|
|
283
|
+
return !!node.modifiers?.some(({ kind }) => kind === ts.SyntaxKind.PublicKeyword ||
|
|
284
|
+
kind === ts.SyntaxKind.PrivateKeyword ||
|
|
285
|
+
kind === ts.SyntaxKind.ProtectedKeyword ||
|
|
286
|
+
kind === ts.SyntaxKind.ReadonlyKeyword);
|
|
293
287
|
}
|
|
294
288
|
/** Checks whether a type node is nullable. */
|
|
295
289
|
function isNullableType(node) {
|
|
296
290
|
// Apparently `foo: null` is `Parameter<TypeNode<NullKeyword>>`,
|
|
297
291
|
// while `foo: undefined` is `Parameter<UndefinedKeyword>`...
|
|
298
|
-
if (node.kind ===
|
|
292
|
+
if (node.kind === ts.SyntaxKind.UndefinedKeyword || node.kind === ts.SyntaxKind.VoidKeyword) {
|
|
299
293
|
return true;
|
|
300
294
|
}
|
|
301
|
-
if (
|
|
302
|
-
return node.literal.kind ===
|
|
295
|
+
if (ts.isLiteralTypeNode(node)) {
|
|
296
|
+
return node.literal.kind === ts.SyntaxKind.NullKeyword;
|
|
303
297
|
}
|
|
304
|
-
if (
|
|
298
|
+
if (ts.isUnionTypeNode(node)) {
|
|
305
299
|
return node.types.some(isNullableType);
|
|
306
300
|
}
|
|
307
301
|
return false;
|
|
308
302
|
}
|
|
309
303
|
/** Checks whether a type node has generic arguments. */
|
|
310
304
|
function hasGenerics(node) {
|
|
311
|
-
if (
|
|
305
|
+
if (ts.isTypeReferenceNode(node)) {
|
|
312
306
|
return node.typeArguments != null && node.typeArguments.length > 0;
|
|
313
307
|
}
|
|
314
|
-
if (
|
|
308
|
+
if (ts.isUnionTypeNode(node)) {
|
|
315
309
|
return node.types.some(hasGenerics);
|
|
316
310
|
}
|
|
317
311
|
return false;
|
|
318
312
|
}
|
|
319
313
|
/** Checks whether an identifier is accessed through `this`, e.g. `this.<some identifier>`. */
|
|
320
314
|
function isAccessedViaThis(node) {
|
|
321
|
-
return (
|
|
322
|
-
node.parent.expression.kind ===
|
|
315
|
+
return (ts.isPropertyAccessExpression(node.parent) &&
|
|
316
|
+
node.parent.expression.kind === ts.SyntaxKind.ThisKeyword &&
|
|
323
317
|
node.parent.name === node);
|
|
324
318
|
}
|
|
325
319
|
/** Finds a `super` call inside of a specific node. */
|
|
326
320
|
function findSuperCall(root) {
|
|
327
321
|
let result = null;
|
|
328
322
|
root.forEachChild(function find(node) {
|
|
329
|
-
if (
|
|
323
|
+
if (ts.isCallExpression(node) && node.expression.kind === ts.SyntaxKind.SuperKeyword) {
|
|
330
324
|
result = node;
|
|
331
325
|
}
|
|
332
326
|
else if (result === null) {
|
|
@@ -367,9 +361,9 @@ function findUninitializedPropertiesToCombine(node, constructor, localTypeChecke
|
|
|
367
361
|
let toHoist = [];
|
|
368
362
|
const membersToDeclarations = new Map();
|
|
369
363
|
for (const member of node.members) {
|
|
370
|
-
if (
|
|
364
|
+
if (ts.isPropertyDeclaration(member) &&
|
|
371
365
|
!member.initializer &&
|
|
372
|
-
!
|
|
366
|
+
!ts.isComputedPropertyName(member.name)) {
|
|
373
367
|
membersToDeclarations.set(member.name.text, member);
|
|
374
368
|
}
|
|
375
369
|
}
|
|
@@ -449,21 +443,21 @@ function shouldCombineInInitializationOrder(toCombine, constructor) {
|
|
|
449
443
|
// Collect the name of constructor parameters that declare new properties.
|
|
450
444
|
// These can be ignored since they'll be hoisted above other properties.
|
|
451
445
|
constructor.parameters.forEach((param) => {
|
|
452
|
-
if (parameterDeclaresProperty(param) &&
|
|
446
|
+
if (parameterDeclaresProperty(param) && ts.isIdentifier(param.name)) {
|
|
453
447
|
injectedMemberNames.add(param.name.text);
|
|
454
448
|
}
|
|
455
449
|
});
|
|
456
450
|
// Collect the names of the properties being combined. We should only reorder
|
|
457
451
|
// the properties if at least one of them refers to another one.
|
|
458
452
|
toCombine.forEach(({ declaration: { name } }) => {
|
|
459
|
-
if (
|
|
453
|
+
if (ts.isStringLiteralLike(name) || ts.isIdentifier(name)) {
|
|
460
454
|
combinedMemberNames.add(name.text);
|
|
461
455
|
}
|
|
462
456
|
});
|
|
463
457
|
// Visit all the initializers and check all the property reads in the form of `this.<name>`.
|
|
464
458
|
// Skip over the ones referring to injected parameters since they're going to be hoisted.
|
|
465
459
|
const walkInitializer = (node) => {
|
|
466
|
-
if (
|
|
460
|
+
if (ts.isPropertyAccessExpression(node) && node.expression.kind === ts.SyntaxKind.ThisKeyword) {
|
|
467
461
|
if (combinedMemberNames.has(node.name.text)) {
|
|
468
462
|
combinedMemberReferenceCount++;
|
|
469
463
|
}
|
|
@@ -500,20 +494,20 @@ function getMemberInitializers(constructor) {
|
|
|
500
494
|
// Only look at top-level constructor statements.
|
|
501
495
|
for (const node of constructor.body.statements) {
|
|
502
496
|
// Only look for statements in the form of `this.<name> = <expr>;` or `this[<name>] = <expr>;`.
|
|
503
|
-
if (!
|
|
504
|
-
!
|
|
505
|
-
node.expression.operatorToken.kind !==
|
|
506
|
-
(!
|
|
507
|
-
!
|
|
508
|
-
node.expression.left.expression.kind !==
|
|
497
|
+
if (!ts.isExpressionStatement(node) ||
|
|
498
|
+
!ts.isBinaryExpression(node.expression) ||
|
|
499
|
+
node.expression.operatorToken.kind !== ts.SyntaxKind.EqualsToken ||
|
|
500
|
+
(!ts.isPropertyAccessExpression(node.expression.left) &&
|
|
501
|
+
!ts.isElementAccessExpression(node.expression.left)) ||
|
|
502
|
+
node.expression.left.expression.kind !== ts.SyntaxKind.ThisKeyword) {
|
|
509
503
|
continue;
|
|
510
504
|
}
|
|
511
505
|
let name;
|
|
512
|
-
if (
|
|
506
|
+
if (ts.isPropertyAccessExpression(node.expression.left)) {
|
|
513
507
|
name = node.expression.left.name.text;
|
|
514
508
|
}
|
|
515
|
-
else if (
|
|
516
|
-
name =
|
|
509
|
+
else if (ts.isElementAccessExpression(node.expression.left)) {
|
|
510
|
+
name = ts.isStringLiteralLike(node.expression.left.argumentExpression)
|
|
517
511
|
? node.expression.left.argumentExpression.text
|
|
518
512
|
: undefined;
|
|
519
513
|
}
|
|
@@ -547,7 +541,7 @@ function hasLocalReferences(root, constructor, localTypeChecker) {
|
|
|
547
541
|
// this.bar = this.foo.getFoo();
|
|
548
542
|
// }
|
|
549
543
|
// ```
|
|
550
|
-
if (
|
|
544
|
+
if (ts.isIdentifier(node) && !isAccessedViaThis(node)) {
|
|
551
545
|
const declarations = localTypeChecker.getSymbolAtLocation(node)?.declarations;
|
|
552
546
|
const isReferencingLocalSymbol = declarations?.some((decl) =>
|
|
553
547
|
// The source file check is a bit redundant since the type checker
|
|
@@ -579,9 +573,9 @@ function isInsideInlineFunction(startNode, boundary) {
|
|
|
579
573
|
if (current === boundary) {
|
|
580
574
|
return false;
|
|
581
575
|
}
|
|
582
|
-
if (
|
|
583
|
-
|
|
584
|
-
|
|
576
|
+
if (ts.isFunctionDeclaration(current) ||
|
|
577
|
+
ts.isFunctionExpression(current) ||
|
|
578
|
+
ts.isArrowFunction(current)) {
|
|
585
579
|
return true;
|
|
586
580
|
}
|
|
587
581
|
current = current.parent;
|
|
@@ -610,7 +604,7 @@ function migrateFile(sourceFile, options) {
|
|
|
610
604
|
if (analysis === null || analysis.classes.length === 0) {
|
|
611
605
|
return [];
|
|
612
606
|
}
|
|
613
|
-
const printer =
|
|
607
|
+
const printer = ts.createPrinter();
|
|
614
608
|
const tracker = new compiler_host.ChangeTracker(printer);
|
|
615
609
|
analysis.classes.forEach(({ node, constructor, superCall }) => {
|
|
616
610
|
const memberIndentation = leading_space.getLeadingLineWhitespaceOfNode(node.members[0]);
|
|
@@ -667,7 +661,7 @@ function migrateClass(node, constructor, superCall, options, memberIndentation,
|
|
|
667
661
|
// Delete all of the constructor overloads since below we're either going to
|
|
668
662
|
// remove the implementation, or we're going to delete all of the parameters.
|
|
669
663
|
for (const member of node.members) {
|
|
670
|
-
if (
|
|
664
|
+
if (ts.isConstructorDeclaration(member) && member !== constructor) {
|
|
671
665
|
removedMembers.add(member);
|
|
672
666
|
tracker.removeNode(member, true);
|
|
673
667
|
}
|
|
@@ -751,7 +745,7 @@ function migrateClass(node, constructor, superCall, options, memberIndentation,
|
|
|
751
745
|
* @param afterSuper Statements to be added after the `super` call.
|
|
752
746
|
*/
|
|
753
747
|
function migrateParameter(node, options, localTypeChecker, printer, tracker, superCall, usedInSuper, usedInConstructor, usesOtherParams, memberIndentation, innerIndentation, prependToConstructor, propsToAdd, afterSuper) {
|
|
754
|
-
if (!
|
|
748
|
+
if (!ts.isIdentifier(node.name)) {
|
|
755
749
|
return;
|
|
756
750
|
}
|
|
757
751
|
const name = node.name.text;
|
|
@@ -762,14 +756,14 @@ function migrateParameter(node, options, localTypeChecker, printer, tracker, sup
|
|
|
762
756
|
// We can't initialize the property if it's referenced within a `super` call or it references
|
|
763
757
|
// other parameters. See the logic further below for the initialization.
|
|
764
758
|
const canInitialize = !usedInSuper && !usesOtherParams;
|
|
765
|
-
const prop =
|
|
759
|
+
const prop = ts.factory.createPropertyDeclaration(cloneModifiers(node.modifiers?.filter((modifier) => {
|
|
766
760
|
// Strip out the DI decorators, as well as `public` which is redundant.
|
|
767
|
-
return !
|
|
761
|
+
return !ts.isDecorator(modifier) && modifier.kind !== ts.SyntaxKind.PublicKeyword;
|
|
768
762
|
})), name,
|
|
769
763
|
// Don't add the question token to private properties since it won't affect interface implementation.
|
|
770
|
-
node.modifiers?.some((modifier) => modifier.kind ===
|
|
764
|
+
node.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.PrivateKeyword)
|
|
771
765
|
? undefined
|
|
772
|
-
: node.questionToken, canInitialize ? undefined : node.type, canInitialize ?
|
|
766
|
+
: node.questionToken, canInitialize ? undefined : node.type, canInitialize ? ts.factory.createIdentifier(PLACEHOLDER) : undefined);
|
|
773
767
|
propsToAdd.push(memberIndentation +
|
|
774
768
|
replaceNodePlaceholder(node.getSourceFile(), prop, replacementCall, printer));
|
|
775
769
|
}
|
|
@@ -823,7 +817,7 @@ function migrateParameter(node, options, localTypeChecker, printer, tracker, sup
|
|
|
823
817
|
function createInjectReplacementCall(param, options, localTypeChecker, printer, tracker) {
|
|
824
818
|
const moduleName = '@angular/core';
|
|
825
819
|
const sourceFile = param.getSourceFile();
|
|
826
|
-
const decorators = ng_decorators.getAngularDecorators(localTypeChecker,
|
|
820
|
+
const decorators = ng_decorators.getAngularDecorators(localTypeChecker, ts.getDecorators(param) || []);
|
|
827
821
|
const literalProps = [];
|
|
828
822
|
const type = param.type;
|
|
829
823
|
let injectedType = '';
|
|
@@ -832,11 +826,11 @@ function createInjectReplacementCall(param, options, localTypeChecker, printer,
|
|
|
832
826
|
if (type) {
|
|
833
827
|
// Remove the type arguments from generic type references, because
|
|
834
828
|
// they'll be specified as type arguments to `inject()`.
|
|
835
|
-
if (
|
|
829
|
+
if (ts.isTypeReferenceNode(type) && type.typeArguments && type.typeArguments.length > 0) {
|
|
836
830
|
injectedType = type.typeName.getText();
|
|
837
831
|
}
|
|
838
|
-
else if (
|
|
839
|
-
injectedType = (type.types.find((t) => !
|
|
832
|
+
else if (ts.isUnionTypeNode(type)) {
|
|
833
|
+
injectedType = (type.types.find((t) => !ts.isLiteralTypeNode(t)) || type.types[0]).getText();
|
|
840
834
|
}
|
|
841
835
|
else {
|
|
842
836
|
injectedType = type.getText();
|
|
@@ -860,23 +854,23 @@ function createInjectReplacementCall(param, options, localTypeChecker, printer,
|
|
|
860
854
|
case 'Attribute':
|
|
861
855
|
if (firstArg) {
|
|
862
856
|
const constructorRef = tracker.addImport(sourceFile, 'HostAttributeToken', moduleName);
|
|
863
|
-
const expression =
|
|
864
|
-
injectedType = printer.printNode(
|
|
857
|
+
const expression = ts.factory.createNewExpression(constructorRef, undefined, [firstArg]);
|
|
858
|
+
injectedType = printer.printNode(ts.EmitHint.Unspecified, expression, sourceFile);
|
|
865
859
|
typeArguments = undefined;
|
|
866
860
|
}
|
|
867
861
|
break;
|
|
868
862
|
case 'Optional':
|
|
869
863
|
hasOptionalDecorator = true;
|
|
870
|
-
literalProps.push(
|
|
864
|
+
literalProps.push(ts.factory.createPropertyAssignment('optional', ts.factory.createTrue()));
|
|
871
865
|
break;
|
|
872
866
|
case 'SkipSelf':
|
|
873
|
-
literalProps.push(
|
|
867
|
+
literalProps.push(ts.factory.createPropertyAssignment('skipSelf', ts.factory.createTrue()));
|
|
874
868
|
break;
|
|
875
869
|
case 'Self':
|
|
876
|
-
literalProps.push(
|
|
870
|
+
literalProps.push(ts.factory.createPropertyAssignment('self', ts.factory.createTrue()));
|
|
877
871
|
break;
|
|
878
872
|
case 'Host':
|
|
879
|
-
literalProps.push(
|
|
873
|
+
literalProps.push(ts.factory.createPropertyAssignment('host', ts.factory.createTrue()));
|
|
880
874
|
break;
|
|
881
875
|
}
|
|
882
876
|
}
|
|
@@ -884,22 +878,22 @@ function createInjectReplacementCall(param, options, localTypeChecker, printer,
|
|
|
884
878
|
// Since the value gets passed through directly anyway, we generate the call using a placeholder
|
|
885
879
|
// which we then replace with the raw text of the `TypeNode`.
|
|
886
880
|
const injectRef = tracker.addImport(param.getSourceFile(), 'inject', moduleName);
|
|
887
|
-
const args = [
|
|
881
|
+
const args = [ts.factory.createIdentifier(PLACEHOLDER)];
|
|
888
882
|
if (literalProps.length > 0) {
|
|
889
|
-
args.push(
|
|
883
|
+
args.push(ts.factory.createObjectLiteralExpression(literalProps));
|
|
890
884
|
}
|
|
891
|
-
let expression =
|
|
885
|
+
let expression = ts.factory.createCallExpression(injectRef, typeArguments, args);
|
|
892
886
|
if (hasOptionalDecorator && options.nonNullableOptional) {
|
|
893
887
|
const hasNullableType = param.questionToken != null || (param.type != null && isNullableType(param.type));
|
|
894
888
|
// Only wrap the expression if the type wasn't already nullable.
|
|
895
889
|
// If it was, the app was likely accounting for it already.
|
|
896
890
|
if (!hasNullableType) {
|
|
897
|
-
expression =
|
|
891
|
+
expression = ts.factory.createNonNullExpression(expression);
|
|
898
892
|
}
|
|
899
893
|
}
|
|
900
894
|
// If the parameter is initialized, add the initializer as a fallback.
|
|
901
895
|
if (param.initializer) {
|
|
902
|
-
expression =
|
|
896
|
+
expression = ts.factory.createBinaryExpression(expression, ts.SyntaxKind.QuestionQuestionToken, param.initializer);
|
|
903
897
|
}
|
|
904
898
|
return replaceNodePlaceholder(param.getSourceFile(), expression, injectedType, printer);
|
|
905
899
|
}
|
|
@@ -914,12 +908,12 @@ function migrateInjectDecorator(firstArg, type, localTypeChecker) {
|
|
|
914
908
|
let typeArguments = null;
|
|
915
909
|
// `inject` no longer officially supports string injection so we need
|
|
916
910
|
// to cast to any. We maintain the type by passing it as a generic.
|
|
917
|
-
if (
|
|
918
|
-
typeArguments = [type ||
|
|
911
|
+
if (ts.isStringLiteralLike(firstArg)) {
|
|
912
|
+
typeArguments = [type || ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword)];
|
|
919
913
|
injectedType += ' as any';
|
|
920
914
|
}
|
|
921
|
-
else if (
|
|
922
|
-
|
|
915
|
+
else if (ts.isCallExpression(firstArg) &&
|
|
916
|
+
ts.isIdentifier(firstArg.expression) &&
|
|
923
917
|
firstArg.arguments.length === 1) {
|
|
924
918
|
const callImport = imports.getImportOfIdentifier(localTypeChecker, firstArg.expression);
|
|
925
919
|
const arrowFn = firstArg.arguments[0];
|
|
@@ -928,9 +922,9 @@ function migrateInjectDecorator(firstArg, type, localTypeChecker) {
|
|
|
928
922
|
if (callImport !== null &&
|
|
929
923
|
callImport.name === 'forwardRef' &&
|
|
930
924
|
callImport.importModule === '@angular/core' &&
|
|
931
|
-
|
|
932
|
-
if (
|
|
933
|
-
const returnStatement = arrowFn.body.statements.find((stmt) =>
|
|
925
|
+
ts.isArrowFunction(arrowFn)) {
|
|
926
|
+
if (ts.isBlock(arrowFn.body)) {
|
|
927
|
+
const returnStatement = arrowFn.body.statements.find((stmt) => ts.isReturnStatement(stmt));
|
|
934
928
|
if (returnStatement && returnStatement.expression) {
|
|
935
929
|
injectedType = returnStatement.expression.getText();
|
|
936
930
|
}
|
|
@@ -941,10 +935,10 @@ function migrateInjectDecorator(firstArg, type, localTypeChecker) {
|
|
|
941
935
|
}
|
|
942
936
|
}
|
|
943
937
|
else if (type &&
|
|
944
|
-
(
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
(
|
|
938
|
+
(ts.isTypeReferenceNode(type) ||
|
|
939
|
+
ts.isTypeLiteralNode(type) ||
|
|
940
|
+
ts.isTupleTypeNode(type) ||
|
|
941
|
+
(ts.isUnionTypeNode(type) && type.types.some(ts.isTypeReferenceNode)))) {
|
|
948
942
|
typeArguments = [type];
|
|
949
943
|
}
|
|
950
944
|
return { injectedType, typeArguments };
|
|
@@ -983,9 +977,9 @@ function stripConstructorParameters(node, tracker) {
|
|
|
983
977
|
*/
|
|
984
978
|
function getLocalTypeChecker(sourceFile) {
|
|
985
979
|
const options = { noEmit: true, skipLibCheck: true };
|
|
986
|
-
const host =
|
|
980
|
+
const host = ts.createCompilerHost(options);
|
|
987
981
|
host.getSourceFile = (fileName) => (fileName === sourceFile.fileName ? sourceFile : undefined);
|
|
988
|
-
const program =
|
|
982
|
+
const program = ts.createProgram({
|
|
989
983
|
rootNames: [sourceFile.fileName],
|
|
990
984
|
options,
|
|
991
985
|
host,
|
|
@@ -1000,7 +994,7 @@ function getLocalTypeChecker(sourceFile) {
|
|
|
1000
994
|
* @param printer Printer used to output AST nodes as strings.
|
|
1001
995
|
*/
|
|
1002
996
|
function replaceNodePlaceholder(sourceFile, node, replacement, printer) {
|
|
1003
|
-
const result = printer.printNode(
|
|
997
|
+
const result = printer.printNode(ts.EmitHint.Unspecified, node, sourceFile);
|
|
1004
998
|
return result.replace(PLACEHOLDER, replacement);
|
|
1005
999
|
}
|
|
1006
1000
|
/**
|
|
@@ -1009,9 +1003,9 @@ function replaceNodePlaceholder(sourceFile, node, replacement, printer) {
|
|
|
1009
1003
|
*/
|
|
1010
1004
|
function cloneModifiers(modifiers) {
|
|
1011
1005
|
return modifiers?.map((modifier) => {
|
|
1012
|
-
return
|
|
1013
|
-
?
|
|
1014
|
-
:
|
|
1006
|
+
return ts.isDecorator(modifier)
|
|
1007
|
+
? ts.factory.createDecorator(modifier.expression)
|
|
1008
|
+
: ts.factory.createModifier(modifier.kind);
|
|
1015
1009
|
});
|
|
1016
1010
|
}
|
|
1017
1011
|
/**
|
|
@@ -1020,18 +1014,18 @@ function cloneModifiers(modifiers) {
|
|
|
1020
1014
|
*/
|
|
1021
1015
|
function cloneName(node) {
|
|
1022
1016
|
switch (node.kind) {
|
|
1023
|
-
case
|
|
1024
|
-
return
|
|
1025
|
-
case
|
|
1026
|
-
return
|
|
1027
|
-
case
|
|
1028
|
-
return
|
|
1029
|
-
case
|
|
1030
|
-
return
|
|
1031
|
-
case
|
|
1032
|
-
return
|
|
1033
|
-
case
|
|
1034
|
-
return
|
|
1017
|
+
case ts.SyntaxKind.Identifier:
|
|
1018
|
+
return ts.factory.createIdentifier(node.text);
|
|
1019
|
+
case ts.SyntaxKind.StringLiteral:
|
|
1020
|
+
return ts.factory.createStringLiteral(node.text, node.getText()[0] === `'`);
|
|
1021
|
+
case ts.SyntaxKind.NoSubstitutionTemplateLiteral:
|
|
1022
|
+
return ts.factory.createNoSubstitutionTemplateLiteral(node.text, node.rawText);
|
|
1023
|
+
case ts.SyntaxKind.NumericLiteral:
|
|
1024
|
+
return ts.factory.createNumericLiteral(node.text);
|
|
1025
|
+
case ts.SyntaxKind.ComputedPropertyName:
|
|
1026
|
+
return ts.factory.createComputedPropertyName(node.expression);
|
|
1027
|
+
case ts.SyntaxKind.PrivateIdentifier:
|
|
1028
|
+
return ts.factory.createPrivateIdentifier(node.text);
|
|
1035
1029
|
default:
|
|
1036
1030
|
return node;
|
|
1037
1031
|
}
|
|
@@ -1061,8 +1055,8 @@ function canRemoveConstructor(options, constructor, removedStatementCount, prepe
|
|
|
1061
1055
|
* @returns
|
|
1062
1056
|
*/
|
|
1063
1057
|
function getNextPreservedStatement(startNode, removedStatements) {
|
|
1064
|
-
const body = nodes.closestNode(startNode,
|
|
1065
|
-
const closestStatement = nodes.closestNode(startNode,
|
|
1058
|
+
const body = nodes.closestNode(startNode, ts.isBlock);
|
|
1059
|
+
const closestStatement = nodes.closestNode(startNode, ts.isStatement);
|
|
1066
1060
|
if (body === null || closestStatement === null) {
|
|
1067
1061
|
return null;
|
|
1068
1062
|
}
|
|
@@ -1103,15 +1097,15 @@ function applyInternalOnlyChanges(node, constructor, localTypeChecker, tracker,
|
|
|
1103
1097
|
result.toCombine.sort((a, b) => a.initializer.getStart() - b.initializer.getStart());
|
|
1104
1098
|
}
|
|
1105
1099
|
result.toCombine.forEach(({ declaration, initializer }) => {
|
|
1106
|
-
const initializerStatement = nodes.closestNode(initializer,
|
|
1107
|
-
const newProperty =
|
|
1100
|
+
const initializerStatement = nodes.closestNode(initializer, ts.isStatement);
|
|
1101
|
+
const newProperty = ts.factory.createPropertyDeclaration(cloneModifiers(declaration.modifiers), cloneName(declaration.name), declaration.questionToken, declaration.type, initializer);
|
|
1108
1102
|
// If the initialization order is being preserved, we have to remove the original
|
|
1109
1103
|
// declaration and re-declare it. Otherwise we can do the replacement in-place.
|
|
1110
1104
|
if (preserveInitOrder) {
|
|
1111
1105
|
tracker.removeNode(declaration, true);
|
|
1112
1106
|
removedMembers.add(declaration);
|
|
1113
1107
|
afterInjectCalls.push(memberIndentation +
|
|
1114
|
-
printer.printNode(
|
|
1108
|
+
printer.printNode(ts.EmitHint.Unspecified, newProperty, declaration.getSourceFile()));
|
|
1115
1109
|
}
|
|
1116
1110
|
else {
|
|
1117
1111
|
tracker.replaceNode(declaration, newProperty);
|
|
@@ -1123,7 +1117,7 @@ function applyInternalOnlyChanges(node, constructor, localTypeChecker, tracker,
|
|
|
1123
1117
|
}
|
|
1124
1118
|
});
|
|
1125
1119
|
result.toHoist.forEach((decl) => {
|
|
1126
|
-
prependToClass.push(memberIndentation + printer.printNode(
|
|
1120
|
+
prependToClass.push(memberIndentation + printer.printNode(ts.EmitHint.Unspecified, decl, decl.getSourceFile()));
|
|
1127
1121
|
tracker.removeNode(decl, true);
|
|
1128
1122
|
removedMembers.add(decl);
|
|
1129
1123
|
});
|