Skip to content

Commit

Permalink
+ ruby34.y: reject return in singleton class (#1048)
Browse files Browse the repository at this point in the history
This tracks upstream commit ruby/ruby@e642ddf
  • Loading branch information
Earlopain authored Dec 17, 2024
1 parent 510eba0 commit 91a0a6a
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 5 deletions.
2 changes: 2 additions & 0 deletions lib/parser/context.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class Context
in_class
in_block
in_lambda
cant_return
]

def initialize
Expand All @@ -38,6 +39,7 @@ def reset
@in_class = false
@in_block = false
@in_lambda = false
@cant_return = false
end

attr_accessor(*FLAGS)
Expand Down
9 changes: 8 additions & 1 deletion lib/parser/ruby34.y
Original file line number Diff line number Diff line change
Expand Up @@ -366,6 +366,7 @@ rule

result = [ val[0], @context.dup ]
@context.in_def = true
@context.cant_return = false
}

defn_head: k_def def_name
Expand Down Expand Up @@ -1319,6 +1320,7 @@ rule
| k_class cpath superclass
{
@context.in_class = true
@context.cant_return = true
local_push
}
bodystmt kEND
Expand All @@ -1334,11 +1336,13 @@ rule
local_pop
@context.in_class = ctx.in_class
@context.cant_return = ctx.cant_return
}
| k_class tLSHFT expr_value term
{
@context.in_def = false
@context.in_class = false
@context.cant_return = true
local_push
}
bodystmt kEND
Expand All @@ -1350,10 +1354,12 @@ rule
local_pop
@context.in_def = ctx.in_def
@context.in_class = ctx.in_class
@context.cant_return = ctx.cant_return
}
| k_module cpath
{
@context.in_class = true
@context.cant_return = true
local_push
}
bodystmt kEND
Expand All @@ -1367,6 +1373,7 @@ rule
local_pop
@context.in_class = ctx.in_class
@context.cant_return = ctx.cant_return
}
| defn_head f_arglist bodystmt kEND
{
Expand Down Expand Up @@ -1425,7 +1432,7 @@ rule
k_return: kRETURN
{
if @context.in_class && !@context.in_def && !(context.in_block || context.in_lambda)
if @context.cant_return && !(context.in_block || context.in_lambda)
diagnostic :error, :invalid_return, nil, val[0]
end
}
Expand Down
42 changes: 38 additions & 4 deletions test/test_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6805,15 +6805,29 @@ def test_context_class
%q{class A; get_context; end},
%q{class A < B; get_context; end}
].each do |code|
assert_context([:in_class], code, ALL_VERSIONS)
assert_context([:in_class], code, ALL_VERSIONS - SINCE_3_4)
assert_context([:in_class, :cant_return], code, SINCE_3_4)
end
end

def test_context_module
assert_context(
[:in_class],
%q{module M; get_context; end},
ALL_VERSIONS)
ALL_VERSIONS - SINCE_3_4)
assert_context(
[:in_class, :cant_return],
%q{module M; get_context; end},
SINCE_3_4)
end

def test_context_sclass
[
%q{class << foo; get_context; end},
%q{class A; class << self; get_context; end; end}
].each do |code|
assert_context([:cant_return], code, SINCE_3_4)
end
end

def test_context_def
Expand Down Expand Up @@ -6900,15 +6914,21 @@ def test_return_in_class
SINCE_2_5)

[
%q{class << foo; return; end},
%q{def m; return; end},
%q{tap { return }},
%q{class A; class << self; return; end; end},
%q{class A; class << self; def m; return; end; end; end},
%q{class A; def m; return; end; end},
].each do |code|
refute_diagnoses(code, ALL_VERSIONS)
end

[
%q{class << foo; return; end},
%q{class A; class << self; return; end; end},
].each do |code|
refute_diagnoses(code, ALL_VERSIONS - SINCE_3_4)
end

[
%q{-> do return end},
%q{class A; -> do return end; end},
Expand All @@ -6917,6 +6937,20 @@ def test_return_in_class
end
end

def test_return_in_sclass_since_34
assert_diagnoses(
[:error, :invalid_return, {}],
%q{class << foo; return; end},
%q{ ^^^^^^ location},
SINCE_3_4)

assert_diagnoses(
[:error, :invalid_return, {}],
%q{class A; class << self; return; end; end},
%q{ ^^^^^^ location},
SINCE_3_4)
end

def test_method_definition_in_while_cond
assert_parses(
s(:while,
Expand Down

0 comments on commit 91a0a6a

Please sign in to comment.