diff --git a/src/lsp.rs b/src/lsp.rs index d0a256c..1939524 100644 --- a/src/lsp.rs +++ b/src/lsp.rs @@ -163,7 +163,7 @@ impl LanguageServer for ProtoLanguageServer { }; let content = self.state.get_content(&uri); - let identifier = tree.get_actionable_node_text_at_position(&pos, content.as_bytes()); + let identifier = tree.get_hoverable_node_text_at_position(&pos, content.as_bytes()); let current_package_name = tree.get_package_name(content.as_bytes()); let Some(identifier) = identifier else { diff --git a/src/parser/tree.rs b/src/parser/tree.rs index 68cffc7..b4c4844 100644 --- a/src/parser/tree.rs +++ b/src/parser/tree.rs @@ -63,6 +63,16 @@ impl ParsedTree { .map(|n| n.utf8_text(content.as_ref()).expect("utf-8 parse error")) } + pub fn get_hoverable_node_text_at_position<'a>( + &'a self, + pos: &Position, + content: &'a [u8], + ) -> Option<&'a str> { + let n = self.get_node_at_position(pos)?; + self.get_actionable_node_text_at_position(pos, content) + .or(Some(n.kind())) + } + pub fn get_ancestor_nodes_at_position<'a>(&'a self, pos: &Position) -> Vec> { let Some(mut n) = self.get_actionable_node_at_position(pos) else { return vec![]; diff --git a/src/workspace/hover.rs b/src/workspace/hover.rs index 70bb3e6..e2c3ded 100644 --- a/src/workspace/hover.rs +++ b/src/workspace/hover.rs @@ -1,11 +1,118 @@ +use std::{collections::HashMap, sync::LazyLock}; + use async_lsp::lsp_types::MarkedString; use crate::{ formatter::ProtoFormatter, state::ProtoLanguageState, utils::split_identifier_package, }; + +static BUITIN_DOCS: LazyLock> = LazyLock::new(|| { + HashMap::from([ + ( + "int32", + r#"A 32-bit integer (varint encoding) + +Values of this type range between `-2147483648` and `2147483647`. +Beware that negative values are encoded as five bytes on the wire!"#, + ), + ( + "int64", + r#"A 64-bit integer (varint encoding) + +Values of this type range between `-9223372036854775808` and `9223372036854775807`. +Beware that negative values are encoded as ten bytes on the wire!"#, + ), + ( + "uint32", + r#"A 32-bit unsigned integer (varint encoding) + +Values of this type range between `0` and `4294967295`."#, + ), + ( + "uint64", + r#"A 64-bit unsigned integer (varint encoding) + +Values of this type range between `0` and `18446744073709551615`."#, + ), + ( + "sint32", + r#"A 32-bit integer (ZigZag encoding) + +Values of this type range between `-2147483648` and `2147483647`."#, + ), + ( + "sint64", + r#"A 64-bit integer (ZigZag encoding) + +Values of this type range between `-9223372036854775808` and `9223372036854775807`."#, + ), + ( + "fixed32", + r#"A 32-bit unsigned integer (4-byte encoding) + +Values of this type range between `0` and `4294967295`."#, + ), + ( + "fixed64", + r#"A 64-bit unsigned integer (8-byte encoding) + +Values of this type range between `0` and `18446744073709551615`."#, + ), + ( + "sfixed32", + r#"A 32-bit integer (4-byte encoding) + +Values of this type range between `-2147483648` and `2147483647`."#, + ), + ( + "sfixed64", + r#"A 64-bit integer (8-byte encoding) + +Values of this type range between `-9223372036854775808` and `9223372036854775807`."#, + ), + ( + "float", + "A single-precision floating point number (IEEE-745.2008 binary32).", + ), + ( + "double", + "A double-precision floating point number (IEEE-745.2008 binary64).", + ), + ( + "string", + r#"A string of text. + +Stores at most 4GB of text. Intended to be UTF-8 encoded Unicode; use `bytes` if you need other encodings."#, + ), + ( + "bytes", + r#"A blob of arbitrary bytes. + +Stores at most 4GB of binary data. Encoded as base64 in JSON."#, + ), + ( + "bool", + r#"A Boolean value: `true` or `false`. + +Encoded as a single byte: `0x00` or `0xff` (all non-zero bytes decode to `true`)."#, + ), + ( + "default", + r#"A magic option that specifies the field's default value. + +Unlike every other option on a field, this does not have a corresponding field in +`google.protobuf.FieldOptions`; it is implemented by compiler magic."#, + ), + ]) +}); + impl ProtoLanguageState { pub fn hover(&self, curr_package: &str, identifier: &str) -> Vec { + if let Some(docs) = BUITIN_DOCS.get(identifier) { + return vec![MarkedString::String(docs.to_string())]; + } + let (mut package, identifier) = split_identifier_package(identifier); if package.is_empty() { package = curr_package; @@ -42,6 +149,7 @@ mod test { state.upsert_file(&c_uri, c.to_owned()); assert_yaml_snapshot!(state.hover("com.workspace", "Author")); + assert_yaml_snapshot!(state.hover("com.workspace", "int64")); assert_yaml_snapshot!(state.hover("com.workspace", "Author.Address")); assert_yaml_snapshot!(state.hover("com.workspace", "com.utility.Foobar.Baz")); assert_yaml_snapshot!(state.hover("com.utility", "Baz")); diff --git a/src/workspace/snapshots/protols__workspace__hover__test__workspace_test_hover-2.snap b/src/workspace/snapshots/protols__workspace__hover__test__workspace_test_hover-2.snap index 55ec65d..1dbb2d6 100644 --- a/src/workspace/snapshots/protols__workspace__hover__test__workspace_test_hover-2.snap +++ b/src/workspace/snapshots/protols__workspace__hover__test__workspace_test_hover-2.snap @@ -1,5 +1,6 @@ --- source: src/workspace/hover.rs -expression: "state.hover(\"com.library\", \"Author.Address\")" +expression: "state.hover(\"com.workspace\", \"int64\")" +snapshot_kind: text --- -- Address is a Address +- "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!" diff --git a/src/workspace/snapshots/protols__workspace__hover__test__workspace_test_hover-3.snap b/src/workspace/snapshots/protols__workspace__hover__test__workspace_test_hover-3.snap index 7e3ab87..00bbfa0 100644 --- a/src/workspace/snapshots/protols__workspace__hover__test__workspace_test_hover-3.snap +++ b/src/workspace/snapshots/protols__workspace__hover__test__workspace_test_hover-3.snap @@ -1,5 +1,6 @@ --- source: src/workspace/hover.rs -expression: "state.hover(\"com.library\", \"com.utility.Foobar.Baz\")" +expression: "state.hover(\"com.workspace\", \"Author.Address\")" +snapshot_kind: text --- -- What is baz? +- Address is a Address diff --git a/src/workspace/snapshots/protols__workspace__hover__test__workspace_test_hover-5.snap b/src/workspace/snapshots/protols__workspace__hover__test__workspace_test_hover-5.snap new file mode 100644 index 0000000..152acde --- /dev/null +++ b/src/workspace/snapshots/protols__workspace__hover__test__workspace_test_hover-5.snap @@ -0,0 +1,6 @@ +--- +source: src/workspace/hover.rs +expression: "state.hover(\"com.utility\", \"Baz\")" +snapshot_kind: text +--- +- What is baz?