Browse Source

HackStudio: Use the C++ semantic syntax highlighter

HackStudio::Editor will now send a request to get semantic token
information to the language server whenever there's a short pause in
editing.

The result is used by the semantic c++ syntax highlighter to provide
better highlighting information.
Itamar 3 years ago
parent
commit
aba2e03b71
2 changed files with 49 additions and 1 deletions
  1. 44 1
      Userland/DevTools/HackStudio/Editor.cpp
  2. 5 0
      Userland/DevTools/HackStudio/Editor.h

+ 44 - 1
Userland/DevTools/HackStudio/Editor.cpp

@@ -16,6 +16,8 @@
 #include <AK/LexicalPath.h>
 #include <LibCore/DirIterator.h>
 #include <LibCore/File.h>
+#include <LibCore/Timer.h>
+#include <LibCpp/SemanticSyntaxHighlighter.h>
 #include <LibCpp/SyntaxHighlighter.h>
 #include <LibGUI/Action.h>
 #include <LibGUI/Application.h>
@@ -51,6 +53,8 @@ ErrorOr<NonnullRefPtr<Editor>> Editor::try_create()
 
 Editor::Editor()
 {
+    create_tokens_info_timer();
+
     set_document(CodeDocument::create());
     m_evaluate_expression_action = GUI::Action::create("Evaluate expression", { Mod_Ctrl, Key_E }, [this](auto&) {
         VERIFY(is_program_running());
@@ -496,6 +500,9 @@ void Editor::set_document(GUI::TextDocument& doc)
     } else {
         set_autocomplete_provider_for(code_document);
     }
+
+    on_token_info_timer_tick();
+    m_tokens_info_timer->restart();
 }
 
 Optional<Editor::AutoCompleteRequestData> Editor::get_autocomplete_request_data()
@@ -602,7 +609,7 @@ void Editor::set_syntax_highlighter_for(const CodeDocument& document)
 {
     switch (document.language()) {
     case Language::Cpp:
-        set_syntax_highlighter(make<Cpp::SyntaxHighlighter>());
+        set_syntax_highlighter(make<Cpp::SemanticSyntaxHighlighter>());
         break;
     case Language::CSS:
         set_syntax_highlighter(make<Web::CSS::SyntaxHighlighter>());
@@ -654,6 +661,12 @@ void Editor::set_language_client_for(const CodeDocument& document)
 
     if (document.language() == Language::Shell)
         m_language_client = get_language_client<LanguageClients::Shell::ServerConnection>(project().root_path());
+
+    if (m_language_client) {
+        m_language_client->on_tokens_info_result = [this](Vector<GUI::AutocompleteProvider::TokenInfo> const& tokens_info) {
+            on_tokens_info_result(tokens_info);
+        };
+    }
 }
 
 void Editor::keydown_event(GUI::KeyEvent& event)
@@ -665,6 +678,8 @@ void Editor::keydown_event(GUI::KeyEvent& event)
     if (!event.shift() && !event.alt() && event.ctrl() && event.key() == KeyCode::Key_P) {
         handle_function_parameters_hint_request();
     }
+
+    m_tokens_info_timer->restart();
 }
 
 void Editor::handle_function_parameters_hint_request()
@@ -711,4 +726,32 @@ void Editor::set_debug_mode(bool enabled)
     m_move_execution_to_line_action->set_enabled(enabled);
 }
 
+void Editor::on_token_info_timer_tick()
+{
+    if (!m_language_client || !m_language_client->is_active_client())
+        return;
+
+    m_language_client->get_tokens_info(code_document().file_path());
+}
+
+void Editor::on_tokens_info_result(Vector<GUI::AutocompleteProvider::TokenInfo> const& tokens_info)
+{
+    auto highlighter = syntax_highlighter();
+    if (highlighter && highlighter->is_cpp_semantic_highlighter()) {
+        auto& semantic_cpp_highlighter = verify_cast<Cpp::SemanticSyntaxHighlighter>(*highlighter);
+        semantic_cpp_highlighter.update_tokens_info(tokens_info);
+        force_rehighlight();
+    }
+}
+
+void Editor::create_tokens_info_timer()
+{
+    static constexpr size_t token_info_timer_interval_ms = 1000;
+    m_tokens_info_timer = Core::Timer::create_repeating((int)token_info_timer_interval_ms, [this] {
+        on_token_info_timer_tick();
+        m_tokens_info_timer->stop();
+    });
+    m_tokens_info_timer->start();
+}
+
 }

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

@@ -1,5 +1,6 @@
 /*
  * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
+ * Copyright (c) 2020-2022, Itamar S. <itamar8910@gmail.com>
  * Copyright (c) 2018-2021, the SerenityOS developers.
  *
  * SPDX-License-Identifier: BSD-2-Clause
@@ -101,6 +102,9 @@ private:
     void set_language_client_for(const CodeDocument&);
     void set_autocomplete_provider_for(CodeDocument const&);
     void handle_function_parameters_hint_request();
+    void on_token_info_timer_tick();
+    void on_tokens_info_result(Vector<GUI::AutocompleteProvider::TokenInfo> const& tokens_info);
+    void create_tokens_info_timer();
 
     explicit Editor();
 
@@ -115,6 +119,7 @@ private:
     bool m_autocomplete_in_focus { false };
     RefPtr<GUI::Action> m_evaluate_expression_action;
     RefPtr<GUI::Action> m_move_execution_to_line_action;
+    RefPtr<Core::Timer> m_tokens_info_timer; // Used for querying language server for syntax highlighting info
 
     OwnPtr<LanguageClient> m_language_client;
     ErrorOr<void> initialize_documentation_tooltip();