fix(compiler-cli): fix extending angularCompilerOptions from non relative extension less TypeScript configuration files (#41349)

support non rooted file of node package and relative path without json extension

close #41343

PR Close #41349
This commit is contained in:
JounQin 2021-03-30 11:24:03 +08:00 committed by atscott
parent dd66da1864
commit f60fb7d92b
2 changed files with 78 additions and 11 deletions

View File

@ -229,13 +229,25 @@ function createParseConfigHost(host: ConfigurationHost, fs = getFileSystem()): t
function getExtendedConfigPath( function getExtendedConfigPath(
configFile: string, extendsValue: string, host: ConfigurationHost, configFile: string, extendsValue: string, host: ConfigurationHost,
fs: FileSystem): AbsoluteFsPath|null { fs: FileSystem): AbsoluteFsPath|null {
let extendedConfigPath: AbsoluteFsPath|null = null; const result = getExtendedConfigPathWorker(configFile, extendsValue, host, fs);
if (result !== null) {
return result;
}
// Try to resolve the paths with a json extension append a json extension to the file in case if
// it is missing and the resolution failed. This is to replicate TypeScript behaviour, see:
// https://github.com/microsoft/TypeScript/blob/294a5a7d784a5a95a8048ee990400979a6bc3a1c/src/compiler/commandLineParser.ts#L2806
return getExtendedConfigPathWorker(configFile, `${extendsValue}.json`, host, fs);
}
function getExtendedConfigPathWorker(
configFile: string, extendsValue: string, host: ConfigurationHost,
fs: FileSystem): AbsoluteFsPath|null {
if (extendsValue.startsWith('.') || fs.isRooted(extendsValue)) { if (extendsValue.startsWith('.') || fs.isRooted(extendsValue)) {
extendedConfigPath = host.resolve(host.dirname(configFile), extendsValue); const extendedConfigPath = host.resolve(host.dirname(configFile), extendsValue);
extendedConfigPath = host.extname(extendedConfigPath) ? if (host.exists(extendedConfigPath)) {
extendedConfigPath : return extendedConfigPath;
absoluteFrom(`${extendedConfigPath}.json`); }
} else { } else {
const parseConfigHost = createParseConfigHost(host, fs); const parseConfigHost = createParseConfigHost(host, fs);
@ -248,16 +260,13 @@ function getExtendedConfigPath(
{moduleResolution: ts.ModuleResolutionKind.NodeJs, resolveJsonModule: true}, {moduleResolution: ts.ModuleResolutionKind.NodeJs, resolveJsonModule: true},
parseConfigHost); parseConfigHost);
if (resolvedModule) { if (resolvedModule) {
extendedConfigPath = absoluteFrom(resolvedModule.resolvedFileName); return absoluteFrom(resolvedModule.resolvedFileName);
} }
} }
if (extendedConfigPath !== null && host.exists(extendedConfigPath)) {
return extendedConfigPath;
}
return null; return null;
} }
export interface PerformCompilationResult { export interface PerformCompilationResult {
diagnostics: Diagnostics; diagnostics: Diagnostics;
program?: api.Program; program?: api.Program;

View File

@ -103,7 +103,7 @@ describe('perform_compile', () => {
})); }));
}); });
it('should merge tsconfig "angularCompilerOptions" when extends point to node package', () => { it('should merge tsconfig "angularCompilerOptions" when extends points to node package', () => {
support.writeFiles({ support.writeFiles({
'tsconfig-level-1.json': `{ 'tsconfig-level-1.json': `{
"extends": "@angular-ru/tsconfig", "extends": "@angular-ru/tsconfig",
@ -136,4 +136,62 @@ describe('perform_compile', () => {
enableIvy: false, enableIvy: false,
})); }));
}); });
it('should merge tsconfig "angularCompilerOptions" when extends points to an extension less non rooted file',
() => {
support.writeFiles({
'tsconfig-level-1.json': `{
"extends": "@1stg/tsconfig/angular",
"angularCompilerOptions": {
"enableIvy": false
}
}`,
'node_modules/@1stg/tsconfig/angular.json': `{
"compilerOptions": {
"strict": true
},
"angularCompilerOptions": {
"skipMetadataEmit": true
}
}`,
'node_modules/@1stg/tsconfig/package.json': `{
"name": "@1stg/tsconfig",
"version": "0.0.0"
}`,
});
const {options} = readConfiguration(path.resolve(basePath, 'tsconfig-level-1.json'));
expect(options).toEqual(jasmine.objectContaining({
strict: true,
skipMetadataEmit: true,
enableIvy: false,
}));
});
it('should merge tsconfig "angularCompilerOptions" when extends points to a non rooted file without json extension',
() => {
support.writeFiles({
'tsconfig-level-1.json': `{
"extends": "./tsconfig.app",
"angularCompilerOptions": {
"enableIvy": false
}
}`,
'tsconfig.app.json': `{
"compilerOptions": {
"strict": true
},
"angularCompilerOptions": {
"skipMetadataEmit": true
}
}`,
});
const {options} = readConfiguration(path.resolve(basePath, 'tsconfig-level-1.json'));
expect(options).toEqual(jasmine.objectContaining({
strict: true,
skipMetadataEmit: true,
enableIvy: false,
}));
});
}); });