diff --git a/Base/res/icons/hackstudio/Member.png b/Base/res/icons/hackstudio/Member.png new file mode 100644 index 0000000000..e79338fd07 Binary files /dev/null and b/Base/res/icons/hackstudio/Member.png differ diff --git a/Base/res/icons/hackstudio/Namespace.png b/Base/res/icons/hackstudio/Namespace.png new file mode 100644 index 0000000000..1332089604 Binary files /dev/null and b/Base/res/icons/hackstudio/Namespace.png differ diff --git a/Userland/DevTools/HackStudio/CMakeLists.txt b/Userland/DevTools/HackStudio/CMakeLists.txt index 1c0b5136b5..35288c2233 100644 --- a/Userland/DevTools/HackStudio/CMakeLists.txt +++ b/Userland/DevTools/HackStudio/CMakeLists.txt @@ -31,6 +31,7 @@ set(SOURCES LanguageClient.cpp Locator.cpp Project.cpp + ProjectDeclarations.cpp ProjectFile.cpp ProjectTemplate.cpp TerminalWrapper.cpp diff --git a/Userland/DevTools/HackStudio/LanguageClient.cpp b/Userland/DevTools/HackStudio/LanguageClient.cpp index 01557b73f5..ca694f4eaf 100644 --- a/Userland/DevTools/HackStudio/LanguageClient.cpp +++ b/Userland/DevTools/HackStudio/LanguageClient.cpp @@ -26,7 +26,7 @@ #include "LanguageClient.h" #include "HackStudio.h" -#include "Locator.h" +#include "ProjectDeclarations.h" #include #include #include @@ -122,7 +122,7 @@ HashMap> ServerConnectionInstance void ServerConnection::handle(const Messages::LanguageClient::DeclarationsInDocument& message) { - locator().set_declared_symbols(message.filename(), message.declarations()); + ProjectDeclarations::the().set_declared_symbols(message.filename(), message.declarations()); } void LanguageClient::search_declaration(const String& path, size_t line, size_t column) diff --git a/Userland/DevTools/HackStudio/Locator.cpp b/Userland/DevTools/HackStudio/Locator.cpp index 91ae7e5de9..8144695c10 100644 --- a/Userland/DevTools/HackStudio/Locator.cpp +++ b/Userland/DevTools/HackStudio/Locator.cpp @@ -27,6 +27,7 @@ #include "Locator.h" #include "HackStudio.h" #include "Project.h" +#include "ProjectDeclarations.h" #include #include #include @@ -85,23 +86,9 @@ public: if (index.column() == Column::Filename) return suggestion.as_symbol_declaration.value().position.file; if (index.column() == Column::Icon) { - static GUI::Icon struct_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Struct.png")); - static GUI::Icon class_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Class.png")); - static GUI::Icon function_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Function.png")); - static GUI::Icon variable_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Variable.png")); - static GUI::Icon preprocessor_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Preprocessor.png")); - switch (suggestion.as_symbol_declaration.value().type) { - case GUI::AutocompleteProvider::DeclarationType::Struct: - return struct_icon; - case GUI::AutocompleteProvider::DeclarationType::Class: - return class_icon; - case GUI::AutocompleteProvider::DeclarationType::Function: - return function_icon; - case GUI::AutocompleteProvider::DeclarationType::Variable: - return variable_icon; - case GUI::AutocompleteProvider::DeclarationType::PreprocessorDefinition: - return preprocessor_icon; - } + auto icon = ProjectDeclarations::get_icon_for(suggestion.as_symbol_declaration.value().type); + if (icon.has_value()) + return icon.value(); return {}; } } @@ -226,12 +213,10 @@ void Locator::update_suggestions() suggestions.append(LocatorSuggestionModel::Suggestion::create_filename(file.name())); }); - for (auto& item : m_document_to_declarations) { - for (auto& decl : item.value) { - if (decl.name.contains(typed_text, CaseSensitivity::CaseInsensitive) || decl.scope.contains(typed_text, CaseSensitivity::CaseInsensitive)) - suggestions.append((LocatorSuggestionModel::Suggestion::create_symbol_declaration(decl))); - } - } + ProjectDeclarations::the().for_each_declared_symbol([&suggestions, &typed_text](auto& decl) { + if (decl.name.contains(typed_text, CaseSensitivity::CaseInsensitive) || decl.scope.contains(typed_text, CaseSensitivity::CaseInsensitive)) + suggestions.append((LocatorSuggestionModel::Suggestion::create_symbol_declaration(decl))); + }); dbgln("I have {} suggestion(s):", suggestions.size()); // Limit the debug logging otherwise this can be very slow for large projects @@ -257,9 +242,4 @@ void Locator::update_suggestions() dbgln("Popup rect: {}", m_popup_window->rect()); m_popup_window->show(); } -void Locator::set_declared_symbols(const String& filename, const Vector& declarations) -{ - m_document_to_declarations.set(filename, declarations); -} - } diff --git a/Userland/DevTools/HackStudio/Locator.h b/Userland/DevTools/HackStudio/Locator.h index 7d8ae8ac85..5b2e365107 100644 --- a/Userland/DevTools/HackStudio/Locator.h +++ b/Userland/DevTools/HackStudio/Locator.h @@ -39,7 +39,6 @@ public: void open(); void close(); - void set_declared_symbols(const String& filename, const Vector&); private: void update_suggestions(); @@ -50,7 +49,6 @@ private: RefPtr m_textbox; RefPtr m_popup_window; RefPtr m_suggestion_view; - HashMap> m_document_to_declarations; }; } diff --git a/Userland/DevTools/HackStudio/ProjectDeclarations.cpp b/Userland/DevTools/HackStudio/ProjectDeclarations.cpp new file mode 100644 index 0000000000..02a8f19790 --- /dev/null +++ b/Userland/DevTools/HackStudio/ProjectDeclarations.cpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2021, Itamar S. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "ProjectDeclarations.h" + +HackStudio::ProjectDeclarations& HackStudio::ProjectDeclarations::the() +{ + static ProjectDeclarations s_instance; + return s_instance; +} +void HackStudio::ProjectDeclarations::set_declared_symbols(const String& filename, const Vector& declarations) +{ + m_document_to_declarations.set(filename, declarations); + if (on_update) + on_update(); +} + +Optional HackStudio::ProjectDeclarations::get_icon_for(GUI::AutocompleteProvider::DeclarationType type) +{ + static GUI::Icon struct_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Struct.png")); + static GUI::Icon class_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Class.png")); + static GUI::Icon function_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Function.png")); + static GUI::Icon variable_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Variable.png")); + static GUI::Icon preprocessor_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Preprocessor.png")); + static GUI::Icon member_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Member.png")); + static GUI::Icon namespace_icon(Gfx::Bitmap::load_from_file("/res/icons/hackstudio/Namespace.png")); + switch (type) { + case GUI::AutocompleteProvider::DeclarationType::Struct: + return struct_icon; + case GUI::AutocompleteProvider::DeclarationType::Class: + return class_icon; + case GUI::AutocompleteProvider::DeclarationType::Function: + return function_icon; + case GUI::AutocompleteProvider::DeclarationType::Variable: + return variable_icon; + case GUI::AutocompleteProvider::DeclarationType::PreprocessorDefinition: + return preprocessor_icon; + case GUI::AutocompleteProvider::DeclarationType::Member: + return member_icon; + case GUI::AutocompleteProvider::DeclarationType::Namespace: + return namespace_icon; + default: + return {}; + } +} diff --git a/Userland/DevTools/HackStudio/ProjectDeclarations.h b/Userland/DevTools/HackStudio/ProjectDeclarations.h new file mode 100644 index 0000000000..93494530f5 --- /dev/null +++ b/Userland/DevTools/HackStudio/ProjectDeclarations.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021, Itamar S. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace HackStudio { + +class ProjectDeclarations { + AK_MAKE_NONCOPYABLE(ProjectDeclarations); + +public: + static ProjectDeclarations& the(); + template + void for_each_declared_symbol(Func); + + void set_declared_symbols(const String& filename, const Vector&); + + static Optional get_icon_for(GUI::AutocompleteProvider::DeclarationType); + + Function on_update = nullptr; + +private: + ProjectDeclarations() = default; + HashMap> m_document_to_declarations; +}; + +template +void ProjectDeclarations::for_each_declared_symbol(Func f) +{ + for (auto& item : m_document_to_declarations) { + for (auto& decl : item.value) { + f(decl); + } + } +} + +}