ember-tooling / ember-eslint-parser Goto Github PK
View Code? Open in Web Editor NEWThis is the eslint parser for ember's gjs and gts files (using <template>).
This is the eslint parser for ember's gjs and gts files (using <template>).
Similar to how we pass requireConfigFile: false
to the babel parser, in here we should pass extraFileExtensions: ['.gjs', '.gts'],
to the TypeScript parser. The reason this is not caught in the tests is because TypeScript only complains about it when you try to do type-aware linting (i.e. passing project: ...
in parserOptions
), but it is probably a good idea to always pass those extraFileExtensions
anyway
Run lint on this code and see following error
import { on } from '@ember/modifier';
const noop = () => {};
<template>
<div {{on 'click' noop}} />
</template>
Parsing error: Unclosed element `template`:··
|
| <template>
|·
If we just add a new line after the closing tag the error goes away
import { on } from '@ember/modifier';
const noop = () => {};
<template>
<div {{on 'click' noop}} />
</template>
For reproduction for example you can just remove a line in this test https://github.com/ember-cli/eslint-plugin-ember/blob/master/tests/lib/rules-preprocessor/gjs-gts-parser-test.js#L111
Strangely, I get this error only for GJS files 🤔
Parsing error: No Babel config file detected for /tests/integration/components/search-box-component-test.gjs. Either disable config file checking with requireConfigFile: false, or configure Babel so that it can find the config files
My eslint config looks like this
module.exports = {
overrides: [
// JS / TS
{
files: ['**/*.{js,ts}'],
plugins: ['ember', '@typescript-eslint'],
parser: '@typescript-eslint/parser',
extends: [
'eslint:recommended',
'plugin:ember/recommended',
'plugin:@typescript-eslint/recommended',
// From eslint-config-prettier - this disables stylistic rules that prettier handles. should be last.
'prettier',
],
rules: {
...commonTypescriptRules,
...commonEmberRules,
},
},
// GTS
{
files: ['**/*.gts'],
plugins: ['ember'],
parser: 'ember-eslint-parser',
extends: [
'eslint:recommended',
'plugin:ember/recommended',
'plugin:ember/recommended-gts',
// From eslint-config-prettier - this disables stylistic rules that prettier handles. should be last.
'prettier',
],
rules: {
...commonTypescriptRules,
...commonEmberRules,
},
globals: {
// give glint/gts files access to global types
ModelFor: 'readonly',
Nullable: 'readonly',
StudentEventsService: 'readonly',
},
},
// GJS
{
files: ['**/*.gjs'],
plugins: ['ember'],
parser: 'ember-eslint-parser',
extends: [
'eslint:recommended',
'plugin:ember/recommended',
'plugin:ember/recommended-gjs',
// From eslint-config-prettier - this disables stylistic rules that prettier handles. should be last.
'prettier',
],
rules: {
...commonEmberRules,
},
},
I can add an additional rule to make it the error go away
{
files: ['**/*.gjs'],
parserOptions: {
requireConfigFile: false,
},
},
But in doing so I end up with a different error in GJS files that use decorators
Parsing error: This experimental syntax requires enabling one of the following parser plugin(s): "decorators", "decorators-legacy". (48:6)
I am wondering if there is something that was configured for GTS but not GJS? Or is there some issue with my config?
Coming from: #28
Custom elements, including web components, are defined in global scope that are available, but not in local/file scope (unless explicitly defined).
There are two paths to informing eslint about new / custom globals:
In a single file
/* global <my-var> */
and globally for the whole project:
{
files: ['**/*.{gjs,gts}'],
plugins: ['ember'],
parser: 'ember-eslint-parser',
globals: {
// used in testing as a shorthand for <output>
out: true,
// used in the app
// etc
},
},
the globals list will likely (and necessarily) be large for web-component users.
// foo.gts
class Foo {
<template>...</template>
}
export default class Bar {
<template>...</template>
}
Something about this causes this code to blow up: https://github.com/gajus/eslint-plugin-jsdoc/blob/v48.0.6/src/exportParser.js#L216-L220
I think it was not expecting the GlimmerTemplate
node inside the class body, and so it tried to access node.key.name
on it and it blows up because GlimmerTemplate
doesn't have a key
. The fact that the code only runs when there is an unexported class is incidental.
I think the bottomline is there are probably code out there outside of our control (well, we can try to PR a fix, but would have to explain a lot of background and convince people to care, and it's kind of a whack-a-mole situation), that have some implicit expectation on what can appear inside a class body.
I think either:
GlimmerTemplate
node by default and only expose it with some kind of opt-inTwo options:
@typescript-eslint/parser
Currently, we conditionally choose which parser to use per-file. This pushes a lot of complexity to the app, because you essentially need to configure two distinct parsers (e.g. installing the decorator babel plugin and passing it in babelOptions
).
Essentially we are requiring users to manage both of these branches simultaneously, which seems like a lot of busywork for ~no benefits.
I think it is generally not necessary and not a good idea to dynamically pick between one of these two parsers per-file, instead of having a fixed on per-project. You may end up getting subtly different behavior/error messages, plus it is just unnecessary overhead to need to learn both.
Personally, my preference would be to always default to using the TypeScript parser, but give users the option of opt-in to using babel if they require it:
// ts/js project
{
overrides: [
{
files: ['**/*.{js,ts,gjs,gts}'],
plugins: ['ember'],
// uses TypeScript parser, nothing to configure, just works
parser: 'ember-eslint-parser'
},
],
}
// js only project
{
overrides: [
{
files: ['**/*.{js,gjs}'],
plugins: ['ember'],
// still uses TypeScript parser internally, nothing to configure, just works, you probably won't ever notice
parser: 'ember-eslint-parser'
},
],
}
// js only project that prefer/requires babel for some reason
{
overrides: [
{
files: ['**/*.{js,gjs}'],
plugins: ['ember'],
parser: 'ember-eslint-parser',
parserOption: {
useBabel: true,
sourceType: 'module',
requireConfigFile: false,
babelOptions: {
plugins: [
'@babel/plugin-proposal-do-expressions',
['@babel/plugin-proposal-decorators', { decoratorsBeforeExport: true }],
],
},
}
},
],
}
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates are awaiting their schedule. Click on a checkbox to get an update now.
@babel/eslint-parser
, @babel/plugin-proposal-decorators
, @typescript-eslint/parser
, @typescript-eslint/visitor-keys
, vite
)These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
@typescript-eslint/eslint-plugin
, globals
).github/workflows/ci.yml
actions/checkout v4
wyvox/action-setup-pnpm v3
actions/checkout v4
wyvox/action-setup-pnpm v3
actions/checkout v4
wyvox/action-setup-pnpm v3
actions/checkout v4
wyvox/action-setup-pnpm v3
actions/checkout v4
wyvox/action-setup-pnpm v3
.github/workflows/plan-release.yml
actions/checkout v4
actions/checkout v4
actions/setup-node v4
pnpm/action-setup v2
peter-evans/create-pull-request v6
.github/workflows/publish.yml
actions/checkout v4
actions/checkout v4
actions/setup-node v4
pnpm/action-setup v2
package.json
@babel/core ^7.23.6
@typescript-eslint/parser ^7.1.0
@typescript-eslint/visitor-keys ^7.1.0
concurrently ^8.2.2
eslint ^8.0.1
eslint-config-prettier ^9.1.0
eslint-config-standard ^17.1.0
eslint-plugin-import ^2.25.2
eslint-plugin-n ^16.4.0
eslint-plugin-prettier ^5.0.1
eslint-plugin-promise ^6.0.0
execa ^8.0.1
fs-extra ^11.2.0
prettier ^3.2.5
publint ^0.2.6
release-plan ^0.8.0
typescript ^5.3.3
vite ^5.0.12
vitest ^1.2.2
test-projects/configs/flat-js/package.json
@babel/eslint-parser 7.23.10
@babel/plugin-proposal-decorators 7.23.9
eslint ^8.0.1
eslint-plugin-ember ^12.0.0
globals ^13.24.0
test-projects/gjs/package.json
@typescript-eslint/eslint-plugin ^6.21.0
@typescript-eslint/parser ^6.21.0
eslint ^8.0.1
eslint-plugin-ember ^12.0.0
typescript ^5.3.3
test-projects/gts/package.json
@ember/test-waiters ^3.1.0
@glint/template ^1.3.0
@glimmer/tracking ^1.1.2
@glimmer/component ^1.1.2
@typescript-eslint/eslint-plugin ^6.21.0
@typescript-eslint/parser ^6.21.0
ember-source ^5.6.0
eslint ^8.0.1
eslint-plugin-ember ^12.0.0
typescript ^5.3.3
test-projects/rules/padding-line-between-statements/package.json
@typescript-eslint/eslint-plugin ^6.21.0
@typescript-eslint/parser ^6.21.0
eslint ^8.0.1
eslint-plugin-ember ^12.0.0
typescript ^5.3.3
I get
TypeError: Cannot read properties of undefined (reading '1')
Occurred while linting index.gjs:1
Rule: "no-use-before-define"
In a GTS file
const [, ...createdClasses] = await Promise.all([minimumDuration, ...savePromises])
results in
Parsing error: Cannot read properties of null (reading 'type')
This worked fine under the existing setup prior to eslint-plugin-ember v12
If you define the first variable, eslint will stop complaining (though may start complaining about unused var, but at least that rule can be ignored)
const [_ignore, ...createdClasses] = await Promise.all([minimumDuration, ...savePromises])
<template>
Price: ${{this.price}}
</template>
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.