fix(core): migration error if program contains files outside of the project (#39790)

Currently all of our migrations are set up to find the tsconfig paths within a project,
create a `Program` out of each and migrate the files inside of the `Program`. The
problem is that the `Program` can include files outside of the project and the CLI
APIs that we use to interact with the file system assume that all files are within
the project.

These changes consolidate the logic, that determines whether a file can be migrated,
in a single place and add an extra check to exclude files outside of the root.

Fixes #39778.

PR Close #39790
This commit is contained in:
Kristiyan Kostadinov 2020-11-20 20:25:30 +01:00 committed by Andrew Kushnir
parent b1ebfb1cab
commit 1a26f6da6e
19 changed files with 72 additions and 64 deletions

View File

@ -10,7 +10,7 @@ import {Rule, SchematicsException, Tree} from '@angular-devkit/schematics';
import {relative} from 'path'; import {relative} from 'path';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {findParentAccesses} from './util'; import {findParentAccesses} from './util';
@ -36,8 +36,8 @@ function runNativeAbstractControlParentMigration(
tree: Tree, tsconfigPath: string, basePath: string) { tree: Tree, tsconfigPath: string, basePath: string) {
const {program} = createMigrationProgram(tree, tsconfigPath, basePath); const {program} = createMigrationProgram(tree, tsconfigPath, basePath);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
sourceFiles.forEach(sourceFile => { sourceFiles.forEach(sourceFile => {
// We sort the nodes based on their position in the file and we offset the positions by one // We sort the nodes based on their position in the file and we offset the positions by one

View File

@ -11,7 +11,7 @@ import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {identifyDynamicQueryNodes, removeOptionsParameter, removeStaticFlag} from './util'; import {identifyDynamicQueryNodes, removeOptionsParameter, removeStaticFlag} from './util';
@ -39,8 +39,8 @@ export default function(): Rule {
function runDynamicQueryMigration(tree: Tree, tsconfigPath: string, basePath: string) { function runDynamicQueryMigration(tree: Tree, tsconfigPath: string, basePath: string) {
const {program} = createMigrationProgram(tree, tsconfigPath, basePath); const {program} = createMigrationProgram(tree, tsconfigPath, basePath);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
const printer = ts.createPrinter(); const printer = ts.createPrinter();
sourceFiles.forEach(sourceFile => { sourceFiles.forEach(sourceFile => {

View File

@ -31,7 +31,7 @@ export class Rule extends Rules.TypedRule {
sourceFiles.forEach(sourceFile => initialNavigationCollector.visitNode(sourceFile)); sourceFiles.forEach(sourceFile => initialNavigationCollector.visitNode(sourceFile));
const {assignments} = initialNavigationCollector; const {assignments} = initialNavigationCollector;
const transformer = new InitialNavigationTransform(typeChecker, getUpdateRecorder); const transformer = new InitialNavigationTransform(getUpdateRecorder);
const updateRecorders = new Map<ts.SourceFile, TslintUpdateRecorder>(); const updateRecorders = new Map<ts.SourceFile, TslintUpdateRecorder>();
transformer.migrateInitialNavigationAssignments(Array.from(assignments)); transformer.migrateInitialNavigationAssignments(Array.from(assignments));

View File

@ -10,7 +10,7 @@ import {Rule, SchematicsException, Tree} from '@angular-devkit/schematics';
import {relative} from 'path'; import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {InitialNavigationCollector} from './collector'; import {InitialNavigationCollector} from './collector';
import {InitialNavigationTransform} from './transform'; import {InitialNavigationTransform} from './transform';
import {UpdateRecorder} from './update_recorder'; import {UpdateRecorder} from './update_recorder';
@ -36,14 +36,14 @@ function runInitialNavigationMigration(tree: Tree, tsconfigPath: string, basePat
const {program} = createMigrationProgram(tree, tsconfigPath, basePath); const {program} = createMigrationProgram(tree, tsconfigPath, basePath);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const initialNavigationCollector = new InitialNavigationCollector(typeChecker); const initialNavigationCollector = new InitialNavigationCollector(typeChecker);
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
// Analyze source files by detecting all modules. // Analyze source files by detecting all modules.
sourceFiles.forEach(sourceFile => initialNavigationCollector.visitNode(sourceFile)); sourceFiles.forEach(sourceFile => initialNavigationCollector.visitNode(sourceFile));
const {assignments} = initialNavigationCollector; const {assignments} = initialNavigationCollector;
const transformer = new InitialNavigationTransform(typeChecker, getUpdateRecorder); const transformer = new InitialNavigationTransform(getUpdateRecorder);
const updateRecorders = new Map<ts.SourceFile, UpdateRecorder>(); const updateRecorders = new Map<ts.SourceFile, UpdateRecorder>();
transformer.migrateInitialNavigationAssignments(Array.from(assignments)); transformer.migrateInitialNavigationAssignments(Array.from(assignments));

View File

@ -13,9 +13,7 @@ import {UpdateRecorder} from './update_recorder';
export class InitialNavigationTransform { export class InitialNavigationTransform {
private printer = ts.createPrinter(); private printer = ts.createPrinter();
constructor( constructor(private getUpdateRecorder: (sf: ts.SourceFile) => UpdateRecorder) {}
private typeChecker: ts.TypeChecker,
private getUpdateRecorder: (sf: ts.SourceFile) => UpdateRecorder) {}
/** Migrate the ExtraOptions#InitialNavigation property assignments. */ /** Migrate the ExtraOptions#InitialNavigation property assignments. */
migrateInitialNavigationAssignments(literals: ts.PropertyAssignment[]) { migrateInitialNavigationAssignments(literals: ts.PropertyAssignment[]) {
@ -62,14 +60,3 @@ function getUpdatedInitialNavigationValue(initializer: ts.Expression): ts.Expres
return !!newText ? ts.createIdentifier(`'${newText}'`) : null; return !!newText ? ts.createIdentifier(`'${newText}'`) : null;
} }
/**
* Check whether the value assigned to an `initialNavigation` assignment
* conforms to the expected types for ExtraOptions#InitialNavigation
* @param node the property assignment to check
*/
function isValidInitialNavigationValue(node: ts.PropertyAssignment): boolean {
return ts.isStringLiteralLike(node.initializer) ||
node.initializer.kind === ts.SyntaxKind.FalseKeyword ||
node.initializer.kind === ts.SyntaxKind.TrueKeyword;
}

View File

@ -10,7 +10,7 @@ import {Rule, SchematicContext, SchematicsException, Tree} from '@angular-devkit
import {relative} from 'path'; import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {NgDefinitionCollector} from './definition_collector'; import {NgDefinitionCollector} from './definition_collector';
import {MissingInjectableTransform} from './transform'; import {MissingInjectableTransform} from './transform';
import {UpdateRecorder} from './update_recorder'; import {UpdateRecorder} from './update_recorder';
@ -46,8 +46,8 @@ function runMissingInjectableMigration(
const failures: string[] = []; const failures: string[] = [];
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const definitionCollector = new NgDefinitionCollector(typeChecker); const definitionCollector = new NgDefinitionCollector(typeChecker);
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
// Analyze source files by detecting all modules, directives and components. // Analyze source files by detecting all modules, directives and components.
sourceFiles.forEach(sourceFile => definitionCollector.visitNode(sourceFile)); sourceFiles.forEach(sourceFile => definitionCollector.visitNode(sourceFile));

View File

@ -11,7 +11,7 @@ import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {Collector} from './collector'; import {Collector} from './collector';
import {AnalysisFailure, ModuleWithProvidersTransform} from './transform'; import {AnalysisFailure, ModuleWithProvidersTransform} from './transform';
@ -49,8 +49,8 @@ function runModuleWithProvidersMigration(tree: Tree, tsconfigPath: string, baseP
const failures: string[] = []; const failures: string[] = [];
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const collector = new Collector(typeChecker); const collector = new Collector(typeChecker);
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
// Analyze source files by detecting all modules. // Analyze source files by detecting all modules.
sourceFiles.forEach(sourceFile => collector.visitNode(sourceFile)); sourceFiles.forEach(sourceFile => collector.visitNode(sourceFile));

View File

@ -11,7 +11,7 @@ import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {COMMON_IMPORT, DOCUMENT_TOKEN_NAME, DocumentImportVisitor, ResolvedDocumentImport} from './document_import_visitor'; import {COMMON_IMPORT, DOCUMENT_TOKEN_NAME, DocumentImportVisitor, ResolvedDocumentImport} from './document_import_visitor';
import {addToImport, createImport, removeFromImport} from './move-import'; import {addToImport, createImport, removeFromImport} from './move-import';
@ -43,8 +43,8 @@ function runMoveDocumentMigration(tree: Tree, tsconfigPath: string, basePath: st
const {program} = createMigrationProgram(tree, tsconfigPath, basePath); const {program} = createMigrationProgram(tree, tsconfigPath, basePath);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const visitor = new DocumentImportVisitor(typeChecker); const visitor = new DocumentImportVisitor(typeChecker);
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
// Analyze source files by finding imports. // Analyze source files by finding imports.
sourceFiles.forEach(sourceFile => visitor.visitNode(sourceFile)); sourceFiles.forEach(sourceFile => visitor.visitNode(sourceFile));

View File

@ -10,7 +10,7 @@ import {Rule, SchematicsException, Tree} from '@angular-devkit/schematics';
import {relative} from 'path'; import {relative} from 'path';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {findNativeEncapsulationNodes} from './util'; import {findNativeEncapsulationNodes} from './util';
@ -35,8 +35,8 @@ export default function(): Rule {
function runNativeViewEncapsulationMigration(tree: Tree, tsconfigPath: string, basePath: string) { function runNativeViewEncapsulationMigration(tree: Tree, tsconfigPath: string, basePath: string) {
const {program} = createMigrationProgram(tree, tsconfigPath, basePath); const {program} = createMigrationProgram(tree, tsconfigPath, basePath);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
sourceFiles.forEach(sourceFile => { sourceFiles.forEach(sourceFile => {
const update = tree.beginUpdate(relative(basePath, sourceFile.fileName)); const update = tree.beginUpdate(relative(basePath, sourceFile.fileName));

View File

@ -11,7 +11,7 @@ import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {findLiteralsToMigrate, migrateLiteral} from './util'; import {findLiteralsToMigrate, migrateLiteral} from './util';
@ -38,8 +38,8 @@ function runNavigationExtrasOmissionsMigration(tree: Tree, tsconfigPath: string,
const {program} = createMigrationProgram(tree, tsconfigPath, basePath); const {program} = createMigrationProgram(tree, tsconfigPath, basePath);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const printer = ts.createPrinter(); const printer = ts.createPrinter();
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
sourceFiles.forEach(sourceFile => { sourceFiles.forEach(sourceFile => {
const literalsToMigrate = findLiteralsToMigrate(sourceFile, typeChecker); const literalsToMigrate = findLiteralsToMigrate(sourceFile, typeChecker);

View File

@ -10,7 +10,7 @@ import {Rule, SchematicsException, Tree} from '@angular-devkit/schematics';
import {relative} from 'path'; import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {RelativeLinkResolutionCollector} from './collector'; import {RelativeLinkResolutionCollector} from './collector';
import {RelativeLinkResolutionTransform} from './transform'; import {RelativeLinkResolutionTransform} from './transform';
import {UpdateRecorder} from './update_recorder'; import {UpdateRecorder} from './update_recorder';
@ -36,8 +36,8 @@ function runRelativeLinkResolutionMigration(tree: Tree, tsconfigPath: string, ba
const {program} = createMigrationProgram(tree, tsconfigPath, basePath); const {program} = createMigrationProgram(tree, tsconfigPath, basePath);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const relativeLinkResolutionCollector = new RelativeLinkResolutionCollector(typeChecker); const relativeLinkResolutionCollector = new RelativeLinkResolutionCollector(typeChecker);
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
// Analyze source files by detecting all modules. // Analyze source files by detecting all modules.
sourceFiles.forEach(sourceFile => relativeLinkResolutionCollector.visitNode(sourceFile)); sourceFiles.forEach(sourceFile => relativeLinkResolutionCollector.visitNode(sourceFile));

View File

@ -11,7 +11,7 @@ import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {getImportSpecifier, replaceImport} from '../../utils/typescript/imports'; import {getImportSpecifier, replaceImport} from '../../utils/typescript/imports';
import {closestNode} from '../../utils/typescript/nodes'; import {closestNode} from '../../utils/typescript/nodes';
@ -59,8 +59,8 @@ function runRendererToRenderer2Migration(tree: Tree, tsconfigPath: string, baseP
}, [MODULE_AUGMENTATION_FILENAME]); }, [MODULE_AUGMENTATION_FILENAME]);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const printer = ts.createPrinter(); const printer = ts.createPrinter();
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
sourceFiles.forEach(sourceFile => { sourceFiles.forEach(sourceFile => {
const rendererImportSpecifier = getImportSpecifier(sourceFile, '@angular/core', 'Renderer'); const rendererImportSpecifier = getImportSpecifier(sourceFile, '@angular/core', 'Renderer');

View File

@ -11,7 +11,7 @@ import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {findLiteralsToMigrate, migrateLiteral} from './util'; import {findLiteralsToMigrate, migrateLiteral} from './util';
@ -41,8 +41,8 @@ function runPreserveQueryParamsMigration(tree: Tree, tsconfigPath: string, baseP
const {program} = createMigrationProgram(tree, tsconfigPath, basePath); const {program} = createMigrationProgram(tree, tsconfigPath, basePath);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const printer = ts.createPrinter(); const printer = ts.createPrinter();
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
sourceFiles.forEach(sourceFile => { sourceFiles.forEach(sourceFile => {
const literalsToMigrate = findLiteralsToMigrate(sourceFile, typeChecker); const literalsToMigrate = findLiteralsToMigrate(sourceFile, typeChecker);

View File

@ -14,7 +14,7 @@ import * as ts from 'typescript';
import {NgComponentTemplateVisitor} from '../../utils/ng_component_template'; import {NgComponentTemplateVisitor} from '../../utils/ng_component_template';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {NgQueryResolveVisitor} from './angular/ng_query_visitor'; import {NgQueryResolveVisitor} from './angular/ng_query_visitor';
import {QueryTemplateStrategy} from './strategies/template_strategy/template_strategy'; import {QueryTemplateStrategy} from './strategies/template_strategy/template_strategy';
@ -123,8 +123,8 @@ function analyzeProject(
} }
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
const queryVisitor = new NgQueryResolveVisitor(typeChecker); const queryVisitor = new NgQueryResolveVisitor(typeChecker);
// Analyze all project source-files and collect all queries that // Analyze all project source-files and collect all queries that

View File

@ -12,7 +12,7 @@ import {relative} from 'path';
import {NgComponentTemplateVisitor} from '../../utils/ng_component_template'; import {NgComponentTemplateVisitor} from '../../utils/ng_component_template';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {analyzeResolvedTemplate} from './analyze_template'; import {analyzeResolvedTemplate} from './analyze_template';
@ -48,8 +48,8 @@ function runTemplateVariableAssignmentCheck(
const {program} = createMigrationProgram(tree, tsconfigPath, basePath); const {program} = createMigrationProgram(tree, tsconfigPath, basePath);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const templateVisitor = new NgComponentTemplateVisitor(typeChecker); const templateVisitor = new NgComponentTemplateVisitor(typeChecker);
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
// Analyze source files by detecting HTML templates. // Analyze source files by detecting HTML templates.
sourceFiles.forEach(sourceFile => templateVisitor.visitNode(sourceFile)); sourceFiles.forEach(sourceFile => templateVisitor.visitNode(sourceFile));

View File

@ -11,7 +11,7 @@ import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {UndecoratedClassesWithDecoratedFieldsTransform} from './transform'; import {UndecoratedClassesWithDecoratedFieldsTransform} from './transform';
import {UpdateRecorder} from './update_recorder'; import {UpdateRecorder} from './update_recorder';
@ -49,8 +49,8 @@ function runUndecoratedClassesMigration(
const failures: string[] = []; const failures: string[] = [];
const {program} = createMigrationProgram(tree, tsconfigPath, basePath); const {program} = createMigrationProgram(tree, tsconfigPath, basePath);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
file => !file.isDeclarationFile && !program.isSourceFileFromExternalLibrary(file)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
const updateRecorders = new Map<ts.SourceFile, UpdateRecorder>(); const updateRecorders = new Map<ts.SourceFile, UpdateRecorder>();
const transform = const transform =
new UndecoratedClassesWithDecoratedFieldsTransform(typeChecker, getUpdateRecorder); new UndecoratedClassesWithDecoratedFieldsTransform(typeChecker, getUpdateRecorder);

View File

@ -16,7 +16,7 @@ import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationCompilerHost} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationCompilerHost} from '../../utils/typescript/compiler_host';
import {createNgcProgram} from './create_ngc_program'; import {createNgcProgram} from './create_ngc_program';
import {NgDeclarationCollector} from './ng_declaration_collector'; import {NgDeclarationCollector} from './ng_declaration_collector';
@ -85,8 +85,8 @@ function runUndecoratedClassesMigration(
const partialEvaluator = new PartialEvaluator( const partialEvaluator = new PartialEvaluator(
new TypeScriptReflectionHost(typeChecker), typeChecker, /* dependencyTracker */ null); new TypeScriptReflectionHost(typeChecker), typeChecker, /* dependencyTracker */ null);
const declarationCollector = new NgDeclarationCollector(typeChecker, partialEvaluator); const declarationCollector = new NgDeclarationCollector(typeChecker, partialEvaluator);
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
s => !s.isDeclarationFile && !program.isSourceFileFromExternalLibrary(s)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
// Analyze source files by detecting all directives, components and providers. // Analyze source files by detecting all directives, components and providers.
sourceFiles.forEach(sourceFile => declarationCollector.visitNode(sourceFile)); sourceFiles.forEach(sourceFile => declarationCollector.visitNode(sourceFile));

View File

@ -11,7 +11,7 @@ import {relative} from 'path';
import * as ts from 'typescript'; import * as ts from 'typescript';
import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths'; import {getProjectTsConfigPaths} from '../../utils/project_tsconfig_paths';
import {createMigrationProgram} from '../../utils/typescript/compiler_host'; import {canMigrateFile, createMigrationProgram} from '../../utils/typescript/compiler_host';
import {getImportSpecifier, replaceImport} from '../../utils/typescript/imports'; import {getImportSpecifier, replaceImport} from '../../utils/typescript/imports';
import {closestNode} from '../../utils/typescript/nodes'; import {closestNode} from '../../utils/typescript/nodes';
@ -54,8 +54,8 @@ function runWaitForAsyncMigration(tree: Tree, tsconfigPath: string, basePath: st
}, [MODULE_AUGMENTATION_FILENAME]); }, [MODULE_AUGMENTATION_FILENAME]);
const typeChecker = program.getTypeChecker(); const typeChecker = program.getTypeChecker();
const printer = ts.createPrinter(); const printer = ts.createPrinter();
const sourceFiles = program.getSourceFiles().filter( const sourceFiles =
f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f)); program.getSourceFiles().filter(sourceFile => canMigrateFile(basePath, sourceFile, program));
const deprecatedFunction = 'async'; const deprecatedFunction = 'async';
const newFunction = 'waitForAsync'; const newFunction = 'waitForAsync';

View File

@ -57,3 +57,24 @@ export function createMigrationCompilerHost(
return host; return host;
} }
/**
* Checks whether a file can be migrate by our automated migrations.
* @param basePath Absolute path to the project.
* @param sourceFile File being checked.
* @param program Program that includes the source file.
*/
export function canMigrateFile(
basePath: string, sourceFile: ts.SourceFile, program: ts.Program): boolean {
// We shouldn't migrate .d.ts files or files from an external library.
if (sourceFile.isDeclarationFile || program.isSourceFileFromExternalLibrary(sourceFile)) {
return false;
}
// Our migrations are set up to create a `Program` from the project's tsconfig and to migrate all
// the files within the program. This can include files that are outside of the Angular CLI
// project. We can't migrate files outside of the project, because our file system interactions
// go through the CLI's `Tree` which assumes that all files are within the project. See:
// https://github.com/angular/angular-cli/blob/0b0961c9c233a825b6e4bb59ab7f0790f9b14676/packages/angular_devkit/schematics/src/tree/host-tree.ts#L131
return !relative(basePath, sourceFile.fileName).startsWith('..');
}