From f26f764c7dfb46e9dd0e893fafc0f8b5b374877c Mon Sep 17 00:00:00 2001 From: Itamar Date: Sat, 3 Jul 2021 12:05:29 +0300 Subject: [PATCH] HackStudio: Show tooltip with parameters hint when pressing Ctrl+P When you press Ctrl+P while the cursor is inside the parameters list of a function call site, HackStudio will request the C++ language server to retrieve the parameters of the called function. The result is displayed in a tooltip window, with the current argument in bold font. --- Userland/DevTools/HackStudio/Editor.cpp | 74 +++++++++++++++++++++++-- Userland/DevTools/HackStudio/Editor.h | 6 ++ 2 files changed, 76 insertions(+), 4 deletions(-) diff --git a/Userland/DevTools/HackStudio/Editor.cpp b/Userland/DevTools/HackStudio/Editor.cpp index 6b181eda5f..8b953fb07c 100644 --- a/Userland/DevTools/HackStudio/Editor.cpp +++ b/Userland/DevTools/HackStudio/Editor.cpp @@ -40,10 +40,8 @@ namespace HackStudio { Editor::Editor() { set_document(CodeDocument::create()); - m_documentation_tooltip_window = GUI::Window::construct(); - m_documentation_tooltip_window->set_rect(0, 0, 500, 400); - m_documentation_tooltip_window->set_window_type(GUI::WindowType::Tooltip); - m_documentation_page_view = m_documentation_tooltip_window->set_main_widget(); + initialize_documentation_tooltip(); + initialize_parameters_hint_tooltip(); m_evaluate_expression_action = GUI::Action::create("Evaluate expression", { Mod_Ctrl, Key_E }, [this](auto&) { if (!execution_position().has_value()) { GUI::MessageBox::show(window(), "Program is not running", "Error", GUI::MessageBox::Type::Error); @@ -74,6 +72,22 @@ Editor::~Editor() { } +void Editor::initialize_documentation_tooltip() +{ + m_documentation_tooltip_window = GUI::Window::construct(); + m_documentation_tooltip_window->set_rect(0, 0, 500, 400); + m_documentation_tooltip_window->set_window_type(GUI::WindowType::Tooltip); + m_documentation_page_view = m_documentation_tooltip_window->set_main_widget(); +} + +void Editor::initialize_parameters_hint_tooltip() +{ + m_parameters_hint_tooltip_window = GUI::Window::construct(); + m_parameters_hint_tooltip_window->set_rect(0, 0, 280, 35); + m_parameters_hint_tooltip_window->set_window_type(GUI::WindowType::Tooltip); + m_parameter_hint_page_view = m_parameters_hint_tooltip_window->set_main_widget(); +} + EditorWrapper& Editor::wrapper() { return static_cast(*parent()); @@ -287,6 +301,8 @@ void Editor::mousemove_event(GUI::MouseEvent& event) void Editor::mousedown_event(GUI::MouseEvent& event) { + m_parameters_hint_tooltip_window->hide(); + auto highlighter = wrapper().editor().syntax_highlighter(); if (!highlighter) { GUI::TextEditor::mousedown_event(event); @@ -566,6 +582,7 @@ void Editor::on_identifier_click(const GUI::TextDocumentSpan& span) }; m_language_client->search_declaration(code_document().file_path(), span.range.start().line(), span.range.start().column()); } + void Editor::set_cursor(const GUI::TextPosition& a_position) { TextEditor::set_cursor(a_position); @@ -606,4 +623,53 @@ void Editor::set_language_client_for(const CodeDocument& document) m_language_client = get_language_client(project().root_path()); } +void Editor::keydown_event(GUI::KeyEvent& event) +{ + TextEditor::keydown_event(event); + + m_parameters_hint_tooltip_window->hide(); + + if (!event.shift() && !event.alt() && event.ctrl() && event.key() == KeyCode::Key_P) { + handle_function_parameters_hint_request(); + } +} + +void Editor::handle_function_parameters_hint_request() +{ + VERIFY(m_language_client); + + m_language_client->on_function_parameters_hint_result = [this](Vector const& params, size_t argument_index) { + dbgln("on_function_parameters_hint_result"); + + StringBuilder html; + for (size_t i = 0; i < params.size(); ++i) { + if (i == argument_index) + html.append(""); + + html.appendff("{}", params[i]); + + if (i == argument_index) + html.append(""); + + if (i < params.size() - 1) + html.append(", "); + } + html.append(""); + + m_parameter_hint_page_view->load_html(html.build(), {}); + + auto cursor_rect = current_editor().cursor_content_rect().location().translated(screen_relative_rect().location()); + + Gfx::Rect content(cursor_rect.x(), cursor_rect.y(), m_parameter_hint_page_view->children_clip_rect().width(), m_parameter_hint_page_view->children_clip_rect().height()); + m_parameters_hint_tooltip_window->move_to(cursor_rect.x(), cursor_rect.y() - m_parameters_hint_tooltip_window->height() - vertical_scrollbar().value()); + + m_parameters_hint_tooltip_window->show(); + }; + + m_language_client->get_parameters_hint( + code_document().file_path(), + cursor().line(), + cursor().column()); +} + } diff --git a/Userland/DevTools/HackStudio/Editor.h b/Userland/DevTools/HackStudio/Editor.h index 0b96b6bf5b..7a98f67ac0 100644 --- a/Userland/DevTools/HackStudio/Editor.h +++ b/Userland/DevTools/HackStudio/Editor.h @@ -62,6 +62,7 @@ private: virtual void drop_event(GUI::DropEvent&) override; virtual void enter_event(Core::Event&) override; virtual void leave_event(Core::Event&) override; + virtual void keydown_event(GUI::KeyEvent&) override; void show_documentation_tooltip_if_available(const String&, const Gfx::IntPoint& screen_location); void navigate_to_include_if_available(String); @@ -94,11 +95,14 @@ private: void flush_file_content_to_langauge_server(); void set_syntax_highlighter_for(const CodeDocument&); void set_language_client_for(const CodeDocument&); + void handle_function_parameters_hint_request(); explicit Editor(); RefPtr m_documentation_tooltip_window; + RefPtr m_parameters_hint_tooltip_window; RefPtr m_documentation_page_view; + RefPtr m_parameter_hint_page_view; String m_last_parsed_token; GUI::TextPosition m_previous_text_position { 0, 0 }; bool m_hovering_editor { false }; @@ -108,6 +112,8 @@ private: RefPtr m_move_execution_to_line_action; OwnPtr m_language_client; + void initialize_documentation_tooltip(); + void initialize_parameters_hint_tooltip(); }; }