# eslint with class property

On github: [**https://github.com/babel/babel-eslint/issues/487#issuecomment-564389834**](https://github.com/babel/babel-eslint/issues/487#issuecomment-564389834)

### **Issue**

If class property is used in class, `eslint` requires `babel-eslint` as parser (defaulted as `espree`) to parse the code before actual linting. For some reason, an error of `eslint(no-undef)` is always shown on the class property.

Firstly, I thought reason is `@babel/plugin-proposal-class-properties` is not provided for `babel-eslint` , while then I found actually `babel-eslint` always have class property as default plugin.

### **TL;DR**

**This should be solved by**

```javascript
{
    "eslint": ">=4.14.0",
    "babel-eslint": ">=8.1.0"
}
```

**with fix from `eslint/eslint`** [**PR#8755**](https://github.com/eslint/eslint/pull/8755)**, and fix from `babel/babel-eslint`** [**PR#542**](https://github.com/babel/babel-eslint/pull/542)**. Thanks to** [**@mysticatea**](https://github.com/mysticatea) **for the hard work.**

**--------**

**Explanation:** This is a issue caused by the 'scope analyze' in eslint. In the older version (<4.14.0), eslint analyze the scope by its own without passing in the correct `childVisitorKeys` attribute.

```javascript
// eslint.js
// gather scope data that may be needed by the rules
scopeManager = escope.analyze(ast, {
    ignoreEval: true,
    nodejsScope: ecmaFeatures.globalReturn,
    impliedStrict: ecmaFeatures.impliedStrict,
    ecmaVersion,
    sourceType: currentConfig.parserOptions.sourceType || "script",
    fallback: Traverser.getKeys
});
```

[**https://github.com/eslint/eslint/blob/421aab44a9c167c82210bed52f68cf990b7edbea/lib/eslint.js#L892**](https://github.com/eslint/eslint/blob/421aab44a9c167c82210bed52f68cf990b7edbea/lib/eslint.js#L892)

A correct scope after `parser.parse()` requires corresponding `childVisitorKeys` defined by different parser, as [PR#8755](https://github.com/eslint/eslint/pull/8755#issue-126156112) explains

After those two PRs, `babel-eslint` will generate the `scopeManager` with its own modification. `eslint` will consume the `scopeManager` (`const scopeManager = parseResult.scopeManager;`), and apply rules over it.

### **Take away:**&#x20;

1. It costs time to locate the root cause for this kind of issue if you are not familiar with the massive project like eslint (or ast concept), not to mention it normally comes with several more issues together.&#x20;
2. If you really want to do the research, start from the `rules` folder and analyze specific rule to get two cents about what goes wrong, in this case, it's the scope. It would be much easier then to narrow down your research in scope-related logic in `parse()`.
3. **The easy way to 'just make things work' maybe is always upgrade version.**

#### How eslint(v4) compiles code

`eslint.js`(entry) -> `CLIEngine(options)` -> `processWithText(text, options)` -> `linter.verify(text, options)`&#x20;

Inside **verify(),** `sourceCode = parse(text, parser, parseOptions)` -> analyze `sourceCode.ast`

* load and analyze an ast for a 200 line file is not too practical

#### H**ow linter analyse ast**

* `sharedTraversalContext` contains scope info
* `scope analyzer` is important for rules to check scope and variables
