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 @@ +<