CoffeeLint

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.

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:

New in 1.0: CoffeeLint will automatically pick up config files. When
linting a file (as opposed to stdin) it will walk up the directory
tree looking for a coffeelint.json or a package.json that has a
"coffeelintConfig" object. If neither of those are found or you're
linting from stdin it will check your home for a coffeelint.json
file.

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, generate a
configuration file and tweak it 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.

This rule mandates that all class names are UpperCamelCased.
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.

default level: error

coffeescript_error

[no description provided]

default level: error

colon_assignment_spacing

This rule checks to see that there is spacing before and
after the colon in a colon assignment (i.e., classes, objects).
The spacing amount is specified by
spacing.left and spacing.right, respectively.
A zero value means no spacing required.

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.

This rule ensures your project uses only windows or
unix line endings. This rule is disabled by default.

default level: ignore

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.

default level: error

missing_fat_arrows

Warns when you use `this` inside a function that wasn't defined
with a fat arrow. This rule does not apply to methods defined in a
class, since they have `this` bound to the class instance (or the
class itself, for class methods). The option `is_strict` is
available for checking bindings of class methods.
It is impossible to statically determine whether a function using
`this` will be bound with the correct `this` value due to language
features like `Function.prototype.call` and
`Function.prototype.bind`, so this rule may produce false positives.

default level: ignore

newlines_after_classes

Checks the number of newlines between classes and other code.

Options:
-

value

- The number of required newlines
after class definitions. Defaults to 3.

default level: ignore

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.

default level: error

no_debugger

This rule detects `debugger` and optionally `console` calls
This rule is `warn` by default.

default level: warn

no_empty_functions

Disallows declaring empty functions. The goal of this rule is that
unintentional empty callbacks can be detected:

someFunctionWithCallback ->
doSomethingSignificant()

The problem is that the call to
doSomethingSignificant will be made regardless
of someFunctionWithCallback's execution. It can
be because you did not indent the call to
doSomethingSignificant properly.
If you really meant that someFunctionWithCallback
should call a callback that does nothing, you can write your code
this way:

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.

default level: ignore

no_implicit_parens

This rule prohibits implicit parens on function calls.

# Some folks don't like this style of coding.
myFunction a, b, c
# And would rather it always be written like this:
myFunction(a, b, c)

Implicit parens are permitted by default, since their use is
idiomatic CoffeeScript.

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.

default level: ignore

no_private_function_fat_arrows

Warns when you use the fat arrow for a private function
inside a class definition scope. It is not necessary and
it does not do anything.

default level: warn

no_stand_alone_at

This rule checks that no stand alone @ are in use, they are
discouraged. Further information in CoffeeScript issue
#1601

default level: ignore

no_tabs

This rule forbids tabs in indentation. Enough said. It is enabled by
default.

default level: error

no_this

This rule prohibits 'this'.
Use '@' instead.

default level: ignore

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.

Disallows defining functions with fat arrows when `this`
is not used within the function.

default level: warn

non_empty_constructor_needs_parens

Requires constructors with parameters to include the parens

default level: ignore

prefer_english_operator

This rule prohibits &&, ||, ==, != and !.
Use and, or, is, isnt, and not instead.
!! for converting to a boolean is ignored.

default level: ignore

space_operators

This rule enforces that operators have spaces around them.

default level: ignore

spacing_after_comma

This rule checks to make sure you have a space after commas.

default level: ignore

transform_messes_up_line_numbers

This rule detects when changes are made by transform function,
and warns that line numbers are probably incorrect.

default level: warn

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'
}

coffeelint.registerRule(RuleConstructor)

Registers a custom rule that may be run by CoffeeLint. If the rule
is ignored by default it will still require overriding it's level
just like the default rules. They have actually all be
re-implemented as pluggable rules that come bundled in CoffeeLint.

Loading Custom Rules

Not every possible rule will be included in the CoffeeLint project.
Maybe it's very specific to your project, or it's not specific to
CoffeeScript.

By convention rule authors add the keyword coffeelintrule to their npm package.json so custom rules can be found easily. Click here to list all currently available custom rules on npm.

For example, maybe you want to get a warning if you don't have a
newline at the end of your files. We'll imagine you globally
installed the package "coffeelint-newline-eof".

{
// This name MUST match the default configuration of the rule being loaded.
"newline_at_eof": {
// NodeJS module to load. It can also be a path to the rule (useful for devleopment)
"module": "coffeelint-newline-at-eof",
// Maybe the rule author set it to error by default and you only want a warning.
"level": "warn"
}
}

Now every time you run CoffeeLint it will load that rule and
override it's default level to "warn".

Building Custom Rules

CoffeeLint has three types of linters that run. In no particular order they are.

LineLinter: processes one line at a time, usually with regular expressions

TokenLinter: processes the token stream generated by CoffeeScript.

ASTLinter: Processes the Abstract Syntax Tree. AST rules are
only called with the root node and it is up to the rule to
recurse the tree.

Rules may be loaded using

--rules /path/to/rules/

or

coffeelint.registerRule(RuleConstructor)

when
outside of the CLI.

Rules do not have to be written in CoffeeScript. A new instance of
each rule is constructed for each file, so the RuleConstructor must
be a constructor function that generates a new clean instance of
your rule when the new operator is used.

Your rule instance must have a .rule attribute with it's default
configuration. "name", "level" "message", and "description" are
all required. "level" must be one of 'ignore', 'warn', or
'error'. Once you have a valid rule configuration CoffeeLint
requires you to implement one function depending on which type of
linter your rule needs.
lintLine(line, lineApi)
lintToken(token, tokenApi)
lintAST(ast, astApi)
The second parameter of each is an object with helper functions.
It's best to just check the source or look at how other plugins
are using those.

If your function returns true it will generate an error. If you
need override how the error is generated, maybe providing a
context attribute, you can return an object that will get mixed
into the generated error. The NoPlusPlus is a simple example of
this.

The core rules have been rewritten as stand alone rules both to
prove the system and provide examples of how to write rules.
To get started no_plus_plus is a Token rule, no_tabs is a Line rule,
and cyclomatic_complexity is an AST rule.

The

--rules

option will load every .js or .coffee file
it finds and assume they export the RuleConstructor. Since the
browser doesn't have a standard export system it's up to you to
determine how you'll load your plugin and register it with

coffeelint.registerRule

Plugins

Some nice folks have coded up some cool CoffeeLint plugins for editors and
build systems. Check them out:

Change Log

1.14.1-1.15.0

This version updates the enable/disable directives. In addition to
the existing # coffeelint: disable=rule_name you can also
use # coffeelint disable-line=rule_name. The rule name is
still optional in both cases, and you can enable the rules using
the same syntax.

1.14.0-1.14.1

Most of the changes are more for linting the development files of
coffeelint. The minor version increase is due to the change in
cyclomatic_complexity, which now ignores nested functions. I foresee
this change affecting very few people but probably still needs a minor
version increase.

cyclomatic_complexity rule has been changed to ignore nested functions

1.11.0-1.13.0

The v1.12.x versions are considered buggy and you should upgrade to v1.13.x if you experience problems

These releases were largely for bugfixes!

Bugfix for no_implicit_braces causing errors in classes and other edge cases

Bugfix for ensure_comprehensions where it failed if a nested loop had an equal sign

Bugfix for braces_spacing failing over generated curly braces

Several changes to indentation See bffa25
for the full list of changes. However between the release of v1.12.0 and v1.13.0, a regression was caused by fixing one of the indentation requests and
as a result the change was reverted. The revert will most likely not affect too many users

Bugfix for newlines_after_classes, also fixed regressions caused between v1.12.0 and v1.13.0. If you have v1.12.x and are experiencing problems, please upgrade.
Also note nested classes are now ignored completely

no_this is now compatible with no_stand_alone_at and will make checks against singular `this`

Bugfix for missing_fat_arrows, declaring a class prototype (via '::' operator) no longer fail if they don't use a fat arrow

Bugfix for eol_last, it now fails if there are multiple newlines at the end of a file (thanks charlierudolph)