aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlls/qqmllscompletion_p.h
blob: a31d3daebcffd4e3134b18d35599ce495fabb67c (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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
// Copyright (C) 2024 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only

#ifndef QQMLLSCOMPLETION_H
#define QQMLLSCOMPLETION_H

//
//  W A R N I N G
//  -------------
//
// This file is not part of the Qt API.  It exists purely as an
// implementation detail.  This header file may change from version to
// version without notice, or even be removed.
//
// We mean it.
//

#include "qqmlcompletioncontextstrings_p.h"
#include "qqmllsutils_p.h"
#include "qqmllsplugin_p.h"

#include <QtLanguageServer/private/qlanguageserverspectypes_p.h>
#include <QtQmlDom/private/qqmldomexternalitems_p.h>
#include <QtQmlDom/private/qqmldomtop_p.h>
#include <QtCore/private/qduplicatetracker_p.h>
#include <QtCore/private/qfactoryloader_p.h>
#include <QtCore/qpluginloader.h>
#include <QtCore/qxpfunctional.h>

QT_BEGIN_NAMESPACE

Q_DECLARE_LOGGING_CATEGORY(QQmlLSCompletionLog)

enum QQmlLSUtilsAppendOption { AppendSemicolon, AppendNothing };

class QQmlLSCompletion
{
    using DomItem = QQmlJS::Dom::DomItem;
public:
    QQmlLSCompletion(const QFactoryLoader &pluginLoader);

    using CompletionItem = QLspSpecification::CompletionItem;
    using BackInsertIterator = std::back_insert_iterator<QList<CompletionItem>>;
    QList<CompletionItem> completions(const DomItem &currentItem,
                                      const CompletionContextStrings &ctx) const;

    static CompletionItem makeSnippet(QUtf8StringView qualifier, QUtf8StringView label,
                                      QUtf8StringView insertText);

    static CompletionItem makeSnippet(QUtf8StringView label, QUtf8StringView insertText);

private:
    struct QQmlLSCompletionPosition
    {
        DomItem itemAtPosition;
        CompletionContextStrings cursorPosition;
        qsizetype offset() const { return cursorPosition.offset(); }
    };

    void collectCompletions(const DomItem &currentItem, const CompletionContextStrings &ctx,
                            BackInsertIterator result) const;

    bool betweenLocations(QQmlJS::SourceLocation left, const QQmlLSCompletionPosition &positionInfo,
                          QQmlJS::SourceLocation right) const;
    bool afterLocation(QQmlJS::SourceLocation left,
                       const QQmlLSCompletionPosition &positionInfo) const;
    bool beforeLocation(const QQmlLSCompletionPosition &ctx, QQmlJS::SourceLocation right) const;
    bool ctxBeforeStatement(const QQmlLSCompletionPosition &positionInfo,
                            const DomItem &parentForContext,
                            QQmlJS::Dom::FileLocationRegion firstRegion) const;
    bool isCaseOrDefaultBeforeCtx(const DomItem &currentClause,
                                  const QQmlLSCompletionPosition &positionInfo,
                                  QQmlJS::Dom::FileLocationRegion keywordRegion) const;
    DomItem previousCaseOfCaseBlock(const DomItem &parentForContext,
                                    const QQmlLSCompletionPosition &positionInfo) const;

    void idsCompletions(const DomItem &component, BackInsertIterator it) const;

    void suggestReachableTypes(const DomItem &context,
                               QQmlJS::Dom::LocalSymbolsTypes typeCompletionType,
                               QLspSpecification::CompletionItemKind kind,
                               BackInsertIterator it) const;

    void suggestJSStatementCompletion(const DomItem &currentItem, BackInsertIterator it) const;
    void suggestCaseAndDefaultStatementCompletion(BackInsertIterator it) const;
    void suggestVariableDeclarationStatementCompletion(
            BackInsertIterator it, QQmlLSUtilsAppendOption option = AppendSemicolon) const;

    void suggestJSExpressionCompletion(const DomItem &context, BackInsertIterator it) const;

    void suggestBindingCompletion(const DomItem &itemAtPosition, BackInsertIterator it) const;

    void insideImportCompletionHelper(const DomItem &file,
                                      const QQmlLSCompletionPosition &positionInfo,
                                      BackInsertIterator it) const;

    void jsIdentifierCompletion(const QQmlJSScope::ConstPtr &scope,
                                QDuplicateTracker<QString> *usedNames, BackInsertIterator it) const;

    void methodCompletion(const QQmlJSScope::ConstPtr &scope, QDuplicateTracker<QString> *usedNames,
                          BackInsertIterator it) const;
    void propertyCompletion(const QQmlJSScope::ConstPtr &scope,
                            QDuplicateTracker<QString> *usedNames, BackInsertIterator it) const;
    void enumerationCompletion(const QQmlJSScope::ConstPtr &scope,
                               QDuplicateTracker<QString> *usedNames, BackInsertIterator it) const;
    void enumerationValueCompletionHelper(const QStringList &enumeratorKeys,
                                          BackInsertIterator it) const;

    void enumerationValueCompletion(const QQmlJSScope::ConstPtr &scope,
                                    const QString &enumeratorName, BackInsertIterator it) const;

    static bool cursorInFrontOfItem(const DomItem &parentForContext,
                                    const QQmlLSCompletionPosition &positionInfo);
    static bool cursorAfterColon(const DomItem &currentItem,
                                 const QQmlLSCompletionPosition &positionInfo);
    void insidePragmaCompletion(QQmlJS::Dom::DomItem currentItem,
                                const QQmlLSCompletionPosition &positionInfo,
                                BackInsertIterator it) const;
    void insideQmlObjectCompletion(const DomItem &parentForContext,
                                   const QQmlLSCompletionPosition &positionInfo,
                                   BackInsertIterator it) const;
    void insidePropertyDefinitionCompletion(const DomItem &currentItem,
                                            const QQmlLSCompletionPosition &positionInfo,
                                            BackInsertIterator it) const;
    void insideBindingCompletion(const DomItem &currentItem,
                                 const QQmlLSCompletionPosition &positionInfo,
                                 BackInsertIterator it) const;
    void insideImportCompletion(const DomItem &currentItem,
                                const QQmlLSCompletionPosition &positionInfo,
                                BackInsertIterator it) const;
    void insideQmlFileCompletion(const DomItem &currentItem,
                                 const QQmlLSCompletionPosition &positionInfo,
                                 BackInsertIterator it) const;
    void suggestContinueAndBreakStatementIfNeeded(const DomItem &itemAtPosition,
                                                  BackInsertIterator it) const;
    void insideScriptLiteralCompletion(const DomItem &currentItem,
                                       const QQmlLSCompletionPosition &positionInfo,
                                       BackInsertIterator it) const;
    void insideCallExpression(const DomItem &currentItem,
                              const QQmlLSCompletionPosition &positionInfo,
                              BackInsertIterator it) const;
    void insideIfStatement(const DomItem &currentItem, const QQmlLSCompletionPosition &positionInfo,
                           BackInsertIterator it) const;
    void insideReturnStatement(const DomItem &currentItem,
                               const QQmlLSCompletionPosition &positionInfo,
                               BackInsertIterator it) const;
    void insideWhileStatement(const DomItem &currentItem,
                              const QQmlLSCompletionPosition &positionInfo,
                              BackInsertIterator it) const;
    void insideDoWhileStatement(const DomItem &parentForContext,
                                const QQmlLSCompletionPosition &positionInfo,
                                BackInsertIterator it) const;
    void insideForStatementCompletion(const DomItem &parentForContext,
                                      const QQmlLSCompletionPosition &positionInfo,
                                      BackInsertIterator it) const;
    void insideForEachStatement(const DomItem &parentForContext,
                                const QQmlLSCompletionPosition &positionInfo,
                                BackInsertIterator it) const;
    void insideSwitchStatement(const DomItem &parentForContext,
                               const QQmlLSCompletionPosition positionInfo,
                               BackInsertIterator it) const;
    void insideCaseClause(const DomItem &parentForContext,
                          const QQmlLSCompletionPosition &positionInfo,
                          BackInsertIterator it) const;
    void insideCaseBlock(const DomItem &parentForContext,
                         const QQmlLSCompletionPosition &positionInfo, BackInsertIterator it) const;
    void insideDefaultClause(const DomItem &parentForContext,
                             const QQmlLSCompletionPosition &positionInfo,
                             BackInsertIterator it) const;
    void insideBinaryExpressionCompletion(const DomItem &parentForContext,
                                          const QQmlLSCompletionPosition &positionInfo,
                                          BackInsertIterator it) const;
    void insideScriptPattern(const DomItem &parentForContext,
                             const QQmlLSCompletionPosition &positionInfo,
                             BackInsertIterator it) const;
    void insideVariableDeclarationEntry(const DomItem &parentForContext,
                                        const QQmlLSCompletionPosition &positionInfo,
                                        BackInsertIterator it) const;
    void insideThrowStatement(const DomItem &parentForContext,
                              const QQmlLSCompletionPosition &positionInfo,
                              BackInsertIterator it) const;
    void insideLabelledStatement(const DomItem &parentForContext,
                                 const QQmlLSCompletionPosition &positionInfo,
                                 BackInsertIterator it) const;
    void insideContinueStatement(const DomItem &parentForContext,
                                 const QQmlLSCompletionPosition &positionInfo,
                                 BackInsertIterator it) const;
    void insideBreakStatement(const DomItem &parentForContext,
                              const QQmlLSCompletionPosition &positionInfo,
                              BackInsertIterator it) const;
    void insideConditionalExpression(const DomItem &parentForContext,
                                     const QQmlLSCompletionPosition &positionInfo,
                                     BackInsertIterator it) const;
    void insideUnaryExpression(const DomItem &parentForContext,
                               const QQmlLSCompletionPosition &positionInfo,
                               BackInsertIterator it) const;
    void insidePostExpression(const DomItem &parentForContext,
                              const QQmlLSCompletionPosition &positionInfo,
                              BackInsertIterator it) const;
    void insideParenthesizedExpression(const DomItem &parentForContext,
                                       const QQmlLSCompletionPosition &positionInfo,
                                       BackInsertIterator it) const;
    void signalHandlerCompletion(const QQmlJSScope::ConstPtr &scope,
                                 QDuplicateTracker<QString> *usedNames,
                                 BackInsertIterator it) const;

    void suggestSnippetsForLeftHandSideOfBinding(const DomItem &items,
                                                 BackInsertIterator result) const;

    void suggestSnippetsForRightHandSideOfBinding(const DomItem &items,
                                                  BackInsertIterator result) const;

private:
    using CompletionFromPluginFunction = void(QQmlLSCompletionPlugin *plugin,
                                              BackInsertIterator result);
    void collectFromPlugins(const qxp::function_ref<CompletionFromPluginFunction> f,
                            BackInsertIterator result) const;

    QStringList m_loadPaths;

    std::vector<std::unique_ptr<QQmlLSCompletionPlugin>> m_plugins;
};

QT_END_NAMESPACE

#endif // QQMLLSCOMPLETION_H