summaryrefslogtreecommitdiff
path: root/Userland/DevTools/HackStudio/LanguageServers/Cpp/ParserAutoComplete.h
blob: c3b735d94822a6a26b30a066fa57ac0bf88089c8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
/*
 * Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
 *
 * SPDX-License-Identifier: BSD-2-Clause
 */

#pragma once

#include <AK/Function.h>
#include <AK/String.h>
#include <AK/Vector.h>
#include <DevTools/HackStudio/AutoCompleteResponse.h>
#include <DevTools/HackStudio/LanguageServers/AutoCompleteEngine.h>
#include <DevTools/HackStudio/LanguageServers/FileDB.h>
#include <LibCpp/AST.h>
#include <LibCpp/Parser.h>
#include <LibCpp/Preprocessor.h>
#include <LibGUI/TextPosition.h>

namespace LanguageServers::Cpp {

using namespace ::Cpp;

class ParserAutoComplete : public AutoCompleteEngine {
public:
    ParserAutoComplete(const FileDB& filedb);

    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 file_opened([[maybe_unused]] const String& file) override;
    virtual Optional<GUI::AutocompleteProvider::ProjectLocation> find_declaration_of(const String& filename, const GUI::TextPosition& identifier_position) override;

private:
    struct DocumentData {
        const String& filename() const { return m_filename; }
        const String& text() const { return m_text; }
        const Preprocessor& preprocessor() const
        {
            VERIFY(m_preprocessor);
            return *m_preprocessor;
        }
        Preprocessor& preprocessor()
        {
            VERIFY(m_preprocessor);
            return *m_preprocessor;
        }
        const Parser& parser() const
        {
            VERIFY(m_parser);
            return *m_parser;
        }
        Parser& parser()
        {
            VERIFY(m_parser);
            return *m_parser;
        }

        String m_filename;
        String m_text;
        OwnPtr<Preprocessor> m_preprocessor;
        OwnPtr<Parser> m_parser;

        // FIXME: This HashTable must be re-computed if a declaration from a header file is modified
        HashTable<NonnullRefPtr<Declaration>> m_declarations_from_headers;
    };

    Vector<GUI::AutocompleteProvider::Entry> autocomplete_property(const DocumentData&, const MemberExpression&, const String partial_text) const;
    Vector<GUI::AutocompleteProvider::Entry> autocomplete_name(const DocumentData&, const ASTNode&, const String& partial_text) const;
    String type_of(const DocumentData&, const Expression&) const;
    String type_of_property(const DocumentData&, const Identifier&) const;
    String type_of_variable(const Identifier&) const;
    bool is_property(const ASTNode&) const;
    bool is_empty_property(const DocumentData&, const ASTNode&, const Position& autocomplete_position) const;
    RefPtr<Declaration> find_declaration_of(const DocumentData&, const ASTNode&) const;

    enum class RecurseIntoScopes {
        No,
        Yes
    };
    NonnullRefPtrVector<Declaration> get_available_declarations(const DocumentData&, const ASTNode&, RecurseIntoScopes) const;

    struct PropertyInfo {
        StringView name;
        RefPtr<Type> type;
    };
    Vector<PropertyInfo> properties_of_type(const DocumentData& document, const String& type) const;
    NonnullRefPtrVector<Declaration> get_global_declarations_including_headers(const DocumentData&, RecurseIntoScopes) const;
    NonnullRefPtrVector<Declaration> get_global_declarations(const DocumentData&, RecurseIntoScopes) const;
    NonnullRefPtrVector<Declaration> get_declarations_recursive(const ASTNode&) const;

    const DocumentData* get_document_data(const String& file) const;
    const DocumentData* get_or_create_document_data(const String& file);
    void set_document_data(const String& file, OwnPtr<DocumentData>&& data);

    OwnPtr<DocumentData> create_document_data_for(const String& file);
    String document_path_from_include_path(const StringView& include_path) const;
    void update_declared_symbols(DocumentData&);
    GUI::AutocompleteProvider::DeclarationType type_of_declaration(const Declaration&);
    String scope_of_declaration(const Declaration&) const;
    String scope_of_name_or_identifier(const ASTNode& node) const;
    Optional<GUI::AutocompleteProvider::ProjectLocation> find_preprocessor_definition(const DocumentData&, const GUI::TextPosition&);

    OwnPtr<DocumentData> create_document_data(String&& text, const String& filename);
    Optional<Vector<GUI::AutocompleteProvider::Entry>> autocomplete_property(const DocumentData&, const ASTNode&, Optional<Token> containing_token) const;
    Optional<Vector<GUI::AutocompleteProvider::Entry>> autocomplete_name(const DocumentData&, const ASTNode&, Optional<Token> containing_token) const;

    HashMap<String, OwnPtr<DocumentData>> m_documents;
};

}