{"action":"created","issue":{"url":"https://api.github.com/repos/jashkenas/coffeescript/issues/3831","labels_url":"https://api.github.com/repos/jashkenas/coffeescript/issues/3831/labels{/name}","comments_url":"https://api.github.com/repos/jashkenas/coffeescript/issues/3831/comments","events_url":"https://api.github.com/repos/jashkenas/coffeescript/issues/3831/events","html_url":"https://github.com/jashkenas/coffeescript/issues/3831","id":56631578,"number":3831,"title":"Extra 'end of interpolation' tag","user":{"login":"swang","id":49867,"avatar_url":"https://avatars.githubusercontent.com/u/49867?v=3","gravatar_id":"","url":"https://api.github.com/users/swang","html_url":"https://github.com/swang","followers_url":"https://api.github.com/users/swang/followers","following_url":"https://api.github.com/users/swang/following{/other_user}","gists_url":"https://api.github.com/users/swang/gists{/gist_id}","starred_url":"https://api.github.com/users/swang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/swang/subscriptions","organizations_url":"https://api.github.com/users/swang/orgs","repos_url":"https://api.github.com/users/swang/repos","events_url":"https://api.github.com/users/swang/events{/privacy}","received_events_url":"https://api.github.com/users/swang/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":2,"created_at":"2015-02-05T06:09:17Z","updated_at":"2015-02-05T09:02:30Z","closed_at":null,"body":"Take this interpolated string:\r\n```cs\r\n\"A #{a} B #{b}\"\r\n```\r\nwhich generates these tokens:\r\n```\r\n[ '(', '(', { first_line: 0, first_column: 0, last_line: 0, last_column: 0 }, origin: [ '', 'interpolation', { first_line: 0, first_column: 2, last_line: 0, last_column: 3 } ] ]\r\n[ 'STRING', '\"A \"', { first_line: 0, first_column: 0, last_line: 0, last_column: 2 } ]\r\n[ '+', '+', { first_line: 0, first_column: 4, last_line: 0, last_column: 4 } ]\r\n[ '(', '(', { first_line: 0, first_column: 4, last_line: 0, last_column: 4 } ]\r\n[ 'IDENTIFIER', 'a', { first_line: 0, first_column: 5, last_line: 0, last_column: 5 }, variable: true ]\r\n[ ')', ')', { first_line: 0, first_column: 6, last_line: 0, last_column: 6 }, origin: [ '', 'end of interpolation', { first_line: 0, first_column: 6, last_line: 0, last_column: 6 } ] ]\r\n[ '+', '+', { first_line: 0, first_column: 7, last_line: 0, last_column: 7 } ]\r\n[ 'STRING', '\" B \"', { first_line: 0, first_column: 7, last_line: 0, last_column: 9 } ]\r\n[ '+', '+', { first_line: 0, first_column: 11, last_line: 0, last_column: 11 } ]\r\n[ '(', '(', { first_line: 0, first_column: 11, last_line: 0, last_column: 11 } ]\r\n[ 'IDENTIFIER', 'b', { first_line: 0, first_column: 12, last_line: 0, last_column: 12 }, variable: true ]\r\n[ ')', ')', { first_line: 0, first_column: 13, last_line: 0, last_column: 13 }, origin: [ '', 'end of interpolation', { first_line: 0, first_column: 13, last_line: 0, last_column: 13 } ] ]\r\n[ ')', ')', { first_line: 0, first_column: 14, last_line: 0, last_column: 14 }, stringEnd: true ]\r\n[ 'TERMINATOR', '\\n', { first_line: 0, first_column: 15, last_line: 0, last_column: 15 } ]\r\n```\r\nWhich looks like this:\r\n```\r\n(\"A \"+(a)+\" B \"+(b))\r\n^       ^         ^\r\n|       +---------+---> end of interpolation tags\r\n|\r\n+---> start of interpolation tag\r\n```\r\nThis is one possible fix, which moves the 'end of interpolation' tag into the last parenthesis to match the 'interpolation' tag on the first parenthesis:\r\n```patch\r\n:100644 100644 e216403... 0000000... M\tsrc/lexer.coffee\r\n\r\ndiff --git a/src/lexer.coffee b/src/lexer.coffee\r\nindex e216403..be83fe5 100644\r\n--- a/src/lexer.coffee\r\n+++ b/src/lexer.coffee\r\n@@ -504,7 +504,6 @@ exports.Lexer = class Lexer\r\n       [open, ..., close] = nested\r\n       open[0]  = open[1]  = '('\r\n       close[0] = close[1] = ')'\r\n-      close.origin = ['', 'end of interpolation', close[2]]\r\n \r\n       # Remove leading 'TERMINATOR' (if any).\r\n       nested.splice 1, 1 if nested[1]?[0] is 'TERMINATOR'\r\n@@ -588,6 +587,7 @@ exports.Lexer = class Lexer\r\n         last_line:    lastToken[2].last_line\r\n         last_column:  lastToken[2].last_column + 1\r\n       }\r\n+      rparen.origin = ['', 'end of interpolation', rparen[2]]\r\n       rparen.stringEnd = true\r\n \r\n   # Pairs up a closing token, ensuring that all listed pairs of tokens are\r\n```\r\nHowever this causes some problems when running the tests:\r\n```\r\n  #1316: unexpected end of interpolation \r\n  AssertionError: Expected [stdin]:1:5: error: unexpected end of interpolation\r\n\"#{+}\"\r\n    ^ to equal [stdin]:1:5: error: unexpected )\r\n\"#{+}\"\r\n```\r\nThe error goes from `unexpected end of interpolation` to `unexpected )`\r\n## Importance\r\nCoffeelint needs to know when string interpolations occur so it can ignore the '+' signs that are added since they interfere with rules about spacing between operators. Personally I think the patch I suggested is the easiest fix to the problem even though it changes the error message to be less helpful. Not sure which way is \"correct\" but would prefer it to be a way that makes it easier for coffeelint to ignore the generated '+' tokens.\r\n\r\nThanks."},"comment":{"url":"https://api.github.com/repos/jashkenas/coffeescript/issues/comments/73014346","html_url":"https://github.com/jashkenas/coffeescript/issues/3831#issuecomment-73014346","issue_url":"https://api.github.com/repos/jashkenas/coffeescript/issues/3831","id":73014346,"user":{"login":"swang","id":49867,"avatar_url":"https://avatars.githubusercontent.com/u/49867?v=3","gravatar_id":"","url":"https://api.github.com/users/swang","html_url":"https://github.com/swang","followers_url":"https://api.github.com/users/swang/followers","following_url":"https://api.github.com/users/swang/following{/other_user}","gists_url":"https://api.github.com/users/swang/gists{/gist_id}","starred_url":"https://api.github.com/users/swang/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/swang/subscriptions","organizations_url":"https://api.github.com/users/swang/orgs","repos_url":"https://api.github.com/users/swang/repos","events_url":"https://api.github.com/users/swang/events{/privacy}","received_events_url":"https://api.github.com/users/swang/received_events","type":"User","site_admin":false},"created_at":"2015-02-05T09:02:30Z","updated_at":"2015-02-05T09:02:30Z","body":"Interesting, I had thought the end interpolation tag was originally in the string in previous versions. Turns out I was wrong and there wasn't one.\r\n\r\nThere is a rule in coffeelint that makes sure operators are properly spaced. Since interpolated strings always had '+' tokens that were unspaced, it would always trigger this rule. To get around it coffeelint would just skip interpolated strings. The extra parentheses throws it off.\r\n\r\nAnyways, It just seems weird that there is no consist start/end of the interpolation. I will look to see if there's another way around this."}}