CoffeeLint

Run

Overview

CoffeeLint is a style checker that helps keep CoffeeScript code clean and consistent. CoffeeScript does a great job at insulating programmers from many of JavaScript's bad parts, but it won't help enforce a consistent style across a code base. CoffeeLint can help with that.

CoffeeLint is in its infancy, so feedback is much appreciated. If you have an idea, a bug report or anything else to say, reach out on the issues page.

Installation

To install, make sure you have a working version of the latest stable version of Node and NPM (the Node Package Manager) and then run:

npm install -g coffeelint

Leave off the g if you do not want to install globally.

Usage

Once you have Coffeelint installed, to lint your scripts, run:

coffeelint application.coffee

To specify your own configuration file, do the following:

coffeelint -f config.json application.coffee

If any errors were found, a non-zero code will be returned.

Options

By default, CoffeeLint will help ensure you are writing idiomatic CoffeeScript, but every rule is optional and configurable so it can be tuned to fit your preferred coding style. To override any of CoffeeLint's default options, start with this example configuration file and tweak as needed. To enable an option, set its level to error and to disable an option, set its level to ignore. If you set the level to warn, violations will be reported, but won't cause a non-zero exit code.

Here's a rundown of CoffeeLint's rules:

Name Description
indentation This rule imposes a standard number of spaces to be used for indentation. Since whitespace is significant in CoffeeScript, it's critical that a project chooses a standard indentation format and stays consistent. Other roads lead to darkness.
# Enabling this option will prevent this ugly
# but otherwise valid CoffeeScript.
twoSpaces = () ->
  fourSpaces = () ->
      eightSpaces = () ->
            'this is valid CoffeeScript'


Two space indentation is enabled by default.
max_line_length This rule imposes a maximum line length on your code. Python's style guide does a good job explaining why you might want to limit the length of your lines, though this is a matter of taste. Lines can be no longer than eighty characters by default.
camel_case_classes This rule mandates that all class names are camel cased. Camel casing class names is a generally accepted way of distinguishing constructor functions - which require the 'new' prefix to behave properly - from plain old functions.
# Good!
class BoaConstrictor

# Bad!
class boaConstrictor

This rule is enabled by default.
no_trailing_semicolons This rule prohibits trailing semicolons, since they are needless cruft in CoffeeScript.
# This semicolon is meaningful.
x = '1234'; console.log(x)

# This semicolon is redundant.
alert('end of line');

Trailing semicolons are forbidden by default.
no_implicit_braces This rule prohibits implicit braces when declaring object literals. Implicit braces can make code more difficult to understand, especially when used in combination with optional parenthesis.
# Do you find this code ambiguous? Is it a
# function call with three arguments or four?
myFunction a, b, 1:2, 3:4

# While the same code written in a more
# explicit manner has no ambiguity.
myFunction(a, b, {1:2, 3:4})

Implicit braces are permitted by default, since their use is idiomatic CoffeeScript.
no_tabs This rule forbids tabs in indentation. Enough said. It is enabled by default.
no_trailing_whitespace This rule forbids trailing whitespace in your code, since it is needless cruft. It is enabled by default.
no_plusplus This rule forbids the increment and decrement arithmetic operators. Some people believe the ++ and -- to be cryptic and the cause of bugs due to misunderstandings of their precedence rules. This rule is disabled by default.
no_throwing_strings This rule forbids throwing string literals or interpolations. While JavaScript (and CoffeeScript by extension) allow any expression to be thrown, it is best to only throw Error objects, because they contain valuable debugging information like the stack trace. Because of JavaScript's dynamic nature, CoffeeLint cannot ensure you are always throwing instances of Error. It will only catch the simple but real case of throwing literal strings.
# CoffeeLint will catch this:
throw "i made a boo boo"

# ... but not this:
throw getSomeString()

This rule is enabled by default.
no_backticks Backticks allow snippets of JavaScript to be embedded in CoffeeScript. While some folks consider backticks useful in a few niche circumstances, they should be avoided because so none of JavaScript's "bad parts", like with and eval, sneak into CoffeeScript. This rule is enabled by default.
line_endings This rule ensures your project uses only windows or unix line endings. This rule is disabled by default.

API

If you'd like to run CoffeeScript in the browser or any other Javascript runtime, include coffee-script.js and coffeelint.js and you're off to the races. Then you can call CoffeeLint directly with the following API:

coffeelint.lint(source, configuration)

Lints the CoffeeScript source with the given configuration and returns an array of lint errors and warnings. If the array is empty, all is well. Compile time errors will be thrown. An error is a Javascript object with the following properties:

{
    rule :      'Name of the violated rule',
    lineNumber: 'Number of the line that caused the violation',
    level:      'The severity level of the violated rule',
    message:    'Information about the violated rule',
    context:    'Optional details about why the rule was violated'
}

Plugins

Some nice folks have coded up some cool text editor plugins that include CoffeeLint. Check them out:

About

CoffeeLint is open sourced under the MIT License. If you want to hack on the code, report a bug or suggest a new feature, head on over here.

Thanks to CoffeeScript's developers for a great language (and a re-usable Lexer). Thanks to the creators of JSLint, JSHint, Pylint, lint and my mother for inspiration.

Change Log

0.4.0

- 2012.04.06

0.3.0

- 2012.03.13

0.2.0

- 2012.01.26

0.1.0

- 2012.01.22
Fork me on GitHub