66 * found in the LICENSE file at https://angular.io/license
77 */
88
9- import { NodePath , PluginObj , types } from '@babel/core' ;
9+ import type { NodePath , PluginObj } from '@babel/core' ;
1010
1111/**
1212 * The name of the Angular class metadata function created by the Angular compiler.
@@ -30,9 +30,19 @@ const SET_CLASS_DEBUG_INFO_NAME = 'ɵsetClassDebugInfo';
3030 * @returns An a string iterable containing one or more keywords.
3131 */
3232export function getKeywords ( ) : Iterable < string > {
33- return [ SET_CLASS_METADATA_NAME , SET_CLASS_METADATA_ASYNC_NAME , SET_CLASS_DEBUG_INFO_NAME ] ;
33+ return Object . keys ( angularMetadataFunctions ) ;
3434}
3535
36+ /**
37+ * An object map of function names and related value checks for discovery of Angular generated
38+ * metadata calls.
39+ */
40+ const angularMetadataFunctions : Record < string , ( args : NodePath [ ] ) => boolean > = {
41+ [ SET_CLASS_METADATA_NAME ] : isSetClassMetadataCall ,
42+ [ SET_CLASS_METADATA_ASYNC_NAME ] : isSetClassMetadataAsyncCall ,
43+ [ SET_CLASS_DEBUG_INFO_NAME ] : isSetClassDebugInfoCall ,
44+ } ;
45+
3646/**
3747 * A babel plugin factory function for eliding the Angular class metadata function (`ɵsetClassMetadata`).
3848 *
@@ -41,23 +51,27 @@ export function getKeywords(): Iterable<string> {
4151export default function ( ) : PluginObj {
4252 return {
4353 visitor : {
44- CallExpression ( path : NodePath < types . CallExpression > ) {
45- const callee = path . node . callee ;
46- const callArguments = path . node . arguments ;
54+ CallExpression ( path ) {
55+ const callee = path . get ( 'callee' ) ;
4756
4857 // The function being called must be the metadata function name
4958 let calleeName ;
50- if ( types . isMemberExpression ( callee ) && types . isIdentifier ( callee . property ) ) {
51- calleeName = callee . property . name ;
52- } else if ( types . isIdentifier ( callee ) ) {
53- calleeName = callee . name ;
59+ if ( callee . isMemberExpression ( ) ) {
60+ const calleeProperty = callee . get ( 'property' ) ;
61+ if ( calleeProperty . isIdentifier ( ) ) {
62+ calleeName = calleeProperty . node . name ;
63+ }
64+ } else if ( callee . isIdentifier ( ) ) {
65+ calleeName = callee . node . name ;
66+ }
67+
68+ if ( ! calleeName ) {
69+ return ;
5470 }
5571
5672 if (
57- calleeName !== undefined &&
58- ( isRemoveClassMetadataCall ( calleeName , callArguments ) ||
59- isRemoveClassmetadataAsyncCall ( calleeName , callArguments ) ||
60- isSetClassDebugInfoCall ( calleeName , callArguments ) )
73+ Object . hasOwn ( angularMetadataFunctions , calleeName ) &&
74+ angularMetadataFunctions [ calleeName ] ( path . get ( 'arguments' ) )
6175 ) {
6276 // The metadata function is always emitted inside a function expression
6377 const parent = path . getFunctionParent ( ) ;
@@ -74,47 +88,41 @@ export default function (): PluginObj {
7488}
7589
7690/** Determines if a function call is a call to `setClassMetadata`. */
77- function isRemoveClassMetadataCall ( name : string , args : types . CallExpression [ 'arguments' ] ) : boolean {
91+ function isSetClassMetadataCall ( callArguments : NodePath [ ] ) : boolean {
7892 // `setClassMetadata` calls have to meet the following criteria:
7993 // * First must be an identifier
8094 // * Second must be an array literal
8195 return (
82- name === SET_CLASS_METADATA_NAME &&
83- args . length === 4 &&
84- types . isIdentifier ( args [ 0 ] ) &&
85- types . isArrayExpression ( args [ 1 ] )
96+ callArguments . length === 4 &&
97+ callArguments [ 0 ] . isIdentifier ( ) &&
98+ callArguments [ 1 ] . isArrayExpression ( )
8699 ) ;
87100}
88101
89102/** Determines if a function call is a call to `setClassMetadataAsync`. */
90- function isRemoveClassmetadataAsyncCall (
91- name : string ,
92- args : types . CallExpression [ 'arguments' ] ,
93- ) : boolean {
103+ function isSetClassMetadataAsyncCall ( callArguments : NodePath [ ] ) : boolean {
94104 // `setClassMetadataAsync` calls have to meet the following criteria:
95105 // * First argument must be an identifier.
96106 // * Second argument must be an inline function.
97107 // * Third argument must be an inline function.
98108 return (
99- name === SET_CLASS_METADATA_ASYNC_NAME &&
100- args . length === 3 &&
101- types . isIdentifier ( args [ 0 ] ) &&
102- isInlineFunction ( args [ 1 ] ) &&
103- isInlineFunction ( args [ 2 ] )
109+ callArguments . length === 3 &&
110+ callArguments [ 0 ] . isIdentifier ( ) &&
111+ isInlineFunction ( callArguments [ 1 ] ) &&
112+ isInlineFunction ( callArguments [ 2 ] )
104113 ) ;
105114}
106115
107116/** Determines if a function call is a call to `setClassDebugInfo`. */
108- function isSetClassDebugInfoCall ( name : string , args : types . CallExpression [ 'arguments' ] ) : boolean {
117+ function isSetClassDebugInfoCall ( callArguments : NodePath [ ] ) : boolean {
109118 return (
110- name === SET_CLASS_DEBUG_INFO_NAME &&
111- args . length === 2 &&
112- types . isIdentifier ( args [ 0 ] ) &&
113- types . isObjectExpression ( args [ 1 ] )
119+ callArguments . length === 2 &&
120+ callArguments [ 0 ] . isIdentifier ( ) &&
121+ callArguments [ 1 ] . isObjectExpression ( )
114122 ) ;
115123}
116124
117125/** Determines if a node is an inline function expression. */
118- function isInlineFunction ( node : types . Node ) : boolean {
119- return types . isFunctionExpression ( node ) || types . isArrowFunctionExpression ( node ) ;
126+ function isInlineFunction ( path : NodePath ) : boolean {
127+ return path . isFunctionExpression ( ) || path . isArrowFunctionExpression ( ) ;
120128}
0 commit comments