| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121 |
- "use strict";
- /**
- * @license
- * Copyright Google LLC 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
- */
- Object.defineProperty(exports, "__esModule", { value: true });
- const core_1 = require("@angular-devkit/core");
- const glob_1 = require("glob");
- const path_1 = require("path");
- const ts = require("typescript");
- const component_resource_collector_1 = require("./component-resource-collector");
- const parse_tsconfig_1 = require("./utils/parse-tsconfig");
- function runMigrationRules(tree, logger, tsconfigPath, targetVersion, ruleTypes, upgradeData, analyzedFiles) {
- // The CLI uses the working directory as the base directory for the
- // virtual file system tree.
- const basePath = process.cwd();
- const parsed = parse_tsconfig_1.parseTsconfigFile(tsconfigPath, path_1.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(getProjectRelativePath(fileName));
- // Strip BOM as otherwise TSC methods (e.g. "getWidth") will return an offset which
- // which breaks the CLI UpdateRecorder. https://github.com/angular/angular/pull/30719
- return buffer ? buffer.toString().replace(/^\uFEFF/, '') : undefined;
- };
- const program = ts.createProgram(parsed.fileNames, parsed.options, host);
- const typeChecker = program.getTypeChecker();
- const rules = [];
- // Create instances of all specified migration rules.
- for (const ruleCtor of ruleTypes) {
- const rule = new ruleCtor(program, typeChecker, targetVersion, upgradeData);
- rule.getUpdateRecorder = getUpdateRecorder;
- rule.init();
- if (rule.ruleEnabled) {
- rules.push(rule);
- }
- }
- const sourceFiles = program.getSourceFiles().filter(f => !f.isDeclarationFile && !program.isSourceFileFromExternalLibrary(f));
- const resourceCollector = new component_resource_collector_1.ComponentResourceCollector(typeChecker);
- const updateRecorderCache = new Map();
- sourceFiles.forEach(sourceFile => {
- const relativePath = getProjectRelativePath(sourceFile.fileName);
- // Do not visit source files which have been checked as part of a
- // previously migrated TypeScript project.
- if (!analyzedFiles.has(relativePath)) {
- _visitTypeScriptNode(sourceFile);
- analyzedFiles.add(relativePath);
- }
- });
- resourceCollector.resolvedTemplates.forEach(template => {
- const relativePath = getProjectRelativePath(template.filePath);
- // Do not visit the template if it has been checked before. Inline
- // templates cannot be referenced multiple times.
- if (template.inline || !analyzedFiles.has(relativePath)) {
- rules.forEach(r => r.visitTemplate(template));
- analyzedFiles.add(relativePath);
- }
- });
- resourceCollector.resolvedStylesheets.forEach(stylesheet => {
- const relativePath = getProjectRelativePath(stylesheet.filePath);
- // Do not visit the stylesheet if it has been checked before. Inline
- // stylesheets cannot be referenced multiple times.
- if (stylesheet.inline || !analyzedFiles.has(relativePath)) {
- rules.forEach(r => r.visitStylesheet(stylesheet));
- analyzedFiles.add(relativePath);
- }
- });
- // In some applications, developers will have global stylesheets which are not specified in any
- // Angular component. Therefore we glob up all CSS and SCSS files outside of node_modules and
- // dist. The files will be read by the individual stylesheet rules and checked.
- // TODO(devversion): double-check if we can solve this in a more elegant way.
- glob_1.sync('!(node_modules|dist)/**/*.+(css|scss)', { absolute: true, cwd: basePath })
- .filter(filePath => !resourceCollector.resolvedStylesheets.some(s => s.filePath === filePath))
- .forEach(filePath => {
- const stylesheet = resourceCollector.resolveExternalStylesheet(filePath, null);
- const relativePath = getProjectRelativePath(filePath);
- // do not visit stylesheets which have been referenced from a component.
- if (!analyzedFiles.has(relativePath)) {
- rules.forEach(r => r.visitStylesheet(stylesheet));
- }
- });
- // Commit all recorded updates in the update recorder. We need to perform the
- // replacements per source file in order to ensure that offsets in the TypeScript
- // program are not incorrectly shifted.
- updateRecorderCache.forEach(recorder => tree.commitUpdate(recorder));
- // Collect all failures reported by individual migration rules.
- const ruleFailures = rules.reduce((res, rule) => res.concat(rule.failures), []);
- // In case there are rule failures, print these to the CLI logger as warnings.
- if (ruleFailures.length) {
- ruleFailures.forEach(({ filePath, message, position }) => {
- const normalizedFilePath = core_1.normalize(getProjectRelativePath(filePath));
- const lineAndCharacter = `${position.line + 1}:${position.character + 1}`;
- logger.warn(`${normalizedFilePath}@${lineAndCharacter} - ${message}`);
- });
- }
- return !!ruleFailures.length;
- function getUpdateRecorder(filePath) {
- const treeFilePath = getProjectRelativePath(filePath);
- if (updateRecorderCache.has(treeFilePath)) {
- return updateRecorderCache.get(treeFilePath);
- }
- const treeRecorder = tree.beginUpdate(treeFilePath);
- updateRecorderCache.set(treeFilePath, treeRecorder);
- return treeRecorder;
- }
- function _visitTypeScriptNode(node) {
- rules.forEach(r => r.visitNode(node));
- ts.forEachChild(node, _visitTypeScriptNode);
- resourceCollector.visitNode(node);
- }
- /** Gets the specified path relative to the project root in POSIX format. */
- function getProjectRelativePath(filePath) {
- return path_1.relative(basePath, filePath).replace(/\\/g, '/');
- }
- }
- exports.runMigrationRules = runMigrationRules;
- //# sourceMappingURL=index.js.map
|