fix(ngcc): correctly match aliased classes between src and dts files (#34254)
The naïve matching algorithm we previously used to match declarations in source files to declarations in typings files was based only on the name of the thing being declared. This did not handle cases where the declared item had been exported via an alias - a common scenario when one of the two file sets (source or typings) has been flattened, while the other has not. The new algorithm tries to overcome this by creating two maps of export name to declaration (i.e. `Map<string, ts.Declaration>`). One for the source files and one for the typings files. It then joins these two together by matching export names, resulting in a new map that maps source declarations to typings declarations directly (i.e. `Map<ts.Declaration, ts.Declaration>`). This new map can handle the declaration names being different between the source and typings as long as they are ultimately both exported with the same alias name. Further more, there is one map for "public exports", i.e. exported via the root of the source tree (the entry-point), and another map for "private exports", which are exported from individual files in the source tree but not necessarily from the root. This second map can be used to "guess" the mapping between exports in a deep (non-flat) file tree, which can be used by ngcc to add required private exports to the entry-point. Fixes #33593 PR Close #34254
This commit is contained in:
parent
e9fb5fdb89
commit
f22a6eb00e
|
@ -58,33 +58,11 @@ export class PrivateDeclarationsAnalyzer {
|
|||
if (declaration.node.name.text === exportedName) {
|
||||
// This declaration is public so we can remove it from the list
|
||||
privateDeclarations.delete(declaration.node.name);
|
||||
} else if (!this.host.getDtsDeclaration(declaration.node)) {
|
||||
} else {
|
||||
// The referenced declaration is exported publicly but via an alias.
|
||||
// In some cases the original declaration is missing from the dts program, such as
|
||||
// when rolling up (flattening) the dts files.
|
||||
// This is because the original declaration gets renamed to the exported alias.
|
||||
|
||||
// There is a constraint on this which we cannot handle. Consider the following
|
||||
// code:
|
||||
//
|
||||
// /src/entry_point.js:
|
||||
// export {MyComponent as aliasedMyComponent} from './a';
|
||||
// export {MyComponent} from './b';`
|
||||
//
|
||||
// /src/a.js:
|
||||
// export class MyComponent {}
|
||||
//
|
||||
// /src/b.js:
|
||||
// export class MyComponent {}
|
||||
//
|
||||
// //typings/entry_point.d.ts:
|
||||
// export declare class aliasedMyComponent {}
|
||||
// export declare class MyComponent {}
|
||||
//
|
||||
// In this case we would end up matching the `MyComponent` from `/src/a.js` to the
|
||||
// `MyComponent` declared in `/typings/entry_point.d.ts` even though that
|
||||
// declaration is actually for the `MyComponent` in `/src/b.js`.
|
||||
|
||||
exportAliasDeclarations.set(declaration.node.name, exportedName);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ export class CommonJsReflectionHost extends Esm5ReflectionHost {
|
|||
protected topLevelHelperCalls = new Map<string, Map<ts.SourceFile, ts.CallExpression[]>>();
|
||||
protected program: ts.Program;
|
||||
protected compilerHost: ts.CompilerHost;
|
||||
constructor(logger: Logger, isCore: boolean, src: BundleProgram, dts?: BundleProgram|null) {
|
||||
constructor(logger: Logger, isCore: boolean, src: BundleProgram, dts: BundleProgram|null = null) {
|
||||
super(logger, isCore, src, dts);
|
||||
this.program = src.program;
|
||||
this.compilerHost = src.host;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {AbsoluteFsPath} from '../../../src/ngtsc/file_system';
|
||||
import {ClassDeclaration, ClassMember, ClassMemberKind, ConcreteDeclaration, CtorParameter, Declaration, Decorator, TypeScriptReflectionHost, TypeValueReference, isDecoratorIdentifier, reflectObjectLiteral} from '../../../src/ngtsc/reflection';
|
||||
import {isWithinPackage} from '../analysis/util';
|
||||
import {Logger} from '../logging/logger';
|
||||
|
@ -50,7 +49,22 @@ export const CONSTRUCTOR_PARAMS = 'ctorParameters' as ts.__String;
|
|||
* a static method called `ctorParameters`.
|
||||
*/
|
||||
export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements NgccReflectionHost {
|
||||
protected dtsDeclarationMap: Map<string, ts.Declaration>|null;
|
||||
/**
|
||||
* A mapping from source declarations typings declarations, which are both publicly exported.
|
||||
*
|
||||
* There should be one entry for every public export visible from the root file of the source
|
||||
* tree. Note that by definition the key and value declarations will not be in the same TS
|
||||
* program.
|
||||
*/
|
||||
protected publicDtsDeclarationMap: Map<ts.Declaration, ts.Declaration>|null = null;
|
||||
/**
|
||||
* A mapping from source declarations to typings declarations, which are not publicly exported.
|
||||
*
|
||||
* This mapping is a best guess between declarations that happen to be exported from their file by
|
||||
* the same name in both the source and the dts file. Note that by definition the key and value
|
||||
* declarations will not be in the same TS program.
|
||||
*/
|
||||
protected privateDtsDeclarationMap: Map<ts.Declaration, ts.Declaration>|null = null;
|
||||
|
||||
/**
|
||||
* The set of source files that have already been preprocessed.
|
||||
|
@ -83,11 +97,9 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
|||
protected decoratorCache = new Map<ClassDeclaration, DecoratorInfo>();
|
||||
|
||||
constructor(
|
||||
protected logger: Logger, protected isCore: boolean, src: BundleProgram,
|
||||
dts?: BundleProgram|null) {
|
||||
protected logger: Logger, protected isCore: boolean, protected src: BundleProgram,
|
||||
protected dts: BundleProgram|null = null) {
|
||||
super(src.program.getTypeChecker());
|
||||
this.dtsDeclarationMap =
|
||||
dts && this.computeDtsDeclarationMap(dts.path, dts.program, dts.package) || null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -484,16 +496,32 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
|||
* `ts.Program` as the input declaration.
|
||||
*/
|
||||
getDtsDeclaration(declaration: ts.Declaration): ts.Declaration|null {
|
||||
if (!this.dtsDeclarationMap) {
|
||||
if (this.dts === null) {
|
||||
return null;
|
||||
}
|
||||
if (!isNamedDeclaration(declaration)) {
|
||||
throw new Error(
|
||||
`Cannot get the dts file for a declaration that has no name: ${declaration.getText()} in ${declaration.getSourceFile().fileName}`);
|
||||
}
|
||||
return this.dtsDeclarationMap.has(declaration.name.text) ?
|
||||
this.dtsDeclarationMap.get(declaration.name.text) ! :
|
||||
null;
|
||||
|
||||
// Try to retrieve the dts declaration from the public map
|
||||
if (this.publicDtsDeclarationMap === null) {
|
||||
this.publicDtsDeclarationMap = this.computePublicDtsDeclarationMap(this.src, this.dts);
|
||||
}
|
||||
if (this.publicDtsDeclarationMap.has(declaration)) {
|
||||
return this.publicDtsDeclarationMap.get(declaration) !;
|
||||
}
|
||||
|
||||
// No public export, try the private map
|
||||
if (this.privateDtsDeclarationMap === null) {
|
||||
this.privateDtsDeclarationMap = this.computePrivateDtsDeclarationMap(this.src, this.dts);
|
||||
}
|
||||
if (this.privateDtsDeclarationMap.has(declaration)) {
|
||||
return this.privateDtsDeclarationMap.get(declaration) !;
|
||||
}
|
||||
|
||||
// No declaration found at all
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1499,42 +1527,91 @@ export class Esm2015ReflectionHost extends TypeScriptReflectionHost implements N
|
|||
}
|
||||
|
||||
/**
|
||||
* Extract all the class declarations from the dtsTypings program, storing them in a map
|
||||
* where the key is the declared name of the class and the value is the declaration itself.
|
||||
* Create a mapping between the public exports in a src program and the public exports of a dts
|
||||
* program.
|
||||
*
|
||||
* It is possible for there to be multiple class declarations with the same local name.
|
||||
* Only the first declaration with a given name is added to the map; subsequent classes will be
|
||||
* ignored.
|
||||
*
|
||||
* We are most interested in classes that are publicly exported from the entry point, so these
|
||||
* are added to the map first, to ensure that they are not ignored.
|
||||
*
|
||||
* @param dtsRootFileName The filename of the entry-point to the `dtsTypings` program.
|
||||
* @param dtsProgram The program containing all the typings files.
|
||||
* @returns a map of class names to class declarations.
|
||||
* @param src the program bundle containing the source files.
|
||||
* @param dts the program bundle containing the typings files.
|
||||
* @returns a map of source declarations to typings declarations.
|
||||
*/
|
||||
protected computeDtsDeclarationMap(
|
||||
dtsRootFileName: AbsoluteFsPath, dtsProgram: ts.Program,
|
||||
dtsPackage: AbsoluteFsPath): Map<string, ts.Declaration> {
|
||||
protected computePublicDtsDeclarationMap(src: BundleProgram, dts: BundleProgram):
|
||||
Map<ts.Declaration, ts.Declaration> {
|
||||
const declarationMap = new Map<ts.Declaration, ts.Declaration>();
|
||||
const dtsDeclarationMap = new Map<string, ts.Declaration>();
|
||||
const checker = dtsProgram.getTypeChecker();
|
||||
const rootDts = getRootFileOrFail(dts);
|
||||
this.collectDtsExportedDeclarations(dtsDeclarationMap, rootDts, dts.program.getTypeChecker());
|
||||
const rootSrc = getRootFileOrFail(src);
|
||||
this.collectSrcExportedDeclarations(declarationMap, dtsDeclarationMap, rootSrc);
|
||||
return declarationMap;
|
||||
}
|
||||
|
||||
// First add all the classes that are publicly exported from the entry-point
|
||||
const rootFile = dtsProgram.getSourceFile(dtsRootFileName);
|
||||
if (!rootFile) {
|
||||
throw new Error(`The given file ${dtsRootFileName} is not part of the typings program.`);
|
||||
}
|
||||
collectExportedDeclarations(checker, dtsDeclarationMap, rootFile);
|
||||
|
||||
// Now add any additional classes that are exported from individual dts files,
|
||||
// but are not publicly exported from the entry-point.
|
||||
dtsProgram.getSourceFiles().forEach(sourceFile => {
|
||||
if (!isWithinPackage(dtsPackage, sourceFile)) {
|
||||
return;
|
||||
/**
|
||||
* Create a mapping between the "private" exports in a src program and the "private" exports of a
|
||||
* dts program. These exports may be exported from individual files in the src or dts programs,
|
||||
* but not exported from the root file (i.e publicly from the entry-point).
|
||||
*
|
||||
* This mapping is a "best guess" since we cannot guarantee that two declarations that happen to
|
||||
* be exported from a file with the same name are actually equivalent. But this is a reasonable
|
||||
* estimate for the purposes of ngcc.
|
||||
*
|
||||
* @param src the program bundle containing the source files.
|
||||
* @param dts the program bundle containing the typings files.
|
||||
* @returns a map of source declarations to typings declarations.
|
||||
*/
|
||||
protected computePrivateDtsDeclarationMap(src: BundleProgram, dts: BundleProgram):
|
||||
Map<ts.Declaration, ts.Declaration> {
|
||||
const declarationMap = new Map<ts.Declaration, ts.Declaration>();
|
||||
const dtsDeclarationMap = new Map<string, ts.Declaration>();
|
||||
const dtsFiles = getNonRootFiles(dts);
|
||||
const typeChecker = dts.program.getTypeChecker();
|
||||
for (const dtsFile of dtsFiles) {
|
||||
if (isWithinPackage(dts.package, dtsFile)) {
|
||||
this.collectDtsExportedDeclarations(dtsDeclarationMap, dtsFile, typeChecker);
|
||||
}
|
||||
collectExportedDeclarations(checker, dtsDeclarationMap, sourceFile);
|
||||
});
|
||||
return dtsDeclarationMap;
|
||||
}
|
||||
const srcFiles = getNonRootFiles(src);
|
||||
for (const srcFile of srcFiles) {
|
||||
this.collectSrcExportedDeclarations(declarationMap, dtsDeclarationMap, srcFile);
|
||||
}
|
||||
return declarationMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect mappings between names of exported declarations in a file and its actual declaration.
|
||||
*
|
||||
* Any new mappings are added to the `dtsDeclarationMap`.
|
||||
*/
|
||||
protected collectDtsExportedDeclarations(
|
||||
dtsDeclarationMap: Map<string, ts.Declaration>, srcFile: ts.SourceFile,
|
||||
checker: ts.TypeChecker): void {
|
||||
const srcModule = srcFile && checker.getSymbolAtLocation(srcFile);
|
||||
const moduleExports = srcModule && checker.getExportsOfModule(srcModule);
|
||||
if (moduleExports) {
|
||||
moduleExports.forEach(exportedSymbol => {
|
||||
const name = exportedSymbol.name;
|
||||
if (exportedSymbol.flags & ts.SymbolFlags.Alias) {
|
||||
exportedSymbol = checker.getAliasedSymbol(exportedSymbol);
|
||||
}
|
||||
const declaration = exportedSymbol.valueDeclaration;
|
||||
if (declaration && !dtsDeclarationMap.has(name)) {
|
||||
dtsDeclarationMap.set(name, declaration);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected collectSrcExportedDeclarations(
|
||||
declarationMap: Map<ts.Declaration, ts.Declaration>,
|
||||
dtsDeclarationMap: Map<string, ts.Declaration>, srcFile: ts.SourceFile): void {
|
||||
const fileExports = this.getExportsOfModule(srcFile);
|
||||
if (fileExports !== null) {
|
||||
for (const [exportName, {node: declaration}] of fileExports) {
|
||||
if (declaration !== null && dtsDeclarationMap.has(exportName)) {
|
||||
declarationMap.set(declaration, dtsDeclarationMap.get(exportName) !);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1862,29 +1939,6 @@ function isClassMemberType(node: ts.Declaration): node is ts.ClassElement|
|
|||
!ts.isIndexSignatureDeclaration(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect mappings between exported declarations in a source file and its associated
|
||||
* declaration in the typings program.
|
||||
*/
|
||||
function collectExportedDeclarations(
|
||||
checker: ts.TypeChecker, dtsDeclarationMap: Map<string, ts.Declaration>,
|
||||
srcFile: ts.SourceFile): void {
|
||||
const srcModule = srcFile && checker.getSymbolAtLocation(srcFile);
|
||||
const moduleExports = srcModule && checker.getExportsOfModule(srcModule);
|
||||
if (moduleExports) {
|
||||
moduleExports.forEach(exportedSymbol => {
|
||||
if (exportedSymbol.flags & ts.SymbolFlags.Alias) {
|
||||
exportedSymbol = checker.getAliasedSymbol(exportedSymbol);
|
||||
}
|
||||
const declaration = exportedSymbol.valueDeclaration;
|
||||
const name = exportedSymbol.name;
|
||||
if (declaration && !dtsDeclarationMap.has(name)) {
|
||||
dtsDeclarationMap.set(name, declaration);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempt to resolve the variable declaration that the given declaration is assigned to.
|
||||
* For example, for the following code:
|
||||
|
@ -1972,3 +2026,16 @@ function getContainingStatement(node: ts.Node): ts.ExpressionStatement|null {
|
|||
}
|
||||
return node || null;
|
||||
}
|
||||
|
||||
function getRootFileOrFail(bundle: BundleProgram): ts.SourceFile {
|
||||
const rootFile = bundle.program.getSourceFile(bundle.path);
|
||||
if (rootFile === undefined) {
|
||||
throw new Error(`The given rootPath ${rootFile} is not a file of the program.`);
|
||||
}
|
||||
return rootFile;
|
||||
}
|
||||
|
||||
function getNonRootFiles(bundle: BundleProgram): ts.SourceFile[] {
|
||||
const rootFile = bundle.program.getSourceFile(bundle.path);
|
||||
return bundle.program.getSourceFiles().filter(f => f !== rootFile);
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ export class UmdReflectionHost extends Esm5ReflectionHost {
|
|||
protected umdImportPaths = new Map<ts.ParameterDeclaration, string|null>();
|
||||
protected program: ts.Program;
|
||||
protected compilerHost: ts.CompilerHost;
|
||||
constructor(logger: Logger, isCore: boolean, src: BundleProgram, dts?: BundleProgram|null) {
|
||||
constructor(logger: Logger, isCore: boolean, src: BundleProgram, dts: BundleProgram|null = null) {
|
||||
super(logger, isCore, src, dts);
|
||||
this.program = src.program;
|
||||
this.compilerHost = src.host;
|
||||
|
|
|
@ -225,7 +225,7 @@ runInEachFileSystem(() => {
|
|||
expect(analyses).toEqual([{
|
||||
identifier: 'ComponentOne',
|
||||
from: _('/node_modules/test-package/src/a.js'),
|
||||
dtsFrom: null,
|
||||
dtsFrom: _('/node_modules/test-package/typings/entry_point.d.ts'),
|
||||
alias: 'aliasedComponentOne',
|
||||
}]);
|
||||
});
|
||||
|
|
|
@ -650,7 +650,7 @@ exports.D = D;
|
|||
|
||||
TYPINGS_SRC_FILES = [
|
||||
{
|
||||
name: _('/src/index.js'),
|
||||
name: _('/ep/src/index.js'),
|
||||
contents: `
|
||||
var internal = require('./internal');
|
||||
var class1 = require('./class1');
|
||||
|
@ -667,7 +667,7 @@ __export(class2);
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/class1.js'),
|
||||
name: _('/ep/src/class1.js'),
|
||||
contents: `
|
||||
var Class1 = (function() {
|
||||
function Class1() {}
|
||||
|
@ -682,7 +682,7 @@ exports.MissingClass1 = MissingClass1;
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/class2.js'),
|
||||
name: _('/ep/src/class2.js'),
|
||||
contents: `
|
||||
var Class2 = (function() {
|
||||
function Class2() {}
|
||||
|
@ -691,8 +691,8 @@ var Class2 = (function() {
|
|||
exports.Class2 = Class2;
|
||||
`
|
||||
},
|
||||
{name: _('/src/func1.js'), contents: 'function mooFn() {} export {mooFn}'}, {
|
||||
name: _('/src/internal.js'),
|
||||
{name: _('/ep/src/func1.js'), contents: 'function mooFn() {} export {mooFn}'}, {
|
||||
name: _('/ep/src/internal.js'),
|
||||
contents: `
|
||||
var InternalClass = (function() {
|
||||
function InternalClass() {}
|
||||
|
@ -707,7 +707,7 @@ exports.Class2 = Class2;
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/missing-class.js'),
|
||||
name: _('/ep/src/missing-class.js'),
|
||||
contents: `
|
||||
var MissingClass2 = (function() {
|
||||
function MissingClass2() {}
|
||||
|
@ -717,7 +717,7 @@ exports. MissingClass2 = MissingClass2;
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/flat-file.js'),
|
||||
name: _('/ep/src/flat-file.js'),
|
||||
contents: `
|
||||
var Class1 = (function() {
|
||||
function Class1() {}
|
||||
|
@ -731,12 +731,12 @@ var MissingClass2 = (function() {
|
|||
function MissingClass2() {}
|
||||
return MissingClass2;
|
||||
}());
|
||||
var Class3 = (function() {
|
||||
function Class3() {}
|
||||
return Class3;
|
||||
var SourceClass = (function() {
|
||||
function SourceClass() {}
|
||||
return SourceClass;
|
||||
}());
|
||||
exports.Class1 = Class1;
|
||||
exports.xClass3 = Class3;
|
||||
exports.AliasedClass = SourceClass;
|
||||
exports.MissingClass1 = MissingClass1;
|
||||
exports.MissingClass2 = MissingClass2;
|
||||
`
|
||||
|
@ -745,29 +745,38 @@ exports.MissingClass2 = MissingClass2;
|
|||
|
||||
TYPINGS_DTS_FILES = [
|
||||
{
|
||||
name: _('/typings/index.d.ts'),
|
||||
name: _('/ep/typings/index.d.ts'),
|
||||
contents: `
|
||||
import {InternalClass} from './internal';
|
||||
import {mooFn} from './func1';
|
||||
export * from './class1';
|
||||
export * from './class2';
|
||||
`
|
||||
import '../../an_external_lib/index';
|
||||
import {InternalClass} from './internal';
|
||||
import {mooFn} from './func1';
|
||||
export * from './class1';
|
||||
export * from './class2';
|
||||
`
|
||||
},
|
||||
{
|
||||
name: _('/typings/class1.d.ts'),
|
||||
name: _('/ep/typings/class1.d.ts'),
|
||||
contents: `export declare class Class1 {}\nexport declare class OtherClass {}`
|
||||
},
|
||||
{
|
||||
name: _('/typings/class2.d.ts'),
|
||||
contents:
|
||||
`export declare class Class2 {}\nexport declare interface SomeInterface {}\nexport {Class3 as xClass3} from './class3';`
|
||||
name: _('/ep/typings/class2.d.ts'),
|
||||
contents: `
|
||||
export declare class Class2 {}
|
||||
export declare interface SomeInterface {}
|
||||
export {TypingsClass as AliasedClass} from './typings-class';
|
||||
`
|
||||
},
|
||||
{name: _('/typings/func1.d.ts'), contents: 'export declare function mooFn(): void;'},
|
||||
{name: _('/ep/typings/func1.d.ts'), contents: 'export declare function mooFn(): void;'},
|
||||
{
|
||||
name: _('/typings/internal.d.ts'),
|
||||
name: _('/ep/typings/internal.d.ts'),
|
||||
contents: `export declare class InternalClass {}\nexport declare class Class2 {}`
|
||||
},
|
||||
{name: _('/typings/class3.d.ts'), contents: `export declare class Class3 {}`},
|
||||
{
|
||||
name: _('/ep/typings/typings-class.d.ts'),
|
||||
contents: `export declare class TypingsClass {}`
|
||||
},
|
||||
{name: _('/ep/typings/shadow-class.d.ts'), contents: `export declare class ShadowClass {}`},
|
||||
{name: _('/an_external_lib/index.d.ts'), contents: 'export declare class ShadowClass {}'},
|
||||
];
|
||||
|
||||
MODULE_WITH_PROVIDERS_PROGRAM = [
|
||||
|
@ -2140,35 +2149,36 @@ exports.ExternalModule = ExternalModule;
|
|||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/typings/index.d.ts'), _('/'));
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class1 = getDeclaration(
|
||||
bundle.program, _('/src/class1.js'), 'Class1', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/class1.js'), 'Class1', ts.isVariableDeclaration);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class1);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/class1.d.ts'));
|
||||
expect(dtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/ep/typings/class1.d.ts'));
|
||||
});
|
||||
|
||||
it('should find the dts declaration for exported functions', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/typings/index.d.ts'), _('/'));
|
||||
const mooFn =
|
||||
getDeclaration(bundle.program, _('/src/func1.js'), 'mooFn', ts.isFunctionDeclaration);
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/func1.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/ep/typings/func1.d.ts'), _('/'));
|
||||
const mooFn = getDeclaration(
|
||||
bundle.program, _('/ep/src/func1.js'), 'mooFn', ts.isFunctionDeclaration);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
const dtsDeclaration = host.getDtsDeclaration(mooFn);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/func1.d.ts'));
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/func1.d.ts'));
|
||||
});
|
||||
|
||||
it('should return null if there is no matching class in the matching dts file', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/typings/index.d.ts'), _('/'));
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/index.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/ep/typings/index.d.ts'), _('/'));
|
||||
const missingClass = getDeclaration(
|
||||
bundle.program, _('/src/class1.js'), 'MissingClass1', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/class1.js'), 'MissingClass1', ts.isVariableDeclaration);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
expect(host.getDtsDeclaration(missingClass)).toBe(null);
|
||||
|
@ -2177,10 +2187,10 @@ exports.ExternalModule = ExternalModule;
|
|||
it('should return null if there is no matching dts file', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/typings/index.d.ts'), _('/'));
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/index.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/ep/typings/index.d.ts'), _('/'));
|
||||
const missingClass = getDeclaration(
|
||||
bundle.program, _('/src/missing-class.js'), 'MissingClass2',
|
||||
bundle.program, _('/ep/src/missing-class.js'), 'MissingClass2',
|
||||
ts.isVariableDeclaration);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
|
@ -2191,62 +2201,73 @@ exports.ExternalModule = ExternalModule;
|
|||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/typings/index.d.ts'), _('/'));
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/flat-file.js'));
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class1 = getDeclaration(
|
||||
bundle.program, _('/src/flat-file.js'), 'Class1', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/flat-file.js'), 'Class1', ts.isVariableDeclaration);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class1);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/class1.d.ts'));
|
||||
expect(dtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/ep/typings/class1.d.ts'));
|
||||
});
|
||||
|
||||
it('should find aliased exports', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/typings/index.d.ts'), _('/'));
|
||||
const class3 = getDeclaration(
|
||||
bundle.program, _('/src/flat-file.js'), 'Class3', ts.isVariableDeclaration);
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/flat-file.js'));
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const sourceClass = getDeclaration(
|
||||
bundle.program, _('/ep/src/flat-file.js'), 'SourceClass', ts.isVariableDeclaration);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class3);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/class3.d.ts'));
|
||||
const dtsDeclaration = host.getDtsDeclaration(sourceClass);
|
||||
if (dtsDeclaration === null) {
|
||||
return fail('Expected dts class to be found');
|
||||
}
|
||||
if (!isNamedClassDeclaration(dtsDeclaration)) {
|
||||
return fail('Expected a named class to be found.');
|
||||
}
|
||||
expect(dtsDeclaration.name.text).toEqual('TypingsClass');
|
||||
expect(_(dtsDeclaration.getSourceFile().fileName))
|
||||
.toEqual(_('/ep/typings/typings-class.d.ts'));
|
||||
});
|
||||
|
||||
it('should find the dts file that contains a matching class declaration, even if the class is not publicly exported',
|
||||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/typings/index.d.ts'), _('/'));
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const internalClass = getDeclaration(
|
||||
bundle.program, _('/src/internal.js'), 'InternalClass', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/internal.js'), 'InternalClass',
|
||||
ts.isVariableDeclaration);
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(internalClass);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/internal.d.ts'));
|
||||
expect(dtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/ep/typings/internal.d.ts'));
|
||||
});
|
||||
|
||||
it('should prefer the publicly exported class if there are multiple classes with the same name',
|
||||
it('should match publicly and internal exported classes correctly, even if they have the same name',
|
||||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/typings/index.d.ts'), _('/'));
|
||||
const class2 = getDeclaration(
|
||||
bundle.program, _('/src/class2.js'), 'Class2', ts.isVariableDeclaration);
|
||||
const internalClass2 = getDeclaration(
|
||||
bundle.program, _('/src/internal.js'), 'Class2', ts.isVariableDeclaration);
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestDtsBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0], _('/ep'));
|
||||
const host = new CommonJsReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const class2 = getDeclaration(
|
||||
bundle.program, _('/ep/src/class2.js'), 'Class2', isNamedVariableDeclaration);
|
||||
const class2DtsDeclaration = host.getDtsDeclaration(class2);
|
||||
expect(class2DtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/typings/class2.d.ts'));
|
||||
.toEqual(_('/ep/typings/class2.d.ts'));
|
||||
|
||||
const internalClass2 = getDeclaration(
|
||||
bundle.program, _('/ep/src/internal.js'), 'Class2', isNamedVariableDeclaration);
|
||||
const internalClass2DtsDeclaration = host.getDtsDeclaration(internalClass2);
|
||||
expect(internalClass2DtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/typings/class2.d.ts'));
|
||||
.toEqual(_('/ep/typings/internal.d.ts'));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -10,12 +10,12 @@ import * as ts from 'typescript';
|
|||
|
||||
import {absoluteFrom, getFileSystem, getSourceFileOrError} from '../../../src/ngtsc/file_system';
|
||||
import {TestFile, runInEachFileSystem} from '../../../src/ngtsc/file_system/testing';
|
||||
import {ClassMemberKind, CtorParameter, Import, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection';
|
||||
import {ClassMemberKind, CtorParameter, isNamedClassDeclaration, isNamedFunctionDeclaration, isNamedVariableDeclaration} from '../../../src/ngtsc/reflection';
|
||||
import {getDeclaration} from '../../../src/ngtsc/testing';
|
||||
import {loadFakeCore, loadTestFiles} from '../../../test/helpers';
|
||||
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
||||
import {MockLogger} from '../helpers/mock_logger';
|
||||
import {getRootFiles, makeTestBundleProgram} from '../helpers/utils';
|
||||
import {getRootFiles, makeTestBundleProgram, makeTestDtsBundleProgram} from '../helpers/utils';
|
||||
|
||||
import {expectTypeValueReferencesForParameters} from './util';
|
||||
|
||||
|
@ -568,8 +568,12 @@ runInEachFileSystem(() => {
|
|||
{name: _('/ep/src/missing-class.js'), contents: 'export class MissingClass2 {}'},
|
||||
{
|
||||
name: _('/ep/src/flat-file.js'),
|
||||
contents:
|
||||
'export class Class1 {}\nexport class MissingClass1 {}\nexport class MissingClass2 {}\class Class3 {}\nexport {Class3 as xClass3};',
|
||||
contents: `
|
||||
export class Class1 {}
|
||||
export class MissingClass1 {}
|
||||
export class MissingClass2 {}
|
||||
class SourceClass {}
|
||||
export {SourceClass as AliasedClass};`,
|
||||
},
|
||||
{
|
||||
name: _('/ep/src/shadow-class.js'),
|
||||
|
@ -594,20 +598,25 @@ runInEachFileSystem(() => {
|
|||
},
|
||||
{
|
||||
name: _('/ep/typings/class2.d.ts'),
|
||||
contents:
|
||||
`export declare class Class2 {}\nexport declare interface SomeInterface {}\nexport {Class3 as xClass3} from './class3';`
|
||||
contents: `
|
||||
export declare class Class2 {}
|
||||
export declare interface SomeInterface {}
|
||||
export {TypingsClass as AliasedClass} from './typings-class';
|
||||
`
|
||||
},
|
||||
{name: _('/ep/typings/func1.d.ts'), contents: 'export declare function mooFn(): void;'},
|
||||
{
|
||||
name: _('/ep/typings/internal.d.ts'),
|
||||
contents: `export declare class InternalClass {}\nexport declare class Class2 {}`
|
||||
},
|
||||
{name: _('/ep/typings/class3.d.ts'), contents: `export declare class Class3 {}`},
|
||||
{
|
||||
name: _('/ep/typings/typings-class.d.ts'),
|
||||
contents: `export declare class TypingsClass {}`
|
||||
},
|
||||
{name: _('/ep/typings/shadow-class.d.ts'), contents: `export declare class ShadowClass {}`},
|
||||
{name: _('/an_external_lib/index.d.ts'), contents: 'export declare class ShadowClass {}'},
|
||||
];
|
||||
|
||||
|
||||
MODULE_WITH_PROVIDERS_PROGRAM = [
|
||||
{
|
||||
name: _('/src/index.js'),
|
||||
|
@ -1967,8 +1976,8 @@ runInEachFileSystem(() => {
|
|||
it('should find the dts declaration for exported functions', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/func1.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/ep/typings/func1.d.ts'), _('/'));
|
||||
const mooFn = getDeclaration(
|
||||
bundle.program, _('/ep/src/func1.js'), 'mooFn', isNamedFunctionDeclaration);
|
||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
@ -2023,7 +2032,7 @@ runInEachFileSystem(() => {
|
|||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/flat-file.js'));
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class1 = getDeclaration(
|
||||
bundle.program, _('/ep/src/flat-file.js'), 'Class1', isNamedClassDeclaration);
|
||||
|
@ -2036,14 +2045,22 @@ runInEachFileSystem(() => {
|
|||
it('should find aliased exports', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/flat-file.js'));
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class3 = getDeclaration(
|
||||
bundle.program, _('/ep/src/flat-file.js'), 'Class3', isNamedClassDeclaration);
|
||||
const sourceClass = getDeclaration(
|
||||
bundle.program, _('/ep/src/flat-file.js'), 'SourceClass', isNamedClassDeclaration);
|
||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class3);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class3.d.ts'));
|
||||
const dtsDeclaration = host.getDtsDeclaration(sourceClass);
|
||||
if (dtsDeclaration === null) {
|
||||
return fail('Expected dts class to be found');
|
||||
}
|
||||
if (!isNamedClassDeclaration(dtsDeclaration)) {
|
||||
return fail('Expected a named class to be found.');
|
||||
}
|
||||
expect(dtsDeclaration.name.text).toEqual('TypingsClass');
|
||||
expect(_(dtsDeclaration.getSourceFile().fileName))
|
||||
.toEqual(_('/ep/typings/typings-class.d.ts'));
|
||||
});
|
||||
|
||||
it('should find the dts file that contains a matching class declaration, even if the class is not publicly exported',
|
||||
|
@ -2061,25 +2078,25 @@ runInEachFileSystem(() => {
|
|||
.toEqual(_('/ep/typings/internal.d.ts'));
|
||||
});
|
||||
|
||||
it('should prefer the publicly exported class if there are multiple classes with the same name',
|
||||
it('should match publicly and internal exported classes correctly, even if they have the same name',
|
||||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class2 = getDeclaration(
|
||||
bundle.program, _('/ep/src/class2.js'), 'Class2', isNamedClassDeclaration);
|
||||
const internalClass2 = getDeclaration(
|
||||
bundle.program, _('/ep/src/internal.js'), 'Class2', isNamedClassDeclaration);
|
||||
const host = new Esm2015ReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const class2 = getDeclaration(
|
||||
bundle.program, _('/ep/src/class2.js'), 'Class2', isNamedClassDeclaration);
|
||||
const class2DtsDeclaration = host.getDtsDeclaration(class2);
|
||||
expect(class2DtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/ep/typings/class2.d.ts'));
|
||||
|
||||
const internalClass2 = getDeclaration(
|
||||
bundle.program, _('/ep/src/internal.js'), 'Class2', isNamedClassDeclaration);
|
||||
const internalClass2DtsDeclaration = host.getDtsDeclaration(internalClass2);
|
||||
expect(internalClass2DtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/ep/typings/class2.d.ts'));
|
||||
.toEqual(_('/ep/typings/internal.d.ts'));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import {loadFakeCore, loadTestFiles} from '../../../test/helpers';
|
|||
import {Esm2015ReflectionHost} from '../../src/host/esm2015_host';
|
||||
import {Esm5ReflectionHost, getIifeBody} from '../../src/host/esm5_host';
|
||||
import {MockLogger} from '../helpers/mock_logger';
|
||||
import {getRootFiles, makeTestBundleProgram} from '../helpers/utils';
|
||||
import {getRootFiles, makeTestBundleProgram, makeTestDtsBundleProgram} from '../helpers/utils';
|
||||
|
||||
import {expectTypeValueReferencesForParameters} from './util';
|
||||
|
||||
|
@ -648,7 +648,7 @@ runInEachFileSystem(() => {
|
|||
|
||||
TYPINGS_SRC_FILES = [
|
||||
{
|
||||
name: _('/src/index.js'),
|
||||
name: _('/ep/src/index.js'),
|
||||
contents: `
|
||||
import {InternalClass} from './internal';
|
||||
import * as func1 from './func1';
|
||||
|
@ -659,7 +659,7 @@ runInEachFileSystem(() => {
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/class1.js'),
|
||||
name: _('/ep/src/class1.js'),
|
||||
contents: `
|
||||
var Class1 = (function() {
|
||||
function Class1() {}
|
||||
|
@ -673,7 +673,7 @@ runInEachFileSystem(() => {
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/class2.js'),
|
||||
name: _('/ep/src/class2.js'),
|
||||
contents: `
|
||||
var Class2 = (function() {
|
||||
function Class2() {}
|
||||
|
@ -682,8 +682,8 @@ runInEachFileSystem(() => {
|
|||
export {Class2};
|
||||
`
|
||||
},
|
||||
{name: _('/src/func1.js'), contents: 'function mooFn() {} export {mooFn}'}, {
|
||||
name: _('/src/internal.js'),
|
||||
{name: _('/ep/src/func1.js'), contents: 'function mooFn() {} export {mooFn}'}, {
|
||||
name: _('/ep/src/internal.js'),
|
||||
contents: `
|
||||
var InternalClass = (function() {
|
||||
function InternalClass() {}
|
||||
|
@ -697,7 +697,7 @@ runInEachFileSystem(() => {
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/missing-class.js'),
|
||||
name: _('/ep/src/missing-class.js'),
|
||||
contents: `
|
||||
var MissingClass2 = (function() {
|
||||
function MissingClass2() {}
|
||||
|
@ -707,7 +707,7 @@ runInEachFileSystem(() => {
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/flat-file.js'),
|
||||
name: _('/ep/src/flat-file.js'),
|
||||
contents: `
|
||||
var Class1 = (function() {
|
||||
function Class1() {}
|
||||
|
@ -721,19 +721,20 @@ runInEachFileSystem(() => {
|
|||
function MissingClass2() {}
|
||||
return MissingClass2;
|
||||
}());
|
||||
var Class3 = (function() {
|
||||
function Class3() {}
|
||||
return Class3;
|
||||
var SourceClass = (function() {
|
||||
function SourceClass() {}
|
||||
return SourceClass;
|
||||
}());
|
||||
export {Class1, Class3 as xClass3, MissingClass1, MissingClass2};
|
||||
export {Class1, SourceClass as AliasedClass, MissingClass1, MissingClass2};
|
||||
`
|
||||
}
|
||||
];
|
||||
|
||||
TYPINGS_DTS_FILES = [
|
||||
{
|
||||
name: _('/typings/index.d.ts'),
|
||||
name: _('/ep/typings/index.d.ts'),
|
||||
contents: `
|
||||
import '../../an_external_lib/index';
|
||||
import {InternalClass} from './internal';
|
||||
import {mooFn} from './func1';
|
||||
export * from './class1';
|
||||
|
@ -741,20 +742,28 @@ runInEachFileSystem(() => {
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/typings/class1.d.ts'),
|
||||
name: _('/ep/typings/class1.d.ts'),
|
||||
contents: `export declare class Class1 {}\nexport declare class OtherClass {}`
|
||||
},
|
||||
{
|
||||
name: _('/typings/class2.d.ts'),
|
||||
contents:
|
||||
`export declare class Class2 {}\nexport declare interface SomeInterface {}\nexport {Class3 as xClass3} from './class3';`
|
||||
name: _('/ep/typings/class2.d.ts'),
|
||||
contents: `
|
||||
export declare class Class2 {}
|
||||
export declare interface SomeInterface {}
|
||||
export {TypingsClass as AliasedClass} from './typings-class';
|
||||
`
|
||||
},
|
||||
{name: _('/typings/func1.d.ts'), contents: 'export declare function mooFn(): void;'},
|
||||
{name: _('/ep/typings/func1.d.ts'), contents: 'export declare function mooFn(): void;'},
|
||||
{
|
||||
name: _('/typings/internal.d.ts'),
|
||||
name: _('/ep/typings/internal.d.ts'),
|
||||
contents: `export declare class InternalClass {}\nexport declare class Class2 {}`
|
||||
},
|
||||
{name: _('/typings/class3.d.ts'), contents: `export declare class Class3 {}`},
|
||||
{
|
||||
name: _('/ep/typings/typings-class.d.ts'),
|
||||
contents: `export declare class TypingsClass {}`
|
||||
},
|
||||
{name: _('/ep/typings/shadow-class.d.ts'), contents: `export declare class ShadowClass {}`},
|
||||
{name: _('/an_external_lib/index.d.ts'), contents: 'export declare class ShadowClass {}'},
|
||||
];
|
||||
|
||||
MODULE_WITH_PROVIDERS_PROGRAM = [
|
||||
|
@ -2369,24 +2378,24 @@ runInEachFileSystem(() => {
|
|||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class1 = getDeclaration(
|
||||
bundle.program, _('/src/class1.js'), 'Class1', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/class1.js'), 'Class1', ts.isVariableDeclaration);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class1);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/class1.d.ts'));
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts'));
|
||||
});
|
||||
|
||||
it('should find the dts declaration for exported functions', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const mooFn =
|
||||
getDeclaration(bundle.program, _('/src/func1.js'), 'mooFn', ts.isFunctionDeclaration);
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/func1.js'));
|
||||
const dts = makeTestDtsBundleProgram(_('/ep/typings/func1.d.ts'), _('/'));
|
||||
const mooFn = getDeclaration(
|
||||
bundle.program, _('/ep/src/func1.js'), 'mooFn', ts.isFunctionDeclaration);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(mooFn);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/func1.d.ts'));
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/func1.d.ts'));
|
||||
});
|
||||
|
||||
it('should return null if there is no matching class in the matching dts file', () => {
|
||||
|
@ -2395,7 +2404,7 @@ runInEachFileSystem(() => {
|
|||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const missingClass = getDeclaration(
|
||||
bundle.program, _('/src/class1.js'), 'MissingClass1', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/class1.js'), 'MissingClass1', ts.isVariableDeclaration);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
expect(host.getDtsDeclaration(missingClass)).toBe(null);
|
||||
|
@ -2407,7 +2416,8 @@ runInEachFileSystem(() => {
|
|||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const missingClass = getDeclaration(
|
||||
bundle.program, _('/src/missing-class.js'), 'MissingClass2', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/missing-class.js'), 'MissingClass2',
|
||||
ts.isVariableDeclaration);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
expect(host.getDtsDeclaration(missingClass)).toBe(null);
|
||||
|
@ -2417,27 +2427,35 @@ runInEachFileSystem(() => {
|
|||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/flat-file.js'));
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class1 = getDeclaration(
|
||||
bundle.program, _('/src/flat-file.js'), 'Class1', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/flat-file.js'), 'Class1', ts.isVariableDeclaration);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class1);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/class1.d.ts'));
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts'));
|
||||
});
|
||||
|
||||
it('should find aliased exports', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/flat-file.js'));
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class3 = getDeclaration(
|
||||
bundle.program, _('/src/flat-file.js'), 'Class3', ts.isVariableDeclaration);
|
||||
const sourceClass = getDeclaration(
|
||||
bundle.program, _('/ep/src/flat-file.js'), 'SourceClass', ts.isVariableDeclaration);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class3);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/class3.d.ts'));
|
||||
const dtsDeclaration = host.getDtsDeclaration(sourceClass);
|
||||
if (dtsDeclaration === null) {
|
||||
return fail('Expected dts class to be found');
|
||||
}
|
||||
if (!isNamedClassDeclaration(dtsDeclaration)) {
|
||||
return fail('Expected a named class to be found.');
|
||||
}
|
||||
expect(dtsDeclaration.name.text).toEqual('TypingsClass');
|
||||
expect(_(dtsDeclaration.getSourceFile().fileName))
|
||||
.toEqual(_('/ep/typings/typings-class.d.ts'));
|
||||
});
|
||||
|
||||
it('should find the dts file that contains a matching class declaration, even if the class is not publicly exported',
|
||||
|
@ -2447,32 +2465,33 @@ runInEachFileSystem(() => {
|
|||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const internalClass = getDeclaration(
|
||||
bundle.program, _('/src/internal.js'), 'InternalClass', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/internal.js'), 'InternalClass', ts.isVariableDeclaration);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(internalClass);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/internal.d.ts'));
|
||||
expect(dtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/ep/typings/internal.d.ts'));
|
||||
});
|
||||
|
||||
it('should prefer the publicly exported class if there are multiple classes with the same name',
|
||||
it('should match publicly and internal exported classes correctly, even if they have the same name',
|
||||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class2 = getDeclaration(
|
||||
bundle.program, _('/src/class2.js'), 'Class2', ts.isVariableDeclaration);
|
||||
const internalClass2 = getDeclaration(
|
||||
bundle.program, _('/src/internal.js'), 'Class2', ts.isVariableDeclaration);
|
||||
const host = new Esm5ReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const class2 = getDeclaration(
|
||||
bundle.program, _('/ep/src/class2.js'), 'Class2', isNamedVariableDeclaration);
|
||||
const class2DtsDeclaration = host.getDtsDeclaration(class2);
|
||||
expect(class2DtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/typings/class2.d.ts'));
|
||||
.toEqual(_('/ep/typings/class2.d.ts'));
|
||||
|
||||
const internalClass2 = getDeclaration(
|
||||
bundle.program, _('/ep/src/internal.js'), 'Class2', isNamedVariableDeclaration);
|
||||
const internalClass2DtsDeclaration = host.getDtsDeclaration(internalClass2);
|
||||
expect(internalClass2DtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/typings/class2.d.ts'));
|
||||
.toEqual(_('/ep/typings/internal.d.ts'));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -720,7 +720,7 @@ __export(xtra_module);
|
|||
|
||||
TYPINGS_SRC_FILES = [
|
||||
{
|
||||
name: _('/src/index.js'),
|
||||
name: _('/ep/src/index.js'),
|
||||
contents: `
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('./internal'), require('./class1'), require('./class2'), require('./missing-class'), require('./flat-file'), require('./func1')) :
|
||||
|
@ -737,7 +737,7 @@ __export(xtra_module);
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/class1.js'),
|
||||
name: _('/ep/src/class1.js'),
|
||||
contents: `
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||
|
@ -758,7 +758,7 @@ __export(xtra_module);
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/class2.js'),
|
||||
name: _('/ep/src/class2.js'),
|
||||
contents: `
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||
|
@ -773,8 +773,8 @@ __export(xtra_module);
|
|||
})));
|
||||
`
|
||||
},
|
||||
{name: _('/src/func1.js'), contents: 'function mooFn() {} export {mooFn}'}, {
|
||||
name: _('/src/internal.js'),
|
||||
{name: _('/ep/src/func1.js'), contents: 'function mooFn() {} export {mooFn}'}, {
|
||||
name: _('/ep/src/internal.js'),
|
||||
contents: `
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||
|
@ -795,7 +795,7 @@ __export(xtra_module);
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/missing-class.js'),
|
||||
name: _('/ep/src/missing-class.js'),
|
||||
contents: `
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||
|
@ -811,7 +811,7 @@ __export(xtra_module);
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/flat-file.js'),
|
||||
name: _('/ep/src/flat-file.js'),
|
||||
contents: `
|
||||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||
|
@ -830,12 +830,12 @@ __export(xtra_module);
|
|||
function MissingClass2() {}
|
||||
return MissingClass2;
|
||||
}());
|
||||
var Class3 = (function() {
|
||||
function Class3() {}
|
||||
return Class3;
|
||||
var SourceClass = (function() {
|
||||
function SourceClass() {}
|
||||
return SourceClass;
|
||||
}());
|
||||
exports.Class1 = Class1;
|
||||
exports.xClass3 = Class3;
|
||||
exports.Class1 = Class1;
|
||||
exports.AliasedClass = SourceClass;
|
||||
exports.MissingClass1 = MissingClass1;
|
||||
exports.MissingClass2 = MissingClass2;
|
||||
})));
|
||||
|
@ -845,29 +845,38 @@ __export(xtra_module);
|
|||
|
||||
TYPINGS_DTS_FILES = [
|
||||
{
|
||||
name: _('/typings/index.d.ts'),
|
||||
name: _('/ep/typings/index.d.ts'),
|
||||
contents: `
|
||||
import {InternalClass} from './internal';
|
||||
import {mooFn} from './func1';
|
||||
export * from './class1';
|
||||
export * from './class2';
|
||||
`
|
||||
import '../../an_external_lib/index';
|
||||
import {InternalClass} from './internal';
|
||||
import {mooFn} from './func1';
|
||||
export * from './class1';
|
||||
export * from './class2';
|
||||
`
|
||||
},
|
||||
{
|
||||
name: _('/typings/class1.d.ts'),
|
||||
name: _('/ep/typings/class1.d.ts'),
|
||||
contents: `export declare class Class1 {}\nexport declare class OtherClass {}`
|
||||
},
|
||||
{
|
||||
name: _('/typings/class2.d.ts'),
|
||||
contents:
|
||||
`export declare class Class2 {}\nexport declare interface SomeInterface {}\nexport {Class3 as xClass3} from './class3';`
|
||||
name: _('/ep/typings/class2.d.ts'),
|
||||
contents: `
|
||||
export declare class Class2 {}
|
||||
export declare interface SomeInterface {}
|
||||
export {TypingsClass as AliasedClass} from './typings-class';
|
||||
`
|
||||
},
|
||||
{name: _('/typings/func1.d.ts'), contents: 'export declare function mooFn(): void;'},
|
||||
{name: _('/ep/typings/func1.d.ts'), contents: 'export declare function mooFn(): void;'},
|
||||
{
|
||||
name: _('/typings/internal.d.ts'),
|
||||
name: _('/ep/typings/internal.d.ts'),
|
||||
contents: `export declare class InternalClass {}\nexport declare class Class2 {}`
|
||||
},
|
||||
{name: _('/typings/class3.d.ts'), contents: `export declare class Class3 {}`},
|
||||
{
|
||||
name: _('/ep/typings/typings-class.d.ts'),
|
||||
contents: `export declare class TypingsClass {}`
|
||||
},
|
||||
{name: _('/ep/typings/shadow-class.d.ts'), contents: `export declare class ShadowClass {}`},
|
||||
{name: _('/an_external_lib/index.d.ts'), contents: 'export declare class ShadowClass {}'},
|
||||
];
|
||||
|
||||
MODULE_WITH_PROVIDERS_PROGRAM = [
|
||||
|
@ -2240,48 +2249,48 @@ __export(xtra_module);
|
|||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestBundleProgram(_('/typings/index.d.ts'));
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class1 = getDeclaration(
|
||||
bundle.program, _('/src/class1.js'), 'Class1', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/class1.js'), 'Class1', ts.isVariableDeclaration);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class1);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/class1.d.ts'));
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts'));
|
||||
});
|
||||
|
||||
it('should find the dts declaration for exported functions', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestBundleProgram(_('/typings/index.d.ts'));
|
||||
const mooFn =
|
||||
getDeclaration(bundle.program, _('/src/func1.js'), 'mooFn', ts.isFunctionDeclaration);
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/func1.js'));
|
||||
const dts = makeTestBundleProgram(_('/ep/typings/func1.d.ts'));
|
||||
const mooFn = getDeclaration(
|
||||
bundle.program, _('/ep/src/func1.js'), 'mooFn', ts.isFunctionDeclaration);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(mooFn);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/func1.d.ts'));
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/func1.d.ts'));
|
||||
});
|
||||
|
||||
it('should return null if there is no matching class in the matching dts file', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestBundleProgram(_('/typings/index.d.ts'));
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const missingClass = getDeclaration(
|
||||
bundle.program, _('/src/class1.js'), 'MissingClass1', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/class1.js'), 'MissingClass1', ts.isVariableDeclaration);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
expect(host.getDtsDeclaration(missingClass)).toBe(null);
|
||||
});
|
||||
|
||||
it('should return null if there is no matching dts file', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestBundleProgram(_('/typings/index.d.ts'));
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const missingClass = getDeclaration(
|
||||
bundle.program, _('/src/missing-class.js'), 'MissingClass2', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/missing-class.js'), 'MissingClass2',
|
||||
ts.isVariableDeclaration);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
expect(host.getDtsDeclaration(missingClass)).toBe(null);
|
||||
|
@ -2291,62 +2300,91 @@ __export(xtra_module);
|
|||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestBundleProgram(_('/typings/index.d.ts'));
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class1 = getDeclaration(
|
||||
bundle.program, _('/src/flat-file.js'), 'Class1', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/flat-file.js'), 'Class1', ts.isVariableDeclaration);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class1);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/class1.d.ts'));
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts'));
|
||||
});
|
||||
|
||||
it('should find the dts file that contains a matching class declaration, even if the source files do not match',
|
||||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/flat-file.js'));
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const class1 = getDeclaration(
|
||||
bundle.program, _('/ep/src/flat-file.js'), 'Class1', ts.isVariableDeclaration);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class1);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/ep/typings/class1.d.ts'));
|
||||
});
|
||||
|
||||
it('should find aliased exports', () => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestBundleProgram(_('/typings/index.d.ts'));
|
||||
const class3 = getDeclaration(
|
||||
bundle.program, _('/src/flat-file.js'), 'Class3', ts.isVariableDeclaration);
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/flat-file.js'));
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const sourceClass = getDeclaration(
|
||||
bundle.program, _('/ep/src/flat-file.js'), 'SourceClass', ts.isVariableDeclaration);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(class3);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/class3.d.ts'));
|
||||
const dtsDeclaration = host.getDtsDeclaration(sourceClass);
|
||||
if (dtsDeclaration === null) {
|
||||
return fail('Expected dts class to be found');
|
||||
}
|
||||
if (!isNamedClassDeclaration(dtsDeclaration)) {
|
||||
return fail('Expected a named class to be found.');
|
||||
}
|
||||
expect(dtsDeclaration.name.text).toEqual('TypingsClass');
|
||||
expect(_(dtsDeclaration.getSourceFile().fileName))
|
||||
.toEqual(_('/ep/typings/typings-class.d.ts'));
|
||||
});
|
||||
|
||||
it('should find the dts file that contains a matching class declaration, even if the class is not publicly exported',
|
||||
it('should match publicly and internal exported classes correctly, even if they have the same name',
|
||||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestBundleProgram(_('/typings/index.d.ts'));
|
||||
const internalClass = getDeclaration(
|
||||
bundle.program, _('/src/internal.js'), 'InternalClass', ts.isVariableDeclaration);
|
||||
const bundle = makeTestBundleProgram(getRootFiles(TYPINGS_SRC_FILES)[0]);
|
||||
const dts = makeTestBundleProgram(getRootFiles(TYPINGS_DTS_FILES)[0]);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const dtsDeclaration = host.getDtsDeclaration(internalClass);
|
||||
expect(dtsDeclaration !.getSourceFile().fileName).toEqual(_('/typings/internal.d.ts'));
|
||||
const class2 = getDeclaration(
|
||||
bundle.program, _('/ep/src/class2.js'), 'Class2', isNamedVariableDeclaration);
|
||||
const class2DtsDeclaration = host.getDtsDeclaration(class2);
|
||||
expect(class2DtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/ep/typings/class2.d.ts'));
|
||||
|
||||
const internalClass2 = getDeclaration(
|
||||
bundle.program, _('/ep/src/internal.js'), 'Class2', isNamedVariableDeclaration);
|
||||
const internalClass2DtsDeclaration = host.getDtsDeclaration(internalClass2);
|
||||
expect(internalClass2DtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/ep/typings/internal.d.ts'));
|
||||
});
|
||||
|
||||
it('should prefer the publicly exported class if there are multiple classes with the same name',
|
||||
() => {
|
||||
loadTestFiles(TYPINGS_SRC_FILES);
|
||||
loadTestFiles(TYPINGS_DTS_FILES);
|
||||
const bundle = makeTestBundleProgram(_('/src/index.js'));
|
||||
const dts = makeTestBundleProgram(_('/typings/index.d.ts'));
|
||||
const bundle = makeTestBundleProgram(_('/ep/src/index.js'));
|
||||
const dts = makeTestBundleProgram(_('/ep/typings/index.d.ts'));
|
||||
const class2 = getDeclaration(
|
||||
bundle.program, _('/src/class2.js'), 'Class2', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/class2.js'), 'Class2', ts.isVariableDeclaration);
|
||||
const internalClass2 = getDeclaration(
|
||||
bundle.program, _('/src/internal.js'), 'Class2', ts.isVariableDeclaration);
|
||||
bundle.program, _('/ep/src/internal.js'), 'Class2', ts.isVariableDeclaration);
|
||||
const host = new UmdReflectionHost(new MockLogger(), false, bundle, dts);
|
||||
|
||||
const class2DtsDeclaration = host.getDtsDeclaration(class2);
|
||||
expect(class2DtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/typings/class2.d.ts'));
|
||||
.toEqual(_('/ep/typings/class2.d.ts'));
|
||||
|
||||
const internalClass2DtsDeclaration = host.getDtsDeclaration(internalClass2);
|
||||
expect(internalClass2DtsDeclaration !.getSourceFile().fileName)
|
||||
.toEqual(_('/typings/class2.d.ts'));
|
||||
.toEqual(_('/ep/typings/internal.d.ts'));
|
||||
});
|
||||
});
|
||||
|
||||
|
|
|
@ -114,7 +114,7 @@ runInEachFileSystem(() => {
|
|||
`import { Directive } from '@angular/core';\nexport class A {\n foo(x) {\n return x;\n }\n}\nA.decorators = [\n { type: Directive, args: [{ selector: '[a]' }] }\n];\n`
|
||||
};
|
||||
INPUT_DTS_PROGRAM = {
|
||||
name: _('/typings/file.d.ts'),
|
||||
name: _('/node_modules/test-package/typings/file.d.ts'),
|
||||
contents: `export declare class A {\nfoo(x: number): number;\n}\n`
|
||||
};
|
||||
});
|
||||
|
@ -126,7 +126,8 @@ runInEachFileSystem(() => {
|
|||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, privateDeclarationsAnalyses, moduleWithProvidersAnalyses);
|
||||
|
||||
const typingsFile = result.find(f => f.path === _('/typings/file.d.ts')) !;
|
||||
const typingsFile =
|
||||
result.find(f => f.path === _('/node_modules/test-package/typings/file.d.ts')) !;
|
||||
expect(typingsFile.contents)
|
||||
.toContain(
|
||||
'foo(x: number): number;\n static ɵfac: ɵngcc0.ɵɵFactoryDef<A>;\n static ɵdir: ɵngcc0.ɵɵDirectiveDefWithMeta');
|
||||
|
@ -139,7 +140,8 @@ runInEachFileSystem(() => {
|
|||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, privateDeclarationsAnalyses, moduleWithProvidersAnalyses);
|
||||
|
||||
const typingsFile = result.find(f => f.path === _('/typings/file.d.ts')) !;
|
||||
const typingsFile =
|
||||
result.find(f => f.path === _('/node_modules/test-package/typings/file.d.ts')) !;
|
||||
expect(typingsFile.contents).toContain(`\n// ADD IMPORTS\n`);
|
||||
});
|
||||
|
||||
|
@ -158,7 +160,8 @@ runInEachFileSystem(() => {
|
|||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, privateDeclarationsAnalyses, moduleWithProvidersAnalyses);
|
||||
|
||||
const typingsFile = result.find(f => f.path === _('/typings/file.d.ts')) !;
|
||||
const typingsFile =
|
||||
result.find(f => f.path === _('/node_modules/test-package/typings/file.d.ts')) !;
|
||||
expect(typingsFile.contents).toContain(`\n// ADD EXPORTS\n`);
|
||||
});
|
||||
|
||||
|
@ -170,7 +173,8 @@ runInEachFileSystem(() => {
|
|||
const result = renderer.renderProgram(
|
||||
decorationAnalyses, privateDeclarationsAnalyses, moduleWithProvidersAnalyses);
|
||||
|
||||
const typingsFile = result.find(f => f.path === _('/typings/file.d.ts')) !;
|
||||
const typingsFile =
|
||||
result.find(f => f.path === _('/node_modules/test-package/typings/file.d.ts')) !;
|
||||
expect(typingsFile.contents).toContain(`\n// ADD MODUlE WITH PROVIDERS PARAMS\n`);
|
||||
});
|
||||
});
|
||||
|
|
|
@ -483,7 +483,7 @@ export { D };
|
|||
beforeEach(() => {
|
||||
MODULE_WITH_PROVIDERS_PROGRAM = [
|
||||
{
|
||||
name: _('/src/index.js'),
|
||||
name: _('/node_modules/test-package/src/index.js'),
|
||||
contents: `
|
||||
import {ExternalModule} from './module';
|
||||
import {LibraryModule} from 'some-library';
|
||||
|
@ -510,7 +510,7 @@ export { D };
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/src/module.js'),
|
||||
name: _('/node_modules/test-package/src/module.js'),
|
||||
contents: `
|
||||
export class ExternalModule {
|
||||
static withProviders1() { return {ngModule: ExternalModule}; }
|
||||
|
@ -525,7 +525,7 @@ export { D };
|
|||
|
||||
MODULE_WITH_PROVIDERS_DTS_PROGRAM = [
|
||||
{
|
||||
name: _('/typings/index.d.ts'),
|
||||
name: _('/node_modules/test-package/typings/index.d.ts'),
|
||||
contents: `
|
||||
import {ModuleWithProviders} from '@angular/core';
|
||||
export declare class SomeClass {}
|
||||
|
@ -552,7 +552,7 @@ export { D };
|
|||
`
|
||||
},
|
||||
{
|
||||
name: _('/typings/module.d.ts'),
|
||||
name: _('/node_modules/test-package/typings/module.d.ts'),
|
||||
contents: `
|
||||
export interface ModuleWithProviders {}
|
||||
export declare class ExternalModule {
|
||||
|
@ -575,7 +575,8 @@ export { D };
|
|||
const moduleWithProvidersAnalyses =
|
||||
new ModuleWithProvidersAnalyzer(host, referencesRegistry, true)
|
||||
.analyzeProgram(bundle.src.program);
|
||||
const typingsFile = getSourceFileOrError(bundle.dts !.program, _('/typings/index.d.ts'));
|
||||
const typingsFile = getSourceFileOrError(
|
||||
bundle.dts !.program, _('/node_modules/test-package/typings/index.d.ts'));
|
||||
const moduleWithProvidersInfo = moduleWithProvidersAnalyses.get(typingsFile) !;
|
||||
|
||||
const output = new MagicString(MODULE_WITH_PROVIDERS_DTS_PROGRAM[0].contents);
|
||||
|
@ -611,8 +612,8 @@ export { D };
|
|||
const moduleWithProvidersAnalyses =
|
||||
new ModuleWithProvidersAnalyzer(host, referencesRegistry, true)
|
||||
.analyzeProgram(bundle.src.program);
|
||||
const typingsFile =
|
||||
getSourceFileOrError(bundle.dts !.program, _('/typings/module.d.ts'));
|
||||
const typingsFile = getSourceFileOrError(
|
||||
bundle.dts !.program, _('/node_modules/test-package/typings/module.d.ts'));
|
||||
const moduleWithProvidersInfo = moduleWithProvidersAnalyses.get(typingsFile) !;
|
||||
|
||||
const output = new MagicString(MODULE_WITH_PROVIDERS_DTS_PROGRAM[1].contents);
|
||||
|
|
Loading…
Reference in New Issue