laser 0.7.0.pre1

Sign up to get free protection for your applications and to get access to all the features.
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