forked from qt-creator/qt-creator
CppEditor: Do not underline leading whitespace
... when visualizing the range of a code model warning. Otherwise, warnings covering multiple lines can get too noisy. Fixes: QTCREATORBUG-18659 Change-Id: Ieff7729d8069e791027f7bdde5fca13f4c7f7163 Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -205,6 +205,9 @@ private slots:
|
|||||||
void test_useSelections_data();
|
void test_useSelections_data();
|
||||||
void test_useSelections();
|
void test_useSelections();
|
||||||
|
|
||||||
|
void test_selectionFiltering_data();
|
||||||
|
void test_selectionFiltering();
|
||||||
|
|
||||||
// tests for "Include Hierarchy"
|
// tests for "Include Hierarchy"
|
||||||
void test_includehierarchy_data();
|
void test_includehierarchy_data();
|
||||||
void test_includehierarchy();
|
void test_includehierarchy();
|
||||||
|
@@ -326,7 +326,8 @@ void CppEditorWidget::onCodeWarningsUpdated(unsigned revision,
|
|||||||
if (revision != documentRevision())
|
if (revision != documentRevision())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
setExtraSelections(TextEditorWidget::CodeWarningsSelection, selections);
|
setExtraSelections(TextEditorWidget::CodeWarningsSelection,
|
||||||
|
unselectLeadingWhitespace(selections));
|
||||||
setRefactorMarkers(refactorMarkers + RefactorMarker::filterOutType(
|
setRefactorMarkers(refactorMarkers + RefactorMarker::filterOutType(
|
||||||
this->refactorMarkers(), CppTools::Constants::CPP_CLANG_FIXIT_AVAILABLE_MARKER_ID));
|
this->refactorMarkers(), CppTools::Constants::CPP_CLANG_FIXIT_AVAILABLE_MARKER_ID));
|
||||||
}
|
}
|
||||||
@@ -1163,6 +1164,63 @@ void CppEditorWidget::invokeTextEditorWidgetAssist(TextEditor::AssistKind assist
|
|||||||
invokeAssist(assistKind, provider);
|
invokeAssist(assistKind, provider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QList<QTextEdit::ExtraSelection> CppEditorWidget::unselectLeadingWhitespace(
|
||||||
|
const QList<QTextEdit::ExtraSelection> &selections)
|
||||||
|
{
|
||||||
|
QList<QTextEdit::ExtraSelection> filtered;
|
||||||
|
for (const QTextEdit::ExtraSelection &sel : selections) {
|
||||||
|
QList<QTextEdit::ExtraSelection> splitSelections;
|
||||||
|
int firstNonWhitespacePos = -1;
|
||||||
|
int lastNonWhitespacePos = -1;
|
||||||
|
bool split = false;
|
||||||
|
const QTextBlock firstBlock = sel.cursor.document()->findBlock(sel.cursor.selectionStart());
|
||||||
|
bool inIndentation = firstBlock.position() == sel.cursor.selectionStart();
|
||||||
|
const auto createSplitSelection = [&] {
|
||||||
|
QTextEdit::ExtraSelection newSelection;
|
||||||
|
newSelection.cursor = QTextCursor(sel.cursor.document());
|
||||||
|
newSelection.cursor.setPosition(firstNonWhitespacePos);
|
||||||
|
newSelection.cursor.setPosition(lastNonWhitespacePos + 1, QTextCursor::KeepAnchor);
|
||||||
|
newSelection.format = sel.format;
|
||||||
|
splitSelections << newSelection;
|
||||||
|
};
|
||||||
|
for (int i = sel.cursor.selectionStart(); i < sel.cursor.selectionEnd(); ++i) {
|
||||||
|
const QChar curChar = sel.cursor.document()->characterAt(i);
|
||||||
|
if (!curChar.isSpace()) {
|
||||||
|
if (firstNonWhitespacePos == -1)
|
||||||
|
firstNonWhitespacePos = i;
|
||||||
|
lastNonWhitespacePos = i;
|
||||||
|
}
|
||||||
|
if (!inIndentation) {
|
||||||
|
if (curChar == QChar::ParagraphSeparator)
|
||||||
|
inIndentation = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (curChar == QChar::ParagraphSeparator)
|
||||||
|
continue;
|
||||||
|
if (curChar.isSpace()) {
|
||||||
|
if (firstNonWhitespacePos != -1) {
|
||||||
|
createSplitSelection();
|
||||||
|
firstNonWhitespacePos = -1;
|
||||||
|
lastNonWhitespacePos = -1;
|
||||||
|
}
|
||||||
|
split = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
inIndentation = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!split) {
|
||||||
|
filtered << sel;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (firstNonWhitespacePos != -1)
|
||||||
|
createSplitSelection();
|
||||||
|
filtered << splitSelections;
|
||||||
|
}
|
||||||
|
return filtered;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CppEditor
|
} // namespace CppEditor
|
||||||
|
|
||||||
|
@@ -94,6 +94,9 @@ public:
|
|||||||
void invokeTextEditorWidgetAssist(TextEditor::AssistKind assistKind,
|
void invokeTextEditorWidgetAssist(TextEditor::AssistKind assistKind,
|
||||||
TextEditor::IAssistProvider *provider) override;
|
TextEditor::IAssistProvider *provider) override;
|
||||||
|
|
||||||
|
static const QList<QTextEdit::ExtraSelection>
|
||||||
|
unselectLeadingWhitespace(const QList<QTextEdit::ExtraSelection> &selections);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
bool event(QEvent *e) override;
|
bool event(QEvent *e) override;
|
||||||
void contextMenuEvent(QContextMenuEvent *) override;
|
void contextMenuEvent(QContextMenuEvent *) override;
|
||||||
|
@@ -249,5 +249,70 @@ void CppEditorPlugin::test_useSelections()
|
|||||||
Tests::UseSelectionsTestCase(testDocument, expectedSelections);
|
Tests::UseSelectionsTestCase(testDocument, expectedSelections);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppEditorPlugin::test_selectionFiltering_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QString>("source");
|
||||||
|
QTest::addColumn<SelectionList>("original");
|
||||||
|
QTest::addColumn<SelectionList>("filtered");
|
||||||
|
|
||||||
|
QTest::addRow("QTCREATORBUG-18659")
|
||||||
|
<< QString("int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" [](const Foo &foo) -> Foo {\n"
|
||||||
|
" return foo;\n"
|
||||||
|
" };\n"
|
||||||
|
"}\n")
|
||||||
|
<< SelectionList{{3, 4, 53}}
|
||||||
|
<< SelectionList{{3, 4, 27}, {4, 8, 11}, {5, 4, 1}};
|
||||||
|
QTest::addRow("indentation-selected-in-first-line")
|
||||||
|
<< QString("int main()\n"
|
||||||
|
"{\n"
|
||||||
|
" [](const Foo &foo) -> Foo {\n"
|
||||||
|
" return foo;\n"
|
||||||
|
" };\n"
|
||||||
|
"}\n")
|
||||||
|
<< SelectionList{{3, 0, 57}}
|
||||||
|
<< SelectionList{{3, 4, 27}, {4, 8, 11}, {5, 4, 1}};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CppEditorPlugin::test_selectionFiltering()
|
||||||
|
{
|
||||||
|
QFETCH(QString, source);
|
||||||
|
QFETCH(SelectionList, original);
|
||||||
|
QFETCH(SelectionList, filtered);
|
||||||
|
|
||||||
|
QTextDocument doc;
|
||||||
|
doc.setPlainText(source);
|
||||||
|
|
||||||
|
const auto convertList = [&doc](const SelectionList &in) {
|
||||||
|
QList<QTextEdit::ExtraSelection> out;
|
||||||
|
for (const Selection &selIn : in) {
|
||||||
|
QTextEdit::ExtraSelection selOut;
|
||||||
|
selOut.format.setFontItalic(true);
|
||||||
|
const QTextBlock startBlock = doc.findBlockByLineNumber(selIn.line - 1);
|
||||||
|
const int startPos = startBlock.position() + selIn.column;
|
||||||
|
selOut.cursor = QTextCursor(&doc);
|
||||||
|
selOut.cursor.setPosition(startPos);
|
||||||
|
selOut.cursor.setPosition(startPos + selIn.length, QTextCursor::KeepAnchor);
|
||||||
|
out << selOut;
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
};
|
||||||
|
|
||||||
|
const QList<QTextEdit::ExtraSelection> expected = convertList(filtered);
|
||||||
|
const QList<QTextEdit::ExtraSelection> actual
|
||||||
|
= CppEditorWidget::unselectLeadingWhitespace(convertList(original));
|
||||||
|
|
||||||
|
QCOMPARE(actual.length(), expected.length());
|
||||||
|
for (int i = 0; i < expected.length(); ++i) {
|
||||||
|
const QTextEdit::ExtraSelection &expectedSelection = expected.at(i);
|
||||||
|
const QTextEdit::ExtraSelection &actualSelection = actual.at(i);
|
||||||
|
QCOMPARE(actualSelection.format, expectedSelection.format);
|
||||||
|
QCOMPARE(actualSelection.cursor.document(), expectedSelection.cursor.document());
|
||||||
|
QCOMPARE(actualSelection.cursor.position(), expectedSelection.cursor.position());
|
||||||
|
QCOMPARE(actualSelection.cursor.anchor(), expectedSelection.cursor.anchor());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace CppEditor
|
} // namespace CppEditor
|
||||||
|
Reference in New Issue
Block a user