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,110 @@
1
+ require_relative '../spec_helper'
2
+
3
+ def cfg_builder_for(input)
4
+ ControlFlow::GraphBuilder.new(annotate_all(input)[1][0][3])
5
+ end
6
+
7
+ RSpec::Matchers.define :have_error do |klass|
8
+ chain :on_line do |number|
9
+ @line = number
10
+ end
11
+
12
+ chain :with_message do |message|
13
+ @message_matcher = message
14
+ end
15
+
16
+ match do |graph|
17
+ graph.all_errors.any? do |err|
18
+ @matches_class = err.is_a?(klass)
19
+ @matches_line = !@line || err.line_number == @line
20
+ @matches_message = if String === @message_matcher
21
+ err.message == @message_matcher
22
+ elsif Regexp === @message_matcher
23
+ err.message =~ @message_matcher
24
+ else
25
+ true
26
+ end
27
+ @matches_message && @matches_line && @matches_class
28
+ end
29
+ end
30
+
31
+ failure_message_for_should do |graph|
32
+ result = 'expected an error that'
33
+ result << " was of the class #{klass.name}" if !@matches_message
34
+ result << " was on line #@line" if !@matches_line
35
+ if !@matches_message
36
+ result << " matches the regex #{@message_matcher}" if Regexp === @message_matcher
37
+ result << " matches the regex #{@message_matcher}" if String === @message_matcher
38
+ end
39
+ result
40
+ end
41
+
42
+ failure_message_for_should_not do |graph|
43
+ "Expected to not find any errors of class #{klass.name}"
44
+ end
45
+ end
46
+
47
+ RSpec::Matchers.define :have_constant do |name|
48
+ chain :with_value do |value|
49
+ @value = value
50
+ end
51
+
52
+ match do |graph|
53
+ graph.constants.keys.find do |var|
54
+ next unless var.non_ssa_name == name
55
+ @constant = var
56
+ @value ||= nil
57
+ if @value
58
+ @constant && (@constant.value == @value)
59
+ else
60
+ @constant
61
+ end
62
+ end
63
+ end
64
+
65
+ failure_message_for_should do |graph|
66
+ if !@constant
67
+ "Expected variable '#{name}' to be inferred as a constant, but it was not."
68
+ elsif @constant.value != @value
69
+ "Expected variable '#{name}' to have value #{@value}, but it was #{@constant.value}."
70
+ else
71
+ "UNEXPECTED FAILURE?!"
72
+ end
73
+ end
74
+
75
+ failure_message_for_should_not do |graph|
76
+ if @constant && @constant.value == @value
77
+ "Expected variable '#{name}' to not have value #{@value}, but it was #{@constant.value}."
78
+ elsif @constant
79
+ "Expected variable '#{name}' to not be inferred as a constant, but it was."
80
+ else
81
+ "UNEXPECTED FAILURE?!"
82
+ end
83
+ end
84
+ end
85
+
86
+
87
+ include Laser::Analysis
88
+ def annotate_all_cfg(body)
89
+ inputs = [['(stdin)', body]]
90
+ inputs.map! do |filename, text|
91
+ [filename, text, Sexp.new(RipperPlus.sexp(text), filename, text)]
92
+ end
93
+ Annotations.apply_inherited_attributes(inputs)
94
+ inputs[0][2]
95
+ end
96
+ def cfg(input)
97
+ cfg_builder = ControlFlow::GraphBuilder.new(annotate_all_cfg(input))
98
+ graph = cfg_builder.build
99
+ graph.analyze
100
+ graph
101
+ end
102
+ def cfg_method(input)
103
+ method_tree = annotate_all_cfg(input)
104
+ body = method_tree.find_type(:bodystmt)
105
+ cfg_builder = ControlFlow::GraphBuilder.new(
106
+ body, Signature.arg_list_for_arglist(body.prev))
107
+ graph = cfg_builder.build
108
+ graph.analyze
109
+ graph
110
+ end
@@ -0,0 +1,125 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe 'Tuple misuse inference' do
4
+ it 'should find code that has statically too few mlhs for mrhs' do
5
+ g = cfg_method <<-EOF
6
+ def foo(x)
7
+ a, b, c, d = x, x
8
+ end
9
+ EOF
10
+ g.should have_error(Laser::UnassignedLHSError).on_line(2).with_message(/\(c\)/)
11
+ g.should have_error(Laser::UnassignedLHSError).on_line(2).with_message(/\(d\)/)
12
+ end
13
+
14
+ it 'should find code that has statically too many mlhs for mrhs' do
15
+ g = cfg_method <<-EOF
16
+ def foo(x)
17
+ a, d = x, x, x
18
+ end
19
+ EOF
20
+ g.should have_error(Laser::DiscardedRHSError).on_line(2)
21
+ end
22
+
23
+ it 'should find statically useless LHS splats' do
24
+ g = cfg_method <<-EOF
25
+ def foo(x)
26
+ a, *b, d = x, x
27
+ end
28
+ EOF
29
+ g.should have_error(Laser::UnassignedLHSError).on_line(2).with_message(/\(b\)/)
30
+ end
31
+
32
+ it 'should find statically useless LHS unnamed splats and report them differently' do
33
+ g = cfg_method <<-EOF
34
+ def foo(x)
35
+ a, *, d = x, x
36
+ end
37
+ EOF
38
+ g.should have_error(Laser::UnassignedLHSError).on_line(2).with_message(/Unnamed LHS/i)
39
+ end
40
+
41
+ it 'should find statically discarded RHS splats' do
42
+ g = cfg_method <<-EOF
43
+ def foo(x)
44
+ a, b, c = x, x, x, *x
45
+ end
46
+ EOF
47
+ g.should have_error(Laser::DiscardedRHSError).on_line(2).with_message(/splat/i)
48
+ end
49
+
50
+ it 'should find dynamically-proven unassigned LHS vars' do
51
+ g = cfg <<-EOF
52
+ class TupleMisuse1
53
+ def foo(x)
54
+ a, b, c = bar(x)
55
+ end
56
+ def bar(x)
57
+ [x, x]
58
+ end
59
+ end
60
+ TupleMisuse1.new.foo(gets)
61
+ EOF
62
+ g.should have_error(Laser::UnassignedLHSError).on_line(3)
63
+ end
64
+
65
+ it 'should find dynamically-proven discarded RHS vals' do
66
+ g = cfg <<-EOF
67
+ class TupleMisuse1
68
+ def foo(x)
69
+ a, b = bar(x)
70
+ end
71
+ def bar(x)
72
+ [x, x, x]
73
+ end
74
+ end
75
+ TupleMisuse1.new.foo(gets)
76
+ EOF
77
+ g.should have_error(Laser::DiscardedRHSError).on_line(3)
78
+ end
79
+
80
+ it 'should find dynamically-proven unassigned LHS splats' do
81
+ g = cfg <<-EOF
82
+ class TupleMisuse1
83
+ def foo(x)
84
+ a, *b, c = bar(x)
85
+ end
86
+ def bar(x)
87
+ [x, x]
88
+ end
89
+ end
90
+ TupleMisuse1.new.foo(gets)
91
+ EOF
92
+ g.should have_error(Laser::UnassignedLHSError).on_line(3)
93
+ end
94
+
95
+ it 'should find dynamically-proven wasted RHS splat vals' do
96
+ g = cfg <<-EOF
97
+ class TupleMisuse1
98
+ def foo(x)
99
+ a, b, c = x, x, *bar(x)
100
+ end
101
+ def bar(x)
102
+ [x, x]
103
+ end
104
+ end
105
+ TupleMisuse1.new.foo(gets)
106
+ EOF
107
+ g.should have_error(Laser::DiscardedRHSError).on_line(3)
108
+ end
109
+
110
+
111
+ it 'should find dynamically-proven unassigned LHS splats with an RHS splat too' do
112
+ g = cfg <<-EOF
113
+ class TupleMisuse1
114
+ def foo(x)
115
+ a, *b, c, d = x, *bar(x)
116
+ end
117
+ def bar(x)
118
+ [x, x]
119
+ end
120
+ end
121
+ TupleMisuse1.new.foo(gets)
122
+ EOF
123
+ g.should have_error(Laser::UnassignedLHSError).on_line(3)
124
+ end
125
+ end
@@ -0,0 +1,76 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe ControlFlow::UnreachabilityAnalysis do
4
+ it 'should find code that follows explicit return' do
5
+ g = cfg_method <<-EOF
6
+ def foo(x)
7
+ y = gets() * 2
8
+ return y
9
+ p y
10
+ end
11
+ EOF
12
+ g.should have_error(Laser::DeadCodeWarning).on_line(4)
13
+ end
14
+
15
+ %w{next break redo}.each do |keyword|
16
+ it "should find code that follows a #{keyword}" do
17
+ g = cfg_method <<-EOF
18
+ def foo(x)
19
+ while y = gets() * 2
20
+ p y
21
+ #{keyword}
22
+ z = y.foo
23
+ end
24
+ end
25
+ EOF
26
+ g.should have_error(Laser::DeadCodeWarning).on_line(5)
27
+ end
28
+ end
29
+
30
+ it 'should find code that follows an if/else/elsif in which each branch jumps' do
31
+ g = cfg_method <<-EOF
32
+ def foo(x)
33
+ y = gets() * 2
34
+ if y.size > 10
35
+ return y
36
+ elsif y.size < 10
37
+ return y[0..4]
38
+ else
39
+ return 'hello'
40
+ end
41
+ puts y
42
+ end
43
+ EOF
44
+ g.should have_error(Laser::DeadCodeWarning).on_line(10)
45
+ end
46
+
47
+ it 'should find code that never runs due to constant propagation' do
48
+ g = cfg_method <<-EOF
49
+ def foo(x)
50
+ y = 'hello' * 3
51
+ if y == 'hellohellohello'
52
+ puts gets
53
+ z = 3
54
+ else
55
+ z = 10
56
+ end
57
+ a = z
58
+ end
59
+ EOF
60
+ g.should have_error(Laser::DeadCodeWarning).on_line(7)
61
+ end
62
+
63
+ it 'should find code that never runs due to CP + local type inference' do
64
+ g = cfg_method <<-EOF
65
+ def foo
66
+ a = gets
67
+ if a.strip # no !, always returns a String
68
+ 10
69
+ else
70
+ 20 # dead code
71
+ end
72
+ end
73
+ EOF
74
+ g.should have_error(Laser::DeadCodeWarning).on_line(6)
75
+ end
76
+ end
@@ -0,0 +1,99 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe ControlFlow::UnusedVariables do
4
+ it 'should find a simple unused variable' do
5
+ g = cfg_method <<-EOF
6
+ def foo(x)
7
+ y = gets() * 2
8
+ z = y
9
+ c = z * z
10
+ end
11
+ EOF
12
+ g.should have_error(Laser::UnusedVariableWarning).on_line(4).with_message(/\b c \b/x)
13
+ end
14
+
15
+ it 'should find a more complex unused variable showing off ssa' do
16
+ g = cfg_method <<-EOF
17
+ def foo(x)
18
+ z = gets * 10
19
+ if z.size > 50
20
+ y = z # this y is used as return value
21
+ else
22
+ y = z * 2
23
+ puts y
24
+ end
25
+ end
26
+ EOF
27
+ g.should have_error(Laser::UnusedVariableWarning).on_line(4).with_message(/\b y \b/x)
28
+ end
29
+
30
+ it 'should see when a variable is assigned and used to compute only unused vars' do
31
+ g = cfg_method <<-EOF
32
+ def foo(x)
33
+ z = gets * 10
34
+ d = z * 2
35
+ a = d
36
+ puts z
37
+ nil
38
+ end
39
+ EOF
40
+ g.should have_error(Laser::UnusedVariableWarning).on_line(3).with_message(/\b d \b/x)
41
+ g.should have_error(Laser::UnusedVariableWarning).on_line(4).with_message(/\b a \b/x)
42
+ g.should_not have_error(Laser::UnusedVariableWarning).with_message(/\b z \b/x)
43
+ end
44
+
45
+ it 'should ignore SSA variables assigned and used to compute only unused vars' do
46
+ g = cfg_method <<-EOF
47
+ def foo(x)
48
+ z = gets * 10
49
+ if z.size > 3
50
+ d = z * 2
51
+ c = z
52
+ else
53
+ d = z * 10
54
+ c = 30
55
+ end
56
+ j = d
57
+ c
58
+ end
59
+ EOF
60
+
61
+ g.should have_error(Laser::UnusedVariableWarning).on_line(4).with_message(/\b d \b/x)
62
+ g.should have_error(Laser::UnusedVariableWarning).on_line(7).with_message(/\b d \b/x)
63
+ g.should have_error(Laser::UnusedVariableWarning).on_line(10).with_message(/\b j \b/x)
64
+ end
65
+
66
+ it 'is improved by constant propagation' do
67
+ g = cfg_method <<-EOF
68
+ def foo(x)
69
+ z = (10 ** 5).to_s(5)
70
+ if z == "11200000"
71
+ d = z * 2
72
+ c = z
73
+ else
74
+ d = z * 10
75
+ c = 30
76
+ end
77
+ j = d
78
+ c
79
+ end
80
+ EOF
81
+
82
+ g.should have_error(Laser::UnusedVariableWarning).on_line(4).with_message(/\b d \b/x)
83
+ g.should have_error(Laser::UnusedVariableWarning).on_line(7).with_message(/\b d \b/x)
84
+ g.should have_error(Laser::UnusedVariableWarning).on_line(8).with_message(/\b c \b/x)
85
+ g.should have_error(Laser::UnusedVariableWarning).on_line(10).with_message(/\b j \b/x)
86
+ end
87
+
88
+ it 'recognizes unused variables introduced through multiple assignment' do
89
+ g = cfg_method <<-EOF
90
+ def foo(x)
91
+ y = gets() * 2
92
+ z, i = y, 3
93
+ c = z * z
94
+ end
95
+ EOF
96
+ g.should have_error(Laser::UnusedVariableWarning).on_line(3).with_message(/\b i \b/x)
97
+ g.should have_error(Laser::UnusedVariableWarning).on_line(4).with_message(/\b c \b/x)
98
+ end
99
+ end
@@ -0,0 +1,372 @@
1
+ require_relative 'spec_helper'
2
+
3
+ describe ControlFlow::YieldProperties do
4
+ it 'should recognize non-yielding methods' do
5
+ g = cfg_method <<-EOF
6
+ def foo(x)
7
+ y = gets() * 2
8
+ z = y
9
+ c = z * z
10
+ end
11
+ EOF
12
+ g.yield_type.should be :ignored
13
+ g.yield_arity.should == Set[]
14
+ end
15
+
16
+ it 'should recognize non-yielding methods via CP' do
17
+ g = cfg_method <<-EOF
18
+ def foo(x)
19
+ x = 2 ** 16
20
+ if x == 65536
21
+ puts x
22
+ else
23
+ yield
24
+ end
25
+ end
26
+ EOF
27
+ g.yield_type.should be :ignored
28
+ g.yield_arity.should == Set[]
29
+ end
30
+
31
+ it 'should recognize simple required-yield methods' do
32
+ g = cfg_method <<-EOF
33
+ def tap
34
+ yield self
35
+ self
36
+ end
37
+ EOF
38
+ g.yield_type.should be :required
39
+ g.yield_arity.should == Set[1]
40
+ end
41
+
42
+ it 'denotes the method required when a branch is unprovable' do
43
+ g = cfg_method <<-EOF
44
+ def one
45
+ if gets.size < 0
46
+ yield
47
+ else
48
+ 1
49
+ end
50
+ end
51
+ EOF
52
+ g.yield_type.should be :required
53
+ g.yield_arity.should == Set[0]
54
+ end
55
+ ['block_given?', 'defined?(yield)', 'defined?(yield($., *$*))', 'Proc.new', 'iterator?'].each do |guard|
56
+ it "denotes the method optional when yield is guarded by #{guard}" do
57
+ g = cfg_method <<-EOF
58
+ def one
59
+ if #{guard}
60
+ yield 1
61
+ else
62
+ 1
63
+ end
64
+ end
65
+ EOF
66
+ g.yield_type.should be :optional
67
+ g.yield_arity.should == Set[1]
68
+ end
69
+
70
+ it "denotes the method foolish when yield is not guarded by #{guard}, but the block is unused when given" do
71
+ g = cfg_method <<-EOF
72
+ def one
73
+ if #{guard}
74
+ 1
75
+ else
76
+ yield 1
77
+ end
78
+ end
79
+ EOF
80
+ g.yield_type.should be :foolish
81
+ g.yield_arity.should == Set[]
82
+ end
83
+ end
84
+
85
+ it 'denotes the method optional when the explicit block arg is checked vs. nil' do
86
+ g = cfg_method <<-EOF
87
+ def one(&blk)
88
+ if blk != nil
89
+ yield 1
90
+ yield(1, 2)
91
+ else
92
+ 1
93
+ end
94
+ end
95
+ EOF
96
+ g.yield_type.should be :optional
97
+ g.yield_arity.should == Set[1, 2]
98
+ end
99
+ [['.call(', ')'], ['[', ']'], ['.===(', ')']].each do |prefix, suffix|
100
+ it "denotes the method optional when the explicit block arg is checked vs. nil and called with #{prefix}#{suffix}" do
101
+ g = cfg_method <<-EOF
102
+ def one(&blk)
103
+ if blk != nil
104
+ blk#{prefix}2, 3#{suffix}
105
+ else
106
+ 1
107
+ end
108
+ end
109
+ EOF
110
+ g.yield_type.should be :optional
111
+ g.yield_arity.should == Set[2]
112
+ end
113
+
114
+ it "denotes the method required when the explicit block arg is not checked vs. nil and called with #{prefix}#{suffix}" do
115
+ g = cfg_method <<-EOF
116
+ def one(&blk)
117
+ blk#{prefix}2, 3#{suffix}
118
+ 1
119
+ end
120
+ EOF
121
+ g.yield_type.should be :required
122
+ g.yield_arity.should == Set[2]
123
+ end
124
+
125
+ it "denotes the method foolish when the explicit block arg is checked vs. nil and called with #{prefix}#{suffix}" do
126
+ g = cfg_method <<-EOF
127
+ def one(&blk)
128
+ if blk == nil
129
+ blk#{prefix}2, 3#{suffix}
130
+ end
131
+ 1
132
+ end
133
+ EOF
134
+ g.yield_type.should be :foolish
135
+ g.yield_arity.should == Set[]
136
+ end
137
+
138
+ it "denotes the method optional when the Proc.new block arg is checked vs. nil and called with #{prefix}#{suffix}" do
139
+ g = cfg_method <<-EOF
140
+ def one
141
+ blk = Proc::new
142
+ if blk != nil
143
+ blk#{prefix}2, 3#{suffix}
144
+ else
145
+ 1
146
+ end
147
+ end
148
+ EOF
149
+ g.yield_type.should be :optional
150
+ g.yield_arity.should == Set[2]
151
+ end
152
+
153
+ it "denotes the method required when the Proc.new block arg is not checked vs. nil and called with #{prefix}#{suffix}" do
154
+ g = cfg_method <<-EOF
155
+ def one
156
+ blk = Proc::new
157
+ blk#{prefix}2, 3#{suffix}
158
+ 1
159
+ end
160
+ EOF
161
+ g.yield_type.should be :required
162
+ g.yield_arity.should == Set[2]
163
+ end
164
+
165
+ it "denotes the method foolish when the Proc.new block arg is checked vs. nil and called with #{prefix}#{suffix}" do
166
+ g = cfg_method <<-EOF
167
+ def one
168
+ blk = Proc::new
169
+ if blk == nil
170
+ blk#{prefix}2, 3#{suffix}
171
+ end
172
+ 1
173
+ end
174
+ EOF
175
+ g.yield_type.should be :foolish
176
+ g.yield_arity.should == Set[]
177
+ end
178
+
179
+ it 'denotes the method ignored when the explicit block arg is never called' do
180
+ g = cfg_method <<-EOF
181
+ def one(&blk)
182
+ result = blk.nil? ? 5 : 10
183
+ result ** result
184
+ end
185
+ EOF
186
+ g.yield_type.should be :ignored
187
+ g.yield_arity.should == Set[]
188
+ end
189
+
190
+ it "is not confused by sending #{prefix}#{suffix} to other arguments" do
191
+ g = cfg_method <<-EOF
192
+ def one(other_arg, &blk)
193
+ other_arg#{prefix}5#{suffix}
194
+ end
195
+ EOF
196
+ g.yield_type.should be :ignored
197
+ end
198
+
199
+ it "uses SSA information to find aliases to the block that receive #{prefix}#{suffix}" do
200
+ g = cfg_method <<-EOF
201
+ def one(other_arg, &blk)
202
+ if gets.size > 2
203
+ other_arg = blk
204
+ end
205
+ other_arg#{prefix}2#{suffix}
206
+ end
207
+ EOF
208
+ g.yield_type.should be :required
209
+ end
210
+ end
211
+
212
+ %w(LocalJumpError StandardError Exception Object Kernel BasicObject).each do |exc|
213
+ it "denotes the method optional when yield is guarded by rescue of #{exc}" do
214
+ g = cfg_method <<-EOF
215
+ def one
216
+ yield 1
217
+ 4
218
+ rescue #{exc}
219
+ 2
220
+ end
221
+ EOF
222
+ g.yield_type.should be :optional
223
+ g.yield_arity.should == Set[1]
224
+ end
225
+ end
226
+
227
+ it "denotes the method optional when yield is guarded by rescue with no handlers" do
228
+ g = cfg_method <<-EOF
229
+ def one
230
+ yield 1
231
+ 4
232
+ rescue
233
+ 2
234
+ end
235
+ EOF
236
+ g.yield_type.should be :optional
237
+ g.yield_arity.should == Set[1]
238
+ end
239
+
240
+ it 'denotes the method optional when yield is guarded by a rescue modifier' do
241
+ g = cfg_method <<-EOF
242
+ def one
243
+ yield 1 rescue 2
244
+ end
245
+ EOF
246
+ g.yield_type.should be :optional
247
+ g.yield_arity.should == Set[1]
248
+ end
249
+
250
+ it "denotes the method required if the yield is guarded by a non-matching rescue" do
251
+ g = cfg_method <<-EOF
252
+ def one
253
+ yield 1
254
+ 4
255
+ rescue RuntimeError
256
+ 2
257
+ end
258
+ EOF
259
+ g.yield_type.should be :required
260
+ g.yield_arity.should == Set[1]
261
+ end
262
+
263
+ it 'infers yield likelihood with to_proc block syntax' do
264
+ cfg <<-EOF
265
+ class YP1
266
+ def foo(x)
267
+ yield x if block_given?
268
+ end
269
+ def bar(y, &blk)
270
+ foo(y, &blk)
271
+ end
272
+ end
273
+ EOF
274
+ method = ClassRegistry['YP1'].instance_method(:bar)
275
+ method.yield_type.should be :optional
276
+ end
277
+
278
+ it 'infers yield likelihood with to_proc to a builtin method' do
279
+ cfg <<-EOF
280
+ class YP2
281
+ def bar(x, &blk)
282
+ [1, 2, x].each(&blk)
283
+ end
284
+ end
285
+ EOF
286
+ method = ClassRegistry['YP2'].instance_method(:bar)
287
+ method.yield_type.should be :optional
288
+ end
289
+
290
+ it 'proves optionality in a complex example of yield likelihood through classes and ivars' do
291
+ cfg <<-EOF
292
+ class YP3
293
+ def initialize(data)
294
+ @data = data
295
+ end
296
+ def each(&blk)
297
+ @data.each(&blk)
298
+ end
299
+ end
300
+ class YP4
301
+ def initialize(data)
302
+ @data = data
303
+ end
304
+ def foobar(&blk)
305
+ @data.each(&blk)
306
+ end
307
+ end
308
+ YP4Temp1 = YP4.new(YP3.new([1, 2, 3]))
309
+ YP4Temp2 = YP4.new(YP3.new({a: :b, c: :d}))
310
+ YP4Temp3 = YP4.new([5, 6])
311
+ EOF
312
+ method = ClassRegistry['YP4'].instance_method(:foobar)
313
+ method.yield_type.should be :optional
314
+ end
315
+
316
+ it 'infers a complex example of yield likelihood through classes and ivars' do
317
+ cfg <<-EOF
318
+ class YP5
319
+ def each
320
+ yield 1
321
+ yield 2
322
+ yield 3
323
+ end
324
+ end
325
+ class YP6
326
+ def initialize(data)
327
+ @data = data
328
+ end
329
+ def foobar(&blk)
330
+ @data.each(&blk)
331
+ end
332
+ end
333
+ YP6Temp1 = YP6.new(YP5.new)
334
+ EOF
335
+ method = ClassRegistry['YP6'].instance_method(:foobar)
336
+ method.yield_type.should be :required
337
+ end
338
+
339
+ it 'infers yield likelihood through super-delegation' do
340
+ cfg <<-EOF
341
+ class YP7
342
+ def each
343
+ yield 1 if block_given?
344
+ end
345
+ end
346
+ class YP8 < YP7
347
+ def each(&blk)
348
+ super(&blk)
349
+ end
350
+ end
351
+ EOF
352
+ method = ClassRegistry['YP8'].instance_method(:each)
353
+ method.yield_type.should be :optional
354
+ end
355
+
356
+ it 'infers yield likelihood through zsuper-delegation' do
357
+ cfg <<-EOF
358
+ class YP9
359
+ def each
360
+ yield 1 if block_given?
361
+ end
362
+ end
363
+ class YP10 < YP9
364
+ def each
365
+ super
366
+ end
367
+ end
368
+ EOF
369
+ method = ClassRegistry['YP10'].instance_method(:each)
370
+ method.yield_type.should be :optional
371
+ end
372
+ end