@@ -1025,46 +1025,43 @@ private module ParameterNodes {
1025
1025
* For example, in the following code:
1026
1026
*
1027
1027
* ```rb
1028
- * def foo(x, y); end
1028
+ * def foo(x, y, z ); end
1029
1029
*
1030
- * foo(*[ a, b ])
1030
+ * foo(a, *[b, c ])
1031
1031
* ```
1032
1032
*
1033
- * We want `a ` to flow to `x ` and `b ` to flow to `y `. We do this by constructing
1033
+ * We want `b ` to flow to `y ` and `c ` to flow to `z `. We do this by constructing
1034
1034
* a `SynthSplatParameterNode` for the method `foo`, and matching the splat argument to this
1035
1035
* parameter node via `parameterMatch/2`. We then add read steps from this node to parameters
1036
- * `x ` and `y `, for content at indices 0 and 1 respectively (see `readStep`).
1036
+ * `y ` and `z `, for content at indices 0 and 1 respectively (see `readStep`).
1037
1037
*
1038
- * We don't yet correctly handle cases where the splat argument is not the first argument, e.g. in
1039
- * ```rb
1040
- * foo(a, *[b])
1041
- * ```
1042
- *
1043
- * TODO: we do now support the above, but we don't support this case:
1038
+ * This node stores the index of the splat argument it is matched to, which allows us to shift
1039
+ * indices correctly when adding read steps. Without this, in the example above we would erroneously
1040
+ * get a read step to `x` and index 0 and `y` and index 1 etc.
1044
1041
*
1042
+ * We don't yet correctly handle cases where a positional argument follows the splat argument, e.g. in
1045
1043
* ```rb
1046
1044
* foo(a, *[b], c)
1047
1045
* ```
1048
- *
1049
- * Update this documentation.
1050
1046
*/
1051
1047
class SynthSplatParameterNode extends ParameterNodeImpl , TSynthSplatParameterNode {
1052
1048
private DataFlowCallable callable ;
1049
+ // The position of the splat argument that is matched to this node
1053
1050
private int n ;
1054
1051
1055
1052
SynthSplatParameterNode ( ) { this = TSynthSplatParameterNode ( callable , n ) }
1056
1053
1057
1054
/**
1058
- * Gets a parameter which will contain the value given by `c`, assuming
1059
- * that the method was called with a single splat argument.
1060
- * For example, if the synth splat parameter is for the following method
1055
+ * Gets a parameter which will contain the value given by `c`.
1056
+ * For example, if the synth splat parameter is for the following method and method call:
1061
1057
*
1062
1058
* ```rb
1063
- * def foo(x, y, a:, *rest)
1064
- * end
1059
+ * def foo(x, y, a:, *rest); end
1060
+ *
1061
+ * foo(arg1, *args)
1065
1062
* ```
1066
1063
*
1067
- * then `getAParameter(element 0) = x` and `getAParameter(element 1) = y`.
1064
+ * then `getAParameter(element 0) = y`.
1068
1065
*/
1069
1066
ParameterNode getAParameter ( ContentSet c ) {
1070
1067
exists ( int m |
0 commit comments