browserify / detective

Find all calls to require() no matter how deeply nested using a proper walk of the AST
Other
414 stars 61 forks source link

Skip commented-out requires #45

Closed paulmillr closed 1 year ago

paulmillr commented 9 years ago

Currently detective parses these as valid requires even though they are not.

require('b')
// require('c')
/*
  require('d')
*/

maybe with https://github.com/jonschlinkert/strip-comments

zertosh commented 9 years ago

I dig this idea. I took a quick look at strip-comments, and two things came to mind: (1) performance, but maybe it's not so bad; (2) strip-comments doesn't seem maintained anymore, not that it matters for the node-detective use case, but it removes comment-like things from strings (doesn't inspire confidence).

Any other ideas? I'd be awesome to be able to skip files if we can.

paulmillr commented 9 years ago

Not sure about other solutions. We can write our own solution that would do this on per-line iteration basis. Nothing fancy.

jmm commented 8 years ago

I must be misunderstanding something; how does Detective report those as requires when it uses the AST? Also, I don't get that when I try it with detective@4.0.0, which I presume was latest when this issue was created. I get only ["b"] as the output.

zertosh commented 8 years ago

@jmm, I think the OP is a bit misworded. The output is the same regardless of version (correctly ["b"]). detective has this optimization where is checks the source string for something that may look like a require, before even bothering to parse the AST. If the word "require" doesn't show up in the source, then you can be pretty sure that there isn't a require call. In the case where a word like "require" shows up in comments (like in jQuery), but not in code, you're parsing the AST for nothing. Stripping comments from source is pretty cheap, so it might be worth doing that before doing the fast check.

jmm commented 8 years ago

@zertosh Ah, gotcha, thanks for the explanation. I knew about that test, but I didn't connect the dots because I misinterpreted "parses" in the OP. I was also thrown off by the inclusion of the legit require() in the example.

Stripping comments from source is pretty cheap, so it might be worth doing that before doing the fast check.

Do you think it'd make sense to do the fast check, then, if that was positive, strip the comments and try it again?

jaydenseric commented 6 years ago

This is a pretty bad bug, and is easily encountered:

// eslint-disable-next-line require-jsdoc
function foo() {}
/**
 * Does foo.
 * @example
 * const foo = require('foo')
 * foo()
 */
export default function foo() {}

This issue appears to cause https://github.com/documentationjs/documentation/issues/1090.

goto-bus-stop commented 6 years ago

The issue there is that detective doesn't support JSX or ES modules syntax. It should not be run on JSX or ES modules files in the first place.

jaydenseric commented 6 years ago

@goto-bus-stop no, the point I'm making in this issue here is that people often use JSDoc @example comments that contain require, and // eslint-disable-next-line require-jsdoc comments which also contains require.

goto-bus-stop commented 6 years ago

This issue is not about a bug but an optimization. Implementing the optimization would only hide the issue you're describing, not fix it. It would pop back up the moment someone uses a string that contains 'require', or uses a method named someobj.require(), for example.

jaydenseric commented 6 years ago

@goto-bus-stop

This issue is not about a bug but an optimization.

This is the repo description:

Find all calls to require() no matter how deeply nested using a proper walk of the AST

If this causing a false positive is not a bug, then I don't know what is…

// eslint-disable-next-line require-jsdoc

There is clearly no call to require() in that code. I could tell that with simple regex, let alone a “proper walk of the AST”.

I'm happy to be corrected if I'm confused, or misdiagnosed something 😕

goto-bus-stop commented 6 years ago

It doesn't detect that require:

detective('// require("xyz")')
// → []
detective('require("xyz")')
// → ["xyz"]

The require string occuring inside a comment just means detective will parse the file to do the AST walk to check for require calls. If the word require does not occur in the file at all, detective doesn't even parse it and just returns an empty array immediately. If require does not occur in some part of the AST, that part is also entirely skipped. This issue is about stripping comments early so we can take advantage of the fast path in more cases.

The issue you're seeing is that a file containing JSX or ES modules is being passed to detective. If the file doesn't contain require at all, detective will take the fast path (without parsing), and not notice that it uses unsupported syntax. If it does, detective will try to parse it, but it doesn't support JSX so the parsing will fail.

e; see https://github.com/browserify/detective/issues/45#issuecomment-162582477

jaydenseric commented 6 years ago

The require string occuring inside a comment just means detective will parse the file to do the AST walk to check for require calls. If the word require does not occur in the file at all, detective doesn't even parse it and just returns an empty array immediately.

Bingo! That makes sense to me now, thanks :)

I was thinking it was reporting the actual strings.