-
Notifications
You must be signed in to change notification settings - Fork 9.4k
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
tests(lint): require file extension in require() #9017
Conversation
Hmm, we could use this for a returned |
all the time. how else do you format? |
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.
eslint is my preferred path too, how hard is it to write a fixer for a rule?
@@ -9,7 +9,7 @@ const BaseNode = require('../base-node.js'); | |||
const TcpConnection = require('./tcp-connection.js'); | |||
const ConnectionPool = require('./connection-pool.js'); | |||
const DNSCache = require('./dns-cache.js'); | |||
const mobileSlow4G = require('../../../config/constants').throttling.mobileSlow4G; |
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 am so curious how these slipped through haha
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.
the answer here is I was conservative and only matched require(...);
and since these do require(...).someVariable
they didn't match :)
@@ -70,7 +70,7 @@ function generateConfig(configJson, flags) { | |||
|
|||
lighthouse.generateConfig = generateConfig; | |||
lighthouse.getAuditList = Runner.getAuditList; | |||
lighthouse.traceCategories = require('./gather/driver').traceCategories; | |||
lighthouse.traceCategories = require('./gather/driver.js').traceCategories; | |||
lighthouse.Audit = require('./audits/audit.js'); |
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.
yikes 😬 those probably need to be fixed and tests added that these don't throw?
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.
yikes 😬 those probably need to be fixed and tests added that these don't throw?
I think this is a valid path? I'm not getting the context of the 😬here :)
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.
if (file.endsWith('.json')) continue; | ||
const fullPathOfDep = path.resolve(dir, file); | ||
if (!fs.existsSync(fullPathOfDep)) { | ||
console.warn(`Uh-oh! Cannot find dependency "${fullPathOfDep}" in ${name}`); // eslint-disable-line no-console |
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.
maybe we should run this line over the codebase without the '.js'
and .json
checks to see if it broke anything else?
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.
maybe we should run this line over the codebase without the '.js' and .json checks to see if it broke anything else?
I was hoping tsc would catch any of those since it usually complains about "Cannot find module", but I can definitely run that over the codebase
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.
seems like this was all false alarms from the GH UI bug lol, so you can feel free to ignore that comment
haha, I guess the red underlines in my editor leave me unable to continue until I fix things, so it never gets too bad
I don't think it'll be hard, it can mostly rip off what's done in dot-js.js |
updated with To test, I reverted the changes in #9006 and this PR and verified that the required paths were restored to the same fixed state (only had to add back the |
const traceSaver = require('../../../lighthouse-core/lib/lantern-trace-saver.js'); | ||
const PredictivePerf = require('../../audits/predictive-perf.js'); | ||
const Simulator = require('../../lib/dependency-graph/simulator/simulator.js'); | ||
const traceSaver = require('../../lib/lantern-trace-saver.js'); |
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.
the only path changes that aren't adding a suffix because these files are already under lighthouse-core/
:)
The lint rule actually won't flag or fix this case normally (since the paths do have a file extension and they resolve to a file), but these were changed when I was testing on the reverted #9006 (which added .js
to them) and it seems worth keeping the simplified form
@@ -6,6 +6,7 @@ | |||
'use strict'; | |||
|
|||
// NOTE: this require path does not resolve correctly. | |||
// eslint-disable-next-line local-rules/require-file-extension |
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.
these are broken on purpose
@@ -5,7 +5,6 @@ | |||
*/ | |||
'use strict'; | |||
|
|||
// eslint-disable-next-line |
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.
here and in network-analyzer-test.js
were fixed in #9006 but the new --fix
missed these because of these disable comments. I assume these were originally disabled for max-len
but maybe moving files reduced the path length over time. It's fine without the disable now
tsconfig.json
Outdated
@@ -18,6 +18,7 @@ | |||
"clients/**/*.js", | |||
"build/**/*.js", | |||
"./types/**/*.d.ts", | |||
"*.js", |
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.
what prompted this?
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.
type checking ./eslint-local-rules.js
. I can narrow it if it messes with people's local, untracked scripts :)
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.
yes please if we can :)
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.
LGTM! yay for cleaner PR reviews :D
eslint-local-rules.js
Outdated
|
||
context.report({ | ||
node: node, | ||
message: 'Required path must have a file extension.', |
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.
super nit but this message felt a bit weird to me since Required
is so typically used for Necessary
/Mandatory
brainstorm of alternatives
Path of module must have a file extension
Path of required module must have a file extension
Require path must have a file extension
Local require path must have a file extension
Path to require must have a file extension
Local path to require must have a file extension
if (!resolvedRequiredPath) { | ||
return context.report({ | ||
node: node, | ||
message: `Cannot resolve module '${requiredPath}'.`, |
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.
FWIW, the eslint messages I see don't end in periods
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.
FWIW, the eslint messages I see don't end in periods
interestingly eslint seems to take care of this itself. e.g.
let asdf = 'asdf';
when hovering in vscode give
'asdf' is assigned a value but never used. Allowed unused vars must match /(^_$)/.
'asdf' is never reassigned. Use 'const' instead.
(with periods) and they do have periods in the source.
But then in the CLI output, you get
error 'asdf' is assigned a value but never used. Allowed unused vars must match /(^_$)/
error 'asdf' is never reassigned. Use 'const' instead
(no periods).
The same thing happens to this message, so I guess they auto-trim periods when printing? Pretty funny.
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.
woah that's awesome haha
const requireFileExtension = { | ||
meta: { | ||
docs: { | ||
description: 'disallow require() without a file extension', |
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.
or wait, is this the message that shows up in eslint CLI?
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 this is actually if you generate docs for the rule?
On the command line you just get error Local require path must have a file extension
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.
Ah gotcha!
eslint-local-rules.js
Outdated
// a suffix to the existing path, but sometimes humans write confusing | ||
// paths, e.g. './lighthouse-core/lib/../lib/lh-error.js'. To cover both | ||
// cases, double check that the paths resolve to the same file. | ||
const resolvedFixedPath = requireResolveOrNull(fixedPath, contextDirname); |
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.
is there a reason all this is outside fix()
if we only use it for the fix case?
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.
is there a reason all this is outside
fix()
if we only use it for the fix case?
Good point, it'll save time in the non --fix
case if it's inside fix()
, so I'll move it.
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.
Good point, it'll save time in the non
--fix
case if it's insidefix()
, so I'll move it.
well, only if there are a bunch of resolvable requires that don't have a file extension, and I'd imagine most of them would be hitting the require cache, so in practice it won't really save any time, but it looks less overwhelming inside fix()
than I thought it would and it makes sense to keep it together
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.
yeah I wasn't really thinking about speed, just relatedness 👍
enforce change made in #9006
creates a local eslint rule that requires a local path in a
require()
statement includes the file extension. eslint has support for local rules on the command line via--rulesdir
, but that means it won't work in text editors with an eslint plugin installed.eslint-plugin-local-rules
is an eslint plugin that gets around that by just loading a local file as its own payload. The downside is that it has to be a root-level file, but on the plus side it works for our inherited.eslintrc.js
files for the clients and viewer.(there's another similar plugin
eslint-plugin-rulesdir
that allows specifying the location of the file, but I'm not sure if it inherits and it appears like it might be broken in vscode (eslint-community/eslint-plugin-rulesdir#2), something that's been tested and is working ineslint-plugin-local-rules
(cletusw/eslint-plugin-local-rules#1))happy to bikeshed on how we do this
(also picks up a few places that #9006 missed and deletes
dot-js.js
as hopefully we don't need any more mass fixes, but I can restore if we want to keep it)