Skip to content

Commit

Permalink
feat(store): add ngrx-store-freeze migration (#1901)
Browse files Browse the repository at this point in the history
Closes #1896
  • Loading branch information
timdeschryver authored and brandonroberts committed Jun 3, 2019
1 parent 5a09844 commit 4146650
Show file tree
Hide file tree
Showing 39 changed files with 1,343 additions and 123 deletions.
3 changes: 3 additions & 0 deletions modules/data/schematics-core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export {
addExportToModule,
addImportToModule,
addProviderToModule,
replaceImport,
} from './utility/ast-utils';

export {
Expand Down Expand Up @@ -71,3 +72,5 @@ export { parseName } from './utility/parse-name';
export { addPackageToPackageJson } from './utility/package';

export { platformVersion } from './utility/libs-version';

export { visitTSSourceFiles } from './utility/visit-utils';
58 changes: 57 additions & 1 deletion modules/data/schematics-core/utility/ast-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import * as ts from 'typescript';
import { Change, InsertChange, NoopChange } from './change';
import {
Change,
InsertChange,
NoopChange,
createReplaceChange,
ReplaceChange,
} from './change';
import { Path } from '@angular-devkit/core';

/**
* Find all nodes from the AST in the subtree of node of SyntaxKind kind.
Expand Down Expand Up @@ -636,3 +643,52 @@ export function insertImport(
ts.SyntaxKind.StringLiteral
);
}

export function replaceImport(
sourceFile: ts.SourceFile,
path: Path,
importFrom: string,
importAsIs: string,
importToBe: string
): ReplaceChange[] {
const imports = sourceFile.statements
.filter(ts.isImportDeclaration)
.filter(
({ moduleSpecifier }) =>
moduleSpecifier.getText(sourceFile) === `'${importFrom}'` ||
moduleSpecifier.getText(sourceFile) === `"${importFrom}"`
);

if (imports.length === 0) {
return [];
}

const changes = imports
.map(p => (p.importClause!.namedBindings! as ts.NamedImports).elements)
.reduce((imports, curr) => imports.concat(curr), [] as ts.ImportSpecifier[])
.map(specifier => {
if (!ts.isImportSpecifier(specifier)) {
return { hit: false };
}

if (specifier.name.text === importAsIs) {
return { hit: true, specifier, text: specifier.name.text };
}

// if import is renamed
if (
specifier.propertyName &&
specifier.propertyName.text === importAsIs
) {
return { hit: true, specifier, text: specifier.propertyName.text };
}

return { hit: false };
})
.filter(({ hit }) => hit)
.map(({ specifier, text }) =>
createReplaceChange(sourceFile, path, specifier!, text!, importToBe)
);

return changes;
}
29 changes: 15 additions & 14 deletions modules/data/schematics-core/utility/change.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,18 @@ export class RemoveChange implements Change {
order: number;
description: string;

constructor(
public path: string,
private pos: number,
private toRemove: string
) {
if (pos < 0) {
constructor(public path: string, public pos: number, public end: number) {
if (pos < 0 || end < 0) {
throw new Error('Negative positions are invalid');
}
this.description = `Removed ${toRemove} into position ${pos} of ${path}`;
this.description = `Removed text in position ${pos} to ${end} of ${path}`;
this.order = pos;
}

apply(host: Host): Promise<void> {
return host.read(this.path).then(content => {
const prefix = content.substring(0, this.pos);
const suffix = content.substring(this.pos + this.toRemove.length);
const suffix = content.substring(this.end);

// TODO: throw error if toRemove doesn't match removed string.
return host.write(this.path, `${prefix}${suffix}`);
Expand All @@ -109,7 +105,7 @@ export class ReplaceChange implements Change {

constructor(
public path: string,
private pos: number,
public pos: number,
public oldText: string,
public newText: string
) {
Expand Down Expand Up @@ -150,14 +146,19 @@ export function createReplaceChange(

export function createChangeRecorder(
tree: Tree,
path: Path,
changes: ReplaceChange[]
path: string,
changes: Change[]
): UpdateRecorder {
const recorder = tree.beginUpdate(path);
for (const change of changes) {
const action = <any>change;
recorder.remove(action.pos, action.oldText.length);
recorder.insertLeft(action.pos, action.newText);
if (change instanceof InsertChange) {
recorder.insertLeft(change.pos, change.toAdd);
} else if (change instanceof RemoveChange) {
recorder.remove(change.pos, change.end - change.pos);
} else if (change instanceof ReplaceChange) {
recorder.remove(change.pos, change.oldText.length);
recorder.insertLeft(change.pos, change.newText);
}
}
return recorder;
}
33 changes: 33 additions & 0 deletions modules/data/schematics-core/utility/visit-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as ts from 'typescript';
import { Tree } from '@angular-devkit/schematics';

export function visitTSSourceFiles<Result = void>(
tree: Tree,
visitor: (
sourceFile: ts.SourceFile,
tree: Tree,
result?: Result
) => Result | undefined
): Result | undefined {
let result: Result | undefined = undefined;

tree.visit(path => {
if (!path.endsWith('.ts')) {
return;
}

const sourceFile = ts.createSourceFile(
path,
tree.read(path)!.toString(),
ts.ScriptTarget.Latest
);

if (sourceFile.isDeclarationFile) {
return;
}

result = visitor(sourceFile, tree, result);
});

return result;
}
3 changes: 3 additions & 0 deletions modules/effects/schematics-core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export {
addExportToModule,
addImportToModule,
addProviderToModule,
replaceImport,
} from './utility/ast-utils';

export {
Expand Down Expand Up @@ -71,3 +72,5 @@ export { parseName } from './utility/parse-name';
export { addPackageToPackageJson } from './utility/package';

export { platformVersion } from './utility/libs-version';

export { visitTSSourceFiles } from './utility/visit-utils';
58 changes: 57 additions & 1 deletion modules/effects/schematics-core/utility/ast-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,14 @@
* found in the LICENSE file at https://angular.io/license
*/
import * as ts from 'typescript';
import { Change, InsertChange, NoopChange } from './change';
import {
Change,
InsertChange,
NoopChange,
createReplaceChange,
ReplaceChange,
} from './change';
import { Path } from '@angular-devkit/core';

/**
* Find all nodes from the AST in the subtree of node of SyntaxKind kind.
Expand Down Expand Up @@ -636,3 +643,52 @@ export function insertImport(
ts.SyntaxKind.StringLiteral
);
}

export function replaceImport(
sourceFile: ts.SourceFile,
path: Path,
importFrom: string,
importAsIs: string,
importToBe: string
): ReplaceChange[] {
const imports = sourceFile.statements
.filter(ts.isImportDeclaration)
.filter(
({ moduleSpecifier }) =>
moduleSpecifier.getText(sourceFile) === `'${importFrom}'` ||
moduleSpecifier.getText(sourceFile) === `"${importFrom}"`
);

if (imports.length === 0) {
return [];
}

const changes = imports
.map(p => (p.importClause!.namedBindings! as ts.NamedImports).elements)
.reduce((imports, curr) => imports.concat(curr), [] as ts.ImportSpecifier[])
.map(specifier => {
if (!ts.isImportSpecifier(specifier)) {
return { hit: false };
}

if (specifier.name.text === importAsIs) {
return { hit: true, specifier, text: specifier.name.text };
}

// if import is renamed
if (
specifier.propertyName &&
specifier.propertyName.text === importAsIs
) {
return { hit: true, specifier, text: specifier.propertyName.text };
}

return { hit: false };
})
.filter(({ hit }) => hit)
.map(({ specifier, text }) =>
createReplaceChange(sourceFile, path, specifier!, text!, importToBe)
);

return changes;
}
29 changes: 15 additions & 14 deletions modules/effects/schematics-core/utility/change.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,22 +77,18 @@ export class RemoveChange implements Change {
order: number;
description: string;

constructor(
public path: string,
private pos: number,
private toRemove: string
) {
if (pos < 0) {
constructor(public path: string, public pos: number, public end: number) {
if (pos < 0 || end < 0) {
throw new Error('Negative positions are invalid');
}
this.description = `Removed ${toRemove} into position ${pos} of ${path}`;
this.description = `Removed text in position ${pos} to ${end} of ${path}`;
this.order = pos;
}

apply(host: Host): Promise<void> {
return host.read(this.path).then(content => {
const prefix = content.substring(0, this.pos);
const suffix = content.substring(this.pos + this.toRemove.length);
const suffix = content.substring(this.end);

// TODO: throw error if toRemove doesn't match removed string.
return host.write(this.path, `${prefix}${suffix}`);
Expand All @@ -109,7 +105,7 @@ export class ReplaceChange implements Change {

constructor(
public path: string,
private pos: number,
public pos: number,
public oldText: string,
public newText: string
) {
Expand Down Expand Up @@ -150,14 +146,19 @@ export function createReplaceChange(

export function createChangeRecorder(
tree: Tree,
path: Path,
changes: ReplaceChange[]
path: string,
changes: Change[]
): UpdateRecorder {
const recorder = tree.beginUpdate(path);
for (const change of changes) {
const action = <any>change;
recorder.remove(action.pos, action.oldText.length);
recorder.insertLeft(action.pos, action.newText);
if (change instanceof InsertChange) {
recorder.insertLeft(change.pos, change.toAdd);
} else if (change instanceof RemoveChange) {
recorder.remove(change.pos, change.end - change.pos);
} else if (change instanceof ReplaceChange) {
recorder.remove(change.pos, change.oldText.length);
recorder.insertLeft(change.pos, change.newText);
}
}
return recorder;
}
33 changes: 33 additions & 0 deletions modules/effects/schematics-core/utility/visit-utils.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import * as ts from 'typescript';
import { Tree } from '@angular-devkit/schematics';

export function visitTSSourceFiles<Result = void>(
tree: Tree,
visitor: (
sourceFile: ts.SourceFile,
tree: Tree,
result?: Result
) => Result | undefined
): Result | undefined {
let result: Result | undefined = undefined;

tree.visit(path => {
if (!path.endsWith('.ts')) {
return;
}

const sourceFile = ts.createSourceFile(
path,
tree.read(path)!.toString(),
ts.ScriptTarget.Latest
);

if (sourceFile.isDeclarationFile) {
return;
}

result = visitor(sourceFile, tree, result);
});

return result;
}
3 changes: 3 additions & 0 deletions modules/entity/schematics-core/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export {
addExportToModule,
addImportToModule,
addProviderToModule,
replaceImport,
} from './utility/ast-utils';

export {
Expand Down Expand Up @@ -71,3 +72,5 @@ export { parseName } from './utility/parse-name';
export { addPackageToPackageJson } from './utility/package';

export { platformVersion } from './utility/libs-version';

export { visitTSSourceFiles } from './utility/visit-utils';
Loading

0 comments on commit 4146650

Please sign in to comment.