Ruby: Remove SynthSplatArgParameterNode

This commit is contained in:
Tom Hvitved
2023-09-08 13:20:26 +02:00
committed by Harry Maclean
parent 5a6a52b767
commit e11a4b63e9
6 changed files with 279 additions and 869 deletions

View File

@@ -473,7 +473,6 @@ private module Cached {
exists(Parameter p | p.getPosition() = pos and p instanceof SplatParameter)
} or
TSynthSplatParameterPosition() or
TSynthArgSplatParameterPosition() or
TAnyParameterPosition() or
TAnyKeywordParameterPosition()
}
@@ -1303,9 +1302,6 @@ class ParameterPosition extends TParameterPosition {
predicate isSynthSplat() { this = TSynthSplatParameterPosition() }
// A fake position to indicate that this parameter node holds content from a synth arg splat node
predicate isSynthArgSplat() { this = TSynthArgSplatParameterPosition() }
predicate isSplat(int n) { this = TSplatParameterPosition(n) }
/**
@@ -1341,8 +1337,6 @@ class ParameterPosition extends TParameterPosition {
or
this.isSynthSplat() and result = "synthetic *"
or
this.isSynthArgSplat() and result = "synthetic * (from *args)"
or
exists(int pos | this.isSplat(pos) and result = "* (position " + pos + ")")
}
}
@@ -1442,11 +1436,8 @@ predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos) {
or
ppos.isSplat(0) and apos.isSynthSplat()
or
ppos.isSynthSplat() and apos.isSynthSplat()
or
ppos.isSynthSplat() and apos.isSplat(0)
or
apos.isSynthSplat() and ppos.isSynthArgSplat()
ppos.isSynthSplat() and
(apos.isSynthSplat() or apos.isSplat(0))
or
// Exact splat match
exists(int n | apos.isSplat(n) and ppos.isSplat(n))

View File

@@ -452,9 +452,6 @@ private module Cached {
exists(c.asCallable()) and // exclude library callables
isParameterNode(_, c, any(ParameterPosition p | p.isPositional(_)))
} or
TSynthSplatArgParameterNode(DataFlowCallable c) {
exists(c.asCallable()) // exclude library callables
} or
TSynthSplatParameterElementNode(DataFlowCallable c, int n) {
exists(c.asCallable()) and // exclude library callables
isParameterNode(_, c, any(ParameterPosition p | p.isSplat(_))) and
@@ -486,7 +483,7 @@ private module Cached {
class TSourceParameterNode =
TNormalParameterNode or TBlockParameterNode or TSelfParameterNode or
TSynthHashSplatParameterNode or TSynthSplatParameterNode or TSynthSplatArgParameterNode;
TSynthHashSplatParameterNode or TSynthSplatParameterNode;
cached
Location getLocation(NodeImpl n) { result = n.getLocationImpl() }
@@ -694,8 +691,6 @@ predicate nodeIsHidden(Node n) {
or
n instanceof SynthSplatArgumentNode
or
n instanceof SynthSplatArgParameterNode
or
n instanceof SynthSplatParameterElementNode
or
n instanceof LambdaSelfReferenceNode
@@ -1087,31 +1082,6 @@ private module ParameterNodes {
final override string toStringImpl() { result = "synthetic *args" }
}
/**
* A node that holds all positional arguments passed in a call to `c`.
* This is a mirror of the `SynthSplatArgumentNode` on the callable side.
* See `SynthSplatArgumentNode` for more information.
*/
class SynthSplatArgParameterNode extends ParameterNodeImpl, TSynthSplatArgParameterNode {
private DataFlowCallable callable;
SynthSplatArgParameterNode() { this = TSynthSplatArgParameterNode(callable) }
final override Parameter getParameter() { none() }
final override predicate isParameterOf(DataFlowCallable c, ParameterPosition pos) {
c = callable and pos.isSynthArgSplat()
}
final override CfgScope getCfgScope() { result = callable.asCallable() }
final override DataFlowCallable getEnclosingCallable() { result = callable }
final override Location getLocationImpl() { result = callable.getLocation() }
final override string toStringImpl() { result = "synthetic *args" }
}
/**
* A node that holds the content of a specific positional argument.
* See `SynthSplatArgumentNode` for more information.
@@ -1285,9 +1255,9 @@ module ArgumentNodes {
*
* 1. We want `3` to flow to `z[0]` and `4` to flow to `z[1]`. We model this by first storing all arguments
* in a synthetic argument node `SynthSplatArgumentNode` (see `storeStepCommon`).
* 2. We match this to an analogous parameter node `SynthSplatArgParameterNode` on the callee side
* 2. We match this to an analogous parameter node `SynthSplatParameterNode` on the callee side
* (see `parameterMatch`).
* 3. For each content element stored in the `SynthSplatArgParameterNode`, we add a read step to a separate
* 3. For each content element stored in the `SynthSplatParameterNode`, we add a read step to a separate
* `SynthSplatParameterElementNode`, which is parameterized by the element index (see `readStep`).
* 4. Finally, we add store steps from these `SynthSplatParameterElementNode`s to the real splat parameter node
* (see `storeStep`).
@@ -1638,12 +1608,12 @@ predicate readStepCommon(Node node1, ContentSet c, Node node2) {
// TODO: convert into the above form
synthSplatArgumentElementReadStep(node1, c, node2)
or
// read from SynthSplatArgParameterNode[n] to nth positional parameter
exists(SynthSplatArgParameterNode argParamNode, NormalParameterNode posNode, int n |
argParamNode = node1 and
// read from SynthSplatParameterNode[n] to nth positional parameter
exists(SynthSplatParameterNode paramNode, NormalParameterNode posNode, int n |
paramNode = node1 and
posNode = node2 and
posNode
.isParameterOf(argParamNode.getEnclosingCallable(),
.isParameterOf(paramNode.getEnclosingCallable(),
any(ParameterPosition p | p.isPositional(n))) and
c = getPositionalContent(n)
)
@@ -1655,6 +1625,7 @@ predicate synthSplatArgumentElementReadStep(
) {
exists(int splatPos, CfgNodes::ExprNodes::CallCfgNode call |
node1.asExpr().(Argument).isArgumentOf(call, any(ArgumentPosition p | p.isSplat(splatPos))) and
splatPos > 0 and
node2.getCall() = call and
(
exists(int n |
@@ -1698,17 +1669,9 @@ predicate readStep(Node node1, ContentSet c, Node node2) {
FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), c,
node2.(FlowSummaryNode).getSummaryNode())
or
// Read from SynthSplatArgParameterNode into SynthSplatParameterElementNode
node2 =
any(SynthSplatParameterElementNode e |
node1.(SynthSplatArgParameterNode).isParameterOf(e.getEnclosingCallable(), _) and
c = getPositionalContent(e.getReadPosition())
)
or
VariableCapture::readStep(node1, any(Content::CapturedVariableContent v | c.isSingleton(v)), node2)
or
// Read from SynthSplatParameterNode into SynthSplatParameterElementNode
// This models flow from elements in a splat argument to elements in a splat parameter, where there are preceding positional parameters.
node2 =
any(SynthSplatParameterElementNode e |
node1.(SynthSplatParameterNode).isParameterOf(e.getEnclosingCallable(), _) and

View File

@@ -334,9 +334,7 @@ predicate readStoreStepIntoSourceNode(
Node nodeFrom, Node nodeTo, DataFlow::ContentSet loadContent, DataFlow::ContentSet storeContent
) {
exists(DataFlowPrivate::SynthSplatParameterElementNode mid |
nodeFrom
.(DataFlowPrivate::SynthSplatArgParameterNode)
.isParameterOf(mid.getEnclosingCallable(), _) and
nodeFrom.(DataFlowPrivate::SynthSplatParameterNode).isParameterOf(mid.getEnclosingCallable(), _) and
loadContent = DataFlowPrivate::getPositionalContent(mid.getReadPosition()) and
nodeTo = mid.getSplatParameterNode(_) and
storeContent = DataFlowPrivate::getPositionalContent(mid.getStorePosition())