summaryrefslogtreecommitdiff
path: root/Userland/DevTools
diff options
context:
space:
mode:
authorItamar <itamar8910@gmail.com>2021-05-22 11:27:54 +0300
committerAndreas Kling <kling@serenityos.org>2021-05-22 15:52:11 +0200
commitc003c3c76d5cef165808a28c042aae08492fa381 (patch)
treed8826a33dfcbda6b05c63a3dbd0a8ddaaa73718b /Userland/DevTools
parentccd491594fcb83141a7d7f24c2db650d877ac8e4 (diff)
downloadserenity-c003c3c76d5cef165808a28c042aae08492fa381.zip
CppLanguageServer+LibGUI: Autocomplete #include paths
The C++ language-server can now autocomplete include paths. Paths that start with '<' will be searched in /usr/include, and paths that start with '"' will be searched in the project's root directory.
Diffstat (limited to 'Userland/DevTools')
-rw-r--r--Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp50
-rw-r--r--Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.h1
2 files changed, 51 insertions, 0 deletions
diff --git a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp
index 4f70cd9a50..f868a280dd 100644
--- a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp
+++ b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.cpp
@@ -8,6 +8,8 @@
#include <AK/Assertions.h>
#include <AK/HashTable.h>
#include <AK/OwnPtr.h>
+#include <LibCore/DirIterator.h>
+#include <LibCore/File.h>
#include <LibCpp/AST.h>
#include <LibCpp/Lexer.h>
#include <LibCpp/Parser.h>
@@ -64,6 +66,13 @@ Vector<GUI::AutocompleteProvider::Entry> CppComprehensionEngine::get_suggestions
const auto& document = *document_ptr;
auto containing_token = document.parser().token_at(position);
+
+ if (containing_token.has_value() && containing_token->type() == Token::Type::IncludePath) {
+ auto results = try_autocomplete_include(document, containing_token.value());
+ if (results.has_value())
+ return results.value();
+ }
+
auto node = document.parser().node_at(position);
if (!node) {
dbgln_if(CPP_LANGUAGE_SERVER_DEBUG, "no node at position {}:{}", position.line, position.column);
@@ -540,6 +549,7 @@ OwnPtr<CppComprehensionEngine::DocumentData> CppComprehensionEngine::create_docu
document_data->m_text = move(text);
document_data->m_preprocessor = make<Preprocessor>(document_data->m_filename, document_data->text());
document_data->preprocessor().set_ignore_unsupported_keywords(true);
+ document_data->preprocessor().set_keep_include_statements(true);
document_data->preprocessor().process();
Preprocessor::Definitions preprocessor_definitions;
@@ -590,4 +600,44 @@ String CppComprehensionEngine::scope_of_declaration(const Declaration& decl) con
return String::formatted("{}::{}", parent_scope, containing_scope);
}
+Optional<Vector<GUI::AutocompleteProvider::Entry>> CppComprehensionEngine::try_autocomplete_include(const DocumentData&, Token include_path_token)
+{
+ VERIFY(include_path_token.type() == Token::Type::IncludePath);
+ auto partial_include = include_path_token.text().trim_whitespace();
+
+ String include_root;
+ auto include_type = GUI::AutocompleteProvider::CompletionKind::ProjectInclude;
+ if (partial_include.starts_with("<")) {
+ include_root = "/usr/include/";
+ include_type = GUI::AutocompleteProvider::CompletionKind::SystemInclude;
+ } else if (partial_include.starts_with("\"")) {
+ include_root = filedb().project_root();
+ } else
+ return {};
+
+ auto last_slash = partial_include.find_last_of("/");
+ auto include_dir = String::empty();
+ auto partial_basename = partial_include.substring_view((last_slash.has_value() ? last_slash.value() : 0) + 1);
+ if (last_slash.has_value()) {
+ include_dir = partial_include.substring_view(1, last_slash.value());
+ }
+
+ auto full_dir = String::formatted("{}{}", include_root, include_dir);
+ dbgln_if(CPP_LANGUAGE_SERVER_DEBUG, "searching path: {}, partial_basename: {}", full_dir, partial_basename);
+
+ Core::DirIterator it(full_dir, Core::DirIterator::Flags::SkipDots);
+ Vector<GUI::AutocompleteProvider::Entry> options;
+
+ while (it.has_next()) {
+ auto path = it.next_path();
+ if (!(path.ends_with(".h") || Core::File::is_directory(LexicalPath::join(full_dir, path).string())))
+ continue;
+ if (path.starts_with(partial_basename)) {
+ options.append({ path, partial_basename.length(), include_type, GUI::AutocompleteProvider::Language::Cpp });
+ }
+ }
+
+ return options;
+}
+
}
diff --git a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.h b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.h
index 5072f45cd1..dfbfaf0c43 100644
--- a/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.h
+++ b/Userland/DevTools/HackStudio/LanguageServers/Cpp/CppComprehensionEngine.h
@@ -103,6 +103,7 @@ private:
OwnPtr<DocumentData> create_document_data(String&& text, const String& filename);
Optional<Vector<GUI::AutocompleteProvider::Entry>> try_autocomplete_property(const DocumentData&, const ASTNode&, Optional<Token> containing_token) const;
Optional<Vector<GUI::AutocompleteProvider::Entry>> try_autocomplete_name(const DocumentData&, const ASTNode&, Optional<Token> containing_token) const;
+ Optional<Vector<GUI::AutocompleteProvider::Entry>> try_autocomplete_include(const DocumentData&, Token include_path_token);
HashMap<String, OwnPtr<DocumentData>> m_documents;
};