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;
|
||||
}
|
||||
|
||||
StringRef clearExtraNewline(StringRef text)
|
||||
{
|
||||
while (text.startswith("\n\n"))
|
||||
text = text.drop_front();
|
||||
return text;
|
||||
}
|
||||
|
||||
Replacements filteredReplacements(const Replacements &replacements,
|
||||
int offset,
|
||||
int extraOffsetToAdd,
|
||||
@@ -83,10 +90,13 @@ Replacements filteredReplacements(const Replacements &replacements,
|
||||
if (replacementOffset + 1 >= offset)
|
||||
replacementOffset += extraOffsetToAdd;
|
||||
|
||||
StringRef text = onlyIndention ? clearExtraNewline(replacement.getReplacementText())
|
||||
: replacement.getReplacementText();
|
||||
|
||||
Error error = filtered.add(Replacement(replacement.getFilePath(),
|
||||
static_cast<unsigned int>(replacementOffset),
|
||||
replacement.getLength(),
|
||||
replacement.getReplacementText()));
|
||||
text));
|
||||
// Throws if error is not checked.
|
||||
if (error)
|
||||
break;
|
||||
@@ -335,10 +345,19 @@ void ClangFormatIndenter::indent(QTextDocument *doc,
|
||||
bool /*autoTriggered*/)
|
||||
{
|
||||
if (cursor.hasSelection()) {
|
||||
QTextBlock currentBlock = doc->findBlock(cursor.selectionStart());
|
||||
while (currentBlock.isValid() && currentBlock.position() < cursor.selectionEnd()) {
|
||||
indentBlock(doc, currentBlock, typedChar, tabSettings);
|
||||
currentBlock = currentBlock.next();
|
||||
// Calling currentBlock.next() might be unsafe because we change the document.
|
||||
// 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);
|
||||
QTC_CHECK(blocksAmount == doc->blockCount()
|
||||
&& "ClangFormat plugin indentation changed the amount of blocks.");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
indentBlock(doc, cursor.block(), typedChar, tabSettings);
|
||||
|
||||
Reference in New Issue
Block a user