rubybreaker 0.0.1 → 0.0.2
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/NEWS +48 -0
- data/README.md +56 -20
- data/Rakefile +9 -34
- data/TODO +10 -10
- data/VERSION +1 -0
- data/bin/gen_stub_rubylib +35 -36
- data/bin/rubybreaker +1 -4
- data/lib/rubybreaker/debug.rb +8 -4
- data/lib/rubybreaker/rubylib/core.rb +738 -571
- data/lib/rubybreaker/runtime/inspector.rb +16 -7
- data/lib/rubybreaker/runtime/monitor.rb +14 -18
- data/lib/rubybreaker/runtime/object_wrapper.rb +9 -3
- data/lib/rubybreaker/runtime/overrides.rb +51 -8
- data/lib/rubybreaker/runtime/pluggable.rb +1 -3
- data/lib/rubybreaker/runtime/type_placeholder.rb +2 -6
- data/lib/rubybreaker/runtime/type_system.rb +53 -17
- data/lib/rubybreaker/runtime/typesig_parser.rb +1 -0
- data/lib/rubybreaker/runtime/util.rb +18 -0
- data/lib/rubybreaker/runtime.rb +42 -15
- data/lib/rubybreaker/type/type_comparer.rb +10 -10
- data/lib/rubybreaker/type/type_grammar.treetop +30 -21
- data/lib/rubybreaker/type/type_unparser.rb +2 -2
- data/lib/rubybreaker/typing/subtyping.rb +21 -21
- data/lib/rubybreaker/util.rb +11 -1
- data/lib/rubybreaker.rb +75 -54
- data/test/integrated/tc_class_methods.rb +35 -0
- data/test/integrated/tc_inherit_broken.rb +29 -0
- data/test/integrated/tc_method_missing.rb +1 -1
- data/test/runtime/tc_obj_wrapper.rb +104 -4
- data/test/ts_integrated.rb +2 -0
- data/test/type/tc_comparer.rb +96 -96
- data/test/type/tc_parser.rb +18 -0
- data/test/type/tc_unparser.rb +16 -0
- data/test/typing/tc_typing.rb +20 -20
- data/webpage/footer.html +1 -1
- data/webpage/header.html +7 -7
- data/webpage/index.html +65 -28
- data/webpage/rdoc/RubyBreaker/Breakable.html +280 -0
- data/webpage/rdoc/RubyBreaker/Broken/BrokenEigen.html +304 -0
- data/webpage/rdoc/RubyBreaker/Broken.html +308 -0
- data/webpage/rdoc/RubyBreaker/Context.html +421 -0
- data/webpage/rdoc/RubyBreaker/Debug.html +411 -0
- data/webpage/rdoc/RubyBreaker/Errors/InternalError.html +263 -0
- data/webpage/rdoc/RubyBreaker/Errors/InvalidSubtypeCheck.html +263 -0
- data/webpage/rdoc/RubyBreaker/Errors/InvalidTypeConstruction.html +214 -0
- data/webpage/rdoc/RubyBreaker/Errors/SubtypeFailure.html +212 -0
- data/webpage/rdoc/RubyBreaker/Errors/TypeError.html +212 -0
- data/webpage/rdoc/RubyBreaker/Errors/UserError.html +264 -0
- data/webpage/rdoc/RubyBreaker/Errors.html +209 -0
- data/webpage/rdoc/RubyBreaker/Kernel.html +259 -0
- data/webpage/rdoc/RubyBreaker/Main.html +560 -0
- data/webpage/rdoc/RubyBreaker/ObjectPosition.html +334 -0
- data/webpage/rdoc/RubyBreaker/Position.html +463 -0
- data/webpage/rdoc/RubyBreaker/RubyTypeUtils.html +308 -0
- data/webpage/rdoc/RubyBreaker/Runtime/Inspector.html +380 -0
- data/webpage/rdoc/RubyBreaker/Runtime/MethodInfo.html +324 -0
- data/webpage/rdoc/RubyBreaker/Runtime/Monitor.html +354 -0
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorInstaller.html +379 -0
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorSwitch.html +382 -0
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorUtils.html +400 -0
- data/webpage/rdoc/RubyBreaker/Runtime/ObjectWrapper.html +411 -0
- data/webpage/rdoc/RubyBreaker/Runtime/Pluggable.html +305 -0
- data/webpage/rdoc/RubyBreaker/Runtime/TypePlaceholder.html +280 -0
- data/webpage/rdoc/RubyBreaker/Runtime/TypeSigParser.html +283 -0
- data/webpage/rdoc/RubyBreaker/Runtime/TypeSystem.html +630 -0
- data/webpage/rdoc/RubyBreaker/Runtime.html +255 -0
- data/webpage/rdoc/RubyBreaker/TestCase.html +332 -0
- data/webpage/rdoc/RubyBreaker/TypeComparer.html +304 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/AnyType.html +260 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/BlockType.html +310 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/DuckType.html +320 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/FusionType.html +323 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/MethodListType.html +281 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/MethodType.html +282 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/NilType.html +260 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/NominalType.html +282 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/OptionalType.html +281 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/OrType.html +281 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/SelfType.html +329 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/Type.html +409 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/VarLengthType.html +282 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs.html +212 -0
- data/webpage/rdoc/RubyBreaker/TypeUnparser.html +273 -0
- data/webpage/rdoc/RubyBreaker/Typing.html +305 -0
- data/webpage/rdoc/RubyBreaker/Utilities.html +294 -0
- data/webpage/rdoc/RubyBreaker.html +337 -0
- data/webpage/rdoc/created.rid +26 -0
- data/webpage/rdoc/images/add.png +0 -0
- data/webpage/rdoc/images/brick.png +0 -0
- data/webpage/rdoc/images/brick_link.png +0 -0
- data/webpage/rdoc/images/bug.png +0 -0
- data/webpage/rdoc/images/bullet_black.png +0 -0
- data/webpage/rdoc/images/bullet_toggle_minus.png +0 -0
- data/webpage/rdoc/images/bullet_toggle_plus.png +0 -0
- data/webpage/rdoc/images/date.png +0 -0
- data/webpage/rdoc/images/delete.png +0 -0
- data/webpage/rdoc/images/find.png +0 -0
- data/webpage/rdoc/images/loadingAnimation.gif +0 -0
- data/webpage/rdoc/images/macFFBgHack.png +0 -0
- data/webpage/rdoc/images/package.png +0 -0
- data/webpage/rdoc/images/page_green.png +0 -0
- data/webpage/rdoc/images/page_white_text.png +0 -0
- data/webpage/rdoc/images/page_white_width.png +0 -0
- data/webpage/rdoc/images/plugin.png +0 -0
- data/webpage/rdoc/images/ruby.png +0 -0
- data/webpage/rdoc/images/tag_blue.png +0 -0
- data/webpage/rdoc/images/tag_green.png +0 -0
- data/webpage/rdoc/images/transparent.png +0 -0
- data/webpage/rdoc/images/wrench.png +0 -0
- data/webpage/rdoc/images/wrench_orange.png +0 -0
- data/webpage/rdoc/images/zoom.png +0 -0
- data/webpage/rdoc/index.html +165 -0
- data/webpage/rdoc/js/darkfish.js +153 -0
- data/webpage/rdoc/js/jquery.js +18 -0
- data/webpage/rdoc/js/navigation.js +142 -0
- data/webpage/rdoc/js/search.js +94 -0
- data/webpage/rdoc/js/search_index.js +1 -0
- data/webpage/rdoc/js/searcher.js +228 -0
- data/webpage/rdoc/rdoc.css +543 -0
- data/webpage/rdoc/table_of_contents.html +376 -0
- data/webpage/rubybreaker.css +31 -31
- metadata +93 -6
|
@@ -20,8 +20,8 @@ grammar TypeGrammar
|
|
|
20
20
|
ret = ret_type.value
|
|
21
21
|
pos = RubyBreaker::Position.get()
|
|
22
22
|
pos.col = meth_name.interval.first
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
return RubyBreaker::MethodType.new(mname,args,blk,ret,pos)
|
|
24
|
+
end
|
|
25
25
|
}
|
|
26
26
|
end
|
|
27
27
|
|
|
@@ -216,15 +216,15 @@ grammar TypeGrammar
|
|
|
216
216
|
nil_type / any_type1 / self_type / nominal_type
|
|
217
217
|
end
|
|
218
218
|
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
219
|
+
rule self_type
|
|
220
|
+
'self' {
|
|
221
|
+
def value
|
|
222
|
+
pos = RubyBreaker::Position.get()
|
|
223
|
+
pos.col = interval.first
|
|
224
|
+
return RubyBreaker::SelfType.new(pos)
|
|
225
|
+
end
|
|
226
|
+
}
|
|
227
|
+
end
|
|
228
228
|
|
|
229
229
|
rule nominal_type
|
|
230
230
|
[a-z_]+ {
|
|
@@ -264,20 +264,29 @@ grammar TypeGrammar
|
|
|
264
264
|
end
|
|
265
265
|
|
|
266
266
|
rule meth_name
|
|
267
|
-
|
|
267
|
+
deprecated_meth_name / normal_meth_name
|
|
268
268
|
end
|
|
269
269
|
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
'==' / '!=' / '<<' / '>>' / '[]' / '**' / '<=' / '>=' / '-@' / '=~' /
|
|
274
|
-
'<' / '>' / '&' / '|' / '*' / '/' / '%' / '+' / '-' / '^'
|
|
275
|
-
end
|
|
270
|
+
rule deprecated_meth_name
|
|
271
|
+
'_deprecated_' normal_meth_name
|
|
272
|
+
end
|
|
276
273
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
274
|
+
rule normal_meth_name
|
|
275
|
+
nominal_meth_name / sym_meth_name
|
|
276
|
+
end
|
|
280
277
|
|
|
278
|
+
rule sym_meth_name
|
|
279
|
+
# Be careful about the order. Remember, it finds a match first
|
|
280
|
+
'===' / '<=>' / '[]=' /
|
|
281
|
+
'!~' / '+@' /
|
|
282
|
+
'==' / '!=' / '<<' / '>>' / '[]' / '**' / '<=' / '>=' / '-@' / '=~' /
|
|
283
|
+
'<' / '>' / '&' / '|' / '*' / '/' / '%' / '+' / '-' / '^' / '~'
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
rule nominal_meth_name
|
|
287
|
+
[a-z_] [a-zA-Z0-9_]* [!?=]?
|
|
288
|
+
end
|
|
289
|
+
|
|
281
290
|
rule space
|
|
282
291
|
[\s]+
|
|
283
292
|
end
|
|
@@ -41,8 +41,8 @@ module RubyBreaker
|
|
|
41
41
|
tokens = tname.split("/")
|
|
42
42
|
tname = tokens.last if tokens.size > 1
|
|
43
43
|
pp.text(tname)
|
|
44
|
-
|
|
45
|
-
|
|
44
|
+
elsif t.instance_of?(SelfType)
|
|
45
|
+
pp.text("self")
|
|
46
46
|
elsif t.instance_of?(DuckType)
|
|
47
47
|
unparse_pp_object_type(pp,t)
|
|
48
48
|
elsif t.instance_of?(FusionType)
|
|
@@ -331,23 +331,23 @@ module RubyBreaker
|
|
|
331
331
|
return is_subtype
|
|
332
332
|
end
|
|
333
333
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
334
|
+
# Self type works exactly like nominal type except that, if RHS is a
|
|
335
|
+
# self type, then only self type is allowed in LHS.
|
|
336
|
+
#
|
|
337
|
+
# For example, consider you are inside Fixnum
|
|
338
|
+
#
|
|
339
|
+
# self <: Fixnum
|
|
340
|
+
# self <: Numeric
|
|
341
|
+
# self <: Object
|
|
342
|
+
# self <: self
|
|
343
|
+
#
|
|
344
|
+
# but,
|
|
345
|
+
#
|
|
346
|
+
# Fixnum !<: self
|
|
347
|
+
#
|
|
348
|
+
def self.self_subtype_rel?(lhs,rhs)
|
|
349
|
+
self.nominal_subtype_rel?(lhs,rhs)
|
|
350
|
+
end
|
|
351
351
|
|
|
352
352
|
# This method checks the subtype relation when LHS is a nominal type.
|
|
353
353
|
# There are several cases to consider:
|
|
@@ -367,8 +367,8 @@ module RubyBreaker
|
|
|
367
367
|
def self.nominal_subtype_rel?(lhs,rhs)
|
|
368
368
|
return false unless lhs.kind_of?(NominalType) # Self type is a nominal type
|
|
369
369
|
if rhs.instance_of?(SelfType)
|
|
370
|
-
|
|
371
|
-
|
|
370
|
+
is_subtype = lhs.instance_of?(SelfType)
|
|
371
|
+
elsif rhs.instance_of?(NominalType) # don't include self type
|
|
372
372
|
is_subtype = RubyTypeUtils.subclass_rel?(lhs.mod, rhs.mod)
|
|
373
373
|
elsif rhs.instance_of?(FusionType)
|
|
374
374
|
# If RHS is a superclass or included module then true
|
|
@@ -444,8 +444,8 @@ module RubyBreaker
|
|
|
444
444
|
is_subtype = rhs.instance_of?(NilType)
|
|
445
445
|
elsif lhs.instance_of?(AnyType)
|
|
446
446
|
is_subtype = true
|
|
447
|
-
|
|
448
|
-
|
|
447
|
+
elsif lhs.instance_of?(SelfType)
|
|
448
|
+
is_subtype = self.self_subtype_rel?(lhs,rhs)
|
|
449
449
|
elsif lhs.instance_of?(NominalType)
|
|
450
450
|
is_subtype = self.nominal_subtype_rel?(lhs,rhs)
|
|
451
451
|
elsif lhs.instance_of?(FusionType)
|
data/lib/rubybreaker/util.rb
CHANGED
|
@@ -17,7 +17,7 @@ module RubyBreaker
|
|
|
17
17
|
word
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
# File activesupport/lib/active_support/inflector/methods.rb
|
|
21
21
|
def self.camelize(lower_case_and_underscored_word, first_letter_in_uppercase = true)
|
|
22
22
|
if first_letter_in_uppercase
|
|
23
23
|
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::#{$1.upcase}" }.gsub(/(?:^|_)(.)/) { $1.upcase }
|
|
@@ -28,4 +28,14 @@ module RubyBreaker
|
|
|
28
28
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
|
+
# http://mentalized.net/journal/2010/04/02/suppress_warnings_from_ruby/
|
|
32
|
+
module Kernel
|
|
33
|
+
def suppress_warning
|
|
34
|
+
original_verbosity = $VERBOSE
|
|
35
|
+
$VERBOSE = nil
|
|
36
|
+
result = yield
|
|
37
|
+
$VERBOSE = original_verbosity
|
|
38
|
+
return result
|
|
39
|
+
end
|
|
40
|
+
end
|
|
31
41
|
end
|
data/lib/rubybreaker.rb
CHANGED
|
@@ -24,21 +24,10 @@ module RubyBreaker
|
|
|
24
24
|
:rubylib => true, # include core ruby library documentation?
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
-
# Broken takes higher precedence than Breakable. Once a module is
|
|
28
|
-
# "declared" to be Broken, it cannot be Breakable.
|
|
29
|
-
#
|
|
30
|
-
# TODO: In future, there will be a module to support both states.
|
|
31
|
-
|
|
32
|
-
# This array lists modules/classes that will be monitored.
|
|
33
|
-
BREAKABLE = []
|
|
34
|
-
|
|
35
27
|
# This array lists modules/classes that are actually instrumented with a
|
|
36
28
|
# monitor.
|
|
37
29
|
INSTALLED = []
|
|
38
30
|
|
|
39
|
-
# This array lists "broken" classes--i.e., with type signatures
|
|
40
|
-
BROKEN = []
|
|
41
|
-
|
|
42
31
|
# This array lists monitored modules/classes that are outputed.
|
|
43
32
|
DOCUMENTED = []
|
|
44
33
|
|
|
@@ -58,14 +47,15 @@ module RubyBreaker
|
|
|
58
47
|
# module/class.
|
|
59
48
|
def self.setup()
|
|
60
49
|
|
|
61
|
-
BREAKABLE.each do |
|
|
50
|
+
BREAKABLE.each do |mod|
|
|
62
51
|
# Avoid already installed module or now Broken module. Remember,
|
|
63
52
|
# once a module is a declared to be Broken, it wins. Broken modules
|
|
64
53
|
# cannot be Breakable!
|
|
65
|
-
unless INSTALLED.include?(
|
|
66
|
-
MonitorInstaller.install_module_monitor(
|
|
67
|
-
INSTALLED <<
|
|
54
|
+
unless INSTALLED.include?(mod) || BROKEN.include?(mod)
|
|
55
|
+
MonitorInstaller.install_module_monitor(mod)
|
|
56
|
+
INSTALLED << mod
|
|
68
57
|
end
|
|
58
|
+
|
|
69
59
|
end
|
|
70
60
|
|
|
71
61
|
# At the end, we generate an output of the type information.
|
|
@@ -81,6 +71,71 @@ module RubyBreaker
|
|
|
81
71
|
eval "load \"#{OPTIONS[:io_file]}\"", TOPLEVEL_BINDING
|
|
82
72
|
end
|
|
83
73
|
|
|
74
|
+
# Pretty prints type information for methods
|
|
75
|
+
def self.pp_methods(pp, meth_type_map)
|
|
76
|
+
meth_type_map.each { |meth_name, meth_type|
|
|
77
|
+
case meth_type
|
|
78
|
+
when MethodType
|
|
79
|
+
pp.breakable()
|
|
80
|
+
pp.text("typesig(\"")
|
|
81
|
+
TypeUnparser.unparse_pp(pp,meth_type)
|
|
82
|
+
pp.text("\")")
|
|
83
|
+
when MethodListType
|
|
84
|
+
meth_type.types.each { |real_meth_type|
|
|
85
|
+
pp.breakable()
|
|
86
|
+
pp.text("typesig(\"")
|
|
87
|
+
TypeUnparser.unparse_pp(pp,real_meth_type)
|
|
88
|
+
pp.text("\")")
|
|
89
|
+
}
|
|
90
|
+
else
|
|
91
|
+
# Can't happen
|
|
92
|
+
end
|
|
93
|
+
}
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Pretty prints type information for the module/class
|
|
97
|
+
def self.pp_module(pp, mod)
|
|
98
|
+
# Skip it if we already have seen it
|
|
99
|
+
return if DOCUMENTED.include?(mod) || mod.to_s[0..1] == "#<"
|
|
100
|
+
|
|
101
|
+
# Remember that we have documented this module/class
|
|
102
|
+
DOCUMENTED << mod
|
|
103
|
+
|
|
104
|
+
# Get the method type mapping
|
|
105
|
+
meth_type_map = Inspector.inspect_all(mod)
|
|
106
|
+
|
|
107
|
+
# Check if this module is a class
|
|
108
|
+
keyword = mod.instance_of?(Class) ? "class" : "module"
|
|
109
|
+
|
|
110
|
+
pp.text("#{keyword} #{mod.to_s}", 80)
|
|
111
|
+
pp.nest(2) do
|
|
112
|
+
pp.breakable("")
|
|
113
|
+
pp.text("include RubyBreaker::Broken", 80)
|
|
114
|
+
|
|
115
|
+
# See if there is any class method to show
|
|
116
|
+
eigen = Runtime.eigen_class(mod)
|
|
117
|
+
|
|
118
|
+
if !DOCUMENTED.include?(eigen)
|
|
119
|
+
DOCUMENTED << eigen
|
|
120
|
+
eigen_meth_type_map = Inspector.inspect_all(eigen)
|
|
121
|
+
if eigen_meth_type_map.size > 0
|
|
122
|
+
pp.breakable()
|
|
123
|
+
pp.text("class << self", 80)
|
|
124
|
+
pp.nest(2) do
|
|
125
|
+
self.pp_methods(pp, eigen_meth_type_map)
|
|
126
|
+
end
|
|
127
|
+
pp.breakable()
|
|
128
|
+
pp.text("end", 80)
|
|
129
|
+
end
|
|
130
|
+
end
|
|
131
|
+
self.pp_methods(pp, meth_type_map)
|
|
132
|
+
|
|
133
|
+
end
|
|
134
|
+
pp.breakable()
|
|
135
|
+
pp.text("end",80)
|
|
136
|
+
pp.breakable()
|
|
137
|
+
end
|
|
138
|
+
|
|
84
139
|
# This method will generate the output
|
|
85
140
|
def self.output()
|
|
86
141
|
|
|
@@ -90,44 +145,11 @@ module RubyBreaker
|
|
|
90
145
|
pp = PrettyPrint.new(str)
|
|
91
146
|
|
|
92
147
|
# Document each module that was monitored
|
|
93
|
-
INSTALLED.each
|
|
94
|
-
|
|
95
|
-
# Skip it if we already have seen it
|
|
96
|
-
next if DOCUMENTED.include?(mod)
|
|
97
|
-
DOCUMENTED << mod
|
|
98
|
-
|
|
99
|
-
pp.text("class #{mod.to_s}")
|
|
100
|
-
pp.nest(2) do
|
|
101
|
-
pp.breakable("")
|
|
102
|
-
pp.text("include RubyBreaker::Broken")
|
|
103
|
-
meth_type_map = Inspector.inspect_all(mod)
|
|
104
|
-
meth_type_map.each { |meth_name, meth_type|
|
|
105
|
-
case meth_type
|
|
106
|
-
when MethodType
|
|
107
|
-
pp.breakable()
|
|
108
|
-
pp.text("typesig(\"")
|
|
109
|
-
TypeUnparser.unparse_pp(pp,meth_type)
|
|
110
|
-
pp.text("\")")
|
|
111
|
-
when MethodListType
|
|
112
|
-
meth_type.types.each { |real_meth_type|
|
|
113
|
-
pp.breakable()
|
|
114
|
-
pp.text("typesig(\"")
|
|
115
|
-
TypeUnparser.unparse_pp(pp,real_meth_type)
|
|
116
|
-
pp.text("\")")
|
|
117
|
-
}
|
|
118
|
-
else
|
|
119
|
-
# Can't happen
|
|
120
|
-
end
|
|
121
|
-
}
|
|
122
|
-
end
|
|
123
|
-
pp.breakable()
|
|
124
|
-
pp.text("end")
|
|
125
|
-
pp.breakable()
|
|
126
|
-
end
|
|
148
|
+
INSTALLED.each { |mod| self.pp_module(pp, mod) }
|
|
127
149
|
pp.flush
|
|
128
150
|
|
|
129
151
|
# First, display the result on the stdout if set
|
|
130
|
-
|
|
152
|
+
print str if OPTIONS[:stdout]
|
|
131
153
|
|
|
132
154
|
# If this was a library mode run, exit now.
|
|
133
155
|
return if OPTIONS[:mode] == :lib
|
|
@@ -136,11 +158,10 @@ module RubyBreaker
|
|
|
136
158
|
open(OPTIONS[:io_file],"a") do |f|
|
|
137
159
|
unless io_exist
|
|
138
160
|
f.puts "# This file is auto-generated by RubyBreaker"
|
|
139
|
-
|
|
161
|
+
f.puts "require \"rubybreaker\""
|
|
140
162
|
end
|
|
141
163
|
f.puts str
|
|
142
164
|
end
|
|
143
|
-
|
|
144
165
|
end
|
|
145
166
|
|
|
146
167
|
# This method will run the input file
|
|
@@ -170,7 +191,7 @@ module RubyBreaker
|
|
|
170
191
|
|
|
171
192
|
if OPTIONS[:rubylib]
|
|
172
193
|
# Load the core library type documentation
|
|
173
|
-
eval("require \"
|
|
194
|
+
eval("require \"rubybreaker/rubylib\"", TOPLEVEL_BINDING)
|
|
174
195
|
end
|
|
175
196
|
|
|
176
197
|
# Read the input file first (as it might contain type documentation
|
|
@@ -178,7 +199,7 @@ module RubyBreaker
|
|
|
178
199
|
Main.input()
|
|
179
200
|
|
|
180
201
|
# Finally, require the program file! Let it run! Wheeee!
|
|
181
|
-
eval
|
|
202
|
+
eval("require '#{prog_file}'", TOPLEVEL_BINDING)
|
|
182
203
|
|
|
183
204
|
end
|
|
184
205
|
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
require "test/unit"
|
|
2
|
+
require_relative "../../lib/rubybreaker"
|
|
3
|
+
|
|
4
|
+
class IntegratedClassMethodsTest < Test::Unit::TestCase
|
|
5
|
+
include RubyBreaker
|
|
6
|
+
include RubyBreaker::TestCase
|
|
7
|
+
|
|
8
|
+
class A
|
|
9
|
+
include RubyBreaker::Breakable
|
|
10
|
+
def self.foo(x); x.to_s end
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
class B
|
|
14
|
+
include RubyBreaker::Broken
|
|
15
|
+
class << self
|
|
16
|
+
typesig("bar(fixnum[to_s]) -> string")
|
|
17
|
+
def bar(x); x.to_s end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_class_methods
|
|
22
|
+
A.foo(1)
|
|
23
|
+
a_foo_meth_type = Runtime::Inspector.inspect_class_meth(A, :foo)
|
|
24
|
+
str = RubyBreaker::TypeUnparser.unparse(a_foo_meth_type)
|
|
25
|
+
assert_equal("foo(fixnum[to_s]) -> string", str)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_broken_class_methods
|
|
29
|
+
b_bar_meth_type = Runtime::Inspector.inspect_class_meth(B, :bar)
|
|
30
|
+
str = RubyBreaker::TypeUnparser.unparse(b_bar_meth_type)
|
|
31
|
+
assert_equal("bar(fixnum[to_s]) -> string", str)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
end
|
|
35
|
+
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
require "test/unit"
|
|
2
|
+
require_relative "../../lib/rubybreaker"
|
|
3
|
+
|
|
4
|
+
class IntegratedInheritBrokenTest < Test::Unit::TestCase
|
|
5
|
+
include RubyBreaker
|
|
6
|
+
include RubyBreaker::TestCase
|
|
7
|
+
|
|
8
|
+
class A
|
|
9
|
+
include RubyBreaker::Broken
|
|
10
|
+
typesig("foo(fixnum[to_s]) -> string")
|
|
11
|
+
def foo(x); x.to_s end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
class B < A
|
|
15
|
+
include RubyBreaker::Breakable
|
|
16
|
+
def bar(x); foo(x) end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def test_both
|
|
20
|
+
b = B.new
|
|
21
|
+
b.bar(1)
|
|
22
|
+
b_meth_type = Runtime::Inspector.inspect_meth(B, :bar)
|
|
23
|
+
str = RubyBreaker::TypeUnparser.unparse(b_meth_type)
|
|
24
|
+
assert_equal("bar(fixnum[to_s]) -> string", str)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
|
|
@@ -23,7 +23,7 @@ class IntegratedMethodMissingTest < Test::Unit::TestCase
|
|
|
23
23
|
meth_type = Runtime::Inspector.inspect_meth(A, :method_missing)
|
|
24
24
|
str = RubyBreaker::TypeUnparser.unparse(meth_type)
|
|
25
25
|
# puts str
|
|
26
|
-
assert_equal("method_missing(symbol[to_s], fixnum[to_s]
|
|
26
|
+
assert_equal("method_missing(symbol[to_s], fixnum[to_s]*) -> string", str, "A#foo failed.")
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
end
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
dir = File.dirname(__FILE__)
|
|
2
1
|
require "test/unit"
|
|
3
|
-
|
|
2
|
+
require_relative "../../lib/rubybreaker/runtime"
|
|
4
3
|
|
|
5
4
|
class ObjectWrapperTest < Test::Unit::TestCase
|
|
6
5
|
include RubyBreaker
|
|
@@ -54,7 +53,7 @@ class ObjectWrapperTest < Test::Unit::TestCase
|
|
|
54
53
|
assert_equal(x.object_id, wrapped_x.object_id)
|
|
55
54
|
end
|
|
56
55
|
|
|
57
|
-
def
|
|
56
|
+
def test_equalities_fixnum()
|
|
58
57
|
x = 42
|
|
59
58
|
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
60
59
|
assert(wrapped_x == wrapped_x)
|
|
@@ -62,7 +61,7 @@ class ObjectWrapperTest < Test::Unit::TestCase
|
|
|
62
61
|
assert(wrapped_x.eql?(wrapped_x))
|
|
63
62
|
assert(42 == wrapped_x)
|
|
64
63
|
assert(wrapped_x == 42)
|
|
65
|
-
assert(42.equal?(wrapped_x))
|
|
64
|
+
assert(42.equal?(wrapped_x)) # try 42.equal?(42) in irb, it will work!
|
|
66
65
|
assert(wrapped_x.equal?(42))
|
|
67
66
|
assert(42.eql?(wrapped_x))
|
|
68
67
|
assert(wrapped_x.eql?(42))
|
|
@@ -70,4 +69,105 @@ class ObjectWrapperTest < Test::Unit::TestCase
|
|
|
70
69
|
assert_equal(42, wrapped_x)
|
|
71
70
|
end
|
|
72
71
|
|
|
72
|
+
def test_equalities_string()
|
|
73
|
+
x = "42"
|
|
74
|
+
y = "42"
|
|
75
|
+
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
76
|
+
assert(wrapped_x == wrapped_x)
|
|
77
|
+
assert(wrapped_x.equal?(wrapped_x))
|
|
78
|
+
assert(wrapped_x.eql?(wrapped_x))
|
|
79
|
+
assert(y == wrapped_x)
|
|
80
|
+
assert(wrapped_x == y)
|
|
81
|
+
assert(!y.equal?(wrapped_x)) # try "42".equal?("42") in irb, it will fail
|
|
82
|
+
assert(wrapped_x.equal?(y))
|
|
83
|
+
assert(y.eql?(wrapped_x))
|
|
84
|
+
assert(wrapped_x.eql?(y))
|
|
85
|
+
assert_equal(y, wrapped_x)
|
|
86
|
+
assert_equal(y, wrapped_x)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def test_equalities_symbol()
|
|
90
|
+
x = :"42"
|
|
91
|
+
y = :"42"
|
|
92
|
+
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
93
|
+
assert(wrapped_x == wrapped_x)
|
|
94
|
+
assert(wrapped_x.equal?(wrapped_x))
|
|
95
|
+
assert(wrapped_x.eql?(wrapped_x))
|
|
96
|
+
assert(y == wrapped_x)
|
|
97
|
+
assert(wrapped_x == y)
|
|
98
|
+
assert(y.equal?(wrapped_x)) # try :"42".equal?(:"42") in irb, it will work
|
|
99
|
+
assert(wrapped_x.equal?(y))
|
|
100
|
+
assert(y.eql?(wrapped_x))
|
|
101
|
+
assert(wrapped_x.eql?(y))
|
|
102
|
+
assert_equal(y, wrapped_x)
|
|
103
|
+
assert_equal(y, wrapped_x)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def test_equalities_array()
|
|
107
|
+
x = [1,2]
|
|
108
|
+
y = [1,2]
|
|
109
|
+
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
110
|
+
assert(wrapped_x == wrapped_x)
|
|
111
|
+
assert(wrapped_x.equal?(wrapped_x))
|
|
112
|
+
assert(wrapped_x.eql?(wrapped_x))
|
|
113
|
+
assert(y == wrapped_x)
|
|
114
|
+
assert(wrapped_x == y)
|
|
115
|
+
assert(!y.equal?(wrapped_x))
|
|
116
|
+
assert(wrapped_x.equal?(y))
|
|
117
|
+
assert(y.eql?(wrapped_x))
|
|
118
|
+
assert(wrapped_x.eql?(y))
|
|
119
|
+
assert_equal(y, wrapped_x)
|
|
120
|
+
assert_equal(y, wrapped_x)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_inequalities_array()
|
|
124
|
+
x = [1,2]
|
|
125
|
+
y = [1,3]
|
|
126
|
+
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
127
|
+
assert(wrapped_x == wrapped_x)
|
|
128
|
+
assert(wrapped_x.equal?(wrapped_x))
|
|
129
|
+
assert(wrapped_x.eql?(wrapped_x))
|
|
130
|
+
assert(y != wrapped_x)
|
|
131
|
+
assert(wrapped_x != y)
|
|
132
|
+
assert(!y.equal?(wrapped_x))
|
|
133
|
+
assert(!wrapped_x.equal?(y))
|
|
134
|
+
assert(!y.eql?(wrapped_x))
|
|
135
|
+
assert(!wrapped_x.eql?(y))
|
|
136
|
+
assert_not_equal(y, wrapped_x)
|
|
137
|
+
assert_not_equal(y, wrapped_x)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def test_equalities_hash()
|
|
141
|
+
x = { :a => 1, :b => 2}
|
|
142
|
+
y = { :a => 1, :b => 2}
|
|
143
|
+
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
144
|
+
assert(wrapped_x == wrapped_x)
|
|
145
|
+
assert(wrapped_x.equal?(wrapped_x))
|
|
146
|
+
assert(wrapped_x.eql?(wrapped_x))
|
|
147
|
+
assert(y == wrapped_x)
|
|
148
|
+
assert(wrapped_x == y)
|
|
149
|
+
assert(!y.equal?(wrapped_x))
|
|
150
|
+
assert(wrapped_x.equal?(y))
|
|
151
|
+
assert(y.eql?(wrapped_x))
|
|
152
|
+
assert(wrapped_x.eql?(y))
|
|
153
|
+
assert_equal(y, wrapped_x)
|
|
154
|
+
assert_equal(y, wrapped_x)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def test_inequalities_hash()
|
|
158
|
+
x = { :a => 1, :b => 2}
|
|
159
|
+
y = { :a => 1, :b => 3}
|
|
160
|
+
wrapped_x = Runtime::ObjectWrapper.new(x)
|
|
161
|
+
assert(wrapped_x == wrapped_x)
|
|
162
|
+
assert(wrapped_x.equal?(wrapped_x))
|
|
163
|
+
assert(wrapped_x.eql?(wrapped_x))
|
|
164
|
+
assert(y != wrapped_x)
|
|
165
|
+
assert(wrapped_x != y)
|
|
166
|
+
assert(!y.equal?(wrapped_x))
|
|
167
|
+
assert(!wrapped_x.equal?(y))
|
|
168
|
+
assert(!y.eql?(wrapped_x))
|
|
169
|
+
assert(!wrapped_x.eql?(y))
|
|
170
|
+
assert_not_equal(y, wrapped_x)
|
|
171
|
+
assert_not_equal(y, wrapped_x)
|
|
172
|
+
end
|
|
73
173
|
end
|