Skip to content

Commit 372ef8d

Browse files
committed
wip: Add hover for builtin types
1 parent 7df5ad0 commit 372ef8d

File tree

5 files changed

+130
-1
lines changed

5 files changed

+130
-1
lines changed

src/lsp.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ impl LanguageServer for ProtoLanguageServer {
163163
};
164164

165165
let content = self.state.get_content(&uri);
166-
let identifier = tree.get_actionable_node_text_at_position(&pos, content.as_bytes());
166+
let identifier = tree.get_hoverable_node_text_at_position(&pos, content.as_bytes());
167167
let current_package_name = tree.get_package_name(content.as_bytes());
168168

169169
let Some(identifier) = identifier else {

src/nodekind.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub enum NodeKind {
88
Message,
99
EnumName,
1010
FieldName,
11+
FieldBuiltinTypeName,
1112
ServiceName,
1213
RpcName,
1314
PackageName,
@@ -23,6 +24,7 @@ impl NodeKind {
2324
NodeKind::Message => "message",
2425
NodeKind::EnumName => "enum_name",
2526
NodeKind::FieldName => "message_or_enum_type",
27+
NodeKind::FieldBuiltinTypeName => "type",
2628
NodeKind::ServiceName => "service_name",
2729
NodeKind::RpcName => "rpc_name",
2830
NodeKind::PackageName => "full_ident",
@@ -57,6 +59,10 @@ impl NodeKind {
5759
n.kind() == Self::FieldName.as_str()
5860
}
5961

62+
pub fn is_builtin_field_type(n: &Node) -> bool {
63+
n.kind() == Self::FieldBuiltinTypeName.as_str()
64+
}
65+
6066
pub fn is_userdefined(n: &Node) -> bool {
6167
n.kind() == Self::EnumName.as_str() || n.kind() == Self::MessageName.as_str()
6268
}

src/parser/tree.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,15 @@ impl ParsedTree {
6363
.map(|n| n.utf8_text(content.as_ref()).expect("utf-8 parse error"))
6464
}
6565

66+
pub fn get_hoverable_node_text_at_position<'a>(&'a self, pos:&Position, content: &'a [u8]) -> Option<&'a str> {
67+
if let Some(n) = self.get_node_at_position(pos) {
68+
if NodeKind::is_builtin_field_type(&n) {
69+
return Some(n.utf8_text(content).expect("utf8-parse error"))
70+
}
71+
}
72+
self.get_actionable_node_text_at_position(pos, content)
73+
}
74+
6675
pub fn get_ancestor_nodes_at_position<'a>(&'a self, pos: &Position) -> Vec<Node<'a>> {
6776
let Some(mut n) = self.get_actionable_node_at_position(pos) else {
6877
return vec![];

src/workspace/hover.rs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,118 @@
1+
use std::{collections::HashMap, sync::LazyLock};
2+
13
use async_lsp::lsp_types::MarkedString;
24

35
use crate::{
46
formatter::ProtoFormatter, state::ProtoLanguageState, utils::split_identifier_package,
57
};
68

9+
10+
static BUITIN_DOCS: LazyLock<HashMap<&'static str, &'static str>> = LazyLock::new(|| {
11+
HashMap::from([
12+
(
13+
"int32",
14+
r#"A 32-bit integer (varint encoding)
15+
16+
Values of this type range between `-2147483648` and `2147483647`.
17+
Beware that negative values are encoded as five bytes on the wire!"#,
18+
),
19+
(
20+
"int64",
21+
r#"A 64-bit integer (varint encoding)
22+
23+
Values of this type range between `-9223372036854775808` and `9223372036854775807`.
24+
Beware that negative values are encoded as ten bytes on the wire!"#,
25+
),
26+
(
27+
"uint32",
28+
r#"A 32-bit unsigned integer (varint encoding)
29+
30+
Values of this type range between `0` and `4294967295`."#,
31+
),
32+
(
33+
"uint64",
34+
r#"A 64-bit unsigned integer (varint encoding)
35+
36+
Values of this type range between `0` and `18446744073709551615`."#,
37+
),
38+
(
39+
"sint32",
40+
r#"A 32-bit integer (ZigZag encoding)
41+
42+
Values of this type range between `-2147483648` and `2147483647`."#,
43+
),
44+
(
45+
"sint64",
46+
r#"A 64-bit integer (ZigZag encoding)
47+
48+
Values of this type range between `-9223372036854775808` and `9223372036854775807`."#,
49+
),
50+
(
51+
"fixed32",
52+
r#"A 32-bit unsigned integer (4-byte encoding)
53+
54+
Values of this type range between `0` and `4294967295`."#,
55+
),
56+
(
57+
"fixed64",
58+
r#"A 64-bit unsigned integer (8-byte encoding)
59+
60+
Values of this type range between `0` and `18446744073709551615`."#,
61+
),
62+
(
63+
"sfixed32",
64+
r#"A 32-bit integer (4-byte encoding)
65+
66+
Values of this type range between `-2147483648` and `2147483647`."#,
67+
),
68+
(
69+
"sfixed64",
70+
r#"A 64-bit integer (8-byte encoding)
71+
72+
Values of this type range between `-9223372036854775808` and `9223372036854775807`."#,
73+
),
74+
(
75+
"float",
76+
"A single-precision floating point number (IEEE-745.2008 binary32).",
77+
),
78+
(
79+
"double",
80+
"A double-precision floating point number (IEEE-745.2008 binary64).",
81+
),
82+
(
83+
"string",
84+
r#"A string of text.
85+
86+
Stores at most 4GB of text. Intended to be UTF-8 encoded Unicode; use `bytes` if you need other encodings."#,
87+
),
88+
(
89+
"bytes",
90+
r#"A blob of arbitrary bytes.
91+
92+
Stores at most 4GB of binary data. Encoded as base64 in JSON."#,
93+
),
94+
(
95+
"bool",
96+
r#"A Boolean value: `true` or `false`.
97+
98+
Encoded as a single byte: `0x00` or `0xff` (all non-zero bytes decode to `true`)."#,
99+
),
100+
(
101+
"default",
102+
r#"A magic option that specifies the field's default value.
103+
104+
Unlike every other option on a field, this does not have a corresponding field in
105+
`google.protobuf.FieldOptions`; it is implemented by compiler magic."#,
106+
),
107+
])
108+
});
109+
7110
impl<F: ProtoFormatter> ProtoLanguageState<F> {
8111
pub fn hover(&self, curr_package: &str, identifier: &str) -> Vec<MarkedString> {
112+
if let Some(docs) = BUITIN_DOCS.get(identifier) {
113+
return vec![MarkedString::String(docs.to_string())];
114+
}
115+
9116
let (mut package, identifier) = split_identifier_package(identifier);
10117
if package.is_empty() {
11118
package = curr_package;
@@ -42,6 +149,7 @@ mod test {
42149
state.upsert_file(&c_uri, c.to_owned());
43150

44151
assert_yaml_snapshot!(state.hover("com.workspace", "Author"));
152+
assert_yaml_snapshot!(state.hover("com.workspace", "int64"));
45153
assert_yaml_snapshot!(state.hover("com.workspace", "Author.Address"));
46154
assert_yaml_snapshot!(state.hover("com.workspace", "com.utility.Foobar.Baz"));
47155
assert_yaml_snapshot!(state.hover("com.utility", "Baz"));
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
source: src/workspace/hover.rs
3+
assertion_line: 152
4+
expression: "state.hover(\"com.workspace\", \"int64\")"
5+
---
6+
- "A 64-bit integer (varint encoding)\n\nValues of this type range between `-9223372036854775808` and `9223372036854775807`.\nBeware that negative values are encoded as ten bytes on the wire!"

0 commit comments

Comments
 (0)