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

Use custom parser for gts/gjs #1942

Merged
merged 1 commit into from
Nov 1, 2023

Conversation

patricklx
Copy link
Contributor

@patricklx patricklx commented Aug 22, 2023

bonus:

  • enables type aware lints
  • prettier eslint plugin (with template tag prettier plugin) will just work for gts/gjs
  • can detect unused block params in templates
  • can detect undef vars in PathExpression
  • can add eslint directive comments in mustache or html disadvantage:
  • prettier will not work without template tag prettier plugin for gts/gjs files

disavdvantage:
needs specific configuration to enable the parser, as setting it globally will overwrite it.
like https://github.com/vuejs/vue-eslint-parser does.

Breaking change:

  • semi rules for template part. by coincidence same as prettier.
  • no-undef rule will take effect for template vars (includes js scope)
  • no-unsed rule will take effect for template block params
  • new config for gjs/gts, notified if not setup correctly

e.g.

// .eslintrc.js
module.exports = {
  plugins: ['ember'],
  extends: [
    'eslint:recommended',
    'plugin:ember/recommended', // or other configuration
  ],
  overrides: [
    {
      files: ['**/*.gts', '**/*.gjs'],
      parser: 'eslint-plugin-ember/gjs-gts-parser'
    },
    }
  ],
  rules: {
    // override / enable optional rules
    'ember/no-replace-test-comments': 'error'
  }
};

fixes #1770
fixes #1894
fixes #1747
fixes #1683
fixes #1659
also fixes gitKrystan/prettier-plugin-ember-template-tag#81
fixes gitKrystan/prettier-plugin-ember-template-tag#84
closes #1667
closes #1957

@patricklx patricklx force-pushed the use-custom-parser branch 2 times, most recently from 2578221 to a96dc3b Compare August 22, 2023 12:52
// override / enable optional rules
'ember/no-replace-test-comments': 'error'
}
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd prefer we specify:

overrides: [
{
  files: ["**/*.{gjs,gts}"],
  parser: 'ember',
}
]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would this also be okay?

{
      files: ['**/*.gts'],
      parser: 'eslint-plugin-ember/gts-parser',
    },
    {
      files: ['**/*.gjs'],
      parser: 'eslint-plugin-ember/gjs-parser',
    },

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems fine, but just wondering, is there a need or benefit to separating the parsers, or can they be specified as one?

overrides: [
  {
    files: ["**/*.{gjs,gts}"],
    parser: 'eslint-plugin-ember/gjs-gts-parser',
  }
]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we could.
we would need to detect if the extension is gts or gjs and choose by that, which internal parser should be chosen

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would that be simple? Is there any reason why we shouldn't just auto-detect the extension for the user? If the user doesn't care about distinguishing between these file types, then we can avoid exposing that complexity to the user, and just handle it internally, right?

@patricklx patricklx force-pushed the use-custom-parser branch 5 times, most recently from 2bb7972 to 71d19ff Compare August 22, 2023 14:49
@patricklx
Copy link
Contributor Author

patricklx commented Aug 22, 2023

@bmish @NullVoxPopuli
I think there are two options

  1. Use non breaking version and keep old code, but strange override
  2. breaking version, and we keep the glimmer preprocessor which only throws an error notifying the user how to setup the parser.

Though i remember the idea was to get rid of ember-template-imports here.
So i will continue with breaking change and look how to notify users about the new configuration. I think i can get something working preprocessors.

@patricklx patricklx force-pushed the use-custom-parser branch 6 times, most recently from 4eff4a0 to e8c8be6 Compare August 23, 2023 09:17
msgs[0].ruleId === null &&
msgs[0].message.startsWith('Parsing error: ')
) {
if (!parsedFiles.has(fileName)) {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is how we check if the file went through our parser or not.
I only notify the user if a parsing error happened. We could also always notify the user if its not correctly setup.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is great! is there a way to check if a gjs / gts file was passed to this though? right now I have a concern about non-gjs and non-gts files hitting this message, would be over-aggressive

Copy link
Contributor Author

@patricklx patricklx Aug 23, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, the preprocessor is only setup for those files. So it only enters if for gjs/gts

}`,
errors: [
{
message: 'Parsing error: Unexpected token (2:40)',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here the error when setup is correct, but some other syntax error

Comment on lines 182 to 183
'Parsing error: Unexpected token. A constructor, method, accessor, or property was expected.\n' +
'To lint Gjs/Gts files please follow the setup guide at https://github.com/ember-cli/eslint-plugin-ember#gtsgjs-eslint-setup',
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

here is the error when not setting it up correctly

@patricklx
Copy link
Contributor Author

patricklx commented Aug 23, 2023

@bmish @NullVoxPopuli
I found a way to notify the users if their eslint config needs to be updated for gts/gjs and link them to the README.md.
So with this we should be able to make a breaking release and users will know what to do.
Or should I include the setup in the error message?

@NullVoxPopuli
Copy link
Contributor

In your PR description, your eslint config uses the root namespace for configuring ember stuff -- I think we need to move the community more towards an overrides-only approach, which I'd been trying to get folks to care about for some time.

For example:

// .eslintrc.js
module.exports = {
  overrides: [
    {
      files: ['**/*.gts'],
      parser: 'eslint-plugin-ember/gts-parser',
      plugins: ['ember'],
      extends: [
        'eslint:recommended',
        'plugin:ember/recommended', // or other configuration
      ],
    },
    {
      files: ['**/*.gjs'],
      parser: 'eslint-plugin-ember/gjs-parser',
      plugins: ['ember'],
      extends: [
        'eslint:recommended',
        'plugin:ember/recommended', // or other configuration
      ],
    },
    {
      files: ['tests/**/*.{gjs,gts}'],
      rules: {
        // override / enable optional rules
        'ember/no-replace-test-comments': 'error'
      }
    }
  ],
};

Reason being that it's way easier to manage long term, as it flattens the amount of cascading you force yourself in to, and you can more easily opt out of plugins, because they never existed for a particular folder in the first place.

This aligns nicely with the direction ESLint9 is going in as the current config format will be dropped. 🙃

this is all tangential to the PR tho lol

}

/**
* simple tokenizer for templates, just splits it up into words and punctuators
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can totally be in a followup PR, but does it makes sense for this to have its own unit tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe, though once the indent rule is added, it will also be tested indirectly :)

@@ -472,6 +564,40 @@ describe('lint errors on the exact line as the <template> tag', () => {
});
});

describe('supports eslint directives inside templates', () => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oooooo

const code = `
<template>
<div>
<!--eslint-disable-next-line-->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

wouldn't this get shipped to users tho? 😅
(non-blocker, just a goofiness)

NullVoxPopuli
NullVoxPopuli previously approved these changes Aug 23, 2023
Copy link
Contributor

@NullVoxPopuli NullVoxPopuli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice work -- thanks for iterating on this, and greatest apologies we had to revert the first time around <3

@patricklx
Copy link
Contributor Author

patricklx commented Aug 24, 2023

In your PR description, your eslint config uses the root namespace for configuring ember stuff -- I think we need to move the community more towards an overrides-only approach, which I'd been trying to get folks to care about for some time.

For example:

// .eslintrc.js
module.exports = {
  overrides: [
    {
      files: ['**/*.gts'],
      parser: 'eslint-plugin-ember/gts-parser',
      plugins: ['ember'],
      extends: [
        'eslint:recommended',
        'plugin:ember/recommended', // or other configuration
      ],
    },
    {
      files: ['**/*.gjs'],
      parser: 'eslint-plugin-ember/gjs-parser',
      plugins: ['ember'],
      extends: [
        'eslint:recommended',
        'plugin:ember/recommended', // or other configuration
      ],
    },
    {
      files: ['tests/**/*.{gjs,gts}'],
      rules: {
        // override / enable optional rules
        'ember/no-replace-test-comments': 'error'
      }
    }
  ],
};

Reason being that it's way easier to manage long term, as it flattens the amount of cascading you force yourself in to, and you can more easily opt out of plugins, because they never existed for a particular folder in the first place.

This aligns nicely with the direction ESLint9 is going in as the current config format will be dropped. 🙃

this is all tangential to the PR tho lol

That would also be good, by using extends in overrides it would not also not be strictly necessary to specify the parser. As that is set in the recommended config.
So only one config would be needed:

{
      files: ['**/*.{gjs,gts}'],
        plugins: ['ember'],
       extends: [
         'eslint:recommended',
         'plugin:ember/recommended', // and other 
}

Or a base config?
edit: the multiple configs actual make more sense, i might want to have different rules for gjs/gts as gts could also have the typescript ones.
should we have different recommended configs for gjs/gts? there we could add rules that work on template and not have them in the js/ts files...

@patricklx
Copy link
Contributor Author

follow-up prs i would like to include in the next major:

@patricklx
Copy link
Contributor Author

@bmish any news for this?
Ember template imports 4 has been released.

@NullVoxPopuli
Copy link
Contributor

eti v4 is more a signal that content-tag should be good to go in the linting prs.

@patricklx
Copy link
Contributor Author

content tag still doesn't emit a format that's usable for linting

@NullVoxPopuli
Copy link
Contributor

It has a second api specifically for linting. Check my glint pr where the ranges are used

@patricklx
Copy link
Contributor Author

I will have a look, but here ranges are not enough.
Need to have a transform which doesn't change offsets

@patricklx
Copy link
Contributor Author

patricklx commented Oct 19, 2023

mmm, so glint uses that to do it's own transform?
it's also possible to know if the template is inside a class expression or normal expression?
If so, then i could also do the custom transform here...
@NullVoxPopuli ?

@patricklx
Copy link
Contributor Author

@bmish @NullVoxPopuli I updated this to use the latest content-tag

Copy link
Contributor

@NullVoxPopuli NullVoxPopuli left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great!

@patricklx patricklx mentioned this pull request Oct 31, 2023
@NullVoxPopuli
Copy link
Contributor

@patricklx this one needs rebase real quick

@patricklx patricklx force-pushed the use-custom-parser branch 2 times, most recently from aca80ed to 8b53ff0 Compare October 31, 2023 13:05
package.json Outdated Show resolved Hide resolved
@patricklx patricklx force-pushed the use-custom-parser branch 8 times, most recently from 4d93fa9 to df57176 Compare November 1, 2023 10:54
@patricklx
Copy link
Contributor Author

@NullVoxPopuli this now uses latest glimmer/syntax

@NullVoxPopuli NullVoxPopuli merged commit 068609d into ember-cli:master Nov 1, 2023
8 checks passed
@bmish bmish changed the title use custom parser for gts/gjs Use custom parser for gts/gjs Nov 3, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment