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.
- data/Rakefile +5 -5
- data/lib/rbgccxml/node.rb +75 -73
- data/lib/rbgccxml/nodes/argument.rb +13 -2
- data/lib/rbgccxml/nodes/base.rb +14 -0
- data/lib/rbgccxml/nodes/class.rb +46 -8
- data/lib/rbgccxml/nodes/constructor.rb +8 -1
- data/lib/rbgccxml/nodes/destructor.rb +7 -0
- data/lib/rbgccxml/nodes/enum_value.rb +6 -4
- data/lib/rbgccxml/nodes/enumeration.rb +21 -2
- data/lib/rbgccxml/nodes/field.rb +18 -0
- data/lib/rbgccxml/nodes/file.rb +4 -1
- data/lib/rbgccxml/nodes/function.rb +6 -4
- data/lib/rbgccxml/nodes/function_type.rb +7 -0
- data/lib/rbgccxml/nodes/method.rb +6 -4
- data/lib/rbgccxml/nodes/struct.rb +3 -2
- data/lib/rbgccxml/nodes/type.rb +5 -3
- data/lib/rbgccxml/nodes/types/array_type.rb +29 -0
- data/lib/rbgccxml/nodes/types/cv_qualified_type.rb +9 -5
- data/lib/rbgccxml/nodes/types/fundamental_type.rb +3 -2
- data/lib/rbgccxml/nodes/types/pointer_type.rb +6 -3
- data/lib/rbgccxml/nodes/types/reference_type.rb +6 -3
- data/lib/rbgccxml/nodes/types/typedef.rb +2 -2
- data/lib/rbgccxml/nodes/variable.rb +7 -0
- data/lib/rbgccxml/parser.rb +47 -32
- data/lib/rbgccxml/query_result.rb +62 -25
- data/lib/rbgccxml/rbgccxml.rb +13 -16
- data/lib/rbgccxml/xml_parsing.rb +65 -97
- data/lib/rbgccxml.rb +26 -22
- data/test/arguments_test.rb +29 -0
- data/test/classes_test.rb +164 -26
- data/test/enumerations_test.rb +27 -19
- data/test/function_pointers_test.rb +18 -0
- data/test/functions_test.rb +7 -2
- data/test/methods_test.rb +3 -3
- data/test/namespaces_test.rb +1 -1
- data/test/node_test.rb +11 -31
- data/test/parser_test.rb +1 -1
- data/test/query_results_test.rb +15 -14
- data/test/structs_test.rb +10 -12
- data/test/test_helper.rb +10 -2
- data/test/types_test.rb +63 -38
- data/test/variables_test.rb +26 -0
- metadata +46 -31
@@ -1,15 +1,18 @@
|
|
1
1
|
module RbGCCXML
|
2
|
-
|
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
|
-
|
10
|
+
# See Node#to_cpp
|
11
|
+
def to_cpp(qualified = true)
|
10
12
|
type = XMLParsing.find_type_of(self.node, "type")
|
11
|
-
"#{type.
|
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
|
-
|
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
|
10
|
+
def to_cpp(qualified = true)
|
10
11
|
type = XMLParsing.find_type_of(self.node, "type")
|
11
|
-
"#{type.
|
12
|
+
"#{type.to_cpp(qualified)}&"
|
12
13
|
end
|
14
|
+
|
13
15
|
end
|
16
|
+
|
14
17
|
end
|
data/lib/rbgccxml/parser.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
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
|
-
|
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
|
-
|
13
|
-
|
14
|
-
|
16
|
+
if includes = config.delete(:includes)
|
17
|
+
@gccxml.add_include includes
|
18
|
+
end
|
15
19
|
|
16
|
-
|
17
|
-
|
18
|
-
|
20
|
+
if flags = config.delete(:cxxflags)
|
21
|
+
@gccxml.add_cxxflags flags
|
22
|
+
end
|
19
23
|
|
20
|
-
|
24
|
+
validate_glob(config[:files])
|
25
|
+
end
|
21
26
|
end
|
22
27
|
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
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
|
-
@
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
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
|
-
|
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
|
-
|
44
|
-
|
61
|
+
document = LibXML::XML::Document.file(xml_file)
|
62
|
+
root = document.root
|
45
63
|
# Everything starts at the :: Namespace
|
46
|
-
|
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.
|
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
|
28
|
-
#
|
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
|
-
#
|
51
|
-
#
|
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
|
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(:
|
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
|
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
|
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
|
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
|
data/lib/rbgccxml/rbgccxml.rb
CHANGED
@@ -3,15 +3,17 @@ module RbGCCXML
|
|
3
3
|
|
4
4
|
class << self
|
5
5
|
|
6
|
-
#
|
7
|
-
#
|
8
|
-
#
|
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
|
-
#
|
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
|
data/lib/rbgccxml/xml_parsing.rb
CHANGED
@@ -1,44 +1,51 @@
|
|
1
1
|
module RbGCCXML
|
2
2
|
|
3
|
-
# A module of methods used to parse out the flat GCC-XML
|
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
|
-
#
|
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>:
|
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(:
|
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
|
-
|
36
|
-
|
34
|
+
cache_key = options.to_s
|
35
|
+
cached = @@find_query_cache[cache_key]
|
36
|
+
return cached if cached
|
37
37
|
|
38
|
-
|
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
|
-
|
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>:
|
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(:
|
62
|
+
# XMLParsing.find_all(:node_type => "Function")
|
56
63
|
#
|
57
64
|
# Returns all matching nodes
|
58
65
|
def self.find_all(options = {})
|
59
|
-
|
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(:
|
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
|
-
|
78
|
+
found = @@doc_root.find(xpath)
|
67
79
|
|
68
|
-
if
|
69
|
-
|
70
|
-
|
80
|
+
if found
|
81
|
+
found.each do |got|
|
82
|
+
results << build_type(type || got.name, got)
|
71
83
|
end
|
72
|
-
|
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
|
-
|
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.
|
113
|
-
|
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
|
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.
|
158
|
-
|
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
|
-
|
166
|
-
#
|
167
|
-
#
|
168
|
-
def self.
|
169
|
-
|
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
|