Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qqmllsutils_p.h
Go to the documentation of this file.
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// Qt-Security score:significant reason:default
4
5#ifndef QLANGUAGESERVERUTILS_P_H
6#define QLANGUAGESERVERUTILS_P_H
7
8//
9// W A R N I N G
10// -------------
11//
12// This file is not part of the Qt API. It exists purely as an
13// implementation detail. This header file may change from version to
14// version without notice, or even be removed.
15//
16// We mean it.
17//
18
19#include <QtLanguageServer/private/qlanguageserverspectypes_p.h>
20#include <QtQmlDom/private/qqmldomexternalitems_p.h>
21#include <QtQmlDom/private/qqmldomtop_p.h>
22#include <algorithm>
23#include <optional>
24#include <tuple>
25#include <variant>
26
28
30
31namespace QQmlLSUtils {
32
38
40{
41 int line = 0;
42 int character = 0;
43};
44
46 NotAnIdentifier, // when resolving expressions like `Qt.point().x` for example, where
47 // `Qt.point()` is not an identifier
48
62 // qqmljsimportvisitor creates extra attached type scopes for `Type.property: ...` compared to
63 // other usages of attached types, like for example `p: Type.property`
68};
69
71{
72 int code = 0;
74};
75
82
84{
85public:
86 Location() = default;
87 Location(const QString &filename, const QQmlJS::SourceLocation &sourceLocation,
88 const TextPosition &end)
90 {
91 }
92
93 QString filename() const { return m_filename; }
94 QQmlJS::SourceLocation sourceLocation() const { return m_sourceLocation; }
95 TextPosition end() const { return m_end; }
96
97 static Location from(const QString &fileName, const QString &code, qsizetype startLine,
98 qsizetype startCharacter, qsizetype length);
99 static Location from(const QString &fileName, const QQmlJS::SourceLocation &sourceLocation,
100 const QString &code);
101 static std::optional<Location> tryFrom(const QString &fileName,
102 const QQmlJS::SourceLocation &sourceLocation,
103 const QQmlJS::Dom::DomItem &someItem);
104
105 friend bool operator<(const Location &a, const Location &b)
106 {
107 return std::make_tuple(a.m_filename, a.m_sourceLocation.begin(), a.m_sourceLocation.end())
108 < std::make_tuple(b.m_filename, b.m_sourceLocation.begin(),
109 b.m_sourceLocation.end());
110 }
111 friend bool operator==(const Location &a, const Location &b)
112 {
113 return std::make_tuple(a.m_filename, a.m_sourceLocation.begin(), a.m_sourceLocation.end())
114 == std::make_tuple(b.m_filename, b.m_sourceLocation.begin(),
115 b.m_sourceLocation.end());
116 }
117
118private:
119 QString m_filename;
120 QQmlJS::SourceLocation m_sourceLocation;
121 TextPosition m_end;
122};
123
124/*!
125Represents a rename operation where the file itself needs to be renamed.
126\internal
127*/
129{
132
133 friend bool comparesEqual(const FileRename &a, const FileRename &b) noexcept
134 {
135 return std::tie(a.oldFilename, a.newFilename) == std::tie(b.oldFilename, b.newFilename);
136 }
137 friend Qt::strong_ordering compareThreeWay(const FileRename &a, const FileRename &b) noexcept
138 {
139 if (a.oldFilename != b.oldFilename)
140 return compareThreeWay(a.oldFilename, b.oldFilename);
141 return compareThreeWay(a.newFilename, b.newFilename);
142 }
144};
145
146struct Edit
147{
150
151 static Edit from(const QString &fileName, const QString &code, qsizetype startLine,
152 qsizetype startCharacter, qsizetype length, const QString &newName);
153
154 friend bool operator<(const Edit &a, const Edit &b)
155 {
156 return std::make_tuple(a.location, a.replacement)
157 < std::make_tuple(b.location, b.replacement);
158 }
159 friend bool operator==(const Edit &a, const Edit &b)
160 {
161 return std::make_tuple(a.location, a.replacement)
162 == std::make_tuple(b.location, b.replacement);
163 }
164};
165
166/*!
167Represents the locations where some highlighting should take place, like in the "find all
168references" feature of the LSP. Those locations are pointing to parts of a Qml file or to a Qml
169file name.
170
171The file names are not reported as usage to the LSP and are currently only needed for the renaming
172operation to be able to rename files.
173
174\internal
175*/
177{
178public:
179 void sort();
180 bool isEmpty() const;
181
182 friend bool comparesEqual(const Usages &a, const Usages &b) noexcept
183 {
184 return a.m_usagesInFile == b.m_usagesInFile && a.m_usagesInFilename == b.m_usagesInFilename;
185 }
187
188 Usages() = default;
189 Usages(const QList<Location> &usageInFile, const QList<QString> &usageInFilename);
190
191 QList<Location> usagesInFile() const { return m_usagesInFile; };
192 QList<QString> usagesInFilename() const { return m_usagesInFilename; };
193
194 void appendUsage(const Location &edit)
195 {
196 if (!m_usagesInFile.contains(edit))
197 m_usagesInFile.append(edit);
198 };
199 void appendFilenameUsage(const QString &edit)
200 {
201
202 if (!m_usagesInFilename.contains(edit))
203 m_usagesInFilename.append(edit);
204 };
205
206private:
207 QList<Location> m_usagesInFile;
208 QList<QString> m_usagesInFilename;
209};
210
211/*!
212Represents the locations where a renaming should take place. Parts of text inside a file can be
213renamed and also filename themselves can be renamed.
214
215\internal
216*/
218{
219public:
220 friend bool comparesEqual(const RenameUsages &a, const RenameUsages &b) noexcept
221 {
222 return std::tie(a.m_renamesInFile, a.m_renamesInFilename)
223 == std::tie(b.m_renamesInFile, b.m_renamesInFilename);
224 }
226
227 RenameUsages() = default;
228 RenameUsages(const QList<Edit> &renamesInFile, const QList<FileRename> &renamesInFilename);
229
230 QList<Edit> renameInFile() const { return m_renamesInFile; };
231 QList<FileRename> renameInFilename() const { return m_renamesInFilename; };
232
233 void appendRename(const Edit &edit) { m_renamesInFile.append(edit); };
234 void appendRename(const FileRename &edit) { m_renamesInFilename.append(edit); };
235
236private:
237 QList<Edit> m_renamesInFile;
238 QList<FileRename> m_renamesInFilename;
239};
240
241/*!
242 \internal
243 Choose whether to resolve the owner type or the entire type (the latter is only required to
244 resolve the types of qualified names and property accesses).
245
246 For properties, methods, enums and co:
247 * ResolveOwnerType returns the base type of the owner that owns the property, method, enum
248 and co. For example, resolving "x" in "myRectangle.x" will return the Item as the owner, as
249 Item is the base type of Rectangle that defines the "x" property.
250 * ResolveActualTypeForFieldMemberExpression is used to resolve field member expressions, and
251 might lose some information about the owner. For example, resolving "x" in "myRectangle.x"
252 will return the JS type for float that was used to define the "x" property.
253 */
258
260
261qsizetype textOffsetFrom(const QString &code, int row, int character);
262TextPosition textRowAndColumnFrom(const QString &code, qsizetype offset);
263QList<ItemLocation> itemsFromTextLocation(const DomItem &file, int line, int character);
264DomItem sourceLocationToDomItem(const DomItem &file, const QQmlJS::SourceLocation &location);
265QByteArray lspUriToQmlUrl(const QByteArray &uri);
266QByteArray qmlUrlToLspUri(const QByteArray &url);
268DomItem baseObject(const DomItem &qmlObject);
269std::optional<Location> findTypeDefinitionOf(const DomItem &item);
270std::optional<Location> findDefinitionOf(const DomItem &item, const QStringList &headerDirectories);
271Usages findUsagesOf(const DomItem &item);
272
273std::optional<ErrorMessage>
274checkNameForRename(const DomItem &item, const QString &newName,
275 const std::optional<ExpressionType> &targetType = std::nullopt);
276RenameUsages renameUsagesOf(const DomItem &item, const QString &newName,
277 const std::optional<ExpressionType> &targetType = std::nullopt);
278std::optional<ExpressionType> resolveExpressionType(const DomItem &item, ResolveOptions);
279bool isValidEcmaScriptIdentifier(QStringView view);
280
281std::pair<QString, QStringList> cmakeBuildCommand(const QString &path);
282
283bool isFieldMemberExpression(const DomItem &item);
284bool isFieldMemberAccess(const DomItem &item);
285bool isFieldMemberBase(const DomItem &item);
286QStringList fieldMemberExpressionBits(const DomItem &item, const DomItem &stopAtChild = {});
287
288QString qualifiersFrom(const DomItem &el);
289
290QQmlJSScope::ConstPtr findDefiningScopeForProperty(const QQmlJSScope::ConstPtr &referrerScope,
291 const QString &nameToCheck);
292QQmlJSScope::ConstPtr findDefiningScopeForBinding(const QQmlJSScope::ConstPtr &referrerScope,
293 const QString &nameToCheck);
294QQmlJSScope::ConstPtr findDefiningScopeForMethod(const QQmlJSScope::ConstPtr &referrerScope,
295 const QString &nameToCheck);
296QQmlJSScope::ConstPtr findDefiningScopeForEnumeration(const QQmlJSScope::ConstPtr &referrerScope,
297 const QString &nameToCheck);
298QQmlJSScope::ConstPtr findDefiningScopeForEnumerationKey(const QQmlJSScope::ConstPtr &referrerScope,
299 const QString &nameToCheck);
300QStringList findFilePathsFromFileNames(const QString &rootDir, const QStringList &fileNamesToSearch,
301 const QSet<QString> &ignoredPaths);
302QString findFilePathFromFileName(const QStringList &rootDirs, const QString &fileNameToSearch,
303 const QSet<QString> &ignoredPaths);
304} // namespace QQmlLSUtils
305
306QT_END_NAMESPACE
307
308#endif // QLANGUAGESERVERUTILS_P_H
DocumentSymbolVisitor(const DomItem &item, const AssemblingFunction af)
friend bool operator<(const Location &a, const Location &b)
static std::optional< Location > tryFrom(const QString &fileName, const QQmlJS::SourceLocation &sourceLocation, const QQmlJS::Dom::DomItem &someItem)
static Location from(const QString &fileName, const QQmlJS::SourceLocation &sourceLocation, const QString &code)
QString filename() const
TextPosition end() const
QQmlJS::SourceLocation sourceLocation() const
friend bool operator==(const Location &a, const Location &b)
Location(const QString &filename, const QQmlJS::SourceLocation &sourceLocation, const TextPosition &end)
static Location from(const QString &fileName, const QString &code, qsizetype startLine, qsizetype startCharacter, qsizetype length)
Represents the locations where a renaming should take place.
friend bool comparesEqual(const RenameUsages &a, const RenameUsages &b) noexcept
void appendRename(const Edit &edit)
RenameUsages(const QList< Edit > &renamesInFile, const QList< FileRename > &renamesInFilename)
QList< Edit > renameInFile() const
void appendRename(const FileRename &edit)
QList< FileRename > renameInFilename() const
Represents the locations where some highlighting should take place, like in the "find allreferences" ...
void appendFilenameUsage(const QString &edit)
QList< Location > usagesInFile() const
QList< QString > usagesInFilename() const
friend bool comparesEqual(const Usages &a, const Usages &b) noexcept
void appendUsage(const Location &edit)
Usages(const QList< Location > &usageInFile, const QList< QString > &usageInFilename)
static constexpr std::array< TypeSymbolRelation, 9 > s_TypeSymbolRelations
std::pair< QLspSpecification::Range, QLspSpecification::Range > symbolRangesOf(const DomItem &item)
static bool shouldFilterOut(const DomItem &item)
QLspSpecification::DocumentSymbol & MutableRefToDocumentSymbol
SymbolsList assembleSymbolsForQmlFile(const DomItem &item, const AssemblingFunction af)
static void adopt(QLspSpecification::DocumentSymbol &&child, MutableRefToDocumentSymbol parent)
static std::optional< QByteArray > tryGetQmlObjectDetail(const DomItem &qmlObj)
static void readoptChildrenIf(const DocumentSymbolPredicate unaryPred, MutableRefToDocumentSymbol currentParent)
std::optional< QByteArray > tryGetDetailOf(const DomItem &item)
static SymbolsList extractChildrenIf(const DocumentSymbolPredicate shouldBeReadopted, MutableRefToDocumentSymbol currentParent)
static bool propertyBoundAtDefinitionLine(const DomItem &propertyDefinition)
static constexpr bool documentSymbolNotSupportedFor(const DomType &type)
static QByteArray getMethodDetail(const DomItem &mItem)
static MutableRefToDocumentSymbol findDirectParentFor(const QLspSpecification::DocumentSymbol &child, MutableRefToDocumentSymbol currentParent)
void reorganizeForOutlineView(SymbolsList &qmlFileSymbols)
SymbolsList buildSymbolOrReturnChildren(const DomItem &item, SymbolsList &&children)
static constexpr SymbolKind symbolKindFor(const DomType &type)
static bool isSubRange(const QLspSpecification::Range &potentialSubRange, const QLspSpecification::Range &range)
static std::optional< QByteArray > tryGetBindingDetail(const DomItem &bItem)
static void reorganizeQmlComponentSymbol(MutableRefToDocumentSymbol qmlCompSymbol)
qxp::function_ref< bool(const QLspSpecification::DocumentSymbol &) const > DocumentSymbolPredicate
QLspSpecification::SymbolKind symbolKindOf(const DomItem &item)
QByteArray symbolNameOf(const DomItem &item)
RenameUsages renameUsagesOf(const DomItem &item, const QString &newName, const std::optional< ExpressionType > &targetType=std::nullopt)
Rename the appearance of item to newName.
QQmlJSScope::ConstPtr findDefiningScopeForProperty(const QQmlJSScope::ConstPtr &referrerScope, const QString &nameToCheck)
Finds the scope where a property is first defined.
bool isFieldMemberBase(const DomItem &item)
QStringList findFilePathsFromFileNames(const QString &rootDir, const QStringList &fileNamesToSearch, const QSet< QString > &ignoredPaths)
@ EnumeratorValueIdentifier
@ GroupedPropertyIdentifier
@ AttachedTypeIdentifierInBindingTarget
@ QualifiedModuleIdentifier
@ PropertyChangedHandlerIdentifier
@ PropertyChangedSignalIdentifier
@ SignalHandlerIdentifier
bool isValidEcmaScriptIdentifier(QStringView view)
QLspSpecification::Range qmlLocationToLspLocation(Location qmlLocation)
Converts a QQmlJS::SourceLocation to a LSP Range.
QQmlJSScope::ConstPtr findDefiningScopeForMethod(const QQmlJSScope::ConstPtr &referrerScope, const QString &nameToCheck)
QQmlJSScope::ConstPtr findDefiningScopeForBinding(const QQmlJSScope::ConstPtr &referrerScope, const QString &nameToCheck)
qsizetype textOffsetFrom(const QString &code, int row, int character)
Convert a text position from (line, column) into an offset.
std::optional< Location > findDefinitionOf(const DomItem &item, const QStringList &headerDirectories)
DomItem baseObject(const DomItem &qmlObject)
QByteArray lspUriToQmlUrl(const QByteArray &uri)
DomItem sourceLocationToDomItem(const DomItem &file, const QQmlJS::SourceLocation &location)
QStringList fieldMemberExpressionBits(const DomItem &item, const DomItem &stopAtChild={})
QByteArray qmlUrlToLspUri(const QByteArray &url)
@ ResolveActualTypeForFieldMemberExpression
TextPosition textRowAndColumnFrom(const QString &code, qsizetype offset)
Convert a text position from an offset into (line, column).
std::optional< ExpressionType > resolveExpressionType(const DomItem &item, ResolveOptions)
Resolves the type of the given DomItem, when possible (e.g., when there are enough type annotations).
bool isFieldMemberExpression(const DomItem &item)
bool isFieldMemberAccess(const DomItem &item)
QQmlJSScope::ConstPtr findDefiningScopeForEnumeration(const QQmlJSScope::ConstPtr &referrerScope, const QString &nameToCheck)
QList< ItemLocation > itemsFromTextLocation(const DomItem &file, int line, int character)
Find the DomItem representing the object situated in file at given line and character/column.
QString qualifiersFrom(const DomItem &el)
QQmlJSScope::ConstPtr findDefiningScopeForEnumerationKey(const QQmlJSScope::ConstPtr &referrerScope, const QString &nameToCheck)
Usages findUsagesOf(const DomItem &item)
std::optional< Location > findTypeDefinitionOf(const DomItem &item)
Returns the location of the type definition pointed by object.
QString findFilePathFromFileName(const QStringList &rootDirs, const QString &fileNameToSearch, const QSet< QString > &ignoredPaths)
std::pair< QString, QStringList > cmakeBuildCommand(const QString &path)
std::optional< ErrorMessage > checkNameForRename(const DomItem &item, const QString &newName, const std::optional< ExpressionType > &targetType=std::nullopt)
QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher)
static Edit from(const QString &fileName, const QString &code, qsizetype startLine, qsizetype startCharacter, qsizetype length, const QString &newName)
friend bool operator<(const Edit &a, const Edit &b)
friend bool operator==(const Edit &a, const Edit &b)
QQmlJSScope::ConstPtr semanticScope
std::optional< QString > name
Represents a rename operation where the file itself needs to be renamed.
friend bool comparesEqual(const FileRename &a, const FileRename &b) noexcept
friend Qt::strong_ordering compareThreeWay(const FileRename &a, const FileRename &b) noexcept
QQmlJS::Dom::DomItem domItem
QQmlJS::Dom::FileLocations::Tree fileLocation