forked from qt-creator/qt-creator
ClangFormat: Fix iteration through text blocks
Document might be edited between consecutive currentBlock.next() calls which is unsafe. Let's instead operate with block numbers. Fixes: QTCREATORBUG-21521 Change-Id: I6863a77a32f5583269e1c796f38afb45cc9e7f77 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@qt.io>
This commit is contained in:
@@ -69,6 +69,13 @@ void adjustFormatStyleForLineBreak(format::FormatStyle &style)
|
|||||||
style.SortUsingDeclarations = false;
|
style.SortUsingDeclarations = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
StringRef clearExtraNewline(StringRef text)
|
||||||
|
{
|
||||||
|
while (text.startswith("\n\n"))
|
||||||
|
text = text.drop_front();
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
|
||||||
Replacements filteredReplacements(const Replacements &replacements,
|
Replacements filteredReplacements(const Replacements &replacements,
|
||||||
int offset,
|
int offset,
|
||||||
int extraOffsetToAdd,
|
int extraOffsetToAdd,
|
||||||
@@ -83,10 +90,13 @@ Replacements filteredReplacements(const Replacements &replacements,
|
|||||||
if (replacementOffset + 1 >= offset)
|
if (replacementOffset + 1 >= offset)
|
||||||
replacementOffset += extraOffsetToAdd;
|
replacementOffset += extraOffsetToAdd;
|
||||||
|
|
||||||
|
StringRef text = onlyIndention ? clearExtraNewline(replacement.getReplacementText())
|
||||||
|
: replacement.getReplacementText();
|
||||||
|
|
||||||
Error error = filtered.add(Replacement(replacement.getFilePath(),
|
Error error = filtered.add(Replacement(replacement.getFilePath(),
|
||||||
static_cast<unsigned int>(replacementOffset),
|
static_cast<unsigned int>(replacementOffset),
|
||||||
replacement.getLength(),
|
replacement.getLength(),
|
||||||
replacement.getReplacementText()));
|
text));
|
||||||
// Throws if error is not checked.
|
// Throws if error is not checked.
|
||||||
if (error)
|
if (error)
|
||||||
break;
|
break;
|
||||||
@@ -335,10 +345,19 @@ void ClangFormatIndenter::indent(QTextDocument *doc,
|
|||||||
bool /*autoTriggered*/)
|
bool /*autoTriggered*/)
|
||||||
{
|
{
|
||||||
if (cursor.hasSelection()) {
|
if (cursor.hasSelection()) {
|
||||||
QTextBlock currentBlock = doc->findBlock(cursor.selectionStart());
|
// Calling currentBlock.next() might be unsafe because we change the document.
|
||||||
while (currentBlock.isValid() && currentBlock.position() < cursor.selectionEnd()) {
|
// Let's operate with block numbers instead.
|
||||||
|
const int startNumber = doc->findBlock(cursor.selectionStart()).blockNumber();
|
||||||
|
const int endNumber = doc->findBlock(cursor.selectionEnd()).blockNumber();
|
||||||
|
for (int currentBlockNumber = startNumber; currentBlockNumber <= endNumber;
|
||||||
|
++currentBlockNumber) {
|
||||||
|
const QTextBlock currentBlock = doc->findBlockByNumber(currentBlockNumber);
|
||||||
|
if (currentBlock.isValid()) {
|
||||||
|
const int blocksAmount = doc->blockCount();
|
||||||
indentBlock(doc, currentBlock, typedChar, tabSettings);
|
indentBlock(doc, currentBlock, typedChar, tabSettings);
|
||||||
currentBlock = currentBlock.next();
|
QTC_CHECK(blocksAmount == doc->blockCount()
|
||||||
|
&& "ClangFormat plugin indentation changed the amount of blocks.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
indentBlock(doc, cursor.block(), typedChar, tabSettings);
|
indentBlock(doc, cursor.block(), typedChar, tabSettings);
|
||||||
|
|||||||
Reference in New Issue
Block a user