mirror of
https://github.com/github/codeql.git
synced 2026-04-30 19:26:02 +02:00
Ruby: support anonymous (hash)splat parameters/arguments
This commit is contained in:
@@ -181,7 +181,10 @@ class HashSplatParameter extends NamedParameter, THashSplatParameter {
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "HashSplatParameter" }
|
||||
|
||||
final override LocalVariable getVariable() { result = TLocalVariableReal(_, _, g.getName()) }
|
||||
final override LocalVariable getVariable() {
|
||||
result = TLocalVariableReal(_, _, g.getName()) or
|
||||
result = TLocalVariableSynth(this, 0)
|
||||
}
|
||||
|
||||
final override string toString() {
|
||||
result = "**" + this.getName()
|
||||
@@ -307,7 +310,10 @@ class SplatParameter extends NamedParameter, TSplatParameter {
|
||||
|
||||
final override string getAPrimaryQlClass() { result = "SplatParameter" }
|
||||
|
||||
final override LocalVariable getVariable() { result = TLocalVariableReal(_, _, g.getName()) }
|
||||
final override LocalVariable getVariable() {
|
||||
result = TLocalVariableReal(_, _, g.getName()) or
|
||||
result = TLocalVariableSynth(this, 0)
|
||||
}
|
||||
|
||||
final override string toString() {
|
||||
result = "*" + this.getName()
|
||||
|
||||
@@ -36,7 +36,7 @@ class LocalVariable extends Variable, TLocalVariable {
|
||||
/** Gets the access where this local variable is first introduced. */
|
||||
VariableAccess getDefiningAccess() {
|
||||
result = this.(LocalVariableReal).getDefiningAccessImpl() or
|
||||
synthChild(any(BlockParameter p | this = p.getVariable()), 0, result)
|
||||
synthChild(any(NamedParameter p | this = p.getVariable()), 0, result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -120,7 +120,7 @@ class VariableAccess extends Expr instanceof VariableAccessImpl {
|
||||
or
|
||||
this = any(HashPattern p).getValue(_)
|
||||
or
|
||||
synthChild(any(BlockParameter p), 0, this)
|
||||
synthChild(any(NamedParameter p), 0, this)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,10 @@ class SplatExprReal extends UnaryOperationImpl, TSplatExprReal {
|
||||
|
||||
final override string getOperatorImpl() { result = "*" }
|
||||
|
||||
final override Expr getOperandImpl() { toGenerated(result) = g.getChild() }
|
||||
final override Expr getOperandImpl() {
|
||||
toGenerated(result) = g.getChild() or
|
||||
synthChild(this, 0, result)
|
||||
}
|
||||
}
|
||||
|
||||
class SplatExprSynth extends UnaryOperationImpl, TSplatExprSynth {
|
||||
@@ -56,7 +59,10 @@ class HashSplatExprImpl extends UnaryOperationImpl, THashSplatExpr {
|
||||
|
||||
HashSplatExprImpl() { this = THashSplatExpr(g) }
|
||||
|
||||
final override Expr getOperandImpl() { toGenerated(result) = g.getChild() }
|
||||
final override Expr getOperandImpl() {
|
||||
toGenerated(result) = g.getChild() or
|
||||
synthChild(this, 0, result)
|
||||
}
|
||||
|
||||
final override string getOperatorImpl() { result = "**" }
|
||||
}
|
||||
|
||||
@@ -1317,46 +1317,62 @@ private module ImplicitHashValueSynthesis {
|
||||
|
||||
/**
|
||||
* ```rb
|
||||
* def foo(&)
|
||||
* bar(&)
|
||||
* def foo(*, **, &)
|
||||
* bar(*, **, &)
|
||||
* end
|
||||
* ```
|
||||
* desugars to,
|
||||
* ```rb
|
||||
* def foo(&__synth_0)
|
||||
* bar(&__synth_0)
|
||||
* def foo(*__synth_0, **__synth_1, &__synth_2)
|
||||
* bar(*__synth_0, **__synth_1, &__synth_2)
|
||||
* end
|
||||
* ```
|
||||
*/
|
||||
private module AnonymousBlockParameterSynth {
|
||||
private BlockParameter anonymousBlockParameter() {
|
||||
private module AnonymousParameterSynth {
|
||||
private class AnonymousParameter = TBlockParameter or THashSplatParameter or TSplatParameter;
|
||||
|
||||
private class AnonymousArgument = TBlockArgument or THashSplatExpr or TSplatExpr;
|
||||
|
||||
private AnonymousParameter anonymousParameter() {
|
||||
exists(Ruby::BlockParameter p | not exists(p.getName()) and toGenerated(result) = p)
|
||||
or
|
||||
exists(Ruby::SplatParameter p | not exists(p.getName()) and toGenerated(result) = p)
|
||||
or
|
||||
exists(Ruby::HashSplatParameter p | not exists(p.getName()) and toGenerated(result) = p)
|
||||
}
|
||||
|
||||
private BlockArgument anonymousBlockArgument() {
|
||||
private AnonymousArgument anonymousArgument() {
|
||||
exists(Ruby::BlockArgument p | not exists(p.getChild()) and toGenerated(result) = p)
|
||||
or
|
||||
exists(Ruby::SplatArgument p | not exists(p.getChild()) and toGenerated(result) = p)
|
||||
or
|
||||
exists(Ruby::HashSplatArgument p | not exists(p.getChild()) and toGenerated(result) = p)
|
||||
}
|
||||
|
||||
private class AnonymousBlockParameterSynthesis extends Synthesis {
|
||||
private class AnonymousParameterSynthesis extends Synthesis {
|
||||
final override predicate child(AstNode parent, int i, Child child) {
|
||||
i = 0 and
|
||||
parent = anonymousBlockParameter() and
|
||||
parent = anonymousParameter() and
|
||||
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(parent, 0)))
|
||||
}
|
||||
|
||||
final override predicate localVariable(AstNode n, int i) {
|
||||
n = anonymousBlockParameter() and i = 0
|
||||
}
|
||||
final override predicate localVariable(AstNode n, int i) { n = anonymousParameter() and i = 0 }
|
||||
}
|
||||
|
||||
private class AnonymousBlockArgumentSynthesis extends Synthesis {
|
||||
private class AnonymousArgumentSynthesis extends Synthesis {
|
||||
final override predicate child(AstNode parent, int i, Child child) {
|
||||
i = 0 and
|
||||
parent = anonymousBlockArgument() and
|
||||
exists(BlockParameter param |
|
||||
param = anonymousBlockParameter() and
|
||||
parent = anonymousArgument() and
|
||||
exists(AnonymousParameter param |
|
||||
param = anonymousParameter() and
|
||||
scopeOf(toGenerated(parent)).getEnclosingMethod() = scopeOf(toGenerated(param)) and
|
||||
child = SynthChild(LocalVariableAccessSynthKind(TLocalVariableSynth(param, 0)))
|
||||
|
|
||||
param instanceof TBlockParameter and parent instanceof TBlockArgument
|
||||
or
|
||||
param instanceof TSplatParameter and parent instanceof TSplatExpr
|
||||
or
|
||||
param instanceof THashSplatParameter and parent instanceof THashSplatExpr
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,10 +269,12 @@ foo(&)
|
||||
# splat argument
|
||||
foo(*bar)
|
||||
foo(*X::bar)
|
||||
foo(*)
|
||||
|
||||
# hash-splat argument
|
||||
foo(**bar)
|
||||
foo(**X::bar)
|
||||
foo(**)
|
||||
|
||||
# the value in a keyword argument
|
||||
foo(blah: bar)
|
||||
|
||||
@@ -84,3 +84,13 @@ def anonymous_block_parameter(array, &)
|
||||
end
|
||||
|
||||
run_block { |x; y, z | puts x }
|
||||
|
||||
# Anonymous splat parameter
|
||||
def anonymous_splat_parameter(array, *)
|
||||
array.concat(*)
|
||||
end
|
||||
|
||||
# Anonymous hash splat parameter
|
||||
def anonymous_hash_splat_parameter(hash, **)
|
||||
hash.merge(**)
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user