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.
- data/.document +5 -0
- data/.rspec +1 -0
- data/Gemfile +14 -0
- data/LICENSE +661 -0
- data/README.md +158 -0
- data/Rakefile +104 -0
- data/VERSION +1 -0
- data/bin/laser +7 -0
- data/design_docs/goals.md +57 -0
- data/design_docs/object_regex.md +426 -0
- data/design_docs/type_annotations.md +80 -0
- data/ext/laser/BasicBlock.cpp +572 -0
- data/ext/laser/BasicBlock.h +118 -0
- data/ext/laser/extconf.rb +3 -0
- data/features/laser.feature +25 -0
- data/features/step_definitions/laser_steps.rb +39 -0
- data/features/support/env.rb +14 -0
- data/features/support/testdata/1_input +1 -0
- data/features/support/testdata/1_output +1 -0
- data/features/support/testdata/2_input +4 -0
- data/features/support/testdata/2_output +4 -0
- data/features/support/testdata/3_input +8 -0
- data/features/support/testdata/3_output +11 -0
- data/features/support/testdata/4_input +5 -0
- data/features/support/testdata/4_output +5 -0
- data/features/support/testdata/5_input +13 -0
- data/laser.gemspec +382 -0
- data/lib/laser.rb +98 -0
- data/lib/laser/analysis/annotations.rb +95 -0
- data/lib/laser/analysis/annotations/annotation_config.yaml +3 -0
- data/lib/laser/analysis/annotations/comment_attachment_annotation.rb +66 -0
- data/lib/laser/analysis/annotations/node_pointers_annotation.rb +36 -0
- data/lib/laser/analysis/annotations/runtime_annotation.rb +55 -0
- data/lib/laser/analysis/argument_expansion.rb +132 -0
- data/lib/laser/analysis/arity.rb +34 -0
- data/lib/laser/analysis/bindings.rb +144 -0
- data/lib/laser/analysis/bootstrap/bootstrap.rb +298 -0
- data/lib/laser/analysis/bootstrap/laser_class.rb +106 -0
- data/lib/laser/analysis/bootstrap/laser_method.rb +255 -0
- data/lib/laser/analysis/bootstrap/laser_module.rb +403 -0
- data/lib/laser/analysis/bootstrap/laser_module_copy.rb +74 -0
- data/lib/laser/analysis/bootstrap/laser_object.rb +69 -0
- data/lib/laser/analysis/bootstrap/laser_proc.rb +150 -0
- data/lib/laser/analysis/bootstrap/laser_singleton_class.rb +44 -0
- data/lib/laser/analysis/comments.rb +35 -0
- data/lib/laser/analysis/control_flow.rb +28 -0
- data/lib/laser/analysis/control_flow/alias_analysis.rb +31 -0
- data/lib/laser/analysis/control_flow/basic_block.rb +105 -0
- data/lib/laser/analysis/control_flow/cfg_builder.rb +2505 -0
- data/lib/laser/analysis/control_flow/cfg_instruction.rb +190 -0
- data/lib/laser/analysis/control_flow/constant_propagation.rb +742 -0
- data/lib/laser/analysis/control_flow/control_flow_graph.rb +370 -0
- data/lib/laser/analysis/control_flow/lifetime_analysis.rb +91 -0
- data/lib/laser/analysis/control_flow/method_call_search.rb +26 -0
- data/lib/laser/analysis/control_flow/raise_properties.rb +25 -0
- data/lib/laser/analysis/control_flow/simulation.rb +385 -0
- data/lib/laser/analysis/control_flow/static_single_assignment.rb +185 -0
- data/lib/laser/analysis/control_flow/unreachability_analysis.rb +57 -0
- data/lib/laser/analysis/control_flow/unused_variables.rb +91 -0
- data/lib/laser/analysis/control_flow/yield_properties.rb +103 -0
- data/lib/laser/analysis/errors.rb +131 -0
- data/lib/laser/analysis/laser_utils.rb +18 -0
- data/lib/laser/analysis/lexical_analysis.rb +172 -0
- data/lib/laser/analysis/method_call.rb +68 -0
- data/lib/laser/analysis/protocol_registry.rb +30 -0
- data/lib/laser/analysis/scope.rb +118 -0
- data/lib/laser/analysis/sexp.rb +159 -0
- data/lib/laser/analysis/sexp_analysis.rb +40 -0
- data/lib/laser/analysis/sexp_extensions/constant_extraction.rb +115 -0
- data/lib/laser/analysis/sexp_extensions/source_location.rb +164 -0
- data/lib/laser/analysis/sexp_extensions/type_inference.rb +47 -0
- data/lib/laser/analysis/signature.rb +76 -0
- data/lib/laser/analysis/special_methods/send.rb +67 -0
- data/lib/laser/analysis/unused_methods.rb +21 -0
- data/lib/laser/analysis/visitor.rb +141 -0
- data/lib/laser/annotation_parser/annotations.treetop +126 -0
- data/lib/laser/annotation_parser/annotations_parser.rb +748 -0
- data/lib/laser/annotation_parser/class_annotations.treetop +82 -0
- data/lib/laser/annotation_parser/class_annotations_parser.rb +654 -0
- data/lib/laser/annotation_parser/overload.treetop +24 -0
- data/lib/laser/annotation_parser/overload_parser.rb +167 -0
- data/lib/laser/annotation_parser/parsers.rb +6 -0
- data/lib/laser/annotation_parser/structural.treetop +37 -0
- data/lib/laser/annotation_parser/structural_parser.rb +406 -0
- data/lib/laser/annotation_parser/useful_parsers.treetop +47 -0
- data/lib/laser/annotation_parser/useful_parsers_parser.rb +674 -0
- data/lib/laser/rake/task.rb +46 -0
- data/lib/laser/runner.rb +189 -0
- data/lib/laser/scanner.rb +169 -0
- data/lib/laser/standard_library/_thread.rb +110 -0
- data/lib/laser/standard_library/abbrev.rb +103 -0
- data/lib/laser/standard_library/array.rb +418 -0
- data/lib/laser/standard_library/base64.rb +91 -0
- data/lib/laser/standard_library/basic_object.rb +55 -0
- data/lib/laser/standard_library/benchmark.rb +556 -0
- data/lib/laser/standard_library/bignum.rb +185 -0
- data/lib/laser/standard_library/cgi.rb +275 -0
- data/lib/laser/standard_library/cgi/cookie.rb +147 -0
- data/lib/laser/standard_library/cgi/core.rb +791 -0
- data/lib/laser/standard_library/cgi/html.rb +1021 -0
- data/lib/laser/standard_library/cgi/session.rb +537 -0
- data/lib/laser/standard_library/cgi/session/pstore.rb +111 -0
- data/lib/laser/standard_library/cgi/util.rb +188 -0
- data/lib/laser/standard_library/class_definitions.rb +333 -0
- data/lib/laser/standard_library/comparable.rb +125 -0
- data/lib/laser/standard_library/complex.rb +162 -0
- data/lib/laser/standard_library/enumerable.rb +178 -0
- data/lib/laser/standard_library/exceptions.rb +135 -0
- data/lib/laser/standard_library/fixnum.rb +188 -0
- data/lib/laser/standard_library/float.rb +180 -0
- data/lib/laser/standard_library/hash.rb +237 -0
- data/lib/laser/standard_library/integer.rb +123 -0
- data/lib/laser/standard_library/laser_magic.rb +7 -0
- data/lib/laser/standard_library/nil_false_true.rb +113 -0
- data/lib/laser/standard_library/numbers.rb +192 -0
- data/lib/laser/standard_library/proc.rb +31 -0
- data/lib/laser/standard_library/set.rb +1348 -0
- data/lib/laser/standard_library/string.rb +666 -0
- data/lib/laser/standard_library/stringio.rb +2 -0
- data/lib/laser/standard_library/symbol.rb +125 -0
- data/lib/laser/standard_library/tsort.rb +242 -0
- data/lib/laser/support/acts_as_struct.rb +66 -0
- data/lib/laser/support/frequency.rb +55 -0
- data/lib/laser/support/inheritable_attributes.rb +145 -0
- data/lib/laser/support/module_extensions.rb +94 -0
- data/lib/laser/support/placeholder_object.rb +13 -0
- data/lib/laser/third_party/rgl/adjacency.rb +221 -0
- data/lib/laser/third_party/rgl/base.rb +228 -0
- data/lib/laser/third_party/rgl/bidirectional.rb +39 -0
- data/lib/laser/third_party/rgl/condensation.rb +47 -0
- data/lib/laser/third_party/rgl/connected_components.rb +138 -0
- data/lib/laser/third_party/rgl/control_flow.rb +170 -0
- data/lib/laser/third_party/rgl/depth_first_spanning_tree.rb +37 -0
- data/lib/laser/third_party/rgl/dominators.rb +124 -0
- data/lib/laser/third_party/rgl/dot.rb +93 -0
- data/lib/laser/third_party/rgl/graphxml.rb +51 -0
- data/lib/laser/third_party/rgl/implicit.rb +174 -0
- data/lib/laser/third_party/rgl/mutable.rb +117 -0
- data/lib/laser/third_party/rgl/rdot.rb +445 -0
- data/lib/laser/third_party/rgl/topsort.rb +72 -0
- data/lib/laser/third_party/rgl/transitivity.rb +180 -0
- data/lib/laser/third_party/rgl/traversal.rb +348 -0
- data/lib/laser/types/types.rb +433 -0
- data/lib/laser/version.rb +14 -0
- data/lib/laser/warning.rb +149 -0
- data/lib/laser/warning_sets/default.yml +13 -0
- data/lib/laser/warnings/assignment_in_condition.rb +20 -0
- data/lib/laser/warnings/comment_spacing.rb +31 -0
- data/lib/laser/warnings/extra_blank_lines.rb +30 -0
- data/lib/laser/warnings/extra_whitespace.rb +16 -0
- data/lib/laser/warnings/hash_symbol_18_warning.rb +63 -0
- data/lib/laser/warnings/hash_symbol_19_warning.rb +29 -0
- data/lib/laser/warnings/line_length.rb +115 -0
- data/lib/laser/warnings/misaligned_unindentation.rb +17 -0
- data/lib/laser/warnings/operator_spacing.rb +68 -0
- data/lib/laser/warnings/parens_on_declaration.rb +30 -0
- data/lib/laser/warnings/rescue_exception.rb +42 -0
- data/lib/laser/warnings/semicolon.rb +25 -0
- data/lib/laser/warnings/sexp_errors.rb +24 -0
- data/lib/laser/warnings/uncalled_method_warning.rb +7 -0
- data/lib/laser/warnings/useless_double_quotes.rb +38 -0
- data/spec/analysis_specs/annotations_spec.rb +47 -0
- data/spec/analysis_specs/annotations_specs/comment_attachment_spec.rb +68 -0
- data/spec/analysis_specs/annotations_specs/node_pointers_annotation_spec.rb +90 -0
- data/spec/analysis_specs/annotations_specs/runtime_annotation_spec.rb +135 -0
- data/spec/analysis_specs/annotations_specs/spec_helper.rb +33 -0
- data/spec/analysis_specs/argument_expansion_spec.rb +113 -0
- data/spec/analysis_specs/bindings_spec.rb +36 -0
- data/spec/analysis_specs/comment_spec.rb +93 -0
- data/spec/analysis_specs/control_flow_specs/cfg_instruction_spec.rb +111 -0
- data/spec/analysis_specs/control_flow_specs/constant_propagation_spec.rb +560 -0
- data/spec/analysis_specs/control_flow_specs/control_flow_graph_spec.rb +5 -0
- data/spec/analysis_specs/control_flow_specs/raise_properties_spec.rb +310 -0
- data/spec/analysis_specs/control_flow_specs/raise_type_inference_spec.rb +301 -0
- data/spec/analysis_specs/control_flow_specs/return_type_inference_spec.rb +431 -0
- data/spec/analysis_specs/control_flow_specs/simulation_spec.rb +158 -0
- data/spec/analysis_specs/control_flow_specs/spec_helper.rb +110 -0
- data/spec/analysis_specs/control_flow_specs/tuple_misuse_inference_spec.rb +125 -0
- data/spec/analysis_specs/control_flow_specs/unreachability_analysis_spec.rb +76 -0
- data/spec/analysis_specs/control_flow_specs/unused_variable_spec.rb +99 -0
- data/spec/analysis_specs/control_flow_specs/yield_properties_spec.rb +372 -0
- data/spec/analysis_specs/error_spec.rb +30 -0
- data/spec/analysis_specs/laser_class_spec.rb +322 -0
- data/spec/analysis_specs/lexical_analysis_spec.rb +184 -0
- data/spec/analysis_specs/protocol_registry_spec.rb +63 -0
- data/spec/analysis_specs/scope_annotation_spec.rb +1013 -0
- data/spec/analysis_specs/scope_spec.rb +126 -0
- data/spec/analysis_specs/sexp_analysis_spec.rb +30 -0
- data/spec/analysis_specs/sexp_extension_specs/constant_extraction_spec.rb +309 -0
- data/spec/analysis_specs/sexp_extension_specs/source_location_spec.rb +231 -0
- data/spec/analysis_specs/sexp_extension_specs/spec_helper.rb +1 -0
- data/spec/analysis_specs/sexp_extension_specs/type_inference_spec.rb +252 -0
- data/spec/analysis_specs/sexp_spec.rb +167 -0
- data/spec/analysis_specs/spec_helper.rb +27 -0
- data/spec/analysis_specs/unused_methods_spec.rb +65 -0
- data/spec/analysis_specs/visitor_spec.rb +64 -0
- data/spec/annotation_parser_specs/annotations_parser_spec.rb +89 -0
- data/spec/annotation_parser_specs/class_annotation_parser_spec.rb +120 -0
- data/spec/annotation_parser_specs/overload_parser_spec.rb +39 -0
- data/spec/annotation_parser_specs/parsers_spec.rb +14 -0
- data/spec/annotation_parser_specs/spec_helper.rb +1 -0
- data/spec/annotation_parser_specs/structural_parser_spec.rb +67 -0
- data/spec/laser_spec.rb +14 -0
- data/spec/rake_specs/spec_helper.rb +1 -0
- data/spec/rake_specs/task_spec.rb +67 -0
- data/spec/runner_spec.rb +207 -0
- data/spec/scanner_spec.rb +75 -0
- data/spec/spec_helper.rb +121 -0
- data/spec/standard_library/exceptions_spec.rb +19 -0
- data/spec/standard_library/globals_spec.rb +14 -0
- data/spec/standard_library/set_spec.rb +31 -0
- data/spec/standard_library/spec_helper.rb +1 -0
- data/spec/standard_library/standard_library_spec.rb +302 -0
- data/spec/support_specs/acts_as_struct_spec.rb +94 -0
- data/spec/support_specs/frequency_spec.rb +23 -0
- data/spec/support_specs/module_extensions_spec.rb +117 -0
- data/spec/support_specs/spec_helper.rb +1 -0
- data/spec/type_specs/spec_helper.rb +1 -0
- data/spec/type_specs/types_spec.rb +133 -0
- data/spec/warning_spec.rb +95 -0
- data/spec/warning_specs/assignment_in_condition_spec.rb +68 -0
- data/spec/warning_specs/comment_spacing_spec.rb +65 -0
- data/spec/warning_specs/extra_blank_lines_spec.rb +70 -0
- data/spec/warning_specs/extra_whitespace_spec.rb +33 -0
- data/spec/warning_specs/hash_symbol_18_warning_spec.rb +89 -0
- data/spec/warning_specs/hash_symbol_19_warning_spec.rb +63 -0
- data/spec/warning_specs/line_length_spec.rb +173 -0
- data/spec/warning_specs/misaligned_unindentation_spec.rb +35 -0
- data/spec/warning_specs/operator_spacing_spec.rb +104 -0
- data/spec/warning_specs/parens_on_declaration_spec.rb +57 -0
- data/spec/warning_specs/rescue_exception_spec.rb +105 -0
- data/spec/warning_specs/semicolon_spec.rb +58 -0
- data/spec/warning_specs/spec_helper.rb +1 -0
- data/spec/warning_specs/useless_double_quotes_spec.rb +74 -0
- data/status_reports/2010/12/2010-12-14.md +163 -0
- data/status_reports/2010/12/2010-12-23.md +298 -0
- data/status_reports/2010/12/2010-12-24.md +6 -0
- data/test/third_party_tests/rgl_tests/TestComponents.rb +65 -0
- data/test/third_party_tests/rgl_tests/TestCycles.rb +61 -0
- data/test/third_party_tests/rgl_tests/TestDirectedGraph.rb +125 -0
- data/test/third_party_tests/rgl_tests/TestDot.rb +18 -0
- data/test/third_party_tests/rgl_tests/TestEdge.rb +34 -0
- data/test/third_party_tests/rgl_tests/TestGraph.rb +71 -0
- data/test/third_party_tests/rgl_tests/TestGraphXML.rb +57 -0
- data/test/third_party_tests/rgl_tests/TestImplicit.rb +52 -0
- data/test/third_party_tests/rgl_tests/TestRdot.rb +863 -0
- data/test/third_party_tests/rgl_tests/TestTransitivity.rb +129 -0
- data/test/third_party_tests/rgl_tests/TestTraversal.rb +220 -0
- data/test/third_party_tests/rgl_tests/TestUnDirectedGraph.rb +102 -0
- data/test/third_party_tests/rgl_tests/examples/north/Graph.log +128 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.0.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.1.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.11.graphml +31 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.12.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.13.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.14.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.15.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.16.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.17.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.19.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.2.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.20.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.22.graphml +43 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.24.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.25.graphml +45 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.27.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.28.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.29.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.3.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.30.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.31.graphml +42 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.34.graphml +42 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.37.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.38.graphml +38 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.39.graphml +36 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.4.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.40.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.41.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.42.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.45.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.46.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.5.graphml +31 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.50.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.56.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.57.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.58.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.6.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.60.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.61.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.62.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.68.graphml +30 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.69.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.7.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.70.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.71.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.72.graphml +28 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.74.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.75.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.78.graphml +27 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.79.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.8.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.80.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.82.graphml +35 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.83.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.85.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.86.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.88.graphml +37 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.89.graphml +29 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.9.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.90.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.91.graphml +31 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.92.graphml +26 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.93.graphml +32 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.10.94.graphml +34 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.12.8.graphml +40 -0
- data/test/third_party_tests/rgl_tests/examples/north/g.14.9.graphml +36 -0
- data/test/third_party_tests/rgl_tests/test_helper.rb +7 -0
- data/test/third_party_tests/test_inheritable_attributes.rb +187 -0
- metadata +470 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
require_relative 'spec_helper'
|
|
2
|
+
|
|
3
|
+
module ScopeSpecHelpers
|
|
4
|
+
def add_scope_instance_variables(klass)
|
|
5
|
+
before do
|
|
6
|
+
@base_scope = klass.new(Scope::GlobalScope, nil)
|
|
7
|
+
@nested_scope = klass.new(@base_scope, nil)
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe Scope::GlobalScope do
|
|
13
|
+
it 'is a closed scope' do
|
|
14
|
+
Scope::GlobalScope.should be_a(ClosedScope)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it 'has no parent' do
|
|
18
|
+
Scope::GlobalScope.parent.should be_nil
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it 'has a self pointer that is an Object' do
|
|
22
|
+
# self_ptr is a Bindings::Base
|
|
23
|
+
Scope::GlobalScope.self_ptr.klass.path.should == 'Class:main'
|
|
24
|
+
Scope::GlobalScope.self_ptr.name.should == 'main'
|
|
25
|
+
Scope::GlobalScope.lookup('self').expr_type.should == Types::ClassType.new('Class:main', :invariant)
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it 'has Object in its constants table' do
|
|
29
|
+
Scope::GlobalScope.constants['Object'].should_not be_nil
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe Scope do
|
|
34
|
+
describe '#initialize' do
|
|
35
|
+
it 'refuses to instantiate a Scope' do
|
|
36
|
+
expect { Scope.new(mock, mock) }.to raise_error(NotImplementedError)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
shared_examples_for Scope do
|
|
42
|
+
extend AnalysisHelpers
|
|
43
|
+
clean_registry
|
|
44
|
+
|
|
45
|
+
before do
|
|
46
|
+
@base_scope = described_class.new(Scope::GlobalScope, nil)
|
|
47
|
+
@nested_scope = described_class.new(@base_scope, nil)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
describe '#lookup' do
|
|
51
|
+
it 'raises a ScopeLookupFailure on failure' do
|
|
52
|
+
expect { Scope::GlobalScope.lookup('sdflkj') }.to raise_error(Scope::ScopeLookupFailure)
|
|
53
|
+
begin
|
|
54
|
+
Scope::GlobalScope.lookup('sdflkj')
|
|
55
|
+
rescue Scope::ScopeLookupFailure => err
|
|
56
|
+
err.scope.should == Scope::GlobalScope
|
|
57
|
+
err.query.should == 'sdflkj'
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe '#dup' do
|
|
63
|
+
before do
|
|
64
|
+
@a, @b, @c = many_mocks(3)
|
|
65
|
+
@nested_scope.locals['a'] = @a
|
|
66
|
+
@nested_scope.locals['b'] = @b
|
|
67
|
+
@nested_scope.locals['c'] = @c
|
|
68
|
+
@duplicate = @nested_scope.dup
|
|
69
|
+
end
|
|
70
|
+
it 'can duplicate itself, shallowly, retaining references to old bindings' do
|
|
71
|
+
@duplicate.lookup('a').should be @a
|
|
72
|
+
@duplicate.lookup('b').should be @b
|
|
73
|
+
@duplicate.lookup('c').should be @c
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it 'retains the same reference to parent scopes' do
|
|
77
|
+
@duplicate.parent.should be @nested_scope.parent
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it 'retains the same reference to the self object' do
|
|
81
|
+
@duplicate.self_ptr.should be @nested_scope.self_ptr
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "ensures changes to a duplicate's locals do not affect the original" do
|
|
85
|
+
new_a = mock
|
|
86
|
+
@duplicate.locals['a'] = new_a
|
|
87
|
+
@nested_scope.lookup('a').should be @a
|
|
88
|
+
@duplicate.lookup('a').should be new_a
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
describe OpenScope do
|
|
94
|
+
it_should_behave_like Scope
|
|
95
|
+
extend ScopeSpecHelpers
|
|
96
|
+
add_scope_instance_variables(OpenScope)
|
|
97
|
+
|
|
98
|
+
describe '#lookup_local' do
|
|
99
|
+
it 'should look in parent scopes when lookup fails' do
|
|
100
|
+
expected = Object.new
|
|
101
|
+
@base_scope.locals['x'] = expected
|
|
102
|
+
@nested_scope.lookup_local('x').should be expected
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it 'should raise if there is no parent' do
|
|
106
|
+
scope = OpenScope.new(nil, nil)
|
|
107
|
+
expect { scope.lookup('foobarmonkey') }.to raise_error(Scope::ScopeLookupFailure)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
describe ClosedScope do
|
|
113
|
+
it_should_behave_like Scope
|
|
114
|
+
extend ScopeSpecHelpers
|
|
115
|
+
add_scope_instance_variables(ClosedScope)
|
|
116
|
+
|
|
117
|
+
describe '#lookup_local' do
|
|
118
|
+
it 'should not look in parent scopes when lookup fails' do
|
|
119
|
+
value = Object.new
|
|
120
|
+
@base_scope.locals['x'] = value
|
|
121
|
+
expect {
|
|
122
|
+
@nested_scope.lookup_local('x')
|
|
123
|
+
}.to raise_error(Scope::ScopeLookupFailure)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
require_relative 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Analysis do
|
|
4
|
+
before do
|
|
5
|
+
@class = Class.new do
|
|
6
|
+
include Analysis
|
|
7
|
+
attr_accessor :body
|
|
8
|
+
def initialize(body)
|
|
9
|
+
self.body = body
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe '#parse' do
|
|
15
|
+
it 'parses its body' do
|
|
16
|
+
@class.new('a').parse.should ==
|
|
17
|
+
[:program, [[:vcall, [:@ident, "a", [1, 0]]]]]
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe '#find_sexps' do
|
|
22
|
+
it 'searches its body' do
|
|
23
|
+
@class.new('a + b').find_sexps(:binary).should_not be_empty
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'returns an empty array if no sexps are found' do
|
|
27
|
+
@class.new('a + b').find_sexps(:rescue).should be_empty
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
require_relative 'spec_helper'
|
|
2
|
+
|
|
3
|
+
describe Sexp do
|
|
4
|
+
describe '#constant_value' do
|
|
5
|
+
it 'defaults to assigning is_constant=false, constant_value=:none' do
|
|
6
|
+
tree = Sexp.new(Ripper.sexp('a'))
|
|
7
|
+
list = tree[1]
|
|
8
|
+
list[0][1].is_constant.should be false
|
|
9
|
+
list[0][1].constant_value.should be :none
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe 'keyword literals' do
|
|
13
|
+
it 'should resolve nil' do
|
|
14
|
+
tree = Sexp.new(Ripper.sexp('a = nil'))
|
|
15
|
+
list = tree[1]
|
|
16
|
+
list[0][2].is_constant.should be true
|
|
17
|
+
list[0][2].constant_value.should == nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it 'should resolve true' do
|
|
21
|
+
tree = Sexp.new(Ripper.sexp('a = true'))
|
|
22
|
+
list = tree[1]
|
|
23
|
+
list[0][2].is_constant.should be true
|
|
24
|
+
list[0][2].constant_value.should == true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it 'should resolve false' do
|
|
28
|
+
tree = Sexp.new(Ripper.sexp('a = false'))
|
|
29
|
+
list = tree[1]
|
|
30
|
+
list[0][2].is_constant.should be true
|
|
31
|
+
list[0][2].constant_value.should == false
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it 'should resolve __LINE__' do
|
|
35
|
+
tree = Sexp.new(Ripper.sexp("a = \n__LINE__"))
|
|
36
|
+
list = tree[1]
|
|
37
|
+
list[0][2].is_constant.should be true
|
|
38
|
+
list[0][2].constant_value.should == 2
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'should resolve __FILE__' do
|
|
42
|
+
tree = Sexp.new(Ripper.sexp("a = \n__FILE__"), 'abc/def.rb', "a = \n__FILE__")
|
|
43
|
+
list = tree[1]
|
|
44
|
+
list[0][2].is_constant.should be true
|
|
45
|
+
list[0][2].constant_value.should == 'abc/def.rb'
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
describe 'character literals' do
|
|
50
|
+
it 'works with single-char literals' do
|
|
51
|
+
tree = Sexp.new(Ripper.sexp('a = ?X'))
|
|
52
|
+
list = tree[1]
|
|
53
|
+
list[0][2].is_constant.should be true
|
|
54
|
+
list[0][2].constant_value.should == 'X'
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it 'works with oddball char literals' do
|
|
58
|
+
tree = Sexp.new(Ripper.sexp('a = ?\M-\C-a'))
|
|
59
|
+
list = tree[1]
|
|
60
|
+
list[0][2].is_constant.should be true
|
|
61
|
+
list[0][2].constant_value.should == "\x81"
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe 'handling string literals' do
|
|
66
|
+
it 'should interpret simple strings' do
|
|
67
|
+
input = 'a = "abc def"'
|
|
68
|
+
tree = annotate_all(input)
|
|
69
|
+
list = tree[1]
|
|
70
|
+
list[0][2].is_constant.should be true
|
|
71
|
+
list[0][2].constant_value.should == "abc def"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it 'should give up with complex interpolation' do
|
|
75
|
+
input = 'a = "abc #{foobar()} def"'
|
|
76
|
+
tree = annotate_all(input)
|
|
77
|
+
list = tree[1]
|
|
78
|
+
list[0][2].is_constant.should be false
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it 'should handle embedded escapes' do
|
|
82
|
+
input = 'a = "abc \n \x12def"'
|
|
83
|
+
tree = annotate_all(input)
|
|
84
|
+
list = tree[1]
|
|
85
|
+
list[0][2].is_constant.should be true
|
|
86
|
+
list[0][2].constant_value.should == "abc \n \x12def"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it 'should not evaluate embedded escapes for single-quoted strings' do
|
|
90
|
+
input = %q{a = 'abc \n \x12def'}
|
|
91
|
+
tree = annotate_all(input)
|
|
92
|
+
list = tree[1]
|
|
93
|
+
list[0][2].is_constant.should be true
|
|
94
|
+
list[0][2].constant_value.should == 'abc \n \x12def'
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
describe 'handling integer literals' do
|
|
99
|
+
it 'discovers the constant value for small decimal literals' do
|
|
100
|
+
tree = Sexp.new(Ripper.sexp('a = 5'))
|
|
101
|
+
list = tree[1]
|
|
102
|
+
list[0][2].is_constant.should be true
|
|
103
|
+
list[0][2].constant_value.should == 5
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it 'discovers the constant value for huge integer literals' do
|
|
107
|
+
tree = Sexp.new(Ripper.sexp('a = 5123907821349078'))
|
|
108
|
+
list = tree[1]
|
|
109
|
+
list[0][2].is_constant.should be true
|
|
110
|
+
list[0][2].constant_value.should == 5123907821349078
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it 'discovers the constant value for hex integer literals' do
|
|
114
|
+
tree = Sexp.new(Ripper.sexp('a = 0xabde3456'))
|
|
115
|
+
list = tree[1]
|
|
116
|
+
list[0][2].is_constant.should be true
|
|
117
|
+
list[0][2].constant_value.should == 0xabde3456
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it 'discovers the constant value for octal integer literals' do
|
|
121
|
+
tree = Sexp.new(Ripper.sexp('a = 012343222245566'))
|
|
122
|
+
list = tree[1]
|
|
123
|
+
list[0][2].is_constant.should be true
|
|
124
|
+
list[0][2].constant_value.should == 012343222245566
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
it 'discovers the constant value for binary integer literals' do
|
|
128
|
+
tree = Sexp.new(Ripper.sexp('a = 0b10100011101010110001'))
|
|
129
|
+
list = tree[1]
|
|
130
|
+
list[0][2].is_constant.should be true
|
|
131
|
+
list[0][2].constant_value.should == 0b10100011101010110001
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
describe 'handling float literals' do
|
|
136
|
+
it 'discovers the constant value for small decimal literals' do
|
|
137
|
+
tree = Sexp.new(Ripper.sexp('a = 5.124897e3'))
|
|
138
|
+
list = tree[1]
|
|
139
|
+
list[0][2].is_constant.should be true
|
|
140
|
+
list[0][2].constant_value.should == 5.124897e3
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
describe 'symbol literals' do
|
|
145
|
+
[:abc_def, :ABC_DEF, :@abc_def, :$abc_def, :@@abc_def, :"hello-world"].each do |sym|
|
|
146
|
+
it "should convert simple symbols of the form #{sym.inspect}" do
|
|
147
|
+
input = "a = #{sym.inspect}"
|
|
148
|
+
tree = annotate_all(input)
|
|
149
|
+
list = tree[1]
|
|
150
|
+
list[0][2].is_constant.should be true
|
|
151
|
+
list[0][2].constant_value.should == sym
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
# [:program,
|
|
156
|
+
# [[:hash,
|
|
157
|
+
# [:assoclist_from_args,
|
|
158
|
+
# [[:assoc_new,
|
|
159
|
+
# [:@label, "abc:", [1, 1]],
|
|
160
|
+
# [:symbol_literal, [:symbol, [:@kw, "def", [1, 7]]]]]]]]]]
|
|
161
|
+
it 'can discover the value of labels in 1.9 hash syntax' do
|
|
162
|
+
input = '{abc: :def}'
|
|
163
|
+
tree = Sexp.new(Ripper.sexp(input))
|
|
164
|
+
label = tree[1][0][1][1][0][1]
|
|
165
|
+
label.is_constant.should be true
|
|
166
|
+
label.constant_value.should == :abc
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
describe 'inclusive range literals' do
|
|
171
|
+
it 'calculates a constant if both ends of the range are constants' do
|
|
172
|
+
tree = Sexp.new(Ripper.sexp('a = 2..0x33'))
|
|
173
|
+
list = tree[1]
|
|
174
|
+
list[0][2].is_constant.should be true
|
|
175
|
+
list[0][2].constant_value.should == (2..51)
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it 'does not create a constant if one of the ends is not a constant' do
|
|
179
|
+
tree = Sexp.new(Ripper.sexp('a = 2..(foobar(2))'))
|
|
180
|
+
list = tree[1]
|
|
181
|
+
list[0][2].is_constant.should be false
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
describe 'exclusive range literals' do
|
|
186
|
+
it 'calculates a constant if both ends of the range are constants' do
|
|
187
|
+
tree = Sexp.new(Ripper.sexp('a = 2...0x33'))
|
|
188
|
+
list = tree[1]
|
|
189
|
+
list[0][2].is_constant.should be true
|
|
190
|
+
list[0][2].constant_value.should == (2...51)
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
it 'does not create a constant if one of the ends is not a constant' do
|
|
194
|
+
tree = Sexp.new(Ripper.sexp('a = 2...(foobar(2))'))
|
|
195
|
+
list = tree[1]
|
|
196
|
+
list[0][2].is_constant.should be false
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
describe 'regex literals' do
|
|
201
|
+
it 'interprets a simple constant regex with standard syntax' do
|
|
202
|
+
input = 'a = /abcdef/'
|
|
203
|
+
tree = annotate_all(input)
|
|
204
|
+
list = tree[1]
|
|
205
|
+
list[0][2].is_constant.should be true
|
|
206
|
+
list[0][2].constant_value.should == /abcdef/
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
it 'does not try to fold complex interpolated regexps' do
|
|
210
|
+
input = 'a = /abc#{abc()}def/'
|
|
211
|
+
tree = annotate_all(input)
|
|
212
|
+
list = tree[1]
|
|
213
|
+
list[0][2].is_constant.should be false
|
|
214
|
+
end
|
|
215
|
+
|
|
216
|
+
it 'interprets a simple regex with nonstandard syntax and options' do
|
|
217
|
+
input = 'a = %r|abcdef|im'
|
|
218
|
+
tree = annotate_all(input)
|
|
219
|
+
list = tree[1]
|
|
220
|
+
list[0][2].is_constant.should be true
|
|
221
|
+
list[0][2].constant_value.should == /abcdef/im
|
|
222
|
+
end
|
|
223
|
+
|
|
224
|
+
it 'interprets a simple regex with extended mode' do
|
|
225
|
+
input = 'a = %r|abcdef|x'
|
|
226
|
+
tree = annotate_all(input)
|
|
227
|
+
list = tree[1]
|
|
228
|
+
list[0][2].is_constant.should be true
|
|
229
|
+
list[0][2].constant_value.should == /abcdef/x
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
describe 'array literals' do
|
|
234
|
+
it 'can evaluate empty hashes' do
|
|
235
|
+
input = 'a = [ ]'
|
|
236
|
+
tree = Sexp.new(Ripper.sexp(input))
|
|
237
|
+
list = tree[1]
|
|
238
|
+
list[0][2].is_constant.should be true
|
|
239
|
+
list[0][2].constant_value.should == []
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it 'should find the constant value if all members are constant' do
|
|
243
|
+
input = 'a = [:a, 3.14, "hello", /abc/x]'
|
|
244
|
+
tree = annotate_all(input)
|
|
245
|
+
list = tree[1]
|
|
246
|
+
list[0][2].is_constant.should be true
|
|
247
|
+
list[0][2].constant_value.should == [:a, 3.14, "hello", /abc/x]
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
it 'should not calculate a constant if a member is not a constant' do
|
|
251
|
+
input = 'a = [:a, :"hi-there", 3.14, foobar()]'
|
|
252
|
+
tree = annotate_all(input)
|
|
253
|
+
list = tree[1]
|
|
254
|
+
list[0][2].is_constant.should be false
|
|
255
|
+
end
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
describe 'hash literals' do
|
|
259
|
+
it 'can evaluate empty hashes' do
|
|
260
|
+
input = 'a = {}'
|
|
261
|
+
tree = Sexp.new(Ripper.sexp(input))
|
|
262
|
+
list = tree[1]
|
|
263
|
+
list[0][2].is_constant.should be true
|
|
264
|
+
list[0][2].constant_value.should == {}
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
it 'can evaluate simple constant hashes' do
|
|
268
|
+
input = 'a = {:a => :b, 3 => 2, "hi" => "world", :a => :c}'
|
|
269
|
+
tree = annotate_all(input)
|
|
270
|
+
list = tree[1]
|
|
271
|
+
list[0][2].is_constant.should be true
|
|
272
|
+
list[0][2].constant_value.should == {:a => :c, 3 => 2, "hi" => "world"}
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
it 'gives up on obviously non-constant hashes' do
|
|
276
|
+
input = 'a = {foobar() => baz()}'
|
|
277
|
+
tree = Sexp.new(Ripper.sexp(input))
|
|
278
|
+
list = tree[1]
|
|
279
|
+
list[0][2].is_constant.should be false
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
it 'can evaluate constant, bare hashes' do
|
|
283
|
+
input = 'a = foo(:a => :b, 3 => 2, "hi" => "world", :a => :c)'
|
|
284
|
+
tree = annotate_all(input)
|
|
285
|
+
list = tree[1]
|
|
286
|
+
list[0][2][2][1][1][0].is_constant.should be true
|
|
287
|
+
list[0][2][2][1][1][0].constant_value.should == {:a => :c, 3 => 2, "hi" => "world"}
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
|
|
291
|
+
describe 'stuff in parentheses' do
|
|
292
|
+
it 'can handle a range in parens' do
|
|
293
|
+
input = 'a = ("a".."z")'
|
|
294
|
+
tree = annotate_all(input)
|
|
295
|
+
list = tree[1]
|
|
296
|
+
list[0][2].is_constant.should be true
|
|
297
|
+
list[0][2].constant_value.should == ("a".."z")
|
|
298
|
+
end
|
|
299
|
+
|
|
300
|
+
it 'can handle compound expressions in parens, taking the value of the last constant' do
|
|
301
|
+
input = 'a = (3; 2; "a".."z")'
|
|
302
|
+
tree = annotate_all(input)
|
|
303
|
+
list = tree[1]
|
|
304
|
+
list[0][2].is_constant.should be true
|
|
305
|
+
list[0][2].constant_value.should == ("a".."z")
|
|
306
|
+
end
|
|
307
|
+
end
|
|
308
|
+
end
|
|
309
|
+
end
|