aboutsummaryrefslogtreecommitdiffstats
path: root/src/shared/lsp/completion.h
blob: 665b5a5ae9f57a652654f93057423845f81ea92a (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
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
// Copyright (C) 2018 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0

#pragma once

#include "jsonrpcmessages.h"
#include "languagefeatures.h"

namespace lsp {

class LANGUAGESERVERPROTOCOL_EXPORT CompletionParams : public TextDocumentPositionParams
{
public:
    using TextDocumentPositionParams::TextDocumentPositionParams;

    enum CompletionTriggerKind {
        /**
         * Completion was triggered by typing an identifier (24x7 code
         * complete), manual invocation (e.g Ctrl+Space) or via API.
         */
        Invoked = 1,
        /**
         * Completion was triggered by a trigger character specified by
         * the `triggerCharacters` properties of the `CompletionRegistrationOptions`.
         */
        TriggerCharacter = 2,
        /// Completion was re-triggered as the current completion list is incomplete.
        TriggerForIncompleteCompletions = 3
    };

    class CompletionContext : public JsonObject
    {
    public:
        using JsonObject::JsonObject;

        /// How the completion was triggered.
        CompletionTriggerKind triggerKind() const
        { return CompletionTriggerKind(typedValue<int>(triggerKindKey)); }
        void setTriggerKind(CompletionTriggerKind triggerKind)
        { insert(triggerKindKey, triggerKind); }

        /**
         * The trigger character (a single character) that has trigger code complete.
         * Is undefined if `triggerKind !== CompletionTriggerKind.TriggerCharacter`
         */
        std::optional<QString> triggerCharacter() const
        { return optionalValue<QString>(triggerCharacterKey); }
        void setTriggerCharacter(const QString &triggerCharacter)
        { insert(triggerCharacterKey, triggerCharacter); }
        void clearTriggerCharacter() { remove(triggerCharacterKey); }

        bool isValid() const override { return contains(triggerKindKey); }
    };

    /**
     * The completion context. This is only available it the client specifies
     * to send this using `ClientCapabilities.textDocument.completion.contextSupport === true`
     */
    std::optional<CompletionContext> context() const
    { return optionalValue<CompletionContext>(contextKey); }
    void setContext(const CompletionContext &context)
    { insert(contextKey, context); }
    void clearContext() { remove(contextKey); }

    // clangd extension
    void setLimit(int limit) { insert(limitKey, limit); }
};

class LANGUAGESERVERPROTOCOL_EXPORT CompletionItem : public JsonObject
{
public:
    using JsonObject::JsonObject;

    /**
     * The label of this completion item. By default also the text that is inserted when selecting
     * this completion.
     */
    QString label() const { return typedValue<QString>(labelKey); }
    void setLabel(const QString &label) { insert(labelKey, label); }

    /// The kind of this completion item. Based of the kind an icon is chosen by the editor.
    std::optional<int> kind() const { return optionalValue<int>(kindKey); }
    void setKind(int kind) { insert(kindKey, kind); }
    void clearKind() { remove(kindKey); }

    /// A human-readable string with additional information about this item, like type information.
    std::optional<QString> detail() const { return optionalValue<QString>(detailKey); }
    void setDetail(const QString &detail) { insert(detailKey, detail); }
    void clearDetail() { remove(detailKey); }

    /// A human-readable string that represents a doc-comment.
    std::optional<MarkupOrString> documentation() const;
    void setDocumentation(const MarkupOrString &documentation)
    { insert(documentationKey, documentation.toJson()); }
    void cleatDocumentation() { remove(documentationKey); }

    /// A string that should be used when comparing this item
    /// with other items. When `falsy` the label is used.
    std::optional<QString> sortText() const { return optionalValue<QString>(sortTextKey); }
    void setSortText(const QString &sortText) { insert(sortTextKey, sortText); }
    void clearSortText() { remove(sortTextKey); }

    /// A string that should be used when filtering a set of
    /// completion items. When `falsy` the label is used.
    std::optional<QString> filterText() const { return optionalValue<QString>(filterTextKey); }
    void setFilterText(const QString &filterText) { insert(filterTextKey, filterText); }
    void clearFilterText() { remove(filterTextKey); }

    /**
     * A string that should be inserted into a document when selecting
     * this completion. When `falsy` the label is used.
     *
     * The `insertText` is subject to interpretation by the client side.
     * Some tools might not take the string literally. For example
     * VS Code when code complete is requested in this example `con<cursor position>`
     * and a completion item with an `insertText` of `console` is provided it
     * will only insert `sole`. Therefore it is recommended to use `textEdit` instead
     * since it avoids additional client side interpretation.
     *
     * @deprecated Use textEdit instead.
     */
    std::optional<QString> insertText() const { return optionalValue<QString>(insertTextKey); }
    void setInsertText(const QString &insertText) { insert(insertTextKey, insertText); }
    void clearInsertText() { remove(insertTextKey); }

    enum InsertTextFormat {
        /// The primary text to be inserted is treated as a plain string.
        PlainText = 1,

        /**
          * The primary text to be inserted is treated as a snippet.
          *
          * A snippet can define tab stops and placeholders with `$1`, `$2`
          * and `${3:foo}`. `$0` defines the final tab stop, it defaults to
          * the end of the snippet. Placeholders with equal identifiers are linked,
          * that is typing in one will update others too.
          */
        Snippet = 2
    };

    /// The format of the insert text. The format applies to both the `insertText` property
    /// and the `newText` property of a provided `textEdit`.
    std::optional<InsertTextFormat> insertTextFormat() const;
    void setInsertTextFormat(const InsertTextFormat &insertTextFormat)
    { insert(insertTextFormatKey, insertTextFormat); }
    void clearInsertTextFormat() { remove(insertTextFormatKey); }

    /**
     * An edit which is applied to a document when selecting this completion. When an edit is provided the value of
     * `insertText` is ignored.
     *
     * *Note:* The range of the edit must be a single line range and it must contain the position at which completion
     * has been requested.
     */
    std::optional<TextEdit> textEdit() const { return optionalValue<TextEdit>(textEditKey); }
    void setTextEdit(const TextEdit &textEdit) { insert(textEditKey, textEdit); }
    void clearTextEdit() { remove(textEditKey); }

    /**
     * An optional array of additional text edits that are applied when
     * selecting this completion. Edits must not overlap with the main edit
     * nor with themselves.
     */
    std::optional<QList<TextEdit>> additionalTextEdits() const
    { return optionalArray<TextEdit>(additionalTextEditsKey); }
    void setAdditionalTextEdits(const QList<TextEdit> &additionalTextEdits)
    { insertArray(additionalTextEditsKey, additionalTextEdits); }
    void clearAdditionalTextEdits() { remove(additionalTextEditsKey); }

    /**
     * An optional set of characters that when pressed while this completion is active will accept it first and
     * then type that character. *Note* that all commit characters should have `length=1` and that superfluous
     * characters will be ignored.
     */
    std::optional<QList<QString>> commitCharacters() const
    { return optionalArray<QString>(commitCharactersKey); }
    void setCommitCharacters(const QList<QString> &commitCharacters)
    { insertArray(commitCharactersKey, commitCharacters); }
    void clearCommitCharacters() { remove(commitCharactersKey); }

    /**
     * An optional command that is executed *after* inserting this completion. *Note* that
     * additional modifications to the current document should be described with the
     * additionalTextEdits-property.
     */
    std::optional<Command> command() const { return optionalValue<Command>(commandKey); }
    void setCommand(const Command &command) { insert(commandKey, command); }
    void clearCommand() { remove(commandKey); }

    /**
     * An data entry field that is preserved on a completion item between
     * a completion and a completion resolve request.
     */
    std::optional<QJsonValue> data() const { return optionalValue<QJsonValue>(dataKey); }
    void setData(const QJsonValue &data) { insert(dataKey, data); }
    void clearData() { remove(dataKey); }

    /**
     * Completion item tags are extra annotations that tweak the rendering of a
     * completion item.
     * @since 3.15.0
     */
    enum CompletionItemTag {
        Deprecated = 1,
    };

    /**
     * Tags for this completion item.
     * @since 3.15.0
     */
    std::optional<QList<CompletionItemTag>> tags() const;

    /**
      * Indicates if this item is deprecated.
      * @deprecated Use `tags` instead if supported.
      */
    std::optional<bool> deprecated() const { return optionalValue<bool>(deprecatedKey); }

    bool isValid() const override { return contains(labelKey); }
};

class LANGUAGESERVERPROTOCOL_EXPORT CompletionList : public JsonObject
{
public:
    using JsonObject::JsonObject;

    /**
     * This list it not complete. Further typing should result in recomputing
     * this list.
     */
    bool isIncomplete() const { return typedValue<bool>(isIncompleteKey); }
    void setIsIncomplete(bool isIncomplete) { insert(isIncompleteKey, isIncomplete); }

    /// The completion items.
    std::optional<QList<CompletionItem>> items() const { return array<CompletionItem>(itemsKey); }
    void setItems(const QList<CompletionItem> &items) { insertArray(itemsKey, items); }
    void clearItems() { remove(itemsKey); }

    bool isValid() const override { return contains(isIncompleteKey); }
};

/// The result of a completion is CompletionItem[] | CompletionList | null
class LANGUAGESERVERPROTOCOL_EXPORT CompletionResult
        : public std::variant<QList<CompletionItem>, CompletionList, std::nullptr_t>
{
public:
    using variant::variant;
    explicit CompletionResult(const QJsonValue &value);
};

class LANGUAGESERVERPROTOCOL_EXPORT CompletionRequest : public Request<
        CompletionResult, std::nullptr_t, CompletionParams>
{
public:
    explicit CompletionRequest(const CompletionParams &params);
    using Request::Request;
    constexpr static const char methodName[] = "textDocument/completion";
};

class LANGUAGESERVERPROTOCOL_EXPORT CompletionItemResolveRequest : public Request<
        CompletionItem, std::nullptr_t, CompletionItem>
{
public:
    explicit CompletionItemResolveRequest(const CompletionItem &params);
    using Request::Request;
    constexpr static const char methodName[] = "completionItem/resolve";
};

} // namespace LanguageClient