rbgccxml 0.8 → 0.9

Sign up to get free protection for your applications and to get access to all the features.
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