From b66d02ae6d6632e2de7fd02c60904a8bcb547001 Mon Sep 17 00:00:00 2001 From: Vinicius Stock Date: Wed, 25 Sep 2024 10:06:51 -0400 Subject: [PATCH] Add heredoc delimiter documentation on hover (#2617) Co-authored-by: Nick Schwaderer --- lib/ruby_lsp/listeners/hover.rb | 38 +++++++++++++++++++ ...doc.exp.json => squiggly_heredoc.exp.json} | 0 test/expectations/hover/dash_heredoc.exp.json | 14 +++++++ .../expectations/hover/plain_heredoc.exp.json | 14 +++++++ .../hover/squiggly_heredoc.exp.json | 14 +++++++ ...doc.exp.json => squiggly_heredoc.exp.json} | 0 test/fixtures/dash_heredoc.rb | 3 ++ test/fixtures/plain_heredoc.rb | 3 ++ .../{heredoc.rb => squiggly_heredoc.rb} | 0 9 files changed, 86 insertions(+) rename test/expectations/folding_ranges/{heredoc.exp.json => squiggly_heredoc.exp.json} (100%) create mode 100644 test/expectations/hover/dash_heredoc.exp.json create mode 100644 test/expectations/hover/plain_heredoc.exp.json create mode 100644 test/expectations/hover/squiggly_heredoc.exp.json rename test/expectations/selection_ranges/{heredoc.exp.json => squiggly_heredoc.exp.json} (100%) create mode 100644 test/fixtures/dash_heredoc.rb create mode 100644 test/fixtures/plain_heredoc.rb rename test/fixtures/{heredoc.rb => squiggly_heredoc.rb} (100%) diff --git a/lib/ruby_lsp/listeners/hover.rb b/lib/ruby_lsp/listeners/hover.rb index 3b3f8c2c7..dda4bade1 100644 --- a/lib/ruby_lsp/listeners/hover.rb +++ b/lib/ruby_lsp/listeners/hover.rb @@ -21,6 +21,7 @@ class Hover Prism::InstanceVariableWriteNode, Prism::SymbolNode, Prism::StringNode, + Prism::InterpolatedStringNode, Prism::SuperNode, Prism::ForwardingSuperNode, ], @@ -68,9 +69,21 @@ def initialize(response_builder, global_state, uri, node_context, dispatcher, so :on_instance_variable_target_node_enter, :on_super_node_enter, :on_forwarding_super_node_enter, + :on_string_node_enter, + :on_interpolated_string_node_enter, ) end + sig { params(node: Prism::StringNode).void } + def on_string_node_enter(node) + generate_heredoc_hover(node) + end + + sig { params(node: Prism::InterpolatedStringNode).void } + def on_interpolated_string_node_enter(node) + generate_heredoc_hover(node) + end + sig { params(node: Prism::ConstantReadNode).void } def on_constant_read_node_enter(node) return if @sorbet_level != RubyDocument::SorbetLevel::Ignore @@ -155,6 +168,31 @@ def on_forwarding_super_node_enter(node) private + sig { params(node: T.any(Prism::InterpolatedStringNode, Prism::StringNode)).void } + def generate_heredoc_hover(node) + return unless node.heredoc? + + opening_content = node.opening_loc&.slice + return unless opening_content + + match = /(<<(?(-|~)?))(?['"`]?)(?\w+)\k/.match(opening_content) + return unless match + + heredoc_delimiter = match.named_captures["delimiter"] + + if heredoc_delimiter + message = if match["type"] == "~" + "This is a squiggly heredoc definition using the `#{heredoc_delimiter}` delimiter. " \ + "Indentation will be ignored in the resulting string." + else + "This is a heredoc definition using the `#{heredoc_delimiter}` delimiter. " \ + "Indentation will be considered part of the string." + end + + @response_builder.push(message, category: :documentation) + end + end + sig { void } def handle_super_node_hover # Sorbet can handle super hover on typed true or higher diff --git a/test/expectations/folding_ranges/heredoc.exp.json b/test/expectations/folding_ranges/squiggly_heredoc.exp.json similarity index 100% rename from test/expectations/folding_ranges/heredoc.exp.json rename to test/expectations/folding_ranges/squiggly_heredoc.exp.json diff --git a/test/expectations/hover/dash_heredoc.exp.json b/test/expectations/hover/dash_heredoc.exp.json new file mode 100644 index 000000000..b84d9220f --- /dev/null +++ b/test/expectations/hover/dash_heredoc.exp.json @@ -0,0 +1,14 @@ +{ + "params": [ + { + "line": 0, + "character": 2 + } + ], + "result": { + "contents": { + "kind": "markdown", + "value": "This is a heredoc definition using the `HEREDOC` delimiter. Indentation will be considered part of the string." + } + } +} diff --git a/test/expectations/hover/plain_heredoc.exp.json b/test/expectations/hover/plain_heredoc.exp.json new file mode 100644 index 000000000..b84d9220f --- /dev/null +++ b/test/expectations/hover/plain_heredoc.exp.json @@ -0,0 +1,14 @@ +{ + "params": [ + { + "line": 0, + "character": 2 + } + ], + "result": { + "contents": { + "kind": "markdown", + "value": "This is a heredoc definition using the `HEREDOC` delimiter. Indentation will be considered part of the string." + } + } +} diff --git a/test/expectations/hover/squiggly_heredoc.exp.json b/test/expectations/hover/squiggly_heredoc.exp.json new file mode 100644 index 000000000..fed4a5fa9 --- /dev/null +++ b/test/expectations/hover/squiggly_heredoc.exp.json @@ -0,0 +1,14 @@ +{ + "params": [ + { + "line": 0, + "character": 2 + } + ], + "result": { + "contents": { + "kind": "markdown", + "value": "This is a squiggly heredoc definition using the `HEREDOC` delimiter. Indentation will be ignored in the resulting string." + } + } +} diff --git a/test/expectations/selection_ranges/heredoc.exp.json b/test/expectations/selection_ranges/squiggly_heredoc.exp.json similarity index 100% rename from test/expectations/selection_ranges/heredoc.exp.json rename to test/expectations/selection_ranges/squiggly_heredoc.exp.json diff --git a/test/fixtures/dash_heredoc.rb b/test/fixtures/dash_heredoc.rb new file mode 100644 index 000000000..367c63e79 --- /dev/null +++ b/test/fixtures/dash_heredoc.rb @@ -0,0 +1,3 @@ +<<-HEREDOC + some text#{1 + 1}other text +HEREDOC diff --git a/test/fixtures/plain_heredoc.rb b/test/fixtures/plain_heredoc.rb new file mode 100644 index 000000000..f2ab2603e --- /dev/null +++ b/test/fixtures/plain_heredoc.rb @@ -0,0 +1,3 @@ +<