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

Implement the no-use-before-define ESLint rule #770

Merged
merged 4 commits into from
Nov 28, 2016

Conversation

aickin
Copy link
Contributor

@aickin aickin commented Nov 23, 2016

Turned on the no-use-before-define rule, in reference to bug #763, and changed the files that didn't pass the new listing rule.

I first turned the rule on completely, but renderMiddleware got really hairy, so I went back and used the {functions: false} parameter to the rule. This means that basic functions don't need to be defined in order, which is OK from a functionality perspective because functions are always hoisted. renderMiddleware is a bit of function soup, so setting this parameter let me sidestep it without compromising on correctness. If someone else wants to tackle implementing the rule with {functions:true}, that's cool, but it's also probably fine not to do so, as well.

I just moved functions or variable definitions around in the files without changing their contents, except for two cases, both of which involved circular references, and which probably require closer review:

  1. ReactServerAgent: this one had a function that referred to the API object, and the methods of the API object call the function. I fixed it by inlining and deleting the function.
  2. PageUtil: the exported object, PageUtil, had a method named makeArray, which was referenced as PageUtil.makeArray in a bunch of functions in the file. Those functions, in turn, are members of PageUtil, causing a circular reference. To break that, I made makeArray a top level function; it doesn't use this at all and is a simple no side effects helper, then I changed all the calls to PageUtil.makeArray to makeArray. I left makeArray as a member of PageUtil, because I have no idea if clients of this file use it or not. Also of note but unrelated: I had to move around the variable declarations inside of the PageConfig definition.

Let me know what y'all think!

@aickin
Copy link
Contributor Author

aickin commented Nov 23, 2016

FYI, because I didn't use comma-chained declaration in RootElement.js, this will have merge conflicts with PR #769. If you choose to merge #769 first, I'll happily do the merge; it should not be difficult at all.

// once the compiler has been run. The file path returned from the promise
// can be required and passed in to reactServer.middleware().
// TODO: add options for sourcemaps.
export default (opts = {}) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Ugh. This is exactly what you said would happen, but it's just as painful as expected.

It's nice to have default exports at the top of modules!

I guess this is the price we pay for the safety this rule provides. 😖

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I hear you; I think I was the original author of a few of those files in that format.

Another option is to convert functions in those files from const foo = (bar) => { /* body */} to function foo(bar) {/* body */} and rely on function hoisting, which I think would allow you to put the exports at the top in most cases (but maybe not all? haven't thought it through). Less ES6-y and relies on some hoisting magic, but maybe more readable? (Maybe?)

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, IMO the little bit of hoisting magic there is worth it for the benefit of having the first thing you see when you open a module be the part you're looking for.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK, gimme a sec. I'll try it out.

@gigabo
Copy link
Contributor

gigabo commented Nov 23, 2016

this will have merge conflicts with PR #769... I'll happily do the merge

Oh, thanks for pointing that out. Yeah, let's merge that first and have you handle the conflict resolution, since the author over there is a pretty new contributor.

@@ -2,6 +2,59 @@ import yargs from "yargs"
import fs from "fs"
import pem from "pem"

const sslize = async argv => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Since this is set up with {functions: false}, would it work to just turn these into normal functions to avoid having to move them above the default exports?

Like, could this stay where it was and turn into:

async function sslize(argv) {
    ...
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, heh, you had the same thought. 😁

…f moving the functions all around, the PR now converts them to hoisted JavaScript functions. Should disrupt the file organization less.
@aickin
Copy link
Contributor Author

aickin commented Nov 23, 2016

OK, I updated the PR with a version that just converts var foo = function() {} to function foo() {} and depends on hoisting. It's much less disruptive (~300 lines changed vs. ~630 in the previous version), and it allows you to keep default exports at the top of the file if that's what you're into.

There are a couple files (logging/server.js and logging/stats.js) where I converted some functions that didn't strictly need to be converted in order to make the linting rule pass. I thought it was better to do that than to have functions defined a bunch of different ways in the same file.

@gigabo
Copy link
Contributor

gigabo commented Nov 23, 2016

Oh, man, that's so much better! 😌

@gigabo
Copy link
Contributor

gigabo commented Nov 23, 2016

I converted some functions that didn't strictly need to be converted in order to make the linting rule pass. I thought it was better to do that than to have functions defined a bunch of different ways in the same file.

Yeah, much nicer that way. Thanks for thinking of that.

@@ -17,6 +17,85 @@ var {isTheFold, markTheFold} = require('../components/TheFold');
// These three data structure define the page interface.


var PageConfig = (function(){
Copy link
Contributor

Choose a reason for hiding this comment

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

Hmm... this is moving a bunch of private helpers up to the top, where the data structures that define the public interface used to be. This one's trickier, isn't it... 🤔

If nothing else the comments above here should stay with the section with those data structures.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

OK. I was unclear if those comments were for clients of this file (in which case they make more sense to me at the top of the file) or folks who are going to muck with the impl of this file (in which I case they definitely belong below). I'll move them!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

And, I should say, I skimmed the comments at best ;)

Copy link
Contributor

Choose a reason for hiding this comment

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

I was unclear if those comments were for clients of this file... or folks who are going to muck with the impl of this file

Both. 😹

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hahahahahaha.

In any case, the PR is updated, and the comment was reunited with the code. Onwards!

@gigabo
Copy link
Contributor

gigabo commented Nov 28, 2016

Okay @aickin I've just merged #769. Please rebase this when you get a chance.

@aickin
Copy link
Contributor Author

aickin commented Nov 28, 2016

Great! It's rebased, and I'll keep an eye on the CI build; let me know if you need anything more.

@gigabo gigabo added the bug An issue with the system label Nov 28, 2016
@gigabo
Copy link
Contributor

gigabo commented Nov 28, 2016

Thanks @aickin!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug An issue with the system
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants