@@ -13,14 +13,19 @@ import { NodePath, PluginObj, types } from '@babel/core';
13
13
*/
14
14
const SET_CLASS_METADATA_NAME = 'ɵsetClassMetadata' ;
15
15
16
+ /**
17
+ * Name of the asynchronous Angular class metadata function created by the Angular compiler.
18
+ */
19
+ const SET_CLASS_METADATA_ASYNC_NAME = 'ɵsetClassMetadataAsync' ;
20
+
16
21
/**
17
22
* Provides one or more keywords that if found within the content of a source file indicate
18
23
* that this plugin should be used with a source file.
19
24
*
20
25
* @returns An a string iterable containing one or more keywords.
21
26
*/
22
27
export function getKeywords ( ) : Iterable < string > {
23
- return [ SET_CLASS_METADATA_NAME ] ;
28
+ return [ SET_CLASS_METADATA_NAME , SET_CLASS_METADATA_ASYNC_NAME ] ;
24
29
}
25
30
26
31
/**
@@ -33,6 +38,7 @@ export default function (): PluginObj {
33
38
visitor : {
34
39
CallExpression ( path : NodePath < types . CallExpression > ) {
35
40
const callee = path . node . callee ;
41
+ const callArguments = path . node . arguments ;
36
42
37
43
// The function being called must be the metadata function name
38
44
let calleeName ;
@@ -41,31 +47,58 @@ export default function (): PluginObj {
41
47
} else if ( types . isIdentifier ( callee ) ) {
42
48
calleeName = callee . name ;
43
49
}
44
- if ( calleeName !== SET_CLASS_METADATA_NAME ) {
45
- return ;
46
- }
47
50
48
- // There must be four arguments that meet the following criteria:
49
- // * First must be an identifier
50
- // * Second must be an array literal
51
- const callArguments = path . node . arguments ;
52
51
if (
53
- callArguments . length !== 4 ||
54
- ! types . isIdentifier ( callArguments [ 0 ] ) ||
55
- ! types . isArrayExpression ( callArguments [ 1 ] )
52
+ calleeName !== undefined &&
53
+ ( isRemoveClassMetadataCall ( calleeName , callArguments ) ||
54
+ isRemoveClassmetadataAsyncCall ( calleeName , callArguments ) )
56
55
) {
57
- return ;
58
- }
56
+ // The metadata function is always emitted inside a function expression
57
+ const parent = path . getFunctionParent ( ) ;
59
58
60
- // The metadata function is always emitted inside a function expression
61
- const parent = path . getFunctionParent ( ) ;
62
-
63
- if ( parent && ( parent . isFunctionExpression ( ) || parent . isArrowFunctionExpression ( ) ) ) {
64
- // Replace the metadata function with `void 0` which is the equivalent return value
65
- // of the metadata function.
66
- path . replaceWith ( path . scope . buildUndefinedNode ( ) ) ;
59
+ if ( parent && ( parent . isFunctionExpression ( ) || parent . isArrowFunctionExpression ( ) ) ) {
60
+ // Replace the metadata function with `void 0` which is the equivalent return value
61
+ // of the metadata function.
62
+ path . replaceWith ( path . scope . buildUndefinedNode ( ) ) ;
63
+ }
67
64
}
68
65
} ,
69
66
} ,
70
67
} ;
71
68
}
69
+
70
+ /** Determines if a function call is a call to `setClassMetadata`. */
71
+ function isRemoveClassMetadataCall ( name : string , args : types . CallExpression [ 'arguments' ] ) : boolean {
72
+ // `setClassMetadata` calls have to meet the following criteria:
73
+ // * First must be an identifier
74
+ // * Second must be an array literal
75
+ return (
76
+ name === SET_CLASS_METADATA_NAME &&
77
+ args . length === 4 &&
78
+ types . isIdentifier ( args [ 0 ] ) &&
79
+ types . isArrayExpression ( args [ 1 ] )
80
+ ) ;
81
+ }
82
+
83
+ /** Determines if a function call is a call to `setClassMetadataAsync`. */
84
+ function isRemoveClassmetadataAsyncCall (
85
+ name : string ,
86
+ args : types . CallExpression [ 'arguments' ] ,
87
+ ) : boolean {
88
+ // `setClassMetadataAsync` calls have to meet the following criteria:
89
+ // * First argument must be an identifier.
90
+ // * Second argument must be an inline function.
91
+ // * Third argument must be an inline function.
92
+ return (
93
+ name === SET_CLASS_METADATA_ASYNC_NAME &&
94
+ args . length === 3 &&
95
+ types . isIdentifier ( args [ 0 ] ) &&
96
+ isInlineFunction ( args [ 1 ] ) &&
97
+ isInlineFunction ( args [ 2 ] )
98
+ ) ;
99
+ }
100
+
101
+ /** Determines if a node is an inline function expression. */
102
+ function isInlineFunction ( node : types . Node ) : boolean {
103
+ return types . isFunctionExpression ( node ) || types . isArrowFunctionExpression ( node ) ;
104
+ }
0 commit comments