ember-codemods / ember-modules-codemod

Codemod to upgrade Ember apps to JavaScript (ES6) modules

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Unknown global Ember.inject

Dhaulagiri opened this issue · comments

Moved from ember-cli/ember-rfc176-data#34

If you have inject destructured like this the ember-modules-codemod fails stating this in an unkown global:

const { inject } = Ember;

This form of destructing does work:

const { inject: { service } } = Ember;

Can/should the first case be supported?

Yes, we should definitely handle this a bit better.

If the Ember.computed case that I mentioned in ember-cli/ember-rfc176-data#34 is working properly, you should checkout https://github.com/ember-cli/ember-modules-codemod/blob/master/transform.js#L230-L270 to see what updates are required to make the same work for Ember.inject...

Same issue also if you use const { inject } = Ember; with inject.controller. Taking a look to see if I can't figure out how to fix...

The Ember.computed case works ok because import { computed } from '@ember/object'; is valid whereas import { inject } from '@ember/service'; is not

Ah, that makes sense. Though, I do think we should actually update it to import things directly. I don't think we intend to allow the following (it only happens to work due to the way the globals are setup):

import computed from '@ember/computed';

export default Component.extend({
  derp: computed.alias('otherThing.derp')
})

My suggestion would be to add some additional logic to handle these sorts of namespaces (Ember.computed and Ember.inject might be the only examples?) so that we transform:

const { computed, inject } = Ember;

export default Component.extend({
  derp: computed.alias('otherThing.derp'),
  thing: inject.service()
})

Into:

import { alias } from '@ember/computed';
import { inject } from '@ember/service';

export default Component.extend({
  derp: alias('otherThing.derp'),
  thing: inject()
})

👍 that seems prudent.

Having never worked on a codemod before I'm honestly finding it a little hard to grok the best way to accomplish this, but I'll poke around at it some more. It's not super hard to manually migrate these either, but it'd obviously be nice if the codemod worked here as well.

Although I think import { inject } from '@ember/service'; should end up as import { inject as service } from '@ember/service'; in the example above?

Ya, maybe name it injectService?

Not sure if it matters, but the json data shows them like this:

screen shot 2017-08-12 at 15 31 56

However this yields:

inject.service is not a function

in practice

You can ignore my last comment, I was doing it wrong.

import { inject } from '@ember/controller';
...
foo: inject('myControllerName') //works
foo: inject.controller('myControllerName') // does not work

Hmm, I've been doing some brainstorming on this, and it's a really weird case.

The tricky bit: if we have an instance of const { inject } from Ember, this means the codemod might need to replace it with either import { inject } from '@ember/service', or import { inject } from '@ember/controller', or both, and which of the two (or both) to use depends on the presence of any inject.service or inject.controller instances later on in the file.

Is there anything in the codemod currently that does this type of lookahead? This seems a bit can-of-worms-y, but having to do this case by-hand isn't handy (heh) either.

Also we'll need to figure out what to do in the case of injecting both a controller and a service in the same file, since the imports can't both be named inject. That seems like a change request for RFC176 itself, though.

[EDIT] corrected some things above -- I keep instinctively writing import instead of const. :P

This should fix it: #46