rbplusplus 0.1.1 → 0.8
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 +31 -15
- data/TODO +20 -0
- data/lib/rbplusplus/builders/base.rb +148 -8
- data/lib/rbplusplus/builders/class.rb +106 -31
- data/lib/rbplusplus/builders/enumeration.rb +40 -0
- data/lib/rbplusplus/builders/extension.rb +31 -6
- data/lib/rbplusplus/builders/module.rb +12 -6
- data/lib/rbplusplus/builders/types_manager.rb +93 -0
- data/lib/rbplusplus/extension.rb +69 -41
- data/lib/rbplusplus/module.rb +3 -1
- data/lib/rbplusplus/transformers/class.rb +67 -0
- data/lib/rbplusplus/transformers/constructor.rb +4 -0
- data/lib/rbplusplus/transformers/function.rb +27 -0
- data/lib/rbplusplus/transformers/method.rb +4 -0
- data/lib/rbplusplus/transformers/module.rb +71 -0
- data/lib/rbplusplus/transformers/node.rb +77 -0
- data/lib/rbplusplus/transformers/node_cache.rb +19 -0
- data/lib/rbplusplus/transformers/node_reference.rb +30 -0
- data/lib/rbplusplus/transformers/rbgccxml.rb +6 -0
- data/lib/rbplusplus/writers/extension.rb +33 -25
- data/lib/rbplusplus/writers/multiple_files_writer.rb +42 -2
- data/lib/rbplusplus/writers/single_file_writer.rb +5 -0
- data/lib/rbplusplus.rb +24 -0
- data/test/class_methods_test.rb +55 -0
- data/test/classes_test.rb +0 -25
- data/test/compiling_test.rb +30 -0
- data/test/constructors_test.rb +40 -0
- data/test/enumerations_test.rb +63 -0
- data/test/file_writers_test.rb +56 -4
- data/test/generated/extconf.rb +25 -5
- data/test/headers/class_methods.h +41 -0
- data/test/headers/complex_static_methods.h +25 -0
- data/test/headers/constructors.h +47 -0
- data/test/headers/enums.h +77 -0
- data/test/headers/external_mapping.h +16 -0
- data/test/headers/external_mapping_rice.h +20 -0
- data/test/headers/include/helper.h +1 -0
- data/test/headers/nested_struct.h +20 -0
- data/test/headers/overload.h +28 -0
- data/test/headers/subclass.h +42 -0
- data/test/headers/to_from_ruby.h +78 -0
- data/test/headers/to_from_ruby_source.cpp +22 -0
- data/test/headers/ugly_helper.h +18 -0
- data/test/headers/ugly_interface.h +115 -0
- data/test/headers/ugly_interface_ns.h +8 -0
- data/test/nested_test.rb +26 -0
- data/test/object_persistence_test.rb +44 -0
- data/test/overloading_test.rb +36 -0
- data/test/struct_test.rb +22 -0
- data/test/subclass_test.rb +31 -0
- data/test/test_helper.rb +5 -0
- data/test/to_from_ruby_test.rb +24 -0
- data/test/wrap_as_test.rb +114 -0
- metadata +43 -6
@@ -0,0 +1,93 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
module Builders
|
3
|
+
|
4
|
+
# This is a singleton class that takes care of handling any to_ruby and from_ruby
|
5
|
+
# definitions this wrapper might need. This is pulled out seperate from other builders
|
6
|
+
# because of C++ coding and compiling restrictions. Mainly,
|
7
|
+
#
|
8
|
+
# 1. All cpp/hpp files where Rice needs to know about a given type needs to know about any to_/from_ruby definitions of that type
|
9
|
+
# 2. The actual definition of these methods can only be in one place or we get compiler redefinition errors.
|
10
|
+
class TypesManager
|
11
|
+
include Singleton
|
12
|
+
|
13
|
+
# Forward off all calls to the singleton instance of this method.
|
14
|
+
# This allows one to use this class as if it's a bunch of class methods. E.g.:
|
15
|
+
#
|
16
|
+
# TypesManager.build_const_converter(type)
|
17
|
+
#
|
18
|
+
def self.method_missing(method, *args)
|
19
|
+
if TypesManager.instance.respond_to?(method)
|
20
|
+
TypesManager.instance.send(method, *args)
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_accessor :body, :prototypes, :includes
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@consts_wrapped = []
|
30
|
+
@body = []
|
31
|
+
@prototypes = []
|
32
|
+
@includes = []
|
33
|
+
end
|
34
|
+
|
35
|
+
# Some libraries have really bad namespace declarations
|
36
|
+
# so we allow for 2 methods of including files
|
37
|
+
# 1. trace the class definition to the parent file
|
38
|
+
# 2. explicitly declare which files to include in every generated source
|
39
|
+
#
|
40
|
+
def add_include_for(type)
|
41
|
+
file = type.file_name(false)
|
42
|
+
if Base.sources.include? file
|
43
|
+
@includes << "#include \"#{file}\""
|
44
|
+
else
|
45
|
+
Base.sources.each do |header|
|
46
|
+
@includes << "#include \"#{header}\""
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# Rice doesn't automatically handle all to_ / from_ruby conversions for a given type.
|
52
|
+
# A common construct is the +const Type&+ variable, which we need to manually handle.
|
53
|
+
def build_const_converter(type)
|
54
|
+
type = type.is_a?(RbGCCXML::Type) ? type.base_type : type
|
55
|
+
|
56
|
+
# Don't need to deal with fundamental types
|
57
|
+
return if type.is_a?(RbGCCXML::FundamentalType)
|
58
|
+
|
59
|
+
full_name = type.qualified_name
|
60
|
+
|
61
|
+
# Only wrap once
|
62
|
+
# TODO cleaner way of doing this
|
63
|
+
return if @consts_wrapped.include?(full_name)
|
64
|
+
|
65
|
+
# Some types are already handled by Rice, ignore such types
|
66
|
+
return if full_name =~ /std::string/
|
67
|
+
|
68
|
+
@consts_wrapped << full_name
|
69
|
+
|
70
|
+
# Enumerations are handled slightly differently
|
71
|
+
class_type = if type.is_a?(RbGCCXML::Enumeration)
|
72
|
+
"new #{full_name}(a)"
|
73
|
+
else
|
74
|
+
"(#{full_name} *)&a"
|
75
|
+
end
|
76
|
+
|
77
|
+
@includes << "#include <rice/Object.hpp>"
|
78
|
+
@includes << "#include <rice/Data_Object.hpp>"
|
79
|
+
@includes << "#include <rice/Data_Type.hpp>"
|
80
|
+
add_include_for type
|
81
|
+
|
82
|
+
@body << "template<>"
|
83
|
+
@body << "Rice::Object to_ruby<#{full_name} >(#{full_name} const & a) {"
|
84
|
+
@body << "\treturn Rice::Data_Object<#{full_name} >(#{class_type}, Rice::Data_Type<#{full_name} >::klass(), 0, 0);"
|
85
|
+
@body << "}"
|
86
|
+
|
87
|
+
@prototypes << "template<>"
|
88
|
+
@prototypes << "Rice::Object to_ruby<#{full_name} >(#{full_name} const & a);"
|
89
|
+
end
|
90
|
+
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
data/lib/rbplusplus/extension.rb
CHANGED
@@ -45,20 +45,11 @@ module RbPlusPlus
|
|
45
45
|
# The list of modules to create
|
46
46
|
attr_accessor :modules
|
47
47
|
|
48
|
-
#
|
49
|
-
|
50
|
-
|
51
|
-
#
|
52
|
-
attr_accessor :
|
53
|
-
|
54
|
-
# List of libraries to link
|
55
|
-
attr_accessor :libraries
|
56
|
-
|
57
|
-
# List of extra CXXFLAGS that might need to be added to compile lines
|
58
|
-
attr_accessor :cxxflags
|
59
|
-
|
60
|
-
# List of extra LDFLAGS that might need to be added to compile lines
|
61
|
-
attr_accessor :ldflags
|
48
|
+
# Various options given by the user to help with
|
49
|
+
# parsing, linking, compiling, etc.
|
50
|
+
#
|
51
|
+
# See #sources for a list of the possible options
|
52
|
+
attr_accessor :options
|
62
53
|
|
63
54
|
# Create a new Ruby extension with a given name. This name will be
|
64
55
|
# the module built into the extension.
|
@@ -67,11 +58,18 @@ module RbPlusPlus
|
|
67
58
|
@name = name
|
68
59
|
@modules = []
|
69
60
|
@writer_mode = :multiple
|
70
|
-
|
71
|
-
@
|
72
|
-
|
73
|
-
|
74
|
-
|
61
|
+
|
62
|
+
@options = {
|
63
|
+
:include_paths => [],
|
64
|
+
:library_paths => [],
|
65
|
+
:libraries => [],
|
66
|
+
:cxxflags => [],
|
67
|
+
:ldflags => [],
|
68
|
+
:include_source_files => [],
|
69
|
+
:includes => []
|
70
|
+
}
|
71
|
+
|
72
|
+
@node = nil
|
75
73
|
|
76
74
|
if block
|
77
75
|
build_working_dir(&block)
|
@@ -84,40 +82,56 @@ module RbPlusPlus
|
|
84
82
|
|
85
83
|
# Define where we can find the header files to parse
|
86
84
|
# Can give an array of directories, a glob, or just a string.
|
87
|
-
# All file names should be full paths, not
|
85
|
+
# All file names should be full paths, not relative.
|
88
86
|
#
|
89
|
-
# Options can be the following:
|
87
|
+
# Options can be any or all of the following:
|
90
88
|
#
|
91
|
-
# * <tt>:include_paths</tt> -
|
92
|
-
# * <tt>:library_paths</tt> -
|
93
|
-
# * <tt>:libraries</tt> -
|
94
|
-
# * <tt>:cxxflags</tt> -
|
95
|
-
# * <tt>:ldflags</tt> -
|
89
|
+
# * <tt>:include_paths</tt> - Path(s) to be added as -I flags
|
90
|
+
# * <tt>:library_paths</tt> - Path(s) to be added as -L flags
|
91
|
+
# * <tt>:libraries</tt> - Path(s) to be added as -l flags
|
92
|
+
# * <tt>:cxxflags</tt> - Flag(s) to be added to command line for parsing / compiling
|
93
|
+
# * <tt>:ldflags</tt> - Flag(s) to be added to command line for linking
|
94
|
+
# * <tt>:includes</tt> - Header file(s) to include at the beginning of each .rb.cpp file generated.
|
95
|
+
# * <tt>:include_source_files</tt> - C++ source files that need to be compiled into the extension but not wrapped.
|
96
96
|
def sources(dirs, options = {})
|
97
97
|
parser_options = {}
|
98
98
|
|
99
99
|
if (paths = options.delete(:include_paths))
|
100
|
-
@
|
101
|
-
parser_options[:includes] =
|
100
|
+
@options[:include_paths] << paths
|
101
|
+
parser_options[:includes] = paths
|
102
102
|
end
|
103
103
|
|
104
104
|
if (lib_paths = options.delete(:library_paths))
|
105
|
-
@
|
105
|
+
@options[:library_paths] << lib_paths
|
106
106
|
end
|
107
107
|
|
108
108
|
if (libs = options.delete(:libraries))
|
109
|
-
@libraries << libs
|
109
|
+
@options[:libraries] << libs
|
110
110
|
end
|
111
111
|
|
112
112
|
if (flags = options.delete(:cxxflags))
|
113
|
-
@cxxflags << flags
|
114
|
-
parser_options[:cxxflags] =
|
113
|
+
@options[:cxxflags] << flags
|
114
|
+
parser_options[:cxxflags] = flags
|
115
115
|
end
|
116
116
|
|
117
117
|
if (flags = options.delete(:ldflags))
|
118
|
-
@ldflags << flags
|
118
|
+
@options[:ldflags] << flags
|
119
|
+
end
|
120
|
+
|
121
|
+
if (files = options.delete(:include_source_files))
|
122
|
+
@options[:include_source_files] << files
|
123
|
+
end
|
124
|
+
|
125
|
+
if (flags = options.delete(:includes))
|
126
|
+
includes = Dir.glob(flags)
|
127
|
+
if(includes.length == 0)
|
128
|
+
puts "Warning: There were no matches for includes #{flags.inspect}"
|
129
|
+
else
|
130
|
+
@options[:includes] += [*includes]
|
131
|
+
end
|
119
132
|
end
|
120
133
|
|
134
|
+
@sources = Dir.glob dirs
|
121
135
|
@parser = RbGCCXML.parse(dirs, parser_options)
|
122
136
|
end
|
123
137
|
|
@@ -125,12 +139,18 @@ module RbPlusPlus
|
|
125
139
|
# Specifing a namespace on the Extension itself will mark functions,
|
126
140
|
# class, enums, etc to be globally available to Ruby (aka not in it's own
|
127
141
|
# module)
|
142
|
+
#
|
143
|
+
# For now, to get access to the underlying RbGCCXML query system, save the
|
144
|
+
# return value of this method:
|
145
|
+
#
|
146
|
+
# node = namespace "lib::to_wrap"
|
147
|
+
#
|
128
148
|
def namespace(name)
|
129
149
|
@node = @parser.namespaces(name)
|
130
150
|
end
|
131
151
|
|
132
152
|
# Mark that this extension needs to create a Ruby module of
|
133
|
-
# a give name. Like Extension, this can be used with or without
|
153
|
+
# a give name. Like Extension.new, this can be used with or without
|
134
154
|
# a block.
|
135
155
|
def module(name, &block)
|
136
156
|
m = RbModule.new(name, @parser, &block)
|
@@ -145,13 +165,15 @@ module RbPlusPlus
|
|
145
165
|
raise "Unknown writer mode #{mode}" unless [:multiple, :single].include?(mode)
|
146
166
|
@writer_mode = mode
|
147
167
|
end
|
148
|
-
|
168
|
+
|
149
169
|
# Start the code generation process.
|
150
170
|
def build
|
151
171
|
raise ConfigurationError.new("Must specify working directory") unless @working_dir
|
152
172
|
raise ConfigurationError.new("Must specify which sources to wrap") unless @parser
|
153
173
|
|
154
174
|
@builder = Builders::ExtensionBuilder.new(@name, @node || @parser)
|
175
|
+
Builders::Base.additional_includes = @options[:includes]
|
176
|
+
Builders::Base.sources = @sources
|
155
177
|
@builder.modules = @modules
|
156
178
|
@builder.build
|
157
179
|
end
|
@@ -160,6 +182,7 @@ module RbPlusPlus
|
|
160
182
|
# #build must be called before this step or nothing will be written out
|
161
183
|
def write
|
162
184
|
prepare_working_dir
|
185
|
+
process_other_source_files
|
163
186
|
|
164
187
|
# Create the code
|
165
188
|
writer_class = @writer_mode == :multiple ? Writers::MultipleFilesWriter : Writers::SingleFileWriter
|
@@ -167,11 +190,7 @@ module RbPlusPlus
|
|
167
190
|
|
168
191
|
# Create the extconf.rb
|
169
192
|
extconf = Writers::ExtensionWriter.new(@builder, @working_dir)
|
170
|
-
extconf.
|
171
|
-
extconf.library_paths = @lib_paths
|
172
|
-
extconf.libraries = @libraries
|
173
|
-
extconf.cxxflags = @cxxflags
|
174
|
-
extconf.ldflags = @ldflags
|
193
|
+
extconf.options = @options
|
175
194
|
extconf.write
|
176
195
|
end
|
177
196
|
|
@@ -192,7 +211,16 @@ module RbPlusPlus
|
|
192
211
|
# and if it does exist, clean it out
|
193
212
|
def prepare_working_dir
|
194
213
|
FileUtils.mkdir_p @working_dir unless File.directory?(@working_dir)
|
195
|
-
FileUtils.rm_rf "#{@working_dir}/*"
|
214
|
+
FileUtils.rm_rf Dir["#{@working_dir}/*"]
|
215
|
+
end
|
216
|
+
|
217
|
+
# Make sure that any files or globs of files in :include_source_files are copied into the working
|
218
|
+
# directory before compilation
|
219
|
+
def process_other_source_files
|
220
|
+
files = @options[:include_source_files].flatten
|
221
|
+
files.each do |f|
|
222
|
+
FileUtils.cp Dir[f], @working_dir
|
223
|
+
end
|
196
224
|
end
|
197
225
|
|
198
226
|
# Cool little eval / binding hack, from need.rb
|
data/lib/rbplusplus/module.rb
CHANGED
@@ -42,8 +42,10 @@ module RbPlusPlus
|
|
42
42
|
|
43
43
|
# Specify a C++ namespace from which the contained code will
|
44
44
|
# be wrapped and exposed to Ruby under this Module.
|
45
|
+
#
|
46
|
+
# Also see Extension#namespace
|
45
47
|
def namespace(name)
|
46
|
-
@node = @parser.namespaces(name)
|
48
|
+
@node = @parser.namespaces.find(:all, :name => name)
|
47
49
|
end
|
48
50
|
|
49
51
|
# Register another module to be defined inside of
|
@@ -0,0 +1,67 @@
|
|
1
|
+
module RbGCCXML
|
2
|
+
class Class
|
3
|
+
# Class can include nested classes and nested structs.
|
4
|
+
#
|
5
|
+
# Class can also include external methods/functions as class level methods
|
6
|
+
# also supports instance level methods
|
7
|
+
#
|
8
|
+
# ex.
|
9
|
+
#
|
10
|
+
# math_class.includes node.namespaces("Math").functions("mod")
|
11
|
+
#
|
12
|
+
# or for a instance method:
|
13
|
+
#
|
14
|
+
# math_class.includes node.namespaces("Math").functions("mod").as_method
|
15
|
+
#
|
16
|
+
# or for nesting a class/struct:
|
17
|
+
#
|
18
|
+
# math_class.includes node.namespaces("Math").classes("Degree")
|
19
|
+
#
|
20
|
+
def includes(val)
|
21
|
+
if (val.is_a?(RbGCCXML::Struct) || val.is_a?(RbGCCXML::Class))
|
22
|
+
@classes ||= []
|
23
|
+
@classes << RbPlusPlus::NodeReference.new(val)
|
24
|
+
else
|
25
|
+
@methods ||= []
|
26
|
+
@methods << RbPlusPlus::NodeReference.new(val)
|
27
|
+
end
|
28
|
+
val.moved=true
|
29
|
+
end
|
30
|
+
|
31
|
+
alias_method :node_methods, :methods
|
32
|
+
def methods(*args) #:nodoc:
|
33
|
+
nodes = node_methods(*args)
|
34
|
+
methods = @methods || QueryResult.new
|
35
|
+
methods << cache(nodes)
|
36
|
+
methods.flatten!
|
37
|
+
return methods if args.empty?
|
38
|
+
return (methods.size == 1 ? methods[0] : methods)
|
39
|
+
end
|
40
|
+
|
41
|
+
alias_method :node_classes, :classes
|
42
|
+
def classes(*args) #:nodoc:
|
43
|
+
[@classes || [], node_classes].flatten
|
44
|
+
end
|
45
|
+
|
46
|
+
# returns a list of superclasses of this node, including the node's class
|
47
|
+
def super_classes
|
48
|
+
retv = []
|
49
|
+
unless node.attributes['bases'].nil? || node.attributes['bases'] == ""
|
50
|
+
node.attributes['bases'].split.each do |cls_id|
|
51
|
+
c = XMLParsing.find(:type => "Class", :id => cls_id)
|
52
|
+
c = XMLParsing.find(:type => "Struct", :id => cls_id) if c.nil?
|
53
|
+
if c.nil?
|
54
|
+
puts "#{self.qualified_name} cannot find super class for id #{cls_id} "
|
55
|
+
next
|
56
|
+
end
|
57
|
+
c = RbPlusPlus::NodeCache.instance.get(c)
|
58
|
+
retv << c unless c.ignored?
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
return retv
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module RbGCCXML
|
2
|
+
class Function
|
3
|
+
attr_reader :special_qualified_name
|
4
|
+
|
5
|
+
# always true for functions, false for methods
|
6
|
+
def static?
|
7
|
+
!(@as_method || false)
|
8
|
+
end
|
9
|
+
|
10
|
+
# Sets this function to be an instance method.
|
11
|
+
# Useful for custom function declaration.
|
12
|
+
def as_instance_method
|
13
|
+
@as_method = true
|
14
|
+
return self
|
15
|
+
end
|
16
|
+
|
17
|
+
def calls(method_name)
|
18
|
+
@special_qualified_name = method_name
|
19
|
+
self
|
20
|
+
end
|
21
|
+
|
22
|
+
alias_method :method_qualified_name, :qualified_name
|
23
|
+
def qualified_name #:nodoc:
|
24
|
+
@special_qualified_name || method_qualified_name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
class RbModule
|
3
|
+
# Helper function for moving pieces of an API into other Ruby locations, eg from a Class to a Module,
|
4
|
+
# from global functions to a Class, or from Module to Module.
|
5
|
+
#
|
6
|
+
# Module may include Functions
|
7
|
+
# e.module "System" do |m|
|
8
|
+
# m.includes node.functions("print").wrap_as("puts") # Moves the ::print function into the System module
|
9
|
+
#
|
10
|
+
# m.include node.classes("Vector3") # Explicitly put Vector3 class in the System module
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
def includes(val)
|
14
|
+
if is_a?(val, RbGCCXML::Function)
|
15
|
+
reference_function(val)
|
16
|
+
elsif is_a?(val, RbGCCXML::Class)
|
17
|
+
reference_class(val)
|
18
|
+
elsif is_a?(val, RbGCCXML::Struct)
|
19
|
+
reference_struct(val)
|
20
|
+
else
|
21
|
+
raise "Cannot use #{self.class}#includes for type '#{val.class}'"
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def functions #:nodoc:
|
26
|
+
functions = @functions || []
|
27
|
+
functions << @node.functions if @node
|
28
|
+
functions.flatten
|
29
|
+
end
|
30
|
+
|
31
|
+
def classes #:nodoc:
|
32
|
+
classes = @classes || []
|
33
|
+
classes << @node.classes if @node
|
34
|
+
classes.flatten
|
35
|
+
end
|
36
|
+
|
37
|
+
def structs #:nodoc:
|
38
|
+
structs = @structs || []
|
39
|
+
structs << @node.structs if @node
|
40
|
+
structs.flatten
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
# Map a function from a different namespace
|
46
|
+
def reference_function(val) #:nodoc:
|
47
|
+
@functions ||= []
|
48
|
+
@functions << NodeReference.new(val)
|
49
|
+
val.moved=true
|
50
|
+
end
|
51
|
+
|
52
|
+
# Map a class from a different namespace
|
53
|
+
def reference_class(val) #:nodoc:
|
54
|
+
@classes ||= []
|
55
|
+
@classes << NodeReference.new(val)
|
56
|
+
val.moved=true
|
57
|
+
end
|
58
|
+
|
59
|
+
def reference_struct(val) #:nodoc:
|
60
|
+
@structs ||= []
|
61
|
+
@structs << NodeReference.new(val)
|
62
|
+
val.moved=true
|
63
|
+
end
|
64
|
+
|
65
|
+
def is_a?(val, klass) #:nodoc:
|
66
|
+
return true if val.is_a?(klass)
|
67
|
+
return true if val.is_a?(NodeReference) && val.references?(klass)
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,77 @@
|
|
1
|
+
module RbGCCXML
|
2
|
+
class Node
|
3
|
+
# Specifies to not export this node
|
4
|
+
def ignore
|
5
|
+
@ignored = true
|
6
|
+
end
|
7
|
+
|
8
|
+
# Returns true if this node is ignored in exporting
|
9
|
+
def ignored?
|
10
|
+
@ignored || false
|
11
|
+
end
|
12
|
+
|
13
|
+
# Specifies that this node has been included somewhere else
|
14
|
+
def moved=(val)
|
15
|
+
@moved = val
|
16
|
+
end
|
17
|
+
|
18
|
+
# Change what the name of this node will be when wrapped into Ruby
|
19
|
+
def wrap_as(name)
|
20
|
+
@renamed = name
|
21
|
+
self
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns true if the node has been moved
|
25
|
+
def moved?
|
26
|
+
@moved || false
|
27
|
+
end
|
28
|
+
|
29
|
+
# Has this node been renamed
|
30
|
+
def renamed?
|
31
|
+
(@renamed.nil? ? false : true)
|
32
|
+
end
|
33
|
+
|
34
|
+
alias_method :rbgccxml_namespaces, :namespaces
|
35
|
+
def namespaces(*args) #:nodoc:
|
36
|
+
nodes = rbgccxml_namespaces(*args)
|
37
|
+
return cache(nodes)
|
38
|
+
end
|
39
|
+
|
40
|
+
alias_method :rbgccxml_classes, :classes
|
41
|
+
def classes(*args) #:nodoc:
|
42
|
+
nodes = rbgccxml_classes(*args)
|
43
|
+
return cache(nodes)
|
44
|
+
end
|
45
|
+
|
46
|
+
alias_method :rbgccxml_functions, :functions
|
47
|
+
def functions(*args) #:nodoc:
|
48
|
+
nodes = rbgccxml_functions(*args)
|
49
|
+
return cache(nodes)
|
50
|
+
end
|
51
|
+
|
52
|
+
alias_method :rbgccxml_methods, :functions
|
53
|
+
def methods(*args) #:nodoc:
|
54
|
+
nodes = rbgccxml_methods(*args)
|
55
|
+
return cache(nodes)
|
56
|
+
end
|
57
|
+
|
58
|
+
alias_method :rbgccxml_name, :name
|
59
|
+
def name #:nodoc:
|
60
|
+
@renamed || rbgccxml_name
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
# Looks up the objects in the node cache.
|
65
|
+
def cache(nodes)
|
66
|
+
if nodes.is_a?(QueryResult)
|
67
|
+
retv = QueryResult.new
|
68
|
+
nodes.each do |node|
|
69
|
+
retv << RbPlusPlus::NodeCache.instance.get(node)
|
70
|
+
end
|
71
|
+
return retv
|
72
|
+
else
|
73
|
+
return RbPlusPlus::NodeCache.instance.get(nodes)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
class NodeCache #:nodoc:
|
3
|
+
include Singleton
|
4
|
+
# Retrieves a node from the cache based on the node's qualified name
|
5
|
+
def get(node)
|
6
|
+
demangled = node.attributes['demangled']
|
7
|
+
@@nodes ||= {}
|
8
|
+
if @@nodes[demangled].nil?
|
9
|
+
@@nodes[demangled] = node
|
10
|
+
end
|
11
|
+
return @@nodes[demangled]
|
12
|
+
end
|
13
|
+
|
14
|
+
# Clears out the cache
|
15
|
+
def clear
|
16
|
+
@@nodes = {}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RbPlusPlus
|
2
|
+
class NodeReference #:nodoc:
|
3
|
+
# Takes the delegate object as input
|
4
|
+
def initialize(from)
|
5
|
+
@delegate = from
|
6
|
+
end
|
7
|
+
|
8
|
+
# Delegate
|
9
|
+
def method_missing(name, *args)
|
10
|
+
@delegate.send name, *args
|
11
|
+
end
|
12
|
+
|
13
|
+
# Always false
|
14
|
+
def moved?
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
# Delegate
|
19
|
+
def methods(*args)
|
20
|
+
@delegate.methods *args
|
21
|
+
end
|
22
|
+
|
23
|
+
# Returns true if the class references the specified class
|
24
|
+
def references?(klass)
|
25
|
+
return true if @delegate.is_a?(klass)
|
26
|
+
return true if @delegate.is_a?(NodeReference) && @delegate.references?(klass)
|
27
|
+
return false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|