aboutsummaryrefslogtreecommitdiffstats
path: root/src/qmlls/qqmllsutils_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qmlls/qqmllsutils_p.h')
-rw-r--r--src/qmlls/qqmllsutils_p.h274
1 files changed, 274 insertions, 0 deletions
diff --git a/src/qmlls/qqmllsutils_p.h b/src/qmlls/qqmllsutils_p.h
new file mode 100644
index 0000000000..84cf31c368
--- /dev/null
+++ b/src/qmlls/qqmllsutils_p.h
@@ -0,0 +1,274 @@
+// 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);
+
+namespace QQmlLSUtils {
+
+struct ItemLocation
+{
+ QQmlJS::Dom::DomItem domItem;
+ QQmlJS::Dom::FileLocations::Tree fileLocation;
+};
+
+struct TextPosition
+{
+ int line;
+ int character;
+};
+
+enum IdentifierType : char {
+ JavaScriptIdentifier,
+ PropertyIdentifier,
+ PropertyChangedSignalIdentifier,
+ PropertyChangedHandlerIdentifier,
+ SignalIdentifier,
+ SignalHandlerIdentifier,
+ MethodIdentifier,
+ QmlObjectIdIdentifier,
+ SingletonIdentifier,
+ EnumeratorIdentifier,
+ EnumeratorValueIdentifier,
+ AttachedTypeIdentifier,
+ GroupedPropertyIdentifier,
+ QmlComponentIdentifier,
+};
+
+struct ErrorMessage
+{
+ int code;
+ QString message;
+};
+
+struct ExpressionType
+{
+ std::optional<QString> name;
+ QQmlJSScope::ConstPtr semanticScope;
+ IdentifierType type;
+};
+
+struct Location
+{
+ QString filename;
+ QQmlJS::SourceLocation sourceLocation;
+
+ static Location from(const QString &fileName, const QString &code, quint32 startLine,
+ quint32 startCharacter, quint32 length);
+
+ friend bool operator<(const Location &a, const Location &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 Location &a, const Location &b)
+ {
+ return std::make_tuple(a.filename, a.sourceLocation.begin(), a.sourceLocation.end())
+ == std::make_tuple(b.filename, b.sourceLocation.begin(), b.sourceLocation.end());
+ }
+};
+
+/*!
+Represents a rename operation where the file itself needs to be renamed.
+\internal
+*/
+struct FileRename
+{
+ QString oldFilename;
+ QString newFilename;
+
+ friend bool comparesEqual(const FileRename &a, const FileRename &b) noexcept
+ {
+ return std::tie(a.oldFilename, a.newFilename) == std::tie(b.oldFilename, b.newFilename);
+ }
+ friend Qt::strong_ordering compareThreeWay(const FileRename &a, const FileRename &b) noexcept
+ {
+ if (a.oldFilename != b.oldFilename)
+ return compareThreeWay(a.oldFilename, b.oldFilename);
+ return compareThreeWay(a.newFilename, b.newFilename);
+ }
+ Q_DECLARE_STRONGLY_ORDERED(FileRename);
+};
+
+struct Edit
+{
+ Location location;
+ QString replacement;
+
+ static Edit from(const QString &fileName, const QString &code, quint32 startLine,
+ quint32 startCharacter, quint32 length, const QString &newName);
+
+ friend bool operator<(const Edit &a, const Edit &b)
+ {
+ return std::make_tuple(a.location, a.replacement)
+ < std::make_tuple(b.location, b.replacement);
+ }
+ friend bool operator==(const Edit &a, const Edit &b)
+ {
+ return std::make_tuple(a.location, a.replacement)
+ == std::make_tuple(b.location, b.replacement);
+ }
+};
+
+/*!
+Represents the locations where some highlighting should take place, like in the "find all
+references" feature of the LSP. Those locations are pointing to parts of a Qml file or to a Qml
+file name.
+
+The file names are not reported as usage to the LSP and are currently only needed for the renaming
+operation to be able to rename files.
+
+\internal
+*/
+class Usages
+{
+public:
+ void sort();
+ bool isEmpty() const;
+
+ friend bool comparesEqual(const Usages &a, const Usages &b)
+ {
+ return a.m_usagesInFile == b.m_usagesInFile && a.m_usagesInFilename == b.m_usagesInFilename;
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(Usages)
+
+ Usages() = default;
+ Usages(const QList<Location> &usageInFile, const QList<QString> &usageInFilename);
+
+ QList<Location> usagesInFile() const { return m_usagesInFile; };
+ QList<QString> usagesInFilename() const { return m_usagesInFilename; };
+
+ void appendUsage(const Location &edit)
+ {
+ if (!m_usagesInFile.contains(edit))
+ m_usagesInFile.append(edit);
+ };
+ void appendFilenameUsage(const QString &edit)
+ {
+
+ if (!m_usagesInFilename.contains(edit))
+ m_usagesInFilename.append(edit);
+ };
+
+private:
+ QList<Location> m_usagesInFile;
+ QList<QString> m_usagesInFilename;
+};
+
+/*!
+Represents the locations where a renaming should take place. Parts of text inside a file can be
+renamed and also filename themselves can be renamed.
+
+\internal
+*/
+class RenameUsages
+{
+public:
+ friend bool comparesEqual(const RenameUsages &a, const RenameUsages &b)
+ {
+ return std::tie(a.m_renamesInFile, a.m_renamesInFilename)
+ == std::tie(b.m_renamesInFile, b.m_renamesInFilename);
+ }
+ Q_DECLARE_EQUALITY_COMPARABLE(RenameUsages)
+
+ RenameUsages() = default;
+ RenameUsages(const QList<Edit> &renamesInFile, const QList<FileRename> &renamesInFilename);
+
+ QList<Edit> renameInFile() const { return m_renamesInFile; };
+ QList<FileRename> renameInFilename() const { return m_renamesInFilename; };
+
+ void appendRename(const Edit &edit) { m_renamesInFile.append(edit); };
+ void appendRename(const FileRename &edit) { m_renamesInFilename.append(edit); };
+
+private:
+ QList<Edit> m_renamesInFile;
+ QList<FileRename> m_renamesInFilename;
+};
+
+/*!
+ \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 ResolveOptions {
+ ResolveOwnerType,
+ ResolveActualTypeForFieldMemberExpression,
+};
+
+using DomItem = QQmlJS::Dom::DomItem;
+
+qsizetype textOffsetFrom(const QString &code, int row, int character);
+TextPosition textRowAndColumnFrom(const QString &code, qsizetype offset);
+QList<ItemLocation> itemsFromTextLocation(const DomItem &file, int line, int character);
+DomItem sourceLocationToDomItem(const DomItem &file, const QQmlJS::SourceLocation &location);
+QByteArray lspUriToQmlUrl(const QByteArray &uri);
+QByteArray qmlUrlToLspUri(const QByteArray &url);
+QLspSpecification::Range qmlLocationToLspLocation(const QString &code,
+ QQmlJS::SourceLocation qmlLocation);
+DomItem baseObject(const DomItem &qmlObject);
+std::optional<Location> findTypeDefinitionOf(const DomItem &item);
+std::optional<Location> findDefinitionOf(const DomItem &item);
+Usages findUsagesOf(const DomItem &item);
+
+std::optional<ErrorMessage>
+checkNameForRename(const DomItem &item, const QString &newName,
+ const std::optional<ExpressionType> &targetType = std::nullopt);
+RenameUsages renameUsagesOf(const DomItem &item, const QString &newName,
+ const std::optional<ExpressionType> &targetType = std::nullopt);
+std::optional<ExpressionType> resolveExpressionType(const DomItem &item, ResolveOptions);
+bool isValidEcmaScriptIdentifier(QStringView view);
+
+QPair<QString, QStringList> cmakeBuildCommand(const QString &path);
+
+bool isFieldMemberExpression(const DomItem &item);
+bool isFieldMemberAccess(const DomItem &item);
+QStringList fieldMemberExpressionBits(const DomItem &item, const DomItem &stopAtChild = {});
+
+QString qualifiersFrom(const DomItem &el);
+
+QQmlJSScope::ConstPtr findDefiningScopeForProperty(const QQmlJSScope::ConstPtr &referrerScope,
+ const QString &nameToCheck);
+QQmlJSScope::ConstPtr findDefiningScopeForBinding(const QQmlJSScope::ConstPtr &referrerScope,
+ const QString &nameToCheck);
+QQmlJSScope::ConstPtr findDefiningScopeForMethod(const QQmlJSScope::ConstPtr &referrerScope,
+ const QString &nameToCheck);
+QQmlJSScope::ConstPtr findDefiningScopeForEnumeration(const QQmlJSScope::ConstPtr &referrerScope,
+ const QString &nameToCheck);
+QQmlJSScope::ConstPtr findDefiningScopeForEnumerationKey(const QQmlJSScope::ConstPtr &referrerScope,
+ const QString &nameToCheck);
+} // namespace QQmlLSUtils
+
+QT_END_NAMESPACE
+
+#endif // QLANGUAGESERVERUTILS_P_H