浏览代码

LanguageServers/Cpp: Update client asynchronously about symbols

As a document is parsed, the language server updates the client
asynchronously about symbol declarations it finds.
Itamar 4 年之前
父节点
当前提交
a94b5376bc

+ 1 - 1
Userland/DevTools/HackStudio/AutoCompleteResponse.h

@@ -110,7 +110,7 @@ inline bool decode(Decoder& decoder, GUI::AutocompleteProvider::Declaration& dec
     if (!decode(decoder, declaration.position))
     if (!decode(decoder, declaration.position))
         return false;
         return false;
     u32 type;
     u32 type;
-    if (!decoder.decode( type))
+    if (!decoder.decode(type))
         return false;
         return false;
 
 
     declaration.type = static_cast<GUI::AutocompleteProvider::DeclarationType>(type);
     declaration.type = static_cast<GUI::AutocompleteProvider::DeclarationType>(type);

+ 1 - 0
Userland/DevTools/HackStudio/LanguageClient.h

@@ -91,6 +91,7 @@ public:
 protected:
 protected:
     virtual void handle(const Messages::LanguageClient::AutoCompleteSuggestions&) override;
     virtual void handle(const Messages::LanguageClient::AutoCompleteSuggestions&) override;
     virtual void handle(const Messages::LanguageClient::DeclarationLocation&) override;
     virtual void handle(const Messages::LanguageClient::DeclarationLocation&) override;
+    virtual void handle(const Messages::LanguageClient::DeclarationsInDocument&) override;
 
 
     String m_project_path;
     String m_project_path;
     WeakPtr<LanguageClient> m_language_client;
     WeakPtr<LanguageClient> m_language_client;

+ 11 - 2
Userland/DevTools/HackStudio/LanguageServers/Cpp/AutoCompleteEngine.cpp

@@ -26,11 +26,20 @@
 
 
 #include "AutoCompleteEngine.h"
 #include "AutoCompleteEngine.h"
 
 
-AutoCompleteEngine::AutoCompleteEngine(const FileDB& filedb)
-    : m_filedb(filedb)
+namespace LanguageServers::Cpp {
+
+AutoCompleteEngine::AutoCompleteEngine(ClientConnection& connection, const FileDB& filedb)
+    : m_connection(connection)
+    , m_filedb(filedb)
 {
 {
 }
 }
 
 
 AutoCompleteEngine::~AutoCompleteEngine()
 AutoCompleteEngine::~AutoCompleteEngine()
 {
 {
 }
 }
+void AutoCompleteEngine::set_declarations_of_document(const String& filename, Vector<GUI::AutocompleteProvider::Declaration>&& declarations)
+{
+    VERIFY(set_declarations_of_document_callback);
+    set_declarations_of_document_callback(m_connection, filename, move(declarations));
+}
+}

+ 11 - 1
Userland/DevTools/HackStudio/LanguageServers/Cpp/AutoCompleteEngine.h

@@ -31,9 +31,13 @@
 #include <LibGUI/AutocompleteProvider.h>
 #include <LibGUI/AutocompleteProvider.h>
 #include <LibGUI/TextPosition.h>
 #include <LibGUI/TextPosition.h>
 
 
+namespace LanguageServers::Cpp {
+
+class ClientConnection;
+
 class AutoCompleteEngine {
 class AutoCompleteEngine {
 public:
 public:
-    AutoCompleteEngine(const FileDB& filedb);
+    AutoCompleteEngine(ClientConnection&, const FileDB& filedb);
     virtual ~AutoCompleteEngine();
     virtual ~AutoCompleteEngine();
 
 
     virtual Vector<GUI::AutocompleteProvider::Entry> get_suggestions(const String& file, const GUI::TextPosition& autocomplete_position) = 0;
     virtual Vector<GUI::AutocompleteProvider::Entry> get_suggestions(const String& file, const GUI::TextPosition& autocomplete_position) = 0;
@@ -44,9 +48,15 @@ public:
 
 
     virtual Optional<GUI::AutocompleteProvider::ProjectLocation> find_declaration_of(const String&, const GUI::TextPosition&) { return {}; };
     virtual Optional<GUI::AutocompleteProvider::ProjectLocation> find_declaration_of(const String&, const GUI::TextPosition&) { return {}; };
 
 
+public:
+    Function<void(ClientConnection&, String, Vector<GUI::AutocompleteProvider::Declaration>)> set_declarations_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>&&);
 
 
 private:
 private:
+    ClientConnection& m_connection;
     const FileDB& m_filedb;
     const FileDB& m_filedb;
 };
 };
+}

+ 9 - 3
Userland/DevTools/HackStudio/LanguageServers/Cpp/ClientConnection.cpp

@@ -40,7 +40,8 @@ ClientConnection::ClientConnection(NonnullRefPtr<Core::LocalSocket> socket, int
     : IPC::ClientConnection<LanguageClientEndpoint, LanguageServerEndpoint>(*this, move(socket), client_id)
     : IPC::ClientConnection<LanguageClientEndpoint, LanguageServerEndpoint>(*this, move(socket), client_id)
 {
 {
     s_connections.set(client_id, *this);
     s_connections.set(client_id, *this);
-    m_autocomplete_engine = make<ParserAutoComplete>(m_filedb);
+    m_autocomplete_engine = make<ParserAutoComplete>(*this, m_filedb);
+    m_autocomplete_engine->set_declarations_of_document_callback = &ClientConnection::set_declarations_of_document_callback;
 }
 }
 
 
 ClientConnection::~ClientConnection()
 ClientConnection::~ClientConnection()
@@ -132,9 +133,9 @@ void ClientConnection::handle(const Messages::LanguageServer::SetAutoCompleteMod
     dbgln("SetAutoCompleteMode: {}", message.mode());
     dbgln("SetAutoCompleteMode: {}", message.mode());
 #endif
 #endif
     if (message.mode() == "Parser")
     if (message.mode() == "Parser")
-        m_autocomplete_engine = make<ParserAutoComplete>(m_filedb);
+        m_autocomplete_engine = make<ParserAutoComplete>(*this, m_filedb);
     else
     else
-        m_autocomplete_engine = make<LexerAutoComplete>(m_filedb);
+        m_autocomplete_engine = make<LexerAutoComplete>(*this, m_filedb);
 }
 }
 
 
 void ClientConnection::handle(const Messages::LanguageServer::FindDeclaration& message)
 void ClientConnection::handle(const Messages::LanguageServer::FindDeclaration& message)
@@ -156,4 +157,9 @@ void ClientConnection::handle(const Messages::LanguageServer::FindDeclaration& m
     post_message(Messages::LanguageClient::DeclarationLocation(GUI::AutocompleteProvider::ProjectLocation { location.value().file, location.value().line, location.value().column }));
     post_message(Messages::LanguageClient::DeclarationLocation(GUI::AutocompleteProvider::ProjectLocation { location.value().file, location.value().line, location.value().column }));
 }
 }
 
 
+void ClientConnection::set_declarations_of_document_callback(ClientConnection& instance, const String& filename, Vector<GUI::AutocompleteProvider::Declaration>&& declarations)
+{
+    instance.post_message(Messages::LanguageClient::DeclarationsInDocument(filename, move(declarations)));
+}
+
 }
 }

+ 2 - 0
Userland/DevTools/HackStudio/LanguageServers/Cpp/ClientConnection.h

@@ -59,6 +59,8 @@ private:
     virtual void handle(const Messages::LanguageServer::SetAutoCompleteMode&) override;
     virtual void handle(const Messages::LanguageServer::SetAutoCompleteMode&) override;
     virtual void handle(const Messages::LanguageServer::FindDeclaration&) override;
     virtual void handle(const Messages::LanguageServer::FindDeclaration&) override;
 
 
+    static void set_declarations_of_document_callback(ClientConnection&, const String&, Vector<GUI::AutocompleteProvider::Declaration>&&);
+
     FileDB m_filedb;
     FileDB m_filedb;
     OwnPtr<AutoCompleteEngine> m_autocomplete_engine;
     OwnPtr<AutoCompleteEngine> m_autocomplete_engine;
 };
 };

+ 2 - 2
Userland/DevTools/HackStudio/LanguageServers/Cpp/LexerAutoComplete.cpp

@@ -31,8 +31,8 @@
 
 
 namespace LanguageServers::Cpp {
 namespace LanguageServers::Cpp {
 
 
-LexerAutoComplete::LexerAutoComplete(const FileDB& filedb)
-    : AutoCompleteEngine(filedb)
+LexerAutoComplete::LexerAutoComplete(ClientConnection& connection, const FileDB& filedb)
+    : AutoCompleteEngine(connection, filedb)
 {
 {
 }
 }
 
 

+ 1 - 1
Userland/DevTools/HackStudio/LanguageServers/Cpp/LexerAutoComplete.h

@@ -39,7 +39,7 @@ using namespace ::Cpp;
 
 
 class LexerAutoComplete : public AutoCompleteEngine {
 class LexerAutoComplete : public AutoCompleteEngine {
 public:
 public:
-    LexerAutoComplete(const FileDB& filedb);
+    LexerAutoComplete(ClientConnection&, const FileDB& filedb);
 
 
     virtual Vector<GUI::AutocompleteProvider::Entry> get_suggestions(const String& file, const GUI::TextPosition& autocomplete_position) override;
     virtual Vector<GUI::AutocompleteProvider::Entry> get_suggestions(const String& file, const GUI::TextPosition& autocomplete_position) override;
 
 

+ 31 - 4
Userland/DevTools/HackStudio/LanguageServers/Cpp/ParserAutoComplete.cpp

@@ -27,6 +27,7 @@
 #include "ParserAutoComplete.h"
 #include "ParserAutoComplete.h"
 #include <AK/Assertions.h>
 #include <AK/Assertions.h>
 #include <AK/HashTable.h>
 #include <AK/HashTable.h>
+#include <DevTools/HackStudio/LanguageServers/Cpp/ClientConnection.h>
 #include <LibCpp/AST.h>
 #include <LibCpp/AST.h>
 #include <LibCpp/Lexer.h>
 #include <LibCpp/Lexer.h>
 #include <LibCpp/Parser.h>
 #include <LibCpp/Parser.h>
@@ -35,8 +36,8 @@
 
 
 namespace LanguageServers::Cpp {
 namespace LanguageServers::Cpp {
 
 
-ParserAutoComplete::ParserAutoComplete(const FileDB& filedb)
-    : AutoCompleteEngine(filedb)
+ParserAutoComplete::ParserAutoComplete(ClientConnection& connection, const FileDB& filedb)
+    : AutoCompleteEngine(connection, filedb)
 {
 {
 }
 }
 
 
@@ -71,6 +72,9 @@ OwnPtr<ParserAutoComplete::DocumentData> ParserAutoComplete::create_document_dat
 #ifdef CPP_LANGUAGE_SERVER_DEBUG
 #ifdef CPP_LANGUAGE_SERVER_DEBUG
     root->dump(0);
     root->dump(0);
 #endif
 #endif
+
+    update_declared_symbols(*document_data);
+
     return move(document_data);
     return move(document_data);
 }
 }
 
 
@@ -79,8 +83,9 @@ void ParserAutoComplete::set_document_data(const String& file, OwnPtr<DocumentDa
     m_documents.set(filedb().to_absolute_path(file), move(data));
     m_documents.set(filedb().to_absolute_path(file), move(data));
 }
 }
 
 
-ParserAutoComplete::DocumentData::DocumentData(String&& _text, const String& filename)
-    : text(move(_text))
+ParserAutoComplete::DocumentData::DocumentData(String&& _text, const String& _filename)
+    : filename(_filename)
+    , text(move(_text))
     , preprocessor(text.view())
     , preprocessor(text.view())
     , parser(preprocessor.process().view(), filename)
     , parser(preprocessor.process().view(), filename)
 {
 {
@@ -360,4 +365,26 @@ RefPtr<Declaration> ParserAutoComplete::find_declaration_of(const DocumentData&
     return {};
     return {};
 }
 }
 
 
+void ParserAutoComplete::update_declared_symbols(const DocumentData& document)
+{
+    Vector<GUI::AutocompleteProvider::Declaration> declarations;
+    for (auto& decl : document.parser.root_node()->declarations()) {
+        declarations.append({ decl.name(), { document.filename, decl.start().line, decl.start().column }, type_of_declaration(decl) });
+    }
+    set_declarations_of_document(document.filename, move(declarations));
+}
+
+GUI::AutocompleteProvider::DeclarationType ParserAutoComplete::type_of_declaration(const Declaration& decl)
+{
+    if (decl.is_struct())
+        return GUI::AutocompleteProvider::DeclarationType::Struct;
+    if (decl.is_class())
+        return GUI::AutocompleteProvider::DeclarationType::Class;
+    if (decl.is_function())
+        return GUI::AutocompleteProvider::DeclarationType::Function;
+    if (decl.is_variable_declaration())
+        return GUI::AutocompleteProvider::DeclarationType::Variable;
+    return GUI::AutocompleteProvider::DeclarationType::Variable;
+}
+
 }
 }

+ 5 - 1
Userland/DevTools/HackStudio/LanguageServers/Cpp/ParserAutoComplete.h

@@ -28,6 +28,7 @@
 
 
 #include "AutoCompleteEngine.h"
 #include "AutoCompleteEngine.h"
 #include "FileDB.h"
 #include "FileDB.h"
+#include <AK/Function.h>
 #include <AK/String.h>
 #include <AK/String.h>
 #include <AK/Vector.h>
 #include <AK/Vector.h>
 #include <DevTools/HackStudio/AutoCompleteResponse.h>
 #include <DevTools/HackStudio/AutoCompleteResponse.h>
@@ -42,7 +43,7 @@ using namespace ::Cpp;
 
 
 class ParserAutoComplete : public AutoCompleteEngine {
 class ParserAutoComplete : public AutoCompleteEngine {
 public:
 public:
-    ParserAutoComplete(const FileDB& filedb);
+    ParserAutoComplete(ClientConnection&, const FileDB& filedb);
 
 
     virtual Vector<GUI::AutocompleteProvider::Entry> get_suggestions(const String& file, const GUI::TextPosition& autocomplete_position) override;
     virtual Vector<GUI::AutocompleteProvider::Entry> get_suggestions(const String& file, const GUI::TextPosition& autocomplete_position) override;
     virtual void on_edit(const String& file) override;
     virtual void on_edit(const String& file) override;
@@ -52,6 +53,7 @@ public:
 private:
 private:
     struct DocumentData {
     struct DocumentData {
         DocumentData(String&& text, const String& filename);
         DocumentData(String&& text, const String& filename);
+        String filename;
         String text;
         String text;
         Preprocessor preprocessor;
         Preprocessor preprocessor;
         Parser parser;
         Parser parser;
@@ -80,6 +82,8 @@ private:
 
 
     OwnPtr<DocumentData> create_document_data_for(const String& file);
     OwnPtr<DocumentData> create_document_data_for(const String& file);
     String document_path_from_include_path(const StringView& include_path) const;
     String document_path_from_include_path(const StringView& include_path) const;
+    void update_declared_symbols(const DocumentData&);
+    GUI::AutocompleteProvider::DeclarationType type_of_declaration(const Declaration&);
 
 
     HashMap<String, OwnPtr<DocumentData>> m_documents;
     HashMap<String, OwnPtr<DocumentData>> m_documents;
 };
 };

+ 1 - 0
Userland/DevTools/HackStudio/LanguageServers/LanguageClient.ipc

@@ -2,4 +2,5 @@ endpoint LanguageClient = 8002
 {
 {
     AutoCompleteSuggestions(Vector<GUI::AutocompleteProvider::Entry> suggestions) =|
     AutoCompleteSuggestions(Vector<GUI::AutocompleteProvider::Entry> suggestions) =|
     DeclarationLocation(GUI::AutocompleteProvider::ProjectLocation location) =|
     DeclarationLocation(GUI::AutocompleteProvider::ProjectLocation location) =|
+    DeclarationsInDocument(String filename, Vector<GUI::AutocompleteProvider::Declaration> declarations) =|
 }
 }

+ 8 - 4
Userland/Libraries/LibCpp/AST.h

@@ -137,13 +137,19 @@ public:
     virtual bool is_variable_declaration() const { return false; }
     virtual bool is_variable_declaration() const { return false; }
     virtual bool is_parameter() const { return false; }
     virtual bool is_parameter() const { return false; }
     virtual bool is_struct_or_class() const { return false; }
     virtual bool is_struct_or_class() const { return false; }
+    virtual bool is_struct() const { return false; }
+    virtual bool is_class() const { return false; }
     virtual bool is_function() const { return false; }
     virtual bool is_function() const { return false; }
+    const StringView& name() const { return m_name; }
+
+    StringView m_name;
 
 
 protected:
 protected:
     Declaration(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
     Declaration(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
         : Statement(parent, start, end, filename)
         : Statement(parent, start, end, filename)
     {
     {
     }
     }
+
 };
 };
 
 
 class InvalidDeclaration : public Declaration {
 class InvalidDeclaration : public Declaration {
@@ -163,7 +169,6 @@ public:
     virtual const char* class_name() const override { return "FunctionDeclaration"; }
     virtual const char* class_name() const override { return "FunctionDeclaration"; }
     virtual void dump(size_t indent) const override;
     virtual void dump(size_t indent) const override;
     virtual bool is_function() const override { return true; }
     virtual bool is_function() const override { return true; }
-    const StringView& name() const { return m_name; }
     RefPtr<FunctionDefinition> definition() { return m_definition; }
     RefPtr<FunctionDefinition> definition() { return m_definition; }
 
 
     FunctionDeclaration(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
     FunctionDeclaration(ASTNode* parent, Optional<Position> start, Optional<Position> end, const String& filename)
@@ -173,7 +178,6 @@ public:
 
 
     virtual NonnullRefPtrVector<Declaration> declarations() const override;
     virtual NonnullRefPtrVector<Declaration> declarations() const override;
 
 
-    StringView m_name;
     RefPtr<Type> m_return_type;
     RefPtr<Type> m_return_type;
     NonnullRefPtrVector<Parameter> m_parameters;
     NonnullRefPtrVector<Parameter> m_parameters;
     RefPtr<FunctionDefinition> m_definition;
     RefPtr<FunctionDefinition> m_definition;
@@ -184,7 +188,6 @@ public:
     virtual ~VariableOrParameterDeclaration() override = default;
     virtual ~VariableOrParameterDeclaration() override = default;
     virtual bool is_variable_or_parameter_declaration() const override { return true; }
     virtual bool is_variable_or_parameter_declaration() const override { return true; }
 
 
-    StringView m_name;
     RefPtr<Type> m_type;
     RefPtr<Type> m_type;
 
 
 protected:
 protected:
@@ -492,6 +495,8 @@ public:
     virtual const char* class_name() const override { return "StructOrClassDeclaration"; }
     virtual const char* class_name() const override { return "StructOrClassDeclaration"; }
     virtual void dump(size_t indent) const override;
     virtual void dump(size_t indent) const override;
     virtual bool is_struct_or_class() const override { return true; }
     virtual bool is_struct_or_class() const override { return true; }
+    virtual bool is_struct() const override { return m_type == Type::Struct; }
+    virtual bool is_class() const override { return m_type == Type::Class; }
 
 
     enum class Type {
     enum class Type {
         Struct,
         Struct,
@@ -505,7 +510,6 @@ public:
     }
     }
 
 
     StructOrClassDeclaration::Type m_type;
     StructOrClassDeclaration::Type m_type;
-    StringView m_name;
     NonnullRefPtrVector<MemberDeclaration> m_members;
     NonnullRefPtrVector<MemberDeclaration> m_members;
 };
 };