Skip to content

Commit 3383fa7

Browse files
backport: Fix a crash in the minitest rewriter (#235)
Original patch: sorbet/sorbet#8446 --- Co-authored-by: Trevor Elliott <[email protected]>
1 parent 5020782 commit 3383fa7

File tree

9 files changed

+231
-61
lines changed

9 files changed

+231
-61
lines changed

ast/Trees.cc

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1343,11 +1343,20 @@ core::NameRef Literal::asString() const {
13431343

13441344
core::NameRef Literal::asSymbol() const {
13451345
ENFORCE(isSymbol());
1346+
return asName();
1347+
}
1348+
1349+
core::NameRef Literal::asName() const {
1350+
ENFORCE(isName());
13461351
auto t = core::cast_type_nonnull<core::NamedLiteralType>(value);
13471352
core::NameRef res = t.asName();
13481353
return res;
13491354
}
13501355

1356+
bool Literal::isName() const {
1357+
return isString() || isSymbol();
1358+
}
1359+
13511360
bool Literal::isSymbol() const {
13521361
return core::isa_type<core::NamedLiteralType>(value) &&
13531362
core::cast_type_nonnull<core::NamedLiteralType>(value).literalKind ==

ast/Trees.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1040,6 +1040,8 @@ EXPRESSION(Literal) {
10401040

10411041
std::string toStringWithTabs(const core::GlobalState &gs, int tabs = 0) const;
10421042
std::string showRaw(const core::GlobalState &gs, int tabs = 0) const;
1043+
bool isName() const;
1044+
core::NameRef asName() const;
10431045
std::string nodeName() const;
10441046
bool isString() const;
10451047
bool isSymbol() const;

rewriter/Minitest.cc

Lines changed: 101 additions & 61 deletions
Large diffs are not rendered by default.
File renamed without changes.

test/scip/testdata/minitest_2.rb

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
# typed: true
2+
3+
class Test
4+
extend T::Sig
5+
def self.test_each(arg, &blk); end
6+
def self.it(name, &blk); end
7+
def self.describe(name, &blk); end
8+
end
9+
10+
class Foo < Test
11+
# The unclosed `do` block here should be a recoverable parse error.
12+
test_each([[1, 2], [3,4]]) do |(a,b)|
13+
# ^^ error: Hint: this "do" token
14+
15+
it "it block 1" do
16+
end
17+
18+
it "it block 2" do
19+
end
20+
end # error: unexpected token "end of file"
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# typed: true
2+
3+
class Test
4+
# ^^^^ definition [..] Test#
5+
extend T::Sig
6+
# ^^^^^^ reference [..] Kernel#extend().
7+
def self.test_each(arg, &blk); end
8+
# ^^^^^^^^^ definition [..] `<Class:Test>`#test_each().
9+
def self.it(name, &blk); end
10+
# ^^ definition [..] `<Class:Test>`#it().
11+
def self.describe(name, &blk); end
12+
# ^^^^^^^^ definition [..] `<Class:Test>`#describe().
13+
end
14+
15+
class Foo < Test
16+
# ^^^ definition [..] Foo#
17+
# ^^^^ reference [..] Test#
18+
# The unclosed `do` block here should be a recoverable parse error.
19+
test_each([[1, 2], [3,4]]) do |(a,b)|
20+
# ^^^^^^^^^ reference [..] `<Class:Test>`#test_each().
21+
# ^^ error: Hint: this "do" token
22+
23+
it "it block 1" do
24+
# ^^^^^^^^^^^^ definition [..] Foo#`<it 'it block 1'>`().
25+
end
26+
27+
it "it block 2" do
28+
# ^^^^^^^^^^^^ definition [..] Foo#`<it 'it block 2'>`().
29+
end
30+
end # error: unexpected token "end of file"

test/scip/testdata/minitest_3.rb

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# typed: true
2+
extend T::Sig
3+
4+
class Test
5+
extend T::Sig
6+
7+
def self.test_each(iter, &blk); end
8+
def self.it(name, &blk); end
9+
def self.describe(name, &blk); end
10+
11+
test_each([[1,2], [3,4]]) do |(a,b)|
12+
13+
describe "d" do
14+
it "b" do
15+
T.reveal_type(a) # error: Revealed type: `Integer`
16+
end
17+
end
18+
19+
it "a" do
20+
T.reveal_type(a) # error: Revealed type: `Integer`
21+
end
22+
23+
end
24+
end
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
# typed: true
2+
extend T::Sig
3+
#^^^^^^ reference [..] Kernel#extend().
4+
# ^ reference [..] T#
5+
# ^^^ reference [..] T#Sig#
6+
7+
class Test
8+
# ^^^^ definition [..] Test#
9+
extend T::Sig
10+
# ^^^^^^ reference [..] Kernel#extend().
11+
12+
def self.test_each(iter, &blk); end
13+
# ^^^^^^^^^ definition [..] `<Class:Test>`#test_each().
14+
def self.it(name, &blk); end
15+
# ^^ definition [..] `<Class:Test>`#it().
16+
def self.describe(name, &blk); end
17+
# ^^^^^^^^ definition [..] `<Class:Test>`#describe().
18+
19+
test_each([[1,2], [3,4]]) do |(a,b)|
20+
# ^^^^^^^^^ reference [..] `<Class:Test>`#test_each().
21+
# ^ definition local 1~#2288740619
22+
# ^ definition local 1~#416088458
23+
# ^ definition local 2~#2288740619
24+
# ^ definition local 2~#416088458
25+
26+
describe "d" do
27+
it "b" do
28+
# ^^^ definition [..] Test#`<it 'b'>`().
29+
T.reveal_type(a) # error: Revealed type: `Integer`
30+
# ^ reference [..] T#
31+
# ^^^^^^^^^^^ reference [..] `<Class:T>`#reveal_type().
32+
# ^ reference local 1~#416088458
33+
end
34+
end
35+
36+
it "a" do
37+
# ^^^ definition [..] Test#`<it 'a'>`().
38+
T.reveal_type(a) # error: Revealed type: `Integer`
39+
# ^ reference [..] T#
40+
# ^^^^^^^^^^^ reference [..] `<Class:T>`#reveal_type().
41+
# ^ reference local 1~#2288740619
42+
end
43+
44+
end
45+
end

0 commit comments

Comments
 (0)