Skip to content

Commit 9846ab4

Browse files
committed
Add more parent scope and method definition receiver tests
1 parent 92da953 commit 9846ab4

3 files changed

Lines changed: 610 additions & 4 deletions

File tree

test/requests/definition_expectations_test.rb

Lines changed: 288 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1419,6 +1419,294 @@ def bar
14191419
end
14201420
end
14211421

1422+
def test_definition_for_implicit_self_method_call_inside_singleton_method
1423+
source = <<~RUBY
1424+
# typed: false
1425+
1426+
class Foo
1427+
def self.bar; end
1428+
1429+
def self.baz
1430+
bar
1431+
end
1432+
end
1433+
RUBY
1434+
1435+
with_server(source) do |server, uri|
1436+
server.process_message(
1437+
id: 1,
1438+
method: "textDocument/definition",
1439+
params: { textDocument: { uri: uri }, position: { character: 4, line: 6 } },
1440+
)
1441+
1442+
response = server.pop_response.response
1443+
assert_equal(1, response.length)
1444+
assert_equal(3, response[0].target_range.start.line)
1445+
end
1446+
end
1447+
1448+
def test_definition_for_method_call_inside_method_with_constant_receiver
1449+
source = <<~RUBY
1450+
# typed: false
1451+
1452+
class Bar
1453+
def self.helper; end
1454+
end
1455+
1456+
class Foo
1457+
def Bar.check
1458+
helper
1459+
end
1460+
end
1461+
RUBY
1462+
1463+
with_server(source) do |server, uri|
1464+
server.process_message(
1465+
id: 1,
1466+
method: "textDocument/definition",
1467+
params: { textDocument: { uri: uri }, position: { character: 4, line: 8 } },
1468+
)
1469+
1470+
response = server.pop_response.response
1471+
assert_equal(1, response.length)
1472+
assert_equal(3, response[0].target_range.start.line)
1473+
end
1474+
end
1475+
1476+
def test_definition_for_super_inside_singleton_method
1477+
source = <<~RUBY
1478+
class Parent
1479+
def self.foo; end
1480+
end
1481+
1482+
class Child < Parent
1483+
def self.foo
1484+
super
1485+
end
1486+
end
1487+
RUBY
1488+
1489+
with_server(source) do |server, uri|
1490+
server.process_message(
1491+
id: 1,
1492+
method: "textDocument/definition",
1493+
params: { textDocument: { uri: uri }, position: { character: 4, line: 6 } },
1494+
)
1495+
1496+
response = server.pop_response.response
1497+
assert_equal(1, response.length)
1498+
assert_equal(1, response[0].target_range.start.line)
1499+
end
1500+
end
1501+
1502+
def test_definition_for_implicit_self_method_call_inside_singleton_method_with_compact_namespace
1503+
source = <<~RUBY
1504+
# typed: false
1505+
1506+
module Foo; end
1507+
1508+
class Foo::Bar
1509+
def self.helper; end
1510+
1511+
def self.check
1512+
helper
1513+
end
1514+
end
1515+
RUBY
1516+
1517+
with_server(source) do |server, uri|
1518+
server.process_message(
1519+
id: 1,
1520+
method: "textDocument/definition",
1521+
params: { textDocument: { uri: uri }, position: { character: 4, line: 8 } },
1522+
)
1523+
1524+
response = server.pop_response.response
1525+
assert_equal(1, response.length)
1526+
assert_equal(5, response[0].target_range.start.line)
1527+
end
1528+
end
1529+
1530+
def test_super_definition_for_method_definition_with_receiver
1531+
source = <<~RUBY
1532+
# typed: false
1533+
1534+
class Foo
1535+
class << self
1536+
# You found me!
1537+
def bar; end
1538+
end
1539+
end
1540+
1541+
class Bar < Foo
1542+
class << self
1543+
end
1544+
end
1545+
1546+
class Qux
1547+
def Bar.bar
1548+
super
1549+
end
1550+
end
1551+
RUBY
1552+
1553+
with_server(source) do |server, uri|
1554+
server.process_message(
1555+
id: 1,
1556+
method: "textDocument/definition",
1557+
params: { textDocument: { uri: uri }, position: { character: 4, line: 16 } },
1558+
)
1559+
1560+
response = server.pop_response.response
1561+
assert_equal(1, response.length)
1562+
assert_equal(5, response[0].target_range.start.line)
1563+
end
1564+
end
1565+
1566+
def test_definition_for_method_call_inside_class_singleton_block_method
1567+
source = <<~RUBY
1568+
# typed: false
1569+
1570+
class Foo
1571+
def self.bar; end
1572+
1573+
class << self
1574+
def baz
1575+
bar
1576+
end
1577+
end
1578+
end
1579+
RUBY
1580+
1581+
with_server(source) do |server, uri|
1582+
server.process_message(
1583+
id: 1,
1584+
method: "textDocument/definition",
1585+
params: { textDocument: { uri: uri }, position: { character: 6, line: 7 } },
1586+
)
1587+
1588+
response = server.pop_response.response
1589+
assert_equal(1, response.length)
1590+
assert_equal(3, response[0].target_range.start.line)
1591+
end
1592+
end
1593+
1594+
def test_definition_for_instance_variable_in_method_with_constant_receiver
1595+
source = <<~RUBY
1596+
class Bar
1597+
class << self; end
1598+
1599+
@config = "default"
1600+
end
1601+
1602+
class Foo
1603+
def Bar.configure
1604+
@config
1605+
end
1606+
end
1607+
RUBY
1608+
1609+
with_server(source) do |server, uri|
1610+
server.process_message(
1611+
id: 1,
1612+
method: "textDocument/definition",
1613+
params: { textDocument: { uri: uri }, position: { character: 4, line: 8 } },
1614+
)
1615+
1616+
# @config should resolve through Bar's singleton class, not Foo
1617+
response = server.pop_response.response
1618+
assert_equal(1, response.length)
1619+
assert_equal(3, response[0].range.start.line)
1620+
end
1621+
end
1622+
1623+
def test_definition_for_class_variable_in_method_with_constant_receiver
1624+
source = <<~RUBY
1625+
class Bar
1626+
@@shared = 1
1627+
end
1628+
1629+
class Foo
1630+
def Bar.check
1631+
@@shared
1632+
end
1633+
end
1634+
RUBY
1635+
1636+
with_server(source) do |server, uri|
1637+
server.process_message(
1638+
id: 1,
1639+
method: "textDocument/definition",
1640+
params: { textDocument: { uri: uri }, position: { character: 4, line: 6 } },
1641+
)
1642+
1643+
# @@shared follows lexical scope (Foo), not the receiver (Bar).
1644+
# Since @@shared is defined in Bar but not in Foo, definition should be empty
1645+
assert_empty(server.pop_response.response)
1646+
end
1647+
end
1648+
1649+
def test_definition_for_constant_in_method_with_constant_receiver
1650+
source = <<~RUBY
1651+
# typed: ignore
1652+
class Bar
1653+
OTHER = "other"
1654+
end
1655+
1656+
class Foo
1657+
MY_CONST = "hello"
1658+
1659+
def Bar.check
1660+
MY_CONST
1661+
end
1662+
end
1663+
RUBY
1664+
1665+
with_server(source) do |server, uri|
1666+
server.process_message(
1667+
id: 1,
1668+
method: "textDocument/definition",
1669+
params: { textDocument: { uri: uri }, position: { character: 4, line: 9 } },
1670+
)
1671+
1672+
# MY_CONST resolves through Foo's lexical scope, not Bar
1673+
response = server.pop_response.response
1674+
assert_equal(1, response.length)
1675+
assert_equal(6, response[0].target_range.start.line)
1676+
end
1677+
end
1678+
1679+
def test_definition_for_instance_variable_in_hoisted_parent_scope
1680+
source = <<~RUBY
1681+
module Bar; end
1682+
1683+
module Foo
1684+
class Bar::Baz
1685+
class << self; end
1686+
1687+
@var = 1
1688+
1689+
def self.get_var
1690+
@var
1691+
end
1692+
end
1693+
end
1694+
RUBY
1695+
1696+
with_server(source) do |server, uri|
1697+
server.process_message(
1698+
id: 1,
1699+
method: "textDocument/definition",
1700+
params: { textDocument: { uri: uri }, position: { character: 6, line: 9 } },
1701+
)
1702+
1703+
# @var should resolve through Bar::Baz's singleton class, not Foo::Bar::Baz
1704+
response = server.pop_response.response
1705+
assert_equal(1, response.length)
1706+
assert_equal(6, response[0].range.start.line)
1707+
end
1708+
end
1709+
14221710
private
14231711

14241712
def create_definition_addon

0 commit comments

Comments
 (0)