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

Incorrect parsing for contextual keyword async #678

Closed
svr93 opened this issue Jul 7, 2019 · 5 comments · Fixed by #681
Closed

Incorrect parsing for contextual keyword async #678

svr93 opened this issue Jul 7, 2019 · 5 comments · Fixed by #681
Labels
bug Something isn't working has pr there is a PR raised to close this package: typescript-estree Issues related to @typescript-eslint/typescript-estree

Comments

@svr93
Copy link

svr93 commented Jul 7, 2019

What code were you trying to parse?

import { TestBed, async } from '@angular/core/testing';

What did you expect to happen?
token type Identifier with value async

What actually happened?
token type Keyword with value async

Versions

package version
@typescript-eslint/typescript-estree 1.11.0
TypeScript 3.4.5
node 10.14.2
npm 6.4.1
@svr93 svr93 added package: typescript-estree Issues related to @typescript-eslint/typescript-estree triage Waiting for maintainers to take a look labels Jul 7, 2019
@bradzacher
Copy link
Member

According to astexplorer that isn't what comes out?

This is the result of the parse (yes, ASTExplorer is on v1.4.2, but we haven't changed anything in the parser)
https://astexplorer.net/#/gist/6bc10f2361963d312bd8ed3e0c46b15e/f2fdc226b280857558b5a9d90c786364c76a4ebb

This is the output of parsing against master (without location info), which is against `v1.11.0`
{
  "body": [
    {
      "source": {
        "raw": "'@angular/core/testing'",
        "type": "Literal",
        "value": "@angular/core/testing",
      },
      "specifiers": [
        {
          "imported": {
            "name": "TestBed",
            "type": "Identifier",
          },
          "local": {
            "name": "TestBed",
            "type": "Identifier",
          },
          "type": "ImportSpecifier",
        },
        //////////////////////////////////
        {
          "imported": {
            "name": "async",
            "type": "Identifier",
          },
          "local": {
            "name": "async",
            "type": "Identifier",
          },
          "type": "ImportSpecifier",
        },
        //////////////////////////////////
      ],
      "type": "ImportDeclaration",
    },
  ],
  "sourceType": "module",
  "tokens": [
    {
      "type": "Keyword",
      "value": "import",
    },
    {
      "type": "Punctuator",
      "value": "{",
    },
    {
      "type": "Identifier",
      "value": "TestBed",
    },
    {
      "type": "Punctuator",
      "value": ",",
    },
    {
      "type": "Keyword",
      "value": "async",
    },
    {
      "type": "Punctuator",
      "value": "}",
    },
    {
      "type": "Identifier",
      "value": "from",
    },
    {
      "type": "String",
      "value": "'@angular/core/testing'",
    },
    {
      "type": "Punctuator",
      "value": ";",
    },
  ],
  "type": "Program",
}

As you can see, in both cases async is correctly parsed as an identifier.
The bug is not in the parser from what I can see.

@bradzacher bradzacher added working as intended Issues that are closed as they are working as intended and removed triage Waiting for maintainers to take a look labels Jul 7, 2019
@svr93
Copy link
Author

svr93 commented Jul 7, 2019

@bradzacher Thank you for quick response!

The parser used for easy integration between TypeScript & JavaScript ecosystems. So I expect identical results with identical strings of code.
My test case:

// @ts-check
const tsParser = require('@typescript-eslint/typescript-estree');
const esParser = require('esprima')
const esParser2 = require('espree')

const code = `import { TestBed, async } from '@angular/core/testing';`;

const { tokens: tsTokens } = tsParser.parse(code, {
  tokens: true,
});
const esTokens = esParser.tokenize(code)
const esTokens2 = esParser2.tokenize(code, {ecmaVersion: 2019, sourceType: 'module'})

console.log(tsTokens.map(({ type, value }) => ({ type, value })))
console.log('---')
console.log(esTokens.map(({ type, value }) => ({ type, value })))
console.log('---')
console.log(esTokens2.map(({ type, value }) => ({ type, value })))

Result is different:

[ { type: 'Keyword', value: 'import' },
  { type: 'Punctuator', value: '{' },
  { type: 'Identifier', value: 'TestBed' },
  { type: 'Punctuator', value: ',' },
  { type: 'Keyword', value: 'async' }, // *?*
  { type: 'Punctuator', value: '}' },
  { type: 'Identifier', value: 'from' },
  { type: 'String', value: '\'@angular/core/testing\'' },
  { type: 'Punctuator', value: ';' } ]
---
[ { type: 'Keyword', value: 'import' },
  { type: 'Punctuator', value: '{' },
  { type: 'Identifier', value: 'TestBed' },
  { type: 'Punctuator', value: ',' },
  { type: 'Identifier', value: 'async' },
  { type: 'Punctuator', value: '}' },
  { type: 'Identifier', value: 'from' },
  { type: 'String', value: '\'@angular/core/testing\'' },
  { type: 'Punctuator', value: ';' } ]
---
[ { type: 'Keyword', value: 'import' },
  { type: 'Punctuator', value: '{' },
  { type: 'Identifier', value: 'TestBed' },
  { type: 'Punctuator', value: ',' },
  { type: 'Identifier', value: 'async' },
  { type: 'Punctuator', value: '}' },
  { type: 'Identifier', value: 'from' },
  { type: 'String', value: '\'@angular/core/testing\'' },
  { type: 'Punctuator', value: ';' } ]

Consistent results will help to use the available ESLint plugins for TypeScript code

@bradzacher
Copy link
Member

bradzacher commented Jul 7, 2019

I see - you should have included that in your initial issue!

Looking again at the example, yes - the tokens array does classify the async token as a keyword.

However looking at the linked issue, and the source code of the plugin, it never inspects that array, and gathers tokens via sourceCode.getTokens(node).

In practice it looks like it all works as expected?

https://astexplorer.net/#/gist/8599f450e5cab7f5711b55ab02bd4a0e/bddd5558899be19236dead04055faa4348a1f66c

[ { type: 'Keyword', value: 'import' },
  { type: 'Punctuator', value: '{' },
  { type: 'Identifier', value: 'TestBed' },
  { type: 'Punctuator', value: ',' },
  { type: 'Identifier', value: 'async' },
  { type: 'Punctuator', value: '}' },
  { type: 'Identifier', value: 'from' },
  { type: 'String', value: '\'@angular/core/testing\'' },
  { type: 'Punctuator', value: ';' } ]

@bradzacher bradzacher reopened this Jul 7, 2019
@bradzacher bradzacher added bug Something isn't working has pr there is a PR raised to close this and removed working as intended Issues that are closed as they are working as intended labels Jul 7, 2019
@bradzacher
Copy link
Member

Note that I have raised #681 to fix the incorrect typing of the token.

@svr93
Copy link
Author

svr93 commented Jul 7, 2019

@bradzacher
I tried to clone this repo - https://github.com/lydell/eslint-plugin-simple-import-issue - and manually patch dependency with your PR changes.

Result: test is OK :)

diff --git a/test.js b/test.js
index 9b2896a..1139a7c 100644
--- a/test.js
+++ b/test.js
@@ -1 +1 @@
-import { TestBed, async } from '@angular/core/testing';
+import { async,TestBed } from '@angular/core/testing';

Plugin works as expected

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Apr 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
bug Something isn't working has pr there is a PR raised to close this package: typescript-estree Issues related to @typescript-eslint/typescript-estree
Projects
None yet
2 participants