Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/cdk/schematics/migration.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
"$schema": "./node_modules/@angular-devkit/schematics/collection-schema.json",
"schematics": {
"migration-v19": {
"version": "19.0.0-0",
"description": "Updates the Angular CDK to v19",
"factory": "./ng-update/index#updateToV19"
"migration-v20": {
"version": "20.0.0-0",
"description": "Updates the Angular CDK to v20",
"factory": "./ng-update/index#updateToV20"
},
"ng-post-update": {
"description": "Prints out results after ng-update.",
Expand Down
6 changes: 3 additions & 3 deletions src/cdk/schematics/ng-update/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,10 @@ import {createMigrationSchematicRule, NullableDevkitMigration} from './devkit-mi

const cdkMigrations: NullableDevkitMigration[] = [];

/** Entry point for the migration schematics with target of Angular CDK 18.0.0 */
export function updateToV19(): Rule {
/** Entry point for the migration schematics with target of Angular CDK 20.0.0 */
export function updateToV20(): Rule {
return createMigrationSchematicRule(
TargetVersion.V19,
TargetVersion.V20,
cdkMigrations,
cdkUpgradeData,
onMigrationComplete,
Expand Down
2 changes: 1 addition & 1 deletion src/cdk/schematics/update-tool/target-version.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

// tslint:disable-next-line:prefer-const-enum
export enum TargetVersion {
V19 = 'version 19',
V20 = 'version 20',
}

/**
Expand Down
8 changes: 4 additions & 4 deletions src/google-maps/schematics/migration.json
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
{
"schematics": {
"migration-v19": {
"version": "19.0.0-0",
"description": "Updates the Angular Google Maps package to v19",
"factory": "./ng-update/index_bundled#updateToV19"
"migration-v20": {
"version": "20.0.0-0",
"description": "Updates the Angular Google Maps package to v20",
"factory": "./ng-update/index_bundled#updateToV20"
}
}
}
41 changes: 1 addition & 40 deletions src/google-maps/schematics/ng-update/BUILD.bazel
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
load("//tools:defaults.bzl", "esbuild", "jasmine_node_test", "spec_bundle", "ts_library")
load("//tools:defaults.bzl", "esbuild", "ts_library")

## THIS ONE IS ESM
# By default everything is ESM
Expand Down Expand Up @@ -38,42 +38,3 @@ esbuild(
visibility = ["//src/google-maps/schematics:__pkg__"],
deps = [":ng_update_lib"],
)

ts_library(
name = "test_lib",
testonly = True,
srcs = glob(["**/*.spec.ts"]),
deps = [
":ng_update_lib",
"@npm//@angular-devkit/core",
"@npm//@angular-devkit/schematics",
"@npm//@bazel/runfiles",
"@npm//@types/jasmine",
"@npm//@types/node",
"@npm//@types/shelljs",
],
)

spec_bundle(
name = "spec_bundle",
external = [
"*/paths.js",
"shelljs",
"@angular-devkit/core/node",
],
platform = "cjs-legacy",
target = "es2020",
deps = [":test_lib"],
)

jasmine_node_test(
name = "test",
data = [
":ng_update_index",
"//src/google-maps/schematics:schematics_assets",
"@npm//shelljs",
],
deps = [
":spec_bundle",
],
)
140 changes: 2 additions & 138 deletions src/google-maps/schematics/ng-update/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,141 +6,5 @@
* found in the LICENSE file at https://angular.dev/license
*/

import {Path} from '@angular-devkit/core';
import {Rule, Tree} from '@angular-devkit/schematics';
import ts from 'typescript';

/** Tag name of the clusterer component. */
const TAG_NAME = 'map-marker-clusterer';

/** Module from which the clusterer is being imported. */
const MODULE_NAME = '@angular/google-maps';

/** Old name of the clusterer class. */
const CLASS_NAME = 'MapMarkerClusterer';

/** New name of the clusterer class. */
const DEPRECATED_CLASS_NAME = 'DeprecatedMapMarkerClusterer';

/** Entry point for the migration schematics with target of Angular Material v19 */
export function updateToV19(): Rule {
return tree => {
tree.visit(path => {
if (path.includes('node_modules')) {
return;
}

if (path.endsWith('.html')) {
const content = tree.read(path)?.toString();

if (content && content.includes('<' + TAG_NAME)) {
tree.overwrite(path, migrateHtml(content));
}
} else if (path.endsWith('.ts') && !path.endsWith('.d.ts')) {
migrateTypeScript(path, tree);
}
});
};
}

/** Migrates an HTML template from the old tag name to the new one. */
function migrateHtml(content: string): string {
return content
.replace(/<map-marker-clusterer/g, '<deprecated-map-marker-clusterer')
.replace(/<\/map-marker-clusterer/g, '</deprecated-map-marker-clusterer');
}

/** Migrates a TypeScript file from the old tag and class names to the new ones. */
function migrateTypeScript(path: Path, tree: Tree) {
const content = tree.read(path)?.toString();

// Exit early if none of the symbols we're looking for are mentioned.
if (
!content ||
(!content.includes('<' + TAG_NAME) &&
!content.includes(MODULE_NAME) &&
!content.includes(CLASS_NAME))
) {
return;
}

const sourceFile = ts.createSourceFile(path, content, ts.ScriptTarget.Latest, true);
const toMigrate = findTypeScriptNodesToMigrate(sourceFile);

if (toMigrate.length === 0) {
return;
}

const printer = ts.createPrinter();
const update = tree.beginUpdate(path);

for (const node of toMigrate) {
let replacement: ts.Node;

if (ts.isStringLiteralLike(node)) {
// Strings should be migrated as if they're HTML.
if (ts.isStringLiteral(node)) {
replacement = ts.factory.createStringLiteral(
migrateHtml(node.text),
node.getText()[0] === `'`,
);
} else {
replacement = ts.factory.createNoSubstitutionTemplateLiteral(migrateHtml(node.text));
}
} else {
// Imports/exports should preserve the old name, but import the clusterer using the new one.
const propertyName = ts.factory.createIdentifier(DEPRECATED_CLASS_NAME);
const name = node.name as ts.Identifier;

replacement = ts.isImportSpecifier(node)
? ts.factory.updateImportSpecifier(node, node.isTypeOnly, propertyName, name)
: ts.factory.updateExportSpecifier(node, node.isTypeOnly, propertyName, name);
}

update
.remove(node.getStart(), node.getWidth())
.insertLeft(
node.getStart(),
printer.printNode(ts.EmitHint.Unspecified, replacement, sourceFile),
);
}

tree.commitUpdate(update);
}

/** Finds the TypeScript nodes that need to be migrated from a specific file. */
function findTypeScriptNodesToMigrate(sourceFile: ts.SourceFile) {
const results: (ts.StringLiteralLike | ts.ImportSpecifier | ts.ExportSpecifier)[] = [];

sourceFile.forEachChild(function walk(node) {
// Most likely a template using the clusterer.
if (ts.isStringLiteral(node) && node.text.includes('<' + TAG_NAME)) {
results.push(node);
} else if (
// Import/export referencing the clusterer.
(ts.isImportDeclaration(node) || ts.isExportDeclaration(node)) &&
node.moduleSpecifier &&
ts.isStringLiteralLike(node.moduleSpecifier) &&
node.moduleSpecifier.text === MODULE_NAME
) {
const bindings = ts.isImportDeclaration(node)
? node.importClause?.namedBindings
: node.exportClause;

if (bindings && (ts.isNamedImports(bindings) || ts.isNamedExports(bindings))) {
bindings.elements.forEach(element => {
const symbolName = element.propertyName || element.name;

if (ts.isIdentifier(symbolName) && symbolName.text === CLASS_NAME) {
results.push(element);
}
});
}
} else {
node.forEachChild(walk);
}
});

// Sort the results in reverse order to make applying the updates easier.
return results.sort((a, b) => b.getStart() - a.getStart());
}
/** Entry point for the migration schematics with target of Angular Material v20 */
export function updateToV20(): void {}
Loading
Loading