@@ -267,6 +267,29 @@ class GraphqlFieldDefinitionMethodCall extends GraphqlSchemaObjectClassMethodCal
267267 }
268268}
269269
270+ /**
271+ * A call to `argument` in a GraphQL InputObject class.
272+ */
273+ class GraphqlInputObjectArgumentDefinitionCall extends DataFlow:: CallNode {
274+ GraphqlInputObjectArgumentDefinitionCall ( ) {
275+ this =
276+ graphQlSchema ( )
277+ .getMember ( "InputObject" )
278+ .getADescendentModule ( )
279+ .getAnOwnModuleSelf ( )
280+ .getAMethodCall ( )
281+ }
282+
283+ /** Gets the name of the argument (i.e. the first argument to this `argument` method call) */
284+ string getArgumentName ( ) { result = this .getArgument ( 0 ) .getConstantValue ( ) .getStringlikeValue ( ) }
285+
286+ /** Gets the type of this argument */
287+ GraphqlType getArgumentType ( ) { result = this .getArgument ( 1 ) .asExpr ( ) .getExpr ( ) }
288+
289+ /** Gets the class representing the receiver of this method. */
290+ ClassDeclaration getReceiverClass ( ) { result = this .asExpr ( ) .getExpr ( ) .getEnclosingModule ( ) }
291+ }
292+
270293/**
271294 * A `MethodCall` that represents calling the class method `argument` inside the
272295 * block for a `field` definition on a GraphQL object.
@@ -313,19 +336,23 @@ private class GraphqlType extends ConstantAccess {
313336 Module getModule ( ) { result .getAnImmediateReference ( ) = this }
314337
315338 /**
316- * Gets a field of this type, if it is an object type.
339+ * Gets the type of a field/argument of this type, if it is an object type.
317340 */
318- GraphqlType getAField ( ) { result = this .getField ( _) }
341+ GraphqlType getAFieldOrArgument ( ) { result = this .getFieldOrArgument ( _) }
319342
320343 /**
321- * Gets the field of this type named `name`, if it exists.
344+ * Gets the type of the `name` field/argument of this type , if it exists.
322345 */
323- GraphqlType getField ( string name ) {
346+ GraphqlType getFieldOrArgument ( string name ) {
324347 result =
325348 any ( GraphqlFieldDefinitionMethodCall field |
326349 field .getFieldName ( ) = name and
327350 this .getModule ( ) .getADeclaration ( ) = field .getReceiverClass ( )
328- ) .getFieldType ( )
351+ ) .getFieldType ( ) or
352+ result =
353+ any ( GraphqlInputObjectArgumentDefinitionCall arg |
354+ arg .getArgumentName ( ) = name and this .getModule ( ) .getADeclaration ( ) = arg .getReceiverClass ( )
355+ ) .getArgumentType ( )
329356 }
330357
331358 /**
@@ -344,7 +371,7 @@ private class GraphqlType extends ConstantAccess {
344371 /**
345372 * Holds if this type is scalar - i.e. it is neither an object or an enum.
346373 */
347- predicate isScalar ( ) { not exists ( this .getAField ( ) ) and not this .isEnum ( ) }
374+ predicate isScalar ( ) { not exists ( this .getAFieldOrArgument ( ) ) and not this .isEnum ( ) }
348375}
349376
350377/**
@@ -440,34 +467,35 @@ private DataFlow::CallNode hashAccess(DataFlow::Node recv, string key) {
440467}
441468
442469private DataFlow:: CallNode parameterAccess (
443- GraphqlFieldResolutionMethod method , GraphqlFieldArgumentDefinitionMethodCall def ,
444- HashSplatParameter param , string key , GraphqlType type
470+ GraphqlFieldResolutionMethod method , HashSplatParameter param , GraphqlType type
445471) {
446- param = method .getAParameter ( ) and
447- def = method .getDefinition ( ) .getAnArgumentCall ( ) and
448- (
449- // Direct access to the params hash
450- def .getArgumentType ( ) = type and
451- def .getArgumentName ( ) = key and
452- exists ( DataFlow:: Node paramRead |
453- paramRead .asExpr ( ) .getExpr ( ) = param .getVariable ( ) .getAnAccess ( ) .( VariableReadAccess ) and
454- result = hashAccess ( paramRead , key )
455- )
456- or
457- // Nested access
458- exists ( GraphqlType type2 |
459- parameterAccess ( method , _, param , _, type2 )
460- .( DataFlow:: LocalSourceNode )
461- .flowsTo ( result .getReceiver ( ) ) and
462- result = hashAccess ( _, key ) and
463- type2 .getField ( key ) = type
472+ exists ( GraphqlFieldArgumentDefinitionMethodCall def , string key |
473+ param = method .getAParameter ( ) and
474+ def = method .getDefinition ( ) .getAnArgumentCall ( ) and
475+ (
476+ // Direct access to the params hash
477+ def .getArgumentType ( ) = type and
478+ def .getArgumentName ( ) = key and
479+ exists ( DataFlow:: Node paramRead |
480+ paramRead .asExpr ( ) .getExpr ( ) = param .getVariable ( ) .getAnAccess ( ) .( VariableReadAccess ) and
481+ result = hashAccess ( paramRead , key )
482+ )
483+ or
484+ // Nested access
485+ exists ( GraphqlType type2 |
486+ parameterAccess ( method , param , type2 )
487+ .( DataFlow:: LocalSourceNode )
488+ .flowsTo ( result .getReceiver ( ) ) and
489+ result = hashAccess ( _, key ) and
490+ type2 .getFieldOrArgument ( key ) = type
491+ )
464492 )
465493 )
466494}
467495
468496private class GraphqlParameterAccess extends RemoteFlowSource:: Range {
469497 GraphqlParameterAccess ( ) {
470- exists ( GraphqlType type | this = parameterAccess ( _, _, _ , _ , type ) and type .isScalar ( ) )
498+ exists ( GraphqlType type | this = parameterAccess ( _, _, type ) and type .isScalar ( ) )
471499 }
472500
473501 override string getSourceType ( ) { result = "GraphQL" }
0 commit comments