fix(ivy): ngcc - compute potential d.ts files from .js files (#31411)

If a package delcares a class internally on an NgModule, ngcc
needs to be able to add a public export to this class's type.

Previously, if the typing file for the declared is not imported
from the typings entry-point file, then ngcc cannot find it.
Now we try to guess the .d.ts files from the equivalent .js
files.

PR Close #31411
This commit is contained in:
Pete Bacon Darwin
2019-07-03 19:31:33 +01:00
committed by Jason Aden
parent e6f1b04cd5
commit 83b19bf1a2
4 changed files with 92 additions and 13 deletions

View File

@ -28,6 +28,7 @@ runInEachFileSystem(() => {
{
name: _('/node_modules/test/public_api.d.ts'),
contents: `
// Note: no import from './internal';
export * from "test/secondary";
export * from "./nested";
export declare class TestClass {};
@ -36,6 +37,7 @@ runInEachFileSystem(() => {
{
name: _('/node_modules/test/public_api.js'),
contents: `
import {internal} from './internal';
export * from "test/secondary";
export * from "./nested";
export const TestClass = function() {};
@ -55,6 +57,11 @@ runInEachFileSystem(() => {
export const RootClass = function() {};
`
},
{
name: _('/node_modules/test/internal.d.ts'),
contents: `export declare function internal(): void;`
},
{name: _('/node_modules/test/internal.js'), contents: `export function internal() {}`},
{name: _('/node_modules/test/nested/index.d.ts'), contents: 'export * from "../root";'},
{name: _('/node_modules/test/nested/index.js'), contents: 'export * from "../root";'},
{name: _('/node_modules/test/es2015/index.js'), contents: 'export * from "./public_api";'},
@ -147,6 +154,7 @@ runInEachFileSystem(() => {
'/node_modules/test/public_api.js',
'/node_modules/test/nested/index.js',
'/node_modules/test/root.js',
'/node_modules/test/internal.js',
// Modules from a secondary entry-point should be declaration files
'/node_modules/test/secondary/public_api.d.ts',
@ -170,5 +178,47 @@ runInEachFileSystem(() => {
'/node_modules/other/index.d.ts',
].map(p => absoluteFrom(p).toString())));
});
it('should include equivalently named, internally imported, src files in the typings program, if `mirrorDtsFromSrc` is true',
() => {
setupMockFileSystem();
const fs = getFileSystem();
const entryPoint: EntryPoint = {
name: 'test',
packageJson: {name: 'test'},
package: absoluteFrom('/node_modules/test'),
path: absoluteFrom('/node_modules/test'),
typings: absoluteFrom('/node_modules/test/index.d.ts'),
compiledByAngular: true,
};
const esm5bundle = makeEntryPointBundle(
fs, entryPoint, './index.js', false, 'esm5', 'esm5', /* transformDts */ true,
/* pathMappings */ undefined, /* mirrorDtsFromSrc */ true) !;
expect(esm5bundle.src.program.getSourceFiles().map(sf => sf.fileName))
.toContain(absoluteFrom('/node_modules/test/internal.js'));
expect(esm5bundle.dts !.program.getSourceFiles().map(sf => sf.fileName))
.toContain(absoluteFrom('/node_modules/test/internal.d.ts'));
});
it('should ignore, internally imported, src files in the typings program, if `mirrorDtsFromSrc` is false',
() => {
setupMockFileSystem();
const fs = getFileSystem();
const entryPoint: EntryPoint = {
name: 'test',
packageJson: {name: 'test'},
package: absoluteFrom('/node_modules/test'),
path: absoluteFrom('/node_modules/test'),
typings: absoluteFrom('/node_modules/test/index.d.ts'),
compiledByAngular: true,
};
const esm5bundle = makeEntryPointBundle(
fs, entryPoint, './index.js', false, 'esm5', 'esm5', /* transformDts */ true,
/* pathMappings */ undefined, /* mirrorDtsFromSrc */ false) !;
expect(esm5bundle.src.program.getSourceFiles().map(sf => sf.fileName))
.toContain(absoluteFrom('/node_modules/test/internal.js'));
expect(esm5bundle.dts !.program.getSourceFiles().map(sf => sf.fileName))
.not.toContain(absoluteFrom('/node_modules/test/internal.d.ts'));
});
});
});