@@ -150,22 +150,14 @@ module Rbi {
150150 class ProcCall extends RbiType , SignatureCall , MethodCallAgainstT {
151151 ProcCall ( ) { this .getMethodName ( ) = "proc" }
152152
153- private ProcReturnsTypeCall getReturnsTypeCall ( ) { result . getProcCall ( ) = this }
154-
155- private ProcParamsCall getParamsCall ( ) { result . getProcCall ( ) = this }
153+ override ReturnsTypeCall getReturnsTypeCall ( ) {
154+ result . ( ProcReturnsTypeCall ) . getProcCall ( ) = this
155+ }
156156
157- /**
158- * Gets the return type of this type signature.
159- */
160- override ReturnType getReturnType ( ) { result = this .getReturnsTypeCall ( ) .getReturnType ( ) }
157+ override ProcParamsCall getParamsCall ( ) { result .getProcCall ( ) = this }
161158
162- /**
163- * Gets the type of a parameter of this type signature.
164- */
165- override ParameterType getAParameterType ( ) {
166- result = this .getParamsCall ( ) .getAParameterType ( )
167- }
168- // TODO: get associated method to which this can be passed
159+ // TODO: widen type for procs/blocks
160+ override MethodBase getAssociatedMethod ( ) { none ( ) }
169161 }
170162 }
171163
@@ -207,15 +199,11 @@ module Rbi {
207199 * A call that defines a type signature for a method or proc.
208200 */
209201 abstract class SignatureCall extends MethodCall {
210- /**
211- * Gets the return type of this type signature.
212- */
213- abstract ReturnType getReturnType ( ) ;
202+ abstract ParamsCall getParamsCall ( ) ;
214203
215- /**
216- * Gets the type of a parameter of this type signature.
217- */
218- abstract ParameterType getAParameterType ( ) ;
204+ abstract ReturnsTypeCall getReturnsTypeCall ( ) ;
205+
206+ abstract MethodBase getAssociatedMethod ( ) ;
219207 }
220208
221209 private predicate isMethodSignatureCallNode ( CfgNode n ) {
@@ -240,20 +228,35 @@ module Rbi {
240228 )
241229 }
242230
231+ /**
232+ * A call to a method named `attr_reader` or `attr_accessor`, used to define
233+ * attribute reader methods for a named attribute.
234+ */
235+ class AttrReaderMethodCall extends MethodCall {
236+ AttrReaderMethodCall ( ) { this .getMethodName ( ) = [ "attr_reader" , "attr_accessor" ] }
237+
238+ /** Gets a name of an attribute defined by this call. */
239+ string getAnAttributeName ( ) {
240+ result = this .getAnArgument ( ) .getConstantValue ( ) .getStringlikeValue ( )
241+ }
242+ }
243+
243244 /** A call to `sig` to define the type signature of a method. */
244245 class MethodSignatureCall extends SignatureCall {
245246 MethodSignatureCall ( ) { this .getMethodName ( ) = "sig" }
246247
247- private MethodReturnsTypeCall getReturnsTypeCall ( ) { result .getMethodSignatureCall ( ) = this }
248+ override ReturnsTypeCall getReturnsTypeCall ( ) {
249+ result .( MethodReturnsTypeCall ) .getMethodSignatureCall ( ) = this
250+ }
248251
249- private MethodParamsCall getParamsCall ( ) { result .getMethodSignatureCall ( ) = this }
252+ override MethodParamsCall getParamsCall ( ) { result .getMethodSignatureCall ( ) = this }
250253
251254 private ExprCfgNode getCfgNode ( ) { result .getExpr ( ) = this }
252255
253256 /**
254257 * Gets the method whose type signature is defined by this call.
255258 */
256- MethodBase getAssociatedMethod ( ) {
259+ override MethodBase getAssociatedMethod ( ) {
257260 result =
258261 min ( ExprCfgNode methodCfgNode , int i |
259262 methodSignatureSuccessorNodeRanked ( this .getCfgNode ( ) , methodCfgNode , i ) and
@@ -267,10 +270,10 @@ module Rbi {
267270 * Gets a call to `attr_reader` or `attr_accessor` where the return type of
268271 * the generated method is described by this call.
269272 */
270- MethodCall getAssociatedAttrReaderCall ( ) {
273+ AttrReaderMethodCall getAssociatedAttrReaderCall ( ) {
271274 result =
272275 min ( ExprNodes:: MethodCallCfgNode c , int i |
273- c .getExpr ( ) . getMethodName ( ) = [ "attr_reader" , "attr_accessor" ] and
276+ c .getExpr ( ) instanceof AttrReaderMethodCall and
274277 methodSignatureSuccessorNodeRanked ( this .getCfgNode ( ) , c , i )
275278 |
276279 c order by i
@@ -280,12 +283,7 @@ module Rbi {
280283 /**
281284 * Gets the return type of this type signature.
282285 */
283- override ReturnType getReturnType ( ) { result = this .getReturnsTypeCall ( ) .getReturnType ( ) }
284-
285- /**
286- * Gets the type of a parameter of this type signature.
287- */
288- override ParameterType getAParameterType ( ) { result = this .getParamsCall ( ) .getAParameterType ( ) }
286+ ReturnType getReturnType ( ) { result = this .getReturnsTypeCall ( ) .getReturnType ( ) }
289287 }
290288
291289 /**
@@ -313,19 +311,64 @@ module Rbi {
313311 MethodSignatureCall getMethodSignatureCall ( ) { result = sigCall }
314312 }
315313
314+ bindingset [ paramName]
315+ private predicate isBlockParamName ( string paramName ) { paramName = [ "blk" , "block" ] }
316+
316317 /**
317318 * A call to `params`. This defines the types of parameters to a method or proc.
318319 */
319320 class ParamsCall extends MethodCall {
320321 ParamsCall ( ) { this .getMethodName ( ) = "params" }
321322
322323 /**
323- * Gets the type of a parameter defined by this call.
324+ * Gets the type of a positional parameter defined by this call.
324325 */
325- ParameterType getAParameterType ( ) { result = this .getArgument ( _) }
326+ ParameterType getPositionalParameterType ( int i ) {
327+ result = this .getArgument ( i ) and
328+ // explicitly exclude keyword parameters
329+ not this .getAssociatedParameter ( result .getName ( ) ) instanceof KeywordParameter and
330+ // and exclude block arguments
331+ not isBlockParamName ( result .getName ( ) )
332+ }
333+
334+ /** Gets the type of the keyword parameter named `keyword`. */
335+ ParameterType getKeywordParameterType ( string keyword ) {
336+ exists ( KeywordParameter kp |
337+ kp = this .getAssociatedParameter ( keyword ) and
338+ kp .getName ( ) = keyword and
339+ result .getType ( ) = this .getKeywordArgument ( keyword )
340+ )
341+ }
342+
343+ /** Gets the type of the block parameter to the associated method. */
344+ ParameterType getBlockParameterType ( ) {
345+ isBlockParamName ( result .getName ( ) ) and
346+ result = this .getArgument ( _)
347+ }
348+
349+ /** Gets the parameter with the given name. */
350+ NamedParameter getAssociatedParameter ( string name ) {
351+ result = this .getSignatureCall ( ) .getAssociatedMethod ( ) .getAParameter ( ) and
352+ result .getName ( ) = name
353+ }
354+
355+ /** Gets the signature call which this params call belongs to. */
356+ SignatureCall getSignatureCall ( ) { this = result .getParamsCall ( ) }
357+
358+ /** Gets a parameter type associated with this call */
359+ ParameterType getAParameterType ( ) {
360+ result = this .getPositionalParameterType ( _) or
361+ result = this .getKeywordParameterType ( _) or
362+ result = this .getBlockParameterType ( )
363+ }
326364 }
327365
366+ /**
367+ * A call that defines a return type for an associated method.
368+ * The return type is either a specific type, or the void type (i.e. "don't care").
369+ */
328370 abstract class ReturnsTypeCall extends MethodCall {
371+ /** Get the `ReturnType` corresponding to this call. */
329372 abstract ReturnType getReturnType ( ) ;
330373 }
331374
@@ -391,6 +434,7 @@ module Rbi {
391434 abstract class ProcReturnsTypeCall extends ReturnsTypeCall , ProcSignatureDefiningCall { }
392435
393436 /** A call that defines the parameter types of a proc or block. */
437+ // TODO: there is currently no way to map from this to parameter types with actual associated parameters
394438 class ProcParamsCall extends ParamsCall , ProcSignatureDefiningCall { }
395439
396440 /** A call that defines the return type of a non-void proc or block. */
@@ -408,25 +452,30 @@ module Rbi {
408452
409453 /**
410454 * A pair defining the type of a parameter to a method.
455+ *
456+ * This is an argument to some call to `params`.
411457 */
412458 class ParameterType extends Pair {
413- private RbiType t ;
459+ private ParamsCall paramsCall ;
414460
415- ParameterType ( ) { t = this . getValue ( ) }
461+ ParameterType ( ) { paramsCall . getAnArgument ( ) = this }
416462
417- /** Gets the `RbiType` of this parameter. */
418- RbiType getType ( ) { result = t }
419-
420- private SignatureCall getOuterMethodSignatureCall ( ) { this = result .getAParameterType ( ) }
463+ private SignatureCall getMethodSignatureCall ( ) { paramsCall = result .getParamsCall ( ) }
421464
422465 private MethodBase getAssociatedMethod ( ) {
423- result = this .getOuterMethodSignatureCall ( ) .( MethodSignatureCall ) .getAssociatedMethod ( )
466+ result = this .getMethodSignatureCall ( ) .( MethodSignatureCall ) .getAssociatedMethod ( )
424467 }
425468
426- /** Gets the parameter to which this type applies. */
469+ /** Gets the `RbiType` of this parameter. */
470+ RbiType getType ( ) { result = this .getValue ( ) }
471+
472+ /** Gets the name of this parameter. */
473+ string getName ( ) { result = this .getKey ( ) .getConstantValue ( ) .getStringlikeValue ( ) }
474+
475+ /** Gets the `NamedParameter` to which this type applies. */
427476 NamedParameter getParameter ( ) {
428477 result = this .getAssociatedMethod ( ) .getAParameter ( ) and
429- result .getName ( ) = this .getKey ( ) . getConstantValue ( ) . getStringlikeValue ( )
478+ result .getName ( ) = this .getName ( )
430479 }
431480 }
432481}
0 commit comments