@@ -13,6 +13,24 @@ function isIgnored(ignore, importPath, exportName) {
1313 }
1414}
1515
16+ function isDecorator ( moduleName , importName ) {
17+ switch ( moduleName ) {
18+ case '@ember/service' :
19+ return importName === 'inject' ;
20+ case '@ember/controller' :
21+ return importName === 'inject' ;
22+ case '@glimmer/tracking' :
23+ return importName === 'tracked' ;
24+ case '@ember/object/compat' :
25+ return importName === 'dependentKeyCompat' ;
26+ case '@ember/object' :
27+ return [ 'action' , 'computed' ] . includes ( importName ) ;
28+ case '@ember/object/computed' :
29+ // only the default import of this module is not a decorator
30+ return importName !== 'default' ;
31+ }
32+ }
33+
1634module . exports = function ( babel ) {
1735 const t = babel . types ;
1836
@@ -165,10 +183,36 @@ module.exports = function (babel) {
165183 ] )
166184 ) ;
167185 } else {
168- // Replace the occurences of the imported name with the global name.
169186 let binding = path . scope . getBinding ( local . name ) ;
187+ let referencePaths = binding . referencePaths ;
188+
189+ if ( isDecorator ( importPath , importName ) ) {
190+ // tldr; decorator paths are not always included in `path.scope.getBinding(local.name)`
191+ //
192+ // In some circumstances, decorators are not included in the
193+ // reference paths for a local binding when the decorator
194+ // identifier name is also defined _within_ the method being
195+ // decorated. This is likely a bug in Babel, that should be
196+ // reported and fixed.
197+ //
198+ // in order to fix that, we have to manually traverse to gather
199+ // the decorator references **before** the
200+ // @babel /plugin-proposal-decorators runs (because it removes
201+ // them)
202+ path . parentPath . traverse ( {
203+ Decorator ( decoratorPath ) {
204+ if (
205+ decoratorPath . node . expression . type === 'Identifier' &&
206+ decoratorPath . node . expression . name === local . name
207+ ) {
208+ referencePaths . push ( decoratorPath . get ( 'expression' ) ) ;
209+ }
210+ } ,
211+ } ) ;
212+ }
170213
171- binding . referencePaths . forEach ( ( referencePath ) => {
214+ // Replace the occurences of the imported name with the global name.
215+ referencePaths . forEach ( ( referencePath ) => {
172216 if ( ! isTypescriptNode ( referencePath . parentPath ) ) {
173217 referencePath . replaceWith ( getMemberExpressionFor ( global ) ) ;
174218 }
0 commit comments