rubybreaker 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (97) hide show
  1. data/NEWS +5 -0
  2. data/NOTES +9 -0
  3. data/README.md +100 -183
  4. data/Rakefile +21 -6
  5. data/VERSION +1 -1
  6. data/bin/rubybreaker +34 -50
  7. data/lib/rubybreaker/debug/debug.rb +6 -0
  8. data/lib/rubybreaker/doc/rdoc.rb +37 -0
  9. data/lib/rubybreaker/doc.rb +3 -0
  10. data/lib/rubybreaker/runtime/inspector.rb +6 -28
  11. data/lib/rubybreaker/runtime/monitor.rb +21 -17
  12. data/lib/rubybreaker/runtime/object_wrapper.rb +7 -2
  13. data/lib/rubybreaker/runtime/type_system.rb +3 -5
  14. data/lib/rubybreaker/runtime/typesig_unparser.rb +1 -4
  15. data/lib/rubybreaker/runtime.rb +64 -105
  16. data/lib/rubybreaker/task.rb +97 -0
  17. data/lib/rubybreaker/test/rspec.rb +1 -1
  18. data/lib/rubybreaker/test/testcase.rb +13 -28
  19. data/lib/rubybreaker/type/type.rb +1 -1
  20. data/lib/rubybreaker/typing/subtyping.rb +10 -5
  21. data/lib/rubybreaker/util.rb +0 -1
  22. data/lib/rubybreaker.rb +163 -115
  23. data/test/integrated/tc_both_broken_breakable.rb +5 -4
  24. data/test/integrated/tc_class_methods.rb +4 -3
  25. data/test/integrated/tc_inherit_broken.rb +4 -3
  26. data/test/integrated/tc_method_missing.rb +4 -4
  27. data/test/integrated/tc_namespace.rb +4 -2
  28. data/test/integrated/tc_simple1.rb +4 -3
  29. data/test/runtime/tc_obj_wrapper.rb +25 -6
  30. data/test/runtime/tc_typesig_parser.rb +0 -1
  31. data/test/testtask/sample.rb +10 -0
  32. data/test/testtask/tc_testtask.rb +25 -0
  33. data/test/ts_rspec.rb +21 -15
  34. data/test/typing/tc_typing.rb +2 -3
  35. data/webpage/index.html +105 -193
  36. data/webpage/rdoc/Kernel.html +286 -0
  37. data/webpage/rdoc/Object.html +17 -11
  38. data/webpage/rdoc/Rake/RubyBreakerTestTask.html +374 -0
  39. data/webpage/rdoc/Rake.html +212 -0
  40. data/webpage/rdoc/RubyBreaker/Breakable.html +24 -40
  41. data/webpage/rdoc/RubyBreaker/Broken.html +21 -69
  42. data/webpage/rdoc/RubyBreaker/Context.html +16 -10
  43. data/webpage/rdoc/RubyBreaker/Errors/InternalError.html +16 -10
  44. data/webpage/rdoc/RubyBreaker/Errors/InvalidSubtypeCheck.html +16 -10
  45. data/webpage/rdoc/RubyBreaker/Errors/InvalidTypeConstruction.html +16 -10
  46. data/webpage/rdoc/RubyBreaker/Errors/SubtypeFailure.html +16 -10
  47. data/webpage/rdoc/RubyBreaker/Errors/TypeError.html +16 -10
  48. data/webpage/rdoc/RubyBreaker/Errors/UserError.html +16 -10
  49. data/webpage/rdoc/RubyBreaker/Errors.html +16 -10
  50. data/webpage/rdoc/RubyBreaker/ObjectPosition.html +16 -10
  51. data/webpage/rdoc/RubyBreaker/Position.html +16 -10
  52. data/webpage/rdoc/RubyBreaker/{TestCase.html → RDocSupport.html} +81 -82
  53. data/webpage/rdoc/RubyBreaker/RubyTypeUtils.html +16 -10
  54. data/webpage/rdoc/RubyBreaker/Runtime/Inspector.html +25 -44
  55. data/webpage/rdoc/RubyBreaker/Runtime/MethodInfo.html +16 -10
  56. data/webpage/rdoc/RubyBreaker/Runtime/Monitor.html +19 -13
  57. data/webpage/rdoc/RubyBreaker/Runtime/MonitorInstaller.html +37 -25
  58. data/webpage/rdoc/RubyBreaker/Runtime/MonitorSwitch.html +20 -14
  59. data/webpage/rdoc/RubyBreaker/Runtime/MonitorUtils.html +21 -15
  60. data/webpage/rdoc/RubyBreaker/Runtime/ObjectWrapper.html +23 -12
  61. data/webpage/rdoc/RubyBreaker/Runtime/Pluggable.html +16 -10
  62. data/webpage/rdoc/RubyBreaker/Runtime/TypeSigParser.html +16 -10
  63. data/webpage/rdoc/RubyBreaker/Runtime/{TypesigUnparser.html → TypeSigUnparser.html} +19 -16
  64. data/webpage/rdoc/RubyBreaker/Runtime/TypeSystem.html +18 -14
  65. data/webpage/rdoc/RubyBreaker/Runtime.html +145 -11
  66. data/webpage/rdoc/RubyBreaker/TypeComparer.html +16 -10
  67. data/webpage/rdoc/RubyBreaker/TypeDefs/AnyType.html +16 -10
  68. data/webpage/rdoc/RubyBreaker/TypeDefs/BlockType.html +16 -10
  69. data/webpage/rdoc/RubyBreaker/TypeDefs/DuckType.html +16 -10
  70. data/webpage/rdoc/RubyBreaker/TypeDefs/FusionType.html +16 -10
  71. data/webpage/rdoc/RubyBreaker/TypeDefs/MethodListType.html +16 -10
  72. data/webpage/rdoc/RubyBreaker/TypeDefs/MethodType.html +16 -10
  73. data/webpage/rdoc/RubyBreaker/TypeDefs/NilType.html +16 -10
  74. data/webpage/rdoc/RubyBreaker/TypeDefs/NominalType.html +16 -10
  75. data/webpage/rdoc/RubyBreaker/TypeDefs/OptionalType.html +16 -10
  76. data/webpage/rdoc/RubyBreaker/TypeDefs/OrType.html +16 -10
  77. data/webpage/rdoc/RubyBreaker/TypeDefs/SelfType.html +17 -11
  78. data/webpage/rdoc/RubyBreaker/TypeDefs/Type.html +17 -11
  79. data/webpage/rdoc/RubyBreaker/TypeDefs/VarLengthType.html +16 -10
  80. data/webpage/rdoc/RubyBreaker/TypeDefs.html +16 -10
  81. data/webpage/rdoc/RubyBreaker/TypeUnparser.html +16 -10
  82. data/webpage/rdoc/RubyBreaker/Typing.html +17 -11
  83. data/webpage/rdoc/RubyBreaker/Util.html +16 -10
  84. data/webpage/rdoc/RubyBreaker.html +167 -34
  85. data/webpage/rdoc/{RubyBreaker/Runtime/TypePlaceholder.html → Test/Unit/TestCase.html} +68 -39
  86. data/webpage/rdoc/Test/Unit.html +211 -0
  87. data/webpage/rdoc/Test.html +211 -0
  88. data/webpage/rdoc/created.rid +18 -17
  89. data/webpage/rdoc/index.html +16 -10
  90. data/webpage/rdoc/js/search_index.js +1 -1
  91. data/webpage/rdoc/table_of_contents.html +61 -48
  92. metadata +21 -12
  93. data/lib/rubybreaker/rubylib/core.rb +0 -2483
  94. data/lib/rubybreaker/rubylib.rb +0 -3
  95. data/lib/rubybreaker/runtime/type_placeholder.rb +0 -23
  96. data/webpage/rdoc/RubyBreaker/Broken/BrokenEigen.html +0 -305
  97. data/webpage/rdoc/RubyBreaker/Main.html +0 -458
data/NEWS CHANGED
@@ -1,3 +1,8 @@
1
+ # VERSION 0.0.5
2
+ * Rake::RubyBreakerTestTask is supported.
3
+ * Manual modification is no longer required if run as a Rake task.
4
+ * Deprecating Breakable and Broken modules. Use breakable() method instead.
5
+
1
6
  # VERSION 0.0.4
2
7
  * RSpec is supported.
3
8
  * Namespace is recognized in type signatures.
data/NOTES ADDED
@@ -0,0 +1,9 @@
1
+
2
+ # Adding RDoc support:
3
+ * Use :rubybreaker: directive. This is needed.
4
+ * Register it using RDoc::Markup::Preprocess#register,preprocess.
5
+ * Use YAML to store the RubyBreaker result and load it when RDoc is run.
6
+ * The user program would use it in Rakefile.
7
+
8
+
9
+
data/README.md CHANGED
@@ -5,30 +5,30 @@
5
5
  RubyBreaker is a dynamic type documentation tool written in pure Ruby. It
6
6
  provides the framework for dynamically instrumenting a Ruby program to
7
7
  monitor objects during executions and document the observed type
8
- information. The type documentation generated by RubyBreaker is also an
9
- executable Ruby code. It contains type signatures that can be interpreted by
10
- RubyBreaker Runtime Library and can be used in future documentation of the
11
- program.
8
+ information. In other words, RubyBreaker "breaks" Ruby code out of its
9
+ obscurity and wildness (as in "code breaking" or "horse
10
+ breaking") by auto-documenting type information. The type documentation
11
+ generated by RubyBreaker is also an executable Ruby code that can be used as
12
+ an input to subsequent analyses.
12
13
 
13
14
  The primary goal of RubyBreaker is to assign a type signature to every
14
- method in designated modules and classes. A type signature is written in
15
- the RubyBreaker Type Annotation Language which resembles the documentation
16
- style used in Ruby API Doc. Overall, this tool should help Ruby programmers
17
- document their code more rigorously and effectively. Currently, manual
18
- modification of the user program is required to run RubyBreaker, but this is
19
- kept minimal.
15
+ method in selected modules and classes. A type signature is written in the
16
+ RubyBreaker Type Annotation Language which resembles the documentation style
17
+ used in Ruby API Doc. Manual code change is _not_ required if used in
18
+ Rakefile and is kept minimal if otherwise. Overall, this tool should help
19
+ Ruby programmers document their code more rigorously and effectively.
20
+
21
+ Current limitations are:
22
+
23
+ * Auto-documentation of block arguments (inherent)
24
+ * Parametric polymorphic types
25
+ * RDoc or YARD documentation support
20
26
 
21
27
  To contribute to the project, visit RubyBreaker's
22
28
  [GitHub page](http://github.com/rockalizer/rubybreaker) and
23
29
  [RubyGems page](http://rubygems.org/gems/rubybreaker). RubyBreaker RDoc can
24
30
  be found in [here](rdoc/index.html).
25
31
 
26
- ## Limitations
27
-
28
- * Block argument cannot be auto-documented. (Inherent)
29
- * Manual modification (minimal) of code is required.
30
- * Parametric polymorphic types are not supported.
31
-
32
32
  ## Requirements
33
33
 
34
34
  Ruby 1.9.x and TreeTop 1.x
@@ -39,15 +39,10 @@ following URL: [TreeTop](http://treetop.rubyforge.org/)
39
39
 
40
40
  ## Installation
41
41
 
42
- It is as simple as running the following:
42
+ It is as simple as running the following command:
43
43
 
44
44
  $ gem install rubybreaker
45
45
 
46
- You probably want to test out your installation by running
47
- `rake test` in your RubyBreaker directory:
48
-
49
- $ rake test
50
-
51
46
  * * *
52
47
 
53
48
  # Tutorial
@@ -57,213 +52,135 @@ Type Annotation Language, and the RubyBreaker Type System.
57
52
 
58
53
  ## Usage
59
54
 
60
- There are two ways to use RubyBreaker:
61
-
62
- $ rubybreaker prog.rb
63
-
64
- Or, use it as a Ruby library and just run the program on Ruby.
55
+ RubyBreaker takes advantage of test cases that already come with the source
56
+ program. It is recommended that RubyBreaker is run as a Rake task, which
57
+ requires a minimum code change in the Rakefile and no code change in the
58
+ source program. If not used as a Rake task, it requires a minimum code
59
+ change in each test case or the source program but should not affect the
60
+ development process much. Let's briefly see how RubyBreaker can be run
61
+ directly as a command-line program to understand the general concept of the
62
+ tool. We will explain how to use RubyBreaker in a Rakefile later.
65
63
 
66
- $ ruby prog.rb
64
+ $ rubybreaker -v prog.rb
67
65
 
68
- Both methods require manual modification of the code, but the former will
69
- generate the output into a separate `.rubybreaker` file whereas the latter
70
- will display the output on the screen. The former will also automatically
71
- import the `.rubybreaker` file for the user program of which the output is
72
- appended at the end. Consequently, this output/input file will grow as more
73
- analysis is done on the program.
66
+ This runs RubyBreaker in verbose mode on `prog.rb`. Note that RubyBreaker
67
+ will actually run `prog.rb` (by simply `require`ing the program file).
68
+ Somewhere in the program, there has to be a _program entry point_ to
69
+ indicate where the _monitoring_ of objects starts. Let's assume `prog.rb`
70
+ as the following:
74
71
 
75
- For example, let us assume `prog.rb` as the following:
76
-
77
- require "rubybreaker"
72
+ require "rubybreaker" # required if using "ruby" instead
78
73
  class A
79
- include RubyBreaker::Breakable
80
74
  def foo(x)
81
75
  x.to_s
82
76
  end
83
77
  end
84
78
  class B
85
- # include RubyBreaker::Breakable
86
79
  def bar(y,z)
87
80
  y.foo(z)
88
81
  end
89
82
  end
90
- RubyBreaker.monitor()
83
+ RubyBreaker.run(A, B)
91
84
  A.new.foo(1)
92
85
 
93
- Do not worry about other parts of the code for now. This example is to show
94
- how `foo` method is *typed* by RubyBreaker. After running `rubybreaker
95
- prog.rb`, the following output will be generated and saved into
96
- `prog.rubybreaker`.
86
+ This example will show how `A#foo` method is given a type by RubyBreaker.
87
+ After running `rubybreaker -v prog.rb`, the following output will be
88
+ generated and saved into `prog.rubybreaker.rb`.
97
89
 
90
+ # This file is auto-generated by RubyBreaker
98
91
  require "rubybreaker"
99
92
  class A
100
- include RubyBreaker::Broken
101
93
  typesig("foo(fixnum[to_s]) -> string")
102
94
  end
103
95
 
104
- Now, assume that the last line of `prog.rb` is changed to
105
- `B.new.bar(A.new,1)` and the `include` command in class `B` is uncommented.
106
- The subsequent analysis will generate the following result:
96
+ Here, the `typesig` method call registers `foo` as a method type that takes
97
+ an object that has `Fixnum#to_s` method and returns a `String`. This
98
+ method is made available by importing `rubybreaker`. Now, assume that an
99
+ additional code, `B.new.bar(A.new,1)`, is added at the end of `prog.rb`. The
100
+ subsequent run will generate the following result:
107
101
 
108
- # This is auto-generated by RubyBreaker
102
+ # This file is auto-generated by RubyBreaker
109
103
  require "rubybreaker"
110
104
  class A
111
- include RubyBreaker::Broken
112
105
  typesig("foo(fixnum[to_s]) -> string")
113
106
  end
114
107
  class B
115
- include RubyBreaker::Broken
116
108
  typesig("bar(a[foo], fixnum[to_s]) -> string")
117
109
  end
118
110
 
119
- RubyBreaker is designed to gather type information based on the actual
120
- execution of a program. This means the program should be equipped with
121
- test suites that cover a reasonable number of program paths for accurate
122
- results. Additionally, RubyBreaker assumes that test runs are correct
123
- and the program behaves correctly (for the test runs) as intended by
124
- the programmer. This assumption is not a strong requirement, but is
125
- necessary to obtain precise type information.
126
-
127
- In order to use RubyBreaker, there needs two kinds of manual code changes.
128
- First, the user must indicate which modules are subject to analysis and
129
- which modules can be used for the analysis. Next, the user has to indicate
130
- where the entry point of the program is. Alternatively, he has to make a
131
- small change to the test cases to use RubyBreaker's testing framework. (If
132
- you are using RSpec, there is no need for this change.)
133
-
134
- ### Breakable and Broken
135
-
136
- In order to indicate modules and classes that already have type information
137
- or to designate those that need to be auto-documented, the user must be
138
- familiar with the two most important modules of RubyBreaker--`Breakable` and
139
- `Broken`. The former refers to a module (or a class) that needs dynamic
140
- instrumentation and monitoring for getting type information. The latter
141
- refers to a module that have type information already documented in type
142
- signature form.
143
-
144
- For example, consider the following Ruby code:
111
+ Keep in mind that RubyBreaker is designed to gather type information based
112
+ on the _actual_ execution of the source program. This means the program
113
+ should be equipped with test cases that have a reasonable program path
114
+ coverage. Additionally, RubyBreaker assumes that test runs are correct and
115
+ the program behaves correctly (for those test runs) as intended by the
116
+ programmer. This assumption is not a strong requirement, but is necessary to
117
+ obtain precise and accurate type information.
145
118
 
146
- require "rubybreaker"
147
- class A
148
- include RubyBreaker::Breakable
149
- def foo(x)
150
- x.to_s
151
- end
152
- end
119
+ ### Using Ruby Unit Testing Framework
153
120
 
154
- By including `Breakable`, class `A` is subject to dynamic instrumentation
155
- and monitoring. On the other hand, the following class is a `Broken` module.
156
- (Yes, like a crazy wild horse that has been _broken_!)
121
+ Instead of manually inserting the entry point indicator into the program,
122
+ you can take advantage of Ruby's built-in testing framework. This is
123
+ preferred to modifying the source program directly, especially for the long
124
+ term program maintainability. But no worries! This method is as simple as
125
+ the previous one.
157
126
 
158
- require "rubybreaker"
159
- class B
160
- include RubyBreaker::Broken
161
- typesig("bar(fixnum[to_s]) -> string")
162
- def foo(x)
163
- x.to_s
127
+ require "test/unit"
128
+ require "rubybreaker" # This should come after test/unit.
129
+ class TestClassA < Test::Unit::TestCase
130
+ def setup()
131
+ RubyBreaker.breakable(Class1, Class2, ...)
132
+ ...
164
133
  end
134
+ # ...tests!...
165
135
  end
166
136
 
167
- This tells RubyBreaker that class `B` has type information in place, and
168
- therefore, it will use the information for analyzing `Breakable` modules
169
- elsewhere (if applicable). In this example, a method `foo` has a type
170
- signature `bar(fixnum[to_s]) -> string`, which means it takes an object that
171
- has `Fixnum`'s `to_s` method and returns a string. More detail on the type
172
- annotation language will be explained in later section.
137
+ That's it! The only requirements are to indicate to RubyBreaker which modules
138
+ and classes to "break" and to place `require rubybreaker` _after_
139
+ `require test/unit`.
173
140
 
174
- ### Hybrid of Breakable and Broken
175
-
176
- Starting from version 0.0.3, RubyBreaker allows a module to be declared as
177
- `Breakable` and `Broken` at the same time. If a method has a corresponding
178
- type signature (manually documented) somewhere, then RubyBreaker will not
179
- monitor it during runtime. All other methods will be instrumented and
180
- monitored by RubyBreaker.
181
-
182
- ### Class Methods
141
+ ### Using RSpec
183
142
 
184
- It is possible to include `Breakable` and/or `Broken` in an eigen-class to
185
- document class methods. To make this easier, RubyBreaker will automatically
186
- support auto-documentation and manual documentation of class methods if the
187
- original module is declared as `Breakable` and/or `Broken`,
188
- respectively--that is, up to immediate eigen class level of a "nominal"
189
- module. The following example shows how class methods can be
190
- auto-documented and manually documented, respectively.
143
+ The requirement is same for RSpec but use `before` instead of `setup` to
144
+ specify which modules and classes to "break".
191
145
 
146
+ require "rspec"
192
147
  require "rubybreaker"
193
- class A
194
- include RubyBreaker::Breakable
195
- class << self
196
- def foo(x); x.to_s end
197
- end
198
- end
199
- class B
200
- include RubyBreaker::Broken
201
- class << self
202
- typesig("foo(fixnum[to_s]) -> string")
203
- def foo(x); x.to_s end
204
- end
205
- end
206
-
207
- ### Program Entry Point
208
-
209
- In Ruby, as soon as a file is `require`d, the execution of that file begins.
210
- For RubyBreaker, however, it is not trivial to find the actual starting
211
- point of the program because there *has* to be a clear point in time at
212
- which monitoring of `Breakable` modules begins.
213
-
214
- Indicating the program entry point is simply done by inserting the following
215
- line at the code (assuming "`require 'rubybreaker'`" is already placed at
216
- the top of the file):
217
-
218
- RubyBreaker.monitor()
219
-
220
- It basically tells RubyBreaker to start monitoring. What really happens at
221
- this point is that all `Breakable` modules are dynamically instrumented so
222
- that they are ready to be monitored. Any execution after this point will
223
- run the instrumented code (for `Breakable` modules) which will gather type
224
- information for methods.
225
-
226
- Although this seems simple and easy, this is not the recommended way for
227
- analyzing a program. Why? Because RubyBreaker comes with a replacement for
228
- the built-in testing framework for Ruby. Even better, if you are using
229
- RSpec, there is no need to change any test code.
230
-
231
- ### Using the Built-in Testing Framework
232
148
 
233
- Instead of manually inserting the entry point indicator into the program,
234
- the user can take advantage of the Ruby Unit Test framework. This is the
235
- recommended way of using RubyBreaker, especially for a long term program
236
- maintainability. But no worries! This method is as simple as the previous
237
- one.
238
-
239
- require "rubybreaker"
240
- require "test/unit"
241
- class TestClassA < Test::Unit::TestCase
242
- include RubyBreaker::TestCase
149
+ describe "TestClassA Test"
150
+ before { RubyBreaker.breakable(Class1, Class2, ...) }
151
+ ...
243
152
  # ...tests!...
244
153
  end
245
154
 
246
- That's it! Also, remember that classes and modules can be re-opened for
247
- "patches" in Ruby. This means that the original classes or modules do not
248
- need to be modified to include `Broken` and/or `Breakable`. In each test
249
- suite or test case, those classes and modules can be re-opened to include
250
- `Broken` and/or `Breakable`. The following shows an example of such a test
251
- case.
252
-
253
- require "rubybreaker"
254
- require "test/unit"
255
- class A
256
- include RubyBreaker::Breakable
257
- end
258
- class TestClassA < Test::Unit::TestCase
259
- ...
155
+ ### Using Rakefile
156
+
157
+ By running RubyBreaker along with the Rakefile, you can avoid modifying the
158
+ source program at all. (You no longer need to import `rubybreaker` in the
159
+ test cases neither.) Therefore, this is the recommended way to use
160
+ RubyBreaker. The following code snippet describes how it can be done:
161
+
162
+ require "rubybreaker/task"
163
+ ...
164
+ desc "Run RubyBreaker"
165
+ Rake::RubyBreakerTestTask.new(:"rubybreaker") do |t|
166
+ t.libs << "lib"
167
+ t.test_files = ["test/foo/tc_foo1.rb"]
168
+ # ...Other test task options..
169
+ t.rubybreaker_opts << "-v" # run in verbose mode
170
+ t.breakable = ["Class1", "Class2", ...] # specify what to monitor
260
171
  end
261
172
 
262
- ### Using RSpec
173
+ Note that `RubyBrakerTestTask` can simply replace your `TestTask` block in
174
+ Rakefile. In fact, the former is a subclass of the latter and includes all
175
+ features supported by the latter. The only additional options are
176
+ `rubybreaker_opts` which is RubyBreaker's command-line options and
177
+ `breakable` which specifies which modules and classes to monitor. Since
178
+ `Class1` and `Class2` are not _recognized_ by this Rakefile, you must use
179
+ string literals to specify modules and classes (and with full namespace).
263
180
 
264
- If using RSpec, it is even easier! No changes are needed for the test code.
265
- Really! _Well, it is still necessary to `require rubybreaker` and manually
266
- insert `Breakable` and `Broken` to appropriate classes and modules._
181
+ If this is the route you are taking, there needs no editing of the source
182
+ program whatsoever. This task will take care of instrumenting the specified
183
+ modules and classes at proper moments.
267
184
 
268
185
  ## Type Annotation
269
186
 
@@ -423,7 +340,7 @@ subsequent "promotions").
423
340
  ## Type System
424
341
 
425
342
  RubyBreaker comes with its own type system to auto-document the type
426
- information. Each method in a `Breakable` module is dynamically instrumented
343
+ information. Each method in a "breakable" module is dynamically instrumented
427
344
  to be monitored during runtime. This monitoring code observes the types of
428
345
  the arguments, block, and return value of each method. Once this information
429
346
  is gathered, RubyBreaker will compare it to the information gathered so far.
data/Rakefile CHANGED
@@ -5,6 +5,7 @@ require "rake"
5
5
  require "rake/testtask"
6
6
  require "rdoc/task"
7
7
  require "rake/clean"
8
+ require_relative "lib/rubybreaker/task"
8
9
 
9
10
  begin
10
11
  require "rdiscount" # used to generate the doc html page
@@ -21,15 +22,21 @@ end
21
22
  # Use rake/clean to remove generated files
22
23
  CLEAN.concat(FileList["webpage/rdoc",
23
24
  "rubybreaker-*.gem",
24
- "webpage/index.html",
25
- "lib/rubybreaker/type/type_grammar.rb"
26
- ])
25
+ "webpage/index.html",
26
+ "*.rubybreaker.rb",
27
+ "lib/rubybreaker/type/type_grammar.rb"])
27
28
 
28
29
  # If no task specified, do test
29
- task :default => [:test]
30
+ task :default => [:test, :testtask_test]
30
31
 
31
32
  desc "Do all"
32
- task :all => [:parser, :test, :rspec, :rdoc, :webpage, :gem] do |t|
33
+ task :all => [:parser,
34
+ :test,
35
+ :testtask_test,
36
+ :rspec,
37
+ :rdoc,
38
+ :webpage,
39
+ :gem] do |t|
33
40
  end
34
41
 
35
42
  desc "Generate gemspec"
@@ -40,7 +47,7 @@ end
40
47
  Rake::RDocTask.new do |rd|
41
48
  rd.rdoc_dir = "#{File.dirname(__FILE__)}/webpage/rdoc"
42
49
  rd.rdoc_files.include("lib/**/*.rb")
43
- rd.rdoc_files.exclude("lib/rubybreaker/rubylib/*.rb", "lib/rubybreaker/type/type_grammar.rb")
50
+ rd.rdoc_files.exclude("lib/rubybreaker/type/type_grammar.rb")
44
51
  end
45
52
 
46
53
  desc "Generate the webpage"
@@ -69,9 +76,17 @@ Rake::TestTask.new(:"test") do |t|
69
76
  t.libs << "lib"
70
77
  test_files = FileList["test/ts_*.rb"]
71
78
  test_files.exclude("test/ts_rspec.rb")
79
+ test_files.exclude("test/ts_testtask.rb")
72
80
  t.test_files = test_files
73
81
  end
74
82
 
83
+ desc "Run rubybreaker testtask test"
84
+ Rake::RubyBreakerTestTask.new(:"testtask_test") do |t|
85
+ t.libs << "lib" << "test/tc_testtask/sample.rb"
86
+ t.test_files = ["test/testtask/tc_testtask.rb"]
87
+ t.breakable = ["SampleClassA"]
88
+ end
89
+
75
90
  if defined?(RSpec)
76
91
  desc "Run RSpec test"
77
92
  RSpec::Core::RakeTask.new(:rspec) do |t|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.4
1
+ 0.0.5
data/bin/rubybreaker CHANGED
@@ -1,72 +1,56 @@
1
1
  #!/usr/bin/env ruby
2
- require "optparse"
3
-
4
2
  require_relative "../lib/rubybreaker"
5
3
 
6
4
  module RubyBreaker
7
5
 
8
- # This method is the main method for running RubyBreaker as a shell
9
- # program.
10
- def self.main()
11
-
12
- option_parser = OptionParser.new do |opts|
13
-
14
- opts.banner = "Usage: #{File.basename(__FILE__)} [options] in_file[.rb]"
15
-
16
- opts.on("--debug", "Run in debug mode") do
17
- OPTIONS[:debug] = true
18
- end
19
-
20
- opts.on("-f","--io-file FILE","Specify an input/output file") do |f|
21
- OPTIONS[:output] = f
22
- end
23
-
24
- opts.on("-s","--[no-]stdout","Show output on the screen") do |b|
25
- OPTIONS[:stdout] = b
26
- end
27
-
28
- opts.on("-a", "--[no-]append", "Append output to the input file") do |b|
29
- OPTIONS[:append] = b
30
- end
6
+ # This method shows the banner and exits with code 1.
7
+ def self.show_banner_and_exit()
8
+ puts OPTION_PARSER.banner
9
+ exit(1)
10
+ end
31
11
 
32
- opts.on("-v","--verbose","Show messages in detail") do
33
- OPTIONS[:verbose] = true
34
- end
12
+ # This method prepares shell mode execution of RubyBreaker.
13
+ def self.main()
14
+ RubyBreaker.setup_logger()
15
+ RubyBreaker.verbose("Running RubyBreaker in shell mode")
35
16
 
36
- opts.on("--[no-]rubylib", "Use Core Ruby Library documentation") do |b|
37
- OPTIONS[:rubylib] = b
38
- end
17
+ # parse the command-line arguments
18
+ OPTION_PARSER.parse!
39
19
 
40
- opts.on("-h","--help","Show this help text") do
41
- puts opts
42
- exit
43
- end
20
+ # Show copyright info if verbose
21
+ puts COPYRIGHT if OPTIONS[:verbose]
44
22
 
45
- end
23
+ # Quit if there is program specified.
24
+ self.show_banner_and_exit() if ARGV.length != 1
46
25
 
47
- option_parser.parse!
26
+ # Get the specified program.
27
+ prog = ARGV[0]
28
+ prog_file = File.expand_path(prog)
48
29
 
49
- OPTIONS[:mode] = :bin # indicate that RubyBreaker is being run as a
50
- # binary (program).
51
-
52
- if OPTIONS[:verbose] # Show copyright info only when verbose
53
- puts COPYRIGHT
54
- puts
55
- end
30
+ # It is ok to omit .rb extension. So try to see if prog_file.rb exists
31
+ if !File.exist?(prog_file) && !File.extname(prog_file) == ".rb"
32
+ prog_file = "#{prog_file}.rb"
33
+ end
56
34
 
57
- # There has to be an input file
58
- if ARGV.length < 1 then
59
- puts option_parser.banner
35
+ # Quit the specified program does not exist.
36
+ if !File.exist?(prog_file)
37
+ fatal("#{ARGV[0]} is an invalid file.")
60
38
  exit(1)
61
39
  end
62
40
 
63
- OPTIONS[:file] = ARGV[0]
41
+ # Remember the program path for later use
42
+ OPTIONS[:prog_file] = prog_file
64
43
 
65
- Main.run()
44
+ # Run the program file!
45
+ self.verbose("Running #{prog}")
46
+ eval "require '#{prog_file}'", TOPLEVEL_BINDING
47
+ self.verbose("Done running #{prog}")
66
48
 
49
+ # Keep in mind that the source program must specify the entry
50
+ # point--using RubyBreaker.run()--in order to observe the type
51
+ # information.
67
52
  end
68
53
 
69
54
  end
70
55
 
71
56
  RubyBreaker.main()
72
-
@@ -8,6 +8,12 @@ require_relative "context"
8
8
 
9
9
  module RubyBreaker
10
10
 
11
+ # This method returns true if the logger is already created and false
12
+ # otherwise.
13
+ def self.defined_logger?()
14
+ return defined?(LOGGER)
15
+ end
16
+
11
17
  # This sets up the logger for debugging RubyBreaker
12
18
  def self.setup_logger #:nodoc:
13
19
  return if defined?(LOGGER)
@@ -0,0 +1,37 @@
1
+ require "yaml"
2
+ require_relative "../type"
3
+
4
+ module RubyBreaker
5
+
6
+ # This module has functionalities that are necessary for supporting RDoc
7
+ # output
8
+ module RDocSupport
9
+
10
+ include TypeDefs
11
+
12
+ # This array keeps track of modules/classes whose type information is
13
+ # documented.
14
+ DOCUMENTED = {} # module => method map
15
+
16
+ # This method exports the RubyBreaker output into a yaml file.
17
+ def self.export_to_yaml(yaml_file, breakable_modules, broken_modules)
18
+ hash = {
19
+ breakable: breakable_modules,
20
+ broken: broken_modules
21
+ }
22
+ File.open(yaml_file, "w") do |f|
23
+ f.puts YAML.dump(hash)
24
+ end
25
+ end
26
+
27
+ # This method imports the RubyBreaker output from a yaml file.
28
+ def self.import_from_yaml(yaml_file)
29
+ File.open(yaml_file, "r") do |f|
30
+ raw = f.read
31
+ hash = YAML.to_hash(raw)
32
+ end
33
+ end
34
+
35
+ end
36
+
37
+ end
@@ -0,0 +1,3 @@
1
+
2
+ require_relative "doc/rdoc"
3
+