Adding JSLint to ReviewBot
Review Request #3435 — Created Oct. 21, 2012 and discarded
Implementation of the JSLint tool for ReviewBot. Parses all uploaded files to a review request and outputs descriptive comments on the relevant .js source files on lines where style errors are found. Options for this tool can be configured in the tool's admin panel. This addition to ReviewBot requires that SpiderMonkey be installed (other engines might also be suitable but have not been tested) to enable the running of the jslint.js linting tool.
manual testing: - tested jslint on the spidermonkey commandline to make sure that the script itself was working as expected locally. - tested what error output the jslint.com website provides for a given file and tested ReviewBot on local dev server tool by posting a review with same file and ensuring output is the same with the same options ticked (seeing that file with errors was being commented by ReviewBot). - started by importing all of the dependencies used by the jslint.com website and removed all which were not necessary to the standalone jslint tool, testing that it yielded the same results. Those other dependencies were only necessary for web purposes, even if Doug Crockford suggests they be bundled with jslint itself and minified. - tested changing options in the option panel, and making sure they affect the output of the static analysis tool in locally published reviews. Included print statements in py and js scripts to make sure the correct options were being passed into jslint.
Description | From | Last Updated |
---|---|---|
This should probably be renamed. JSLint is more than a style checker. |
SM smacleod | |
This should probably be adjusted like 'name'. It might be a good idea to include the version number of JSLint … |
SM smacleod | |
This should probably be changed to be case insensitive. I've seen some use '.JS' I really would like to add … |
SM smacleod | |
This appears to still be just copied from the pep8 tool, but you'll need to change this parsing code to … |
SM smacleod | |
let's put these in alphabetical order. |
SM smacleod | |
As Aamir pointed out, 'import os' should be coming first. Imports should be ordered like this: Standard Library imports (e.g. … |
SM smacleod | |
If this is enabled, I think you should definitely indicate in the review body_top, or body_bottom that the scan was … |
SM smacleod | |
This should probably be done only once per request, instead of every time handle_file is called (Once per file). You'll … |
SM smacleod | |
I don't think this is quite correct. The package key should probably be 'reviewbot', or 'reviewbot.tools'. I'm fine with lib … |
SM smacleod | |
Let's rename jsLint.py to jslint.py. So, this should be changed to 'jslint = reviewbot.tools.jslint:JSLintTool', |
SM smacleod | |
I believe, generally, we prefer the higher level imports to go above the more granular ones, so line 3 and … |
mike_conley | |
Evil? Or Eval? Or Evil-Eval? Not sure if this is being cheeky, or just a typo. :) |
mike_conley | |
Isn't 80 the traditional character limit? Or is something here 0-indexed? Or have I just been lied to all my … |
mike_conley | |
PACKAGE_ROOT is in all caps, and lib_path is not. Why? |
mike_conley | |
Can you not simply pass the actual True and False literals to the script? Will the JS engine accept something … |
mike_conley | |
Might not be necessary to sent the lowercase form of the strings. runJSLint is checking the content of the string … |
AL Allyshia | |
Yeah, maybe this is overkill then. |
mike_conley | |
This line will need to be indented two more spaces, since it's still inside the dicts parens. |
mike_conley | |
Is there a reason this is not called *before* we do all of JSLineTool's specialized stuff? |
mike_conley | |
Let's put a newline after the if-block. |
mike_conley | |
I don't think the string representation of dict for the things you're passing is going to change anytime soon, so … |
mike_conley | |
self.jsLintOptions is a dict. wondering if we should depend on auto-formatting of dict to string used here or whether we … |
AL Allyshia | |
Yeah, a little less silent-fail would probably be good here. |
mike_conley | |
This function should be documented. Also, as a general rule, we tend to use 4-space indentation for Javascript. |
mike_conley | |
var options |
mike_conley | |
Should be formatted like: if (custom_options) { ... } |
mike_conley | |
for (var op in custom_options) { |
mike_conley | |
var custom |
mike_conley | |
See comment on line 127 of jslint.py. Originally this check did not exist, and we passed the straight string value … |
AL Allyshia | |
It'd be nice if the caller could just pass in things typed as one would expect, without having to jump … |
mike_conley | |
It'd be awesome to have the tool return an all-clear. Maybe even a ship-it, if the tool is configured for … |
mike_conley | |
} else { |
mike_conley | |
Spaces on either side of the =, space before the { |
mike_conley | |
Space after the if and before the { |
mike_conley | |
Spaces on either side of the +'s, and line up line 33 so that it's still contained (vertically) within the … |
mike_conley | |
2 Blank lines here. |
SM smacleod | |
> 79 characters |
SM smacleod | |
Can we break this out one per line, 4 space indented. |
SM smacleod | |
I'm curious why you're having to call int(...) here. The values of self.settings *should* be the proper type, is this … |
SM smacleod | |
Could we change the formatting here a bit (Also note the trailling comma): "load('%s'); runJSLint('%s', read('%s'), %s);" % ( self.runJSLint_path, … |
SM smacleod |
- Change Summary:
-
small fix to setup.py to match entry_point name to class name defined in jsLint.py
-
-
-
This should probably be adjusted like 'name'. It might be a good idea to include the version number of JSLint (Not the self.version, but the actual JSLint projects version) in the description here.
-
This should probably be changed to be case insensitive. I've seen some use '.JS' I really would like to add better support for file matching to review bot in general, and make it so tool devs don't have to worry about this. I haven't thought of a good solution yet though.
-
This appears to still be just copied from the pep8 tool, but you'll need to change this parsing code to match the output from your javscript.
-
It's probably worth figuring out a way to pass these options in from the python code. If you can't pass arguments into the JS, you could probably generate 'options' in the python, and pass it as a string as part of the call to execute. Once you solve that problem, they can be added to the admin panel like the pep8 tool's 'max_line_length'.
-
- Status:
- Re-opened
- Description:
-
+ UPDATE:
+ - addressed first comments + - wondering about new lib structure. Should the lib folder be like reviewbot/lib/JSLint as previously suggested or would there be any benefit to having it be /reviewbot/tools/lib ... -- was left this way for simplicity when constructing paths for now, but can be easily changed. + - passing in path to jslint.js to runJSLint.js for now and allowing runJSLint to load it rather than loading it manually inside the jsLint.py script. Any thoughts on whether another way would be better? + - will do some more testing and perhaps error handling + NOTE : bot/reviewbot/tools/jslint.js and bot/reviewbot/tools/runJSLint.js have been DELETED. + + + - new static analysis tool for ReviewBot : JSLint, Douglas Crockford's JavaScript inspector
- jslint.js source is "latest" taken from git://github.com/douglascrockford/JSLint.git
- adding a new js file to run jslint with certain parameters and print desired output to stdout*
- DEPENDENCY: Spidermonkey 1.8.5 JS Engine for running JS code
- js code is run from command line using "execute" command in ReviewBot Tool as is done for PEP8
*NOTE that this makes using python-spidermonkey unnecessary for writing/calling js code in our Python scripts.
OTHER NOTES:
* using spidermonkey "read(<filename>)" method for reading the file to be parsed and analyzed, but other possibility is to get patched file contents as a string from the File object in the targetted review and use that instead. Comments welcome. * need to figure out a better file structure for storing the js file resources used by jsLint.py. Currently: ReviewBot/bot/reviewbot/Tools
jsLint.py
pep8.py
jslint.js
runJSLint.js
...- options can be initialized in jsLint.py (as in pep8 model) rather than in runJSLint.js...comments welcome.
Other TODOs:
- play with more options, give user options from RB interface when manually triggering JSLint? - Testing Done:
-
- manual testing of running JSLint from within Python tool
- - Still need to add inline text to diff view using existing interface, then will test that manually
-
-
As Aamir pointed out, 'import os' should be coming first. Imports should be ordered like this: Standard Library imports (e.g. os, sys, etc.) ===BLANK LINE=== Third Party imports ===BLANK LINE=== Local Imports (e.g. 'reviewbot...') Also, imports should be ordered alphabetically within the three categories.
-
If this is enabled, I think you should definitely indicate in the review body_top, or body_bottom that the scan was stopped after a single error. Maybe even print PASSED, or FAILED etc. In most cases we'll probably want to find all errors and print them, so I think you should probably default this to False. I think you were probably emulating the defaults from JSLint itself, but False seems more natural in our setting. Also, this reminds me, does JSLint stop on certain errors, and refuse to continue scanning until they are fixed? If this is the case, is there a way we can detect this, and indicate to the user that scanning stopped after that point?
-
This should probably be done only once per request, instead of every time handle_file is called (Once per file). You'll probably want to override handle_files, or execute, and take care of this stuff there. Make sure to call the base class' method from your overridden method.
-
What exactly does JSLint output which causes the failure? I'm wondering if it's something that should be displayed in the review another way?
-
Quite the opinionated option, with quite a useless description. Not sure what this does, but it gives me the vibe it could be a hot button issue. Do you think this is an option we should include? I'd say we should at least figure out what it does.
-
I don't think this is quite correct. The package key should probably be 'reviewbot', or 'reviewbot.tools'. I'm fine with lib being inside the tools folder, but I think the JSLint specific stuff needs to be put in a sub folder as well (We may end up expanding with other things in here, and I'd like to have it organized). So, you'll have something like: package_data={ 'reviewbot.tools': [ 'lib/jslint/*.js', ] }
-
Let's rename jsLint.py to jslint.py. So, this should be changed to 'jslint = reviewbot.tools.jslint:JSLintTool',
- Change Summary:
-
- Addressed previous comments, including style changes and changes to lib structure. - Modified the way JSLINT accepts and handles options (in both py and js scrpts). Managed to fix the issue whereby scan was stopping short of full completion when run as a ReviewBot tool, though this still requires a bit of testing to ensure that it is performing optimally. It seems that running jsling directly from the spidermonkey commandline actually scans up to 91% of the file, whereas the maximum hit for running via the python tool for the same file was 75%. Not sure if there is a difference in the way options are passed that is making that difference, and more testing should be done to ensure that that difference still holds. Managed to match the scanning level (75%) as seen on the jslint.com website, which is expected performance. -POSSIBLE IMPROVEMENTS: have a pass/fail notice written at the top-of-file comment section, notify the user whether premature stopping was due to pass/fail option being set to true in user options?
- Testing Done:
-
~ - manual testing of running JSLint from within Python tool
~ manual testing:
+ - tested jslint on the spidermonkey commandline to make sure that the script itself was working as expected locally. + - tested what error output the jslint.com website provides for a given file and tested ReviewBot tool by posting a review with same file and ensuring output is the same with the same options ticked. + - started by importing all of the dependencies used by the jslint.com website and removed all which were not necessary to the standalone jslint tool, testing that it yielded the same results. Those other dependencies were only necessary for web purposes, even if Doug Crockford suggests they be bundled with jslint itself and minified. + - tested changing options in the option panel, and making sure they affect the output of the static analysis tool in locally published reviews. Included print statements in py and js scripts to make sure the correct options were being passed into jslint.
-
Somme comments to guide reviewers and sollicit feedback.
-
Might not be necessary to sent the lowercase form of the strings. runJSLint is checking the content of the string anyway, it could check for upper case "True" and "False".
-
self.jsLintOptions is a dict. wondering if we should depend on auto-formatting of dict to string used here or whether we should use an explicit json.dumps() type conversion to string. Thoughts on why that might be advantageous?
-
See comment on line 127 of jslint.py. Originally this check did not exist, and we passed the straight string value to jslint as an option. Since conversion to boolean value, kept on accepting lower case string since it best mimics the js boolean values (you could argue in the interest of modularity, if another program were to use this js script, they might not send in uppercase 'True' and 'False', so we are picking a standard).
-
-
I believe, generally, we prefer the higher level imports to go above the more granular ones, so line 3 and 4 should be swapped.
-
-
Isn't 80 the traditional character limit? Or is something here 0-indexed? Or have I just been lied to all my life?
-
-
Can you not simply pass the actual True and False literals to the script? Will the JS engine accept something like: js -e "load('foo'); runJSLint('bar', read('baz'), {someOption: false, otherOption: true}" ?
-
-
-
-
-
I don't think the string representation of dict for the things you're passing is going to change anytime soon, so I'm not too worried, personally. This line needs to have two spaces removed from its indentation.
-
-
This function should be documented. Also, as a general rule, we tend to use 4-space indentation for Javascript.
-
-
-
-
-
It'd be nice if the caller could just pass in things typed as one would expect, without having to jump through type conversion hoops...see my question above about passing boolean literals.
-
It'd be awesome to have the tool return an all-clear. Maybe even a ship-it, if the tool is configured for it. (The ship-it thing might be out of scope, and a nice-to-have...but I think hearing about a no-error run would be a good thing).
-
-
-
-
Spaces on either side of the +'s, and line up line 33 so that it's still contained (vertically) within the parentheses of the above line.
- Change Summary:
-
taking out of WIP status addressed latest comments: - made style/formatting changes to both .py and .js source, added documentation - used json.dumps() instead of stringified dictionary for passing custom options to runJSLint.js so that conversion from string to boolean is not necessary on JS side and we don't have to pass lowercase string values of booleans True and False on the py side. - added TODOs for implementing proper failure/success messages to the user -- support for this section in a review should be added. - cleaned up error handling to return False (ignore file) on ValueError in jslint.py TESTED that behaviour of jslint was maintained after these changes and that changes to the option (admin) panel were picked up on new reviews.
- Change Summary:
-
Condensed description.
- Description:
-
~ UPDATE:
~ Implementation of the JSLint tool for ReviewBot. Parses all uploaded files to a review request and outputs descriptive comments on the relevant .js source files on lines where style errors are found. Options for this tool can be configured in the tool's admin panel. This addition to ReviewBot requires that SpiderMonkey be installed (other engines might also be suitable but have not been tested) to enable the running of the jslint.js linting tool.
- - addressed first comments - - wondering about new lib structure. Should the lib folder be like reviewbot/lib/JSLint as previously suggested or would there be any benefit to having it be /reviewbot/tools/lib ... -- was left this way for simplicity when constructing paths for now, but can be easily changed. - - passing in path to jslint.js to runJSLint.js for now and allowing runJSLint to load it rather than loading it manually inside the jsLint.py script. Any thoughts on whether another way would be better? - - will do some more testing and perhaps error handling - NOTE : bot/reviewbot/tools/jslint.js and bot/reviewbot/tools/runJSLint.js have been DELETED. - - - - - new static analysis tool for ReviewBot : JSLint, Douglas Crockford's JavaScript inspector
- - jslint.js source is "latest" taken from git://github.com/douglascrockford/JSLint.git
- - adding a new js file to run jslint with certain parameters and print desired output to stdout*
- - DEPENDENCY: Spidermonkey 1.8.5 JS Engine for running JS code
- - js code is run from command line using "execute" command in ReviewBot Tool as is done for PEP8
*NOTE that this makes using python-spidermonkey unnecessary for writing/calling js code in our Python scripts.
- - OTHER NOTES:
- * using spidermonkey "read(<filename>)" method for reading the file to be parsed and analyzed, but other possibility is to get patched file contents as a string from the File object in the targetted review and use that instead. Comments welcome. - * need to figure out a better file structure for storing the js file resources used by jsLint.py. Currently: - - ReviewBot/bot/reviewbot/Tools
jsLint.py
pep8.py
jslint.js
runJSLint.js
...- - - options can be initialized in jsLint.py (as in pep8 model) rather than in runJSLint.js...comments welcome.
- - Other TODOs:
- - play with more options, give user options from RB interface when manually triggering JSLint? - Testing Done:
-
manual testing:
- tested jslint on the spidermonkey commandline to make sure that the script itself was working as expected locally. ~ - tested what error output the jslint.com website provides for a given file and tested ReviewBot tool by posting a review with same file and ensuring output is the same with the same options ticked. ~ - tested what error output the jslint.com website provides for a given file and tested ReviewBot on local dev server tool by posting a review with same file and ensuring output is the same with the same options ticked (seeing that file with errors was being commented by ReviewBot). - started by importing all of the dependencies used by the jslint.com website and removed all which were not necessary to the standalone jslint tool, testing that it yielded the same results. Those other dependencies were only necessary for web purposes, even if Doug Crockford suggests they be bundled with jslint itself and minified. - tested changing options in the option panel, and making sure they affect the output of the static analysis tool in locally published reviews. Included print statements in py and js scripts to make sure the correct options were being passed into jslint.
-
The latest diff seems to have been uploaded strangely, only showing part of the change. Could you please update this again with the full patch?
-
Allyshia, this is looking really good. I pulled the patch down, and ran Review Bot locally against it with PEP8 and JSLint :D We are going to have to update this to be a separate package before it can be committed though (The JSLint Licensing issues :/). We can discuss that in IRC.
-
-
-
-
I'm curious why you're having to call int(...) here. The values of self.settings *should* be the proper type, is this not the case?
-
Could we change the formatting here a bit (Also note the trailling comma): "load('%s'); runJSLint('%s', read('%s'), %s);" % ( self.runJSLint_path, self.jsLint_path, path, json.dumps(self.jsLintOptions)),
- Change Summary:
-
- addressing formatting issues brought up in last review - this review request will continue as a new request on a new repo as JSLint is being moved out of Review Bot.