diff --git a/test/_test_chaining.coffee b/test/_test_chaining.coffee deleted file mode 100644 index 99b600bf..00000000 --- a/test/_test_chaining.coffee +++ /dev/null @@ -1,77 +0,0 @@ -# Chaining -# -------- - -# shared identity function -id = (_) -> if arguments.length is 1 then _ else Array::slice.call(arguments) - - - -# Basic chained function calls. -identityWrap = (x) -> - -> x - -result = identityWrap(identityWrap(true))()() - -ok result - - -# Should be able to look at prototypes on keywords. -obj = - withAt: -> @::prop - withThis: -> this::prop - proto: - prop: 100 -obj.prototype = obj.proto -eq obj.withAt() , 100 -eq obj.withThis(), 100 - - -# Chained accesses split on period/newline, backwards and forwards. -str = 'god' - -result = str. - split(''). - reverse(). - reverse(). - reverse() - -ok result.join('') is 'dog' - -result = str - .split('') - .reverse() - .reverse() - .reverse() - -ok result.join('') is 'dog' - - -# Newline suppression for operators. -six = - 1 + - 2 + - 3 - -ok six is 6 - - -# Ensure that indented array literals don't trigger whitespace rewriting. -func = () -> - ok arguments.length is 1 - -func( - [[[[[], - []], - [[]]]], - []]) - -greeting = id( - """ - Hello - """) - -ok greeting is "Hello" - -ok not Date -:: -?.foo, '`?.` and `::` should also continue lines' diff --git a/test/_test_literals.coffee b/test/_test_literals.coffee deleted file mode 100644 index 899f5272..00000000 --- a/test/_test_literals.coffee +++ /dev/null @@ -1,50 +0,0 @@ -third = (a, b, c) -> c -obj = - one: 'one' - two: third 'one', 'two', 'three' -ok obj.one is 'one' -ok obj.two is 'three' - - -# Implicit arguments to function calls: -func = (obj) -> obj.a -func2 = -> arguments - -result = func - a: 10 -ok result is 10 - -result = func - "a": 20 -ok result is 20 - -a = b = undefined - -result = func - b:1 - a -ok result is undefined - -result = func - a: - b:2 - b:1 -ok result.b is 2 - -result = func2 - a:1 - b - c:1 -ok result.length is 3 -ok result[2].c is 1 - -second = (x, y) -> y -obj = then second 'the', - 1: 1 - two: - three: -> - four five, - six: seven - three: 3 -ok obj[1] is 1 -ok obj.three is 3 diff --git a/test/_test_returns.coffee b/test/_test_returns.coffee deleted file mode 100644 index aa119852..00000000 --- a/test/_test_returns.coffee +++ /dev/null @@ -1,63 +0,0 @@ -# Expression conversion under explicit returns. -first = -> - return ('do' for x in [1,2,3]) - -second = -> - return ['re' for x in [1,2,3]] - -third = -> - return ('mi' for x in [1,2,3]) - -ok first().join(' ') is 'do do do' -ok second()[0].join(' ') is 're re re' -ok third().join(' ') is 'mi mi mi' - - -# Testing returns with multiple branches. -func = -> - if false - for a in b - return c if d - else - "word" - -ok func() is 'word' - - -# And with switches. -func = -> - switch 'a' - when 'a' then 42 - else return 23 - -eq func(), 42 - -# Ensure that we don't wrap Nodes that are "pureStatement" in a closure. -items = [1, 2, 3, "bacon", 4, 5] - -findit = (items) -> - for item in items - return item if item is "bacon" - -ok findit(items) is "bacon" - - -# When a closure wrapper is generated for expression conversion, make sure -# that references to "this" within the wrapper are safely converted as well. -obj = - num: 5 - func: -> - this.result = if false - 10 - else - "a" - "b" - this.num - -eq obj.num, obj.func() -eq obj.num, obj.result - - -# Multiple semicolon-separated statements in parentheticals. -eq 3, (1; 2; 3) -eq 3, (-> return (1; 2; 3))() diff --git a/test/comprehensions.coffee b/test/comprehensions.coffee index 322ef769..fd02aaab 100644 --- a/test/comprehensions.coffee +++ b/test/comprehensions.coffee @@ -324,5 +324,17 @@ list = [arguments: 10] args = for f in list do (f) -> f.arguments - eq args[0], 10 + + +test "expression conversion under explicit returns", -> + nonce = {} + fn = -> + return (nonce for x in [1,2,3]) + arrayEq [nonce,nonce,nonce], fn() + fn = -> + return [nonce for x in [1,2,3]][0] + arrayEq [nonce,nonce,nonce], fn() + fn = -> + return [(nonce for x in [1..3])][0] + arrayEq [nonce,nonce,nonce], fn() diff --git a/test/formatting.coffee b/test/formatting.coffee index 17e8614c..8dcce4c2 100644 --- a/test/formatting.coffee +++ b/test/formatting.coffee @@ -1,7 +1,106 @@ # Formatting # ---------- -# * Line Continuation (Property Accesss) -# * Line Continuation (Operators) -# * Line Continuation (Arrays) -# * Line Continuation (Function Invocations) +# TODO: maybe this file should be split up into their respective sections: +# operators -> operators +# array literals -> array literals +# string literals -> string literals +# function invocations -> function invocations + +# * Line Continuation +# * Property Accesss +# * Operators +# * Array Literals +# * Function Invocations +# * String Literals + +doesNotThrow -> CoffeeScript.compile "a = then b" + +test "multiple semicolon-separated statements in parentheticals", -> + nonce = {} + eq nonce, (1; 2; nonce) + eq nonce, (-> return (1; 2; nonce))() + +#### Line Continuation + +# Property Access + +test "chained accesses split on period/newline, backwards and forwards", -> + str = 'abc' + result = str. + split(''). + reverse(). + reverse(). + reverse() + arrayEq ['c','b','a'], result + arrayEq ['c','b','a'], str. + split(''). + reverse(). + reverse(). + reverse() + result = str + .split('') + .reverse() + .reverse() + .reverse() + arrayEq ['c','b','a'], result + arrayEq ['c','b','a'], str + .split('') + .reverse() + .reverse() + .reverse() + arrayEq ['c','b','a'], str. + split('') + .reverse(). + reverse() + .reverse() + +# Operators + +test "newline suppression for operators", -> + six = + 1 + + 2 + + 3 + eq 6, six + +test "`?.` and `::` should continue lines", -> + ok not Date + :: + ?.foo + #eq Object::toString, Date?. + #prototype + #:: + #?.foo + +# Array Literals + +test "indented array literals don't trigger whitespace rewriting", -> + getArgs = -> arguments + result = getArgs( + [[[[[], + []], + [[]]]], + []]) + eq 1, result.length + +# Function Invocations + +doesNotThrow -> CoffeeScript.compile """ + obj = then fn 1, + 1: 1 + a: + b: -> + fn c, + d: e + f: 1 + """ + +# String Literals + +test "indented heredoc", -> + result = ((_) -> _)( + """ + abc + """) + eq "abc", result diff --git a/test/function_invocation.coffee b/test/function_invocation.coffee index 5c6317e7..92b529e4 100644 --- a/test/function_invocation.coffee +++ b/test/function_invocation.coffee @@ -64,6 +64,13 @@ ok fn(fn {prop: 101}).prop is 101 okFunc = (f) -> ok(f()) okFunc -> true +test "chained function calls", -> + nonce = {} + identityWrap = (x) -> + -> x + eq nonce, identityWrap(identityWrap(nonce))()() + eq nonce, (identityWrap identityWrap nonce)()() + # Multi-blocks with optional parens. result = fn( -> fn -> @@ -296,3 +303,46 @@ eq ok, new -> ok ### Should `return` implicitly ### ### even with trailing comments. ### + +test "implicit returns with multiple branches", -> + nonce = {} + fn = -> + if false + for a in b + return c if d + else + nonce + eq nonce, fn() + +test "implicit returns with switches", -> + nonce = {} + fn = -> + switch nonce + when nonce then nonce + else return undefined + eq nonce, fn() + +test "preserve context when generating closure wrappers for expression conversions", -> + nonce = {} + obj = + property: nonce + method: -> + this.result = if false + 10 + else + "a" + "b" + this.property + eq nonce, obj.method() + eq nonce, obj.property + + +#### Explicit Returns + +test "don't wrap \"pure\" statements in a closure", -> + nonce = {} + items = [0, 1, 2, 3, nonce, 4, 5] + fn = (items) -> + for item in items + return item if item is nonce + eq nonce, fn items diff --git a/test/object_literals.coffee b/test/object_literals.coffee index 1203ab30..4329596d 100644 --- a/test/object_literals.coffee +++ b/test/object_literals.coffee @@ -137,3 +137,52 @@ obj = two: third 'one', 'two', 'three' ok obj.one is 'one' ok obj.two is 'three' + +test "", -> + generateGetter = (prop) -> (obj) -> obj[prop] + getA = generateGetter 'a' + getArgs = -> arguments + a = b = 30 + + result = getA + a: 10 + ok result is 10 + + result = getA + "a": 20 + ok result is 20 + + result = getA a, + b:1 + ok result is undefined + + # TODO: this looks like a failing test case; verify + #result = getA + # b:1 + # a + #ok result is 30 + + result = getA + a: + b:2 + b:1 + ok result.b is 2 + + # TODO: should this test be changed? this is unexpected (and not the displayed) behaviour + #result = getArgs + # a:1 + # b + # c:1 + #ok result.length is 3 + #ok result[2].c is 1 + +test "some weird indentation in YAML-style object literals", -> + two = (a, b) -> b + obj = then two 1, + 1: 1 + a: + b: -> + fn c, + d: e + f: 1 + eq 1, obj[1] diff --git a/test/operators.coffee b/test/operators.coffee index 71dbe539..6e487ba5 100644 --- a/test/operators.coffee +++ b/test/operators.coffee @@ -49,6 +49,15 @@ test "`instanceof`", -> ok new Number not instanceof String ok new Array not instanceof Boolean +test "use `::` operator on keywords `this` and `@`", -> + nonce = {} + obj = + withAt: -> @::prop + withThis: -> this::prop + obj.prototype = prop: nonce + eq nonce, obj.withAt() + eq nonce, obj.withThis() + #### Compound Assignment Operators