diff options
author | Ivan Donchevskii <ivan.donchevskii@qt.io> | 2019-02-19 12:46:38 +0100 |
---|---|---|
committer | Ivan Donchevskii <ivan.donchevskii@qt.io> | 2019-02-19 12:47:22 +0000 |
commit | be65a57935badcc19f844b36ccf1456f2000a96d (patch) | |
tree | 5e5a893e6f3b83035dc137bd7cb6fe882afa277d /src | |
parent | 08e1fbbbfa8760e94922d69ab7397af64370081a (diff) |
ClangFormat: Fix unit-tests
Amends dcf763c7ee.
Change the logic in empty lines modification to properly
indent all empty lines.
Change-Id: Id945cf66915dfd192216660543594a7905426761
Reviewed-by: Marco Bubke <marco.bubke@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/plugins/clangformat/clangformatbaseindenter.cpp | 137 | ||||
-rw-r--r-- | src/plugins/clangformat/clangformatbaseindenter.h | 2 |
2 files changed, 75 insertions, 64 deletions
diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp index 6d06b05812..da36731796 100644 --- a/src/plugins/clangformat/clangformatbaseindenter.cpp +++ b/src/plugins/clangformat/clangformatbaseindenter.cpp @@ -39,7 +39,7 @@ namespace ClangFormat { static void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style, ReplacementsToKeep replacementsToKeep) { - style.MaxEmptyLinesToKeep = 2; + style.MaxEmptyLinesToKeep = 100; style.SortIncludes = false; style.SortUsingDeclarations = false; @@ -68,7 +68,6 @@ static clang::tooling::Replacements filteredReplacements( const clang::tooling::Replacements &replacements, int utf8Offset, int utf8Length, - int extraEmptySpaceOffset, ReplacementsToKeep replacementsToKeep) { clang::tooling::Replacements filtered; @@ -81,9 +80,6 @@ static clang::tooling::Replacements filteredReplacements( if (replacementDoesNotMatchRestriction) continue; - if (replacementOffset >= utf8Offset - 1) - replacementOffset += extraEmptySpaceOffset; - llvm::StringRef text = replacementsToKeep == ReplacementsToKeep::OnlyIndent ? clearExtraNewline(replacement.getReplacementText()) : replacement.getReplacementText(); @@ -147,18 +143,23 @@ static int previousEmptyLinesLength(const QTextBlock ¤tBlock) return length; } -static void modifyToIndentEmptyLines( - QByteArray &buffer, int utf8Offset, const QTextBlock &block, bool secondTry) +static int modifyToIndentEmptyLines(QByteArray &buffer, const QTextBlock &block, bool secondTry) { const QString blockText = block.text(); int firstNonWhitespace = Utils::indexOf(blockText, [](const QChar &ch) { return !ch.isSpace(); }); + int utf8Offset = Utils::Text::utf8NthLineOffset(block.document(), + buffer, + block.blockNumber() + 1); if (firstNonWhitespace > 0) utf8Offset += firstNonWhitespace; + else + utf8Offset += blockText.length(); const bool closingParenBlock = firstNonWhitespace >= 0 && blockText.at(firstNonWhitespace) == ')'; + int extraLength = 0; if (firstNonWhitespace < 0 || closingParenBlock) { //This extra text works for the most cases. QByteArray dummyText("a;a;"); @@ -174,6 +175,7 @@ static void modifyToIndentEmptyLines( dummyText = "&& a"; buffer.insert(utf8Offset, dummyText); + extraLength += dummyText.length(); } if (secondTry) { @@ -186,52 +188,61 @@ static void modifyToIndentEmptyLines( // unclosed parentheses. // TODO: Does it help to add different endings depending on the context? buffer.insert(nextLinePos, ')'); + extraLength += 1; } } + + return extraLength; } -static Utils::LineColumn utf16LineColumn(const QTextBlock &block, - int blockOffsetUtf8, - const QByteArray &utf8Buffer, - int utf8Offset) +static Utils::LineColumn utf16LineColumn(const QByteArray &utf8Buffer, int utf8Offset) { - // If lastIndexOf('\n') returns -1 then we are fine to add 1 and get 0 offset. - const int lineStartUtf8Offset = utf8Offset == 0 - ? 0 - : utf8Buffer.lastIndexOf('\n', utf8Offset - 1) + 1; - int line = block.blockNumber() + 1; // Init with the line corresponding the block. - - if (utf8Offset < blockOffsetUtf8) { - line -= static_cast<int>(std::count(utf8Buffer.begin() + lineStartUtf8Offset, - utf8Buffer.begin() + blockOffsetUtf8, - '\n')); - } else { - line += static_cast<int>(std::count(utf8Buffer.begin() + blockOffsetUtf8, - utf8Buffer.begin() + lineStartUtf8Offset, - '\n')); - } + Utils::LineColumn lineColumn; + lineColumn.line = std::count(utf8Buffer.begin(), utf8Buffer.begin() + utf8Offset, '\n') + 1; + lineColumn.column = utf8Offset - utf8Buffer.lastIndexOf('\n', utf8Offset - 1); + return lineColumn; +} - const QByteArray lineText = utf8Buffer.mid(lineStartUtf8Offset, - utf8Offset - lineStartUtf8Offset); - return Utils::LineColumn(line, QString::fromUtf8(lineText).size() + 1); +static QString utf16LineLengthInUtf8Buffer(const QByteArray &utf8Buffer, int currentUtf8Offset) +{ + const int lineStartUtf8Offset = utf8Buffer.lastIndexOf('\n', currentUtf8Offset - 1) + 1; + const int lineEndUtf8Offset = utf8Buffer.indexOf('\n', currentUtf8Offset); + return QString::fromUtf8( + utf8Buffer.mid(lineStartUtf8Offset, lineEndUtf8Offset - lineStartUtf8Offset)); } -static TextEditor::Replacements utf16Replacements(const QTextBlock &block, - int blockOffsetUtf8, +static bool isInsideModifiedLine(const QString &originalLine, + const QString &modifiedLine, + int column) +{ + // Track the cases when we have inserted extra text into the line to get the indentation. + return originalLine.length() < modifiedLine.length() && column != modifiedLine.length() + 1 + && (column > originalLine.length() || originalLine.trimmed().isEmpty() + || !modifiedLine.startsWith(originalLine)); +} + +static TextEditor::Replacements utf16Replacements(const QTextDocument *doc, const QByteArray &utf8Buffer, const clang::tooling::Replacements &replacements) { TextEditor::Replacements convertedReplacements; convertedReplacements.reserve(replacements.size()); + for (const clang::tooling::Replacement &replacement : replacements) { - const Utils::LineColumn lineColUtf16 = utf16LineColumn(block, - blockOffsetUtf8, - utf8Buffer, - static_cast<int>( - replacement.getOffset())); + Utils::LineColumn lineColUtf16 = utf16LineColumn(utf8Buffer, + static_cast<int>(replacement.getOffset())); if (!lineColUtf16.isValid()) continue; - const int utf16Offset = Utils::Text::positionInText(block.document(), + + const QString lineText = doc->findBlockByNumber(lineColUtf16.line - 1).text(); + const QString bufferLineText = utf16LineLengthInUtf8Buffer(utf8Buffer, + replacement.getOffset()); + if (isInsideModifiedLine(lineText, bufferLineText, lineColUtf16.column)) + continue; + + lineColUtf16.column = std::min(lineColUtf16.column, lineText.length() + 1); + + const int utf16Offset = Utils::Text::positionInText(doc, lineColUtf16.line, lineColUtf16.column); const int utf16Length = QString::fromUtf8( @@ -270,14 +281,11 @@ static QString selectedLines(QTextDocument *doc, const QTextBlock &startBlock, const QTextBlock &endBlock) { - QString text = Utils::Text::textAt(QTextCursor(doc), - startBlock.position(), - std::max(0, - endBlock.position() + endBlock.length() - - startBlock.position() - 1)); - while (!text.isEmpty() && text.rbegin()->isSpace()) - text.chop(1); - return text; + return Utils::Text::textAt(QTextCursor(doc), + startBlock.position(), + std::max(0, + endBlock.position() + endBlock.length() + - startBlock.position() - 1)); } ClangFormatBaseIndenter::ClangFormatBaseIndenter(QTextDocument *doc) @@ -358,10 +366,7 @@ TextEditor::Replacements ClangFormatBaseIndenter::format( clang::format::FormattingAttemptStatus status; const clang::tooling::Replacements clangReplacements = reformat(style, buffer.data(), ranges, m_fileName.toString().toStdString(), &status); - const TextEditor::Replacements toReplace = utf16Replacements(block, - utf8Offset, - buffer, - clangReplacements); + const TextEditor::Replacements toReplace = utf16Replacements(m_doc, buffer, clangReplacements); applyReplacements(m_doc, toReplace); return toReplace; @@ -392,7 +397,7 @@ static bool doNotIndentInContext(QTextDocument *doc, int pos) return false; } -void ClangFormatBaseIndenter::indentBlocks(const QTextBlock &startBlock, +void ClangFormatBaseIndenter::indentBlocks(QTextBlock startBlock, const QTextBlock &endBlock, const QChar &typedChar, int cursorPositionInEditor) @@ -403,6 +408,15 @@ void ClangFormatBaseIndenter::indentBlocks(const QTextBlock &startBlock, return; } + if (startBlock.position() > 0) { + startBlock = startBlock.previous(); + while (startBlock.position() > 0 && startBlock.text().trimmed().isEmpty()) + startBlock = startBlock.previous(); + if (!startBlock.text().trimmed().isEmpty()) { + startBlock = startBlock.next(); + } + } + const int startBlockPosition = startBlock.position(); trimFirstNonEmptyBlock(startBlock); if (cursorPositionInEditor >= 0) @@ -564,22 +578,20 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) rangeStart = formattingRangeStart(startBlock, buffer, lastSaveRevision()); - int extraEmptySpaceOffset = previousEmptyLinesLength(startBlock); - utf8Offset -= extraEmptySpaceOffset; - buffer.remove(utf8Offset, extraEmptySpaceOffset); - - adjustFormatStyleForLineBreak(style, replacementsToKeep); - if (typedChar == QChar::Null && startBlock == endBlock) { - modifyToIndentEmptyLines(buffer, utf8Offset, startBlock, secondTry); - utf8Length = 0; - } - if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) { buffer.insert(utf8Offset - 1, " //"); - extraEmptySpaceOffset -= 3; utf8Offset += 3; } + adjustFormatStyleForLineBreak(style, replacementsToKeep); + if (typedChar == QChar::Null) { + for (int index = startBlock.blockNumber(); index <= endBlock.blockNumber(); ++index) { + utf8Length += modifyToIndentEmptyLines(buffer, + m_doc->findBlockByNumber(index), + secondTry); + } + } + if (replacementsToKeep != ReplacementsToKeep::IndentAndBefore || utf8Offset < rangeStart) rangeStart = utf8Offset; @@ -601,7 +613,6 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer clangReplacements, utf8Offset, utf8Length, - extraEmptySpaceOffset, replacementsToKeep); } const bool canTryAgain = replacementsToKeep == ReplacementsToKeep::OnlyIndent @@ -617,7 +628,7 @@ TextEditor::Replacements ClangFormatBaseIndenter::replacements(QByteArray buffer true); } - return utf16Replacements(startBlock, originalOffsetUtf8, originalBuffer, filtered); + return utf16Replacements(m_doc, buffer, filtered); } } // namespace ClangFormat diff --git a/src/plugins/clangformat/clangformatbaseindenter.h b/src/plugins/clangformat/clangformatbaseindenter.h index 272cbd648f..360f27fbed 100644 --- a/src/plugins/clangformat/clangformatbaseindenter.h +++ b/src/plugins/clangformat/clangformatbaseindenter.h @@ -75,7 +75,7 @@ protected: private: void indent(const QTextCursor &cursor, const QChar &typedChar, int cursorPositionInEditor); - void indentBlocks(const QTextBlock &startBlock, + void indentBlocks(QTextBlock startBlock, const QTextBlock &endBlock, const QChar &typedChar, int cursorPositionInEditor); |