Integrating JSLint more tightly into NetBeans

Updated on August 3rd, 2009, to reflect jslint4java release 1.3.1

In my previous blog entry, Netbeans, JavaScript, Ant, Hudson, and JSLint: Oh my!, I described an approach for integrating JSLint into my NetBeans project.  While this approach worked, I still had to navigate to each JavaScript issue manually.  This is a huge pain, something that I haven't done since my earliest days as a developer, before I learned about Emacs' next error functionality.  NetBeans also has a really nice "Next Error" function that automatically navigates the user to the next error detected by the compiler.  Unfortunately, NetBeans didn't recognize the native output of JSLint.   This got me thinking about building a custom wrapper around JSLint so I can transform the output to whatever NetBeans would be happy with.

At roughly the same time, Dominic Mitchell posted a comment in response to my blog entry, pointing me towards jslint4java, which not only wraps JSLint and transforms its output, but it also provides a nice JSLint task interface to Ant.  This looked very promising, so I gave the just recently released jslint4java version 1.3 a whirl, but unfortunately, NetBeans did not recognize the output as errors.

Netbeans not recognizing output as an error

After some experimenting, I learned that NetBeans expects compiler errors to have exactly the same format as javac error messages.  As an example, version 1.3 of jslint4java outputs:

utilities.js:145:22:Use '===' to compare with 'undefined'

Whereas NetBeans expects the following output:

/Users/ashamash/projects/omalley/src/trunk/CQS/web/js/utilities.js:145:22: Use '===' to compare with 'undefined'.

There are two subtle differences:

  • All filenames need to have the full path (e.g. /Users/ashamash/projects/omalley/src/trunk/CQS/web/js/utilities.js vs. just utilities.js)
  • There needs to be a space between the colon and the error description (e.g. 145:22: Use vs. 145:22:Use)

With these two changes, NetBeans is a lot happier:

NetBeans recognizing output as an error

I sent Dominic the code changes needed to implement this, and after a couple of rounds of collaboration, the current development version of jslint4java has these modifications in it, as well as release jslint4java release 1.3.1 (released July 31st, 2009).

To integrate this version into NetBeans builds, follow these steps:

  1. Download jslint4java release 1.3.1 from http://jslint4java.googlecode.com/files/jslint4java-1.3.1-dist.zip, unpack it somewhere, note the path to the jslint4java-1.3.1.jar file.
  2. Define the properties needed in nbproject/project.properties:
    #
    # cqs.build.jslint: true/false setting to determine whether to run the
    # jslint javascript analysis utility on the individual javascript
    # files.  Default is true for production purposes, but developers can
    # set it to false in the file private/private.properties.  It is
    # highly recommended that this be left to true.
    #
    # cqs.build.jslint.failonerror: this true/false setting determines
    # whether the build should fail or not if jslint detects any errors.
    # Currently set to false until we fix all the javascript code so it
    # passes jslint.
    #
    cqs.build.jslint=true
    cqs.build.jslint.failonerror=false
    #
    cqs.js.jslint.files=\\
           js/utilities.js,\\
           js/file2.js,\\
           js/file3.js
    
  3. Now, you are ready to integrate jslint4java into your project's build.xml file, this is the Ant task that we use.  In our project, we keep an explicit list of JavaScript files we want to lint, so we can separate them from 3rd party code.  Another approach, described in the jslint4java docs, is to analyze all the JavaScript files in a given directory.  You can do what works best for you. 
        <target name="doJSLint4Java">
            <echo level="info" message="doJSLintWithJSLint4Java: running on files ${cqs.js.jslint.files}...." />
            
            <property name="jslint4java.dir" value="../tools/jslint4java-1.3.1" />
            <property name="jslint4java.jar.file" value="${jslint4java.dir}/jslint4java-1.3.1.jar"/> 
            <available file="${jslint4java.jar.file}" property="jslint4java.jar.file.available" />
            <fail unless="jslint4java.jar.file.available" message="jslint4java Jar file not found - expected at ${jslint4java.jar.file}" />
    
            <taskdef name="jslint4java"
                     classname="com.googlecode.jslint4java.ant.JSLintTask"
                     classpath="${jslint4java.jar.file}" />
    
            <jslint4java haltOnFailure="${cqs.build.jslint.failonerror}">⁞
              <formatter type="plain" />
              <filelist id="jslint.filelist" dir="${basedir}/web" files="${cqs.js.jslint.files}"/>
            </jslint4java>
    
            <echo level="info" message="doJSLintWithJSLint4Java: finished running...." />
        </target>
    
    
  4. For our project, we use "The Good Parts" JSLint setting, and embed the appropriate settings as a comment at the top of our JavaScript files.  You can use the tool at http://jslint.com/ to help you figure out which settings are best for your project.

And that's it.  You should read about best practices with JSLint, etc.  Thanks to Dominic Mitchell for making this tool available!

If you want to build it from scratch, you can follow these steps:

  1. Download the current snapshot of jslint4java, use git:
    $ git clone git://github.com/happygiraffe/jslint4java.git
    Initialized empty Git repository in /Users/ashamash/projects/jslint4java/src/jslint4java/.git/
    remote: Counting objects: 2548, done.
    remote: Compressing objects: 100% (862/862), done.
    remote: Total 2548 (delta 1028), reused 2346 (delta 940)
    Receiving objects: 100% (2548/2548), 1021.89 KiB | 232 KiB/s, done.
    Resolving deltas: 100% (1028/1028), done.
    $ 
    
  2. To build it, use Maven:
    $ mvn -Pdist clean package
    [INFO] Scanning for projects...
    [INFO] Reactor build order: 
    [INFO]   jslint4java parent
    [INFO]   jslint4java
    [INFO]   jslint4java ant task
    [INFO]   jslint4java docs
    [INFO]   jslint4java distribution
    [INFO] ------------------------------------------------------------------------
    [INFO] Building jslint4java parent
    [INFO]    task-segment: [clean, package]
    [INFO] ------------------------------------------------------------------------
    [INFO] [clean:clean]
    [INFO] Deleting file set: /Users/ashamash/projects/jslint4java/src/jslint4java/target (included: [\*\*], excluded: [])
    [INFO] [site:attach-descriptor]
    [INFO] [javadoc:jar {execution: attach-javadocs}]
    [INFO] Not executing Javadoc as the project is not a Java classpath-capable package
    [INFO] Preparing javadoc:aggregate
    [INFO] ------------------------------------------------------------------------
    [INFO] Building jslint4java parent
    [INFO] ------------------------------------------------------------------------
    [WARNING] Removing: aggregate from forked lifecycle, to prevent recursive invocation.
    [INFO] No goals needed for project - skipping
    [INFO] ------------------------------------------------------------------------
    [INFO] Building jslint4java
    [INFO] ------------------------------------------------------------------------
    [INFO] No goals needed for project - skipping
    [INFO] ------------------------------------------------------------------------
    [INFO] Building jslint4java ant task
    [INFO] ------------------------------------------------------------------------
    [INFO] No goals needed for project - skipping
    [INFO] ------------------------------------------------------------------------
    [INFO] Building jslint4java docs
    [INFO] ------------------------------------------------------------------------
    [INFO] No goals needed for project - skipping
    [INFO] ------------------------------------------------------------------------
    [INFO] Building jslint4java distribution
    [INFO] ------------------------------------------------------------------------
    [INFO] No goals needed for project - skipping
    [WARNING] The dependency: com.googlecode.jslint4java:jslint4java-ant:jar:1.4-SNAPSHOT can't be resolved but has been found in the reactor.
    This dependency has been excluded from the plugin execution. You should rerun this mojo after executing mvn install.
    [INFO] [javadoc:aggregate {execution: aggregate-javadoc}]
    [WARNING] The dependency: [com.googlecode.jslint4java:jslint4java-ant:jar:1.4-SNAPSHOT] can't be resolved but has been found in the reactor (probably snapshots).
    This dependency has been excluded from the Javadoc classpath. You should rerun javadoc after executing mvn install.
    [WARNING] IGNORED to add some artifacts in the classpath. See above.
    [INFO] ------------------------------------------------------------------------
    [INFO] Building jslint4java
    [INFO]    task-segment: [clean, package]
    [INFO] ------------------------------------------------------------------------
    [INFO] [clean:clean]
    [INFO] Deleting file set: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java/target (included: [\*\*], excluded: [])
    [INFO] [resources:resources]
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] Copying 1 resource
    [INFO] [compiler:compile]
    [INFO] Compiling 6 source files to /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java/target/classes
    [INFO] [resources:testResources]
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] skip non existing resourceDirectory /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java/src/test/resources
    [INFO] [compiler:testCompile]
    [INFO] Compiling 5 source files to /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java/target/test-classes
    [INFO] [surefire:test]
    [INFO] Surefire report directory: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java/target/surefire-reports
    
    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running com.googlecode.jslint4java.OptionTest
    Tests run: 4, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.049 sec
    Running com.googlecode.jslint4java.IssueTest
    Tests run: 3, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.122 sec
    Running com.googlecode.jslint4java.JSLintTest
    Tests run: 15, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 5.119 sec
    Running com.googlecode.jslint4java.OptionParserTest
    Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.005 sec
    Running com.googlecode.jslint4java.UtilTest
    Tests run: 9, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.019 sec
    
    Results :
    
    Tests run: 33, Failures: 0, Errors: 0, Skipped: 0
    
    [INFO] [jar:jar]
    [INFO] Building jar: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java/target/jslint4java-1.4-SNAPSHOT.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] Building jslint4java ant task
    [INFO]    task-segment: [clean, package]
    [INFO] ------------------------------------------------------------------------
    [INFO] [clean:clean]
    [INFO] Deleting file set: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-ant/target (included: [\*\*], excluded: [])
    [INFO] [resources:resources]
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] Copying 1 resource
    [INFO] [compiler:compile]
    [INFO] Compiling 5 source files to /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-ant/target/classes
    [INFO] [resources:testResources]
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] Copying 6 resources
    [INFO] [compiler:testCompile]
    [INFO] Compiling 1 source file to /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-ant/target/test-classes
    [INFO] [surefire:test]
    [INFO] Surefire report directory: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-ant/target/surefire-reports
    
    -------------------------------------------------------
     T E S T S
    -------------------------------------------------------
    Running com.googlecode.jslint4java.ant.PlainResultFormatterTest
    Tests run: 2, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.09 sec
    
    Results :
    
    Tests run: 2, Failures: 0, Errors: 0, Skipped: 0
    
    [INFO] [antrun:run {execution: default}]
    [INFO] Executing tasks
    
    allTests:
    [au:antunit] Build File: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-ant/target/test-classes/antunit/tests.xml
    [au:antunit] Tests run: 7, Failures: 0, Errors: 0, Time elapsed: 3.573 sec
    [au:antunit] Target: testArbitraryResource took 0.836 sec
    [au:antunit] Target: testFailsOnError took 0.862 sec
    [au:antunit] Target: testNamesInOutputHavePath took 0.433 sec
    [au:antunit] Target: testNoResources took 0.331 sec
    [au:antunit] Target: testOptionParams took 0.378 sec
    [au:antunit] Target: testSuccess took 0.277 sec
    [au:antunit] Target: testIssue6 took 0.393 sec
    [INFO] Executed tasks
    [INFO] [jar:jar]
    [INFO] Building jar: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-ant/target/jslint4java-ant-1.4-SNAPSHOT.jar
    [INFO] [shade:shade {execution: make-shaded-jar}]
    [INFO] Including com.googlecode.jslint4java:jslint4java:jar:1.4-SNAPSHOT in the shaded jar.
    [INFO] Including rhino:js:jar:1.7R1 in the shaded jar.
    [INFO] Attaching shaded artifact.
    [INFO] ------------------------------------------------------------------------
    [INFO] Building jslint4java docs
    [INFO]    task-segment: [clean, package]
    [INFO] ------------------------------------------------------------------------
    [INFO] [clean:clean]
    [INFO] Deleting file set: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-docs/target (included: [\*\*], excluded: [])
    [INFO] [resources:resources {execution: filter-docs}]
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] Copying 6 resources
    [INFO] [site:attach-descriptor]
    [INFO] [assembly:single {execution: zip}]
    [INFO] Reading assembly descriptor: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-docs/src/main/assembly/zip.xml
    [INFO] Building zip: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-docs/target/jslint4java-docs-1.4-SNAPSHOT.zip
    [INFO] ------------------------------------------------------------------------
    [INFO] Building jslint4java distribution
    [INFO]    task-segment: [clean, package]
    [INFO] ------------------------------------------------------------------------
    [INFO] [clean:clean]
    [INFO] Deleting file set: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-dist/target (included: [\*\*], excluded: [])
    [INFO] [site:attach-descriptor]
    [INFO] [assembly:single {execution: dist}]
    [INFO] Reading assembly descriptor: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-dist/src/main/assembly/dist.xml
    [INFO] Building zip: /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-dist/target/jslint4java-1.4-SNAPSHOT-dist.zip
    [INFO] 
    [INFO] 
    [INFO] ------------------------------------------------------------------------
    [INFO] Reactor Summary:
    [INFO] ------------------------------------------------------------------------
    [INFO] jslint4java parent .................................... SUCCESS [10.958s]
    [INFO] jslint4java ........................................... SUCCESS [9.327s]
    [INFO] jslint4java ant task .................................. SUCCESS [6.435s]
    [INFO] jslint4java docs ...................................... SUCCESS [3.104s]
    [INFO] jslint4java distribution .............................. SUCCESS [1.791s]
    [INFO] ------------------------------------------------------------------------
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESSFUL
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 32 seconds
    [INFO] Finished at: Mon Aug 03 12:10:02 EDT 2009
    [INFO] Final Memory: 48M/81M
    [INFO] ------------------------------------------------------------------------
    
  3. Note the path to the jslint4java-ant/target/jslint4java-1.4-SNAPSHOT-shaded.jar file, this is the jar file you'll need to reference in the build.xml file.
    $ find `pwd` -name '\*.jar' -print
    /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java/target/jslint4java-1.4-SNAPSHOT.jar
    /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-ant/target/jslint4java-ant-1.4-SNAPSHOT-shaded.jar
    /Users/ashamash/projects/jslint4java/src/jslint4java/jslint4java-ant/target/jslint4java-ant-1.4-SNAPSHOT.jar
    

During this exercise, I was exposed to two new (for me) technologies, git and Maven (I'm personally an svn and ant type of person).  I especially liked the Maven integration in NetBeans.  Both experiences were quite good, but that's a story for another day.

Comments:

Great work, looking forward to a netbeans plugin maybe?

This would save a great deal of time for us with peer reviews.

Posted by Neil on August 01, 2009 at 09:33 AM EDT #

I've now released jslint4java 1.3.1, so hopefully most of the build step should no longer be necessary. Just download the zip file, extract and drop the jar in ~/.ant/lib.

http://code.google.com/p/jslint4java/downloads/detail?name=jslint4java-1.3.1-dist.zip

This includes a bundled copy of rhino, so no extras need be downloaded.

Many thanks for your help in preparing this, Ari!

Posted by Dominic Mitchell on August 03, 2009 at 10:44 AM EDT #

I've updated my blog w/regards to jslint4java 1.3.1 release, so it should be easier to install (no build needed, one jar file has everything, etc.) A NetBeans plugin would make it even easier, I'll work on it.

Posted by Ari Shamash on August 04, 2009 at 06:41 AM EDT #

As well as a plugin to do the install of the lib etc and build script stuff, a right click context menu on a js file so that you could check a single file without building the whole web app would be handy.

Posted by Neil Hathaway on August 04, 2009 at 07:48 AM EDT #

Post a Comment:
  • HTML Syntax: NOT allowed
About

Ari Shamash is the software engineering manager of the Sun Software Library engineering team at Sun Microsystems.

Search

Categories
Archives
« April 2014
SunMonTueWedThuFriSat
  
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
   
       
Today