From fca1724ebf3d159b1ff6f733ed9583c7ff886e01 Mon Sep 17 00:00:00 2001 From: Paul Gschwendtner Date: Sat, 9 Mar 2019 15:51:33 +0100 Subject: [PATCH] refactor(core): static-query schematic incorrectly handles multiple tsconfigs (#29133) Currently when the static-query runs for a project with multiple TypeScript configuration files (e.g. a usual CLI project), the migration incorrectly applies the code transformation multiple times. This is because the migration is currently based on the source file contents in the file system, while the actual source file contents could have already changed in the devkit schematic tree. PR Close #29133 --- .../migrations/static-queries/migration.ts | 10 ++++++++ .../test/static_queries_migration_spec.ts | 25 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/packages/core/schematics/migrations/static-queries/migration.ts b/packages/core/schematics/migrations/static-queries/migration.ts index d54a08b784..57b7822119 100644 --- a/packages/core/schematics/migrations/static-queries/migration.ts +++ b/packages/core/schematics/migrations/static-queries/migration.ts @@ -25,6 +25,16 @@ import {parseTsconfigFile} from './typescript/tsconfig'; export function runStaticQueryMigration(tree: Tree, tsconfigPath: string, basePath: string) { const parsed = parseTsconfigFile(tsconfigPath, dirname(tsconfigPath)); const host = ts.createCompilerHost(parsed.options, true); + + // We need to overwrite the host "readFile" method, as we want the TypeScript + // program to be based on the file contents in the virtual file tree. Otherwise + // if we run the migration for multiple tsconfig files which have intersecting + // source files, it can end up updating query definitions multiple times. + host.readFile = fileName => { + const buffer = tree.read(relative(basePath, fileName)); + return buffer ? buffer.toString() : undefined; + }; + const program = ts.createProgram(parsed.fileNames, parsed.options, host); const typeChecker = program.getTypeChecker(); const queryVisitor = new NgQueryResolveVisitor(typeChecker); diff --git a/packages/core/schematics/test/static_queries_migration_spec.ts b/packages/core/schematics/test/static_queries_migration_spec.ts index 8bd207ceed..dc23eae3b0 100644 --- a/packages/core/schematics/test/static_queries_migration_spec.ts +++ b/packages/core/schematics/test/static_queries_migration_spec.ts @@ -710,5 +710,30 @@ describe('static-queries migration', () => { expect(tree.readContent('/index.ts')) .toContain(`@${queryType}('test', { static: true }) query2: any;`); }); + + it('should properly handle multiple tsconfig files', () => { + writeFile('/src/index.ts', ` + import {Component, ${queryType}} from '@angular/core'; + + @Component({template: ''}) + export class MyComp { + private @${queryType}('test') query: any; + } + `); + + writeFile('/src/tsconfig.json', JSON.stringify({ + compilerOptions: { + lib: ['es2015'], + } + })); + + // The migration runs for "/tsconfig.json" and "/src/tsconfig.json" which both + // contain the "src/index.ts" file. This test ensures that we don't incorrectly + // apply the code transformation multiple times with outdated offsets. + runMigration(); + + expect(tree.readContent('/src/index.ts')) + .toContain(`@${queryType}('test', { static: false }) query: any;`); + }); } });