File indexing completed on 2024-04-28 05:49:01

0001 /*
0002  *    SPDX-FileCopyrightText: 2022 Mark Nauwelaerts <mark.nauwelaerts@gmail.com>
0003  *
0004  *    SPDX-License-Identifier: MIT
0005  */
0006 
0007 #include "lspclientutils.h"
0008 
0009 #include <KTextEditor/Document>
0010 
0011 LSPRange transformRange(const QUrl &url, const LSPClientRevisionSnapshot &snapshot, const LSPRange &range)
0012 {
0013     KTextEditor::Document *doc;
0014     qint64 revision;
0015 
0016     auto result = range;
0017     snapshot.find(url, doc, revision);
0018     if (doc) {
0019         doc->transformRange(result, KTextEditor::MovingRange::DoNotExpand, KTextEditor::MovingRange::AllowEmpty, revision);
0020     }
0021     return result;
0022 }
0023 
0024 void applyEdits(KTextEditor::Document *doc, const LSPClientRevisionSnapshot *snapshot, const QList<LSPTextEdit> &edits)
0025 {
0026     // NOTE:
0027     // server might be pretty sloppy wrt edits (e.g. python-language-server)
0028     // e.g. send one edit for the whole document rather than 'surgical edits'
0029     // and that even when requesting format for a limited selection
0030     // ... but then we are but a client and do as we are told
0031     // all-in-all a low priority feature
0032 
0033     // all coordinates in edits are wrt original document,
0034     // so create moving ranges that will adjust to preceding edits as they are applied
0035     QList<KTextEditor::MovingRange *> ranges;
0036     for (const auto &edit : edits) {
0037         auto range = snapshot ? transformRange(doc->url(), *snapshot, edit.range) : edit.range;
0038         KTextEditor::MovingRange *mr = doc->newMovingRange(range);
0039         ranges.append(mr);
0040     }
0041 
0042     // now make one transaction (a.o. for one undo) and apply in sequence
0043     if (!ranges.empty()) {
0044         KTextEditor::Document::EditingTransaction transaction(doc);
0045         for (int i = 0; i < ranges.length(); ++i) {
0046             doc->replaceText(ranges.at(i)->toRange(), edits.at(i).newText);
0047         }
0048     }
0049 
0050     qDeleteAll(ranges);
0051 }