-
-
Notifications
You must be signed in to change notification settings - Fork 208
Breaking: Replace parse with parseForESLint and refactor codebase #509
Conversation
Really excited to see work being done on this. I haven't had time to dig deeply into this myself, but now that you have, what do you think would be needed in the current proposal to avoid monkeypatching altogether? Looks like it's still necessary. |
Sorry, I see - it's for the backwards compatibility with ESLint 3.x! @hzoo I was under the impression we were dropping support when we land this - what are your thoughts? |
Yeah because we are in the process of Babel 7 which is a major bump it's ok to drop old stuff (like we said with minimum of Node 4, babylon 7, etc) |
@kaicataldo, just to check, which bits are you referring to regarding ESLint 3.x? |
Hm, maybe I'm just missing something. When would
Thanks for working on this! |
Ah cool, yeah you mean in general with that. We're on the same page 👍😁 |
If I understand @hzoo correctly I can look to remove parse from this PR before it lands? |
Okay, awesome 👍 Yeah, I think we should cut a major release and drop support for ESLint v3.x when we release this. At least for me, in an ideal world, babel-eslint becomes as thin a wrapper as we can make it around Babylon, both for maintainability and predictability's sake. |
https://github.com/babel/babel-eslint/releases yeah the last releases i've done under v8.0.0 alpha so major was already the plan |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the investigating!
I found some lack of .ecmaFeatures
, it causes the test failing.
index.js
Outdated
eslintOptions.allowImportExportEverywhere = | ||
parserOptions.allowImportExportEverywhere; | ||
if (parserOptions.sourceType === "module") { | ||
eslintOptions.globalReturn = false; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eslintOptions.ecmaFeatures.globalReturn
index.js
Outdated
if (parserOptions.sourceType === "module") { | ||
eslintOptions.globalReturn = false; | ||
} else { | ||
delete eslintOptions.globalReturn; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
babel-eslint
seems to enable allowReturnOutsideFunction
option always, so I guess eslintOptions.ecmaFeatures.globalReturn
should be true
. Or allowReturnOutsideFunction
should follow to eslintOptions.ecmaFeatures.globalReturn
.
index.js
Outdated
function analyzeScope(ast) { | ||
var eslintScopeOptions = { | ||
ignoreEval: true, | ||
impliedStrict: eslintOptions.impliedStrict, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eslintOptions.ecmaFeatures.impliedStrict
index.js
Outdated
if (node.value && node.value.type === "TypeCastExpression") { | ||
visitTypeAnnotation.call(this, node.value); | ||
if (eslintOptions.globalReturn !== undefined) { | ||
eslintOptions.nodejsScope = eslintOptions.globalReturn; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eslintOptions.ecmaFeatures.globalReturn
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FYI, the eslintOptions.ecmaFeatures.globalReturn
is set by env: {node: true}
:
babel-eslint/test/non-regression.js
Line 17 in 42d0c5b
node: true, |
Thanks @mysticatea - interestingly I did not actually change the ones you pointed out, they were previously also missing My main issue was that I was setting Now that I have added the missing I have updated the description of the PR to reflect the current state, I am back to using your latest commit on the ESLint PR. |
Would it possible to address those issues separately? We could still hold off on a release if we feel like those are important things for the next major, but this feels like a big enough change for one PR already to me! |
One potential reason for doing everything at the same time: This PR is being used to evaluate the features in eslint/eslint#8755. I think the goal of eslint/eslint#8755 is to allow parsers like |
@not-an-aardvark Sounds good to me - wasn't clear to me if the other issues were actually related (the first one doesn't seem to be). |
lib/extend-default-visitor-keys.js
Outdated
BABEL_VISITOR_KEYS | ||
); | ||
extendedVisitorKeys.MethodDefinition.push("decorators"); | ||
extendedVisitorKeys.Property.push("decorators"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It looks like this still monkeypatches the default visitor keys from ESLint. Since extendedVisitorKeys
is only a shallow clone, the extendedVisitorKeys.MethodDefinition
array is still shared with the array from ESLint.
lib/get-eslint-modules.js
Outdated
var Definition = eslintMod.require("eslint-scope/lib/definition").Definition; | ||
var Referencer = eslintMod.require("eslint-scope/lib/referencer"); | ||
var Traverser = eslintMod.require("eslint/lib/util/traverser"); | ||
var ScopeManager = eslintMod.require("eslint-scope/lib/scope-manager"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All of these APIs are internal, and are subject to change/be removed in the future. Is it necessary to import the specific modules that are being used by ESLint? Could babel-eslint
use more generic modules instead, by depending on eslint-scope
and estraverse
directly? If not, what APIs would ESLint need to provide in order to make this possible?
Ideally, I think babel-eslint
should only use ESLint's public APIs. As currently implemented, this will break if e.g. ESLint stops depending on eslint-scope
in the future, or changes how Traverser
works internally. The overarching goal here is to fix the recurring issue of "babel-eslint
is broken due to an internal change in ESLint", but we can only achieve that if babel-eslint
avoids using internal APIs (and ESLint provides sufficient public APIs to make everything work and be stable).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I really like and agreed with that perspective, @not-an-aardvark!
I don't think depending on eslint-scope or estraverse directly is an option, because they need to be the matching versions to the end user's installed ESLint version. We would be leaving ourselves open to issues there if eslint-scope was a dep, but ESLint was a resolved peerDep.
I would like to hear from @mysticatea on this too, of course, because I believe I have implemented this how he originally intended in his ESLint PR, but I may be wrong.
I believe we would want to extend the ESLint PR further to provide APIs to solve the fragility you mention, and as I say I think you've made an excellent point.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can of course hack away on both sides (ESLint and babel-eslint) to try and come up with my "ideal" API surface, and then report back, but would be good to hear @mysticatea thoughts on what you have said and the implementation thus far.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think depending on eslint-scope or estraverse directly is an option, because they need to be the matching versions to the end user's installed ESLint version.
Could you clarify why this is a requirement? It seems like if babel-eslint
is being used and is providing scope information, then it doesn't matter what version of eslint-scope
is installed for eslint
, because the version of eslint-scope
from eslint
won't get used anyway.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- I think
babel-eslint
should haveeslint-scope
in owndependencies
of package.json. It can pin the version ofeslint-scope
until it gets public API to override its behavior. - I think
babel-eslint
should have own visitor keys instead of it extends ESLint's. - I think about
fallback: Traverser.getKeys
, we can move thefallback
logic from ESLint toeslint-scope
, so it's shared with all parsers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@not-an-aardvark I guess I didn't really have a specific scenario in mind, just a general sense of caution around babel-eslint
having to concern itself with two modules instead of one (ESLint and eslint-scope instead of just ESLint).
My concerns may well be unfounded, I think it was just a general sense of "what if the version of eslint-scope
which babel-eslint
depends is not the one which makes sense for the version of ESLint the user has installed", e.g. the user has a previous major version of ESLint installed, but the eslint-scope
is intended to be used with the current major version...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess I'm thinking about it like this: eslint-scope
is just a general scope analysis library. eslint
happens to use eslint-scope
for scope analysis by default, but provided that eslint-scope
doesn't make any major breaking changes, babel-eslint
should be to provide scope analysis however it chooses, including by using a separate version of eslint-scope
. So it shouldn't matter if the versions are different.
I'll take a look at this in the morning - looks really cool! |
Based on the comments up to and including my latest one: #509 (comment) Would you agree @mysticatea @not-an-aardvark @kaicataldo that it makes sense as a next step for me create a new branch on |
I'm not very familiar with the current state of |
Full disclaimer, I have no idea how |
@not-an-aardvark @mysticatea Please take another look, I have added a new commit which explores the idea of having It now does not need to resolve ESLint at all, because I have also branched You can see the branch here: https://github.com/eslint/eslint-scope/compare/api-for-babel-eslint?expand=1 It also adds a couple more things to the public API surface of If we do decide to go this route, we will obviously have to update @mysticatea ESLint PR to bring in the (I also bumped the babel and babylon related deps to their latest versions) |
Thanks @JamesHenry, that looks pretty good to me (although I'm not too familiar with |
Yeah, it's a fair enough point, it did occur to me too. Perhaps that needs to be discussed at a TSC meeting as it's yet another library to maintain? |
I'm actually not sure why we're using Would it be possible for |
We were/are I think, the ESLint PR that this PR is working towards removed it: eslint/eslint#8755 |
Closing in favour of #542 |
DO NOT MERGE.
This PR is an initial implementation of the proposed changes coming to ESLint in eslint/eslint#8755.
[Updated] summary of changes
parse()
and its required monkey patching in favour ofparseForESLint()
. This is a breaking change.parseForESLint()
method (ESLint will prefer this over aparse()
method if one is available anyway).babel-eslint
PR and so, as discussed with @hzoo, I wanted to leave the codebase in a state where it was a bit more accessible for the next developer. I am sorry that this makes the PR a little more involved to review, as things have moved around a bit.index.js
has deliberately been made very concise, with most things broken out into dedicated files within a newlib/
directory.[Updated] Remaining work
There are currently three failing tests related to a linting error being expected, but not found. I will try and find time to dig into these soon.
cc @kaicataldo