aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlls/qqmllsutils_p.h
blob: 0ba58f8294fb90a9810af459ca3e85c9e82a4f5d (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
// Copyright (C) 2023 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 QLANGUAGESERVERUTILS_P_H
#define QLANGUAGESERVERUTILS_P_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 <QtLanguageServer/private/qlanguageserverspectypes_p.h>
#include <QtQmlDom/private/qqmldomexternalitems_p.h>
#include <QtQmlDom/private/qqmldomtop_p.h>
#include <algorithm>
#include <optional>
#include <tuple>
#include <variant>

QT_BEGIN_NAMESPACE

Q_DECLARE_LOGGING_CATEGORY(QQmlLSUtilsLog);

struct QQmlLSUtilsItemLocation
{
    QQmlJS::Dom::DomItem domItem;
    QQmlJS::Dom::FileLocations::Tree fileLocation;
};

struct QQmlLSUtilsTextPosition
{
    int line;
    int character;
};

enum QQmlLSUtilsIdentifierType : char {
    JavaScriptIdentifier,
    PropertyIdentifier,
    PropertyChangedSignalIdentifier,
    PropertyChangedHandlerIdentifier,
    SignalIdentifier,
    SignalHandlerIdentifier,
    MethodIdentifier,
    QmlObjectIdIdentifier,
    SingletonIdentifier,
    EnumeratorIdentifier,
    EnumeratorValueIdentifier,
    AttachedTypeIdentifier,
    GroupedPropertyIdentifier,
    QmlComponentIdentifier,
};

struct QQmlLSUtilsErrorMessage
{
    int code;
    QString message;
};

struct QQmlLSUtilsExpressionType
{
    std::optional<QString> name;
    QQmlJSScope::ConstPtr semanticScope;
    QQmlLSUtilsIdentifierType type;
};

struct QQmlLSUtilsLocation
{
    QString filename;
    QQmlJS::SourceLocation sourceLocation;

    static QQmlLSUtilsLocation from(const QString &fileName, const QString &code, quint32 startLine,
                                    quint32 startCharacter, quint32 length);

    friend bool operator<(const QQmlLSUtilsLocation &a, const QQmlLSUtilsLocation &b)
    {
        return std::make_tuple(a.filename, a.sourceLocation.begin(), a.sourceLocation.end())
                < std::make_tuple(b.filename, b.sourceLocation.begin(), b.sourceLocation.end());
    }
    friend bool operator==(const QQmlLSUtilsLocation &a, const QQmlLSUtilsLocation &b)
    {
        return std::make_tuple(a.filename, a.sourceLocation.begin(), a.sourceLocation.end())
                == std::make_tuple(b.filename, b.sourceLocation.begin(), b.sourceLocation.end());
    }
};

struct QQmlLSUtilsEdit
{
    QQmlLSUtilsLocation location;
    QString replacement;

    static QQmlLSUtilsEdit from(const QString &fileName, const QString &code, quint32 startLine,
                                quint32 startCharacter, quint32 length, const QString &newName);

    friend bool operator<(const QQmlLSUtilsEdit &a, const QQmlLSUtilsEdit &b)
    {
        return std::make_tuple(a.location, a.replacement)
                < std::make_tuple(b.location, b.replacement);
    }
    friend bool operator==(const QQmlLSUtilsEdit &a, const QQmlLSUtilsEdit &b)
    {
        return std::make_tuple(a.location, a.replacement)
                == std::make_tuple(b.location, b.replacement);
    }
};

/*!
   \internal
    Choose whether to resolve the owner type or the entire type (the latter is only required to
    resolve the types of qualified names and property accesses).

    For properties, methods, enums and co:
    * ResolveOwnerType returns the base type of the owner that owns the property, method, enum
      and co. For example, resolving "x" in "myRectangle.x" will return the Item as the owner, as
      Item is the base type of Rectangle that defines the "x" property.
    * ResolveActualTypeForFieldMemberExpression is used to resolve field member expressions, and
      might lose some information about the owner. For example, resolving "x" in "myRectangle.x"
      will return the JS type for float that was used to define the "x" property.
 */
enum QQmlLSUtilsResolveOptions {
    ResolveOwnerType,
    ResolveActualTypeForFieldMemberExpression,
};

enum class ImportCompletionType { None, Module, Version };

using DomItem = QQmlJS::Dom::DomItem;

class QQmlLSUtils
{
public:
    static qsizetype textOffsetFrom(const QString &code, int row, int character);
    static QQmlLSUtilsTextPosition textRowAndColumnFrom(const QString &code, qsizetype offset);
    static QList<QQmlLSUtilsItemLocation> itemsFromTextLocation(const DomItem &file,
                                                                int line, int character);
    static DomItem sourceLocationToDomItem(const DomItem &file,
                                                        const QQmlJS::SourceLocation &location);
    static QByteArray lspUriToQmlUrl(const QByteArray &uri);
    static QByteArray qmlUrlToLspUri(const QByteArray &url);
    static QLspSpecification::Range qmlLocationToLspLocation(const QString &code,
                                                             QQmlJS::SourceLocation qmlLocation);
    static DomItem baseObject(const DomItem &qmlObject);
    static std::optional<QQmlLSUtilsLocation>
    findTypeDefinitionOf(const DomItem &item);
    static std::optional<QQmlLSUtilsLocation> findDefinitionOf(const DomItem &item);
    static QList<QQmlLSUtilsLocation> findUsagesOf(const DomItem &item);

    static std::optional<QQmlLSUtilsErrorMessage> checkNameForRename(
            const DomItem &item, const QString &newName,
            const std::optional<QQmlLSUtilsExpressionType> &targetType = std::nullopt);
    static QList<QQmlLSUtilsEdit> renameUsagesOf(
            const DomItem &item, const QString &newName,
            const std::optional<QQmlLSUtilsExpressionType> &targetType = std::nullopt);

    static std::optional<QQmlLSUtilsExpressionType> resolveExpressionType(
            const DomItem &item, QQmlLSUtilsResolveOptions);
    static bool isValidEcmaScriptIdentifier(QStringView view);

    static QPair<QString, QStringList> cmakeBuildCommand(const QString &path);

    // Documentation Hints
    static QByteArray getDocumentationFromLocation(const DomItem &file, const QQmlLSUtilsTextPosition &position);

    static bool isFieldMemberExpression(const DomItem &item);
    static bool isFieldMemberAccess(const DomItem &item);
    static QStringList fieldMemberExpressionBits(const DomItem &item,
                                                 const DomItem &stopAtChild = {});

    static QString qualifiersFrom(const DomItem &el);
};
QT_END_NAMESPACE

#endif // QLANGUAGESERVERUTILS_P_H