From 2432947bd3c2982a21693eb7b8b855c42c620ba1 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Sat, 29 Apr 2017 19:46:51 -0700 Subject: [PATCH 1/5] Start with the test I want to pass: return an implicit (braces-less) object --- src/grammar.coffee | 1 - src/lexer.coffee | 2 +- test/objects.coffee | 12 ++++++++++++ 3 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/grammar.coffee b/src/grammar.coffee index 7f41808c39..3b5601de61 100644 --- a/src/grammar.coffee +++ b/src/grammar.coffee @@ -229,7 +229,6 @@ grammar = o 'AWAIT RETURN', -> new AwaitReturn ] - # A block comment. Comment: [ o 'HERECOMMENT', -> new Comment $1 diff --git a/src/lexer.coffee b/src/lexer.coffee index 51618e63bb..f4432599b5 100644 --- a/src/lexer.coffee +++ b/src/lexer.coffee @@ -455,7 +455,7 @@ exports.Lexer = class Lexer this # Matches and consumes non-meaningful whitespace. Tag the previous token - # as being "spaced", because there are some cases where it makes a difference. + # as being “spaced”, because there are some cases where it makes a difference. whitespaceToken: -> return 0 unless (match = WHITESPACE.exec @chunk) or (nline = @chunk.charAt(0) is '\n') diff --git a/test/objects.coffee b/test/objects.coffee index 21e431ad64..ab4733ee60 100644 --- a/test/objects.coffee +++ b/test/objects.coffee @@ -575,3 +575,15 @@ test "#4324: Shorthand after interpolated key", -> obj = {"#{1}": 1, a} eq 1, obj[1] eq 2, obj.a + +test "#1263: Braceless object return", -> + fn = -> + return + a: 1 + b: 2 + c: 3 + + obj = fn() + eq 1, obj.a + eq 2, obj.b + eq 3, obj.c From d7d48fbe99b2a4fe39c3ef0922fe524cd5a634d0 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Sun, 30 Apr 2017 12:00:44 -0700 Subject: [PATCH 2/5] =?UTF-8?q?Update=20Rewriter=20class=20to=20follow=20p?= =?UTF-8?q?attern=20of=20nodes.coffee;=20move=20debugging=20snippet=20to?= =?UTF-8?q?=20where=20it=E2=80=99ll=20work=20in=20CS2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- lib/coffeescript/rewriter.js | 4 ++-- src/rewriter.coffee | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/lib/coffeescript/rewriter.js b/lib/coffeescript/rewriter.js index ebae87c587..7e29b4febd 100644 --- a/lib/coffeescript/rewriter.js +++ b/lib/coffeescript/rewriter.js @@ -1,6 +1,6 @@ // Generated by CoffeeScript 2.0.0-beta1 (function() { - var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, rite, + var BALANCED_PAIRS, CALL_CLOSERS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, Rewriter, SINGLE_CLOSERS, SINGLE_LINERS, generate, k, left, len, rite, indexOf = [].indexOf; generate = function(tag, value, origin) { @@ -13,7 +13,7 @@ return tok; }; - exports.Rewriter = (function() { + exports.Rewriter = Rewriter = (function() { class Rewriter { rewrite(tokens1) { this.tokens = tokens1; diff --git a/src/rewriter.coffee b/src/rewriter.coffee index f349233518..453170c672 100644 --- a/src/rewriter.coffee +++ b/src/rewriter.coffee @@ -14,11 +14,7 @@ generate = (tag, value, origin) -> # The **Rewriter** class is used by the [Lexer](lexer.html), directly against # its internal array of tokens. -class exports.Rewriter - - # Helpful snippet for debugging: - # - # console.log (t[0] + '/' + t[1] for t in @tokens).join ' ' +exports.Rewriter = class Rewriter # Rewrite the token stream in multiple passes, one logical filter at # a time. This could certainly be changed into a single pass through the @@ -26,6 +22,8 @@ class exports.Rewriter # like this. The order of these passes matters -- indentation must be # corrected before implicit parentheses can be wrapped around blocks of code. rewrite: (@tokens) -> + # Helpful snippet for debugging: + # console.log (t[0] + '/' + t[1] for t in @tokens).join ' ' @removeLeadingNewlines() @closeOpenCalls() @closeOpenIndexes() @@ -186,7 +184,7 @@ class exports.Rewriter # Don't end an implicit call on next indent if any of these are in an argument if inImplicitCall() and tag in ['IF', 'TRY', 'FINALLY', 'CATCH', 'CLASS', 'SWITCH'] - stack.push ['CONTROL', i, ours: true] + stack.push ['CONTROL', i, ours: yes] return forward(1) if tag is 'INDENT' and inImplicit() From c287a5591560875a6d15c3a9351266576cb17244 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Sun, 30 Apr 2017 14:49:19 -0700 Subject: [PATCH 3/5] Allow export default implicit object --- lib/coffeescript/lexer.js | 2 +- src/lexer.coffee | 2 +- test/modules.coffee | 22 ++++++++++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/lib/coffeescript/lexer.js b/lib/coffeescript/lexer.js index 459b3db81c..01dcd28753 100644 --- a/lib/coffeescript/lexer.js +++ b/lib/coffeescript/lexer.js @@ -890,7 +890,7 @@ unfinished() { var ref; - return LINE_CONTINUER.test(this.chunk) || ((ref = this.tag()) === '\\' || ref === '.' || ref === '?.' || ref === '?::' || ref === 'UNARY' || ref === 'MATH' || ref === 'UNARY_MATH' || ref === '+' || ref === '-' || ref === '**' || ref === 'SHIFT' || ref === 'RELATION' || ref === 'COMPARE' || ref === '&' || ref === '^' || ref === '|' || ref === '&&' || ref === '||' || ref === 'BIN?' || ref === 'THROW' || ref === 'EXTENDS'); + return LINE_CONTINUER.test(this.chunk) || ((ref = this.tag()) === '\\' || ref === '.' || ref === '?.' || ref === '?::' || ref === 'UNARY' || ref === 'MATH' || ref === 'UNARY_MATH' || ref === '+' || ref === '-' || ref === '**' || ref === 'SHIFT' || ref === 'RELATION' || ref === 'COMPARE' || ref === '&' || ref === '^' || ref === '|' || ref === '&&' || ref === '||' || ref === 'BIN?' || ref === 'THROW' || ref === 'EXTENDS' || ref === 'DEFAULT'); } formatString(str, options) { diff --git a/src/lexer.coffee b/src/lexer.coffee index f4432599b5..33247b2aeb 100644 --- a/src/lexer.coffee +++ b/src/lexer.coffee @@ -790,7 +790,7 @@ exports.Lexer = class Lexer LINE_CONTINUER.test(@chunk) or @tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', 'UNARY_MATH', '+', '-', '**', 'SHIFT', 'RELATION', 'COMPARE', '&', '^', '|', '&&', '||', - 'BIN?', 'THROW', 'EXTENDS'] + 'BIN?', 'THROW', 'EXTENDS', 'DEFAULT'] formatString: (str, options) -> @replaceUnicodeCodePointEscapes str.replace(STRING_OMIT, '$1'), options diff --git a/test/modules.coffee b/test/modules.coffee index c26dabfb3e..33a9c30ac4 100644 --- a/test/modules.coffee +++ b/test/modules.coffee @@ -353,6 +353,28 @@ test "export default object", -> };""" eq toJS(input), output +test "export default implicit object", -> + input = "export default foo: 'bar', baz: 'qux'" + output = """ + export default { + foo: 'bar', + baz: 'qux' + };""" + eq toJS(input), output + +test "export default multiline implicit object", -> + input = """ + export default + foo: 'bar', + baz: 'qux' + """ + output = """ + export default { + foo: 'bar', + baz: 'qux' + };""" + eq toJS(input), output + test "export default assignment expression", -> input = "export default foo = 'bar'" output = """ From 75f6912529f3f8f546dbdb9e5210bfa22fd61cd0 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Sun, 30 Apr 2017 15:07:10 -0700 Subject: [PATCH 4/5] `return` assumes a continuation onto the next line *if* the next line is indented --- lib/coffeescript/lexer.js | 2 +- src/lexer.coffee | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/coffeescript/lexer.js b/lib/coffeescript/lexer.js index 01dcd28753..200cdee33b 100644 --- a/lib/coffeescript/lexer.js +++ b/lib/coffeescript/lexer.js @@ -465,7 +465,7 @@ return indent.length; } if (size > this.indent) { - if (noNewlines) { + if (noNewlines || this.tag() === 'RETURN') { this.indebt = size - this.indent; this.suppressNewlines(); return indent.length; diff --git a/src/lexer.coffee b/src/lexer.coffee index 33247b2aeb..6a61c28bec 100644 --- a/src/lexer.coffee +++ b/src/lexer.coffee @@ -403,7 +403,7 @@ exports.Lexer = class Lexer return indent.length if size > @indent - if noNewlines + if noNewlines or @tag() is 'RETURN' @indebt = size - @indent @suppressNewlines() return indent.length From 1f4916587482c39fb7a7675014a006959d507398 Mon Sep 17 00:00:00 2001 From: Geoffrey Booth Date: Sun, 30 Apr 2017 18:03:24 -0700 Subject: [PATCH 5/5] Fix comment; improve test --- src/rewriter.coffee | 2 +- test/objects.coffee | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/rewriter.coffee b/src/rewriter.coffee index 453170c672..da4c26e6ec 100644 --- a/src/rewriter.coffee +++ b/src/rewriter.coffee @@ -23,7 +23,7 @@ exports.Rewriter = class Rewriter # corrected before implicit parentheses can be wrapped around blocks of code. rewrite: (@tokens) -> # Helpful snippet for debugging: - # console.log (t[0] + '/' + t[1] for t in @tokens).join ' ' + # console.log (t[0] + '/' + t[1] for t in @tokens).join ' ' @removeLeadingNewlines() @closeOpenCalls() @closeOpenIndexes() diff --git a/test/objects.coffee b/test/objects.coffee index ab4733ee60..d006d11f7a 100644 --- a/test/objects.coffee +++ b/test/objects.coffee @@ -581,9 +581,9 @@ test "#1263: Braceless object return", -> return a: 1 b: 2 - c: 3 + c: -> 3 obj = fn() eq 1, obj.a eq 2, obj.b - eq 3, obj.c + eq 3, obj.c()