@@ -13,14 +13,19 @@ import { NodePath, PluginObj, types } from '@babel/core';
1313 */
1414const SET_CLASS_METADATA_NAME = 'ɵsetClassMetadata' ;
1515
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+
1621/**
1722 * Provides one or more keywords that if found within the content of a source file indicate
1823 * that this plugin should be used with a source file.
1924 *
2025 * @returns An a string iterable containing one or more keywords.
2126 */
2227export function getKeywords ( ) : Iterable < string > {
23- return [ SET_CLASS_METADATA_NAME ] ;
28+ return [ SET_CLASS_METADATA_NAME , SET_CLASS_METADATA_ASYNC_NAME ] ;
2429}
2530
2631/**
@@ -33,6 +38,7 @@ export default function (): PluginObj {
3338 visitor : {
3439 CallExpression ( path : NodePath < types . CallExpression > ) {
3540 const callee = path . node . callee ;
41+ const callArguments = path . node . arguments ;
3642
3743 // The function being called must be the metadata function name
3844 let calleeName ;
@@ -41,31 +47,58 @@ export default function (): PluginObj {
4147 } else if ( types . isIdentifier ( callee ) ) {
4248 calleeName = callee . name ;
4349 }
44- if ( calleeName !== SET_CLASS_METADATA_NAME ) {
45- return ;
46- }
4750
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 ;
5251 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 ) )
5655 ) {
57- return ;
58- }
56+ // The metadata function is always emitted inside a function expression
57+ const parent = path . getFunctionParent ( ) ;
5958
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+ }
6764 }
6865 } ,
6966 } ,
7067 } ;
7168}
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