refactor(core): add `createMigrationCompilerHost` (#32827)
Current we need to create and override certain compiler host methods in every schematic because schematics use a virtual fs. We this change we extract this logic to a common util. PR Close #32827
This commit is contained in:
parent
60047037a3
commit
01677b21b6
|
@ -11,10 +11,13 @@ import {dirname, relative} from 'path';
|
|||
import * as ts from 'typescript';
|
||||
|
||||
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
|
||||
import {createMigrationCompilerHost} from '../../utils/typescript/compiler_host';
|
||||
import {parseTsconfigFile} from '../../utils/typescript/parse_tsconfig';
|
||||
|
||||
import {identifyDynamicQueryNodes, removeOptionsParameter, removeStaticFlag} from './util';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Runs the dynamic queries migration for all TypeScript projects in the current CLI workspace.
|
||||
*/
|
||||
|
@ -39,20 +42,7 @@ export default function(): Rule {
|
|||
|
||||
function runDynamicQueryMigration(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));
|
||||
// Strip BOM as otherwise TSC methods (Ex: getWidth) will return an offset which
|
||||
// which breaks the CLI UpdateRecorder.
|
||||
// See: https://github.com/angular/angular/pull/30719
|
||||
return buffer ? buffer.toString().replace(/^\uFEFF/, '') : undefined;
|
||||
};
|
||||
|
||||
const host = createMigrationCompilerHost(tree, parsed.options, basePath);
|
||||
const program = ts.createProgram(parsed.fileNames, parsed.options, host);
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const sourceFiles = program.getSourceFiles().filter(
|
||||
|
|
|
@ -9,10 +9,9 @@
|
|||
import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics';
|
||||
import {dirname, relative} from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
|
||||
import {createMigrationCompilerHost} from '../../utils/typescript/compiler_host';
|
||||
import {parseTsconfigFile} from '../../utils/typescript/parse_tsconfig';
|
||||
|
||||
import {NgModuleCollector} from './module_collector';
|
||||
import {MissingInjectableTransform} from './transform';
|
||||
import {UpdateRecorder} from './update_recorder';
|
||||
|
@ -49,20 +48,9 @@ export default function(): Rule {
|
|||
function runMissingInjectableMigration(
|
||||
tree: Tree, tsconfigPath: string, basePath: string): string[] {
|
||||
const parsed = parseTsconfigFile(tsconfigPath, dirname(tsconfigPath));
|
||||
const host = ts.createCompilerHost(parsed.options, true);
|
||||
const host = createMigrationCompilerHost(tree, parsed.options, basePath);
|
||||
const failures: string[] = [];
|
||||
|
||||
// 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.
|
||||
host.readFile = fileName => {
|
||||
const buffer = tree.read(relative(basePath, fileName));
|
||||
// Strip BOM because TypeScript respects this character and it ultimately
|
||||
// results in shifted offsets since the CLI UpdateRecorder tries to
|
||||
// automatically account for the BOM character.
|
||||
// https://github.com/angular/angular-cli/issues/14558
|
||||
return buffer ? buffer.toString().replace(/^\uFEFF/, '') : undefined;
|
||||
};
|
||||
|
||||
const program = ts.createProgram(parsed.fileNames, parsed.options, host);
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const moduleCollector = new NgModuleCollector(typeChecker);
|
||||
|
|
|
@ -11,11 +11,14 @@ import {dirname, relative} from 'path';
|
|||
import * as ts from 'typescript';
|
||||
|
||||
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
|
||||
import {createMigrationCompilerHost} from '../../utils/typescript/compiler_host';
|
||||
import {parseTsconfigFile} from '../../utils/typescript/parse_tsconfig';
|
||||
|
||||
import {COMMON_IMPORT, DOCUMENT_TOKEN_NAME, DocumentImportVisitor, ResolvedDocumentImport} from './document_import_visitor';
|
||||
import {addToImport, createImport, removeFromImport} from './move-import';
|
||||
|
||||
|
||||
|
||||
/** Entry point for the V8 move-document migration. */
|
||||
export default function(): Rule {
|
||||
return (tree: Tree) => {
|
||||
|
@ -40,19 +43,7 @@ export default function(): Rule {
|
|||
*/
|
||||
function runMoveDocumentMigration(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));
|
||||
// Strip BOM as otherwise TSC methods (Ex: getWidth) will return an offset which
|
||||
// which breaks the CLI UpdateRecorder.
|
||||
// See: https://github.com/angular/angular/pull/30719
|
||||
return buffer ? buffer.toString().replace(/^\uFEFF/, '') : undefined;
|
||||
};
|
||||
const host = createMigrationCompilerHost(tree, parsed.options, basePath);
|
||||
|
||||
const program = ts.createProgram(parsed.fileNames, parsed.options, host);
|
||||
const typeChecker = program.getTypeChecker();
|
||||
|
|
|
@ -11,6 +11,7 @@ import {dirname, relative} from 'path';
|
|||
import * as ts from 'typescript';
|
||||
|
||||
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
|
||||
import {createMigrationCompilerHost} from '../../utils/typescript/compiler_host';
|
||||
import {parseTsconfigFile} from '../../utils/typescript/parse_tsconfig';
|
||||
|
||||
import {HelperFunction, getHelper} from './helpers';
|
||||
|
@ -18,6 +19,7 @@ import {migrateExpression, replaceImport} from './migration';
|
|||
import {findCoreImport, findRendererReferences} from './util';
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Migration that switches from `Renderer` to `Renderer2`. More information on how it works:
|
||||
* https://hackmd.angular.io/UTzUZTnPRA-cSa_4mHyfYw
|
||||
|
@ -46,17 +48,7 @@ export default function(): Rule {
|
|||
|
||||
function runRendererToRenderer2Migration(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 host = createMigrationCompilerHost(tree, parsed.options, basePath);
|
||||
const program = ts.createProgram(parsed.fileNames, parsed.options, host);
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const printer = ts.createPrinter();
|
||||
|
|
|
@ -14,6 +14,7 @@ import * as ts from 'typescript';
|
|||
|
||||
import {NgComponentTemplateVisitor} from '../../utils/ng_component_template';
|
||||
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
|
||||
import {createMigrationCompilerHost} from '../../utils/typescript/compiler_host';
|
||||
import {parseTsconfigFile} from '../../utils/typescript/parse_tsconfig';
|
||||
|
||||
import {NgQueryResolveVisitor} from './angular/ng_query_visitor';
|
||||
|
@ -117,20 +118,7 @@ function analyzeProject(
|
|||
logger: logging.LoggerApi):
|
||||
AnalyzedProject|null {
|
||||
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));
|
||||
// Strip BOM as otherwise TSC methods (Ex: getWidth) will return an offset which
|
||||
// which breaks the CLI UpdateRecorder.
|
||||
// See: https://github.com/angular/angular/pull/30719
|
||||
return buffer ? buffer.toString().replace(/^\uFEFF/, '') : undefined;
|
||||
};
|
||||
|
||||
const host = createMigrationCompilerHost(tree, parsed.options, basePath);
|
||||
const program = ts.createProgram(parsed.fileNames, parsed.options, host);
|
||||
const syntacticDiagnostics = program.getSyntacticDiagnostics();
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import * as ts from 'typescript';
|
|||
|
||||
import {NgComponentTemplateVisitor} from '../../utils/ng_component_template';
|
||||
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
|
||||
import {createMigrationCompilerHost} from '../../utils/typescript/compiler_host';
|
||||
import {parseTsconfigFile} from '../../utils/typescript/parse_tsconfig';
|
||||
|
||||
import {analyzeResolvedTemplate} from './analyze_template';
|
||||
|
@ -47,18 +48,7 @@ export default function(): Rule {
|
|||
function runTemplateVariableAssignmentCheck(
|
||||
tree: Tree, tsconfigPath: string, basePath: string, logger: Logger) {
|
||||
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.
|
||||
host.readFile = fileName => {
|
||||
const buffer = tree.read(relative(basePath, fileName));
|
||||
// Strip BOM as otherwise TSC methods (Ex: getWidth) will return an offset which
|
||||
// which breaks the CLI UpdateRecorder.
|
||||
// See: https://github.com/angular/angular/pull/30719
|
||||
return buffer ? buffer.toString().replace(/^\uFEFF/, '') : undefined;
|
||||
};
|
||||
|
||||
const host = createMigrationCompilerHost(tree, parsed.options, basePath);
|
||||
const program = ts.createProgram(parsed.fileNames, parsed.options, host);
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const templateVisitor = new NgComponentTemplateVisitor(typeChecker);
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics';
|
||||
import {dirname, relative} from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
|
||||
import {createMigrationCompilerHost} from '../../utils/typescript/compiler_host';
|
||||
import {parseTsconfigFile} from '../../utils/typescript/parse_tsconfig';
|
||||
import {FALLBACK_DECORATOR, addImport, getNamedImports, getUndecoratedClassesWithDecoratedFields, hasNamedImport} from './utils';
|
||||
|
||||
|
@ -44,20 +44,7 @@ export default function(): Rule {
|
|||
|
||||
function runUndecoratedClassesMigration(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 them multiple times.
|
||||
host.readFile = fileName => {
|
||||
const buffer = tree.read(relative(basePath, fileName));
|
||||
// Strip BOM as otherwise TSC methods (Ex: getWidth) will return an offset which
|
||||
// which breaks the CLI UpdateRecorder.
|
||||
// See: https://github.com/angular/angular/pull/30719
|
||||
return buffer ? buffer.toString().replace(/^\uFEFF/, '') : undefined;
|
||||
};
|
||||
|
||||
const host = createMigrationCompilerHost(tree, parsed.options, basePath);
|
||||
const program = ts.createProgram(parsed.fileNames, parsed.options, host);
|
||||
const typeChecker = program.getTypeChecker();
|
||||
const printer = ts.createPrinter();
|
||||
|
|
|
@ -9,12 +9,14 @@
|
|||
import {logging} from '@angular-devkit/core';
|
||||
import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit/schematics';
|
||||
import {AotCompiler} from '@angular/compiler';
|
||||
import {createCompilerHost} from '@angular/compiler-cli';
|
||||
import {PartialEvaluator} from '@angular/compiler-cli/src/ngtsc/partial_evaluator';
|
||||
import {TypeScriptReflectionHost} from '@angular/compiler-cli/src/ngtsc/reflection';
|
||||
import {relative} from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
|
||||
import {createMigrationCompilerHost} from '../../utils/typescript/compiler_host';
|
||||
|
||||
import {createNgcProgram} from './create_ngc_program';
|
||||
import {NgDeclarationCollector} from './ng_declaration_collector';
|
||||
|
@ -146,21 +148,8 @@ function gracefullyCreateProgram(
|
|||
tree: Tree, basePath: string, tsconfigPath: string,
|
||||
logger: logging.LoggerApi): {compiler: AotCompiler, program: ts.Program}|null {
|
||||
try {
|
||||
const {ngcProgram, host, program, compiler} = createNgcProgram((options) => {
|
||||
const host = ts.createCompilerHost(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.
|
||||
host.readFile = fileName => {
|
||||
const buffer = tree.read(relative(basePath, fileName));
|
||||
// Strip BOM as otherwise TSC methods (Ex: getWidth) will return an offset which
|
||||
// which breaks the CLI UpdateRecorder.
|
||||
// See: https://github.com/angular/angular/pull/30719
|
||||
return buffer ? buffer.toString().replace(/^\uFEFF/, '') : undefined;
|
||||
};
|
||||
|
||||
return host;
|
||||
}, tsconfigPath);
|
||||
const {ngcProgram, host, program, compiler} = createNgcProgram(
|
||||
(options) => createMigrationCompilerHost(tree, options, basePath), tsconfigPath);
|
||||
const syntacticDiagnostics = ngcProgram.getTsSyntacticDiagnostics();
|
||||
const structuralDiagnostics = ngcProgram.getNgStructuralDiagnostics();
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google Inc. All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {Tree} from '@angular-devkit/schematics';
|
||||
import {relative} from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
export function createMigrationCompilerHost(
|
||||
tree: Tree, options: ts.CompilerOptions, basePath: string): ts.CompilerHost {
|
||||
const host = ts.createCompilerHost(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 multiple migrations we might have intersecting changes and
|
||||
// source files.
|
||||
host.readFile = fileName => {
|
||||
const buffer = tree.read(relative(basePath, fileName));
|
||||
// Strip BOM as otherwise TSC methods (Ex: getWidth) will return an offset which
|
||||
// which breaks the CLI UpdateRecorder.
|
||||
// See: https://github.com/angular/angular/pull/30719
|
||||
return buffer ? buffer.toString().replace(/^\uFEFF/, '') : undefined;
|
||||
};
|
||||
|
||||
return host;
|
||||
}
|
Loading…
Reference in New Issue