Skip to content

Commit 8e41f26

Browse files
devversionmmalerba
authored andcommitted
refactor: improve tsconfig parsing for update-tool
Improves the tsconfig parsing for the update-tool so that errors are actually reported. We do not want to silently proceed migrating a project if the tsconfig does not exist, could not be parsed etc. Currently this works by accident as we just let TypeScript include/glob for all TS files in the project directory.
1 parent 35462ba commit 8e41f26

File tree

7 files changed

+64
-5
lines changed

7 files changed

+64
-5
lines changed

src/cdk/schematics/ng-update/devkit-migration-rule.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,8 @@ export function createMigrationSchematicRule(
9898
// In some applications, developers will have global stylesheets which are not
9999
// specified in any Angular component. Therefore we glob up all CSS and SCSS files
100100
// in the project and migrate them if needed.
101-
// TODO: rework this to collect global stylesheets from the workspace config. COMP-280.
101+
// TODO: rework this to collect global stylesheets from the workspace config.
102+
// TODO: https://github.com/angular/components/issues/24032.
102103
const additionalStylesheetPaths = findStylesheetFiles(tree, project.root);
103104

104105
if (buildTsconfigPath !== null) {

src/cdk/schematics/ng-update/public-api.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
export * from './data/index';
1010
export * from './devkit-migration';
1111
export * from './devkit-migration-rule';
12+
export * from './devkit-file-system';
1213
export * from './html-parsing/angular';
1314
export * from './html-parsing/elements';
1415
export * from './typescript/base-types';

src/cdk/schematics/testing/test-case-setup.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ export async function createTestCaseSetup(
7373
runner.logger.subscribe(entry => (logOutput += `${entry.message}\n`));
7474
const {appTree, writeFile} = await createFileSystemTestApp(runner);
7575

76-
_patchTypeScriptDefaultLib(appTree);
76+
patchDevkitTreeToExposeTypeScript(appTree);
7777

7878
// Write each test-case input to the file-system. This is necessary because otherwise
7979
// TypeScript compiler API won't be able to pick up the test cases.
@@ -219,7 +219,7 @@ export function defineJasmineTestCases(
219219
* default library typings. These need to be readable in unit tests because otherwise
220220
* type checking within migration rules is not working as in real applications.
221221
*/
222-
export function _patchTypeScriptDefaultLib(tree: Tree) {
222+
export function patchDevkitTreeToExposeTypeScript<T extends Tree>(tree: T): T {
223223
const _originalRead = tree.read;
224224
tree.read = function (filePath: Path) {
225225
// In case a file within the TypeScript package is requested, we read the file from
@@ -232,4 +232,5 @@ export function _patchTypeScriptDefaultLib(tree: Tree) {
232232
return _originalRead.call(this, filePath);
233233
}
234234
};
235+
return tree;
235236
}

src/cdk/schematics/update-tool/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,8 @@ export class UpdateProject<Context> {
183183
/**
184184
* Creates a program form the specified tsconfig and patches the host
185185
* to read files and directories through the given file system.
186+
*
187+
* @throws {TsconfigParseError} If the tsconfig could not be parsed.
186188
*/
187189
static createProgramFromTsconfig(tsconfigPath: WorkspacePath, fs: FileSystem): ts.Program {
188190
const parsed = parseTsconfigFile(fs.resolve(tsconfigPath), fs);
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import * as ts from 'typescript';
10+
import {FileSystem} from '../file-system';
11+
import {createFormatDiagnosticHost} from './virtual-host';
12+
13+
/** Formats the specified diagnostics with respect to the given file system. */
14+
export function formatDiagnostics(diagnostics: ts.Diagnostic[], fileSystem: FileSystem): string {
15+
const formatHost = createFormatDiagnosticHost(fileSystem);
16+
return ts.formatDiagnosticsWithColorAndContext(diagnostics, formatHost);
17+
}

src/cdk/schematics/update-tool/utils/parse-tsconfig.ts

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,16 +10,44 @@ import * as ts from 'typescript';
1010
import {FileSystem, WorkspacePath} from '../file-system';
1111
import {FileSystemHost} from './virtual-host';
1212
import {dirname} from 'path';
13+
import {formatDiagnostics} from './diagnostics';
1314

15+
/** Class capturing a tsconfig parse error. */
16+
export class TsconfigParseError extends Error {}
17+
18+
/**
19+
* Attempts to parse the specified tsconfig file.
20+
*
21+
* @throws {TsconfigParseError} If the tsconfig could not be read or parsed.
22+
*/
1423
export function parseTsconfigFile(
1524
tsconfigPath: WorkspacePath,
1625
fileSystem: FileSystem,
1726
): ts.ParsedCommandLine {
18-
const {config} = ts.readConfigFile(tsconfigPath, p => fileSystem.read(fileSystem.resolve(p))!);
19-
return ts.parseJsonConfigFileContent(
27+
if (!fileSystem.fileExists(tsconfigPath)) {
28+
throw new TsconfigParseError(`Tsconfig cannot not be read: ${tsconfigPath}`);
29+
}
30+
31+
const {config, error} = ts.readConfigFile(
32+
tsconfigPath,
33+
p => fileSystem.read(fileSystem.resolve(p))!,
34+
);
35+
36+
// If there is a config reading error, we never attempt to parse the config.
37+
if (error) {
38+
throw new TsconfigParseError(formatDiagnostics([error], fileSystem));
39+
}
40+
41+
const parsed = ts.parseJsonConfigFileContent(
2042
config,
2143
new FileSystemHost(fileSystem),
2244
dirname(tsconfigPath),
2345
{},
2446
);
47+
48+
if (parsed.errors.length) {
49+
throw new TsconfigParseError(formatDiagnostics(parsed.errors, fileSystem));
50+
}
51+
52+
return parsed;
2553
}

src/cdk/schematics/update-tool/utils/virtual-host.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,3 +114,12 @@ export function createFileSystemCompilerHost(
114114

115115
return host;
116116
}
117+
118+
/** Creates a format diagnostic host that works with the given file system. */
119+
export function createFormatDiagnosticHost(fileSystem: FileSystem): ts.FormatDiagnosticsHost {
120+
return {
121+
getCanonicalFileName: p => fileSystem.resolve(p),
122+
getCurrentDirectory: () => '/',
123+
getNewLine: () => '\n',
124+
};
125+
}

0 commit comments

Comments
 (0)