From f3caa9292f8a247b22c1de258a200af010d90a93 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Fri, 30 Jul 2010 22:06:22 -0400 Subject: [PATCH] Fixing Issue #552, Indentation bug with chained calls with nested object literals... --- lib/lexer.js | 32 +++++++++++++++++++++----------- src/lexer.coffee | 28 +++++++++++++++++++--------- test/test_blocks.coffee | 22 +++++++++++++++++++++- 3 files changed, 61 insertions(+), 21 deletions(-) diff --git a/lib/lexer.js b/lib/lexer.js index d38a1678..4223fb4c 100644 --- a/lib/lexer.js +++ b/lib/lexer.js @@ -242,6 +242,7 @@ if (noNewlines) { return this.suppressNewlines(); } + this.outdebt = 0; diff = size - this.indent; this.token('INDENT', diff); this.indents.push(diff); @@ -251,19 +252,28 @@ this.indent = size; return true; }; - Lexer.prototype.outdentToken = function(moveOut, noNewlines) { - var lastIndent; - if (moveOut > -this.outdebt) { - while (moveOut > 0 && this.indents.length) { - lastIndent = this.indents.pop(); - this.token('OUTDENT', lastIndent); - moveOut -= lastIndent; + Lexer.prototype.outdentToken = function(moveOut, noNewlines, close) { + var dent, len; + while (moveOut > 0) { + len = this.indents.length - 1; + if (this.indents[len] === undefined) { + moveOut = 0; + } else if (this.indents[len] === this.outdebt) { + moveOut -= this.outdebt; + this.outdebt = 0; + } else if (this.indents[len] < this.outdebt) { + this.outdebt -= this.indents[len]; + moveOut -= this.indents[len]; + } else { + dent = this.indents.pop(); + dent -= this.outdebt; + moveOut -= dent; + this.outdebt = 0; + this.token('OUTDENT', dent); } - } else { - this.outdebt += moveOut; } - if (!(noNewlines)) { - this.outdebt = moveOut; + if (dent) { + this.outdebt -= moveOut; } if (!(this.tag() === 'TERMINATOR' || noNewlines)) { this.token('TERMINATOR', "\n"); diff --git a/src/lexer.coffee b/src/lexer.coffee index 4f14a055..57c83b10 100644 --- a/src/lexer.coffee +++ b/src/lexer.coffee @@ -205,6 +205,7 @@ exports.Lexer = class Lexer return @newlineToken indent else if size > @indent return @suppressNewlines() if noNewlines + @outdebt = 0 diff = size - @indent @token 'INDENT', diff @indents.push diff @@ -215,15 +216,24 @@ exports.Lexer = class Lexer # Record an outdent token or multiple tokens, if we happen to be moving back # inwards past several recorded indents. - outdentToken: (moveOut, noNewlines) -> - if moveOut > -@outdebt - while moveOut > 0 and @indents.length - lastIndent = @indents.pop() - @token 'OUTDENT', lastIndent - moveOut -= lastIndent - else - @outdebt += moveOut - @outdebt = moveOut unless noNewlines + outdentToken: (moveOut, noNewlines, close) -> + while moveOut > 0 + len = @indents.length - 1 + if @indents[len] is undefined + moveOut = 0 + else if @indents[len] is @outdebt + moveOut -= @outdebt + @outdebt = 0 + else if @indents[len] < @outdebt + @outdebt -= @indents[len] + moveOut -= @indents[len] + else + dent = @indents.pop() + dent -= @outdebt + moveOut -= dent + @outdebt = 0 + @token 'OUTDENT', dent + @outdebt -= moveOut if dent @token 'TERMINATOR', "\n" unless @tag() is 'TERMINATOR' or noNewlines true diff --git a/test/test_blocks.coffee b/test/test_blocks.coffee index 04cc73ea..d71cd2c3 100644 --- a/test/test_blocks.coffee +++ b/test/test_blocks.coffee @@ -32,4 +32,24 @@ func = -> } obj.key - 5 -ok func() is 5 \ No newline at end of file +ok func() is 5 + + +# Ensure that chained calls with indented implicit object literals below are +# alright. +result = null +obj = + method: (val) -> this + second: (hash) -> result = hash.three + + +obj + .method( + 101 + ).second( + one: + two: 2 + three: 3 + ) + +ok result is 3