@@ -76,6 +76,11 @@ module.exports = {
76
76
const allowList = context . options [ 0 ] ?. allowList ?? [ ] ;
77
77
// Maps local names to imported names of imports
78
78
const localToImportedNameMap = new Map ( ) ;
79
+ let namespaceImportName ;
80
+
81
+ const isDisallowed = function ( fn ) {
82
+ return EMBER_RUNLOOP_FUNCTIONS . includes ( fn ) && ! allowList . includes ( fn ) ;
83
+ } ;
79
84
80
85
/**
81
86
* Reports a node with usage of a disallowed runloop function
@@ -109,38 +114,50 @@ module.exports = {
109
114
if ( EMBER_RUNLOOP_FUNCTIONS . includes ( importedName ) ) {
110
115
localToImportedNameMap . set ( spec . local . name , importedName ) ;
111
116
}
117
+ } else if ( spec . type === 'ImportNamespaceSpecifier' ) {
118
+ namespaceImportName = spec . local . name ;
112
119
}
113
120
}
114
121
}
115
122
} ,
116
123
117
124
CallExpression ( node ) {
125
+ const callee = node . callee ;
126
+
118
127
// Examples: run(...), later(...)
119
- if ( node . callee . type === 'Identifier' ) {
120
- const name = node . callee . name ;
121
- const runloopFn = localToImportedNameMap . get ( name ) ;
122
- const isNotAllowed = runloopFn && ! allowList . includes ( runloopFn ) ;
123
- if ( isNotAllowed ) {
124
- report ( node , runloopFn , name ) ;
128
+ if ( callee . type === 'Identifier' ) {
129
+ const localName = callee . name ;
130
+ const runloopFn = localToImportedNameMap . get ( localName ) ;
131
+
132
+ if ( runloopFn && isDisallowed ( runloopFn ) ) {
133
+ report ( node , runloopFn , localName ) ;
125
134
}
135
+
136
+ return ;
126
137
}
127
138
128
- // runloop functions (aside from run itself) can chain onto `run`, so we need to check for this
129
- // Examples: run.later(...), run.schedule(...)
130
- if ( node . callee . type === 'MemberExpression' && node . callee . object ?. type === 'Identifier' ) {
131
- const objectName = node . callee . object . name ;
132
- const objectRunloopFn = localToImportedNameMap . get ( objectName ) ;
133
-
134
- if ( objectRunloopFn === 'run' && node . callee . property ?. type === 'Identifier' ) {
135
- const runloopFn = node . callee . property . name ;
136
-
137
- if (
138
- EMBER_RUNLOOP_FUNCTIONS . includes ( runloopFn ) &&
139
- runloopFn !== 'run' &&
140
- ! allowList . includes ( runloopFn )
141
- ) {
142
- report ( node , runloopFn , `${ objectName } .${ runloopFn } ` ) ;
143
- }
139
+ if (
140
+ callee . type === 'MemberExpression' &&
141
+ callee . object . type === 'Identifier' &&
142
+ callee . property . type === 'Identifier'
143
+ ) {
144
+ const objectName = callee . object . name ;
145
+ const methodName = callee . property . name ;
146
+
147
+ // runloop functions (aside from run itself) can chain onto `run`, so we need to check for this
148
+ // Examples: run.later(...), run.schedule(...)
149
+ if (
150
+ localToImportedNameMap . get ( objectName ) === 'run' &&
151
+ isDisallowed ( methodName ) &&
152
+ methodName !== 'run'
153
+ ) {
154
+ report ( node , methodName , `${ objectName } .${ methodName } ` ) ;
155
+ return ;
156
+ }
157
+
158
+ // Example: `import * as runloop from '@ember/runloop'` -> `runloop.later(...)`
159
+ if ( objectName === namespaceImportName && isDisallowed ( methodName ) ) {
160
+ report ( node , methodName , `${ objectName } .${ methodName } ` ) ;
144
161
}
145
162
}
146
163
} ,
0 commit comments