Skip to content

Commit 2af3eea

Browse files
committed
fix(@angular-devkit/build-angular): emit warning when using extract-i18n in Ivy
i18n is not yet implemented in Ivy, we should emit a warning stating this and exit gracefully. This also swaps the readTsConfig logic to use `@angular/compiler-cli` instead of `typescript`. This is needed because when parsing the tsconfig, typescript is not aware of `angularCompilerOptions` and will not merged them if they are at un upper level tsconfig file when using `extends`. Closes #14225
1 parent 3d25d4c commit 2af3eea

File tree

5 files changed

+36
-19
lines changed

5 files changed

+36
-19
lines changed

packages/angular_devkit/build_angular/package.json

+1
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
"zone.js": "^0.9.1"
8787
},
8888
"peerDependencies": {
89+
"@angular/compiler-cli": ">=8.0.0-beta.0 < 9.0.0",
8990
"typescript": ">=3.1 < 3.5"
9091
}
9192
}

packages/angular_devkit/build_angular/src/angular-cli-files/models/build-options.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,8 @@
99
// TODO: cleanup this file, it's copied as is from Angular CLI.
1010

1111
import { logging } from '@angular-devkit/core';
12-
import { ParsedCommandLine, ScriptTarget } from 'typescript';
12+
import { ParsedConfiguration } from '@angular/compiler-cli';
13+
import { ScriptTarget } from 'typescript';
1314
import {
1415
AssetPatternClass,
1516
Budget,
@@ -93,7 +94,7 @@ export interface WebpackConfigOptions<T = BuildOptions> {
9394
projectRoot: string;
9495
sourceRoot?: string;
9596
buildOptions: T;
96-
tsConfig: ParsedCommandLine;
97+
tsConfig: ParsedConfiguration;
9798
tsConfigPath: string;
9899
supportES2015: boolean;
99100
}

packages/angular_devkit/build_angular/src/angular-cli-files/utilities/read-tsconfig.ts

+21-14
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,30 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8-
// TODO: cleanup this file, it's copied as is from Angular CLI.
8+
9+
import { ParsedConfiguration } from '@angular/compiler-cli';
910
import * as path from 'path';
1011

11-
export function readTsconfig(tsconfigPath: string) {
12-
// build-angular has a peer dependency on typescript
13-
const projectTs = require('typescript') as typeof import('typescript');
14-
const configResult = projectTs.readConfigFile(tsconfigPath, projectTs.sys.readFile);
15-
const tsConfig = projectTs.parseJsonConfigFileContent(configResult.config, projectTs.sys,
16-
path.dirname(tsconfigPath), undefined, tsconfigPath);
12+
/**
13+
* Reads and parses a given TsConfig file.
14+
*
15+
* @param tsconfigPath - An absolute or relative path from 'workspaceRoot' of the tsconfig file.
16+
* @param workspaceRoot - workspaceRoot root location when provided
17+
* it will resolve 'tsconfigPath' from this path.
18+
*/
19+
export function readTsconfig(tsconfigPath: string, workspaceRoot?: string): ParsedConfiguration {
20+
const tsConfigFullPath = workspaceRoot
21+
? path.resolve(workspaceRoot, tsconfigPath)
22+
: tsconfigPath;
23+
24+
// We use 'ng' instead of 'ts' here because 'ts' is not aware of 'angularCompilerOptions'
25+
// and will not merged them if they are at un upper level tsconfig file when using `extends`.
26+
const ng: typeof import('@angular/compiler-cli') = require('@angular/compiler-cli');
1727

18-
if (tsConfig.errors.length > 0) {
19-
throw new Error(
20-
`Errors found while reading ${tsconfigPath}:\n ${
21-
tsConfig.errors.map(e => e.messageText).join('\n ')
22-
}`,
23-
);
28+
const configResult = ng.readConfiguration(tsConfigFullPath);
29+
if (configResult.errors && configResult.errors.length) {
30+
throw new Error(ng.formatDiagnostics(configResult.errors));
2431
}
2532

26-
return tsConfig;
33+
return configResult;
2734
}

packages/angular_devkit/build_angular/src/browser/index.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -199,9 +199,7 @@ export function buildWebpackBrowser(
199199
normalize(workspace.getProject(projectName).root),
200200
);
201201

202-
const tsConfigPath = path.resolve(getSystemPath(workspace.root), options.tsConfig);
203-
const tsConfig = readTsconfig(tsConfigPath);
204-
202+
const tsConfig = readTsconfig(options.tsConfig, context.workspaceRoot);
205203
const target = tsConfig.options.target || ScriptTarget.ES5;
206204
const buildBrowserFeatures = new BuildBrowserFeatures(
207205
getSystemPath(projectRoot),

packages/angular_devkit/build_angular/src/extract-i18n/index.ts

+10
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import {
2020
getStatsConfig,
2121
getStylesConfig,
2222
} from '../angular-cli-files/models/webpack-configs';
23+
import { readTsconfig } from '../angular-cli-files/utilities/read-tsconfig';
2324
import { statsErrorsToString, statsWarningsToString } from '../angular-cli-files/utilities/stats';
2425
import { Schema as BrowserBuilderOptions } from '../browser/schema';
2526
import { Version } from '../utils/version';
@@ -58,6 +59,15 @@ async function execute(options: ExtractI18nBuilderOptions, context: BuilderConte
5859
await context.getBuilderNameForTarget(browserTarget),
5960
);
6061

62+
// FIXME: i18n is not yet implemented in Ivy
63+
// We should display a warning and exit gracefully.
64+
const { options: compilerOptions } = readTsconfig(browserOptions.tsConfig, context.workspaceRoot);
65+
if (compilerOptions.enableIvy) {
66+
context.logger.warn('We are sorry but i18n is not yet implemented in Ivy.');
67+
68+
return { success: true };
69+
}
70+
6171
// We need to determine the outFile name so that AngularCompiler can retrieve it.
6272
let outFile = options.outFile || getI18nOutfile(options.i18nFormat);
6373
if (options.outputPath) {

0 commit comments

Comments
 (0)