Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature request: async/await support #814

Closed
rkistner opened this issue Aug 11, 2016 · 16 comments
Closed

Feature request: async/await support #814

rkistner opened this issue Aug 11, 2016 · 16 comments

Comments

@rkistner
Copy link
Contributor

I realize that it is not standardized yet (currently stage 3), but support for async/await would be extremely useful for me. What would it involve to get this implemented?

The functionality I'm looking for would entail:

// Case 1
async function myfunction() {
    return 'test';
}

var promise = myfunction();
// promise inferred as Promise<string> (currently just string).

// Case 2
async function myfunction2() {
    var promise = Promise.resolve('test');
    var value = await promise;
    // value inferred as string (currently unknown).
}

I'm willing to help with the implementation in my spare time. If you feel this should not be in the core library since it's not standardized yet, would it be feasible to implement this in some kind of "plugin", or would I have to fork ternjs? I understand that it is also not part of the acorn parser yet, but there already exists plugins an acorn plugin implementing it.

@rkistner
Copy link
Contributor Author

Alternatively, instead of implementing it in ternjs directly, would it be feasible to "pre-transform" the AST before passing it to tern? I can imagine something like the following:

  1. Inside any async function, transform return <expression> into return Promise.resolve(<expression>).
  2. Transform await <expression> into Promise.resolve(<expression>)._value (not sure exactly how to access the underlying value type here, but should be able to figure something out).

Of course these transformations are very different in behaviour, but should give the same result for type inference.

@rkistner
Copy link
Contributor Author

I have a basic proof of concept working now with the transforms as described above, so the approach seems to be working. There are still some tricky cases such as arrow functions, but I should be able to figure something out. I'll share my code when I've cleaned it up.

So it does seem like it's feasible to implement this completely outside of Tern, but the implementation would be cleaner if Tern could work with e.g. AwaitExpression directly.

@rkistner
Copy link
Contributor Author

Initial proof of concept here: https://github.com/rkistner/tern-asyncawait. Tests are passing, but haven't actually used it yet.

@marijnh
Copy link
Member

marijnh commented Sep 5, 2016

This was landed with #446

@marijnh marijnh closed this as completed Sep 5, 2016
@rkistner
Copy link
Contributor Author

rkistner commented Sep 5, 2016

acornjs/acorn#446 only implements it in Acorn, not in Tern yet, so this should probably stay open for now?

@marijnh
Copy link
Member

marijnh commented Sep 5, 2016

Oops, I thought this was in the Acorn repo. Reopening!

@CandySunPlus
Copy link

+1

@jsl9208
Copy link

jsl9208 commented Mar 2, 2017

Any progress?

@peltsi212
Copy link

Node 8 has been released 2017-05-30 and it supports async/await
eslint support ES2017
http://eslint.org/blog/2016/09/eslint-v3.6.0-released
Is it possible to upgrade eslint and get support for async/await to tern?

@marijnh
Copy link
Member

marijnh commented Jun 29, 2017

Tern has nothing to do with ESLint, getting async/await support here would require implementing it in Tern.

@peltsi212
Copy link

Here is reference to
Eclipse IDE with Tern ESLint linter
http://eslint.org/docs/user-guide/integrations

It seems that I mixed two projects with name tern

@FireController1847
Copy link

Would love to see this implimented

@CrowderSoup
Copy link

Would love to see async/await support in Tern. Currently can't navigate to the definition of async functions which really slows me down in VIM.

@rkistner
Copy link
Contributor Author

For anyone still following this issue, I got something mostly working a while back, using the following approach:

To start with:

  • Make sure to use ecmaVersion 8 when parsing.
  • Make sure you have proper definitions for Promises.

Create a Tern plugin with a postParse hook. The postParse hook walks the AST, and transforms async functions and await expressions into nodes that Tern supports:

I transformed await statements (AwaitExpression) into a function call that returns the value of the Promise. This is of course completely impossible/invalid in actual JS, but works fine for type checking. Actually implementing this function call required some hacks, with a custom infer.registerFunction for this.

I transformed async functions (both FunctionDeclaration and ArrowFunctionExpression), by adding a fake return statement with the correct type to the end of the body. I also wrapped any ReturnStatement into one that returns a Promise, instead of the original value.

These transformations all felt like a significant hack, that could be implemented better in Tern itself, but it did work quite well for me.

While this plugin is still in use, nowadays I recommend TypeScript instead. While the type inference for plain JS isn't always as good as Tern, I found it good enough for personal development, and it keeps on improving over time.

I there is enough interest, I can see if I can extract and publish the source for this plugin.

@rmzg
Copy link

rmzg commented Jun 12, 2018

I don't know about anyone else but I'd really appreciate a plugin that fixed this issue. I tried with your example code you posted earlier but I couldn't figure out how to get the combination of YCM/Tern to actually work with it.

@rmzg
Copy link

rmzg commented Jun 13, 2018

Update:

I added the index.js file from https://github.com/rkistner/tern-asyncawait as a plugin to my .tern-config, updated the ecmaversion from 7 to 8 and it mostly works so far. It's a gigantic hack but it's better than ternjs just failing to parse async functions in the first place.

Also fun note, if you have a plugin named "foo" in your config file then you try to edit a file named ./foo.js, tern will try to load the file you're editing as a plugin. This is great fun to figure out.

@othree othree closed this as completed Oct 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

9 participants