diff options
author | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2019-04-07 20:40:29 +0300 |
---|---|---|
committer | Orgad Shaneh <orgad.shaneh@audiocodes.com> | 2019-04-07 23:13:17 +0300 |
commit | 39ba01da711c07c43abe8aeacedd98990874ba82 (patch) | |
tree | 4a1c8853bd8db754fbf57eac5fff21b7e7342c8a /src/plugins/clangformat | |
parent | a33386e014db5fdf65903654e9b1ae542ee36c0f (diff) | |
parent | 5273ef2a8aa3c8d268b107edc770b53e1aed7803 (diff) | |
download | qt-creator-39ba01da711c07c43abe8aeacedd98990874ba82.tar.gz |
Merge remote-tracking branch 'origin/4.9'
Change-Id: I7d1912cd5c4d824fd40d3454c5f1bb796f2c21d8
Diffstat (limited to 'src/plugins/clangformat')
-rw-r--r-- | src/plugins/clangformat/clangformatbaseindenter.cpp | 89 | ||||
-rw-r--r-- | src/plugins/clangformat/clangformatconfigwidget.cpp | 17 | ||||
-rw-r--r-- | src/plugins/clangformat/clangformatutils.cpp | 7 |
3 files changed, 81 insertions, 32 deletions
diff --git a/src/plugins/clangformat/clangformatbaseindenter.cpp b/src/plugins/clangformat/clangformatbaseindenter.cpp index 2e039c5ec1..c7968a5c1c 100644 --- a/src/plugins/clangformat/clangformatbaseindenter.cpp +++ b/src/plugins/clangformat/clangformatbaseindenter.cpp @@ -47,6 +47,7 @@ void adjustFormatStyleForLineBreak(clang::format::FormatStyle &style, // This is a separate pass, don't do it unless it's the full formatting. style.FixNamespaceComments = false; + style.AlignTrailingComments = false; if (replacementsToKeep == ReplacementsToKeep::IndentAndBefore) return; @@ -118,13 +119,11 @@ void trimRHSWhitespace(const QTextBlock &block) const int extraSpaceCount = static_cast<int>(std::distance(initialText.rbegin(), lastNonSpace)); QTextCursor cursor(block); - cursor.beginEditBlock(); cursor.movePosition(QTextCursor::Right, QTextCursor::MoveAnchor, initialText.size() - extraSpaceCount); cursor.movePosition(QTextCursor::Right, QTextCursor::KeepAnchor, extraSpaceCount); cursor.removeSelectedText(); - cursor.endEditBlock(); } QTextBlock reverseFindLastEmptyBlock(QTextBlock start) @@ -139,7 +138,13 @@ QTextBlock reverseFindLastEmptyBlock(QTextBlock start) return start; } -enum class CharacterContext { AfterComma, LastAfterComma, NewStatement, Continuation, Unknown }; +enum class CharacterContext { + AfterComma, + LastAfterComma, + NewStatementOrContinuation, + IfOrElseWithoutScope, + Unknown +}; QChar findFirstNonWhitespaceCharacter(const QTextBlock ¤tBlock) { @@ -150,10 +155,42 @@ QChar findFirstNonWhitespaceCharacter(const QTextBlock ¤tBlock) return currentPos < doc->characterCount() ? doc->characterAt(currentPos) : QChar::Null; } +int findMatchingOpeningParen(const QTextBlock &blockEndingWithClosingParen) +{ + const QTextDocument *doc = blockEndingWithClosingParen.document(); + int currentPos = blockEndingWithClosingParen.position() + + blockEndingWithClosingParen.text().lastIndexOf(')'); + int parenBalance = 1; + + while (currentPos > 0 && parenBalance > 0) { + --currentPos; + if (doc->characterAt(currentPos) == ')') + ++parenBalance; + if (doc->characterAt(currentPos) == '(') + --parenBalance; + } + + if (parenBalance == 0) + return currentPos; + + return -1; +} + +bool comesDirectlyAfterIf(const QTextDocument *doc, int pos) +{ + --pos; + while (pos > 0 && doc->characterAt(pos).isSpace()) + --pos; + return pos > 0 && doc->characterAt(pos) == 'f' && doc->characterAt(pos - 1) == 'i'; +} + CharacterContext characterContext(const QTextBlock ¤tBlock, const QTextBlock &previousNonEmptyBlock) { const QString prevLineText = previousNonEmptyBlock.text().trimmed(); + if (prevLineText.isEmpty()) + return CharacterContext::NewStatementOrContinuation; + const QChar firstNonWhitespaceChar = findFirstNonWhitespaceCharacter(currentBlock); if (prevLineText.endsWith(',')) { // We don't need to add comma in case it's the last argument. @@ -162,12 +199,15 @@ CharacterContext characterContext(const QTextBlock ¤tBlock, return CharacterContext::AfterComma; } - if (prevLineText.endsWith(';') || prevLineText.endsWith('{') || prevLineText.endsWith('}') - || firstNonWhitespaceChar == QChar::Null) { - return CharacterContext::NewStatement; + if (prevLineText.endsWith("else")) + return CharacterContext::IfOrElseWithoutScope; + if (prevLineText.endsWith(')')) { + const int pos = findMatchingOpeningParen(previousNonEmptyBlock); + if (pos >= 0 && comesDirectlyAfterIf(previousNonEmptyBlock.document(), pos)) + return CharacterContext::IfOrElseWithoutScope; } - return CharacterContext::Continuation; + return CharacterContext::NewStatementOrContinuation; } bool nextBlockExistsAndEmpty(const QTextBlock ¤tBlock) @@ -181,20 +221,18 @@ bool nextBlockExistsAndEmpty(const QTextBlock ¤tBlock) QByteArray dummyTextForContext(CharacterContext context, bool closingBraceBlock) { - if (closingBraceBlock - && (context == CharacterContext::NewStatement - || context == CharacterContext::Continuation)) { + if (closingBraceBlock && context == CharacterContext::NewStatementOrContinuation) return QByteArray(); - } switch (context) { case CharacterContext::AfterComma: return "a,"; - case CharacterContext::NewStatement: - return "a;"; - case CharacterContext::Continuation: case CharacterContext::LastAfterComma: - return "& a &"; + return "a"; + case CharacterContext::IfOrElseWithoutScope: + return ";"; + case CharacterContext::NewStatementOrContinuation: + return "/**/"; case CharacterContext::Unknown: default: QTC_ASSERT(false, return "";); @@ -202,7 +240,7 @@ QByteArray dummyTextForContext(CharacterContext context, bool closingBraceBlock) } // Add extra text in case of the empty line or the line starting with ')'. -// Track such extra pieces of text in isInsideModifiedLine(). +// Track such extra pieces of text in isInsideDummyTextInLine(). int forceIndentWithExtraText(QByteArray &buffer, CharacterContext &charContext, const QTextBlock &block, @@ -265,7 +303,7 @@ int forceIndentWithExtraText(QByteArray &buffer, return extraLength; } -bool isInsideModifiedLine(const QString &originalLine, const QString &modifiedLine, int column) +bool isInsideDummyTextInLine(const QString &originalLine, const QString &modifiedLine, int column) { // Detect the cases when we have inserted extra text into the line to get the indentation. return originalLine.length() < modifiedLine.length() && column != modifiedLine.length() + 1 @@ -291,7 +329,7 @@ TextEditor::Replacements utf16Replacements(const QTextDocument *doc, const QString bufferLineText = Utils::Text::utf16LineTextInUtf8Buffer(utf8Buffer, static_cast<int>(replacement.getOffset())); - if (isInsideModifiedLine(lineText, bufferLineText, lineColUtf16.column)) + if (isInsideDummyTextInLine(lineText, bufferLineText, lineColUtf16.column)) continue; lineColUtf16.column = std::min(lineColUtf16.column, lineText.length() + 1); @@ -319,14 +357,12 @@ void applyReplacements(QTextDocument *doc, const TextEditor::Replacements &repla int fullOffsetShift = 0; QTextCursor editCursor(doc); for (const TextEditor::Replacement &replacement : replacements) { - editCursor.beginEditBlock(); editCursor.setPosition(replacement.offset + fullOffsetShift); editCursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, replacement.length); editCursor.removeSelectedText(); editCursor.insertText(replacement.text); - editCursor.endEditBlock(); fullOffsetShift += replacement.text.length() - replacement.length; } } @@ -510,8 +546,11 @@ TextEditor::Replacements ClangFormatBaseIndenter::format( ranges = clang::tooling::calculateRangesAfterReplacements(clangReplacements, ranges); clang::format::FormattingAttemptStatus status; - const clang::tooling::Replacements formatReplacements - = reformat(style, *changedCode, ranges, m_fileName.toString().toStdString(), &status); + const clang::tooling::Replacements formatReplacements = reformat(style, + *changedCode, + ranges, + assumedFileName, + &status); clangReplacements = clangReplacements.merge(formatReplacements); const TextEditor::Replacements toReplace = utf16Replacements(m_doc, buffer, clangReplacements); @@ -533,7 +572,7 @@ TextEditor::Replacements ClangFormatBaseIndenter::indentsFor(QTextBlock startBlo startBlock = reverseFindLastEmptyBlock(startBlock); const int startBlockPosition = startBlock.position(); - if (startBlock.position() > 0) { + if (startBlockPosition > 0) { trimRHSWhitespace(startBlock.previous()); if (cursorPositionInEditor >= 0) cursorPositionInEditor += startBlock.position() - startBlockPosition; @@ -548,9 +587,9 @@ TextEditor::Replacements ClangFormatBaseIndenter::indentsFor(QTextBlock startBlo // Format before current position only in case the cursor is inside the indented block. // So if cursor position is less then the block position then the current line is before // the indented block - don't trigger extra formatting in this case. - // cursorPositionInEditor == -1 means the consition matches automatically. + // cursorPositionInEditor == -1 means the condition matches automatically. - // Format only before newline or complete statement not to break code. + // Format only before complete statement not to break code. replacementsToKeep = ReplacementsToKeep::IndentAndBefore; } diff --git a/src/plugins/clangformat/clangformatconfigwidget.cpp b/src/plugins/clangformat/clangformatconfigwidget.cpp index 72e1778999..4f2d77a6f7 100644 --- a/src/plugins/clangformat/clangformatconfigwidget.cpp +++ b/src/plugins/clangformat/clangformatconfigwidget.cpp @@ -125,11 +125,17 @@ void ClangFormatConfigWidget::initialize() if (lastItem->spacerItem()) m_ui->verticalLayout->removeItem(lastItem); + m_ui->clangFormatOptionsTable->setEnabled(true); if (!m_ui->overrideDefault->isChecked()) { - m_ui->clangFormatOptionsTable->hide(); - m_preview->hide(); - m_ui->verticalLayout->addStretch(1); - return; + if (m_project) { + m_ui->clangFormatOptionsTable->hide(); + m_preview->hide(); + m_ui->verticalLayout->addStretch(1); + return; + } else { + // Show the fallback configuration only globally. + m_ui->clangFormatOptionsTable->setEnabled(false); + } } m_ui->clangFormatOptionsTable->show(); @@ -145,6 +151,7 @@ void ClangFormatConfigWidget::initialize() if (!currentProject || !projectConfigExists()) { m_ui->projectHasClangFormat->hide(); } else { + m_ui->projectHasClangFormat->show(); m_ui->projectHasClangFormat->setText( tr("Current project has its own overridden .clang-format file " "and can be configured in Projects > Code Style > C++.")); @@ -189,7 +196,7 @@ void ClangFormatConfigWidget::apply() } settings.write(); - if (!m_ui->overrideDefault->isChecked()) + if (!m_ui->clangFormatOptionsTable->isVisible()) return; const QString text = m_ui->clangFormatOptionsTable->toPlainText(); diff --git a/src/plugins/clangformat/clangformatutils.cpp b/src/plugins/clangformat/clangformatutils.cpp index 61e9386282..09a3150c89 100644 --- a/src/plugins/clangformat/clangformatutils.cpp +++ b/src/plugins/clangformat/clangformatutils.cpp @@ -293,8 +293,11 @@ static QByteArray configBaseStyleName(const QString &configFile) static clang::format::FormatStyle styleForFile(Utils::FileName fileName, bool checkForSettings) { QString configFile = configForFile(fileName, checkForSettings); - if (configFile.isEmpty()) - return constructStyle(); + if (configFile.isEmpty()) { + // If no configuration is found create a global one (if it does not yet exist) and use it. + createStyleFileIfNeeded(true); + configFile = globalPath().appendPath(Constants::SETTINGS_FILE_NAME).toString(); + } fileName = assumedPathForConfig(configFile); Expected<FormatStyle> style = format::getStyle("file", |