Skip to content

Commit 40d8d9c

Browse files
committed
fix(tsc-wrapped): generate metadata for exports without module specifier
fixes angular#13327
1 parent ee2ac02 commit 40d8d9c

File tree

3 files changed

+56
-9
lines changed

3 files changed

+56
-9
lines changed

modules/@angular/compiler-cli/test/aot_host_spec.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@ describe('CompilerHost', () => {
175175
foo: {__symbolic: 'class'},
176176
Bar: {__symbolic: 'class', members: {ngOnInit: [{__symbolic: 'method'}]}},
177177
BarChild: {__symbolic: 'class', extends: {__symbolic: 'reference', name: 'Bar'}},
178+
ReExport: {__symbolic: 'reference', module: './lib/utils2', name: 'ReExport'},
178179
},
179180
exports: [{from: './lib/utils2', export: ['Export']}],
180181
}
@@ -212,7 +213,11 @@ const FILES: Entry = {
212213
},
213214
'metadata_versions': {
214215
'v1.d.ts': `
216+
import {ReExport} from './lib/utils2';
217+
export {ReExport};
218+
215219
export {Export} from './lib/utils2';
220+
216221
export declare class Bar {
217222
ngOnInit() {}
218223
}

tools/@angular/tsc-wrapped/src/collector.ts

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import * as ts from 'typescript';
1010

1111
import {Evaluator, errorSymbol, isPrimitive} from './evaluator';
12-
import {ClassMetadata, ConstructorMetadata, FunctionMetadata, MemberMetadata, MetadataEntry, MetadataError, MetadataMap, MetadataObject, MetadataSymbolicBinaryExpression, MetadataSymbolicCallExpression, MetadataSymbolicExpression, MetadataSymbolicIfExpression, MetadataSymbolicIndexExpression, MetadataSymbolicPrefixExpression, MetadataSymbolicReferenceExpression, MetadataSymbolicSelectExpression, MetadataSymbolicSpreadExpression, MetadataValue, MethodMetadata, ModuleExportMetadata, ModuleMetadata, VERSION, isClassMetadata, isConstructorMetadata, isFunctionMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataSymbolicExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSelectExpression, isMethodMetadata} from './schema';
12+
import {ClassMetadata, ConstructorMetadata, FunctionMetadata, MemberMetadata, MetadataEntry, MetadataError, MetadataMap, MetadataSymbolicBinaryExpression, MetadataSymbolicCallExpression, MetadataSymbolicExpression, MetadataSymbolicIfExpression, MetadataSymbolicIndexExpression, MetadataSymbolicPrefixExpression, MetadataSymbolicReferenceExpression, MetadataSymbolicSelectExpression, MetadataSymbolicSpreadExpression, MetadataValue, MethodMetadata, ModuleExportMetadata, ModuleMetadata, VERSION, isClassMetadata, isConstructorMetadata, isFunctionMetadata, isMetadataError, isMetadataGlobalReferenceExpression, isMetadataSymbolicExpression, isMetadataSymbolicReferenceExpression, isMetadataSymbolicSelectExpression, isMethodMetadata} from './schema';
1313
import {Symbols} from './symbols';
1414

1515

@@ -234,6 +234,7 @@ export class MetadataCollector {
234234
}
235235
}
236236
break;
237+
237238
case ts.SyntaxKind.FunctionDeclaration:
238239
if (!(node.flags & ts.NodeFlags.Export)) {
239240
// Report references to this function as an error.
@@ -249,22 +250,36 @@ export class MetadataCollector {
249250
break;
250251
}
251252
});
253+
252254
ts.forEachChild(sourceFile, node => {
253255
switch (node.kind) {
254256
case ts.SyntaxKind.ExportDeclaration:
255257
// Record export declarations
256258
const exportDeclaration = <ts.ExportDeclaration>node;
257-
const moduleSpecifier = exportDeclaration.moduleSpecifier;
259+
const {moduleSpecifier, exportClause} = exportDeclaration;
260+
261+
if (!moduleSpecifier) {
262+
// no module specifier -> export {propName as name};
263+
if (exportClause) {
264+
exportClause.elements.forEach(spec => {
265+
const name = spec.name.text;
266+
const propNode = spec.propertyName || spec.name;
267+
const value: MetadataValue = evaluator.evaluateNode(propNode);
268+
if (!metadata) metadata = {};
269+
metadata[name] = recordEntry(value, node);
270+
});
271+
}
272+
}
273+
258274
if (moduleSpecifier && moduleSpecifier.kind == ts.SyntaxKind.StringLiteral) {
259275
// Ignore exports that don't have string literals as exports.
260276
// This is allowed by the syntax but will be flagged as an error by the type checker.
261277
const from = (<ts.StringLiteral>moduleSpecifier).text;
262278
const moduleExport: ModuleExportMetadata = {from};
263-
if (exportDeclaration.exportClause) {
264-
moduleExport.export = exportDeclaration.exportClause.elements.map(
265-
element => element.propertyName ?
266-
{name: element.propertyName.text, as: element.name.text} :
267-
element.name.text);
279+
if (exportClause) {
280+
moduleExport.export = exportClause.elements.map(
281+
spec => spec.propertyName ? {name: spec.propertyName.text, as: spec.name.text} :
282+
spec.name.text);
268283
}
269284
if (!exports) exports = [];
270285
exports.push(moduleExport);
@@ -281,6 +296,7 @@ export class MetadataCollector {
281296
}
282297
// Otherwise don't record metadata for the class.
283298
break;
299+
284300
case ts.SyntaxKind.FunctionDeclaration:
285301
// Record functions that return a single value. Record the parameter
286302
// names substitution will be performed by the StaticReflector.
@@ -297,6 +313,7 @@ export class MetadataCollector {
297313
}
298314
}
299315
break;
316+
300317
case ts.SyntaxKind.EnumDeclaration:
301318
if (node.flags & ts.NodeFlags.Export) {
302319
const enumDeclaration = <ts.EnumDeclaration>node;
@@ -332,14 +349,15 @@ export class MetadataCollector {
332349
} else {
333350
nextDefaultValue =
334351
recordEntry(errorSym('Unsuppported enum member name', member.name), node);
335-
};
352+
}
336353
}
337354
if (writtenMembers) {
338355
if (!metadata) metadata = {};
339356
metadata[enumName] = recordEntry(enumValueHolder, node);
340357
}
341358
}
342359
break;
360+
343361
case ts.SyntaxKind.VariableStatement:
344362
const variableStatement = <ts.VariableStatement>node;
345363
for (const variableDeclaration of variableStatement.declarationList.declarations) {
@@ -373,7 +391,7 @@ export class MetadataCollector {
373391
}
374392
} else {
375393
// Destructuring (or binding) declarations are not supported,
376-
// var {<identifier>[, <identifer>]+} = <expression>;
394+
// var {<identifier>[, <identifier>]+} = <expression>;
377395
// or
378396
// var [<identifier>[, <identifier}+] = <expression>;
379397
// are not supported.

tools/@angular/tsc-wrapped/test/collector.spec.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ describe('Collector', () => {
3939
'local-symbol-ref-func-dynamic.ts',
4040
'private-enum.ts',
4141
're-exports.ts',
42+
're-exports-2.ts',
4243
'static-field-reference.ts',
4344
'static-method.ts',
4445
'static-method-call.ts',
@@ -527,6 +528,23 @@ describe('Collector', () => {
527528
]);
528529
});
529530

531+
it('should be able to collect exports with no module specifier', () => {
532+
const source = program.getSourceFile('/re-exports-2.ts');
533+
const metadata = collector.getMetadata(source);
534+
expect(metadata.metadata).toEqual({
535+
OtherModule: {__symbolic: 'reference', module: './static-field-reference', name: 'Foo'},
536+
MyOtherModule: {__symbolic: 'reference', module: './static-field', name: 'MyModule'},
537+
// TODO(vicb): support exported symbols - https://github.com/angular/angular/issues/13473
538+
MyClass: {
539+
__symbolic: 'error',
540+
message: 'Reference to non-exported class',
541+
line: 3,
542+
character: 4,
543+
context: {className: 'MyClass'}
544+
},
545+
});
546+
});
547+
530548
it('should collect an error symbol if collecting a reference to a non-exported symbol', () => {
531549
const source = program.getSourceFile('/local-symbol-ref.ts');
532550
const metadata = collector.getMetadata(source);
@@ -983,6 +1001,12 @@ const FILES: Directory = {
9831001
export {Foo as OtherModule} from './static-field-reference';
9841002
export * from 'angular2/core';
9851003
`,
1004+
're-exports-2.ts': `
1005+
import {MyModule} from './static-field';
1006+
import {Foo as OtherModule} from './static-field-reference';
1007+
class MyClass {}
1008+
export {OtherModule, MyModule as MyOtherModule, MyClass};
1009+
`,
9861010
'local-symbol-ref.ts': `
9871011
import {Component, Validators} from 'angular2/core';
9881012

0 commit comments

Comments
 (0)