1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 22:57:44 +00:00

HackStudio: Make TODO entries clickable

Now you can click a TODO entry to set focus on that position of that
file.
This commit is contained in:
Federico Guerinoni 2021-06-01 23:54:55 +02:00 committed by Linus Groh
parent 935c7b2f4b
commit e0f1c237d2
15 changed files with 83 additions and 39 deletions

View file

@ -8,6 +8,7 @@
#include <AK/String.h> #include <AK/String.h>
#include <AK/Types.h> #include <AK/Types.h>
#include <LibCpp/Parser.h>
#include <LibGUI/AutocompleteProvider.h> #include <LibGUI/AutocompleteProvider.h>
#include <LibIPC/Decoder.h> #include <LibIPC/Decoder.h>
#include <LibIPC/Encoder.h> #include <LibIPC/Encoder.h>
@ -102,4 +103,33 @@ inline bool decode(Decoder& decoder, GUI::AutocompleteProvider::Declaration& dec
return true; return true;
} }
template<>
inline bool encode(Encoder& encoder, Cpp::Parser::TodoEntry const& entry)
{
encoder << entry.content;
encoder << entry.filename;
encoder << (u64)entry.line;
encoder << (u64)entry.column;
return true;
}
template<>
inline bool decode(Decoder& decoder, Cpp::Parser::TodoEntry& entry)
{
u64 line = 0;
u64 column = 0;
if (!decoder.decode(entry.content))
return false;
if (!decoder.decode(entry.filename))
return false;
if (!decoder.decode(line))
return false;
if (!decoder.decode(column))
return false;
entry.line = line;
entry.column = column;
return true;
}
} }

View file

@ -99,7 +99,7 @@ void ServerConnection::declarations_in_document(const String& filename, const Ve
ProjectDeclarations::the().set_declared_symbols(filename, declarations); ProjectDeclarations::the().set_declared_symbols(filename, declarations);
} }
void ServerConnection::todo_entries_in_document(const String& filename, const Vector<String>& todo_entries) void ServerConnection::todo_entries_in_document(String const& filename, Vector<Cpp::Parser::TodoEntry> const& todo_entries)
{ {
ToDoEntries::the().set_entries(filename, move(todo_entries)); ToDoEntries::the().set_entries(filename, move(todo_entries));
} }

View file

@ -14,6 +14,7 @@
#include <AK/WeakPtr.h> #include <AK/WeakPtr.h>
#include <AK/Weakable.h> #include <AK/Weakable.h>
#include <LibCore/ElapsedTimer.h> #include <LibCore/ElapsedTimer.h>
#include <LibCpp/Preprocessor.h>
#include <LibIPC/ServerConnection.h> #include <LibIPC/ServerConnection.h>
#include <DevTools/HackStudio/LanguageServers/LanguageClientEndpoint.h> #include <DevTools/HackStudio/LanguageServers/LanguageClientEndpoint.h>
@ -46,7 +47,7 @@ protected:
virtual void auto_complete_suggestions(Vector<GUI::AutocompleteProvider::Entry> const&) override; virtual void auto_complete_suggestions(Vector<GUI::AutocompleteProvider::Entry> const&) override;
virtual void declaration_location(GUI::AutocompleteProvider::ProjectLocation const&) override; virtual void declaration_location(GUI::AutocompleteProvider::ProjectLocation const&) override;
virtual void declarations_in_document(String const&, Vector<GUI::AutocompleteProvider::Declaration> const&) override; virtual void declarations_in_document(String const&, Vector<GUI::AutocompleteProvider::Declaration> const&) override;
virtual void todo_entries_in_document(String const&, Vector<String> const&) override; virtual void todo_entries_in_document(String const&, Vector<Cpp::Parser::TodoEntry> const&) override;
void set_wrapper(ServerConnectionWrapper& wrapper) { m_wrapper = &wrapper; } void set_wrapper(ServerConnectionWrapper& wrapper) { m_wrapper = &wrapper; }
String m_project_path; String m_project_path;

View file

@ -32,7 +32,7 @@ void CodeComprehensionEngine::set_declarations_of_document(const String& filenam
set_declarations_of_document_callback(filename, move(declarations)); set_declarations_of_document_callback(filename, move(declarations));
} }
void CodeComprehensionEngine::set_todo_entries_of_document(const String& filename, Vector<String>&& todo_entries) void CodeComprehensionEngine::set_todo_entries_of_document(String const& filename, Vector<Cpp::Parser::TodoEntry>&& todo_entries)
{ {
VERIFY(set_todo_entries_of_document_callback); VERIFY(set_todo_entries_of_document_callback);
set_todo_entries_of_document_callback(filename, move(todo_entries)); set_todo_entries_of_document_callback(filename, move(todo_entries));

View file

@ -30,12 +30,12 @@ public:
public: public:
Function<void(const String&, Vector<GUI::AutocompleteProvider::Declaration>&&)> set_declarations_of_document_callback; Function<void(const String&, Vector<GUI::AutocompleteProvider::Declaration>&&)> set_declarations_of_document_callback;
Function<void(const String&, Vector<String>&&)> set_todo_entries_of_document_callback; Function<void(String const&, Vector<Cpp::Parser::TodoEntry>&&)> set_todo_entries_of_document_callback;
protected: protected:
const FileDB& filedb() const { return m_filedb; } const FileDB& filedb() const { return m_filedb; }
void set_declarations_of_document(const String&, Vector<GUI::AutocompleteProvider::Declaration>&&); void set_declarations_of_document(const String&, Vector<GUI::AutocompleteProvider::Declaration>&&);
void set_todo_entries_of_document(const String&, Vector<String>&&); void set_todo_entries_of_document(String const&, Vector<Cpp::Parser::TodoEntry>&&);
const HashMap<String, Vector<GUI::AutocompleteProvider::Declaration>>& all_declarations() const { return m_all_declarations; } const HashMap<String, Vector<GUI::AutocompleteProvider::Declaration>>& all_declarations() const { return m_all_declarations; }
private: private:

View file

@ -22,7 +22,7 @@ public:
m_autocomplete_engine->set_declarations_of_document_callback = [this](const String& filename, Vector<GUI::AutocompleteProvider::Declaration>&& declarations) { m_autocomplete_engine->set_declarations_of_document_callback = [this](const String& filename, Vector<GUI::AutocompleteProvider::Declaration>&& declarations) {
async_declarations_in_document(filename, move(declarations)); async_declarations_in_document(filename, move(declarations));
}; };
m_autocomplete_engine->set_todo_entries_of_document_callback = [this](const String& filename, Vector<String>&& todo_entries) { m_autocomplete_engine->set_todo_entries_of_document_callback = [this](String const& filename, Vector<Cpp::Parser::TodoEntry>&& todo_entries) {
async_todo_entries_in_document(filename, move(todo_entries)); async_todo_entries_in_document(filename, move(todo_entries));
}; };
} }

View file

@ -3,5 +3,5 @@ endpoint LanguageClient
auto_complete_suggestions(Vector<GUI::AutocompleteProvider::Entry> suggestions) =| auto_complete_suggestions(Vector<GUI::AutocompleteProvider::Entry> suggestions) =|
declaration_location(GUI::AutocompleteProvider::ProjectLocation location) =| declaration_location(GUI::AutocompleteProvider::ProjectLocation location) =|
declarations_in_document(String filename, Vector<GUI::AutocompleteProvider::Declaration> declarations) =| declarations_in_document(String filename, Vector<GUI::AutocompleteProvider::Declaration> declarations) =|
todo_entries_in_document(String filename, Vector<String> todo_entries) =| todo_entries_in_document(String filename, Vector<Cpp::Parser::TodoEntry> todo_entries) =|
} }

View file

@ -8,6 +8,7 @@
#include "ShellComprehensionEngine.h" #include "ShellComprehensionEngine.h"
#include <DevTools/HackStudio/LanguageServers/ClientConnection.h> #include <DevTools/HackStudio/LanguageServers/ClientConnection.h>
#include <LibCpp/Parser.h>
namespace LanguageServers::Shell { namespace LanguageServers::Shell {
@ -21,7 +22,7 @@ class ClientConnection final : public LanguageServers::ClientConnection {
m_autocomplete_engine->set_declarations_of_document_callback = [this](const String& filename, Vector<GUI::AutocompleteProvider::Declaration>&& declarations) { m_autocomplete_engine->set_declarations_of_document_callback = [this](const String& filename, Vector<GUI::AutocompleteProvider::Declaration>&& declarations) {
async_declarations_in_document(filename, move(declarations)); async_declarations_in_document(filename, move(declarations));
}; };
m_autocomplete_engine->set_todo_entries_of_document_callback = [this](const String& filename, Vector<String>&& todo_entries) { m_autocomplete_engine->set_todo_entries_of_document_callback = [this](String const& filename, Vector<Cpp::Parser::TodoEntry>&& todo_entries) {
async_todo_entries_in_document(filename, move(todo_entries)); async_todo_entries_in_document(filename, move(todo_entries));
}; };
} }

View file

@ -14,20 +14,20 @@ ToDoEntries& HackStudio::ToDoEntries::the()
return s_instance; return s_instance;
} }
void ToDoEntries::set_entries(const String& filename, const Vector<String>&& entries) void ToDoEntries::set_entries(String const& filename, Vector<Cpp::Parser::TodoEntry> const&& entries)
{ {
m_document_to_entries.set(filename, move(entries)); m_document_to_entries.set(filename, move(entries));
if (on_update) if (on_update)
on_update(); on_update();
} }
Vector<ToDoEntryPair> ToDoEntries::get_entries() Vector<Cpp::Parser::TodoEntry> ToDoEntries::get_entries()
{ {
Vector<ToDoEntryPair> ret; Vector<Cpp::Parser::TodoEntry> ret;
for (auto& it : m_document_to_entries) for (auto& it : m_document_to_entries) {
for (auto& entry : it.value) for (auto& entry : it.value)
ret.append({ it.key, entry }); ret.append({ entry.content, it.key, entry.line, entry.column });
}
return ret; return ret;
} }

View file

@ -10,29 +10,25 @@
#include <AK/HashMap.h> #include <AK/HashMap.h>
#include <AK/Noncopyable.h> #include <AK/Noncopyable.h>
#include <AK/String.h> #include <AK/String.h>
#include <LibCpp/Parser.h>
namespace HackStudio { namespace HackStudio {
struct ToDoEntryPair {
String filename;
String comment;
};
class ToDoEntries { class ToDoEntries {
AK_MAKE_NONCOPYABLE(ToDoEntries); AK_MAKE_NONCOPYABLE(ToDoEntries);
public: public:
static ToDoEntries& the(); static ToDoEntries& the();
void set_entries(const String& filename, const Vector<String>&& entries); void set_entries(String const& filename, Vector<Cpp::Parser::TodoEntry> const&& entries);
Vector<ToDoEntryPair> get_entries(); Vector<Cpp::Parser::TodoEntry> get_entries();
Function<void()> on_update = nullptr; Function<void()> on_update = nullptr;
private: private:
ToDoEntries() = default; ToDoEntries() = default;
HashMap<String, Vector<String>> m_document_to_entries; HashMap<String, Vector<Cpp::Parser::TodoEntry>> m_document_to_entries;
}; };
} }

View file

@ -6,13 +6,8 @@
#include "ToDoEntriesWidget.h" #include "ToDoEntriesWidget.h"
#include "HackStudio.h" #include "HackStudio.h"
#include "Project.h"
#include "ToDoEntries.h" #include "ToDoEntries.h"
#include <AK/StringBuilder.h>
#include <LibGUI/BoxLayout.h> #include <LibGUI/BoxLayout.h>
#include <LibGUI/Button.h>
#include <LibGUI/TableView.h>
#include <LibGUI/TextBox.h>
#include <LibGfx/FontDatabase.h> #include <LibGfx/FontDatabase.h>
namespace HackStudio { namespace HackStudio {
@ -22,16 +17,18 @@ public:
enum Column { enum Column {
Filename, Filename,
Text, Text,
Line,
Column,
__Count __Count
}; };
explicit ToDoEntriesModel(const Vector<ToDoEntryPair>&& matches) explicit ToDoEntriesModel(Vector<Cpp::Parser::TodoEntry> const&& matches)
: m_matches(move(matches)) : m_matches(move(matches))
{ {
} }
virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override { return m_matches.size(); } virtual int row_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return m_matches.size(); }
virtual int column_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override { return Column::__Count; } virtual int column_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return Column::__Count; }
virtual String column_name(int column) const override virtual String column_name(int column) const override
{ {
@ -40,12 +37,16 @@ public:
return "Filename"; return "Filename";
case Column::Text: case Column::Text:
return "Text"; return "Text";
case Column::Line:
return "Line";
case Column::Column:
return "Col";
default: default:
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }
virtual GUI::Variant data(const GUI::ModelIndex& index, GUI::ModelRole role) const override virtual GUI::Variant data(GUI::ModelIndex const& index, GUI::ModelRole role) const override
{ {
if (role == GUI::ModelRole::TextAlignment) if (role == GUI::ModelRole::TextAlignment)
return Gfx::TextAlignment::CenterLeft; return Gfx::TextAlignment::CenterLeft;
@ -60,7 +61,11 @@ public:
case Column::Filename: case Column::Filename:
return match.filename; return match.filename;
case Column::Text: case Column::Text:
return match.comment; return match.content;
case Column::Line:
return String::formatted("{}", match.line + 1);
case Column::Column:
return String::formatted("{}", match.column);
} }
} }
return {}; return {};
@ -77,7 +82,7 @@ public:
} }
private: private:
Vector<ToDoEntryPair> m_matches; Vector<Cpp::Parser::TodoEntry> m_matches;
}; };
void ToDoEntriesWidget::refresh() void ToDoEntriesWidget::refresh()
@ -91,6 +96,11 @@ ToDoEntriesWidget::ToDoEntriesWidget()
{ {
set_layout<GUI::VerticalBoxLayout>(); set_layout<GUI::VerticalBoxLayout>();
m_result_view = add<GUI::TableView>(); m_result_view = add<GUI::TableView>();
m_result_view->on_activation = [](auto& index) {
auto& match = *(Cpp::Parser::TodoEntry const*)index.internal_data();
open_file(match.filename, match.line, match.column);
};
} }
} }

View file

@ -6,9 +6,7 @@
#pragma once #pragma once
#include <LibGUI/Button.h>
#include <LibGUI/TableView.h> #include <LibGUI/TableView.h>
#include <LibGUI/TextBox.h>
#include <LibGUI/Widget.h> #include <LibGUI/Widget.h>
namespace HackStudio { namespace HackStudio {

View file

@ -961,13 +961,13 @@ void Parser::print_tokens() const
} }
} }
Vector<String> Parser::get_todo_entries() const Vector<Parser::TodoEntry> Parser::get_todo_entries() const
{ {
Vector<String> ret; Vector<TodoEntry> ret;
for (auto& token : m_tokens) { for (auto& token : m_tokens) {
if (token.type() == Token::Type::Comment) { if (token.type() == Token::Type::Comment) {
if (token.text().contains("TODO")) { if (token.text().contains("TODO")) {
ret.append(token.text()); ret.append({ token.text(), m_filename, token.start().line, token.start().column });
} }
} }
} }

View file

@ -35,7 +35,14 @@ public:
void print_tokens() const; void print_tokens() const;
const Vector<String>& errors() const { return m_state.errors; } const Vector<String>& errors() const { return m_state.errors; }
const Preprocessor::Definitions& preprocessor_definitions() const { return m_preprocessor_definitions; } const Preprocessor::Definitions& preprocessor_definitions() const { return m_preprocessor_definitions; }
Vector<String> get_todo_entries() const;
struct TodoEntry {
String content;
String filename;
size_t line { 0 };
size_t column { 0 };
};
Vector<TodoEntry> get_todo_entries() const;
struct TokenAndPreprocessorDefinition { struct TokenAndPreprocessorDefinition {
Token token; Token token;

View file

@ -14,6 +14,7 @@
#include <AK/Vector.h> #include <AK/Vector.h>
namespace Cpp { namespace Cpp {
class Preprocessor { class Preprocessor {
public: public: