1// Copyright (C) 2023 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#ifndef QLANGUAGESERVERUTILS_P_H
5#define QLANGUAGESERVERUTILS_P_H
6
7//
8// W A R N I N G
9// -------------
10//
11// This file is not part of the Qt API. It exists purely as an
12// implementation detail. This header file may change from version to
13// version without notice, or even be removed.
14//
15// We mean it.
16//
17
18#include <QtLanguageServer/private/qlanguageserverspectypes_p.h>
19#include <QtQmlDom/private/qqmldomexternalitems_p.h>
20#include <QtQmlDom/private/qqmldomtop_p.h>
21#include <algorithm>
22#include <optional>
23#include <tuple>
24#include <variant>
25
26QT_BEGIN_NAMESPACE
27
28Q_DECLARE_LOGGING_CATEGORY(QQmlLSUtilsLog);
29
30namespace QQmlLSUtils {
31
32struct ItemLocation
33{
34 QQmlJS::Dom::DomItem domItem;
35 QQmlJS::Dom::FileLocations::Tree fileLocation;
36};
37
38struct TextPosition
39{
40 int line;
41 int character;
42};
43
44enum IdentifierType : char {
45 NotAnIdentifier, // when resolving expressions like `Qt.point().x` for example, where
46 // `Qt.point()` is not an identifier
47
48 JavaScriptIdentifier,
49 PropertyIdentifier,
50 PropertyChangedSignalIdentifier,
51 PropertyChangedHandlerIdentifier,
52 SignalIdentifier,
53 SignalHandlerIdentifier,
54 MethodIdentifier,
55 LambdaMethodIdentifier,
56 QmlObjectIdIdentifier,
57 SingletonIdentifier,
58 EnumeratorIdentifier,
59 EnumeratorValueIdentifier,
60 AttachedTypeIdentifier,
61 GroupedPropertyIdentifier,
62 QmlComponentIdentifier,
63 QualifiedModuleIdentifier,
64};
65
66struct ErrorMessage
67{
68 int code;
69 QString message;
70};
71
72struct ExpressionType
73{
74 std::optional<QString> name;
75 QQmlJSScope::ConstPtr semanticScope;
76 IdentifierType type = NotAnIdentifier;
77};
78
79class Location
80{
81public:
82 Location() = default;
83 Location(const QString &filename, const QQmlJS::SourceLocation &sourceLocation,
84 const TextPosition &end)
85 : m_filename(filename), m_sourceLocation(sourceLocation), m_end(end)
86 {
87 }
88
89 QString filename() const { return m_filename; }
90 QQmlJS::SourceLocation sourceLocation() const { return m_sourceLocation; }
91 TextPosition end() const { return m_end; }
92
93 static Location from(const QString &fileName, const QString &code, quint32 startLine,
94 quint32 startCharacter, quint32 length);
95 static Location from(const QString &fileName, const QQmlJS::SourceLocation &sourceLocation,
96 const QString &code);
97 static std::optional<Location> tryFrom(const QString &fileName,
98 const QQmlJS::SourceLocation &sourceLocation,
99 const QQmlJS::Dom::DomItem &someItem);
100
101 friend bool operator<(const Location &a, const Location &b)
102 {
103 return std::make_tuple(args: a.m_filename, args: a.m_sourceLocation.begin(), args: a.m_sourceLocation.end())
104 < std::make_tuple(args: b.m_filename, args: b.m_sourceLocation.begin(),
105 args: b.m_sourceLocation.end());
106 }
107 friend bool operator==(const Location &a, const Location &b)
108 {
109 return std::make_tuple(args: a.m_filename, args: a.m_sourceLocation.begin(), args: a.m_sourceLocation.end())
110 == std::make_tuple(args: b.m_filename, args: b.m_sourceLocation.begin(),
111 args: b.m_sourceLocation.end());
112 }
113
114private:
115 QString m_filename;
116 QQmlJS::SourceLocation m_sourceLocation;
117 TextPosition m_end;
118};
119
120/*!
121Represents a rename operation where the file itself needs to be renamed.
122\internal
123*/
124struct FileRename
125{
126 QString oldFilename;
127 QString newFilename;
128
129 friend bool comparesEqual(const FileRename &a, const FileRename &b) noexcept
130 {
131 return std::tie(args: a.oldFilename, args: a.newFilename) == std::tie(args: b.oldFilename, args: b.newFilename);
132 }
133 friend Qt::strong_ordering compareThreeWay(const FileRename &a, const FileRename &b) noexcept
134 {
135 if (a.oldFilename != b.oldFilename)
136 return compareThreeWay(s1: a.oldFilename, s2: b.oldFilename);
137 return compareThreeWay(s1: a.newFilename, s2: b.newFilename);
138 }
139 Q_DECLARE_STRONGLY_ORDERED(FileRename);
140};
141
142struct Edit
143{
144 Location location;
145 QString replacement;
146
147 static Edit from(const QString &fileName, const QString &code, quint32 startLine,
148 quint32 startCharacter, quint32 length, const QString &newName);
149
150 friend bool operator<(const Edit &a, const Edit &b)
151 {
152 return std::make_tuple(args: a.location, args: a.replacement)
153 < std::make_tuple(args: b.location, args: b.replacement);
154 }
155 friend bool operator==(const Edit &a, const Edit &b)
156 {
157 return std::make_tuple(args: a.location, args: a.replacement)
158 == std::make_tuple(args: b.location, args: b.replacement);
159 }
160};
161
162/*!
163Represents the locations where some highlighting should take place, like in the "find all
164references" feature of the LSP. Those locations are pointing to parts of a Qml file or to a Qml
165file name.
166
167The file names are not reported as usage to the LSP and are currently only needed for the renaming
168operation to be able to rename files.
169
170\internal
171*/
172class Usages
173{
174public:
175 void sort();
176 bool isEmpty() const;
177
178 friend bool comparesEqual(const Usages &a, const Usages &b)
179 {
180 return a.m_usagesInFile == b.m_usagesInFile && a.m_usagesInFilename == b.m_usagesInFilename;
181 }
182 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(Usages)
183
184 Usages() = default;
185 Usages(const QList<Location> &usageInFile, const QList<QString> &usageInFilename);
186
187 QList<Location> usagesInFile() const { return m_usagesInFile; };
188 QList<QString> usagesInFilename() const { return m_usagesInFilename; };
189
190 void appendUsage(const Location &edit)
191 {
192 if (!m_usagesInFile.contains(t: edit))
193 m_usagesInFile.append(t: edit);
194 };
195 void appendFilenameUsage(const QString &edit)
196 {
197
198 if (!m_usagesInFilename.contains(str: edit))
199 m_usagesInFilename.append(t: edit);
200 };
201
202private:
203 QList<Location> m_usagesInFile;
204 QList<QString> m_usagesInFilename;
205};
206
207/*!
208Represents the locations where a renaming should take place. Parts of text inside a file can be
209renamed and also filename themselves can be renamed.
210
211\internal
212*/
213class RenameUsages
214{
215public:
216 friend bool comparesEqual(const RenameUsages &a, const RenameUsages &b)
217 {
218 return std::tie(args: a.m_renamesInFile, args: a.m_renamesInFilename)
219 == std::tie(args: b.m_renamesInFile, args: b.m_renamesInFilename);
220 }
221 Q_DECLARE_EQUALITY_COMPARABLE_NON_NOEXCEPT(RenameUsages)
222
223 RenameUsages() = default;
224 RenameUsages(const QList<Edit> &renamesInFile, const QList<FileRename> &renamesInFilename);
225
226 QList<Edit> renameInFile() const { return m_renamesInFile; };
227 QList<FileRename> renameInFilename() const { return m_renamesInFilename; };
228
229 void appendRename(const Edit &edit) { m_renamesInFile.append(t: edit); };
230 void appendRename(const FileRename &edit) { m_renamesInFilename.append(t: edit); };
231
232private:
233 QList<Edit> m_renamesInFile;
234 QList<FileRename> m_renamesInFilename;
235};
236
237/*!
238 \internal
239 Choose whether to resolve the owner type or the entire type (the latter is only required to
240 resolve the types of qualified names and property accesses).
241
242 For properties, methods, enums and co:
243 * ResolveOwnerType returns the base type of the owner that owns the property, method, enum
244 and co. For example, resolving "x" in "myRectangle.x" will return the Item as the owner, as
245 Item is the base type of Rectangle that defines the "x" property.
246 * ResolveActualTypeForFieldMemberExpression is used to resolve field member expressions, and
247 might lose some information about the owner. For example, resolving "x" in "myRectangle.x"
248 will return the JS type for float that was used to define the "x" property.
249 */
250enum ResolveOptions {
251 ResolveOwnerType,
252 ResolveActualTypeForFieldMemberExpression,
253};
254
255using DomItem = QQmlJS::Dom::DomItem;
256
257qsizetype textOffsetFrom(const QString &code, int row, int character);
258TextPosition textRowAndColumnFrom(const QString &code, qsizetype offset);
259QList<ItemLocation> itemsFromTextLocation(const DomItem &file, int line, int character);
260DomItem sourceLocationToDomItem(const DomItem &file, const QQmlJS::SourceLocation &location);
261QByteArray lspUriToQmlUrl(const QByteArray &uri);
262QByteArray qmlUrlToLspUri(const QByteArray &url);
263QLspSpecification::Range qmlLocationToLspLocation(Location qmlLocation);
264DomItem baseObject(const DomItem &qmlObject);
265std::optional<Location> findTypeDefinitionOf(const DomItem &item);
266std::optional<Location> findDefinitionOf(const DomItem &item);
267Usages findUsagesOf(const DomItem &item);
268
269std::optional<ErrorMessage>
270checkNameForRename(const DomItem &item, const QString &newName,
271 const std::optional<ExpressionType> &targetType = std::nullopt);
272RenameUsages renameUsagesOf(const DomItem &item, const QString &newName,
273 const std::optional<ExpressionType> &targetType = std::nullopt);
274std::optional<ExpressionType> resolveExpressionType(const DomItem &item, ResolveOptions);
275bool isValidEcmaScriptIdentifier(QStringView view);
276
277QPair<QString, QStringList> cmakeBuildCommand(const QString &path);
278
279bool isFieldMemberExpression(const DomItem &item);
280bool isFieldMemberAccess(const DomItem &item);
281bool isFieldMemberBase(const DomItem &item);
282QStringList fieldMemberExpressionBits(const DomItem &item, const DomItem &stopAtChild = {});
283
284QString qualifiersFrom(const DomItem &el);
285
286QQmlJSScope::ConstPtr findDefiningScopeForProperty(const QQmlJSScope::ConstPtr &referrerScope,
287 const QString &nameToCheck);
288QQmlJSScope::ConstPtr findDefiningScopeForBinding(const QQmlJSScope::ConstPtr &referrerScope,
289 const QString &nameToCheck);
290QQmlJSScope::ConstPtr findDefiningScopeForMethod(const QQmlJSScope::ConstPtr &referrerScope,
291 const QString &nameToCheck);
292QQmlJSScope::ConstPtr findDefiningScopeForEnumeration(const QQmlJSScope::ConstPtr &referrerScope,
293 const QString &nameToCheck);
294QQmlJSScope::ConstPtr findDefiningScopeForEnumerationKey(const QQmlJSScope::ConstPtr &referrerScope,
295 const QString &nameToCheck);
296} // namespace QQmlLSUtils
297
298QT_END_NAMESPACE
299
300#endif // QLANGUAGESERVERUTILS_P_H
301

Provided by KDAB

Privacy Policy
Learn Advanced QML with KDAB
Find out more

source code of qtdeclarative/src/qmlls/qqmllsutils_p.h