Merge pull request #4313 from eelco/no-whitespace-mixing-strict

Don’t allow mixing spaces and tabs for indentation
This commit is contained in:
Jeremy Ashkenas
2016-09-27 10:24:20 -04:00
committed by GitHub
5 changed files with 61 additions and 26 deletions

View File

@@ -40,6 +40,7 @@ exports.Lexer = class Lexer
@indebt = 0 # The over-indentation at the current level.
@outdebt = 0 # The under-outdentation at the current level.
@indents = [] # The stack of all current indentation levels.
@indentLiteral = '' # The indentation
@ends = [] # The stack for pairing up tokens.
@tokens = [] # Stream of parsed tokens in the form `['TYPE', value, location data]`.
@seenFor = no # Used to recognize FORIN and FOROF tokens.
@@ -351,6 +352,16 @@ exports.Lexer = class Lexer
size = indent.length - 1 - indent.lastIndexOf '\n'
noNewlines = @unfinished()
newIndentLiteral = if size > 0 then indent[-size..] else ''
unless /^(.?)\1*$/.exec newIndentLiteral
@error 'mixed indentation', offset: indent.length
return indent.length
minLiteralLength = Math.min newIndentLiteral.length, @indentLiteral.length
if newIndentLiteral[...minLiteralLength] isnt @indentLiteral[...minLiteralLength]
@error 'indentation mismatch', offset: indent.length
return indent.length
if size - @indebt is @indent
if noNewlines then @suppressNewlines() else @newlineToken 0
return indent.length
@@ -362,6 +373,7 @@ exports.Lexer = class Lexer
return indent.length
unless @tokens.length
@baseIndent = @indent = size
@indentLiteral = newIndentLiteral
return indent.length
diff = size - @indent + @outdebt
@token 'INDENT', diff, indent.length - size, size
@@ -369,6 +381,7 @@ exports.Lexer = class Lexer
@ends.push {tag: 'OUTDENT'}
@outdebt = @indebt = 0
@indent = size
@indentLiteral = newIndentLiteral
else if size < @baseIndent
@error 'missing indentation', offset: indent.length
else
@@ -405,6 +418,7 @@ exports.Lexer = class Lexer
@token 'TERMINATOR', '\n', outdentLength, 0 unless @tag() is 'TERMINATOR' or noNewlines
@indent = decreasedIndent
@indentLiteral = @indentLiteral[...decreasedIndent]
this
# Matches and consumes non-meaningful whitespace. Tag the previous token

View File

@@ -76,7 +76,7 @@ test "#2516: Unicode spaces should not be part of identifiers", ->
eq 5, {c: 5}[ 'c' ]
# A line where every space in non-breaking
  eq 1 + 1, 2  
eq 1 + 1, 2  
test "don't accidentally stringify keywords", ->
ok (-> this == 'this')() is false

View File

@@ -41,18 +41,6 @@ test "compiler error formatting", ->
^^^^
'''
test "compiler error formatting with mixed tab and space", ->
assertErrorFormat """
\t if a
\t test
""",
'''
[stdin]:1:4: error: unexpected if
\t if a
\t ^^
'''
if require?
fs = require 'fs'
path = require 'path'

View File

@@ -254,3 +254,36 @@ test "#1275: allow indentation before closing brackets", ->
a = 1
)
eq 1, a
test "dont allow mixing of spaces and tabs for indentation", ->
try
CoffeeScript.compile '''
new Layer
x: 0
y: 1
'''
ok no
catch e
eq 'indentation mismatch', e.message
test "each code block that starts at indentation 0 can use a different style", ->
doesNotThrow ->
CoffeeScript.compile '''
new Layer
x: 0
y: 1
new Layer
x: 0
y: 1
'''
test "tabs and spaces cannot be mixed for indentation", ->
try
CoffeeScript.compile '''
new Layer
x: 0
y: 1
'''
ok no
catch e
eq 'mixed indentation', e.message

View File

@@ -59,21 +59,21 @@ test "#1183: super + fat arrows", ->
dolater = (cb) -> cb()
class A
constructor: ->
@_i = 0
foo : (cb) ->
dolater =>
@_i += 1
cb()
constructor: ->
@_i = 0
foo : (cb) ->
dolater =>
@_i += 1
cb()
class B extends A
constructor : ->
super
foo : (cb) ->
dolater =>
dolater =>
@_i += 2
super cb
constructor : ->
super
foo : (cb) ->
dolater =>
dolater =>
@_i += 2
super cb
b = new B
b.foo => eq b._i, 3