rbgccxml 0.8 → 0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. data/Rakefile +5 -5
  2. data/lib/rbgccxml/node.rb +75 -73
  3. data/lib/rbgccxml/nodes/argument.rb +13 -2
  4. data/lib/rbgccxml/nodes/base.rb +14 -0
  5. data/lib/rbgccxml/nodes/class.rb +46 -8
  6. data/lib/rbgccxml/nodes/constructor.rb +8 -1
  7. data/lib/rbgccxml/nodes/destructor.rb +7 -0
  8. data/lib/rbgccxml/nodes/enum_value.rb +6 -4
  9. data/lib/rbgccxml/nodes/enumeration.rb +21 -2
  10. data/lib/rbgccxml/nodes/field.rb +18 -0
  11. data/lib/rbgccxml/nodes/file.rb +4 -1
  12. data/lib/rbgccxml/nodes/function.rb +6 -4
  13. data/lib/rbgccxml/nodes/function_type.rb +7 -0
  14. data/lib/rbgccxml/nodes/method.rb +6 -4
  15. data/lib/rbgccxml/nodes/struct.rb +3 -2
  16. data/lib/rbgccxml/nodes/type.rb +5 -3
  17. data/lib/rbgccxml/nodes/types/array_type.rb +29 -0
  18. data/lib/rbgccxml/nodes/types/cv_qualified_type.rb +9 -5
  19. data/lib/rbgccxml/nodes/types/fundamental_type.rb +3 -2
  20. data/lib/rbgccxml/nodes/types/pointer_type.rb +6 -3
  21. data/lib/rbgccxml/nodes/types/reference_type.rb +6 -3
  22. data/lib/rbgccxml/nodes/types/typedef.rb +2 -2
  23. data/lib/rbgccxml/nodes/variable.rb +7 -0
  24. data/lib/rbgccxml/parser.rb +47 -32
  25. data/lib/rbgccxml/query_result.rb +62 -25
  26. data/lib/rbgccxml/rbgccxml.rb +13 -16
  27. data/lib/rbgccxml/xml_parsing.rb +65 -97
  28. data/lib/rbgccxml.rb +26 -22
  29. data/test/arguments_test.rb +29 -0
  30. data/test/classes_test.rb +164 -26
  31. data/test/enumerations_test.rb +27 -19
  32. data/test/function_pointers_test.rb +18 -0
  33. data/test/functions_test.rb +7 -2
  34. data/test/methods_test.rb +3 -3
  35. data/test/namespaces_test.rb +1 -1
  36. data/test/node_test.rb +11 -31
  37. data/test/parser_test.rb +1 -1
  38. data/test/query_results_test.rb +15 -14
  39. data/test/structs_test.rb +10 -12
  40. data/test/test_helper.rb +10 -2
  41. data/test/types_test.rb +63 -38
  42. data/test/variables_test.rb +26 -0
  43. metadata +46 -31
@@ -1,15 +1,18 @@
1
1
  module RbGCCXML
2
- # This represents a Pointer of any other kind of type
2
+
3
+ # Represents a <PointerType>, a node designating a pointer type to another Type.
3
4
  class PointerType < Type
4
5
 
5
6
  def ==(val)
6
7
  check_sub_type_without(val, /\*/)
7
8
  end
8
9
 
9
- def to_s(full = false)
10
+ # See Node#to_cpp
11
+ def to_cpp(qualified = true)
10
12
  type = XMLParsing.find_type_of(self.node, "type")
11
- "#{type.to_s(full)}*"
13
+ "#{type.to_cpp(qualified)}*"
12
14
  end
15
+
13
16
  end
14
17
 
15
18
  end
@@ -1,14 +1,17 @@
1
1
  module RbGCCXML
2
- # This deals with C++ Reference nodes (&)
2
+
3
+ # References a <ReferenceType> node, which is a reference to another Type.
3
4
  class ReferenceType < Type
4
5
 
5
6
  def ==(val)
6
7
  check_sub_type_without(val, /\&/)
7
8
  end
8
9
 
9
- def to_s(full = false)
10
+ def to_cpp(qualified = true)
10
11
  type = XMLParsing.find_type_of(self.node, "type")
11
- "#{type.to_s(full)}&"
12
+ "#{type.to_cpp(qualified)}&"
12
13
  end
14
+
13
15
  end
16
+
14
17
  end
@@ -1,6 +1,6 @@
1
1
  module RbGCCXML
2
- # This represents a Typedef, basically the renaming of one type to
3
- # another.
2
+
3
+ # Represents a <Typedef> node.
4
4
  class Typedef < Type
5
5
  end
6
6
 
@@ -0,0 +1,7 @@
1
+ module RbGCCXML
2
+
3
+ # Represents a <Variable> node, which is either a global variable or a Class constant.
4
+ class Variable < Node
5
+ end
6
+
7
+ end
@@ -1,4 +1,4 @@
1
- require 'tempfile'
1
+ require 'libxml'
2
2
 
3
3
  module RbGCCXML
4
4
 
@@ -6,48 +6,63 @@ module RbGCCXML
6
6
  # Please use RbGCCXML.parse and not this class directly
7
7
  class Parser
8
8
 
9
- def initialize(config = {})
10
- @gccxml = GCCXML.new
9
+ def initialize(config = {})
10
+ if config[:pregenerated]
11
+ @xml_file = config.delete[:pregenerated]
12
+ else
13
+ require 'gccxml'
14
+ @gccxml = GCCXML.new
11
15
 
12
- if includes = config.delete(:includes)
13
- @gccxml.add_include includes
14
- end
16
+ if includes = config.delete(:includes)
17
+ @gccxml.add_include includes
18
+ end
15
19
 
16
- if flags = config.delete(:cxxflags)
17
- @gccxml.add_cxxflags flags
18
- end
20
+ if flags = config.delete(:cxxflags)
21
+ @gccxml.add_cxxflags flags
22
+ end
19
23
 
20
- validate_glob(config[:files])
24
+ validate_glob(config[:files])
25
+ end
21
26
  end
22
27
 
23
- # Start the parsing process. This includes
24
- # 1. Creating a temp file for the resulting xml
25
- # 2. Finding all the files to run through gccxml
26
- # 3. If applicable, build another temp file and #include
27
- # the header files to ensure one pass into gccxml
28
+ # Starts the parsing process. If the parser was configured
29
+ # with one or more header files, this includes:
30
+ # 1. Creating a temp file for the resulting XML.
31
+ # 2. Finding all the files to run through GCC-XML.
32
+ # 3. If applicable (more than one header was specified),
33
+ # build another temp file and #include the header files
34
+ # to ensure one and only one pass into GCC-XML.
28
35
  # 4. Build up our :: Namespace node and pass that back
29
- # to the user for querying
36
+ # to the user for querying.
37
+ #
38
+ # If the parser was configured for pregenerated GCC-XML
39
+ # output, we only have to perform step 4 above.
30
40
  def parse
31
- @results_file = Tempfile.new("rbgccxml")
32
- parse_file = nil
33
-
34
- if @files.length == 1
35
- parse_file = @files[0]
41
+ if @gccxml
42
+ require 'tempfile'
43
+ @results_file = Tempfile.new("rbgccxml")
44
+ parse_file = nil
45
+
46
+ if @files.length == 1
47
+ parse_file = @files[0]
48
+ else
49
+ # Otherwise we need to build up a single header file
50
+ # that #include's all of the files in the list, and
51
+ # parse that out instead
52
+ parse_file = build_header_for(@files)
53
+ end
54
+
55
+ xml_file = @results_file.path
56
+ @gccxml.parse(parse_file, xml_file)
36
57
  else
37
- # Otherwise we need to build up a single header file
38
- # that #include's all of the files in the list, and
39
- # parse that out instead
40
- parse_file = build_header_for(@files)
58
+ xml_file = @xml_file
41
59
  end
42
60
 
43
- @gccxml.parse(parse_file, @results_file.path)
44
-
61
+ document = LibXML::XML::Document.file(xml_file)
62
+ root = document.root
45
63
  # Everything starts at the :: Namespace
46
- document = Hpricot.XML(@results_file)
47
- global_ns = document.search("//Namespace[@name='::']")[0]
48
-
64
+ global_ns = root.find("//Namespace[@name='::']")[0]
49
65
  XMLParsing.doc_root = document
50
-
51
66
  Namespace.new global_ns
52
67
  end
53
68
 
@@ -82,7 +97,7 @@ module RbGCCXML
82
97
  if found.empty?
83
98
  raise SourceNotFoundError.new(
84
99
  "Cannot find files matching #{files.inspect}. " +
85
- "You might need to specify a full path.")
100
+ "You might need to specify a full path.")
86
101
  end
87
102
 
88
103
  @files = found.select {|f| !::File.directory?(f) }
@@ -1,7 +1,7 @@
1
1
  module RbGCCXML
2
2
  # All queries return either an instance of this class, or in the case of
3
3
  # a single result, the node found. Use this class to further define query
4
- # parameters.
4
+ # parameters for multiple return sets.
5
5
  class QueryResult < Array
6
6
 
7
7
  # To facilitate the management of what could be many nodes found by a single query,
@@ -9,8 +9,10 @@ module RbGCCXML
9
9
  # We assume that if one node accepts the method, then all of them will.
10
10
  def method_missing(name, *args)
11
11
  if self[0].respond_to?(name)
12
- self.each do |node|
13
- node.send(name, *args)
12
+ self.inject(QueryResult.new) do |memo, node|
13
+ ret = node.send(name, *args)
14
+ memo << ret if ret
15
+ memo
14
16
  end
15
17
  else
16
18
  super
@@ -19,13 +21,14 @@ module RbGCCXML
19
21
 
20
22
  EXPECTED_OPTIONS = [:name, :returns, :arguments, :access] unless defined?(EXPECTED_OPTIONS)
21
23
 
22
- # Find within this result set any nodes that match the given options
23
- # Options can be any or all of the following, based on the type of node:
24
- #
24
+ # Find within this result set any nodes that match the given options.
25
+ # Options can be any or all of the following, based on the type of node
26
+ # (all entries can be either Strings or Symbols):
27
+ #
25
28
  # <tt>:name</tt>:: The unmangled name of the node. Can be a string or Regexp. Works on all nodes.
26
- # <tt>:arguments</tt>:: Search according to argument types.
27
- # This needs to be an array of strings or symbols. nil can be
28
- # used as a "any" flag. Only works on Functions, Methods, and Constructors
29
+ # <tt>:arguments</tt>:: Search according to argument types.
30
+ # This needs to be an array of strings or symbols. nil is used as the wildcard.
31
+ # Only works on Functions, Methods, and Constructors
29
32
  # <tt>:returns</tt>:: Search according to the return type. Can be a string or symbol.
30
33
  # Only works on Functions and Methods
31
34
  # <tt>:access</tt>:: Search according to access properties. Can be :public, :protected, or :private.
@@ -36,32 +39,32 @@ module RbGCCXML
36
39
  #
37
40
  # find(:arguments => [nil, nil, nil], :returns => :int)
38
41
  #
39
- # It's also possible to do this in two steps, chaining the +find+ calls, as long as
42
+ # It's also possible to do this in two steps, chaining the +find+ calls, as long as
40
43
  # each +find+ in the chain has multiple results:
41
44
  #
42
45
  # find(:arguments => [nil, nil, nil]).find(:returns => :int)
43
- #
44
- # However if you want 3 random arguments OR returning int, you should use
46
+ #
47
+ # However if you want 3 random arguments OR returning int, you should use
45
48
  # two seperate queries:
46
49
  #
47
50
  # find(:arguments => [nil, nil, nil])
48
51
  # find(:returns => :int)
49
52
  #
50
- # When dealing with how to specify the types, Typedefs, user defined types, fundamental
51
- # types (int, char, etc) and pointers to all of these are currently supported. To find
52
- # functions that return a pointer to MyClass:
53
+ # Typedefs, user defined types, fundamental types (int, char, etc), pointers, and references
54
+ # are all supported. For example, to find functions that return a pointer to MyClass:
53
55
  #
54
56
  # find(:returns => "MyClass*")
55
57
  #
56
- # There will be cases where you'll want to search *all* of a given type no matter what scope
57
- # or nesting exists. To put a finder into this mode, you simply send :all as the first parameter:
58
+ # There will be cases where you'll want to search *all* of a given type no matter what the current scope
59
+ # or nesting. To put a finder into this mode, specify :all as the first parameter:
58
60
  #
59
61
  # find(:all, [arguments as defined above])
60
62
  #
61
- # will find all nodes that fit the normal arguments for a given type (the node type of the first
62
- # in the initial result set. e.g. if you run <tt>classes.find(:all)</tt> then all Class nodes)
63
+ # This will find all nodes that fit the normal arguments for a given type (the node type of the first
64
+ # in the initial result set. e.g. if you run <tt>classes.find(:all)</tt> then all Class nodes) across
65
+ # the entire source.
63
66
  #
64
- # Returns: A new QueryResult containing the results, allowing for nested +finds+.
67
+ # Returns: A new QueryResult containing the results, allowing for nested +finds+.
65
68
  # However, If there is only one result, returns that single Node instead.
66
69
  def find(*options)
67
70
  result = QueryResult.new
@@ -69,7 +72,7 @@ module RbGCCXML
69
72
 
70
73
  if options[0] == :all
71
74
  node_type = self[0].class.to_s.split(/::/)[-1]
72
- query_set = XMLParsing.find_all(:type => node_type)
75
+ query_set = XMLParsing.find_all(:node_type => node_type)
73
76
  options = options[1]
74
77
  else
75
78
  options = options[0]
@@ -90,13 +93,13 @@ module RbGCCXML
90
93
  # C++ name
91
94
  if name
92
95
  found[:name] ||= []
93
- found[:name] << node if node == name
96
+ found[:name] << node if matches?(node.name, name)
94
97
  end
95
98
 
96
99
  # Return type
97
100
  if returns && [Function, Method].include?(node.class)
98
101
  found[:returns] ||= []
99
- found[:returns] << node if node.return_type == returns.to_s
102
+ found[:returns] << node if type_matches?(node.return_type, returns.to_s)
100
103
  end
101
104
 
102
105
  # Arguments list
@@ -109,7 +112,7 @@ module RbGCCXML
109
112
  keep = true
110
113
  arguments.each_with_index do |arg, idx|
111
114
  # nil is the "any" flag
112
- if !arg.nil? && args[idx].cpp_type != arg.to_s
115
+ if !arg.nil? && !type_matches?(args[idx].cpp_type, arg.to_s)
113
116
  keep = false
114
117
  break
115
118
  end
@@ -134,12 +137,46 @@ module RbGCCXML
134
137
  tmp = (tmp & value)
135
138
  end
136
139
 
137
- # But make sure that we always have a QueryResult and
140
+ # But make sure that we always have a QueryResult and
138
141
  # not a plain Array
139
142
  result << tmp
140
143
  result.flatten!
141
144
 
142
145
  result.length == 1 ? result[0] : result
143
146
  end
147
+
148
+ # Performs a normal Enumerable#find_all operation, except that if only
149
+ # one Node is being returned by the Enumerable#find_all, returns that
150
+ # single node.
151
+ def find_all(&block)
152
+ res = super
153
+ res.length == 1 ? res[0] : res
154
+ end
155
+
156
+ private
157
+
158
+ # Finders can take strings or regexes, so this wraps up the logic that chooses
159
+ # between straight equality matching and matching
160
+ def matches?(value, against)
161
+ case against
162
+ when Regexp
163
+ value =~ against
164
+ else
165
+ value == against
166
+ end
167
+ end
168
+
169
+ def type_matches?(node, against)
170
+ against_full =
171
+ against.is_a?(Regexp) ?
172
+ against :
173
+ /#{against.to_s.gsub("*", "\\*").gsub(/^::/, "").gsub("[", "\\[").gsub("]", "\\]")}$/
174
+
175
+ matches?(node.name, against) ||
176
+ matches?(node.to_cpp, against_full) ||
177
+ matches?(node.to_cpp(false), against_full)
178
+ end
179
+
180
+
144
181
  end
145
182
  end
@@ -3,15 +3,17 @@ module RbGCCXML
3
3
 
4
4
  class << self
5
5
 
6
- # This is where it all happens. This method must be called after any calls
7
- # to RbGCCXML.gccxml_path= or RbGCCXML.add_include_paths.
8
- # Files can be one of many formats (and should always be full directory paths):
6
+ # Starting point to any RbGCCXML parsing project.
7
+ #
8
+ # This method must be called *after* any calls to RbGCCXML.gccxml_path=
9
+ # or RbGCCXML.add_include_paths. Files can be one of many formats
10
+ # (and should always be full directory paths):
9
11
  #
10
12
  # <tt>"/path/to/file.h"</tt>
11
13
  #
12
14
  # <tt>"/dir/glob/**/*.h"</tt>
13
15
  #
14
- # An array of either of the above.
16
+ # or an array of either of the above.
15
17
  #
16
18
  # +options+ can be any of:
17
19
  #
@@ -19,24 +21,19 @@ module RbGCCXML
19
21
  # cxxflags: A single string, or an array of strings of other command line flags
20
22
  #
21
23
  # Returns the Namespace Node linked to the global namespace "::".
22
- #
23
24
  def parse(files, options = {})
24
- # Steps here:
25
- # 1. Find gccxml
26
- # 2. Find all files expected to be parsed
27
- # 3. If multiple files:
28
- # Build up a temp file with #includes to each file to be parsed
29
- # 4. If multiple files:
30
- # Run gccxml on this generated file
31
- # else
32
- # Run gccxml on the expected file
33
- # 5. Parse out XML into class tree
34
-
35
25
  options.merge!(:files => files)
36
26
  @parser = Parser.new options
37
27
  @parser.parse
38
28
  end
39
29
 
30
+ # Use this call to parse a pregenerated GCC-XML file.
31
+ #
32
+ # Returns the Namespace Node linked to the global namespace "::".
33
+ def parse_xml(filename)
34
+ @parser = Parser.new :pregenerated => filename
35
+ @parser.parse
36
+ end
40
37
  end
41
38
 
42
39
  class SourceNotFoundError < RuntimeError; end
@@ -1,44 +1,51 @@
1
1
  module RbGCCXML
2
2
 
3
- # A module of methods used to parse out the flat GCC-XML file into
3
+ # A module of methods used to parse out the flat GCC-XML xml structure into
4
4
  # a proper heirarchy. These methods are used internally and not intended
5
5
  # for outside use.
6
6
  module XMLParsing
7
7
 
8
- # I'm not sure if Hpricot is unable to jump back out to the document
9
- # root or if I just can't find how, but we give this module the
10
- # Hpricot document to do proper searching.
8
+ # Save a reference to the root node of the parsed XML
11
9
  def self.doc_root=(root)
12
10
  @@doc_root = root
11
+ self.clear_cache
12
+ end
13
+
14
+ # Clear the internal query cache
15
+ def self.clear_cache
16
+ @@find_query_cache = {}
17
+ @@all_query_cache = {}
13
18
  end
14
19
 
15
20
  # Generic finding of nodes according to attributes.
16
21
  # Special options:
17
22
  #
18
- # <tt>:type</tt>:: Specify a certain node type to search by
23
+ # <tt>:node_type</tt>:: Specify a certain node type to search by
19
24
  #
20
25
  # Any other options is directly mapped to attributes on the node. For example, to find
21
26
  # a Function node that have the name "functor":
22
27
  #
23
- # XMLParsing.find(:type => "Function", :name => "functor")
28
+ # XMLParsing.find(:node_type => "Function", :name => "functor")
24
29
  #
25
30
  # Returns the first found node
26
31
  def self.find(options = {})
27
32
  return nil if options.empty?
28
- type = options.delete(:type)
29
-
30
- # Look value up in the cache for common operations if a type was given
31
- if(type && options.length == 1 && options.keys[0] == :id)
32
- return cache(type, options[:id])
33
- end
34
33
 
35
- attrs = options.map {|key, value| "[@#{key}='#{value}']"}.join
36
- xpath = "//#{type}#{attrs}"
34
+ cache_key = options.to_s
35
+ cached = @@find_query_cache[cache_key]
36
+ return cached if cached
37
37
 
38
- got = @@doc_root.at(xpath)
38
+ type = options.delete(:node_type)
39
+
40
+ attrs = options.map {|key, value| "[@#{key}='#{value}']"}.join
41
+ xpath = "//#{type || '*'}#{attrs}"
42
+
43
+ got = @@doc_root.find(xpath).first
39
44
 
40
45
  if got
41
- RbGCCXML.const_get(type || got.name).new(got)
46
+ result = build_type(type || got.name, got)
47
+ @@find_query_cache[cache_key] = result
48
+ result
42
49
  else
43
50
  nil
44
51
  end
@@ -47,31 +54,36 @@ module RbGCCXML
47
54
  # Generic finding of nodes according to attributes.
48
55
  # Special options:
49
56
  #
50
- # <tt>:type</tt>:: Specify a certain node type to search by
57
+ # <tt>:node_type</tt>:: Specify a certain node type to search by
51
58
  #
52
59
  # Any other options is directly mapped to attributes on the node. For example, to find all
53
60
  # Function nodes:
54
61
  #
55
- # XMLParsing.find_all(:type => "Function")
62
+ # XMLParsing.find_all(:node_type => "Function")
56
63
  #
57
64
  # Returns all matching nodes
58
65
  def self.find_all(options = {})
59
- return nil if options.empty?
66
+ results = QueryResult.new
67
+ return results if options.empty?
68
+ cache_key = options.to_s
69
+
70
+ cached = @@all_query_cache[cache_key]
71
+ return cached if cached
60
72
 
61
- type = options.delete(:type)
73
+ type = options.delete(:node_type)
62
74
  attrs = options.map {|key, value| "[@#{key}='#{value}']"}.join
63
75
 
64
76
  xpath = "//#{type}#{attrs}"
65
77
 
66
- results = @@doc_root.search(xpath)
78
+ found = @@doc_root.find(xpath)
67
79
 
68
- if results
69
- results.collect do |got|
70
- RbGCCXML.const_get(type || got.name).new(got)
80
+ if found
81
+ found.each do |got|
82
+ results << build_type(type || got.name, got)
71
83
  end
72
- else
73
- nil
84
+ @@all_query_cache[cache_key] = results
74
85
  end
86
+ results
75
87
  end
76
88
 
77
89
  # Look through the DOM under +node+ for +node_type+ nodes.
@@ -79,18 +91,7 @@ module RbGCCXML
79
91
  #
80
92
  # Returns a QueryResult with the findings.
81
93
  def self.find_nested_nodes_of_type(node, node_type)
82
- results = QueryResult.new
83
-
84
- # First of all limit which elements we're searching for, to ease processing.
85
- # In the GCCXML output, node heirarchy is designated by id, members, and context
86
- # attributes:
87
- #
88
- # id => Unique identifier of a given node
89
- # members => Space-delimited array of node id's that are under this node
90
- # context => The parent node id of this node
91
- #
92
- # We only want those nodes in node's context.
93
- return nested_cache(node_type, node.attributes["id"]).flatten
94
+ self.find_all(:node_type => node_type, :context => node.attributes["id"])
94
95
  end
95
96
 
96
97
  # Arguments are a special case in gccxml as they are actual children of
@@ -99,6 +100,19 @@ module RbGCCXML
99
100
  get_children_nodes_of_type(node, "Argument")
100
101
  end
101
102
 
103
+ # Classes / Structs can have superclasses. This method finds the
104
+ # classes that are those superclasses according to the access type
105
+ # passed in (nil means find all of them)
106
+ def self.find_bases_for(node, access_type = nil)
107
+ bases = get_children_nodes_of_type(node, "Base")
108
+
109
+ if access_type
110
+ bases = bases.select {|b| b.attributes["access"] == access_type.to_s }
111
+ end
112
+
113
+ bases.map {|b| b.cpp_type }
114
+ end
115
+
102
116
  # Enumeration values are children of the Enumeration element
103
117
  def self.get_values_of(enum)
104
118
  get_children_nodes_of_type(enum.node, "EnumValue")
@@ -109,76 +123,30 @@ module RbGCCXML
109
123
  def self.get_children_nodes_of_type(node, type)
110
124
  results = QueryResult.new
111
125
 
112
- node.get_elements_by_tag_name(type).each do |found|
113
- results << RbGCCXML.const_get(type).new(found)
126
+ node.children.each do |found|
127
+ next unless found.element?
128
+ results << build_type(type, found)
114
129
  end
115
130
 
116
131
  results.flatten
117
132
  end
118
133
 
119
- # Entrance into the type management. Given a GCCXML node and an attribute
134
+ # Entrance into the type management. Given a GCC-XML node and an attribute
120
135
  # to reference, find the C++ type related. For example, finding the return
121
136
  # type of a function:
122
137
  #
123
138
  # +find_type_of(func_node, "returns")+ could return "std::string" node, "int" node, etc
124
- def self.find_type_of(node, attribute)
125
- id = node.attributes[attribute]
126
- %w( PointerType ReferenceType FundamentalType Typedef Enumeration CvQualifiedType Class Struct ).each do |type|
127
- return cache(type, id) if cache(type, id)
128
- end
129
- return nil
130
- end
131
-
132
- #
133
- # Returns the element in cache for type at id.
134
- # Used internally.
135
- #
136
- def self.cache(type, id)
137
- @@types_cache ||= {}
138
- @@types_cache[type] ||= {}
139
- build_cache(type) if @@types_cache[type].empty?
140
- return @@types_cache[type][id]
141
- end
142
-
143
- #
144
- # Creates a cache to work off of.
145
- # Used internally
146
- #
147
- def self.build_cache(type)
148
- XMLParsing.find_all(:type => type).each do |result|
149
- @@types_cache[type][result.attributes["id"]] = result
150
- end
151
- end
152
-
153
- #
154
- # Returns the element in cache for type at id
155
- # Used internally
156
139
  #
157
- def self.nested_cache(type, context)
158
- @@nested_cache ||= {}
159
- @@nested_cache[type] ||= {}
160
- build_nested_cache(type) if @@nested_cache[type].empty?
161
- return @@nested_cache[type][context] || QueryResult.new
140
+ def self.find_type_of(node, attr)
141
+ self.find(:id => node.attributes[attr])
162
142
  end
163
-
164
- #
165
- # Creates a nested cache to work off of.
166
- # Used internally
167
- #
168
- def self.build_nested_cache(type)
169
- XMLParsing.find_all(:type => type).each do |result|
170
- @@nested_cache[type][result.attributes["context"]] ||= QueryResult.new
171
- @@nested_cache[type][result.attributes["context"]] << result
172
- end
173
- end
174
-
175
-
176
- #
177
- # Clears the cache. Use this if you are querying two seperate libraries.
178
- #
179
- def self.clear_cache
180
- @@nested_cache = nil
181
- @@types_cache = nil
143
+
144
+ private
145
+
146
+ # Builds up the related RbGCCXML node according to the GCC-XML node found
147
+ # for a given query.
148
+ def self.build_type(type_name, node)
149
+ RbGCCXML.const_get(type_name).new(node)
182
150
  end
183
151
  end
184
152
  end