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"
5#include "qqmlrenamesymbolsupport_p.h"
6#include <utility>
7
8QT_BEGIN_NAMESPACE
9
10using namespace Qt::StringLiterals;
11QQmlRenameSymbolSupport::QQmlRenameSymbolSupport(QmlLsp::QQmlCodeModel *model) : BaseT(model) { }
12
13QString QQmlRenameSymbolSupport::name() const
14{
15 return u"QmlRenameSymbolSupport"_s;
16}
17
18void QQmlRenameSymbolSupport::setupCapabilities(
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(handler: getRequestHandler());
31}
32
33void QQmlRenameSymbolSupport::process(QQmlRenameSymbolSupport::RequestPointerArgument request)
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 QQmlLSUtils::ItemLocation &front =
43 std::get<QList<QQmlLSUtils::ItemLocation>>(v&: itemsFound).front();
44
45 const QString newName = QString::fromUtf8(ba: request->m_parameters.newName);
46 auto expressionType =
47 QQmlLSUtils::resolveExpressionType(item: front.domItem, QQmlLSUtils::ResolveOwnerType);
48
49 if (!expressionType) {
50 guard.setError(QQmlLSUtils::ErrorMessage{ .code: 0, .message: u"Cannot rename the requested object"_s });
51 return;
52 }
53
54 if (guard.setErrorFrom(QQmlLSUtils::checkNameForRename(item: front.domItem, newName, targetType: expressionType)))
55 return;
56
57 auto &editsByFileForResult = result.documentChanges.emplace();
58
59 // The QLspSpecification::WorkspaceEdit requires the changes to be grouped by files, so
60 // collect them into editsByFileUris.
61 QMap<QUrl, QList<QLspSpecification::TextEdit>> editsByFileUris;
62
63 const auto renames = QQmlLSUtils::renameUsagesOf(item: front.domItem, newName, targetType: expressionType);
64 for (const auto &rename : renames.renameInFile()) {
65 QLspSpecification::TextEdit edit;
66
67 const QUrl uri = QUrl::fromLocalFile(localfile: rename.location.filename());
68 edit.range = QQmlLSUtils::qmlLocationToLspLocation(qmlLocation: rename.location);
69 edit.newText = rename.replacement.toUtf8();
70
71 editsByFileUris[uri].append(t: edit);
72 }
73
74 for (auto it = editsByFileUris.keyValueBegin(); it != editsByFileUris.keyValueEnd(); ++it) {
75 QLspSpecification::TextDocumentEdit editsForCurrentFile;
76 editsForCurrentFile.textDocument.uri = it->first.toEncoded();
77
78 // TODO: do we need to take care of the optional versioning in
79 // editsForCurrentFile.textDocument.version? see
80 // https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#optionalVersionedTextDocumentIdentifier
81 // for more details
82
83 for (const auto &x : std::as_const(t&: it->second)) {
84 editsForCurrentFile.edits.append(t: x);
85 }
86 editsByFileForResult.append(t: editsForCurrentFile);
87 }
88
89 // if files need to be renamed, then do it after the text edits
90 for (const auto &rename : renames.renameInFilename()) {
91 QLspSpecification::RenameFile currentRenameFile;
92 currentRenameFile.kind = "rename";
93 currentRenameFile.oldUri = QUrl::fromLocalFile(localfile: rename.oldFilename).toEncoded();
94 currentRenameFile.newUri = QUrl::fromLocalFile(localfile: rename.newFilename).toEncoded();
95 editsByFileForResult.append(t: currentRenameFile);
96 }
97}
98
99QT_END_NAMESPACE
100

Provided by KDAB

Privacy Policy
Learn to use CMake with our Intro Training
Find out more

source code of qtdeclarative/src/qmlls/qqmlrenamesymbolsupport.cpp