mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
Issue #1547 'use strict' duplicate formal parameter are prohibited
updated error message (thanks @davidchambers) code style fixes
This commit is contained in:
parent
a2ef66f197
commit
7521068ba3
2 changed files with 55 additions and 12 deletions
|
@ -1162,8 +1162,10 @@ exports.Code = class Code extends Base
|
|||
o.scope.shared = del(o, 'sharedScope')
|
||||
o.indent += TAB
|
||||
delete o.bare
|
||||
vars = []
|
||||
exprs = []
|
||||
params = []
|
||||
exprs = []
|
||||
for name in @paramNames() # this step must be performed before the others
|
||||
unless o.scope.check name then o.scope.parameter name
|
||||
for param in @params when param.splat
|
||||
o.scope.add p.name.value, 'var', yes for p in @params when p.name.value
|
||||
splats = new Assign new Value(new Arr(p.asReference o for p in @params)),
|
||||
|
@ -1180,11 +1182,15 @@ exports.Code = class Code extends Base
|
|||
lit = new Literal ref.name.value + ' == null'
|
||||
val = new Assign new Value(param.name), param.value, '='
|
||||
exprs.push new If lit, val
|
||||
vars.push ref unless splats
|
||||
params.push ref unless splats
|
||||
wasEmpty = @body.isEmpty()
|
||||
exprs.unshift splats if splats
|
||||
@body.expressions.unshift exprs... if exprs.length
|
||||
o.scope.parameter vars[i] = v.compile o for v, i in vars unless splats
|
||||
o.scope.parameter params[i] = p.compile o for p, i in params
|
||||
uniqs = []
|
||||
for name in @paramNames()
|
||||
throw SyntaxError "multiple parameters named '#{name}'" if name in uniqs
|
||||
uniqs.push name
|
||||
@body.makeReturn() unless wasEmpty or @noReturn
|
||||
if @bound
|
||||
if o.scope.parent.method?.bound
|
||||
|
@ -1194,12 +1200,18 @@ exports.Code = class Code extends Base
|
|||
idt = o.indent
|
||||
code = 'function'
|
||||
code += ' ' + @name if @ctor
|
||||
code += '(' + vars.join(', ') + ') {'
|
||||
code += '(' + params.join(', ') + ') {'
|
||||
code += "\n#{ @body.compileWithDeclarations o }\n#{@tab}" unless @body.isEmpty()
|
||||
code += '}'
|
||||
return @tab + code if @ctor
|
||||
if @front or (o.level >= LEVEL_ACCESS) then "(#{code})" else code
|
||||
|
||||
# A list of parameter names, excluding those generated by the compiler.
|
||||
paramNames: ->
|
||||
names = []
|
||||
names.push param.names()... for param in @params
|
||||
names
|
||||
|
||||
# Short-circuit `traverseChildren` method to prevent it from crossing scope boundaries
|
||||
# unless `crossScope` is `true`.
|
||||
traverseChildren: (crossScope, func) ->
|
||||
|
@ -1223,7 +1235,8 @@ exports.Param = class Param extends Base
|
|||
node = @name
|
||||
if node.this
|
||||
node = node.properties[0].name
|
||||
node = new Literal '_' + node.value if node.value.reserved
|
||||
if node.value.reserved
|
||||
node = new Literal o.scope.freeVariable node.value
|
||||
else if node.isComplex()
|
||||
node = new Literal o.scope.freeVariable 'arg'
|
||||
node = new Value node
|
||||
|
@ -1233,6 +1246,36 @@ exports.Param = class Param extends Base
|
|||
isComplex: ->
|
||||
@name.isComplex()
|
||||
|
||||
# Finds the name or names of a `Param`; useful for detecting duplicates.
|
||||
# In a sense, a destructured parameter represents multiple JS parameters,
|
||||
# thus this method returns an `Array` of names.
|
||||
# Reserved words used as param names, as well as the Object and Array
|
||||
# literals used for destructured params, get a compiler generated name
|
||||
# during the `Code` compilation step, so this is necessarily an incomplete
|
||||
# list of a parameter's names.
|
||||
names: (name = @name)->
|
||||
atParam = (obj) ->
|
||||
{value} = obj.properties[0].name
|
||||
return if value.reserved then [] else [value]
|
||||
# * simple literals `foo`
|
||||
return [name.value] if name instanceof Literal
|
||||
# * at-params `@foo`
|
||||
return atParam(name) if name instanceof Value
|
||||
names = []
|
||||
for obj in name.objects
|
||||
# * assignments within destructured parameters `{foo:bar}`
|
||||
if obj instanceof Assign
|
||||
names.push obj.variable.base.value
|
||||
# * destructured parameters within destructured parameters `[{a}]`
|
||||
else if obj.isArray() or obj.isObject()
|
||||
names.push @names(obj.base)...
|
||||
# * at-params within destructured parameters `{@foo}`
|
||||
else if obj.this
|
||||
names.push atParam(obj)...
|
||||
# * simple destructured parameters {foo}
|
||||
else names.push obj.base.value
|
||||
names
|
||||
|
||||
#### Splat
|
||||
|
||||
# A splat, either as a parameter to a function, an argument to a call,
|
||||
|
|
|
@ -91,9 +91,9 @@ test "self-referencing functions", ->
|
|||
|
||||
test "splats", ->
|
||||
arrayEq [0, 1, 2], (((splat...) -> splat) 0, 1, 2)
|
||||
arrayEq [2, 3], (((_, _, splat...) -> splat) 0, 1, 2, 3)
|
||||
arrayEq [0, 1], (((splat..., _, _) -> splat) 0, 1, 2, 3)
|
||||
arrayEq [2], (((_, _, splat..., _) -> splat) 0, 1, 2, 3)
|
||||
arrayEq [2, 3], (((_, _1, splat...) -> splat) 0, 1, 2, 3)
|
||||
arrayEq [0, 1], (((splat..., _, _1) -> splat) 0, 1, 2, 3)
|
||||
arrayEq [2], (((_, _1, splat..., _2) -> splat) 0, 1, 2, 3)
|
||||
|
||||
test "@-parameters: automatically assign an argument's value to a property of the context", ->
|
||||
nonce = {}
|
||||
|
@ -131,7 +131,7 @@ test "destructuring in function definition", ->
|
|||
test "default values", ->
|
||||
nonceA = {}
|
||||
nonceB = {}
|
||||
a = (_,_,arg=nonceA) -> arg
|
||||
a = (_,_1,arg=nonceA) -> arg
|
||||
eq nonceA, a()
|
||||
eq nonceA, a(0)
|
||||
eq nonceB, a(0,0,nonceB)
|
||||
|
@ -139,7 +139,7 @@ test "default values", ->
|
|||
eq nonceA, a(0,0,null)
|
||||
eq false , a(0,0,false)
|
||||
eq nonceB, a(undefined,undefined,nonceB,undefined)
|
||||
b = (_,arg=nonceA,_,_) -> arg
|
||||
b = (_,arg=nonceA,_1,_2) -> arg
|
||||
eq nonceA, b()
|
||||
eq nonceA, b(0)
|
||||
eq nonceB, b(0,nonceB)
|
||||
|
@ -147,7 +147,7 @@ test "default values", ->
|
|||
eq nonceA, b(0,null)
|
||||
eq false , b(0,false)
|
||||
eq nonceB, b(undefined,nonceB,undefined)
|
||||
c = (arg=nonceA,_,_) -> arg
|
||||
c = (arg=nonceA,_,_1) -> arg
|
||||
eq nonceA, c()
|
||||
eq 0, c(0)
|
||||
eq nonceB, c(nonceB)
|
||||
|
|
Loading…
Add table
Reference in a new issue