laser 0.7.0.pre1

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.
Files changed (319) hide show
  1. data/.document +5 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +14 -0
  4. data/LICENSE +661 -0
  5. data/README.md +158 -0
  6. data/Rakefile +104 -0
  7. data/VERSION +1 -0
  8. data/bin/laser +7 -0
  9. data/design_docs/goals.md +57 -0
  10. data/design_docs/object_regex.md +426 -0
  11. data/design_docs/type_annotations.md +80 -0
  12. data/ext/laser/BasicBlock.cpp +572 -0
  13. data/ext/laser/BasicBlock.h +118 -0
  14. data/ext/laser/extconf.rb +3 -0
  15. data/features/laser.feature +25 -0
  16. data/features/step_definitions/laser_steps.rb +39 -0
  17. data/features/support/env.rb +14 -0
  18. data/features/support/testdata/1_input +1 -0
  19. data/features/support/testdata/1_output +1 -0
  20. data/features/support/testdata/2_input +4 -0
  21. data/features/support/testdata/2_output +4 -0
  22. data/features/support/testdata/3_input +8 -0
  23. data/features/support/testdata/3_output +11 -0
  24. data/features/support/testdata/4_input +5 -0
  25. data/features/support/testdata/4_output +5 -0
  26. data/features/support/testdata/5_input +13 -0
  27. data/laser.gemspec +382 -0
  28. data/lib/laser.rb +98 -0
  29. data/lib/laser/analysis/annotations.rb +95 -0
  30. data/lib/laser/analysis/annotations/annotation_config.yaml +3 -0
  31. data/lib/laser/analysis/annotations/comment_attachment_annotation.rb +66 -0
  32. data/lib/laser/analysis/annotations/node_pointers_annotation.rb +36 -0
  33. data/lib/laser/analysis/annotations/runtime_annotation.rb +55 -0
  34. data/lib/laser/analysis/argument_expansion.rb +132 -0
  35. data/lib/laser/analysis/arity.rb +34 -0
  36. data/lib/laser/analysis/bindings.rb +144 -0
  37. data/lib/laser/analysis/bootstrap/bootstrap.rb +298 -0
  38. data/lib/laser/analysis/bootstrap/laser_class.rb +106 -0
  39. data/lib/laser/analysis/bootstrap/laser_method.rb +255 -0
  40. data/lib/laser/analysis/bootstrap/laser_module.rb +403 -0
  41. data/lib/laser/analysis/bootstrap/laser_module_copy.rb +74 -0
  42. data/lib/laser/analysis/bootstrap/laser_object.rb +69 -0
  43. data/lib/laser/analysis/bootstrap/laser_proc.rb +150 -0
  44. data/lib/laser/analysis/bootstrap/laser_singleton_class.rb +44 -0
  45. data/lib/laser/analysis/comments.rb +35 -0
  46. data/lib/laser/analysis/control_flow.rb +28 -0
  47. data/lib/laser/analysis/control_flow/alias_analysis.rb +31 -0
  48. data/lib/laser/analysis/control_flow/basic_block.rb +105 -0
  49. data/lib/laser/analysis/control_flow/cfg_builder.rb +2505 -0
  50. data/lib/laser/analysis/control_flow/cfg_instruction.rb +190 -0
  51. data/lib/laser/analysis/control_flow/constant_propagation.rb +742 -0
  52. data/lib/laser/analysis/control_flow/control_flow_graph.rb +370 -0
  53. data/lib/laser/analysis/control_flow/lifetime_analysis.rb +91 -0
  54. data/lib/laser/analysis/control_flow/method_call_search.rb +26 -0
  55. data/lib/laser/analysis/control_flow/raise_properties.rb +25 -0
  56. data/lib/laser/analysis/control_flow/simulation.rb +385 -0
  57. data/lib/laser/analysis/control_flow/static_single_assignment.rb +185 -0
  58. data/lib/laser/analysis/control_flow/unreachability_analysis.rb +57 -0
  59. data/lib/laser/analysis/control_flow/unused_variables.rb +91 -0
  60. data/lib/laser/analysis/control_flow/yield_properties.rb +103 -0
  61. data/lib/laser/analysis/errors.rb +131 -0
  62. data/lib/laser/analysis/laser_utils.rb +18 -0
  63. data/lib/laser/analysis/lexical_analysis.rb +172 -0
  64. data/lib/laser/analysis/method_call.rb +68 -0
  65. data/lib/laser/analysis/protocol_registry.rb +30 -0
  66. data/lib/laser/analysis/scope.rb +118 -0
  67. data/lib/laser/analysis/sexp.rb +159 -0
  68. data/lib/laser/analysis/sexp_analysis.rb +40 -0
  69. data/lib/laser/analysis/sexp_extensions/constant_extraction.rb +115 -0
  70. data/lib/laser/analysis/sexp_extensions/source_location.rb +164 -0
  71. data/lib/laser/analysis/sexp_extensions/type_inference.rb +47 -0
  72. data/lib/laser/analysis/signature.rb +76 -0
  73. data/lib/laser/analysis/special_methods/send.rb +67 -0
  74. data/lib/laser/analysis/unused_methods.rb +21 -0
  75. data/lib/laser/analysis/visitor.rb +141 -0
  76. data/lib/laser/annotation_parser/annotations.treetop +126 -0
  77. data/lib/laser/annotation_parser/annotations_parser.rb +748 -0
  78. data/lib/laser/annotation_parser/class_annotations.treetop +82 -0
  79. data/lib/laser/annotation_parser/class_annotations_parser.rb +654 -0
  80. data/lib/laser/annotation_parser/overload.treetop +24 -0
  81. data/lib/laser/annotation_parser/overload_parser.rb +167 -0
  82. data/lib/laser/annotation_parser/parsers.rb +6 -0
  83. data/lib/laser/annotation_parser/structural.treetop +37 -0
  84. data/lib/laser/annotation_parser/structural_parser.rb +406 -0
  85. data/lib/laser/annotation_parser/useful_parsers.treetop +47 -0
  86. data/lib/laser/annotation_parser/useful_parsers_parser.rb +674 -0
  87. data/lib/laser/rake/task.rb +46 -0
  88. data/lib/laser/runner.rb +189 -0
  89. data/lib/laser/scanner.rb +169 -0
  90. data/lib/laser/standard_library/_thread.rb +110 -0
  91. data/lib/laser/standard_library/abbrev.rb +103 -0
  92. data/lib/laser/standard_library/array.rb +418 -0
  93. data/lib/laser/standard_library/base64.rb +91 -0
  94. data/lib/laser/standard_library/basic_object.rb +55 -0
  95. data/lib/laser/standard_library/benchmark.rb +556 -0
  96. data/lib/laser/standard_library/bignum.rb +185 -0
  97. data/lib/laser/standard_library/cgi.rb +275 -0
  98. data/lib/laser/standard_library/cgi/cookie.rb +147 -0
  99. data/lib/laser/standard_library/cgi/core.rb +791 -0
  100. data/lib/laser/standard_library/cgi/html.rb +1021 -0
  101. data/lib/laser/standard_library/cgi/session.rb +537 -0
  102. data/lib/laser/standard_library/cgi/session/pstore.rb +111 -0
  103. data/lib/laser/standard_library/cgi/util.rb +188 -0
  104. data/lib/laser/standard_library/class_definitions.rb +333 -0
  105. data/lib/laser/standard_library/comparable.rb +125 -0
  106. data/lib/laser/standard_library/complex.rb +162 -0
  107. data/lib/laser/standard_library/enumerable.rb +178 -0
  108. data/lib/laser/standard_library/exceptions.rb +135 -0
  109. data/lib/laser/standard_library/fixnum.rb +188 -0
  110. data/lib/laser/standard_library/float.rb +180 -0
  111. data/lib/laser/standard_library/hash.rb +237 -0
  112. data/lib/laser/standard_library/integer.rb +123 -0
  113. data/lib/laser/standard_library/laser_magic.rb +7 -0
  114. data/lib/laser/standard_library/nil_false_true.rb +113 -0
  115. data/lib/laser/standard_library/numbers.rb +192 -0
  116. data/lib/laser/standard_library/proc.rb +31 -0
  117. data/lib/laser/standard_library/set.rb +1348 -0
  118. data/lib/laser/standard_library/string.rb +666 -0
  119. data/lib/laser/standard_library/stringio.rb +2 -0
  120. data/lib/laser/standard_library/symbol.rb +125 -0
  121. data/lib/laser/standard_library/tsort.rb +242 -0
  122. data/lib/laser/support/acts_as_struct.rb +66 -0
  123. data/lib/laser/support/frequency.rb +55 -0
  124. data/lib/laser/support/inheritable_attributes.rb +145 -0
  125. data/lib/laser/support/module_extensions.rb +94 -0
  126. data/lib/laser/support/placeholder_object.rb +13 -0
  127. data/lib/laser/third_party/rgl/adjacency.rb +221 -0
  128. data/lib/laser/third_party/rgl/base.rb +228 -0
  129. data/lib/laser/third_party/rgl/bidirectional.rb +39 -0
  130. data/lib/laser/third_party/rgl/condensation.rb +47 -0
  131. data/lib/laser/third_party/rgl/connected_components.rb +138 -0
  132. data/lib/laser/third_party/rgl/control_flow.rb +170 -0
  133. data/lib/laser/third_party/rgl/depth_first_spanning_tree.rb +37 -0
  134. data/lib/laser/third_party/rgl/dominators.rb +124 -0
  135. data/lib/laser/third_party/rgl/dot.rb +93 -0
  136. data/lib/laser/third_party/rgl/graphxml.rb +51 -0
  137. data/lib/laser/third_party/rgl/implicit.rb +174 -0
  138. data/lib/laser/third_party/rgl/mutable.rb +117 -0
  139. data/lib/laser/third_party/rgl/rdot.rb +445 -0
  140. data/lib/laser/third_party/rgl/topsort.rb +72 -0
  141. data/lib/laser/third_party/rgl/transitivity.rb +180 -0
  142. data/lib/laser/third_party/rgl/traversal.rb +348 -0
  143. data/lib/laser/types/types.rb +433 -0
  144. data/lib/laser/version.rb +14 -0
  145. data/lib/laser/warning.rb +149 -0
  146. data/lib/laser/warning_sets/default.yml +13 -0
  147. data/lib/laser/warnings/assignment_in_condition.rb +20 -0
  148. data/lib/laser/warnings/comment_spacing.rb +31 -0
  149. data/lib/laser/warnings/extra_blank_lines.rb +30 -0
  150. data/lib/laser/warnings/extra_whitespace.rb +16 -0
  151. data/lib/laser/warnings/hash_symbol_18_warning.rb +63 -0
  152. data/lib/laser/warnings/hash_symbol_19_warning.rb +29 -0
  153. data/lib/laser/warnings/line_length.rb +115 -0
  154. data/lib/laser/warnings/misaligned_unindentation.rb +17 -0
  155. data/lib/laser/warnings/operator_spacing.rb +68 -0
  156. data/lib/laser/warnings/parens_on_declaration.rb +30 -0
  157. data/lib/laser/warnings/rescue_exception.rb +42 -0
  158. data/lib/laser/warnings/semicolon.rb +25 -0
  159. data/lib/laser/warnings/sexp_errors.rb +24 -0
  160. data/lib/laser/warnings/uncalled_method_warning.rb +7 -0
  161. data/lib/laser/warnings/useless_double_quotes.rb +38 -0
  162. data/spec/analysis_specs/annotations_spec.rb +47 -0
  163. data/spec/analysis_specs/annotations_specs/comment_attachment_spec.rb +68 -0
  164. data/spec/analysis_specs/annotations_specs/node_pointers_annotation_spec.rb +90 -0
  165. data/spec/analysis_specs/annotations_specs/runtime_annotation_spec.rb +135 -0
  166. data/spec/analysis_specs/annotations_specs/spec_helper.rb +33 -0
  167. data/spec/analysis_specs/argument_expansion_spec.rb +113 -0
  168. data/spec/analysis_specs/bindings_spec.rb +36 -0
  169. data/spec/analysis_specs/comment_spec.rb +93 -0
  170. data/spec/analysis_specs/control_flow_specs/cfg_instruction_spec.rb +111 -0
  171. data/spec/analysis_specs/control_flow_specs/constant_propagation_spec.rb +560 -0
  172. data/spec/analysis_specs/control_flow_specs/control_flow_graph_spec.rb +5 -0
  173. data/spec/analysis_specs/control_flow_specs/raise_properties_spec.rb +310 -0
  174. data/spec/analysis_specs/control_flow_specs/raise_type_inference_spec.rb +301 -0
  175. data/spec/analysis_specs/control_flow_specs/return_type_inference_spec.rb +431 -0
  176. data/spec/analysis_specs/control_flow_specs/simulation_spec.rb +158 -0
  177. data/spec/analysis_specs/control_flow_specs/spec_helper.rb +110 -0
  178. data/spec/analysis_specs/control_flow_specs/tuple_misuse_inference_spec.rb +125 -0
  179. data/spec/analysis_specs/control_flow_specs/unreachability_analysis_spec.rb +76 -0
  180. data/spec/analysis_specs/control_flow_specs/unused_variable_spec.rb +99 -0
  181. data/spec/analysis_specs/control_flow_specs/yield_properties_spec.rb +372 -0
  182. data/spec/analysis_specs/error_spec.rb +30 -0
  183. data/spec/analysis_specs/laser_class_spec.rb +322 -0
  184. data/spec/analysis_specs/lexical_analysis_spec.rb +184 -0
  185. data/spec/analysis_specs/protocol_registry_spec.rb +63 -0
  186. data/spec/analysis_specs/scope_annotation_spec.rb +1013 -0
  187. data/spec/analysis_specs/scope_spec.rb +126 -0
  188. data/spec/analysis_specs/sexp_analysis_spec.rb +30 -0
  189. data/spec/analysis_specs/sexp_extension_specs/constant_extraction_spec.rb +309 -0
  190. data/spec/analysis_specs/sexp_extension_specs/source_location_spec.rb +231 -0
  191. data/spec/analysis_specs/sexp_extension_specs/spec_helper.rb +1 -0
  192. data/spec/analysis_specs/sexp_extension_specs/type_inference_spec.rb +252 -0
  193. data/spec/analysis_specs/sexp_spec.rb +167 -0
  194. data/spec/analysis_specs/spec_helper.rb +27 -0
  195. data/spec/analysis_specs/unused_methods_spec.rb +65 -0
  196. data/spec/analysis_specs/visitor_spec.rb +64 -0
  197. data/spec/annotation_parser_specs/annotations_parser_spec.rb +89 -0
  198. data/spec/annotation_parser_specs/class_annotation_parser_spec.rb +120 -0
  199. data/spec/annotation_parser_specs/overload_parser_spec.rb +39 -0
  200. data/spec/annotation_parser_specs/parsers_spec.rb +14 -0
  201. data/spec/annotation_parser_specs/spec_helper.rb +1 -0
  202. data/spec/annotation_parser_specs/structural_parser_spec.rb +67 -0
  203. data/spec/laser_spec.rb +14 -0
  204. data/spec/rake_specs/spec_helper.rb +1 -0
  205. data/spec/rake_specs/task_spec.rb +67 -0
  206. data/spec/runner_spec.rb +207 -0
  207. data/spec/scanner_spec.rb +75 -0
  208. data/spec/spec_helper.rb +121 -0
  209. data/spec/standard_library/exceptions_spec.rb +19 -0
  210. data/spec/standard_library/globals_spec.rb +14 -0
  211. data/spec/standard_library/set_spec.rb +31 -0
  212. data/spec/standard_library/spec_helper.rb +1 -0
  213. data/spec/standard_library/standard_library_spec.rb +302 -0
  214. data/spec/support_specs/acts_as_struct_spec.rb +94 -0
  215. data/spec/support_specs/frequency_spec.rb +23 -0
  216. data/spec/support_specs/module_extensions_spec.rb +117 -0
  217. data/spec/support_specs/spec_helper.rb +1 -0
  218. data/spec/type_specs/spec_helper.rb +1 -0
  219. data/spec/type_specs/types_spec.rb +133 -0
  220. data/spec/warning_spec.rb +95 -0
  221. data/spec/warning_specs/assignment_in_condition_spec.rb +68 -0
  222. data/spec/warning_specs/comment_spacing_spec.rb +65 -0
  223. data/spec/warning_specs/extra_blank_lines_spec.rb +70 -0
  224. data/spec/warning_specs/extra_whitespace_spec.rb +33 -0
  225. data/spec/warning_specs/hash_symbol_18_warning_spec.rb +89 -0
  226. data/spec/warning_specs/hash_symbol_19_warning_spec.rb +63 -0
  227. data/spec/warning_specs/line_length_spec.rb +173 -0
  228. data/spec/warning_specs/misaligned_unindentation_spec.rb +35 -0
  229. data/spec/warning_specs/operator_spacing_spec.rb +104 -0
  230. data/spec/warning_specs/parens_on_declaration_spec.rb +57 -0
  231. data/spec/warning_specs/rescue_exception_spec.rb +105 -0
  232. data/spec/warning_specs/semicolon_spec.rb +58 -0
  233. data/spec/warning_specs/spec_helper.rb +1 -0
  234. data/spec/warning_specs/useless_double_quotes_spec.rb +74 -0
  235. data/status_reports/2010/12/2010-12-14.md +163 -0
  236. data/status_reports/2010/12/2010-12-23.md +298 -0
  237. data/status_reports/2010/12/2010-12-24.md +6 -0
  238. data/test/third_party_tests/rgl_tests/TestComponents.rb +65 -0
  239. data/test/third_party_tests/rgl_tests/TestCycles.rb +61 -0
  240. data/test/third_party_tests/rgl_tests/TestDirectedGraph.rb +125 -0
  241. data/test/third_party_tests/rgl_tests/TestDot.rb +18 -0
  242. data/test/third_party_tests/rgl_tests/TestEdge.rb +34 -0
  243. data/test/third_party_tests/rgl_tests/TestGraph.rb +71 -0
  244. data/test/third_party_tests/rgl_tests/TestGraphXML.rb +57 -0
  245. data/test/third_party_tests/rgl_tests/TestImplicit.rb +52 -0
  246. data/test/third_party_tests/rgl_tests/TestRdot.rb +863 -0
  247. data/test/third_party_tests/rgl_tests/TestTransitivity.rb +129 -0
  248. data/test/third_party_tests/rgl_tests/TestTraversal.rb +220 -0
  249. data/test/third_party_tests/rgl_tests/TestUnDirectedGraph.rb +102 -0
  250. data/test/third_party_tests/rgl_tests/examples/north/Graph.log +128 -0
  251. data/test/third_party_tests/rgl_tests/examples/north/g.10.0.graphml +28 -0
  252. data/test/third_party_tests/rgl_tests/examples/north/g.10.1.graphml +28 -0
  253. data/test/third_party_tests/rgl_tests/examples/north/g.10.11.graphml +31 -0
  254. data/test/third_party_tests/rgl_tests/examples/north/g.10.12.graphml +27 -0
  255. data/test/third_party_tests/rgl_tests/examples/north/g.10.13.graphml +27 -0
  256. data/test/third_party_tests/rgl_tests/examples/north/g.10.14.graphml +27 -0
  257. data/test/third_party_tests/rgl_tests/examples/north/g.10.15.graphml +26 -0
  258. data/test/third_party_tests/rgl_tests/examples/north/g.10.16.graphml +26 -0
  259. data/test/third_party_tests/rgl_tests/examples/north/g.10.17.graphml +26 -0
  260. data/test/third_party_tests/rgl_tests/examples/north/g.10.19.graphml +37 -0
  261. data/test/third_party_tests/rgl_tests/examples/north/g.10.2.graphml +28 -0
  262. data/test/third_party_tests/rgl_tests/examples/north/g.10.20.graphml +38 -0
  263. data/test/third_party_tests/rgl_tests/examples/north/g.10.22.graphml +43 -0
  264. data/test/third_party_tests/rgl_tests/examples/north/g.10.24.graphml +30 -0
  265. data/test/third_party_tests/rgl_tests/examples/north/g.10.25.graphml +45 -0
  266. data/test/third_party_tests/rgl_tests/examples/north/g.10.27.graphml +38 -0
  267. data/test/third_party_tests/rgl_tests/examples/north/g.10.28.graphml +30 -0
  268. data/test/third_party_tests/rgl_tests/examples/north/g.10.29.graphml +38 -0
  269. data/test/third_party_tests/rgl_tests/examples/north/g.10.3.graphml +26 -0
  270. data/test/third_party_tests/rgl_tests/examples/north/g.10.30.graphml +34 -0
  271. data/test/third_party_tests/rgl_tests/examples/north/g.10.31.graphml +42 -0
  272. data/test/third_party_tests/rgl_tests/examples/north/g.10.34.graphml +42 -0
  273. data/test/third_party_tests/rgl_tests/examples/north/g.10.37.graphml +28 -0
  274. data/test/third_party_tests/rgl_tests/examples/north/g.10.38.graphml +38 -0
  275. data/test/third_party_tests/rgl_tests/examples/north/g.10.39.graphml +36 -0
  276. data/test/third_party_tests/rgl_tests/examples/north/g.10.4.graphml +26 -0
  277. data/test/third_party_tests/rgl_tests/examples/north/g.10.40.graphml +37 -0
  278. data/test/third_party_tests/rgl_tests/examples/north/g.10.41.graphml +37 -0
  279. data/test/third_party_tests/rgl_tests/examples/north/g.10.42.graphml +26 -0
  280. data/test/third_party_tests/rgl_tests/examples/north/g.10.45.graphml +28 -0
  281. data/test/third_party_tests/rgl_tests/examples/north/g.10.46.graphml +32 -0
  282. data/test/third_party_tests/rgl_tests/examples/north/g.10.5.graphml +31 -0
  283. data/test/third_party_tests/rgl_tests/examples/north/g.10.50.graphml +30 -0
  284. data/test/third_party_tests/rgl_tests/examples/north/g.10.56.graphml +29 -0
  285. data/test/third_party_tests/rgl_tests/examples/north/g.10.57.graphml +32 -0
  286. data/test/third_party_tests/rgl_tests/examples/north/g.10.58.graphml +32 -0
  287. data/test/third_party_tests/rgl_tests/examples/north/g.10.6.graphml +26 -0
  288. data/test/third_party_tests/rgl_tests/examples/north/g.10.60.graphml +32 -0
  289. data/test/third_party_tests/rgl_tests/examples/north/g.10.61.graphml +34 -0
  290. data/test/third_party_tests/rgl_tests/examples/north/g.10.62.graphml +34 -0
  291. data/test/third_party_tests/rgl_tests/examples/north/g.10.68.graphml +30 -0
  292. data/test/third_party_tests/rgl_tests/examples/north/g.10.69.graphml +32 -0
  293. data/test/third_party_tests/rgl_tests/examples/north/g.10.7.graphml +29 -0
  294. data/test/third_party_tests/rgl_tests/examples/north/g.10.70.graphml +26 -0
  295. data/test/third_party_tests/rgl_tests/examples/north/g.10.71.graphml +27 -0
  296. data/test/third_party_tests/rgl_tests/examples/north/g.10.72.graphml +28 -0
  297. data/test/third_party_tests/rgl_tests/examples/north/g.10.74.graphml +29 -0
  298. data/test/third_party_tests/rgl_tests/examples/north/g.10.75.graphml +29 -0
  299. data/test/third_party_tests/rgl_tests/examples/north/g.10.78.graphml +27 -0
  300. data/test/third_party_tests/rgl_tests/examples/north/g.10.79.graphml +34 -0
  301. data/test/third_party_tests/rgl_tests/examples/north/g.10.8.graphml +29 -0
  302. data/test/third_party_tests/rgl_tests/examples/north/g.10.80.graphml +34 -0
  303. data/test/third_party_tests/rgl_tests/examples/north/g.10.82.graphml +35 -0
  304. data/test/third_party_tests/rgl_tests/examples/north/g.10.83.graphml +32 -0
  305. data/test/third_party_tests/rgl_tests/examples/north/g.10.85.graphml +34 -0
  306. data/test/third_party_tests/rgl_tests/examples/north/g.10.86.graphml +34 -0
  307. data/test/third_party_tests/rgl_tests/examples/north/g.10.88.graphml +37 -0
  308. data/test/third_party_tests/rgl_tests/examples/north/g.10.89.graphml +29 -0
  309. data/test/third_party_tests/rgl_tests/examples/north/g.10.9.graphml +26 -0
  310. data/test/third_party_tests/rgl_tests/examples/north/g.10.90.graphml +32 -0
  311. data/test/third_party_tests/rgl_tests/examples/north/g.10.91.graphml +31 -0
  312. data/test/third_party_tests/rgl_tests/examples/north/g.10.92.graphml +26 -0
  313. data/test/third_party_tests/rgl_tests/examples/north/g.10.93.graphml +32 -0
  314. data/test/third_party_tests/rgl_tests/examples/north/g.10.94.graphml +34 -0
  315. data/test/third_party_tests/rgl_tests/examples/north/g.12.8.graphml +40 -0
  316. data/test/third_party_tests/rgl_tests/examples/north/g.14.9.graphml +36 -0
  317. data/test/third_party_tests/rgl_tests/test_helper.rb +7 -0
  318. data/test/third_party_tests/test_inheritable_attributes.rb +187 -0
  319. metadata +470 -0
@@ -0,0 +1,63 @@
1
+ require_relative 'spec_helper'
2
+ require 'ostruct'
3
+
4
+ describe ProtocolRegistry do
5
+ extend AnalysisHelpers
6
+ clean_registry
7
+
8
+ before(:each) do
9
+ ProtocolRegistry.class_protocols = {}
10
+ end
11
+
12
+ describe '#add_class' do
13
+ it 'adds a protocol to the main protocol list, and adds a shortcut in the class map' do
14
+ x = OpenStruct.new
15
+ x.path = 'SuperPath'
16
+ ProtocolRegistry.add_class x
17
+ ProtocolRegistry.class_protocols['SuperPath'].should == x
18
+ end
19
+ end
20
+
21
+ describe '#[]' do
22
+ it 'looks up quick queries by class path' do
23
+ x = OpenStruct.new
24
+ x.path = 'SuperPath'
25
+ ProtocolRegistry.add_class x
26
+ ProtocolRegistry['SuperPath'].should == [x]
27
+ end
28
+ end
29
+ end
30
+
31
+ describe 'ClassRegistry' do
32
+ extend AnalysisHelpers
33
+ clean_registry
34
+
35
+ describe '#[]' do
36
+ it 'finds classes with the given name' do
37
+ ClassRegistry['Object'].should == ProtocolRegistry['Object'].first
38
+ x = OpenStruct.new
39
+ x.path = 'SillyWilly'
40
+ ProtocolRegistry.add_class x
41
+ ClassRegistry['SillyWilly'].should == x
42
+ end
43
+
44
+ it 'raises on failure' do
45
+ expect { ClassRegistry['Hiybbprqag'] }.to raise_error(ArgumentError)
46
+ end
47
+ end
48
+
49
+ describe 'built-in classes' do
50
+ it 'sets up Module, Class, and Object as instances of Class correctly' do
51
+ ClassRegistry['BasicObject'].binding.class_used.should == ClassRegistry['BasicObject'].singleton_class
52
+ ClassRegistry['Object'].binding.class_used.should == ClassRegistry['Object'].singleton_class
53
+ ClassRegistry['Module'].binding.class_used.should == ClassRegistry['Module'].singleton_class
54
+ ClassRegistry['Class'].binding.class_used.should == ClassRegistry['Class'].singleton_class
55
+ end
56
+ it "sets up Module, Class, and Object's hierarchy" do
57
+ ClassRegistry['BasicObject'].superclass.should == nil
58
+ ClassRegistry['Object'].superclass.should == ClassRegistry['BasicObject']
59
+ ClassRegistry['Module'].superclass.should == ClassRegistry['Object']
60
+ ClassRegistry['Class'].superclass.should == ClassRegistry['Module']
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,1013 @@
1
+ require_relative 'spec_helper'
2
+ require 'set'
3
+ describe 'general analyses' do
4
+ extend AnalysisHelpers
5
+ clean_registry
6
+
7
+ it_should_behave_like 'an annotator'
8
+
9
+ it 'adds the #scope method to Sexp' do
10
+ Sexp.instance_methods.should include(:scope)
11
+ end
12
+ # This is the AST that Ripper generates for the parsed code. It is
13
+ # provided here because otherwise the test is inscrutable.
14
+ #
15
+ # [:program,
16
+ # [[:module,
17
+ # [:const_ref, [:@const, "M13", [1, 7]]],
18
+ # [:bodystmt,
19
+ # [[:void_stmt],
20
+ # [:def,
21
+ # [:@ident, "silly", [1, 16]],
22
+ # [:paren,
23
+ # [:params, nil, nil, [:rest_param, [:@ident, "rest", [1, 23]]], nil, nil]],
24
+ # [:bodystmt,
25
+ # [[:void_stmt],
26
+ # [:command,
27
+ # [:@ident, "p", [1, 30]],
28
+ # [:args_add_block, [[:var_ref, [:@ident, "rest", [1, 32]]]], false]]],
29
+ # nil, nil, nil]]],
30
+ # nil, nil, nil]]]]
31
+ it 'defines methods on the current Module, if inside a module lexically' do
32
+ tree = annotate_all('module M13; def silly(*rest); p rest; end; end; class C13; include M13; end')
33
+ # now make sure the method got created in the M13 module!
34
+ method = ClassRegistry['M13'].instance_method(:silly)
35
+ method.should_not be_nil
36
+ rest = method.arguments[0]
37
+ rest.name.should == 'rest'
38
+ rest.kind.should == :rest
39
+ method.name.should == 'silly'
40
+ tree.all_errors.should be_empty
41
+ end
42
+
43
+ # [:program,
44
+ # [[:module,
45
+ # [:const_ref, [:@const, "M49", [1, 7]]],
46
+ # [:bodystmt,
47
+ # [[:void_stmt],
48
+ # [:defs,
49
+ # [:var_ref, [:@kw, "self", [1, 16]]],
50
+ # [:@period, ".", [1, 20]],
51
+ # [:@ident, "silly", [1, 21]],
52
+ # [:paren,
53
+ # [:params,
54
+ # [[:@ident, "a", [1, 27]]],
55
+ # [[[:@ident, "b", [1, 30]], [:var_ref, [:@ident, "a", [1, 32]]]]],
56
+ # nil, nil, nil]],
57
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]]],
58
+ # nil, nil, nil]]]]
59
+ it "allows singleton method declarations on a Module's self" do
60
+ tree = annotate_all('module M49; def self.silly(a, b=a); end; end')
61
+
62
+ method = ClassRegistry['M49'].singleton_class.instance_method(:silly)
63
+ method.should_not be_nil
64
+ a = method.arguments[0]
65
+ a.name.should == 'a'
66
+ a.kind.should == :positional
67
+ b = method.arguments[1]
68
+ b.name.should == 'b'
69
+ b.kind.should == :optional
70
+ method.name.should == 'silly'
71
+ tree.all_errors.should be_empty
72
+ end
73
+
74
+ # [:program,
75
+ # [[:module,
76
+ # [:const_ref, [:@const, "M49", [1, 7]]],
77
+ # [:bodystmt,
78
+ # [[:void_stmt],
79
+ # [:sclass,
80
+ # [:var_ref, [:@kw, "self", [1, 21]]],
81
+ # [:bodystmt,
82
+ # [[:def,
83
+ # [:@ident, "silly", [1, 31]],
84
+ # [:paren,
85
+ # [:params,
86
+ # [[:@ident, "a", [1, 37]]],
87
+ # [[[:@ident, "b", [1, 40]], [:var_ref, [:@ident, "a", [1, 42]]]]],
88
+ # nil, nil, nil]],
89
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]]],
90
+ # nil, nil, nil]]],
91
+ # nil, nil, nil]]]]
92
+ it "allows singleton method declarations on a Module's self using sclass opening" do
93
+ tree = annotate_all('module M50; class << self; def silly(a, b=a); end; end; end')
94
+
95
+ method = ClassRegistry['M50'].singleton_class.instance_method(:silly)
96
+ method.should_not be_nil
97
+ a = method.arguments[0]
98
+ a.name.should == 'a'
99
+ a.kind.should == :positional
100
+ b = method.arguments[1]
101
+ b.name.should == 'b'
102
+ b.kind.should == :optional
103
+ method.name.should == 'silly'
104
+ tree.all_errors.should be_empty
105
+ end
106
+
107
+ # [:program,
108
+ # [[:class,
109
+ # [:const_ref, [:@const, "C51", [1, 6]]],
110
+ # nil,
111
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]],
112
+ # [:sclass,
113
+ # [:var_ref, [:@const, "C51", [1, 25]]],
114
+ # [:bodystmt,
115
+ # [[:def,
116
+ # [:@ident, "silly", [1, 34]],
117
+ # [:paren,
118
+ # [:params,
119
+ # [[:@ident, "a", [1, 40]]],
120
+ # [[[:@ident, "b", [1, 43]], [:var_ref, [:@ident, "a", [1, 45]]]]],
121
+ # nil, nil, nil]],
122
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]]],
123
+ # nil, nil, nil]]]]
124
+
125
+ it "allows singleton method declarations on a Module's self using sclass opening" do
126
+ tree = annotate_all('class C51; end; class << C51; def silly(a, b=a); end; end')
127
+
128
+ method = ClassRegistry['C51'].singleton_class.instance_method(:silly)
129
+ method.should_not be_nil
130
+ a = method.arguments[0]
131
+ a.name.should == 'a'
132
+ a.kind.should == :positional
133
+ b = method.arguments[1]
134
+ b.name.should == 'b'
135
+ b.kind.should == :optional
136
+ method.name.should == 'silly'
137
+ tree.all_errors.should be_empty
138
+ end
139
+
140
+ # This is the AST that Ripper generates for the parsed code. It is
141
+ # provided here because otherwise the test is inscrutable.
142
+ #
143
+ # sexp = [:program, [
144
+ # [:class, [:const_ref, [:@const, "C89", [1, 6]]], nil,
145
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]],
146
+ # [:class, [:const_ref, [:@const, "CPP", [1, 22]]], [:var_ref, [:@const, "C89", [1, 28]]],
147
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]]]]
148
+ it 'creates a new class with the appropriate superclass when specified' do
149
+ tree = annotate_all('class C89; end; class CPP < C89; end')
150
+ a, b = ClassRegistry['C89'], ClassRegistry['CPP']
151
+
152
+ a.klass.path.should == 'Class'
153
+ a.path.should == 'C89'
154
+ a.superclass.should == ClassRegistry['Object']
155
+ b.klass.path.should == 'Class'
156
+ b.path.should == 'CPP'
157
+ b.superclass.should == a
158
+ tree.all_errors.should be_empty
159
+ end
160
+
161
+ # This is the AST that Ripper generates for the parsed code. It is
162
+ # provided here because otherwise the test is inscrutable.
163
+ #
164
+ # sexp = [:program,
165
+ # [[:module, [:const_ref, [:@const, "WWD", [1, 7]]],
166
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]],
167
+ # [:class,
168
+ # [:const_path_ref, [:var_ref, [:@const, "WWD", [1, 23]]],
169
+ # [:@const, "SuperModule", [1, 28]]],
170
+ # [:var_ref, [:@const, "Module", [1, 42]]],
171
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]]]]
172
+ it 'declares classes inside modules with path-based definitions' do
173
+ tree = annotate_all('module WWD; end; class WWD::SuperModule < Module; end')
174
+
175
+ mod = ClassRegistry['WWD']
176
+ mod.should be_a(LaserModule)
177
+ supermod = ClassRegistry['WWD::SuperModule']
178
+ supermod.should be_a(LaserClass)
179
+ supermod.superclass.should == ClassRegistry['Module']
180
+ tree.all_errors.should be_empty
181
+ end
182
+
183
+ # [:program,
184
+ # [[:class,
185
+ # [:const_ref, [:@const, "Alpha", [1, 6]]],
186
+ # nil,
187
+ # [:bodystmt,
188
+ # [[:def,
189
+ # [:@ident, "do_xyz", [1, 17]],
190
+ # [:paren,
191
+ # [:params,
192
+ # [[:@ident, "a", [1, 24]]],
193
+ # [[[:@ident, "b", [1, 27]], [:var_ref, [:@ident, "a", [1, 29]]]]],
194
+ # nil, nil, nil]],
195
+ # [:bodystmt,
196
+ # [[:void_stmt],
197
+ # [:command,
198
+ # [:@ident, "p", [1, 33]],
199
+ # [:args_add_block, [[:var_ref, [:@ident, "b", [1, 35]]]], false]]],
200
+ # nil, nil, nil]]],
201
+ # nil, nil, nil]],
202
+ # [:class,
203
+ # [:const_ref, [:@const, "B22", [1, 54]]],
204
+ # [:var_ref, [:@const, "Alpha", [1, 60]]],
205
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]]]]
206
+ it 'defines methods on the current Class, which are inherited' do
207
+ tree = annotate_all('class Alpha; def do_xyz(a, b=a); p b; end; end; class B22 < Alpha; end')
208
+ # now make sure the method got created in the M13 module!
209
+ ['Alpha', 'B22'].each do |klass|
210
+ method = ClassRegistry[klass].instance_method(:do_xyz)
211
+ method.should_not be_nil
212
+ a = method.arguments[0]
213
+ a.name.should == 'a'
214
+ a.kind.should == :positional
215
+ b = method.arguments[1]
216
+ b.name.should == 'b'
217
+ b.kind.should == :optional
218
+ method.name.should == 'do_xyz'
219
+ end
220
+ tree.all_errors.should be_empty
221
+ end
222
+
223
+ it 'removes methods via #remove_method' do
224
+ annotate_all('class RM1; def do_xyz(a); end; end')
225
+ ClassRegistry['RM1'].instance_method(:do_xyz).should be_a(LaserMethod)
226
+ annotate_all('class RM1; remove_method :do_xyz; end')
227
+ ClassRegistry['RM1'].instance_method(:do_xyz).should be nil
228
+ end
229
+
230
+ it 'passes resolution to superclasses after #remove_method' do
231
+ annotate_all('class RM2; def do_xyz(a); end; end; class RMSub < RM2; def do_xyz(b); end; end')
232
+ ClassRegistry['RMSub'].instance_method(:do_xyz).should be_a(LaserMethod)
233
+ ClassRegistry['RMSub'].instance_method(:do_xyz).should_not ==
234
+ ClassRegistry['RM2'].instance_method(:do_xyz)
235
+
236
+ annotate_all('class RMSub; remove_method :do_xyz; end')
237
+ ClassRegistry['RMSub'].instance_method(:do_xyz).should ==
238
+ ClassRegistry['RM2'].instance_method(:do_xyz)
239
+ end
240
+
241
+ # [:program,
242
+ # [[:def,
243
+ # [:@ident, "abc", [1, 4]],
244
+ # [:paren,
245
+ # [:params,
246
+ # [[:@ident, "bar", [1, 8]]],
247
+ # nil, nil, nil,
248
+ # [:blockarg, [:@ident, "blk", [1, 14]]]]],
249
+ # [:bodystmt,
250
+ # [[:void_stmt],
251
+ # [:command,
252
+ # [:@ident, "p", [1, 20]],
253
+ # [:args_add_block, [[:var_ref, [:@ident, "blk", [1, 22]]]], false]]],
254
+ # nil, nil, nil]]]]
255
+ it 'defines method on the main object, if no scope is otherwise enclosing a method definition' do
256
+ tree = annotate_all('def abce(bar, &blk); p blk; end')
257
+ method = Scope::GlobalScope.self_ptr.singleton_class.instance_method(:abce)
258
+ method.should_not be_nil
259
+ Scope::GlobalScope.self_ptr.singleton_class.visibility_table[:abce].should == :private
260
+ bar = method.arguments[0]
261
+ bar.name.should == 'bar'
262
+ bar.kind.should == :positional
263
+ blk = method.arguments[1]
264
+ blk.name.should == 'blk'
265
+ blk.kind.should == :block
266
+ method.name.should == 'abce'
267
+ tree.all_errors.should be_empty
268
+ end
269
+
270
+ # [:program,
271
+ # [[:defs,
272
+ # [:var_ref, [:@kw, "self", [1, 4]]],
273
+ # [:@period, ".", [1, 8]],
274
+ # [:@ident, "abc", [1, 9]],
275
+ # [:paren,
276
+ # [:params,
277
+ # [[:@ident, "bar", [1, 13]]],
278
+ # nil, nil, nil,
279
+ # [:blockarg, [:@ident, "blk", [1, 19]]]]],
280
+ # [:bodystmt,
281
+ # [[:void_stmt],
282
+ # [:command,
283
+ # [:@ident, "p", [1, 25]],
284
+ # [:args_add_block, [[:var_ref, [:@ident, "blk", [1, 27]]]], false]]],
285
+ # nil, nil, nil]]]]
286
+ it 'defines singleton methods on the main object, if no scope is otherwise enclosing a method definition' do
287
+ tree = annotate_all('def self.abcd(bar, &blk); p blk; end')
288
+ method = Scope::GlobalScope.self_ptr.singleton_class.instance_method(:abcd)
289
+ method.should_not be_nil
290
+ bar = method.arguments[0]
291
+ bar.name.should == 'bar'
292
+ bar.kind.should == :positional
293
+ blk = method.arguments[1]
294
+ blk.name.should == 'blk'
295
+ blk.kind.should == :block
296
+ method.name.should == 'abcd'
297
+ tree.all_errors.should be_empty
298
+ end
299
+
300
+ # [:program,
301
+ # [[:module,
302
+ # [:const_ref, [:@const, "TestA", [1, 7]]],
303
+ # [:bodystmt,
304
+ # [[:void_stmt],
305
+ # [:assign,
306
+ # [:var_field, [:@const, "PI", [1, 14]]],
307
+ # [:@float, "3.14", [1, 19]]],
308
+ # [:assign,
309
+ # [:var_field, [:@const, "TAU", [1, 25]]],
310
+ # [:binary,
311
+ # [:var_ref, [:@const, "PI", [1, 31]]],
312
+ # :*,
313
+ # [:@int, "2", [1, 36]]]]],
314
+ # nil, nil, nil]]]]
315
+ it 'creates new constant bindings as new constants are assigned to' do
316
+ tree = annotate_all('module TestA; PI = 3.14; TAU = PI * 2; end')
317
+
318
+ ClassRegistry['TestA'].should be_a(LaserModule)
319
+ ClassRegistry['TestA'].const_get('PI').should_not be_nil
320
+ ClassRegistry['TestA'].const_get('TAU').should_not be_nil
321
+ end
322
+
323
+ it 'handles module inclusions done in the typical method-call fashion' do
324
+ input = 'module A113; end; module B113; end; class C113; include A113, B113; end'
325
+ tree = annotate_all(input)
326
+
327
+ c113 = ClassRegistry['C113']
328
+ c113.should_not be nil
329
+ c113.ancestors.should == [ClassRegistry['C113'], ClassRegistry['A113'], ClassRegistry['B113'],
330
+ ClassRegistry['Object'], ClassRegistry['Kernel'], ClassRegistry['BasicObject']]
331
+
332
+ tree.all_errors.should be_empty
333
+ end
334
+
335
+ it 'handles complex module/class hierarchies' do
336
+ input = "module A114; end; module B114; include A114; end; module C114; include B114; end\n" +
337
+ "class X114; include A114; end; class Y114 < X114; include C114; end"
338
+ tree = annotate_all(input)
339
+
340
+ ClassRegistry['A114'].ancestors.should == [ClassRegistry['A114']]
341
+ ClassRegistry['B114'].ancestors.should == [ClassRegistry['B114'], ClassRegistry['A114']]
342
+ ClassRegistry['C114'].ancestors.should == [ClassRegistry['C114'], ClassRegistry['B114'], ClassRegistry['A114']]
343
+
344
+ ClassRegistry['X114'].ancestors.should == [ClassRegistry['X114'], ClassRegistry['A114'], ClassRegistry['Object'],
345
+ ClassRegistry['Kernel'], ClassRegistry['BasicObject']]
346
+ ClassRegistry['Y114'].ancestors.should == [ClassRegistry['Y114'], ClassRegistry['C114'], ClassRegistry['B114'],
347
+ ClassRegistry['X114'], ClassRegistry['A114'], ClassRegistry['Object'],
348
+ ClassRegistry['Kernel'], ClassRegistry['BasicObject']]
349
+ tree.all_errors.should be_empty
350
+ end
351
+
352
+ it 'generates an error when a class is re-opened as a module' do
353
+ input = "class A115; end; module A115; end"
354
+ tree = annotate_all(input)
355
+
356
+ tree.errors.should_not be_empty
357
+ tree.all_errors.first.should be_a(TopLevelSimulationRaised)
358
+ err = tree.all_errors.first
359
+ err.error.normal_class.should == ClassRegistry['LaserReopenedClassAsModuleError']
360
+ end
361
+
362
+ it 'generates an error when a module is re-opened as a class' do
363
+ input = "module A116; end; class A116; end"
364
+ tree = annotate_all(input)
365
+
366
+ tree.errors.should_not be_empty
367
+ tree.all_errors.first.should be_a(TopLevelSimulationRaised)
368
+ err = tree.all_errors.first
369
+ err.error.normal_class.should == ClassRegistry['LaserReopenedModuleAsClassError']
370
+ end
371
+
372
+ it 'handles module inclusions done in the parenthesized method-call fashion' do
373
+ input = 'module A117; end; module B117; end; class C117; include(A117, B117); end'
374
+ tree = annotate_all(input)
375
+
376
+ c117 = ClassRegistry['C117']
377
+ c117.should_not be nil
378
+ c117.ancestors.should == [ClassRegistry['C117'], ClassRegistry['A117'],
379
+ ClassRegistry['B117'], ClassRegistry['Object'],
380
+ ClassRegistry['Kernel'], ClassRegistry['BasicObject']]
381
+
382
+ tree.all_errors.should be_empty
383
+ end
384
+
385
+ it 'reports an error when a module is included unnecessarily' do
386
+ input = 'module A240; end; class B240; include A240; end; class C240 < B240; include A240; end'
387
+ tree = annotate_all(input)
388
+
389
+ c240 = ClassRegistry['C240']
390
+ c240.should_not be nil
391
+ c240.ancestors.should == [ClassRegistry['C240'], ClassRegistry['B240'],
392
+ ClassRegistry['A240'], ClassRegistry['Object'],
393
+ ClassRegistry['Kernel'], ClassRegistry['BasicObject']]
394
+ tree.all_errors.should_not be_empty
395
+ tree.all_errors.size.should == 1
396
+ tree.all_errors.first.should be_a(TopLevelSimulationRaised)
397
+ err = tree.all_errors.first
398
+ err.error.class.should == DoubleIncludeError
399
+ end
400
+
401
+ it 'handles module extensions done in the typical method-call fashion' do
402
+ input = 'module A118; end; module B118; end; class C118; extend A118, B118; end'
403
+ tree = annotate_all(input)
404
+
405
+ c118 = ClassRegistry['C118']
406
+ c118.should_not be nil
407
+ c118.singleton_class.ancestors.should == [ClassRegistry['C118'].singleton_class,
408
+ ClassRegistry['A118'], ClassRegistry['B118'],
409
+ ClassRegistry['Object'].singleton_class,
410
+ ClassRegistry['BasicObject'].singleton_class,
411
+ ClassRegistry['Class'], ClassRegistry['Module'],
412
+ ClassRegistry['Object'], ClassRegistry['Kernel'],
413
+ ClassRegistry['BasicObject']]
414
+ tree.all_errors.should be_empty
415
+ end
416
+
417
+ it 'handles complex module/class extension hierarchies' do
418
+ input = "module A119; end; module B119; extend A119; end; module C119; extend B119; end\n" +
419
+ "class X119; extend A119; end; class Y119 < X119; extend C119; end"
420
+ tree = annotate_all(input)
421
+
422
+ ClassRegistry['A119'].singleton_class.ancestors.should ==
423
+ [ClassRegistry['A119'].singleton_class, ClassRegistry['Module'],
424
+ ClassRegistry['Object'], ClassRegistry['Kernel'], ClassRegistry['BasicObject']]
425
+ ClassRegistry['B119'].singleton_class.ancestors.should ==
426
+ [ClassRegistry['B119'].singleton_class, ClassRegistry['A119'],
427
+ ClassRegistry['Module'], ClassRegistry['Object'], ClassRegistry['Kernel'],
428
+ ClassRegistry['BasicObject']]
429
+ ClassRegistry['C119'].singleton_class.ancestors.should ==
430
+ [ClassRegistry['C119'].singleton_class, ClassRegistry['B119'],
431
+ ClassRegistry['Module'], ClassRegistry['Object'], ClassRegistry['Kernel'],
432
+ ClassRegistry['BasicObject']]
433
+
434
+ ClassRegistry['X119'].singleton_class.ancestors.should ==
435
+ [ClassRegistry['X119'].singleton_class, ClassRegistry['A119'],
436
+ ClassRegistry['Object'].singleton_class,
437
+ ClassRegistry['BasicObject'].singleton_class,
438
+ ClassRegistry['Class'], ClassRegistry['Module'],
439
+ ClassRegistry['Object'], ClassRegistry['Kernel'],
440
+ ClassRegistry['BasicObject']]
441
+ ClassRegistry['Y119'].singleton_class.ancestors.should ==
442
+ [ClassRegistry['Y119'].singleton_class, ClassRegistry['C119'],
443
+ ClassRegistry['X119'].singleton_class, ClassRegistry['A119'],
444
+ ClassRegistry['Object'].singleton_class,
445
+ ClassRegistry['BasicObject'].singleton_class,
446
+ ClassRegistry['Class'], ClassRegistry['Module'],
447
+ ClassRegistry['Object'], ClassRegistry['Kernel'],
448
+ ClassRegistry['BasicObject']]
449
+
450
+ tree.all_errors.should be_empty
451
+ end
452
+
453
+ it 'handles module extensions done in the parenthesized method-call fashion' do
454
+ input = 'module A120; end; module B120; end; class C120; extend(A120, B120); end'
455
+ tree = annotate_all(input)
456
+
457
+ c120 = ClassRegistry['C120']
458
+ c120.should_not be nil
459
+ c120.singleton_class.ancestors.should == [ClassRegistry['C120'].singleton_class,
460
+ ClassRegistry['A120'], ClassRegistry['B120'],
461
+ ClassRegistry['Object'].singleton_class,
462
+ ClassRegistry['BasicObject'].singleton_class,
463
+ ClassRegistry['Class'], ClassRegistry['Module'],
464
+ ClassRegistry['Object'], ClassRegistry['Kernel'],
465
+ ClassRegistry['BasicObject']]
466
+ tree.all_errors.should be_empty
467
+ end
468
+
469
+ # [:program,
470
+ # [[:class,
471
+ # [:const_ref, [:@const, "A121", [1, 6]]],
472
+ # nil,
473
+ # [:bodystmt,
474
+ # [[:assign, [:var_field, [:@ident, "x", [1, 12]]], [:@int, "10", [1, 16]]],
475
+ # [:assign,
476
+ # [:var_field, [:@ident, "y", [1, 20]]],
477
+ # [:var_ref, [:@ident, "z", [1, 24]]]]],
478
+ # nil, nil, nil]]]]
479
+ it 'should generate an error if a local variable cannot be found' do
480
+ input = 'class A121; x = 10; y = Z223; end'
481
+ tree = annotate_all(input)
482
+
483
+ errors = tree.all_errors
484
+ errors.should_not be_empty
485
+ errors.first.should be_a(TopLevelSimulationRaised)
486
+ errors.first.error.class.should == ArgumentError
487
+ end
488
+
489
+ it 'switches to private visibility upon reaching a call to #private in a class/module' do
490
+ input = 'class A122; private; def foobar; end; end'
491
+ tree = annotate_all(input)
492
+
493
+ ClassRegistry['A122'].visibility_table[:foobar].should == :private
494
+ end
495
+
496
+ it 'does not switch to private visibility if a local variable is called private' do
497
+ input = 'class A123; private = 5; private; def foobar; end; end'
498
+ tree = annotate_all(input)
499
+
500
+ ClassRegistry['A123'].visibility_table[:foobar].should == :public
501
+ end
502
+
503
+ it 'switches back and forth from public, private, and protected visibility in a class/module' do
504
+ input = 'module A124; def abc; end; private; def foobar; end; protected; def silly; end; private; def priv; end; end'
505
+ tree = annotate_all(input)
506
+
507
+ ClassRegistry['A124'].visibility_table[:abc].should == :public
508
+ ClassRegistry['A124'].visibility_table[:foobar].should == :private
509
+ ClassRegistry['A124'].visibility_table[:silly].should == :protected
510
+ ClassRegistry['A124'].visibility_table[:priv].should == :private
511
+ end
512
+
513
+ it 'switches to back visibility when re-opening the same class from within (complex edge case)' do
514
+ input = 'class E1; private; class ::E1; def foo; end; end; def bar; end; end'
515
+ tree = annotate_all(input)
516
+
517
+ ClassRegistry['E1'].visibility_table[:foo].should == :public
518
+ ClassRegistry['E1'].visibility_table[:bar].should == :private
519
+ end
520
+
521
+ it 'switches to private on module_function and back on public/protected' do
522
+ input = 'module A200; def abc; end; module_function; def foobar; end; protected;' +
523
+ 'def silly; end; public; def priv; end; end'
524
+ tree = annotate_all(input)
525
+
526
+ ClassRegistry['A200'].visibility_table[:abc].should == :public
527
+ ClassRegistry['A200'].visibility_table[:foobar].should == :private
528
+ ClassRegistry['A200'].visibility_table[:silly].should == :protected
529
+ ClassRegistry['A200'].visibility_table[:priv].should == :public
530
+ end
531
+
532
+ it 'sets all module_function methods to private when specified as arguments' do
533
+ input = 'module A201; def abc; end; def foobar; end; def silly; end; module_function :abc, :silly; end'
534
+ tree = annotate_all(input)
535
+
536
+ ClassRegistry['A201'].visibility_table[:abc].should == :private
537
+ ClassRegistry['A201'].visibility_table[:foobar].should == :public
538
+ ClassRegistry['A201'].visibility_table[:silly].should == :private
539
+ end
540
+
541
+ it 'creates public singleton class methods when module_function is used with no args' do
542
+ input = 'module A202; def def; end; module_function; def foobar; "hi"; 3; end;' +
543
+ 'def silly; /regex/; end; public; def priv; end; end'
544
+ tree = annotate_all(input)
545
+
546
+ ClassRegistry['A202'].singleton_class.visibility_table[:foobar].should == :public
547
+ ClassRegistry['A202'].singleton_class.visibility_table[:silly].should == :public
548
+ ClassRegistry['A202'].singleton_class.instance_method(:def).should be nil
549
+ ClassRegistry['A202'].singleton_class.instance_method(:priv).should be nil
550
+ end
551
+
552
+ it 'creates public singleton class methods when module_function is used with args' do
553
+ input = 'module A203; def def; end; def foobar; "hi"; 3; end;' +
554
+ 'def silly; /regex/; end; public; def priv; end; module_function :foobar, :silly; end'
555
+ tree = annotate_all(input)
556
+
557
+ ClassRegistry['A203'].singleton_class.visibility_table[:foobar].should == :public
558
+ ClassRegistry['A203'].singleton_class.visibility_table[:silly].should == :public
559
+ ClassRegistry['A203'].singleton_class.instance_method(:def).should be nil
560
+ ClassRegistry['A203'].singleton_class.instance_method(:priv).should be nil
561
+ end
562
+
563
+ it 'uses a default private scope at the top level but can switch to public and private' do
564
+ input = 'def t11; end; public; def t12; end; private; def t13; end'
565
+ tree = annotate_all(input)
566
+
567
+ singleton = Scope::GlobalScope.self_ptr.singleton_class
568
+ singleton.visibility_table[:t11].should == :private
569
+ singleton.visibility_table[:t12].should == :public
570
+ singleton.visibility_table[:t13].should == :private
571
+ end
572
+
573
+ it 'raises an error if you try to use protected at the top level' do
574
+ input = 'def t14; end; protected; def t15; end; public; def t16; end'
575
+ tree = annotate_all(input)
576
+ tree.all_errors.size.should be 1
577
+ tree.all_errors.first.should be_a(TopLevelSimulationRaised)
578
+ tree.all_errors.first.error.normal_class.should == ClassRegistry['NameError']
579
+
580
+ # recovers by not changing visibility
581
+ # singleton = Scope::GlobalScope.self_ptr.singleton_class
582
+ # singleton.visibility_table[:t14].should == :private
583
+ # singleton.visibility_table[:t15].should == :private
584
+ # singleton.visibility_table[:t16].should == :public
585
+ end
586
+
587
+ it 'allows specifying private/public/protected for individual methods at the class level' do
588
+ input = 'class A125; def t17; end; def t18; end; def t19; end; private *[:t17, :t19]; end'
589
+ tree = annotate_all(input)
590
+
591
+ ClassRegistry['A125'].visibility_table[:t17].should == :private
592
+ ClassRegistry['A125'].visibility_table[:t18].should == :public
593
+ ClassRegistry['A125'].visibility_table[:t19].should == :private
594
+ end
595
+
596
+
597
+ it 'allows specifying private/public/protected for individual methods at the top level' do
598
+ input = 'def t17; end; def t18; end; def t19; end; public *[:t17, :t19]'
599
+ tree = annotate_all(input)
600
+
601
+ # recovers by not changing visibility
602
+ singleton = Scope::GlobalScope.self_ptr.singleton_class
603
+ singleton.visibility_table[:t17].should == :public
604
+ singleton.visibility_table[:t18].should == :private
605
+ singleton.visibility_table[:t19].should == :public
606
+ end
607
+
608
+ it 'can resolve constant aliasing with superclasses' do
609
+ tree = annotate_all('class Alpha111; end; Beta111 = Alpha111; class B290 < Beta111; end')
610
+
611
+ ClassRegistry['B290'].superclass.should == ClassRegistry['Alpha111']
612
+
613
+ tree.all_errors.should be_empty
614
+ end
615
+
616
+ describe 'performing requires' do
617
+ before do
618
+ @load_paths = Scope::GlobalScope.lookup('$:').value
619
+ @features = Scope::GlobalScope.lookup('$"').value
620
+ @original = @load_paths.dup
621
+ @orig_features = @features.dup
622
+ end
623
+
624
+ after do
625
+ @load_paths.replace(@original)
626
+ @features.replace(@orig_features)
627
+ end
628
+
629
+ it 'should load the file from $: if it is not yet in $"' do
630
+ @load_paths.unshift('/abc/def')
631
+ File.should_receive(:exist?).with('/abc/def/foobaz.rb').and_return(true)
632
+ File.should_receive(:read).with('/abc/def/foobaz.rb').and_return('class Alpha112 < Hash;end')
633
+ annotate_all("require 'foobaz'")
634
+ ClassRegistry['Alpha112'].superclass.should == ClassRegistry['Hash']
635
+ end
636
+
637
+ it 'should check all paths in $: for the file in a row' do
638
+ @load_paths.unshift('/abc/def').unshift('/def/jkl').unshift('/jkl/uio')
639
+ File.should_receive(:exist?).with('/jkl/uio/foobaz.rb').and_return(false)
640
+ File.should_receive(:exist?).with('/def/jkl/foobaz.rb').and_return(false)
641
+ File.should_receive(:exist?).with('/abc/def/foobaz.rb').and_return(true)
642
+ File.should_receive(:read).with('/abc/def/foobaz.rb').and_return('class Alpha113 < Array;end')
643
+ annotate_all("require 'foobaz'")
644
+ ClassRegistry['Alpha113'].superclass.should == ClassRegistry['Array']
645
+ end
646
+
647
+ it 'should not load the file if it is found in $"' do
648
+ @load_paths.unshift('/abc/def').unshift('/def/jkl').unshift('/jkl/uio')
649
+ @features.unshift('/abc/def/foobaz.rb')
650
+ File.should_receive(:exist?).with('/jkl/uio/foobaz.rb').and_return(false)
651
+ File.should_receive(:exist?).with('/def/jkl/foobaz.rb').and_return(false)
652
+ File.should_receive(:exist?).with('/abc/def/foobaz.rb').and_return(true)
653
+ File.should_not_receive(:read)
654
+ annotate_all("require 'foobaz'")
655
+ end
656
+ end
657
+
658
+ it 'should raise a SuperclassMismatchError when an improper superclass is specified' do
659
+ input = 'class A250 < String; end; class A250 < Fixnum; end'
660
+ tree = annotate_all(input)
661
+ tree.all_errors.size.should be 1
662
+ tree.all_errors.first.should be_a(TopLevelSimulationRaised)
663
+ tree.all_errors.first.error.normal_class.should == ClassRegistry['LaserSuperclassMismatchError']
664
+ end
665
+
666
+ it "should not raise a SuperclassMismatchError when BasicObject's superclass is omitted" do
667
+ input = 'class BasicObject; end'
668
+ tree = annotate_all(input)
669
+ tree.all_errors.should be_empty
670
+ end
671
+
672
+ it "should not raise a SuperclassMismatchError when BasicObject's superclass is nil" do
673
+ input = 'class BasicObject < nil; end'
674
+ tree = annotate_all(input)
675
+ tree.all_errors.should be_empty
676
+ end
677
+
678
+ it "should raise a SuperclassMismatchError when BasicObject's superclass is specified and not nil" do
679
+ input = 'class BasicObject < String; end'
680
+ tree = annotate_all(input)
681
+ tree.all_errors.size.should be 1
682
+ tree.all_errors.first.should be_a(TopLevelSimulationRaised)
683
+ tree.all_errors.first.error.normal_class.should == ClassRegistry['LaserSuperclassMismatchError']
684
+ end
685
+
686
+ it "should not raise a SuperclassMismatchError when Object's superclass is omitted" do
687
+ input = 'class Object; end'
688
+ tree = annotate_all(input)
689
+ tree.all_errors.should be_empty
690
+ end
691
+
692
+ it "should not raise a SuperclassMismatchError when Object's superclass is BasicObject" do
693
+ input = 'class Object < BasicObject; end'
694
+ tree = annotate_all(input)
695
+ tree.all_errors.should be_empty
696
+ end
697
+
698
+ it "should raise a SuperclassMismatchError when Object's superclass is specified and not BasicObject" do
699
+ input = 'class Object < Array; end'
700
+ tree = annotate_all(input)
701
+ tree.all_errors.size.should be 1
702
+ tree.all_errors.first.should be_a(TopLevelSimulationRaised)
703
+ tree.all_errors.first.error.normal_class.should == ClassRegistry['LaserSuperclassMismatchError']
704
+ end
705
+
706
+ it "should not raise a SuperclassMismatchError when Class's superclass is omitted" do
707
+ input = 'class Class; end'
708
+ tree = annotate_all(input)
709
+ tree.all_errors.should be_empty
710
+ end
711
+
712
+ it "should not raise a SuperclassMismatchError when Class's superclass is Module" do
713
+ input = 'class Class < Module; end'
714
+ tree = annotate_all(input)
715
+ tree.all_errors.should be_empty
716
+ end
717
+
718
+ it "should raise a SuperclassMismatchError when Class's superclass is specified and not Module" do
719
+ input = 'class Class < BasicObject; end'
720
+ tree = annotate_all(input)
721
+ tree.all_errors.size.should be 1
722
+ tree.all_errors.first.should be_a(TopLevelSimulationRaised)
723
+ tree.all_errors.first.error.normal_class.should == ClassRegistry['LaserSuperclassMismatchError']
724
+ end
725
+
726
+ it "should not raise a SuperclassMismatchError when a class is opened without it's Object superclass" do
727
+ input = 'class String; end'
728
+ tree = annotate_all(input)
729
+ tree.all_errors.should be_empty
730
+ end
731
+
732
+ it 'observes aliases and sets the corresponding instance methods correctly' do
733
+ input = 'class SA99; def foo; end; alias silly foo; end'
734
+ annotate_all(input)
735
+ ClassRegistry['SA99'].instance_method(:silly).should be(
736
+ ClassRegistry['SA99'].instance_method(:foo))
737
+ end
738
+
739
+ it 'observes undefs and sets the corresponding instance method to nil' do
740
+ input = 'class SA100; def foo; end; end; class SA101 < SA100; undef foo, :inspect; end'
741
+ annotate_all(input)
742
+ ClassRegistry['SA100'].instance_method(:foo).should_not be nil
743
+ ClassRegistry['SA100'].instance_method(:inspect).should_not be nil
744
+ ClassRegistry['SA101'].instance_method(:foo).should be nil
745
+ ClassRegistry['SA101'].instance_method(:inspect).should be nil
746
+ end
747
+ end
748
+
749
+ describe 'complete tests' do
750
+ extend AnalysisHelpers
751
+ clean_registry
752
+ # This is the AST that Ripper generates for the parsed code. It is
753
+ # provided here because otherwise the test is inscrutable.
754
+ #
755
+ # sexp =
756
+ # [:program,
757
+ # [[:module,
758
+ # [:const_ref, [:@const, "And", [1, 7]]],
759
+ # [:bodystmt,
760
+ # [[:void_stmt],
761
+ # [:module,
762
+ # [:const_ref, [:@const, "Or", [2, 9]]],
763
+ # [:bodystmt,
764
+ # [[:void_stmt],
765
+ # [:module,
766
+ # [:const_ref, [:@const, "Is", [3, 11]]],
767
+ # [:bodystmt,
768
+ # [[:void_stmt],
769
+ # [:module,
770
+ # [:const_ref, [:@const, "Ten", [4, 13]]],
771
+ # [:bodystmt,
772
+ # [[:void_stmt],
773
+ # [:module,
774
+ # [:const_ref, [:@const, "Seven", [5, 15]]],
775
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]]],
776
+ # nil, nil, nil]]],
777
+ # nil, nil, nil]]],
778
+ # nil, nil, nil]]],
779
+ # nil, nil, nil]],
780
+ # [:module,
781
+ # [:const_ref, [:@const, "And", [11, 7]]],
782
+ # [:bodystmt,
783
+ # [[:void_stmt],
784
+ # [:class,
785
+ # [:const_path_ref,
786
+ # [:var_ref, [:@const, "Or", [12, 8]]],
787
+ # [:@const, "Type", [12, 12]]],
788
+ # nil,
789
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]],
790
+ # [:class,
791
+ # [:const_path_ref,
792
+ # [:const_path_ref,
793
+ # [:const_path_ref,
794
+ # [:var_ref, [:@const, "Or", [14, 8]]],
795
+ # [:@const, "Is", [14, 12]]],
796
+ # [:@const, "Ten", [14, 16]]],
797
+ # [:@const, "Kind", [14, 21]]],
798
+ # [:const_path_ref,
799
+ # [:const_path_ref,
800
+ # [:top_const_ref, [:@const, "And", [14, 30]]],
801
+ # [:@const, "Or", [14, 35]]],
802
+ # [:@const, "Type", [14, 39]]],
803
+ # [:bodystmt,
804
+ # [[:module,
805
+ # [:const_ref, [:@const, "Silly", [15, 11]]],
806
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]]],
807
+ # nil, nil, nil]],
808
+ # [:module,
809
+ # [:const_path_ref,
810
+ # [:const_path_ref,
811
+ # [:const_path_ref,
812
+ # [:const_path_ref,
813
+ # [:var_ref, [:@const, "Or", [18, 9]]],
814
+ # [:@const, "Is", [18, 13]]],
815
+ # [:@const, "Ten", [18, 17]]],
816
+ # [:@const, "Kind", [18, 22]]],
817
+ # [:@const, "Silly", [18, 28]]],
818
+ # [:bodystmt, [[:void_stmt]], nil, nil, nil]]],
819
+ # nil, nil, nil]]]]
820
+
821
+ it 'handles a monstrous comprehensive module and class nesting example' do
822
+ tree = annotate_all(<<-EOF
823
+ module And
824
+ module Or
825
+ module Is
826
+ module Ten
827
+ module Seven
828
+ end
829
+ end
830
+ end
831
+ end
832
+ end
833
+ module And
834
+ class Or::Type
835
+ end
836
+ class Or::Is::Ten::Kind < ::And::Or::Type
837
+ module Silly
838
+ end
839
+ end
840
+ module Or::Is::Ten::Kind::Silly
841
+ end
842
+ end
843
+ EOF
844
+ )
845
+ modules = %w(And And::Or And::Or::Is And::Or::Is::Ten And::Or::Is::Ten::Seven
846
+ And::Or::Is::Ten::Kind::Silly)
847
+ modules.each { |mod| ClassRegistry[mod].should be_a(LaserModule) }
848
+ ClassRegistry['And::Or::Type'].should be_a(LaserClass)
849
+ ClassRegistry['And::Or::Type'].superclass.should be ClassRegistry['Object']
850
+ ClassRegistry['And::Or::Is::Ten::Kind'].should be_a(LaserClass)
851
+ ClassRegistry['And::Or::Is::Ten::Kind'].superclass.should be ClassRegistry['And::Or::Type']
852
+ end
853
+
854
+ describe 'with a real ruby file as input' do
855
+ before do
856
+ @input = %q{
857
+ module Laser
858
+ module Analysis
859
+ module Bindings
860
+ # This class represents a Base in Ruby. It may have a known protocol (type),
861
+ # class, value (if constant!), and a variety of other details.
862
+ class Base
863
+ include Comparable
864
+
865
+ def initialize(name, value)
866
+ @name = name
867
+ @value = :uninitialized
868
+ bind!(value)
869
+ end
870
+
871
+ def name
872
+ @name
873
+ end
874
+
875
+ def name=(other)
876
+ @name = other
877
+ end
878
+
879
+ def value
880
+ @value
881
+ end
882
+
883
+ def bind!(value)
884
+ if respond_to?(:validate_value)
885
+ validate_value(value)
886
+ end
887
+ @value = value
888
+ end
889
+
890
+ def <=>(other)
891
+ self.name <=> other.name
892
+ end
893
+
894
+ def scope
895
+ value.scope
896
+ end
897
+
898
+ def protocol
899
+ value.protocol
900
+ end
901
+
902
+ def class_used
903
+ value.klass
904
+ end
905
+ #
906
+ # def to_s
907
+ # inspect
908
+ # end
909
+ #
910
+ # def inspect
911
+ # "#<#{self.class.name.split('::').last}: #{name}>"
912
+ # end
913
+ end
914
+
915
+ class KeywordBinding < Base
916
+ private :bind!
917
+ end
918
+
919
+ # Constants have slightly different properties in their bindings: They shouldn't
920
+ # be rebound. However.... Ruby allows it. It prints a warning when the rebinding
921
+ # happens, but we should be able to detect this statically. Oh, and they can't be
922
+ # bound inside a method. That too is easily detected statically.
923
+ class ConstantBinding < Base
924
+ # Require an additional force parameter to rebind a Constant. That way, the user
925
+ # can configure whether rebinding counts as a warning or an error.
926
+ def bind!(val, force=false)
927
+ if @value != :uninitialized && !force
928
+ raise TypeError.new('Cannot rebind a constant binding without const_set')
929
+ end
930
+ super(val)
931
+ end
932
+ end
933
+
934
+ # We may want to track # of assignments/reads from local vars, so we should subclass
935
+ # Base for it.
936
+ class LocalVariableBinding < Base
937
+ end
938
+
939
+ # Possible extension ideas:
940
+ # - Initial definition point?
941
+ class GlobalVariableBinding < Base
942
+ end
943
+
944
+ class ArgumentBinding < Base
945
+ attr_reader :kind, :default_value_sexp
946
+ def initialize(name, value, kind, default_value = nil)
947
+ super(name, value)
948
+ @kind = kind
949
+ @default_value_sexp = default_value
950
+ end
951
+ end
952
+ end
953
+ end
954
+ end
955
+ }
956
+ end
957
+
958
+ it 'correctly resolves many bindings, creates new modules and classes, and defines methods' do
959
+ tree = annotate_all(@input)
960
+
961
+ bindings_mod = 'Laser::Analysis::Bindings'
962
+ ClassRegistry['Laser'].should be_a(LaserModule)
963
+ ClassRegistry['Laser::Analysis'].should be_a(LaserModule)
964
+ ClassRegistry[bindings_mod].should be_a(LaserModule)
965
+ ClassRegistry["#{bindings_mod}::Base"].should be_a(LaserClass)
966
+ ClassRegistry["#{bindings_mod}::KeywordBinding"].should be_a(LaserClass)
967
+ ClassRegistry["#{bindings_mod}::ConstantBinding"].should be_a(LaserClass)
968
+ ClassRegistry["#{bindings_mod}::LocalVariableBinding"].should be_a(LaserClass)
969
+ ClassRegistry["#{bindings_mod}::GlobalVariableBinding"].should be_a(LaserClass)
970
+ ClassRegistry["#{bindings_mod}::ArgumentBinding"].should be_a(LaserClass)
971
+
972
+ ClassRegistry["#{bindings_mod}::Base"].superclass.should be ClassRegistry['Object']
973
+ [ClassRegistry["#{bindings_mod}::KeywordBinding"],
974
+ ClassRegistry["#{bindings_mod}::ConstantBinding"],
975
+ ClassRegistry["#{bindings_mod}::LocalVariableBinding"],
976
+ ClassRegistry["#{bindings_mod}::GlobalVariableBinding"],
977
+ ClassRegistry["#{bindings_mod}::ArgumentBinding"]].each do |subclass|
978
+ subclass.superclass.should be ClassRegistry["#{bindings_mod}::Base"]
979
+ end
980
+
981
+ generic = ClassRegistry["#{bindings_mod}::Base"]
982
+ class_binding = ClassRegistry["#{bindings_mod}::ConstantBinding"]
983
+ kw_binding = ClassRegistry["#{bindings_mod}::KeywordBinding"]
984
+ arg_binding = ClassRegistry["#{bindings_mod}::ArgumentBinding"]
985
+
986
+ arg_binding.ancestors.should == [arg_binding, generic, ClassRegistry['Comparable'],
987
+ ClassRegistry['Object'], ClassRegistry['Kernel'],
988
+ ClassRegistry['BasicObject']]
989
+
990
+ %w(initialize bind! <=> scope protocol class_used to_s inspect).each do |method|
991
+ generic.instance_method(method).should_not be_nil
992
+ generic.visibility_table[method].should == :public
993
+ end
994
+ kw_binding.visibility_table[:bind!].should == :private
995
+ init_method = generic.instance_method(:initialize)
996
+ init_method.arguments.size.should == 2
997
+ init_method.arguments.map(&:name).should == ['name', 'value']
998
+
999
+ arg_binding_method = arg_binding.instance_method(:initialize)
1000
+ arg_binding_method.arguments.size.should == 4
1001
+ arg_binding_method.arguments.map(&:name).should == ['name', 'value', 'kind', 'default_value']
1002
+
1003
+
1004
+ generic.instance_method(:initialize).arity.should == (2..2)
1005
+ generic.instance_method(:bind!).arity.should == (1..1)
1006
+ generic.instance_method(:<=>).arity.should == (1..1)
1007
+ generic.instance_method(:scope).arity.should == (0..0)
1008
+ generic.instance_method(:class_used).arity.should == (0..0)
1009
+ class_binding.instance_method(:bind!).arity.should == (1..2)
1010
+ arg_binding.instance_method(:initialize).arity.should == (3..4)
1011
+ end
1012
+ end
1013
+ end