Skip to content

Commit a34c937

Browse files
committed
Further improve completion and go to definition in comments
1 parent fd70d83 commit a34c937

File tree

3 files changed

+319
-14
lines changed

3 files changed

+319
-14
lines changed

crates/emmylua_ls/src/handlers/completion/providers/desc_provider.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ pub fn add_completions(builder: &mut CompletionBuilder) -> Option<()> {
5555
fn add_global_completions(builder: &mut CompletionBuilder) -> Option<()> {
5656
let mut seen_types = HashSet::new();
5757

58-
// 1. Children in scope.
58+
// Children in scope.
5959
if let Some(scope) = find_comment_scope(
6060
builder.semantic_model.get_db(),
6161
builder.semantic_model.get_file_id(),
@@ -75,13 +75,29 @@ fn add_global_completions(builder: &mut CompletionBuilder) -> Option<()> {
7575
}
7676
}
7777

78-
// 2. Types in namespaces.
78+
// Types in namespaces.
7979
complete_types_by_prefix(builder, "", Some(&seen_types));
8080

81-
// 3. Globals.
81+
// Types in current module.
82+
if let Some(module) = builder.semantic_model.get_module() {
83+
if let Some(member_info_map) = builder
84+
.semantic_model
85+
.get_member_info_map(module.export_type.as_ref().unwrap_or(&LuaType::Nil))
86+
{
87+
seen_types.extend(member_info_map.iter().flat_map(|(_, members)| {
88+
members.iter().filter_map(|member| match &member.typ {
89+
LuaType::Def(type_id) => Some(type_id.clone()),
90+
_ => None,
91+
})
92+
}));
93+
add_completions_for_members(builder, &member_info_map, CompletionTriggerStatus::Dot);
94+
}
95+
}
96+
97+
// Globals.
8298
add_global_env(builder, &mut HashSet::new(), "");
8399

84-
// 4. Modules.
100+
// Modules.
85101
add_modules(builder, "", None);
86102

87103
Some(())

crates/emmylua_ls/src/handlers/test/completion_test.rs

Lines changed: 269 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1302,7 +1302,13 @@ mod tests {
13021302
);
13031303

13041304
ws.check_completion(
1305-
r"--- :lua:obj:`<??>`",
1305+
r#"
1306+
--- :lua:obj:`<??>`
1307+
1308+
return {
1309+
foo = 0
1310+
}
1311+
"#,
13061312
vec![
13071313
VirtualCompletionItem {
13081314
label: "mod_with_class_and_def".to_string(),
@@ -1334,6 +1340,11 @@ mod tests {
13341340
kind: CompletionItemKind::FILE,
13351341
label_detail: None,
13361342
},
1343+
VirtualCompletionItem {
1344+
label: "foo".to_string(),
1345+
kind: CompletionItemKind::CONSTANT,
1346+
label_detail: None,
1347+
},
13371348
VirtualCompletionItem {
13381349
label: "mod_with_class".to_string(),
13391350
kind: CompletionItemKind::FILE,
@@ -1458,6 +1469,263 @@ mod tests {
14581469
);
14591470
}
14601471

1472+
#[test]
1473+
fn test_doc_completion_in_members() {
1474+
let make_ws = || {
1475+
let mut ws = ProviderVirtualWorkspace::new();
1476+
1477+
let mut emmyrc = Emmyrc::default();
1478+
emmyrc.doc.syntax = DocSyntax::Rst;
1479+
ws.analysis.update_config(emmyrc.into());
1480+
ws
1481+
};
1482+
1483+
let mut ws = make_ws();
1484+
ws.check_completion(
1485+
r#"
1486+
--- @class Foo
1487+
--- @field x integer
1488+
local Foo = {}
1489+
1490+
--- :lua:obj:`<??>`
1491+
Foo.y = 0
1492+
"#,
1493+
vec![
1494+
VirtualCompletionItem {
1495+
label: "Foo".to_string(),
1496+
kind: CompletionItemKind::CLASS,
1497+
label_detail: None,
1498+
},
1499+
VirtualCompletionItem {
1500+
label: "virtual_0".to_string(),
1501+
kind: CompletionItemKind::FILE,
1502+
label_detail: None,
1503+
},
1504+
VirtualCompletionItem {
1505+
label: "x".to_string(),
1506+
kind: CompletionItemKind::VARIABLE,
1507+
label_detail: None,
1508+
},
1509+
VirtualCompletionItem {
1510+
label: "y".to_string(),
1511+
kind: CompletionItemKind::CONSTANT,
1512+
label_detail: None,
1513+
},
1514+
],
1515+
);
1516+
1517+
let mut ws = make_ws();
1518+
ws.check_completion(
1519+
r#"
1520+
--- @class Foo
1521+
--- @field x integer
1522+
local Foo = {}
1523+
1524+
--- :lua:obj:`<??>`
1525+
Foo.y = function() end
1526+
"#,
1527+
vec![
1528+
VirtualCompletionItem {
1529+
label: "Foo".to_string(),
1530+
kind: CompletionItemKind::CLASS,
1531+
label_detail: None,
1532+
},
1533+
VirtualCompletionItem {
1534+
label: "virtual_0".to_string(),
1535+
kind: CompletionItemKind::FILE,
1536+
label_detail: None,
1537+
},
1538+
VirtualCompletionItem {
1539+
label: "x".to_string(),
1540+
kind: CompletionItemKind::VARIABLE,
1541+
label_detail: None,
1542+
},
1543+
VirtualCompletionItem {
1544+
label: "y".to_string(),
1545+
kind: CompletionItemKind::FUNCTION,
1546+
label_detail: Some("()".to_string()),
1547+
},
1548+
],
1549+
);
1550+
1551+
let mut ws = make_ws();
1552+
ws.check_completion(
1553+
r#"
1554+
--- @class Foo
1555+
--- @field x integer
1556+
local Foo = {}
1557+
1558+
--- :lua:obj:`<??>`
1559+
function Foo.y() end
1560+
"#,
1561+
vec![
1562+
VirtualCompletionItem {
1563+
label: "Foo".to_string(),
1564+
kind: CompletionItemKind::CLASS,
1565+
label_detail: None,
1566+
},
1567+
VirtualCompletionItem {
1568+
label: "virtual_0".to_string(),
1569+
kind: CompletionItemKind::FILE,
1570+
label_detail: None,
1571+
},
1572+
VirtualCompletionItem {
1573+
label: "x".to_string(),
1574+
kind: CompletionItemKind::VARIABLE,
1575+
label_detail: None,
1576+
},
1577+
VirtualCompletionItem {
1578+
label: "y".to_string(),
1579+
kind: CompletionItemKind::FUNCTION,
1580+
label_detail: Some("()".to_string()),
1581+
},
1582+
],
1583+
);
1584+
1585+
let mut ws = make_ws();
1586+
ws.check_completion(
1587+
r#"
1588+
--- @class Foo
1589+
--- @field x integer
1590+
local Foo = {}
1591+
1592+
--- :lua:obj:`<??>`
1593+
function Foo:y() end
1594+
"#,
1595+
vec![
1596+
VirtualCompletionItem {
1597+
label: "Foo".to_string(),
1598+
kind: CompletionItemKind::CLASS,
1599+
label_detail: None,
1600+
},
1601+
VirtualCompletionItem {
1602+
label: "virtual_0".to_string(),
1603+
kind: CompletionItemKind::FILE,
1604+
label_detail: None,
1605+
},
1606+
VirtualCompletionItem {
1607+
label: "x".to_string(),
1608+
kind: CompletionItemKind::VARIABLE,
1609+
label_detail: None,
1610+
},
1611+
VirtualCompletionItem {
1612+
label: "y".to_string(),
1613+
kind: CompletionItemKind::FUNCTION,
1614+
label_detail: Some("(self)".to_string()),
1615+
},
1616+
],
1617+
);
1618+
1619+
let mut ws = make_ws();
1620+
ws.check_completion(
1621+
r#"
1622+
--- @class Foo
1623+
--- @field x integer
1624+
local Foo = {
1625+
--- :lua:obj:`<??>`
1626+
y = 0
1627+
}
1628+
"#,
1629+
vec![
1630+
VirtualCompletionItem {
1631+
label: "Foo".to_string(),
1632+
kind: CompletionItemKind::CLASS,
1633+
label_detail: None,
1634+
},
1635+
VirtualCompletionItem {
1636+
label: "virtual_0".to_string(),
1637+
kind: CompletionItemKind::FILE,
1638+
label_detail: None,
1639+
},
1640+
VirtualCompletionItem {
1641+
label: "x".to_string(),
1642+
kind: CompletionItemKind::VARIABLE,
1643+
label_detail: None,
1644+
},
1645+
VirtualCompletionItem {
1646+
label: "y".to_string(),
1647+
kind: CompletionItemKind::CONSTANT,
1648+
label_detail: None,
1649+
},
1650+
],
1651+
);
1652+
1653+
let mut ws = make_ws();
1654+
ws.check_completion(
1655+
r#"
1656+
--- @class Foo
1657+
--- @field x integer
1658+
local Foo = {
1659+
--- :lua:obj:`<??>`
1660+
y = function() end
1661+
}
1662+
"#,
1663+
vec![
1664+
VirtualCompletionItem {
1665+
label: "Foo".to_string(),
1666+
kind: CompletionItemKind::CLASS,
1667+
label_detail: None,
1668+
},
1669+
VirtualCompletionItem {
1670+
label: "virtual_0".to_string(),
1671+
kind: CompletionItemKind::FILE,
1672+
label_detail: None,
1673+
},
1674+
VirtualCompletionItem {
1675+
label: "x".to_string(),
1676+
kind: CompletionItemKind::VARIABLE,
1677+
label_detail: None,
1678+
},
1679+
VirtualCompletionItem {
1680+
label: "y".to_string(),
1681+
kind: CompletionItemKind::FUNCTION,
1682+
label_detail: Some("()".to_string()),
1683+
},
1684+
],
1685+
);
1686+
1687+
let mut ws = make_ws();
1688+
ws.check_completion(
1689+
r#"
1690+
--- @class Foo
1691+
--- @field x integer
1692+
local Foo = {}
1693+
1694+
function Foo:init()
1695+
--- :lua:obj:`<??>`
1696+
self.y = 0
1697+
end
1698+
"#,
1699+
vec![
1700+
VirtualCompletionItem {
1701+
label: "Foo".to_string(),
1702+
kind: CompletionItemKind::CLASS,
1703+
label_detail: None,
1704+
},
1705+
VirtualCompletionItem {
1706+
label: "virtual_0".to_string(),
1707+
kind: CompletionItemKind::FILE,
1708+
label_detail: None,
1709+
},
1710+
VirtualCompletionItem {
1711+
label: "x".to_string(),
1712+
kind: CompletionItemKind::VARIABLE,
1713+
label_detail: None,
1714+
},
1715+
VirtualCompletionItem {
1716+
label: "y".to_string(),
1717+
kind: CompletionItemKind::CONSTANT,
1718+
label_detail: None,
1719+
},
1720+
VirtualCompletionItem {
1721+
label: "init".to_string(),
1722+
kind: CompletionItemKind::FUNCTION,
1723+
label_detail: Some("(self) -> nil".to_string()),
1724+
},
1725+
],
1726+
);
1727+
}
1728+
14611729
#[test]
14621730
fn test_doc_completion_myst_empty() {
14631731
let make_ws = || {

0 commit comments

Comments
 (0)