mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-05-03 03:00:14 -04:00
Handle nested calls and function oneliners when chaining
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// Generated by CoffeeScript 1.6.3
|
||||
(function() {
|
||||
var BALANCED_PAIRS, EXPRESSION_CLOSE, EXPRESSION_END, EXPRESSION_START, IMPLICIT_CALL, IMPLICIT_END, IMPLICIT_FUNC, IMPLICIT_UNSPACED_CALL, INVERSES, LINEBREAKS, SINGLE_CLOSERS, SINGLE_LINERS, generate, left, rite, _i, _len, _ref,
|
||||
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, left, rite, _i, _len, _ref,
|
||||
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
|
||||
__slice = [].slice;
|
||||
|
||||
@@ -149,7 +149,7 @@
|
||||
var stack;
|
||||
stack = [];
|
||||
return this.scanTokens(function(token, i, tokens) {
|
||||
var endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, nextTag, offset, prevTag, prevToken, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
|
||||
var endAllImplicitCalls, endImplicitCall, endImplicitObject, forward, inImplicit, inImplicitCall, inImplicitControl, inImplicitObject, nextTag, offset, prevTag, prevToken, s, sameLine, stackIdx, stackTag, stackTop, startIdx, startImplicitCall, startImplicitObject, startsLine, tag, _ref, _ref1, _ref2, _ref3, _ref4, _ref5;
|
||||
tag = token[0];
|
||||
prevTag = (prevToken = i > 0 ? tokens[i - 1] : [])[0];
|
||||
nextTag = (i < tokens.length - 1 ? tokens[i + 1] : [])[0];
|
||||
@@ -194,6 +194,14 @@
|
||||
tokens.splice(i, 0, generate('CALL_END', ')'));
|
||||
return i += 1;
|
||||
};
|
||||
endAllImplicitCalls = function() {
|
||||
var _results;
|
||||
_results = [];
|
||||
while (inImplicitCall()) {
|
||||
_results.push(endImplicitCall());
|
||||
}
|
||||
return _results;
|
||||
};
|
||||
startImplicitObject = function(j, startsLine) {
|
||||
var idx;
|
||||
if (startsLine == null) {
|
||||
@@ -285,9 +293,15 @@
|
||||
startImplicitObject(s, !!startsLine);
|
||||
return forward(2);
|
||||
}
|
||||
if ((prevTag === 'OUTDENT' || prevToken.newLine) && inImplicitCall() && (tag === '.' || tag === '?.' || tag === '::' || tag === '?::')) {
|
||||
endImplicitCall();
|
||||
return forward(1);
|
||||
if (inImplicitCall() && __indexOf.call(CALL_CLOSERS, tag) >= 0) {
|
||||
if (prevTag === 'OUTDENT') {
|
||||
endImplicitCall();
|
||||
return forward(1);
|
||||
}
|
||||
if (prevToken.newLine) {
|
||||
endAllImplicitCalls();
|
||||
return forward(1);
|
||||
}
|
||||
}
|
||||
if (inImplicitObject() && __indexOf.call(LINEBREAKS, tag) >= 0) {
|
||||
stackTop()[2].sameLine = false;
|
||||
@@ -346,8 +360,8 @@
|
||||
var action, condition, indent, outdent, starter;
|
||||
starter = indent = outdent = null;
|
||||
condition = function(token, i) {
|
||||
var _ref, _ref1, _ref2;
|
||||
return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'TERMINATOR' && (_ref1 = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref1) >= 0)) && !(token[0] === 'ELSE' && starter !== 'THEN') && !(((_ref2 = token[0]) === 'CATCH' || _ref2 === 'FINALLY') && (starter === '->' || starter === '=>'));
|
||||
var _ref, _ref1, _ref2, _ref3;
|
||||
return token[1] !== ';' && (_ref = token[0], __indexOf.call(SINGLE_CLOSERS, _ref) >= 0) && !(token[0] === 'TERMINATOR' && (_ref1 = this.tag(i + 1), __indexOf.call(EXPRESSION_CLOSE, _ref1) >= 0)) && !(token[0] === 'ELSE' && starter !== 'THEN') && !(((_ref2 = token[0]) === 'CATCH' || _ref2 === 'FINALLY') && (starter === '->' || starter === '=>')) || (_ref3 = token[0], __indexOf.call(CALL_CLOSERS, _ref3) >= 0) && this.tokens[i - 1].newLine;
|
||||
};
|
||||
action = function(token, i) {
|
||||
return this.tokens.splice((this.tag(i - 1) === ',' ? i - 1 : i), 0, outdent);
|
||||
@@ -472,4 +486,6 @@
|
||||
|
||||
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT'];
|
||||
|
||||
CALL_CLOSERS = ['.', '?.', '::', '?::'];
|
||||
|
||||
}).call(this);
|
||||
|
||||
@@ -159,6 +159,10 @@ class exports.Rewriter
|
||||
tokens.splice i, 0, generate 'CALL_END', ')'
|
||||
i += 1
|
||||
|
||||
endAllImplicitCalls = ->
|
||||
while inImplicitCall()
|
||||
endImplicitCall()
|
||||
|
||||
startImplicitObject = (j, startsLine = yes) ->
|
||||
idx = j ? i
|
||||
stack.push ['{', idx, sameLine: yes, startsLine: startsLine, ours: yes]
|
||||
@@ -281,10 +285,13 @@ class exports.Rewriter
|
||||
# .g b
|
||||
# .h a
|
||||
#
|
||||
if (prevTag is 'OUTDENT' or prevToken.newLine) and inImplicitCall() and
|
||||
tag in ['.', '?.', '::', '?::']
|
||||
endImplicitCall()
|
||||
return forward(1)
|
||||
if inImplicitCall() and tag in CALL_CLOSERS
|
||||
if prevTag is 'OUTDENT'
|
||||
endImplicitCall()
|
||||
return forward(1)
|
||||
if prevToken.newLine
|
||||
endAllImplicitCalls()
|
||||
return forward(1)
|
||||
|
||||
stackTop()[2].sameLine = no if inImplicitObject() and tag in LINEBREAKS
|
||||
|
||||
@@ -363,7 +370,8 @@ class exports.Rewriter
|
||||
token[1] isnt ';' and token[0] in SINGLE_CLOSERS and
|
||||
not (token[0] is 'TERMINATOR' and @tag(i + 1) in EXPRESSION_CLOSE) and
|
||||
not (token[0] is 'ELSE' and starter isnt 'THEN') and
|
||||
not (token[0] in ['CATCH', 'FINALLY'] and starter in ['->', '=>'])
|
||||
not (token[0] in ['CATCH', 'FINALLY'] and starter in ['->', '=>']) or
|
||||
token[0] in CALL_CLOSERS and @tokens[i - 1].newLine
|
||||
|
||||
action = (token, i) ->
|
||||
@tokens.splice (if @tag(i - 1) is ',' then i - 1 else i), 0, outdent
|
||||
@@ -478,3 +486,6 @@ SINGLE_CLOSERS = ['TERMINATOR', 'CATCH', 'FINALLY', 'ELSE', 'OUTDENT', 'LEADIN
|
||||
|
||||
# Tokens that end a line.
|
||||
LINEBREAKS = ['TERMINATOR', 'INDENT', 'OUTDENT']
|
||||
|
||||
# Tokens that close open calls when they follow a newline.
|
||||
CALL_CLOSERS = ['.', '?.', '::', '?::']
|
||||
|
||||
@@ -78,11 +78,24 @@ test "#1495, method call chaining", ->
|
||||
'aaabbbccc'.replace /(\w)\1\1/g, '$1$1'
|
||||
.replace /([abc])\1/g, '$1'
|
||||
|
||||
# Unreadable code, not a real-life use case
|
||||
result = str.split ''.
|
||||
# Nested calls
|
||||
result = [1..3]
|
||||
.slice Math.max 0, 1
|
||||
.concat [3]
|
||||
arrayEq result, [2, 3, 3]
|
||||
|
||||
# Single line function arguments.
|
||||
result = [1..6]
|
||||
.map (x) -> x * x
|
||||
.filter (x) -> x % 2 is 0
|
||||
.reverse()
|
||||
arrayEq result, [36, 16, 4]
|
||||
|
||||
# The parens are forced
|
||||
result = str.split(''.
|
||||
split ''
|
||||
.join('')
|
||||
.join ', '
|
||||
.join ''
|
||||
).join ', '
|
||||
eq 'a, b, c', result
|
||||
|
||||
# Operators
|
||||
|
||||
Reference in New Issue
Block a user