qmlls: Fix TextSynchronization
The offset from a given range was incorrectly calculated in findBlockByNumber because textblocks that are used to obtain that position were mistakenly ignoring the newline character. This were leading us to setting a different text than what we actually typed. Add an extra text block if the text ends with \n. Add a manual test but exclude it from tst_qmlformat as it is not a valid qml document. Fixes: QTBUG-113725 Change-Id: Ifb1b4121fd8af46df7627d986303ae67e170e50c Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
dc30e3859f
commit
7a4175ff60
|
@ -68,22 +68,30 @@ void TextDocument::setPlainText(const QString &text)
|
|||
m_content = text;
|
||||
m_blocks.clear();
|
||||
|
||||
int blockStart = 0;
|
||||
int blockNumber = 0;
|
||||
while (blockStart < text.size()) {
|
||||
const auto appendToBlocks = [this](int blockNumber, int start, int length) {
|
||||
Block block;
|
||||
block.textBlock.setBlockNumber(blockNumber++);
|
||||
block.textBlock.setPosition(blockStart);
|
||||
block.textBlock.setBlockNumber(blockNumber);
|
||||
block.textBlock.setPosition(start);
|
||||
block.textBlock.setDocument(this);
|
||||
block.textBlock.setLength(length);
|
||||
m_blocks.append(block);
|
||||
};
|
||||
|
||||
int blockStart = 0;
|
||||
int blockNumber = -1;
|
||||
while (blockStart < text.size()) {
|
||||
int blockEnd = text.indexOf(u'\n', blockStart) + 1;
|
||||
if (blockEnd == 0)
|
||||
blockEnd = text.size();
|
||||
|
||||
block.textBlock.setLength(blockEnd - blockStart);
|
||||
m_blocks.append(block);
|
||||
appendToBlocks(++blockNumber, blockStart, blockEnd - blockStart);
|
||||
blockStart = blockEnd;
|
||||
}
|
||||
// Add an empty block if the text ends with \n. This is required for retrieving
|
||||
// the actual line of the text editor if requested, for example, in findBlockByNumber.
|
||||
// Consider a case with text aa\nbb\n\n. You are on 4th line of the text editor and even
|
||||
// if it is an empty line, we introduce a text block for it to maybe use later.
|
||||
if (text.endsWith(u'\n'))
|
||||
appendToBlocks(++blockNumber, blockStart, 0);
|
||||
}
|
||||
|
||||
bool TextDocument::isModified() const
|
||||
|
|
|
@ -87,6 +87,7 @@ void TestQmlformat::initTestCase()
|
|||
m_excludedDirs << "doc/src/snippets/qtquick1/qtbinding";
|
||||
m_excludedDirs << "doc/src/snippets/qtquick1/imports";
|
||||
m_excludedDirs << "tests/manual/v4";
|
||||
m_excludedDirs << "tests/manual/qmllsformatter";
|
||||
m_excludedDirs << "tests/auto/qml/ecmascripttests";
|
||||
m_excludedDirs << "tests/auto/qml/qmllint";
|
||||
|
||||
|
|
|
@ -0,0 +1,45 @@
|
|||
// Copyright (C) 2023 The Qt Company Ltd.
|
||||
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
|
||||
|
||||
// Start Test
|
||||
// Open that test.qml file in a text editor that has a client for qmlls
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Test Case - 1
|
||||
// Type the following line manually
|
||||
|
||||
import QtQml
|
||||
|
||||
Window {
|
||||
|
||||
|
||||
}
|
||||
|
||||
// Then, execute "Format Document" in the text editor
|
||||
|
||||
// Expected Result
|
||||
import QtQml
|
||||
|
||||
Window {
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////
|
||||
// Test Case - 2
|
||||
// Type the following line manually
|
||||
|
||||
import QtQml
|
||||
|
||||
Window {
|
||||
aa a: {
|
||||
}
|
||||
}
|
||||
|
||||
// Then, execute "Format Document" in the text editor
|
||||
|
||||
// Expected Result
|
||||
import QtQml
|
||||
|
||||
Window {
|
||||
aa: {
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue