浏览代码

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.
Itamar 4 年之前
父节点
当前提交
f26f764c7d
共有 2 个文件被更改,包括 76 次插入4 次删除
  1. 70 4
      Userland/DevTools/HackStudio/Editor.cpp
  2. 6 0
      Userland/DevTools/HackStudio/Editor.h

+ 70 - 4
Userland/DevTools/HackStudio/Editor.cpp

@@ -40,10 +40,8 @@ namespace HackStudio {
 Editor::Editor()
 Editor::Editor()
 {
 {
     set_document(CodeDocument::create());
     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<Web::OutOfProcessWebView>();
+    initialize_documentation_tooltip();
+    initialize_parameters_hint_tooltip();
     m_evaluate_expression_action = GUI::Action::create("Evaluate expression", { Mod_Ctrl, Key_E }, [this](auto&) {
     m_evaluate_expression_action = GUI::Action::create("Evaluate expression", { Mod_Ctrl, Key_E }, [this](auto&) {
         if (!execution_position().has_value()) {
         if (!execution_position().has_value()) {
             GUI::MessageBox::show(window(), "Program is not running", "Error", GUI::MessageBox::Type::Error);
             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<Web::OutOfProcessWebView>();
+}
+
+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<Web::OutOfProcessWebView>();
+}
+
 EditorWrapper& Editor::wrapper()
 EditorWrapper& Editor::wrapper()
 {
 {
     return static_cast<EditorWrapper&>(*parent());
     return static_cast<EditorWrapper&>(*parent());
@@ -287,6 +301,8 @@ void Editor::mousemove_event(GUI::MouseEvent& event)
 
 
 void Editor::mousedown_event(GUI::MouseEvent& event)
 void Editor::mousedown_event(GUI::MouseEvent& event)
 {
 {
+    m_parameters_hint_tooltip_window->hide();
+
     auto highlighter = wrapper().editor().syntax_highlighter();
     auto highlighter = wrapper().editor().syntax_highlighter();
     if (!highlighter) {
     if (!highlighter) {
         GUI::TextEditor::mousedown_event(event);
         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());
     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)
 void Editor::set_cursor(const GUI::TextPosition& a_position)
 {
 {
     TextEditor::set_cursor(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<LanguageClients::Shell::ServerConnection>(project().root_path());
         m_language_client = get_language_client<LanguageClients::Shell::ServerConnection>(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<String> 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("<b>");
+
+            html.appendff("{}", params[i]);
+
+            if (i == argument_index)
+                html.append("</b>");
+
+            if (i < params.size() - 1)
+                html.append(", ");
+        }
+        html.append("<style>body { background-color: #dac7b5; }</style>");
+
+        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());
+}
+
 }
 }

+ 6 - 0
Userland/DevTools/HackStudio/Editor.h

@@ -62,6 +62,7 @@ private:
     virtual void drop_event(GUI::DropEvent&) override;
     virtual void drop_event(GUI::DropEvent&) override;
     virtual void enter_event(Core::Event&) override;
     virtual void enter_event(Core::Event&) override;
     virtual void leave_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 show_documentation_tooltip_if_available(const String&, const Gfx::IntPoint& screen_location);
     void navigate_to_include_if_available(String);
     void navigate_to_include_if_available(String);
@@ -94,11 +95,14 @@ private:
     void flush_file_content_to_langauge_server();
     void flush_file_content_to_langauge_server();
     void set_syntax_highlighter_for(const CodeDocument&);
     void set_syntax_highlighter_for(const CodeDocument&);
     void set_language_client_for(const CodeDocument&);
     void set_language_client_for(const CodeDocument&);
+    void handle_function_parameters_hint_request();
 
 
     explicit Editor();
     explicit Editor();
 
 
     RefPtr<GUI::Window> m_documentation_tooltip_window;
     RefPtr<GUI::Window> m_documentation_tooltip_window;
+    RefPtr<GUI::Window> m_parameters_hint_tooltip_window;
     RefPtr<Web::OutOfProcessWebView> m_documentation_page_view;
     RefPtr<Web::OutOfProcessWebView> m_documentation_page_view;
+    RefPtr<Web::OutOfProcessWebView> m_parameter_hint_page_view;
     String m_last_parsed_token;
     String m_last_parsed_token;
     GUI::TextPosition m_previous_text_position { 0, 0 };
     GUI::TextPosition m_previous_text_position { 0, 0 };
     bool m_hovering_editor { false };
     bool m_hovering_editor { false };
@@ -108,6 +112,8 @@ private:
     RefPtr<GUI::Action> m_move_execution_to_line_action;
     RefPtr<GUI::Action> m_move_execution_to_line_action;
 
 
     OwnPtr<LanguageClient> m_language_client;
     OwnPtr<LanguageClient> m_language_client;
+    void initialize_documentation_tooltip();
+    void initialize_parameters_hint_tooltip();
 };
 };
 
 
 }
 }