All queries return either an instance of this class, or in the case of a single result, the node found. Use this class to further define query parameters for multiple return sets.

Methods
Constants
EXPECTED_OPTIONS = [:name, :returns, :arguments, :access] unless defined?(EXPECTED_OPTIONS)
Public Instance methods
find(*options)

Find within this result set any nodes that match the given options. Options can be any or all of the following, based on the type of node (all entries can be either Strings or Symbols):

:name:The unmangled name of the node. Can be a string or Regexp. Works on all nodes.
:arguments:Search according to argument types. This needs to be an array of strings or symbols. nil is used as the wildcard. Only works on Functions, Methods, and Constructors
:returns:Search according to the return type. Can be a string or symbol. Only works on Functions and Methods
:access:Search according to access properties. Can be :public, :protected, or :private. Only works on Classes and Methods

All arguments added to the options are processed in an AND format. If you are looking for 3 random arguments with a return type of int:

  find(:arguments => [nil, nil, nil], :returns => :int)

It‘s also possible to do this in two steps, chaining the find calls, as long as each find in the chain has multiple results:

  find(:arguments => [nil, nil, nil]).find(:returns => :int)

However if you want 3 random arguments OR returning int, you should use two seperate queries:

  find(:arguments => [nil, nil, nil])
  find(:returns => :int)

Typedefs, user defined types, fundamental types (int, char, etc), pointers, and references are all supported. For example, to find functions that return a pointer to MyClass:

  find(:returns => "MyClass*")

There will be cases where you‘ll want to search all of a given type no matter what the current scope or nesting. To put a finder into this mode, specify :all as the first parameter:

  find(:all, [arguments as defined above])

This will find all nodes that fit the normal arguments for a given type (the node type of the first in the initial result set. e.g. if you run classes.find(:all) then all Class nodes) across the entire source.

Returns: A new QueryResult containing the results, allowing for nested finds. However, If there is only one result, returns that single Node instead.

     # File lib/rbgccxml/query_result.rb, line 69
 69:     def find(*options)
 70:       result = QueryResult.new
 71:       query_set = self
 72: 
 73:       if options[0] == :all
 74:         node_type = self[0].class.to_s.split(/::/)[-1]
 75:         query_set = NodeCache.all(node_type)
 76:         options = options[1]
 77:       else
 78:         options = options[0]
 79:       end
 80: 
 81:       name = options.delete(:name)
 82:       returns = options.delete(:returns)
 83:       arguments = options.delete(:arguments)
 84:       access = options.delete(:access)
 85: 
 86:       raise ":arguments must be an array" if arguments && !arguments.is_a?(Array)
 87:       raise "Unknown keys #{options.keys.join(", ")}. " +
 88:         "Expected are: #{EXPECTED_OPTIONS.join(",")}" unless options.empty?
 89: 
 90:       found = {}
 91: 
 92:       query_set.each do |node|
 93:         # C++ name
 94:         if name
 95:           found[:name] ||= []
 96:           found[:name] << node if matches?(node.name, name)
 97:         end
 98: 
 99:         # Return type
100:         if returns && [Function, Method].include?(node.class)
101:           found[:returns] ||= []
102:           found[:returns] << node if type_matches?(node.return_type, returns.to_s)
103:         end
104: 
105:         # Arguments list
106:         if arguments && [Function, Method, Constructor].include?(node.class)
107:           found[:arguments] ||= []
108:           keep = false
109:           args = node.arguments
110: 
111:           if args.size == arguments.size
112:             keep = true
113:             arguments.each_with_index do |arg, idx|
114:               # nil is the "any" flag
115:               if !arg.nil? && !type_matches?(args[idx].cpp_type, arg.to_s)
116:                 keep = false
117:                 break
118:               end
119:             end
120:           end
121: 
122:           found[:arguments] << node if keep
123:         end
124: 
125:         # Access type
126:         if access
127:           found[:access] ||= []
128:           found[:access] << node if node["access"] == access.to_s
129:         end
130:       end
131: 
132:       # Now we do an intersection of all the found nodes,
133:       # which ensures that we AND together all the parts
134:       # the user is looking for
135:       tmp = query_set
136:       found.each_value do |value|
137:         tmp = (tmp & value)
138:       end
139: 
140:       # But make sure that we always have a QueryResult and
141:       # not a plain Array
142:       result << tmp
143:       result.flatten!
144: 
145:       result.length == 1 ? result[0] : result
146:     end
find_all(&block)

Performs a normal Enumerable#find_all operation, except that if only one Node is being returned by the Enumerable#find_all, returns that single node.

     # File lib/rbgccxml/query_result.rb, line 151
151:     def find_all(&block)
152:       res = QueryResult.new(super)
153:       res.length == 1 ? res[0] : res
154:     end
method_missing(name, *args)

To facilitate the management of what could be many nodes found by a single query, we forward off any unknown methods to each node in the results query. We assume that if one node accepts the method, then all of them will.

    # File lib/rbgccxml/query_result.rb, line 10
10:     def method_missing(name, *args)
11:       if self[0].respond_to?(name)
12:         self.inject(QueryResult.new) do |memo, node|
13:           ret = node.send(name, *args)
14:           memo << ret if ret
15:           memo
16:         end
17:       else
18:         super
19:       end
20:     end
select(&block)

Same with find_all, force to work as a QueryResult

     # File lib/rbgccxml/query_result.rb, line 157
157:     def select(&block)
158:       res = QueryResult.new(super)
159:       res.length == 1 ? res[0] : res
160:     end