mirror of
https://github.com/jashkenas/coffeescript.git
synced 2026-05-03 03:00:14 -04:00
Merge branch 'master' into 2
# Conflicts: # test/error_messages.coffee
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
this.seenFor = false;
|
||||
this.seenImport = false;
|
||||
this.seenExport = false;
|
||||
this.exportSpecifierList = false;
|
||||
this.chunkLine = opts.line || 0;
|
||||
this.chunkColumn = opts.column || 0;
|
||||
code = this.clean(code);
|
||||
@@ -66,7 +67,7 @@
|
||||
};
|
||||
|
||||
Lexer.prototype.identifierToken = function() {
|
||||
var alias, colon, colonOffset, id, idLength, input, match, poppedToken, prev, ref2, ref3, ref4, ref5, tag, tagToken;
|
||||
var alias, colon, colonOffset, id, idLength, input, match, poppedToken, prev, ref2, ref3, ref4, ref5, ref6, ref7, tag, tagToken;
|
||||
if (!(match = IDENTIFIER.exec(this.chunk))) {
|
||||
return 0;
|
||||
}
|
||||
@@ -81,12 +82,16 @@
|
||||
this.token('FROM', id);
|
||||
return id.length;
|
||||
}
|
||||
if (id === 'as' && this.seenImport && (this.tag() === 'IDENTIFIER' || this.value() === '*')) {
|
||||
if (id === 'as' && this.seenImport) {
|
||||
if (this.value() === '*') {
|
||||
this.tokens[this.tokens.length - 1][0] = 'IMPORT_ALL';
|
||||
} else if (ref2 = this.value(), indexOf.call(COFFEE_KEYWORDS, ref2) >= 0) {
|
||||
this.tokens[this.tokens.length - 1][0] = 'IDENTIFIER';
|
||||
}
|
||||
if ((ref3 = this.tag()) === 'IMPORT_ALL' || ref3 === 'IDENTIFIER') {
|
||||
this.token('AS', id);
|
||||
return id.length;
|
||||
}
|
||||
this.token('AS', id);
|
||||
return id.length;
|
||||
}
|
||||
if (id === 'as' && this.seenExport && this.tag() === 'IDENTIFIER') {
|
||||
this.token('AS', id);
|
||||
@@ -96,11 +101,11 @@
|
||||
this.token('DEFAULT', id);
|
||||
return id.length;
|
||||
}
|
||||
ref2 = this.tokens, prev = ref2[ref2.length - 1];
|
||||
tag = colon || (prev != null) && (((ref3 = prev[0]) === '.' || ref3 === '?.' || ref3 === '::' || ref3 === '?::') || !prev.spaced && prev[0] === '@') ? 'PROPERTY' : 'IDENTIFIER';
|
||||
if (tag === 'IDENTIFIER' && (indexOf.call(JS_KEYWORDS, id) >= 0 || indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
|
||||
ref4 = this.tokens, prev = ref4[ref4.length - 1];
|
||||
tag = colon || (prev != null) && (((ref5 = prev[0]) === '.' || ref5 === '?.' || ref5 === '::' || ref5 === '?::') || !prev.spaced && prev[0] === '@') ? 'PROPERTY' : 'IDENTIFIER';
|
||||
if (tag === 'IDENTIFIER' && (indexOf.call(JS_KEYWORDS, id) >= 0 || indexOf.call(COFFEE_KEYWORDS, id) >= 0) && !(this.exportSpecifierList && indexOf.call(COFFEE_KEYWORDS, id) >= 0)) {
|
||||
tag = id.toUpperCase();
|
||||
if (tag === 'WHEN' && (ref4 = this.tag(), indexOf.call(LINE_BREAK, ref4) >= 0)) {
|
||||
if (tag === 'WHEN' && (ref6 = this.tag(), indexOf.call(LINE_BREAK, ref6) >= 0)) {
|
||||
tag = 'LEADING_WHEN';
|
||||
} else if (tag === 'FOR') {
|
||||
this.seenFor = true;
|
||||
@@ -162,7 +167,7 @@
|
||||
tagToken.origin = [tag, alias, tagToken[2]];
|
||||
}
|
||||
if (poppedToken) {
|
||||
ref5 = [poppedToken[2].first_line, poppedToken[2].first_column], tagToken[2].first_line = ref5[0], tagToken[2].first_column = ref5[1];
|
||||
ref7 = [poppedToken[2].first_line, poppedToken[2].first_column], tagToken[2].first_line = ref7[0], tagToken[2].first_column = ref7[1];
|
||||
}
|
||||
if (colon) {
|
||||
colonOffset = input.lastIndexOf(':');
|
||||
@@ -563,6 +568,11 @@
|
||||
return value.length;
|
||||
}
|
||||
}
|
||||
if (value === '{' && (prev != null ? prev[0] : void 0) === 'EXPORT') {
|
||||
this.exportSpecifierList = true;
|
||||
} else if (this.exportSpecifierList && value === '}') {
|
||||
this.exportSpecifierList = false;
|
||||
}
|
||||
if (value === ';') {
|
||||
this.seenFor = this.seenImport = this.seenExport = false;
|
||||
tag = 'TERMINATOR';
|
||||
|
||||
@@ -46,6 +46,7 @@ exports.Lexer = class Lexer
|
||||
@seenFor = no # Used to recognize FORIN and FOROF tokens.
|
||||
@seenImport = no # Used to recognize IMPORT FROM? AS? tokens.
|
||||
@seenExport = no # Used to recognize EXPORT FROM? AS? tokens.
|
||||
@exportSpecifierList = no # Used to identify when in an EXPORT {...} FROM? ...
|
||||
|
||||
@chunkLine =
|
||||
opts.line or 0 # The start line for the current @chunk.
|
||||
@@ -116,10 +117,14 @@ exports.Lexer = class Lexer
|
||||
if id is 'from' and @tag() is 'YIELD'
|
||||
@token 'FROM', id
|
||||
return id.length
|
||||
if id is 'as' and @seenImport and (@tag() is 'IDENTIFIER' or @value() is '*')
|
||||
@tokens[@tokens.length - 1][0] = 'IMPORT_ALL' if @value() is '*'
|
||||
@token 'AS', id
|
||||
return id.length
|
||||
if id is 'as' and @seenImport
|
||||
if @value() is '*'
|
||||
@tokens[@tokens.length - 1][0] = 'IMPORT_ALL'
|
||||
else if @value() in COFFEE_KEYWORDS
|
||||
@tokens[@tokens.length - 1][0] = 'IDENTIFIER'
|
||||
if @tag() in ['IMPORT_ALL', 'IDENTIFIER']
|
||||
@token 'AS', id
|
||||
return id.length
|
||||
if id is 'as' and @seenExport and @tag() is 'IDENTIFIER'
|
||||
@token 'AS', id
|
||||
return id.length
|
||||
@@ -137,7 +142,8 @@ exports.Lexer = class Lexer
|
||||
else
|
||||
'IDENTIFIER'
|
||||
|
||||
if tag is 'IDENTIFIER' and (id in JS_KEYWORDS or id in COFFEE_KEYWORDS)
|
||||
if tag is 'IDENTIFIER' and (id in JS_KEYWORDS or id in COFFEE_KEYWORDS) and
|
||||
not (@exportSpecifierList and id in COFFEE_KEYWORDS)
|
||||
tag = id.toUpperCase()
|
||||
if tag is 'WHEN' and @tag() in LINE_BREAK
|
||||
tag = 'LEADING_WHEN'
|
||||
@@ -469,6 +475,11 @@ exports.Lexer = class Lexer
|
||||
@error message, origin[2] if message
|
||||
return value.length if skipToken
|
||||
|
||||
if value is '{' and prev?[0] is 'EXPORT'
|
||||
@exportSpecifierList = yes
|
||||
else if @exportSpecifierList and value is '}'
|
||||
@exportSpecifierList = no
|
||||
|
||||
if value is ';'
|
||||
@seenFor = @seenImport = @seenExport = no
|
||||
tag = 'TERMINATOR'
|
||||
|
||||
@@ -1149,3 +1149,23 @@ test "bound functions cannot be generators", ->
|
||||
f = => yield this
|
||||
^^^^^^^^^^
|
||||
'''
|
||||
|
||||
test "CoffeeScript keywords cannot be used as unaliased names in import lists", ->
|
||||
assertErrorFormat """
|
||||
import { unless, baz as bar } from 'lib'
|
||||
bar.barMethod()
|
||||
""", '''
|
||||
[stdin]:1:10: error: unexpected unless
|
||||
import { unless, baz as bar } from 'lib'
|
||||
^^^^^^
|
||||
'''
|
||||
|
||||
test "CoffeeScript keywords cannot be used as local names in import list aliases", ->
|
||||
assertErrorFormat """
|
||||
import { bar as unless, baz as bar } from 'lib'
|
||||
bar.barMethod()
|
||||
""", '''
|
||||
[stdin]:1:17: error: unexpected unless
|
||||
import { bar as unless, baz as bar } from 'lib'
|
||||
^^^^^^
|
||||
'''
|
||||
|
||||
@@ -510,6 +510,23 @@ test "export as aliases members imported from another module", ->
|
||||
} from 'lib';"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "export list can contain CoffeeScript keywords", ->
|
||||
input = "export { unless } from 'lib'"
|
||||
output = """
|
||||
export {
|
||||
unless
|
||||
} from 'lib';"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "export list can contain CoffeeScript keywords when aliasing", ->
|
||||
input = "export { when as bar, baz as unless } from 'lib'"
|
||||
output = """
|
||||
export {
|
||||
when as bar,
|
||||
baz as unless
|
||||
} from 'lib';"""
|
||||
eq toJS(input), output
|
||||
|
||||
|
||||
# Edge cases
|
||||
|
||||
@@ -608,6 +625,18 @@ test "`as` can be used as an alias name", ->
|
||||
} from 'lib';"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "CoffeeScript keywords can be used as imported names in import lists", ->
|
||||
input = """
|
||||
import { unless as bar } from 'lib'
|
||||
bar.barMethod()"""
|
||||
output = """
|
||||
import {
|
||||
unless as bar
|
||||
} from 'lib';
|
||||
|
||||
bar.barMethod();"""
|
||||
eq toJS(input), output
|
||||
|
||||
test "`*` can be used in an expression on the same line as an export keyword", ->
|
||||
input = "export foo = (x) -> x * x"
|
||||
output = """
|
||||
|
||||
Reference in New Issue
Block a user