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
Notes: sideshowbarker 2024-07-18 11:36:52 +09:00
15 changed files with 83 additions and 39 deletions

View File

@ -8,6 +8,7 @@
#include <AK/String.h>
#include <AK/Types.h>
#include <LibCpp/Parser.h>
#include <LibGUI/AutocompleteProvider.h>
#include <LibIPC/Decoder.h>
#include <LibIPC/Encoder.h>
@ -102,4 +103,33 @@ inline bool decode(Decoder& decoder, GUI::AutocompleteProvider::Declaration& dec
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);
}
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));
}

View File

@ -14,6 +14,7 @@
#include <AK/WeakPtr.h>
#include <AK/Weakable.h>
#include <LibCore/ElapsedTimer.h>
#include <LibCpp/Preprocessor.h>
#include <LibIPC/ServerConnection.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 declaration_location(GUI::AutocompleteProvider::ProjectLocation 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; }
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));
}
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);
set_todo_entries_of_document_callback(filename, move(todo_entries));

View File

@ -30,12 +30,12 @@ public:
public:
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:
const FileDB& filedb() const { return m_filedb; }
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; }
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) {
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));
};
}

View File

@ -3,5 +3,5 @@ endpoint LanguageClient
auto_complete_suggestions(Vector<GUI::AutocompleteProvider::Entry> suggestions) =|
declaration_location(GUI::AutocompleteProvider::ProjectLocation location) =|
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 <DevTools/HackStudio/LanguageServers/ClientConnection.h>
#include <LibCpp/Parser.h>
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) {
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));
};
}

View File

@ -14,20 +14,20 @@ ToDoEntries& HackStudio::ToDoEntries::the()
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));
if (on_update)
on_update();
}
Vector<ToDoEntryPair> ToDoEntries::get_entries()
Vector<Cpp::Parser::TodoEntry> ToDoEntries::get_entries()
{
Vector<ToDoEntryPair> ret;
for (auto& it : m_document_to_entries)
Vector<Cpp::Parser::TodoEntry> ret;
for (auto& it : m_document_to_entries) {
for (auto& entry : it.value)
ret.append({ it.key, entry });
ret.append({ entry.content, it.key, entry.line, entry.column });
}
return ret;
}

View File

@ -10,29 +10,25 @@
#include <AK/HashMap.h>
#include <AK/Noncopyable.h>
#include <AK/String.h>
#include <LibCpp/Parser.h>
namespace HackStudio {
struct ToDoEntryPair {
String filename;
String comment;
};
class ToDoEntries {
AK_MAKE_NONCOPYABLE(ToDoEntries);
public:
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;
private:
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 "HackStudio.h"
#include "Project.h"
#include "ToDoEntries.h"
#include <AK/StringBuilder.h>
#include <LibGUI/BoxLayout.h>
#include <LibGUI/Button.h>
#include <LibGUI/TableView.h>
#include <LibGUI/TextBox.h>
#include <LibGfx/FontDatabase.h>
namespace HackStudio {
@ -22,16 +17,18 @@ public:
enum Column {
Filename,
Text,
Line,
Column,
__Count
};
explicit ToDoEntriesModel(const Vector<ToDoEntryPair>&& matches)
explicit ToDoEntriesModel(Vector<Cpp::Parser::TodoEntry> const&& matches)
: m_matches(move(matches))
{
}
virtual int row_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override { return m_matches.size(); }
virtual int column_count(const GUI::ModelIndex& = GUI::ModelIndex()) const override { return Column::__Count; }
virtual int row_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return m_matches.size(); }
virtual int column_count(GUI::ModelIndex const& = GUI::ModelIndex()) const override { return Column::__Count; }
virtual String column_name(int column) const override
{
@ -40,12 +37,16 @@ public:
return "Filename";
case Column::Text:
return "Text";
case Column::Line:
return "Line";
case Column::Column:
return "Col";
default:
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)
return Gfx::TextAlignment::CenterLeft;
@ -60,7 +61,11 @@ public:
case Column::Filename:
return match.filename;
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 {};
@ -77,7 +82,7 @@ public:
}
private:
Vector<ToDoEntryPair> m_matches;
Vector<Cpp::Parser::TodoEntry> m_matches;
};
void ToDoEntriesWidget::refresh()
@ -91,6 +96,11 @@ ToDoEntriesWidget::ToDoEntriesWidget()
{
set_layout<GUI::VerticalBoxLayout>();
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
#include <LibGUI/Button.h>
#include <LibGUI/TableView.h>
#include <LibGUI/TextBox.h>
#include <LibGUI/Widget.h>
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) {
if (token.type() == Token::Type::Comment) {
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;
const Vector<String>& errors() const { return m_state.errors; }
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 {
Token token;

View File

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