From aec8a4b0a4eb332140d363d5c81d00eae382ff6a Mon Sep 17 00:00:00 2001 From: nobu Date: Fri, 2 Oct 2009 11:37:44 +0000 Subject: * parse.y (ripper_yylval_id, ripper_get_{id,value}): wrap ID by NODE to track local variable assignment. * parse.y (lvar_defined_gen, assignable_gen): enable local variable check. [ruby-core:24923] * parse.y (validate): use value only. * test/ripper/test_parser_events.rb (test_local_variables): tests based on a patch from Magnus Holm in [ruby-core:25885]. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@25187 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- test/ripper/dummyparser.rb | 35 +++++++++---- test/ripper/test_parser_events.rb | 106 ++++++++++++++++++++++++++++++++------ 2 files changed, 116 insertions(+), 25 deletions(-) (limited to 'test/ripper') diff --git a/test/ripper/dummyparser.rb b/test/ripper/dummyparser.rb index 483ac0d013..a76632e466 100644 --- a/test/ripper/dummyparser.rb +++ b/test/ripper/dummyparser.rb @@ -13,7 +13,15 @@ class Node attr_reader :children def to_s - "#{@name}(#{@children.map {|n| n.to_s }.join(',')})" + "#{@name}(#{Node.trim_nil(@children).map {|n| n.to_s }.join(',')})" + end + + def self.trim_nil(list) + if !list.empty? and list.last.nil? + list = list[0...-1] + list.pop while !list.empty? and list.last.nil? + end + list end end @@ -34,14 +42,23 @@ class NodeList end def to_s - '[' + @list.join(',') + ']' + "[#{@list.join(',')}]" end end class DummyParser < Ripper + def hook(name) + class << self; self; end.class_eval do + define_method(name) do |*a, &b| + result = super(*a, &b) + yield + result + end + end + self + end def on_program(stmts) - $thru_program = true stmts end @@ -170,8 +187,8 @@ class DummyParser < Ripper Node.new('binary', a, b, c) end - def on_block_var(a) - Node.new('block_var', a) + def on_block_var(a, b) + Node.new('block_var', a, b) end def on_bodystmt(a, b, c, d) @@ -346,8 +363,8 @@ class DummyParser < Ripper Node.new('param_error', a) end - def on_params(a, b, c, d) - Node.new('params', a, b, c, d) + def on_params(a, b, c, d, e) + Node.new('params', a, b, c, d, e) end def on_paren(a) @@ -370,8 +387,8 @@ class DummyParser < Ripper Node.new('redo') end - def on_regexp_literal(a) - Node.new('regexp_literal', a) + def on_regexp_literal(a, b) + Node.new('regexp_literal', a, b) end def on_rescue(a, b, c, d) diff --git a/test/ripper/test_parser_events.rb b/test/ripper/test_parser_events.rb index fa640a37ec..f8db938d38 100644 --- a/test/ripper/test_parser_events.rb +++ b/test/ripper/test_parser_events.rb @@ -1,6 +1,6 @@ begin -require 'dummyparser' +require_relative 'dummyparser' require 'test/unit' class TestRipper_ParserEvents < Test::Unit::TestCase @@ -16,15 +16,16 @@ class TestRipper_ParserEvents < Test::Unit::TestCase end =end - def parse(str) - DummyParser.new(str).parse.to_s + def parse(str, nm = nil, &bl) + dp = DummyParser.new(str) + dp.hook(nm, &bl) if nm + dp.parse.to_s end - $thru_program = false - def test_program - assert_equal '[void()]', parse('') - assert_equal true, $thru_program + thru_program = false + assert_equal '[void()]', parse('', :on_program) {thru_program = true} + assert_equal true, thru_program end def test_stmts_new @@ -104,11 +105,11 @@ class TestRipper_ParserEvents < Test::Unit::TestCase assert_equal '[assign(aref_field(ref(a),[1]),2)]', parse('a[1]=2') end -=begin def test_arg_ambiguous - assert_equal true, $thru__arg_ambiguous + thru_arg_ambiguous = false + parse('m //', :on_arg_ambiguous) {thru_arg_ambiguous = true} + assert_equal true, thru_arg_ambiguous end -=end def test_array # array literal assert_equal '[array([1,2,3])]', parse('[1,2,3]') @@ -118,27 +119,89 @@ class TestRipper_ParserEvents < Test::Unit::TestCase assert_equal '[assign(var_field(v),1)]', parse('v=1') end -=begin def test_assign_error - assert_equal true, $thru__assign_error + thru_assign_error = false + parse('$` = 1', :on_assign_error) {thru_assign_error = true} + assert_equal true, thru_assign_error + thru_assign_error = false + parse('$`, _ = 1', :on_assign_error) {thru_assign_error = true} + assert_equal true, thru_assign_error + + thru_assign_error = false + parse('self::X = 1', :on_assign_error) {thru_assign_error = true} + assert_equal false, thru_assign_error + parse('def m\n self::X = 1\nend', :on_assign_error) {thru_assign_error = true} + assert_equal true, thru_assign_error + + thru_assign_error = false + parse('X = 1', :on_assign_error) {thru_assign_error = true} + assert_equal false, thru_assign_error + parse('def m\n X = 1\nend', :on_assign_error) {thru_assign_error = true} + assert_equal true, thru_assign_error + + thru_assign_error = false + parse('::X = 1', :on_assign_error) {thru_assign_error = true} + assert_equal false, thru_assign_error + parse('def m\n ::X = 1\nend', :on_assign_error) {thru_assign_error = true} + assert_equal true, thru_assign_error end def test_begin - assert_equal true, $thru__begin + thru_begin = false + parse('begin end', :on_begin) {thru_begin = true} + assert_equal true, thru_begin end def test_binary - assert_equal true, $thru__binary + thru_binary = nil + %w"and or + - * / % ** | ^ & <=> > >= < <= == === != =~ !~ << >> && ||".each do |op| + thru_binary = false + parse("a #{op} b", :on_binary) {thru_binary = true} + assert_equal true, thru_binary + end end def test_block_var - assert_equal true, $thru__block_var + thru_block_var = false + parse("proc{||}", :on_block_var) {thru_block_var = true} + assert_equal true, thru_block_var + thru_block_var = false + parse("proc{| |}", :on_block_var) {thru_block_var = true} + assert_equal true, thru_block_var + thru_block_var = false + parse("proc{|x|}", :on_block_var) {thru_block_var = true} + assert_equal true, thru_block_var + thru_block_var = false + parse("proc{|;y|}", :on_block_var) {thru_block_var = true} + assert_equal true, thru_block_var + thru_block_var = false + parse("proc{|x;y|}", :on_block_var) {thru_block_var = true} + assert_equal true, thru_block_var + + thru_block_var = false + parse("proc do || end", :on_block_var) {thru_block_var = true} + assert_equal true, thru_block_var + thru_block_var = false + parse("proc do | | end", :on_block_var) {thru_block_var = true} + assert_equal true, thru_block_var + thru_block_var = false + parse("proc do |x| end", :on_block_var) {thru_block_var = true} + assert_equal true, thru_block_var + thru_block_var = false + parse("proc do |;y| end", :on_block_var) {thru_block_var = true} + assert_equal true, thru_block_var + thru_block_var = false + parse("proc do |x;y| end", :on_block_var) {thru_block_var = true} + assert_equal true, thru_block_var end def test_bodystmt - assert_equal true, $thru__bodystmt + thru_bodystmt = false + parse("class X\nend", :on_bodystmt) {thru_bodystmt = true} + assert_equal true, thru_bodystmt end +=begin def test_brace_block assert_equal true, $thru__brace_block end @@ -492,6 +555,17 @@ class TestRipper_ParserEvents < Test::Unit::TestCase end =end + def test_local_variables + cmd = 'command(w,[regexp_literal(xstring_add(xstring_new(),25 # ),/)])' + div = 'binary(ref(w),/,25)' + var = 'params(["w"])' + bug1939 = '[ruby-core:24923]' + + assert_equal("[#{cmd}]", parse('w /25 # /'), bug1939) + assert_equal("[assign(var_field(w),1),#{div}]", parse("w = 1; w /25 # /"), bug1939) + assert_equal("[fcall(p,[],&brace_block(block_var(#{var}),[#{div}]))]", parse("p{|w|w /25 # /\n}"), bug1939) + assert_equal("[def(p,paren(#{var}),bodystmt([#{div}]))]", parse("def p(w)\nw /25 # /\nend"), bug1939) + end end rescue LoadError -- cgit v1.2.3