1
+ var _ = require ( 'lodash' ) ;
2
+
3
+ module . exports = function mergeDecoratorDocs ( ) {
4
+ return {
5
+ $runAfter : [ 'processing-docs' ] ,
6
+ $runBefore : [ 'docs-processed' ] ,
7
+ docsToMergeInfo : [
8
+ { nameTemplate : _ . template ( '${name}Decorator' ) , decoratorProperty : 'decoratorInterfaceDoc' } ,
9
+ { nameTemplate : _ . template ( '${name}Metadata' ) , decoratorProperty : 'metadataDoc' } ,
10
+ { nameTemplate : _ . template ( '${name}MetadataType' ) , decoratorProperty : 'metadataInterfaceDoc' } ,
11
+ { nameTemplate : _ . template ( '${name}MetadataFactory' ) , decoratorProperty : 'metadataFactoryDoc' }
12
+ ] ,
13
+ $process : function ( docs ) {
14
+
15
+ var docsToMergeInfo = this . docsToMergeInfo ;
16
+ var docsToMerge = Object . create ( null ) ;
17
+
18
+ docs . forEach ( function ( doc ) {
19
+
20
+ // find all the decorators, signified by a call to `makeDecorator(metadata)`
21
+ var makeDecorator = getMakeDecoratorCall ( doc ) ;
22
+ if ( makeDecorator ) {
23
+ doc . docType = 'decorator' ;
24
+ doc . decoratorType = makeDecorator . arguments [ 0 ] . text ;
25
+
26
+ // keep track of the docs that need to be merged into this decorator doc
27
+ docsToMergeInfo . forEach ( function ( info ) {
28
+ docsToMerge [ info . nameTemplate ( { name : doc . name } ) ] = { decoratorDoc : doc , property : info . decoratorProperty } ;
29
+ } ) ;
30
+ }
31
+ } ) ;
32
+
33
+ // merge the metadata docs into the decorator docs
34
+ docs = docs . filter ( function ( doc ) {
35
+ if ( docsToMerge [ doc . name ] ) {
36
+ var decoratorDoc = docsToMerge [ doc . name ] . decoratorDoc ;
37
+ var property = docsToMerge [ doc . name ] . property ;
38
+
39
+ // attach this document to its decorator
40
+ decoratorDoc [ property ] = doc ;
41
+
42
+ // remove doc from its module doc's exports
43
+ doc . moduleDoc . exports = doc . moduleDoc . exports . filter ( function ( exportDoc ) { return exportDoc !== doc ; } ) ;
44
+
45
+ // remove from the overall list of docs to be rendered
46
+ return false ;
47
+ }
48
+ return true ;
49
+ } ) ;
50
+ }
51
+ } ;
52
+ } ;
53
+
54
+ function getMakeDecoratorCall ( doc , type ) {
55
+
56
+ var makeDecoratorFnName = 'make' + ( type || '' ) + 'Decorator' ;
57
+
58
+ var initializer = doc . exportSymbol &&
59
+ doc . exportSymbol . valueDeclaration &&
60
+ doc . exportSymbol . valueDeclaration . initializer ;
61
+
62
+ if ( initializer ) {
63
+ // There appear to be two forms of initializer:
64
+ // export var Injectable: InjectableFactory = <InjectableFactory>makeDecorator(InjectableMetadata);
65
+ // and
66
+ // export var RouteConfig: (configs: RouteDefinition[]) => ClassDecorator = makeDecorator(RouteConfigAnnotation);
67
+ // In the first case, the type assertion `<InjectableFactory>` causes the AST to contain an extra level of expression
68
+ // to hold the new type of the expression.
69
+ if ( initializer . expression && initializer . expression . expression ) {
70
+ initializer = initializer . expression ;
71
+ }
72
+ if ( initializer . expression && initializer . expression . text === makeDecoratorFnName ) {
73
+ return initializer ;
74
+ }
75
+ }
76
+ }
0 commit comments