rbgccxml 0.1
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 +73 -0
- data/TODO +31 -0
- data/lib/jamis.rb +589 -0
- data/lib/rbgccxml/node.rb +122 -0
- data/lib/rbgccxml/nodes/argument.rb +11 -0
- data/lib/rbgccxml/nodes/class.rb +28 -0
- data/lib/rbgccxml/nodes/constructor.rb +12 -0
- data/lib/rbgccxml/nodes/file.rb +6 -0
- data/lib/rbgccxml/nodes/function.rb +24 -0
- data/lib/rbgccxml/nodes/method.rb +11 -0
- data/lib/rbgccxml/nodes/namespace.rb +6 -0
- data/lib/rbgccxml/nodes/struct.rb +6 -0
- data/lib/rbgccxml/nodes/type.rb +7 -0
- data/lib/rbgccxml/nodes/types/fundamental_type.rb +8 -0
- data/lib/rbgccxml/nodes/types/pointer_type.rb +17 -0
- data/lib/rbgccxml/nodes/types/typedef.rb +8 -0
- data/lib/rbgccxml/parser.rb +87 -0
- data/lib/rbgccxml/query_result.rb +113 -0
- data/lib/rbgccxml/rbgccxml.rb +42 -0
- data/lib/rbgccxml/xml_parsing.rb +89 -0
- data/lib/rbgccxml.rb +31 -0
- data/test/classes_test.rb +60 -0
- data/test/functions_test.rb +102 -0
- data/test/methods_test.rb +59 -0
- data/test/namespaces_test.rb +25 -0
- data/test/node_test.rb +66 -0
- data/test/parser_test.rb +65 -0
- data/test/structs_test.rb +60 -0
- data/test/test_helper.rb +14 -0
- data/test/types_test.rb +41 -0
- metadata +98 -0
@@ -0,0 +1,122 @@
|
|
1
|
+
module RbGCCXML
|
2
|
+
|
3
|
+
class NotQueryableException < RuntimeError; end
|
4
|
+
|
5
|
+
# A Node is part of the C++ code as dictated by GCC-XML. This class
|
6
|
+
# defines all of the starting points into the querying system, along
|
7
|
+
# with helper methods to access data from the C++ code itself.
|
8
|
+
#
|
9
|
+
# Any Node further down the heirarchy chain can and should define which
|
10
|
+
# finder methods are and are not avaiable at that level. For example, the
|
11
|
+
# Class Node cannot search for other Namespaces within that class.
|
12
|
+
class Node
|
13
|
+
attr_reader :node
|
14
|
+
|
15
|
+
# Initialize this node according to the XML element passed in
|
16
|
+
# Only to be used internally.
|
17
|
+
def initialize(node)
|
18
|
+
@node = node
|
19
|
+
end
|
20
|
+
|
21
|
+
# Get the C++ name of this node
|
22
|
+
def name
|
23
|
+
@node.attributes['name']
|
24
|
+
end
|
25
|
+
|
26
|
+
# Get the fully qualified (demangled) C++ name of this node.
|
27
|
+
# The 'demangled' attribute of the node for methods / functions is the
|
28
|
+
# full signature, so cut that out.
|
29
|
+
def qualified_name
|
30
|
+
if @node.attributes["demangled"]
|
31
|
+
@node.attributes["demangled"].split(/\(/)[0]
|
32
|
+
else
|
33
|
+
self.name
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Any unknown methods get sent to the XML node
|
38
|
+
def method_missing(name, *args)
|
39
|
+
if @node.respond_to?(name)
|
40
|
+
@node.send(name, *args)
|
41
|
+
else
|
42
|
+
# Make sure we still throw NoMethodErrors
|
43
|
+
super
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Get the file name of the file this node is found in.
|
48
|
+
def file_name(basename = true)
|
49
|
+
file_id = @node.attributes["file"]
|
50
|
+
file_node = XMLParsing::find(:type => "File", :id => file_id)
|
51
|
+
name = file_node.attributes["name"]
|
52
|
+
basename ? ::File.basename(name) : name
|
53
|
+
end
|
54
|
+
|
55
|
+
# Get the parent node of this node. e.g. function.parent will get the class
|
56
|
+
# the function is contained in.
|
57
|
+
def parent
|
58
|
+
return nil if @node.attributes["context"] == "_1"
|
59
|
+
XMLParsing::find(:id => @node.attributes["context"])
|
60
|
+
end
|
61
|
+
|
62
|
+
# Find all namespaces. There are two ways of calling this method:
|
63
|
+
# #namespaces => Get all namespaces in this scope
|
64
|
+
# #namespaces(name) => Shortcut for namespaces.find(:name => name)
|
65
|
+
def namespaces(name = nil)
|
66
|
+
if name
|
67
|
+
namespaces.find(:name => name)
|
68
|
+
else
|
69
|
+
XMLParsing::find_nested_nodes_of_type(@node, "Namespace")
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
# Find all classes in this scope. Like #namespaces, there are
|
74
|
+
# two ways of calling this method.
|
75
|
+
def classes(name = nil)
|
76
|
+
if name
|
77
|
+
classes.find(:name => name)
|
78
|
+
else
|
79
|
+
XMLParsing::find_nested_nodes_of_type(@node, "Class")
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Find all structs in this scope. Like #namespaces, there are
|
84
|
+
# two ways of calling this method.
|
85
|
+
def structs(name = nil)
|
86
|
+
if name
|
87
|
+
structs.find(:name => name)
|
88
|
+
else
|
89
|
+
XMLParsing::find_nested_nodes_of_type(@node, "Struct")
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# Find all functions in this scope. Functions are free non-class
|
94
|
+
# functions. To search for class methods, use #methods.
|
95
|
+
#
|
96
|
+
# Like #namespaces, there are two ways of calling this method.
|
97
|
+
def functions(name = nil)
|
98
|
+
if name
|
99
|
+
functions.find(:name => name)
|
100
|
+
else
|
101
|
+
XMLParsing::find_nested_nodes_of_type(@node, "Function")
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
# Special equality testing. A given node can be tested against
|
106
|
+
# a String to test against the name of the node. For example
|
107
|
+
#
|
108
|
+
# source.classes("MyClass") == "MyClass" #=> true
|
109
|
+
# source.classes("MyClass") == source.classes.find(:name => "MyClass") #=> true
|
110
|
+
#
|
111
|
+
def ==(val)
|
112
|
+
if val.is_a?(String)
|
113
|
+
return true if self.name == val
|
114
|
+
return true if self.qualified_name =~ /#{val.gsub("*", "\\*")}/
|
115
|
+
false
|
116
|
+
else
|
117
|
+
super
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module RbGCCXML
|
2
|
+
# Node type represending <Class ...> nodes.
|
3
|
+
class Class < Node
|
4
|
+
|
5
|
+
# Classes cannot have nested namespaces
|
6
|
+
def namespaces(name = nil)
|
7
|
+
raise NotQueryableException.new("Cannot query for Namespaces while in a Class")
|
8
|
+
end
|
9
|
+
|
10
|
+
# Find all the constructors for this class
|
11
|
+
def constructors
|
12
|
+
XMLParsing::find_nested_nodes_of_type(@node, "Constructor")
|
13
|
+
end
|
14
|
+
|
15
|
+
# Find all methods for this class. The typical two-ways apply:
|
16
|
+
#
|
17
|
+
# <tt>methods</tt>:: Get all methods in this scope
|
18
|
+
# <tt>methods(name)</tt>:: Shortcut for methods.find(:name => name)
|
19
|
+
#
|
20
|
+
def methods(name = nil)
|
21
|
+
if name
|
22
|
+
methods.find(:name => name)
|
23
|
+
else
|
24
|
+
XMLParsing::find_nested_nodes_of_type(@node, "Method")
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
module RbGCCXML
|
2
|
+
# Class representing <Constructor ...> nodes.
|
3
|
+
# Has arguments
|
4
|
+
class Constructor < Function
|
5
|
+
|
6
|
+
# Constructors do not have a return_type, this raises an
|
7
|
+
# exception.
|
8
|
+
def return_type
|
9
|
+
raise "There is no return_type of a constructor"
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module RbGCCXML
|
2
|
+
# Function query node. Functions are the end point of the tree.
|
3
|
+
# They have arguments and return types.
|
4
|
+
class Function < Node
|
5
|
+
|
6
|
+
# First of all, no more querying once you're this far in
|
7
|
+
%w(classes namespaces functions).each do |f|
|
8
|
+
define_method(f) do
|
9
|
+
raise NotQueryableException.new("Cannot query for #{f} while in a Function")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Get the list of arguments for this Function.
|
14
|
+
# Returns an array of Argument nodes
|
15
|
+
def arguments
|
16
|
+
XMLParsing.find_arguments_for(node)
|
17
|
+
end
|
18
|
+
|
19
|
+
# Find the return type of this function
|
20
|
+
def return_type
|
21
|
+
XMLParsing.find_type_of(node, "returns")
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module RbGCCXML
|
2
|
+
|
3
|
+
# This represents a Pointer of any other kind of type
|
4
|
+
class PointerType < Type
|
5
|
+
|
6
|
+
# Does this type match the given name string?
|
7
|
+
def ==(val)
|
8
|
+
# Look for the '*' denoting a pointer type.
|
9
|
+
# Assuming we find one, drop it and look for the
|
10
|
+
# base type.
|
11
|
+
return false unless val =~ /\*/
|
12
|
+
new_val = val.gsub("*", "").strip
|
13
|
+
XMLParsing.find_type_of(self.node, "type") == new_val
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'tempfile'
|
2
|
+
|
3
|
+
module RbGCCXML
|
4
|
+
|
5
|
+
# This class starts the whole process.
|
6
|
+
# Please use RbGCCXML.parse and not this class directly
|
7
|
+
class Parser
|
8
|
+
|
9
|
+
def initialize(config = {})
|
10
|
+
@gccxml = GCCXML.new
|
11
|
+
|
12
|
+
if includes = config.delete(:includes)
|
13
|
+
@gccxml.add_include includes
|
14
|
+
end
|
15
|
+
|
16
|
+
validate_glob(config[:files])
|
17
|
+
end
|
18
|
+
|
19
|
+
# Start the parsing process. This includes
|
20
|
+
# 1. Creating a temp file for the resulting xml
|
21
|
+
# 2. Finding all the files to run through gccxml
|
22
|
+
# 3. If applicable, build another temp file and #include
|
23
|
+
# the header files to ensure one pass into gccxml
|
24
|
+
# 4. Build up our :: Namespace node and pass that back
|
25
|
+
# to the user for querying
|
26
|
+
def parse
|
27
|
+
@results_file = Tempfile.new("rbgccxml")
|
28
|
+
parse_file = nil
|
29
|
+
|
30
|
+
if @files.length == 1
|
31
|
+
parse_file = @files[0]
|
32
|
+
else
|
33
|
+
# Otherwise we need to build up a single header file
|
34
|
+
# that #include's all of the files in the list, and
|
35
|
+
# parse that out instead
|
36
|
+
parse_file = build_header_for(@files)
|
37
|
+
end
|
38
|
+
|
39
|
+
@gccxml.parse(parse_file, @results_file.path)
|
40
|
+
|
41
|
+
# Everything starts at the :: Namespace
|
42
|
+
document = Hpricot.XML(@results_file)
|
43
|
+
global_ns = document.search("//Namespace[@name='::']")[0]
|
44
|
+
|
45
|
+
XMLParsing.doc_root = document
|
46
|
+
|
47
|
+
Namespace.new global_ns
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def build_header_for(files)
|
53
|
+
header = Tempfile.new("header_wrapper")
|
54
|
+
header.open
|
55
|
+
|
56
|
+
@files.each do |file|
|
57
|
+
header.write "#include \"#{file}\"\n"
|
58
|
+
end
|
59
|
+
|
60
|
+
header.close
|
61
|
+
|
62
|
+
header.path
|
63
|
+
end
|
64
|
+
|
65
|
+
def validate_glob(files)
|
66
|
+
found = []
|
67
|
+
|
68
|
+
if files.is_a?(Array)
|
69
|
+
files.each {|f| found << Dir[f] }
|
70
|
+
elsif ::File.directory?(files)
|
71
|
+
found = Dir[files + "/*"]
|
72
|
+
else
|
73
|
+
found = Dir[files]
|
74
|
+
end
|
75
|
+
|
76
|
+
found.flatten!
|
77
|
+
|
78
|
+
if found.empty?
|
79
|
+
raise SourceNotFoundError.new(
|
80
|
+
"Cannot find files matching #{files.inspect}. " +
|
81
|
+
"You might need to specify a full path.")
|
82
|
+
end
|
83
|
+
|
84
|
+
@files = found.select {|f| !::File.directory?(f) }
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,113 @@
|
|
1
|
+
module RbGCCXML
|
2
|
+
# Any node query will return an instance of this class, QueryResult. This
|
3
|
+
# class is an Array with slightly different handling of #find. Array#find
|
4
|
+
# expects a block to find elements, we want #find to take an options
|
5
|
+
# hash.
|
6
|
+
class QueryResult < Array
|
7
|
+
|
8
|
+
# Find within this result set any nodes that match the given options
|
9
|
+
# Options can be any or all of the following, based on the type of node:
|
10
|
+
#
|
11
|
+
# All nodes:
|
12
|
+
# <tt>:name</tt>:: The unmangled name of the node. Can be a string or Regexp. Works on all nodes.
|
13
|
+
# <tt>:arguments</tt>:: Search according to argument types.
|
14
|
+
# This needs to be an array of strings or symbols. nil can be
|
15
|
+
# used as a "any" flag. Only works on Functions, Methods, and Constructors
|
16
|
+
# <tt>:returns</tt>:: Search according to the return type. Can be a string or symbol.
|
17
|
+
# Only works on Functions and Methods
|
18
|
+
#
|
19
|
+
# All arguments added to the options are processed in an AND format. If you
|
20
|
+
# are looking for 3 random arguments with a return type of int:
|
21
|
+
#
|
22
|
+
# find(:arguments => [nil, nil, nil], :returns => :int)
|
23
|
+
#
|
24
|
+
# It's also possible to do this in two steps, chaining the +find+ calls, as long as
|
25
|
+
# each +find+ in the chain has multiple results:
|
26
|
+
#
|
27
|
+
# find(:arguments => [nil, nil, nil]).find(:returns => :int)
|
28
|
+
#
|
29
|
+
# However if you want 3 random arguments OR returning int, you should use
|
30
|
+
# two seperate queries:
|
31
|
+
#
|
32
|
+
# find(:arguments => [nil, nil, nil])
|
33
|
+
# find(:returns => :int)
|
34
|
+
#
|
35
|
+
# When dealing with how to specify the types, Typedefs, user defined types, fundamental
|
36
|
+
# types (int, char, etc) and pointers to all of these are currently supported. To find
|
37
|
+
# functions that return a pointer to MyClass:
|
38
|
+
#
|
39
|
+
# find(:returns => "MyClass*")
|
40
|
+
#
|
41
|
+
# Returns: A new QueryResult containing the results, allowing for nested +finds+.
|
42
|
+
# However, If there is only one result, returns that single Node instead.
|
43
|
+
def find(options = {})
|
44
|
+
result = QueryResult.new
|
45
|
+
|
46
|
+
# Handler hash for doing AND intersection checking
|
47
|
+
found = {}
|
48
|
+
|
49
|
+
name = options.delete(:name)
|
50
|
+
returns = options.delete(:returns)
|
51
|
+
arguments = options.delete(:arguments)
|
52
|
+
|
53
|
+
raise ":arguments must be an array" if arguments && !arguments.is_a?(Array)
|
54
|
+
raise "Unknown keys #{option.keys.join(", ")}. " +
|
55
|
+
"Expected are: :name, :arguments, and :returns" unless options.empty?
|
56
|
+
|
57
|
+
self.each do |node|
|
58
|
+
# C++ name
|
59
|
+
if name
|
60
|
+
found[:name] ||= []
|
61
|
+
if name.is_a?(Regexp)
|
62
|
+
found_name = (node.attributes["name"] =~ name)
|
63
|
+
else
|
64
|
+
found_name = (node.attributes["name"] == name)
|
65
|
+
end
|
66
|
+
|
67
|
+
found[:name] << node if found_name
|
68
|
+
end
|
69
|
+
|
70
|
+
# Return type
|
71
|
+
if returns && [Function, Method].include?(node.class)
|
72
|
+
found[:returns] ||= []
|
73
|
+
found[:returns] << node if node.return_type == returns.to_s
|
74
|
+
end
|
75
|
+
|
76
|
+
# Arguments list
|
77
|
+
if arguments && [Function, Method, Constructor].include?(node.class)
|
78
|
+
found[:arguments] ||= []
|
79
|
+
keep = false
|
80
|
+
args = node.arguments
|
81
|
+
|
82
|
+
if args.size == arguments.size
|
83
|
+
keep = true
|
84
|
+
arguments.each_with_index do |arg, idx|
|
85
|
+
# nil is the "any" flag
|
86
|
+
if !arg.nil? && args[idx].cpp_type != arg.to_s
|
87
|
+
keep = false
|
88
|
+
break
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
found[:arguments] << node if keep
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# Now we do an intersection of all the found nodes,
|
98
|
+
# which ensures that we AND together all the parts
|
99
|
+
# the user is looking for
|
100
|
+
tmp = self
|
101
|
+
found.each_value do |value|
|
102
|
+
tmp = (tmp & value)
|
103
|
+
end
|
104
|
+
|
105
|
+
# But make sure that we always have a QueryResult and
|
106
|
+
# not a plain Array
|
107
|
+
result << tmp
|
108
|
+
result.flatten!
|
109
|
+
|
110
|
+
result.length == 1 ? result[0] : result
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# RbGCCXML, the library to parse and query C++ header code.
|
2
|
+
module RbGCCXML
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# This is where it all happens. This method must be 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):
|
9
|
+
#
|
10
|
+
# <tt>"/path/to/file.h"</tt>
|
11
|
+
#
|
12
|
+
# <tt>"/dir/glob/**/*.h"</tt>
|
13
|
+
#
|
14
|
+
# An array of either of the above.
|
15
|
+
#
|
16
|
+
# +options+ can be any of:
|
17
|
+
#
|
18
|
+
# includes:: A single string, or an array of strings of directory includes (-I directives)
|
19
|
+
#
|
20
|
+
# Returns the Namespace Node linked to the global namespace "::".
|
21
|
+
#
|
22
|
+
def parse(files, options = {})
|
23
|
+
# Steps here:
|
24
|
+
# 1. Find gccxml
|
25
|
+
# 2. Find all files expected to be parsed
|
26
|
+
# 3. If multiple files:
|
27
|
+
# Build up a temp file with #includes to each file to be parsed
|
28
|
+
# 4. If multiple files:
|
29
|
+
# Run gccxml on this generated file
|
30
|
+
# else
|
31
|
+
# Run gccxml on the expected file
|
32
|
+
# 5. Parse out XML into class tree
|
33
|
+
|
34
|
+
@parser = Parser.new :files => files, :includes => options[:includes]
|
35
|
+
@parser.parse
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
|
40
|
+
class SourceNotFoundError < RuntimeError; end
|
41
|
+
class ConfigurationError < RuntimeError; end
|
42
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module RbGCCXML
|
2
|
+
|
3
|
+
# A module of methods used to parse out the flat GCC-XML file into
|
4
|
+
# a proper heirarchy. These methods are used internally and not intended
|
5
|
+
# for outside use.
|
6
|
+
module XMLParsing
|
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.
|
11
|
+
def self.doc_root=(root)
|
12
|
+
@@doc_root = root
|
13
|
+
end
|
14
|
+
|
15
|
+
# Generic finding of nodes according to attributes.
|
16
|
+
# Special options:
|
17
|
+
#
|
18
|
+
# <tt>:type</tt>:: Specify a certain node type to search by
|
19
|
+
#
|
20
|
+
# Any other options is directly mapped to attributes on the node. For example, to find
|
21
|
+
# a Function node that have the name "functor":
|
22
|
+
#
|
23
|
+
# XMLParsing.find(:type => "Function", :name => "functor")
|
24
|
+
#
|
25
|
+
# Returns the first found node
|
26
|
+
def self.find(options = {})
|
27
|
+
return nil if options.empty?
|
28
|
+
|
29
|
+
type = options.delete(:type)
|
30
|
+
attrs = options.map {|key, value| "[@#{key}='#{value}']"}.join
|
31
|
+
|
32
|
+
xpath = "//#{type}#{attrs}"
|
33
|
+
|
34
|
+
got = @@doc_root.search(xpath)[0]
|
35
|
+
|
36
|
+
if got
|
37
|
+
RbGCCXML.const_get(type || got.name).new(got)
|
38
|
+
else
|
39
|
+
nil
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
# Look through the DOM under +node+ for +node_type+ nodes.
|
44
|
+
# +node_type+ must be the string name of an existing Node subclass.
|
45
|
+
#
|
46
|
+
# Returns a QueryResult with the findings.
|
47
|
+
def self.find_nested_nodes_of_type(node, node_type)
|
48
|
+
results = QueryResult.new
|
49
|
+
|
50
|
+
# First of all limit which elements we're searching for, to ease processing.
|
51
|
+
# In the GCCXML output, node heirarchy is designated by id, members, and context
|
52
|
+
# attributes:
|
53
|
+
#
|
54
|
+
# id => Unique identifier of a given node
|
55
|
+
# members => Space-delimited array of node id's that are under this node
|
56
|
+
# context => The parent node id of this node
|
57
|
+
#
|
58
|
+
# We only want those nodes in node's context.
|
59
|
+
xpath = "//#{node_type}[@context='#{node.attributes["id"]}']"
|
60
|
+
|
61
|
+
@@doc_root.search(xpath).each do |found|
|
62
|
+
results << RbGCCXML.const_get(node_type).new(found)
|
63
|
+
end
|
64
|
+
|
65
|
+
results.flatten
|
66
|
+
end
|
67
|
+
|
68
|
+
# Arguments are a special case in gccxml as they are actual children of
|
69
|
+
# the functions / methods they are a part of.
|
70
|
+
def self.find_arguments_for(node)
|
71
|
+
results = QueryResult.new
|
72
|
+
|
73
|
+
node.get_elements_by_tag_name("Argument").each do |argument|
|
74
|
+
results << Argument.new(argument)
|
75
|
+
end
|
76
|
+
|
77
|
+
results.flatten
|
78
|
+
end
|
79
|
+
|
80
|
+
# Entrance into the type management. Given a GCCXML node and an attribute
|
81
|
+
# to reference, find the C++ type related. For example, finding the return
|
82
|
+
# type of a function:
|
83
|
+
#
|
84
|
+
# +find_type_of(func_node, "returns")+ could return "std::string" node, "int" node, etc
|
85
|
+
def self.find_type_of(node, attribute)
|
86
|
+
XMLParsing.find(:id => node.attributes[attribute])
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
data/lib/rbgccxml.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'hpricot'
|
2
|
+
gem 'gccxml_gem'
|
3
|
+
require 'gccxml'
|
4
|
+
|
5
|
+
require 'rbgccxml/rbgccxml'
|
6
|
+
|
7
|
+
module RbGCCXML
|
8
|
+
|
9
|
+
# Core classes
|
10
|
+
autoload :Parser, "rbgccxml/parser"
|
11
|
+
autoload :Node, "rbgccxml/node"
|
12
|
+
autoload :QueryResult, "rbgccxml/query_result"
|
13
|
+
autoload :XMLParsing, "rbgccxml/xml_parsing"
|
14
|
+
|
15
|
+
# Nodes
|
16
|
+
autoload :Argument, "rbgccxml/nodes/argument"
|
17
|
+
autoload :Class, "rbgccxml/nodes/class"
|
18
|
+
autoload :Constructor, "rbgccxml/nodes/constructor"
|
19
|
+
autoload :File, "rbgccxml/nodes/file"
|
20
|
+
autoload :Function, "rbgccxml/nodes/function"
|
21
|
+
autoload :Method, "rbgccxml/nodes/method"
|
22
|
+
autoload :Namespace, "rbgccxml/nodes/namespace"
|
23
|
+
autoload :Struct, "rbgccxml/nodes/struct"
|
24
|
+
|
25
|
+
# Type Management
|
26
|
+
autoload :Type, "rbgccxml/nodes/type"
|
27
|
+
autoload :FundamentalType, "rbgccxml/nodes/types/fundamental_type"
|
28
|
+
autoload :PointerType, "rbgccxml/nodes/types/pointer_type"
|
29
|
+
autoload :Typedef, "rbgccxml/nodes/types/typedef"
|
30
|
+
|
31
|
+
end
|