forked from qt-creator/qt-creator
ClangFormat: Take line context into account when formatting
In some cases indenting/formatting after special characters can break the code. Let's try to avoid such corner cases. Change-Id: I8918bc460af31d696e49f60e0ea85f34e9ff5664 Fixes: QTCREATORBUG-21474 Reviewed-by: Marco Bubke <marco.bubke@qt.io>
This commit is contained in:
@@ -408,6 +408,36 @@ int ClangFormatBaseIndenter::indentBeforeCursor(const QTextBlock &block,
|
|||||||
return cursorPositionInEditor;
|
return cursorPositionInEditor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool doNotIndentInContext(QTextDocument *doc, int pos)
|
||||||
|
{
|
||||||
|
const QChar character = doc->characterAt(pos);
|
||||||
|
const QTextBlock currentBlock = doc->findBlock(pos);
|
||||||
|
const QString text = currentBlock.text().left(pos - currentBlock.position());
|
||||||
|
switch (character.toLatin1()) {
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
case ':':
|
||||||
|
// Do not indent when it's the first ':' and it's not the 'case' line.
|
||||||
|
if (text.contains(QLatin1String("case")) || text.contains(QLatin1String("default"))
|
||||||
|
|| text.contains(QLatin1String("public")) || text.contains(QLatin1String("private"))
|
||||||
|
|| text.contains(QLatin1String("protected")) || text.contains(QLatin1String("signals"))
|
||||||
|
|| text.contains(QLatin1String("Q_SIGNALS"))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (pos > 0 && doc->characterAt(pos - 1) != ':')
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
// "<<" and ">>" could be problematic
|
||||||
|
if (pos > 0 && doc->characterAt(pos - 1) == character)
|
||||||
|
return true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
||||||
const QChar &typedChar,
|
const QChar &typedChar,
|
||||||
int cursorPositionInEditor)
|
int cursorPositionInEditor)
|
||||||
@@ -416,12 +446,21 @@ void ClangFormatBaseIndenter::indentBlock(const QTextBlock &block,
|
|||||||
const int blockPosition = currentBlock.position();
|
const int blockPosition = currentBlock.position();
|
||||||
trimFirstNonEmptyBlock(currentBlock);
|
trimFirstNonEmptyBlock(currentBlock);
|
||||||
|
|
||||||
|
if (typedChar != QChar::Null && cursorPositionInEditor > 0
|
||||||
|
&& m_doc->characterAt(cursorPositionInEditor - 1) == typedChar
|
||||||
|
&& doNotIndentInContext(m_doc, cursorPositionInEditor - 1)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (formatWhileTyping()
|
if (formatWhileTyping()
|
||||||
&& (cursorPositionInEditor == -1 || cursorPositionInEditor >= blockPosition)) {
|
&& (cursorPositionInEditor == -1 || cursorPositionInEditor >= blockPosition)
|
||||||
|
&& (typedChar == QChar::Null || typedChar == ';' || typedChar == '}')) {
|
||||||
// Format before current position only in case the cursor is inside the indented block.
|
// 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
|
// 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.
|
// the indented block - don't trigger extra formatting in this case.
|
||||||
// cursorPositionInEditor == -1 means the consition matches automatically.
|
// cursorPositionInEditor == -1 means the consition matches automatically.
|
||||||
|
|
||||||
|
// Format only before newline or complete statement not to break code.
|
||||||
if (cursorPositionInEditor >= 0)
|
if (cursorPositionInEditor >= 0)
|
||||||
cursorPositionInEditor += currentBlock.position() - blockPosition;
|
cursorPositionInEditor += currentBlock.position() - blockPosition;
|
||||||
else
|
else
|
||||||
|
Reference in New Issue
Block a user