coffeelint/src/coffeelint.coffee in coffeelint-0.0.5 vs coffeelint/src/coffeelint.coffee in coffeelint-0.0.6
- old
+ new
@@ -94,10 +94,14 @@
empty_constructor_needs_parens :
level : IGNORE
message : 'Invoking a constructor without parens and without arguments'
+ non_empty_constructor_needs_parens :
+ level : IGNORE
+ message : 'Invoking a constructor without parens and with arguments'
+
no_empty_param_list :
level : IGNORE
message : 'Empty parameter list is forbidden'
space_operators :
@@ -119,10 +123,14 @@
no_stand_alone_at :
level : IGNORE
message : '@ must not be used stand alone'
+ arrow_spacing :
+ level : IGNORE
+ message : 'Function arrow (->) must be spaced properly'
+
coffeescript_error :
level : ERROR
message : '' # The default coffeescript error is fine.
@@ -400,19 +408,23 @@
# Return an error if the given token fails a lint check, false
# otherwise.
lintToken : (token) ->
[type, value, lineNumber] = token
- lineNumber = lineNumber.first_line if lineNumber?.first_line?
+ if typeof lineNumber == "object"
+ if type == 'OUTDENT' or type == 'INDENT'
+ lineNumber = lineNumber.last_line
+ else
+ lineNumber = lineNumber.first_line
@tokensByLine[lineNumber] ?= []
@tokensByLine[lineNumber].push(token)
# CoffeeScript loses line numbers of interpolations and multi-line
# regexes, so fake it by using the last line number we know.
@lineNumber = lineNumber or @lineNumber or 0
-
# Now lint it.
switch type
+ when "->" then @lintArrowSpacing(token)
when "INDENT" then @lintIndentation(token)
when "CLASS" then @lintClass(token)
when "UNARY" then @lintUnary(token)
when "{","}" then @lintBrace(token)
when "IDENTIFIER" then @lintIdentifier(token)
@@ -428,18 +440,22 @@
when "=", "MATH", "COMPARE", "LOGIC"
@lintMath(token)
else null
lintUnary: (token) ->
- if token[1] is 'new'
- expectedIdentifier = @peek(1)
- # The callStart is generated if your parameters are on the next line
- # but is missing if there are no params and no parens.
- expectedCallStart = @peek(2)
- if expectedIdentifier?[0] is 'IDENTIFIER' and
- expectedCallStart?[0] isnt 'CALL_START'
- @createLexError('empty_constructor_needs_parens')
+ if token[1] is 'new'
+ expectedIdentifier = @peek(1)
+ # The callStart is generated if your parameters are all on the same
+ # line with implicit parens, and if your parameters start on the
+ # next line, but is missing if there are no params and no parens.
+ expectedCallStart = @peek(2)
+ if expectedIdentifier?[0] is 'IDENTIFIER' and expectedCallStart?
+ if expectedCallStart[0] is 'CALL_START'
+ if expectedCallStart.generated
+ @createLexError('non_empty_constructor_needs_parens')
+ else
+ @createLexError('empty_constructor_needs_parens')
# Lint the given array token.
lintArray : (token) ->
# Track the array token pairs
if token[0] == '['
@@ -671,10 +687,31 @@
attrs = {context: "class name: #{className}"}
@createLexError('camel_case_classes', attrs)
else
null
+ lintArrowSpacing : (token) ->
+ # Throw error unless the following happens.
+
+ # We will take a look at the previous token to see
+ # 1. That the token is properly spaced
+ # 2. Wasn't generated by the CoffeeScript compiler
+ # 3. That it is just indentation
+ # 4. If the function declaration has no parameters
+ # e.g. x(-> 3)
+ # x( -> 3)
+ # we will accept either having a space or not having a space there.
+ unless (token.spaced? or token.newLine?) and
+ # Throw error unless the previous token...
+ (@peek(-1).spaced? or #1
+ @peek(-1).generated? or #2
+ @peek(-1)[0] is "INDENT" or #3
+ (@peek(-1)[0] is "CALL_START" and not @peek(-1).generated?)) #4
+ @createLexError('arrow_spacing')
+ else
+ null
+
createLexError : (rule, attrs = {}) ->
attrs.lineNumber = @lineNumber + 1
attrs.level = @config[rule].level
attrs.line = @lines[@lineNumber]
createError(rule, attrs)
@@ -766,11 +803,14 @@
message = coffeeError.toString()
# Parse the line number
lineNumber = -1
- match = /line (\d+)/.exec message
- lineNumber = parseInt match[1], 10 if match?.length > 1
+ if coffeeError.location?
+ lineNumber = coffeeError.location.first_line + 1
+ else
+ match = /line (\d+)/.exec message
+ lineNumber = parseInt match[1], 10 if match?.length > 1
attrs = {
message: message
level: rule.level
lineNumber: lineNumber
}