rubybreaker 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/NEWS +4 -0
- data/README.md +33 -19
- data/Rakefile +31 -13
- data/TODO +6 -4
- data/VERSION +1 -1
- data/bin/rubybreaker +0 -1
- data/lib/rubybreaker/debug/debug.rb +1 -1
- data/lib/rubybreaker/runtime/typesig_unparser.rb +96 -0
- data/lib/rubybreaker/runtime.rb +1 -0
- data/lib/rubybreaker/test/rspec.rb +15 -0
- data/lib/rubybreaker/test/testcase.rb +4 -4
- data/lib/rubybreaker/test.rb +1 -0
- data/lib/rubybreaker/type/type_grammar.treetop +5 -4
- data/lib/rubybreaker/type/type_unparser.rb +69 -25
- data/lib/rubybreaker.rb +9 -77
- data/test/integrated/tc_namespace.rb +56 -0
- data/test/ts_integrated.rb +1 -0
- data/test/ts_rspec.rb +31 -0
- data/test/ts_type.rb +2 -0
- data/test/type/tc_camelize.rb +24 -0
- data/test/type/tc_namespace.rb +25 -0
- data/test/type/tc_unparser.rb +31 -32
- data/webpage/index.html +34 -19
- data/webpage/rdoc/Object.html +308 -0
- data/webpage/rdoc/RubyBreaker/Breakable.html +5 -1
- data/webpage/rdoc/RubyBreaker/Broken/BrokenEigen.html +5 -1
- data/webpage/rdoc/RubyBreaker/Broken.html +5 -1
- data/webpage/rdoc/RubyBreaker/Context.html +5 -1
- data/webpage/rdoc/RubyBreaker/Errors/InternalError.html +4 -0
- data/webpage/rdoc/RubyBreaker/Errors/InvalidSubtypeCheck.html +4 -0
- data/webpage/rdoc/RubyBreaker/Errors/InvalidTypeConstruction.html +4 -0
- data/webpage/rdoc/RubyBreaker/Errors/SubtypeFailure.html +4 -0
- data/webpage/rdoc/RubyBreaker/Errors/TypeError.html +4 -0
- data/webpage/rdoc/RubyBreaker/Errors/UserError.html +4 -0
- data/webpage/rdoc/RubyBreaker/Errors.html +4 -0
- data/webpage/rdoc/RubyBreaker/Main.html +17 -132
- data/webpage/rdoc/RubyBreaker/ObjectPosition.html +5 -1
- data/webpage/rdoc/RubyBreaker/Position.html +5 -1
- data/webpage/rdoc/RubyBreaker/RubyTypeUtils.html +4 -0
- data/webpage/rdoc/RubyBreaker/Runtime/Inspector.html +4 -0
- data/webpage/rdoc/RubyBreaker/Runtime/MethodInfo.html +5 -1
- data/webpage/rdoc/RubyBreaker/Runtime/Monitor.html +5 -1
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorInstaller.html +4 -0
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorSwitch.html +5 -1
- data/webpage/rdoc/RubyBreaker/Runtime/MonitorUtils.html +4 -0
- data/webpage/rdoc/RubyBreaker/Runtime/ObjectWrapper.html +4 -0
- data/webpage/rdoc/RubyBreaker/Runtime/Pluggable.html +4 -0
- data/webpage/rdoc/RubyBreaker/Runtime/TypePlaceholder.html +5 -1
- data/webpage/rdoc/RubyBreaker/Runtime/TypeSigParser.html +4 -0
- data/webpage/rdoc/RubyBreaker/Runtime/TypeSystem.html +5 -1
- data/webpage/rdoc/RubyBreaker/Runtime/TypesigUnparser.html +404 -0
- data/webpage/rdoc/RubyBreaker/Runtime.html +5 -0
- data/webpage/rdoc/RubyBreaker/TestCase.html +47 -43
- data/webpage/rdoc/RubyBreaker/TypeComparer.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/AnyType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/BlockType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/DuckType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/FusionType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/MethodListType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/MethodType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/NilType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/NominalType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/OptionalType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/OrType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/SelfType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs/Type.html +11 -6
- data/webpage/rdoc/RubyBreaker/TypeDefs/VarLengthType.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeDefs.html +4 -0
- data/webpage/rdoc/RubyBreaker/TypeUnparser.html +15 -7
- data/webpage/rdoc/RubyBreaker/Typing.html +4 -0
- data/webpage/rdoc/RubyBreaker/Util.html +4 -0
- data/webpage/rdoc/RubyBreaker.html +6 -6
- data/webpage/rdoc/created.rid +9 -7
- data/webpage/rdoc/index.html +4 -0
- data/webpage/rdoc/js/search_index.js +1 -1
- data/webpage/rdoc/table_of_contents.html +36 -24
- metadata +13 -7
data/lib/rubybreaker.rb
CHANGED
@@ -30,9 +30,6 @@ module RubyBreaker
|
|
30
30
|
# monitor.
|
31
31
|
INSTALLED = []
|
32
32
|
|
33
|
-
# This array lists monitored modules/classes that are outputed.
|
34
|
-
DOCUMENTED = []
|
35
|
-
|
36
33
|
# Extension used by RubyBreaker for output/input
|
37
34
|
EXTENSION = "rubybreaker"
|
38
35
|
|
@@ -75,71 +72,6 @@ module RubyBreaker
|
|
75
72
|
eval "load \"#{OPTIONS[:io_file]}\"", TOPLEVEL_BINDING
|
76
73
|
end
|
77
74
|
|
78
|
-
# Pretty prints type information for methods
|
79
|
-
def self.pp_methods(pp, meth_type_map)
|
80
|
-
meth_type_map.each { |meth_name, meth_type|
|
81
|
-
case meth_type
|
82
|
-
when MethodType
|
83
|
-
pp.breakable()
|
84
|
-
pp.text("typesig(\"")
|
85
|
-
TypeUnparser.unparse_pp(pp,meth_type)
|
86
|
-
pp.text("\")")
|
87
|
-
when MethodListType
|
88
|
-
meth_type.types.each { |real_meth_type|
|
89
|
-
pp.breakable()
|
90
|
-
pp.text("typesig(\"")
|
91
|
-
TypeUnparser.unparse_pp(pp,real_meth_type)
|
92
|
-
pp.text("\")")
|
93
|
-
}
|
94
|
-
else
|
95
|
-
# Can't happen
|
96
|
-
end
|
97
|
-
}
|
98
|
-
end
|
99
|
-
|
100
|
-
# Pretty prints type information for the module/class
|
101
|
-
def self.pp_module(pp, mod)
|
102
|
-
# Skip it if we already have seen it
|
103
|
-
return if DOCUMENTED.include?(mod) || mod.to_s[0..1] == "#<"
|
104
|
-
|
105
|
-
# Remember that we have documented this module/class
|
106
|
-
DOCUMENTED << mod
|
107
|
-
|
108
|
-
# Get the method type mapping
|
109
|
-
meth_type_map = Inspector.inspect_all(mod)
|
110
|
-
|
111
|
-
# Check if this module is a class
|
112
|
-
keyword = mod.instance_of?(Class) ? "class" : "module"
|
113
|
-
|
114
|
-
pp.text("#{keyword} #{mod.to_s}", 80)
|
115
|
-
pp.nest(2) do
|
116
|
-
pp.breakable("")
|
117
|
-
pp.text("include RubyBreaker::Broken", 80)
|
118
|
-
|
119
|
-
# See if there is any class method to show
|
120
|
-
eigen = Runtime.eigen_class(mod)
|
121
|
-
|
122
|
-
if !DOCUMENTED.include?(eigen)
|
123
|
-
DOCUMENTED << eigen
|
124
|
-
eigen_meth_type_map = Inspector.inspect_all(eigen)
|
125
|
-
if eigen_meth_type_map.size > 0
|
126
|
-
pp.breakable()
|
127
|
-
pp.text("class << self", 80)
|
128
|
-
pp.nest(2) do
|
129
|
-
self.pp_methods(pp, eigen_meth_type_map)
|
130
|
-
end
|
131
|
-
pp.breakable()
|
132
|
-
pp.text("end", 80)
|
133
|
-
end
|
134
|
-
end
|
135
|
-
self.pp_methods(pp, meth_type_map)
|
136
|
-
|
137
|
-
end
|
138
|
-
pp.breakable()
|
139
|
-
pp.text("end",80)
|
140
|
-
pp.breakable()
|
141
|
-
end
|
142
|
-
|
143
75
|
# This method will generate the output.
|
144
76
|
def self.output()
|
145
77
|
|
@@ -147,15 +79,15 @@ module RubyBreaker
|
|
147
79
|
|
148
80
|
io_exist = OPTIONS[:io_file] && File.exist?(OPTIONS[:io_file])
|
149
81
|
|
150
|
-
|
151
|
-
pp = PrettyPrint.new(str)
|
152
|
-
|
82
|
+
code = ""
|
153
83
|
# Document each module that was monitored
|
154
|
-
INSTALLED.each { |mod|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
84
|
+
INSTALLED.each { |mod|
|
85
|
+
str = Runtime::TypesigUnparser.unparse(mod)
|
86
|
+
code << str
|
87
|
+
if OPTIONS[:mode] == :lib
|
88
|
+
print str
|
89
|
+
end
|
90
|
+
}
|
159
91
|
|
160
92
|
# If this was a library mode run, exit now.
|
161
93
|
return if OPTIONS[:mode] == :lib
|
@@ -166,7 +98,7 @@ module RubyBreaker
|
|
166
98
|
f.puts "# This file is auto-generated by RubyBreaker"
|
167
99
|
f.puts "require \"rubybreaker\""
|
168
100
|
end
|
169
|
-
f.
|
101
|
+
f.print code
|
170
102
|
end
|
171
103
|
|
172
104
|
RubyBreaker.verbose("Done generating type documentation")
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require_relative "../../lib/rubybreaker"
|
3
|
+
|
4
|
+
class IntegratedNamespaceTest < Test::Unit::TestCase
|
5
|
+
include RubyBreaker
|
6
|
+
include RubyBreaker::TestCase
|
7
|
+
|
8
|
+
class A < String
|
9
|
+
class C < String
|
10
|
+
class D < String
|
11
|
+
class E < String
|
12
|
+
end
|
13
|
+
end
|
14
|
+
class F
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class B
|
20
|
+
include RubyBreaker::Breakable
|
21
|
+
def foo(x); x.to_s end
|
22
|
+
def bar(x); x.to_s end
|
23
|
+
def baz(x); x.to_s end
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_namspace_b_foo
|
27
|
+
a = A.new
|
28
|
+
b = B.new
|
29
|
+
b.foo(a)
|
30
|
+
meth_type = Runtime::Inspector.inspect_meth(B, :foo)
|
31
|
+
str = RubyBreaker::TypeUnparser.unparse(meth_type)
|
32
|
+
# puts str
|
33
|
+
assert_equal("foo(integrated_namespace_test/a[to_s]) -> string", str, "B#foo failed.")
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_namspace_b_foo_nested
|
37
|
+
a = A::C.new
|
38
|
+
b = B.new
|
39
|
+
b.bar(a)
|
40
|
+
meth_type = Runtime::Inspector.inspect_meth(B, :bar)
|
41
|
+
str = RubyBreaker::TypeUnparser.unparse(meth_type)
|
42
|
+
# puts str
|
43
|
+
assert_equal("bar(integrated_namespace_test/a/c[to_s]) -> string", str, "B#bar failed.")
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_namespace_e_baz
|
47
|
+
e = A::C::D::E.new
|
48
|
+
b = B.new
|
49
|
+
b.baz(e)
|
50
|
+
meth_type = Runtime::Inspector.inspect_meth(B, :baz)
|
51
|
+
str = meth_type.unparse(:namespace => A::C::F)
|
52
|
+
assert_equal("baz(d/e[to_s]) -> string", str, "B#baz failed.")
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
data/test/ts_integrated.rb
CHANGED
data/test/ts_rspec.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
require "rspec"
|
2
|
+
require_relative "../lib/rubybreaker"
|
3
|
+
|
4
|
+
class RSpecTestA
|
5
|
+
include RubyBreaker::Breakable
|
6
|
+
def foo(x); x.to_s end
|
7
|
+
end
|
8
|
+
|
9
|
+
class RSpecTestB
|
10
|
+
include RubyBreaker::Broken
|
11
|
+
typesig("foo(fixnum[to_s]) -> string")
|
12
|
+
end
|
13
|
+
|
14
|
+
describe RSpecTestA do
|
15
|
+
it "should return a string of number" do
|
16
|
+
a = RSpecTestA.new
|
17
|
+
a.foo(1)
|
18
|
+
a_foo_type = RubyBreaker::Runtime::Inspector.inspect_meth(RSpecTestA, :foo)
|
19
|
+
str = a_foo_type.unparse()
|
20
|
+
str.should == "foo(fixnum[to_s]) -> string"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe RSpecTestB do
|
25
|
+
it "should return the documented type of B#foo" do
|
26
|
+
b_foo_type = RubyBreaker::Runtime::Inspector.inspect_meth(RSpecTestB, :foo)
|
27
|
+
str = b_foo_type.unparse()
|
28
|
+
str.should == "foo(fixnum[to_s]) -> string"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
data/test/ts_type.rb
CHANGED
@@ -0,0 +1,24 @@
|
|
1
|
+
# This test verifies type unparser for RubyBreaker types.
|
2
|
+
require "test/unit"
|
3
|
+
require_relative "../../lib/rubybreaker/type"
|
4
|
+
|
5
|
+
class UnparserCamelizeTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
include RubyBreaker
|
8
|
+
|
9
|
+
class CamelizedClassName; end
|
10
|
+
|
11
|
+
def test_camelize_type()
|
12
|
+
t1 = NominalType.new(CamelizedClassName)
|
13
|
+
str1 = t1.unparse({:style => :camelize, :namespace => UnparserCamelizeTest})
|
14
|
+
# puts str1
|
15
|
+
assert_equal("CamelizedClassName",str1.strip())
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_camelize_no_namespace_type()
|
19
|
+
t1 = NominalType.new(CamelizedClassName)
|
20
|
+
str1 = t1.unparse({:style => :camelize, :namespace => UnparserCamelizeTest})
|
21
|
+
# puts str1
|
22
|
+
assert_equal("CamelizedClassName",str1.strip())
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# This test verifies handling of namespace in parsing types.
|
2
|
+
require "test/unit"
|
3
|
+
require_relative "../../lib/rubybreaker/type"
|
4
|
+
|
5
|
+
class TypeNamespaceTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
include RubyBreaker
|
8
|
+
|
9
|
+
class A
|
10
|
+
end
|
11
|
+
|
12
|
+
def setup
|
13
|
+
@parser = Runtime::TypeSigParser::PARSER
|
14
|
+
end
|
15
|
+
|
16
|
+
def teardown
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_namespace_1
|
20
|
+
t1 = @parser.parse("foo(type_namespace_test/a[to_s]) -> string").value
|
21
|
+
str = t1.unparse(:style => :camelize)
|
22
|
+
assert_equal("foo(TypeNamespaceTest::A[to_s]) -> String", str)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
data/test/type/tc_unparser.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
# This test verifies type unparser for RubyBreaker types.
|
2
2
|
|
3
|
-
dir = File.dirname(__FILE__)
|
4
3
|
require "test/unit"
|
5
|
-
|
4
|
+
require_relative "../../lib/rubybreaker/type"
|
6
5
|
|
7
6
|
class UnparserTest < Test::Unit::TestCase
|
8
7
|
|
@@ -30,14 +29,14 @@ class UnparserTest < Test::Unit::TestCase
|
|
30
29
|
|
31
30
|
def test_nominal_type()
|
32
31
|
t1 = NominalType.new(A)
|
33
|
-
str1 = TypeUnparser.unparse(t1)
|
32
|
+
str1 = TypeUnparser.unparse(t1, :namespace => UnparserTest)
|
34
33
|
# puts str1
|
35
34
|
assert_equal("a",str1)
|
36
35
|
end
|
37
36
|
|
38
37
|
def test_self_type()
|
39
38
|
t1 = SelfType.new()
|
40
|
-
str1 = TypeUnparser.unparse(t1)
|
39
|
+
str1 = TypeUnparser.unparse(t1, :namespace => UnparserTest)
|
41
40
|
# puts str1
|
42
41
|
assert_equal("self", str1)
|
43
42
|
end
|
@@ -45,7 +44,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
45
44
|
def test_opt_type()
|
46
45
|
t1 = NominalType.new(A)
|
47
46
|
t2 = OptionalType.new(t1)
|
48
|
-
str2 = TypeUnparser.unparse(t2)
|
47
|
+
str2 = TypeUnparser.unparse(t2, :namespace => UnparserTest)
|
49
48
|
# puts str1
|
50
49
|
assert_equal("a?",str2)
|
51
50
|
end
|
@@ -55,7 +54,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
55
54
|
t2 = NominalType.new(B)
|
56
55
|
t3 = OrType.new([t1, t2])
|
57
56
|
t4 = OptionalType.new(t3)
|
58
|
-
str4 = TypeUnparser.unparse(t4)
|
57
|
+
str4 = TypeUnparser.unparse(t4, :namespace => UnparserTest)
|
59
58
|
# puts str1
|
60
59
|
assert_equal("(a || b)?",str4)
|
61
60
|
end
|
@@ -63,15 +62,15 @@ class UnparserTest < Test::Unit::TestCase
|
|
63
62
|
def test_star_type()
|
64
63
|
t1 = NominalType.new(A)
|
65
64
|
t2 = VarLengthType.new(t1)
|
66
|
-
str2 = TypeUnparser.unparse(t2)
|
65
|
+
str2 = TypeUnparser.unparse(t2, :namespace => UnparserTest)
|
67
66
|
# puts str1
|
68
|
-
assert_equal("a*",str2)
|
67
|
+
assert_equal("a*", str2)
|
69
68
|
end
|
70
69
|
|
71
70
|
def test_star_duck_type()
|
72
71
|
t1 = DuckType.new([:foo, :bar])
|
73
72
|
t2 = VarLengthType.new(t1)
|
74
|
-
str2 = TypeUnparser.unparse(t2)
|
73
|
+
str2 = TypeUnparser.unparse(t2, :namespace => UnparserTest)
|
75
74
|
# puts str1
|
76
75
|
assert_equal("[bar, foo]*",str2)
|
77
76
|
end
|
@@ -79,7 +78,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
79
78
|
def test_star_fusion_type()
|
80
79
|
t1 = FusionType.new(NominalType.new(A), [:foo, :bar])
|
81
80
|
t2 = VarLengthType.new(t1)
|
82
|
-
str2 = TypeUnparser.unparse(t2)
|
81
|
+
str2 = TypeUnparser.unparse(t2, :namespace => UnparserTest)
|
83
82
|
# puts str1
|
84
83
|
assert_equal("a[bar, foo]*",str2)
|
85
84
|
end
|
@@ -89,49 +88,49 @@ class UnparserTest < Test::Unit::TestCase
|
|
89
88
|
t2 = NominalType.new(B)
|
90
89
|
t3 = OrType.new([t1, t2])
|
91
90
|
t4 = VarLengthType.new(t3)
|
92
|
-
str4 = TypeUnparser.unparse(t4)
|
91
|
+
str4 = TypeUnparser.unparse(t4, :namespace => UnparserTest)
|
93
92
|
# puts str1
|
94
93
|
assert_equal("(a || b)*",str4)
|
95
94
|
end
|
96
95
|
|
97
96
|
def test_duck_type()
|
98
97
|
t1 = DuckType.new(["+"])
|
99
|
-
str1 = TypeUnparser.unparse(t1)
|
98
|
+
str1 = TypeUnparser.unparse(t1, :namespace => UnparserTest)
|
100
99
|
# puts str1
|
101
100
|
assert_equal("[+]",str1)
|
102
101
|
end
|
103
102
|
|
104
103
|
def test_duck_type_more_meths()
|
105
104
|
t1 = DuckType.new(["+","foo","bar"])
|
106
|
-
str1 = TypeUnparser.unparse(t1)
|
105
|
+
str1 = TypeUnparser.unparse(t1, :namespace => UnparserTest)
|
107
106
|
#puts str1
|
108
107
|
assert_equal("[+, bar, foo]",str1)
|
109
108
|
end
|
110
109
|
|
111
110
|
def test_duck_type_symbolic_meths()
|
112
111
|
t1 = DuckType.new(["+","-","[]","[]="])
|
113
|
-
str1 = TypeUnparser.unparse(t1)
|
112
|
+
str1 = TypeUnparser.unparse(t1, :namespace => UnparserTest)
|
114
113
|
#puts str1
|
115
114
|
assert_equal("[+, -, [], []=]",str1)
|
116
115
|
end
|
117
116
|
|
118
117
|
def test_fusion_type()
|
119
118
|
t1 = FusionType.new(NominalType.new(A), ["+"])
|
120
|
-
str1 = TypeUnparser.unparse(t1)
|
119
|
+
str1 = TypeUnparser.unparse(t1, :namespace => UnparserTest)
|
121
120
|
# puts str1
|
122
121
|
assert_equal("a[+]",str1)
|
123
122
|
end
|
124
123
|
|
125
124
|
def test_fusion_type_more_meths()
|
126
125
|
t1 = FusionType.new(NominalType.new(A), ["+","foo","bar"])
|
127
|
-
str1 = TypeUnparser.unparse(t1)
|
126
|
+
str1 = TypeUnparser.unparse(t1, :namespace => UnparserTest)
|
128
127
|
# puts str1
|
129
128
|
assert_equal("a[+, bar, foo]",str1)
|
130
129
|
end
|
131
130
|
|
132
131
|
def test_fusion_type_symbolic_meths()
|
133
132
|
t1 = FusionType.new(NominalType.new(A), ["+","-","[]","[]="])
|
134
|
-
str1 = TypeUnparser.unparse(t1)
|
133
|
+
str1 = TypeUnparser.unparse(t1, :namespace => UnparserTest)
|
135
134
|
# puts str1
|
136
135
|
assert_equal("a[+, -, [], []=]",str1)
|
137
136
|
end
|
@@ -140,7 +139,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
140
139
|
t1 = NominalType.new(A)
|
141
140
|
t2 = NominalType.new(B)
|
142
141
|
t3 = OrType.new([t1,t2])
|
143
|
-
str3 = TypeUnparser.unparse(t3)
|
142
|
+
str3 = TypeUnparser.unparse(t3, :namespace => UnparserTest)
|
144
143
|
# puts str3
|
145
144
|
assert_equal("a || b", str3)
|
146
145
|
end
|
@@ -150,7 +149,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
150
149
|
t2 = NominalType.new(B)
|
151
150
|
t3 = NominalType.new(C)
|
152
151
|
t4 = OrType.new([t1,t2,t3])
|
153
|
-
str4 = TypeUnparser.unparse(t4)
|
152
|
+
str4 = TypeUnparser.unparse(t4, :namespace => UnparserTest)
|
154
153
|
# puts str3
|
155
154
|
assert_equal("a || b || c", str4)
|
156
155
|
end
|
@@ -159,7 +158,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
159
158
|
t1 = NominalType.new(A)
|
160
159
|
t2 = NominalType.new(B)
|
161
160
|
t3 = BlockType.new([t1],nil,t2)
|
162
|
-
str3 = TypeUnparser.unparse(t3)
|
161
|
+
str3 = TypeUnparser.unparse(t3, :namespace => UnparserTest)
|
163
162
|
# puts str3
|
164
163
|
assert_equal("|a| -> b",str3)
|
165
164
|
end
|
@@ -169,7 +168,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
169
168
|
t2 = NominalType.new(B)
|
170
169
|
t3 = NominalType.new(C)
|
171
170
|
t4 = BlockType.new([t1,t2],nil,t3)
|
172
|
-
str4 = TypeUnparser.unparse(t4)
|
171
|
+
str4 = TypeUnparser.unparse(t4, :namespace => UnparserTest)
|
173
172
|
# puts str3
|
174
173
|
assert_equal("|a, b| -> c",str4)
|
175
174
|
end
|
@@ -179,7 +178,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
179
178
|
t2 = NominalType.new(B)
|
180
179
|
t3 = SelfType.new()
|
181
180
|
t4 = BlockType.new([t1,t2],nil,t3)
|
182
|
-
str4 = TypeUnparser.unparse(t4)
|
181
|
+
str4 = TypeUnparser.unparse(t4, :namespace => UnparserTest)
|
183
182
|
# puts str3
|
184
183
|
assert_equal("|a, b| -> self",str4)
|
185
184
|
end
|
@@ -190,7 +189,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
190
189
|
t3 = NominalType.new(C)
|
191
190
|
t4 = NominalType.new(D)
|
192
191
|
t5 = BlockType.new([t1],BlockType.new([t2],nil,t3),t4)
|
193
|
-
str5 = TypeUnparser.unparse(t5)
|
192
|
+
str5 = TypeUnparser.unparse(t5, :namespace => UnparserTest)
|
194
193
|
# puts str5
|
195
194
|
assert_equal("|a| {|b| -> c} -> d",str5)
|
196
195
|
end
|
@@ -202,7 +201,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
202
201
|
t4 = NominalType.new(D)
|
203
202
|
t5 = NominalType.new(E)
|
204
203
|
t6 = BlockType.new([t1,t2],BlockType.new([t3],nil,t4),t5)
|
205
|
-
str6 = TypeUnparser.unparse(t6)
|
204
|
+
str6 = TypeUnparser.unparse(t6, :namespace => UnparserTest)
|
206
205
|
# puts str5
|
207
206
|
assert_equal("|a, b| {|c| -> d} -> e",str6)
|
208
207
|
end
|
@@ -214,7 +213,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
214
213
|
t4 = NominalType.new(D)
|
215
214
|
t5 = NominalType.new(E)
|
216
215
|
t6 = BlockType.new([OrType.new([t1,t2])],BlockType.new([t3],nil,t4),t5)
|
217
|
-
str6 = TypeUnparser.unparse(t6)
|
216
|
+
str6 = TypeUnparser.unparse(t6, :namespace => UnparserTest)
|
218
217
|
# puts str5
|
219
218
|
assert_equal("|a || b| {|c| -> d} -> e",str6)
|
220
219
|
end
|
@@ -223,7 +222,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
223
222
|
t1 = NominalType.new(A)
|
224
223
|
t2 = NominalType.new(B)
|
225
224
|
t3 = MethodType.new("m",[t1],nil,t2)
|
226
|
-
str3 = TypeUnparser.unparse(t3)
|
225
|
+
str3 = TypeUnparser.unparse(t3, :namespace => UnparserTest)
|
227
226
|
# puts str3
|
228
227
|
assert_equal("m(a) -> b", str3)
|
229
228
|
end
|
@@ -232,7 +231,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
232
231
|
t1 = NominalType.new(A)
|
233
232
|
t2 = NominalType.new(B)
|
234
233
|
t3 = MethodType.new("==",[t1],nil,t2)
|
235
|
-
str3 = TypeUnparser.unparse(t3)
|
234
|
+
str3 = TypeUnparser.unparse(t3, :namespace => UnparserTest)
|
236
235
|
# puts str3
|
237
236
|
assert_equal("==(a) -> b", str3)
|
238
237
|
end
|
@@ -242,7 +241,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
242
241
|
t2 = NominalType.new(B)
|
243
242
|
t3 = NominalType.new(C)
|
244
243
|
t4 = MethodType.new("m",[t1,t2],nil,t3)
|
245
|
-
str4 = TypeUnparser.unparse(t4)
|
244
|
+
str4 = TypeUnparser.unparse(t4, :namespace => UnparserTest)
|
246
245
|
# puts str3
|
247
246
|
assert_equal("m(a, b) -> c", str4)
|
248
247
|
end
|
@@ -252,7 +251,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
252
251
|
t2 = NominalType.new(B)
|
253
252
|
t3 = SelfType.new()
|
254
253
|
t4 = MethodType.new("m",[t1,t2],nil,t3)
|
255
|
-
str4 = TypeUnparser.unparse(t4)
|
254
|
+
str4 = TypeUnparser.unparse(t4, :namespace => UnparserTest)
|
256
255
|
# puts str3
|
257
256
|
assert_equal("m(a, b) -> self", str4)
|
258
257
|
end
|
@@ -262,7 +261,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
262
261
|
t2 = NominalType.new(B)
|
263
262
|
t3 = NominalType.new(C)
|
264
263
|
t4 = MethodType.new("m",[OrType.new([t1,t2])],nil,t3)
|
265
|
-
str4 = TypeUnparser.unparse(t4)
|
264
|
+
str4 = TypeUnparser.unparse(t4, :namespace => UnparserTest)
|
266
265
|
# puts str3
|
267
266
|
assert_equal("m(a || b) -> c", str4)
|
268
267
|
end
|
@@ -273,7 +272,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
273
272
|
t3 = NominalType.new(C)
|
274
273
|
t4 = NominalType.new(D)
|
275
274
|
t5 = MethodType.new("m",[t1],BlockType.new([t2],nil,t3),t4)
|
276
|
-
str5 = TypeUnparser.unparse(t5)
|
275
|
+
str5 = TypeUnparser.unparse(t5, :namespace => UnparserTest)
|
277
276
|
# puts str5
|
278
277
|
assert_equal("m(a) {|b| -> c} -> d", str5)
|
279
278
|
end
|
@@ -285,7 +284,7 @@ class UnparserTest < Test::Unit::TestCase
|
|
285
284
|
t4 = NominalType.new(D)
|
286
285
|
t5 = NominalType.new(E)
|
287
286
|
t6 = MethodType.new("m",[t1,t2],BlockType.new([t3],nil,t4),t5)
|
288
|
-
str6 = TypeUnparser.unparse(t6)
|
287
|
+
str6 = TypeUnparser.unparse(t6, :namespace => UnparserTest)
|
289
288
|
# puts str5
|
290
289
|
assert_equal("m(a, b) {|c| -> d} -> e", str6)
|
291
290
|
end
|
data/webpage/index.html
CHANGED
@@ -16,7 +16,7 @@
|
|
16
16
|
|
17
17
|
<h1>Introduction</h1>
|
18
18
|
|
19
|
-
<p>RubyBreaker is a dynamic type documentation tool written
|
19
|
+
<p>RubyBreaker is a dynamic type documentation tool written in pure Ruby. It
|
20
20
|
provides the framework for dynamically instrumenting a Ruby program to
|
21
21
|
monitor objects during executions and document the observed type
|
22
22
|
information. The type documentation generated by RubyBreaker is also an
|
@@ -27,7 +27,7 @@ program.</p>
|
|
27
27
|
<p>The primary goal of RubyBreaker is to assign a type signature to every
|
28
28
|
method in designated modules and classes. A type signature is written in
|
29
29
|
the RubyBreaker Type Annotation Language which resembles the documentation
|
30
|
-
style used in
|
30
|
+
style used in Ruby API Doc. Overall, this tool should help Ruby programmers
|
31
31
|
document their code more rigorously and effectively. Currently, manual
|
32
32
|
modification of the user program is required to run RubyBreaker, but this is
|
33
33
|
kept minimal.</p>
|
@@ -40,10 +40,9 @@ be found in <a href="rdoc/index.html">here</a>.</p>
|
|
40
40
|
<h2>Limitations</h2>
|
41
41
|
|
42
42
|
<ul>
|
43
|
-
<li>It only works on toy Ruby programs so far :)</li>
|
44
43
|
<li>Block argument cannot be auto-documented. (Inherent)</li>
|
45
44
|
<li>Manual modification (minimal) of code is required.</li>
|
46
|
-
<li>
|
45
|
+
<li>Parametric polymorphic types are not supported.</li>
|
47
46
|
</ul>
|
48
47
|
|
49
48
|
|
@@ -153,7 +152,8 @@ necessary to obtain precise type information.</p>
|
|
153
152
|
First, the user must indicate which modules are subject to analysis and
|
154
153
|
which modules can be used for the analysis. Next, the user has to indicate
|
155
154
|
where the entry point of the program is. Alternatively, he has to make a
|
156
|
-
small change to the test cases to use RubyBreaker's testing framework
|
155
|
+
small change to the test cases to use RubyBreaker's testing framework. (If
|
156
|
+
you are using RSpec, there is no need for this change.)</p>
|
157
157
|
|
158
158
|
<h3>Breakable and Broken</h3>
|
159
159
|
|
@@ -236,9 +236,7 @@ end
|
|
236
236
|
<p>In Ruby, as soon as a file is <code>require</code>d, the execution of that file begins.
|
237
237
|
For RubyBreaker, however, it is not trivial to find the actual starting
|
238
238
|
point of the program because there <em>has</em> to be a clear point in time at
|
239
|
-
which monitoring of <code>Breakable</code> modules begins
|
240
|
-
attempting to instrument and monitor at the same time will cause an infinite
|
241
|
-
loop!</em></p>
|
239
|
+
which monitoring of <code>Breakable</code> modules begins.</p>
|
242
240
|
|
243
241
|
<p>Indicating the program entry point is simply done by inserting the following
|
244
242
|
line at the code (assuming "<code>require 'rubybreaker'</code>" is already placed at
|
@@ -254,11 +252,11 @@ run the instrumented code (for <code>Breakable</code> modules) which will gather
|
|
254
252
|
information for methods.</p>
|
255
253
|
|
256
254
|
<p>Although this seems simple and easy, this is not the recommended way for
|
257
|
-
analyzing a program. Why? Because RubyBreaker
|
258
|
-
|
259
|
-
|
255
|
+
analyzing a program. Why? Because RubyBreaker comes with a replacement for
|
256
|
+
the built-in testing framework for Ruby. Even better, if you are using
|
257
|
+
RSpec, there is no need to change any test code.</p>
|
260
258
|
|
261
|
-
<h3>Using
|
259
|
+
<h3>Using the Built-in Testing Framework</h3>
|
262
260
|
|
263
261
|
<p>Instead of manually inserting the entry point indicator into the program,
|
264
262
|
the user can take advantage of the Ruby Unit Test framework. This is the
|
@@ -274,11 +272,28 @@ class TestClassA < Test::Unit::TestCase
|
|
274
272
|
end
|
275
273
|
</code></pre>
|
276
274
|
|
277
|
-
<p>That's it
|
275
|
+
<p>That's it! Also, remember that classes and modules can be re-opened for
|
276
|
+
"patches" in Ruby. This means that the original classes or modules do not
|
277
|
+
need to be modified to include <code>Broken</code> and/or <code>Breakable</code>. In each test
|
278
|
+
suite or test case, those classes and modules can be re-opened to include
|
279
|
+
<code>Broken</code> and/or <code>Breakable</code>. The following shows an example of such a test
|
280
|
+
case.</p>
|
278
281
|
|
279
|
-
<
|
280
|
-
|
281
|
-
|
282
|
+
<pre><code>require "rubybreaker"
|
283
|
+
require "test/unit"
|
284
|
+
class A
|
285
|
+
include RubyBreaker::Breakable
|
286
|
+
end
|
287
|
+
class TestClassA < Test::Unit::TestCase
|
288
|
+
...
|
289
|
+
end
|
290
|
+
</code></pre>
|
291
|
+
|
292
|
+
<h3>Using RSpec</h3>
|
293
|
+
|
294
|
+
<p>If using RSpec, it is even easier! No changes are needed for the test code.
|
295
|
+
Really! <em>Well, it is still necessary to <code>require rubybreaker</code> and manually
|
296
|
+
insert <code>Breakable</code> and <code>Broken</code> to appropriate classes and modules.</em></p>
|
282
297
|
|
283
298
|
<h2>Type Annotation</h2>
|
284
299
|
|
@@ -316,7 +331,9 @@ instance, <code>fixnum</code> is an object of type <code>Fixnum</code>. Use lowe
|
|
316
331
|
underscores instead of <em>camelized</em> name. <code>MyClass</code>, for example would be
|
317
332
|
<code>my_class</code> in RubyBreaker type signatures. There is no particular
|
318
333
|
reason for this convention other than it is the common practice used in
|
319
|
-
RubyDoc
|
334
|
+
RubyDoc. Use <code>/</code> to indicate the namespace delimiter <code>::</code>. For example,
|
335
|
+
<code>NamspaceA::ClassB</code> would be represented by <code>namespace_a/class_b</code> in
|
336
|
+
a RubyBreaker type signature.</p>
|
320
337
|
|
321
338
|
<h3>Self Type</h3>
|
322
339
|
|
@@ -475,8 +492,6 @@ RubyBreaker. <em>Technical documentation coming soon...</em></p>
|
|
475
492
|
University of Maryland and represents an object using a structural type with
|
476
493
|
respect to a nominal type.</p>
|
477
494
|
|
478
|
-
<hr />
|
479
|
-
|
480
495
|
<h1>Copyright</h1>
|
481
496
|
|
482
497
|
<p>Copyright (c) 2012 Jong-hoon (David) An. All Rights Reserved.</p>
|