Class: GraphQL::Analysis::AST::QueryComplexity

Inherits:
Analyzer
  • Object
show all
Defined in:
lib/graphql/analysis/ast/query_complexity.rb

Direct Known Subclasses

MaxQueryComplexity

Defined Under Namespace

Modules: ComplexityMergeFunctions Classes: ScopedTypeComplexity

Instance Method Summary collapse

Methods inherited from Analyzer

#analyze?

Constructor Details

#initialize(query) ⇒ QueryComplexity

State for the query complexity calculation: - complexities_on_type holds complexity scores for each type in an IRep node



9
10
11
12
# File 'lib/graphql/analysis/ast/query_complexity.rb', line 9

def initialize(query)
  super
  @complexities_on_type_by_query = {}
end

Instance Method Details

#max_possible_complexityInteger

Returns:

  • (Integer)


93
94
95
96
97
98
99
100
# File 'lib/graphql/analysis/ast/query_complexity.rb', line 93

def max_possible_complexity
  @complexities_on_type_by_query.reduce(0) do |total, (query, complexities_on_type)|
    root_complexity = complexities_on_type.last
    # Use this entry point to calculate the total complexity
    total_complexity_for_query = ComplexityMergeFunctions.merged_max_complexity_for_scopes(query, [root_complexity.scoped_children])
    total + total_complexity_for_query
  end
end

#on_enter_field(node, parent, visitor) ⇒ Object



62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/graphql/analysis/ast/query_complexity.rb', line 62

def on_enter_field(node, parent, visitor)
  # We don't want to visit fragment definitions,
  # we'll visit them when we hit the spreads instead
  return if visitor.visiting_fragment_definition?
  return if visitor.skipping?
  parent_type = visitor.parent_type_definition
  field_key = node.alias || node.name
  # Find the complexity calculation for this field --
  # if we're re-entering a selection, we'll already have one.
  # Otherwise, make a new one and store it.
  #
  # `node` and `visitor.field_definition` may appear from a cache,
  # but I think that's ok. If the arguments _didn't_ match,
  # then the query would have been rejected as invalid.
  complexities_on_type = @complexities_on_type_by_query[visitor.query] ||= [ScopedTypeComplexity.new(nil, nil, query)]

  complexity = complexities_on_type.last.scoped_children[parent_type][field_key] ||= ScopedTypeComplexity.new(node, visitor.field_definition, visitor.query)
  # Push it on the stack.
  complexities_on_type.push(complexity)
end

#on_leave_field(node, parent, visitor) ⇒ Object



83
84
85
86
87
88
89
90
# File 'lib/graphql/analysis/ast/query_complexity.rb', line 83

def on_leave_field(node, parent, visitor)
  # We don't want to visit fragment definitions,
  # we'll visit them when we hit the spreads instead
  return if visitor.visiting_fragment_definition?
  return if visitor.skipping?
  complexities_on_type = @complexities_on_type_by_query[visitor.query]
  complexities_on_type.pop
end

#resultObject

Overide this method to use the complexity result



15
16
17
# File 'lib/graphql/analysis/ast/query_complexity.rb', line 15

def result
  max_possible_complexity
end