Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qqmlrenamesymbolsupport.cpp
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
4#include "qqmllsutils_p.h"
6#include <utility>
7
9
10using namespace Qt::StringLiterals;
12
14{
15 return u"QmlRenameSymbolSupport"_s;
16}
17
19 const QLspSpecification::InitializeParams &,
20 QLspSpecification::InitializeResult &serverCapabilities)
21{
22 // use a bool for now. Alternatively, if the client supports "prepareSupport", one could
23 // use a RenameOptions here. See following page for more information about prepareSupport:
24 // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#textDocument_prepareRename
25 serverCapabilities.capabilities.renameProvider = true;
26}
27
28void QQmlRenameSymbolSupport::registerHandlers(QLanguageServer *, QLanguageServerProtocol *protocol)
29{
30 protocol->registerRenameRequestHandler(getRequestHandler());
31}
32
34{
35 QLspSpecification::WorkspaceEdit result;
36 ResponseScopeGuard guard(result, request->m_response);
37
38 auto itemsFound = itemsForRequest(request);
39 if (guard.setErrorFrom(itemsFound))
40 return;
41
42 QQmlLSUtilsItemLocation &front = std::get<QList<QQmlLSUtilsItemLocation>>(itemsFound).front();
43
44 const QString newName = QString::fromUtf8(request->m_parameters.newName);
46
47 if (!expressionType) {
48 guard.setError(QQmlLSUtilsErrorMessage{ 0, u"Cannot rename the requested object"_s });
49 return;
50 }
51
52 if (guard.setErrorFrom(QQmlLSUtils::checkNameForRename(front.domItem, newName, expressionType)))
53 return;
54
55 auto &editsByFileForResult = result.documentChanges.emplace();
56
57 // The QLspSpecification::WorkspaceEdit requires the changes to be grouped by files, so
58 // collect them into editsByFileUris.
59 QMap<QUrl, QList<QLspSpecification::TextEdit>> editsByFileUris;
60
61 auto renames = QQmlLSUtils::renameUsagesOf(front.domItem, newName, expressionType);
62
63 QQmlJS::Dom::DomItem files = front.domItem.top().field(QQmlJS::Dom::Fields::qmlFileWithPath);
64
65 QHash<QString, QString> codeCache;
66
67 for (const auto &rename : renames) {
68 QLspSpecification::TextEdit edit;
69
70 const QUrl uri = QUrl::fromLocalFile(rename.location.filename);
71
72 auto cacheEntry = codeCache.find(rename.location.filename);
73 if (cacheEntry == codeCache.end()) {
74 auto file = files.key(rename.location.filename)
75 .field(QQmlJS::Dom::Fields::currentItem)
76 .ownerAs<QQmlJS::Dom::QmlFile>();
77 if (!file) {
78 qDebug() << "File" << rename.location.filename
79 << "not found in DOM! Available files are" << files.keys();
80 continue;
81 }
82 cacheEntry = codeCache.insert(rename.location.filename, file->code());
83 }
84
85 edit.range = QQmlLSUtils::qmlLocationToLspLocation(cacheEntry.value(),
86 rename.location.sourceLocation);
87 edit.newText = rename.replacement.toUtf8();
88
89 editsByFileUris[uri].append(edit);
90 }
91
92 for (auto it = editsByFileUris.keyValueBegin(); it != editsByFileUris.keyValueEnd(); ++it) {
93 QLspSpecification::TextDocumentEdit editsForCurrentFile;
94 editsForCurrentFile.textDocument.uri = it->first.toEncoded();
95
96 // TODO: do we need to take care of the optional versioning in
97 // editsForCurrentFile.textDocument.version? see
98 // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#optionalVersionedTextDocumentIdentifier
99 // for more details
100
101 for (const auto &x : std::as_const(it->second)) {
102 editsForCurrentFile.edits.append(x);
103 }
104 editsByFileForResult.append(editsForCurrentFile);
105 }
106}
107
Implements a server for the language server protocol.
DomItem field(QStringView name) const
DomItem top() const
A QmlFile, when loaded in a DomEnvironment that has the DomCreationOption::WithSemanticAnalysis,...
static std::optional< QQmlLSUtilsErrorMessage > checkNameForRename(const DomItem &item, const QString &newName, const std::optional< QQmlLSUtilsExpressionType > &targetType=std::nullopt)
static std::optional< QQmlLSUtilsExpressionType > resolveExpressionType(const DomItem &item, QQmlLSUtilsResolveOptions)
static QLspSpecification::Range qmlLocationToLspLocation(const QString &code, QQmlJS::SourceLocation qmlLocation)
Converts a QQmlJS::SourceLocation to a LSP Range.
static QList< QQmlLSUtilsEdit > renameUsagesOf(const DomItem &item, const QString &newName, const std::optional< QQmlLSUtilsExpressionType > &targetType=std::nullopt)
Rename the appearance of item to newName.
void setupCapabilities(const QLspSpecification::InitializeParams &clientInfo, QLspSpecification::InitializeResult &) override
void process(RequestPointerArgument request) override
void registerHandlers(QLanguageServer *server, QLanguageServerProtocol *protocol) override
QQmlRenameSymbolSupport(QmlLsp::QQmlCodeModel *codeModel)
QString name() const override
\macro QT_RESTRICTED_CAST_FROM_ASCII
Definition qstring.h:129
static QString fromUtf8(QByteArrayView utf8)
This is an overloaded member function, provided for convenience. It differs from the above function o...
Definition qstring.cpp:6018
\inmodule QtCore
Definition qurl.h:94
static QUrl fromLocalFile(const QString &localfile)
Returns a QUrl representation of localFile, interpreted as a local file.
Definition qurl.cpp:3368
QSet< QString >::iterator it
Combined button and popup list for selecting options.
#define qDebug
[1]
Definition qlogging.h:164
GLint GLint GLint GLint GLint x
[0]
GLuint64EXT * result
[6]
@ ResolveOwnerType
QSqlQueryModel * model
[16]
QFile file
[0]
QStringList files
[8]
QNetworkRequest request(url)
std::variant< QList< QQmlLSUtilsItemLocation >, QQmlLSUtilsErrorMessage > itemsForRequest(const RequestPointer &request)
QQmlJS::Dom::DomItem domItem
This class sends a result or an error when going out of scope.
void setError(const QQmlLSUtilsErrorMessage &error)
bool setErrorFrom(const std::variant< T... > &variant)