diff options
-rw-r--r-- | src/plugins/texteditor/syntaxhighlighter.cpp | 16 | ||||
-rw-r--r-- | src/plugins/texteditor/syntaxhighlighter.h | 5 | ||||
-rw-r--r-- | tests/auto/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/auto.qbs | 1 | ||||
-rw-r--r-- | tests/auto/texteditor/CMakeLists.txt | 1 | ||||
-rw-r--r-- | tests/auto/texteditor/highlighter/CMakeLists.txt | 4 | ||||
-rw-r--r-- | tests/auto/texteditor/highlighter/highlighter.qbs | 15 | ||||
-rw-r--r-- | tests/auto/texteditor/highlighter/tst_highlighter.cpp | 317 | ||||
-rw-r--r-- | tests/auto/texteditor/texteditor.qbs | 6 |
9 files changed, 365 insertions, 1 deletions
diff --git a/src/plugins/texteditor/syntaxhighlighter.cpp b/src/plugins/texteditor/syntaxhighlighter.cpp index de72c7b0db6..6d2616193ef 100644 --- a/src/plugins/texteditor/syntaxhighlighter.cpp +++ b/src/plugins/texteditor/syntaxhighlighter.cpp @@ -23,8 +23,12 @@ class SyntaxHighlighterPrivate Q_DECLARE_PUBLIC(SyntaxHighlighter) public: SyntaxHighlighterPrivate() + : SyntaxHighlighterPrivate(TextEditorSettings::fontSettings()) + { } + + SyntaxHighlighterPrivate(const FontSettings &fontSettings) { - updateFormats(TextEditorSettings::fontSettings()); + updateFormats(fontSettings); } QPointer<QTextDocument> doc; @@ -76,6 +80,16 @@ void SyntaxHighlighter::delayedRehighlight() rehighlight(); } +#ifdef WITH_TESTS +SyntaxHighlighter::SyntaxHighlighter(QTextDocument *parent, const FontSettings &fontsettings) + : QObject(parent), d_ptr(new SyntaxHighlighterPrivate(fontsettings)) +{ + d_ptr->q_ptr = this; + if (parent) + setDocument(parent); +} +#endif + void SyntaxHighlighterPrivate::applyFormatChanges(int from, int charsRemoved, int charsAdded) { bool formatsChanged = false; diff --git a/src/plugins/texteditor/syntaxhighlighter.h b/src/plugins/texteditor/syntaxhighlighter.h index 7a1822e4667..1b66e2ff56a 100644 --- a/src/plugins/texteditor/syntaxhighlighter.h +++ b/src/plugins/texteditor/syntaxhighlighter.h @@ -91,6 +91,11 @@ private: void delayedRehighlight(); QScopedPointer<SyntaxHighlighterPrivate> d_ptr; + +#ifdef WITH_TESTS + friend class tst_highlighter; + SyntaxHighlighter(QTextDocument *parent, const FontSettings &fontsettings); +#endif }; } // namespace TextEditor diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt index 9849f8776ec..5dcd026a7af 100644 --- a/tests/auto/CMakeLists.txt +++ b/tests/auto/CMakeLists.txt @@ -20,6 +20,7 @@ add_subdirectory(qml) add_subdirectory(runextensions) add_subdirectory(sdktool) add_subdirectory(solutions) +add_subdirectory(texteditor) add_subdirectory(toolchaincache) add_subdirectory(tracing) add_subdirectory(treeviewfind) diff --git a/tests/auto/auto.qbs b/tests/auto/auto.qbs index 063977537ba..603b5cd1b15 100644 --- a/tests/auto/auto.qbs +++ b/tests/auto/auto.qbs @@ -23,6 +23,7 @@ Project { "runextensions/runextensions.qbs", "sdktool/sdktool.qbs", "solutions/solutions.qbs", + "texteditor/texteditor.qbs", "toolchaincache/toolchaincache.qbs", "tracing/tracing.qbs", "treeviewfind/treeviewfind.qbs", diff --git a/tests/auto/texteditor/CMakeLists.txt b/tests/auto/texteditor/CMakeLists.txt new file mode 100644 index 00000000000..23684431c43 --- /dev/null +++ b/tests/auto/texteditor/CMakeLists.txt @@ -0,0 +1 @@ +add_subdirectory(highlighter) diff --git a/tests/auto/texteditor/highlighter/CMakeLists.txt b/tests/auto/texteditor/highlighter/CMakeLists.txt new file mode 100644 index 00000000000..76370bf8255 --- /dev/null +++ b/tests/auto/texteditor/highlighter/CMakeLists.txt @@ -0,0 +1,4 @@ +add_qtc_test(tst_highlighter + DEPENDS TextEditor Utils Qt::Widgets + SOURCES tst_highlighter.cpp +) diff --git a/tests/auto/texteditor/highlighter/highlighter.qbs b/tests/auto/texteditor/highlighter/highlighter.qbs new file mode 100644 index 00000000000..641a71ef66d --- /dev/null +++ b/tests/auto/texteditor/highlighter/highlighter.qbs @@ -0,0 +1,15 @@ +import qbs + +QtcAutotest { + + Depends { name: "TextEditor" } + Depends { name: "Utils" } + Depends { name: "Qt.widgets" } // For QTextDocument & friends + + name: "Highlighter autotest" + + Group { + name: "Source Files" + files: "tst_highlighter.cpp" + } +} diff --git a/tests/auto/texteditor/highlighter/tst_highlighter.cpp b/tests/auto/texteditor/highlighter/tst_highlighter.cpp new file mode 100644 index 00000000000..163699c0cb1 --- /dev/null +++ b/tests/auto/texteditor/highlighter/tst_highlighter.cpp @@ -0,0 +1,317 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef WITH_TESTS +#define WITH_TESTS +#endif + +#include <texteditor/semantichighlighter.h> +#include <texteditor/syntaxhighlighter.h> +#include <texteditor/texteditorsettings.h> + +#include <QObject> +#include <QTextBlock> +#include <QTextDocument> +#include <QtTest> + +namespace TextEditor { + +class tst_highlighter: public QObject +{ + Q_OBJECT + +private slots: + void init_testCase(); + void init(); + void test_setExtraAdditionalFormats(); + void test_clearExtraFormats(); + void test_incrementalApplyAdditionalFormats(); + void cleanup(); + +private: + QTextDocument *doc = nullptr; + SyntaxHighlighter *highlighter = nullptr; + FontSettings fontsettings; + QHash<int, QTextCharFormat> formatHash; + QTextCharFormat whitespaceFormat; +}; + +void tst_highlighter::init_testCase() +{ + QTextCharFormat c0; + c0.setFontItalic(true); + formatHash[0] = c0; + QTextCharFormat c1; + c1.setFontOverline(true); + formatHash[1] = c1; +} + +void tst_highlighter::init() +{ + const QString text = +R"(First +Second with spaces + +Last)"; + + + doc = new QTextDocument(); + doc->setPlainText(text); + + highlighter = new SyntaxHighlighter(doc, fontsettings); +} + +static const HighlightingResults &highlightingResults() +{ + static HighlightingResults results{HighlightingResult(), + HighlightingResult(1, 1, 5, 0), + HighlightingResult(2, 4, 7, 0), + HighlightingResult(2, 17, 5, 1), + HighlightingResult(4, 1, 8, 0), + HighlightingResult(6, 1, 8, 1)}; + return results; +} + +void tst_highlighter::test_setExtraAdditionalFormats() +{ + QCOMPARE(doc->blockCount(), 4); + + SemanticHighlighter::setExtraAdditionalFormats(highlighter, highlightingResults(), formatHash); + + for (auto block = doc->firstBlock(); block.isValid(); block = block.next()) { + QVERIFY(block.blockNumber() < 4); + QVERIFY(block.layout()); + auto formats = block.layout()->formats(); + switch (block.blockNumber()) { + case 0: // First + QCOMPARE(formats.size(), 1); + QCOMPARE(formats.at(0).format.fontItalic(), true); + QCOMPARE(formats.at(0).format.fontOverline(), false); + QCOMPARE(formats.at(0).start, 0); + QCOMPARE(formats.at(0).length, 5); + break; + case 1: // Second with spaces + QCOMPARE(formats.size(), 4); + QCOMPARE(formats.at(0).format.fontItalic(), false); + QCOMPARE(formats.at(0).format.fontOverline(), false); + QCOMPARE(formats.at(0).start, 6); + QCOMPARE(formats.at(0).length, 1); + + QCOMPARE(formats.at(1).format.fontItalic(), false); + QCOMPARE(formats.at(1).format.fontOverline(), false); + QCOMPARE(formats.at(1).start, 11); + QCOMPARE(formats.at(1).length, 1); + + QCOMPARE(formats.at(2).format.fontItalic(), true); + QCOMPARE(formats.at(2).format.fontOverline(), false); + QCOMPARE(formats.at(2).start, 3); + QCOMPARE(formats.at(2).length, 7); + + QCOMPARE(formats.at(3).format.fontItalic(), false); + QCOMPARE(formats.at(3).format.fontOverline(), true); + QCOMPARE(formats.at(3).start, 16); + QCOMPARE(formats.at(3).length, 3); + break; + case 2: // + QCOMPARE(formats.size(), 1); + QCOMPARE(formats.at(0).format.fontItalic(), false); + QCOMPARE(formats.at(0).format.fontOverline(), true); + QCOMPARE(formats.at(0).start, 0); + QCOMPARE(formats.at(0).length, 1); + break; + case 3: // Last + QCOMPARE(formats.size(), 2); + QCOMPARE(formats.at(0).format.fontItalic(), false); + QCOMPARE(formats.at(0).format.fontOverline(), true); + QCOMPARE(formats.at(0).start, 0); + QCOMPARE(formats.at(0).length, 1); + + QCOMPARE(formats.at(1).format.fontItalic(), true); + QCOMPARE(formats.at(1).format.fontOverline(), false); + QCOMPARE(formats.at(1).start, 0); + QCOMPARE(formats.at(1).length, 5); + break; + } + } +} + +void tst_highlighter::test_clearExtraFormats() +{ + QCOMPARE(doc->blockCount(), 4); + + SemanticHighlighter::setExtraAdditionalFormats(highlighter, highlightingResults(), formatHash); + + QTextBlock firstBlock = doc->findBlockByNumber(0); + QTextBlock spacesLineBlock = doc->findBlockByNumber(1); + QTextBlock emptyLineBlock = doc->findBlockByNumber(2); + QTextBlock lastBlock = doc->findBlockByNumber(3); + + highlighter->clearExtraFormats(emptyLineBlock); + QVERIFY(emptyLineBlock.layout()->formats().isEmpty()); + + highlighter->clearExtraFormats(spacesLineBlock); + + auto formats = spacesLineBlock.layout()->formats(); + // the spaces are not extra formats and should remain when clearing extra formats + QCOMPARE(formats.size(), 2); + QCOMPARE(formats.at(0).format.fontItalic(), false); + QCOMPARE(formats.at(0).format.fontOverline(), false); + QCOMPARE(formats.at(0).start, 6); + QCOMPARE(formats.at(0).length, 1); + + QCOMPARE(formats.at(1).format.fontItalic(), false); + QCOMPARE(formats.at(1).format.fontOverline(), false); + QCOMPARE(formats.at(1).start, 11); + QCOMPARE(formats.at(1).length, 1); + + // first and last should be untouched + formats = firstBlock.layout()->formats(); + QCOMPARE(formats.size(), 1); + QCOMPARE(formats.at(0).format.fontItalic(), true); + QCOMPARE(formats.at(0).format.fontOverline(), false); + QCOMPARE(formats.at(0).start, 0); + QCOMPARE(formats.at(0).length, 5); + + formats = lastBlock.layout()->formats(); + QCOMPARE(formats.size(), 2); + QCOMPARE(formats.at(0).format.fontItalic(), false); + QCOMPARE(formats.at(0).format.fontOverline(), true); + QCOMPARE(formats.at(0).start, 0); + QCOMPARE(formats.at(0).length, 1); + + QCOMPARE(formats.at(1).format.fontItalic(), true); + QCOMPARE(formats.at(1).format.fontOverline(), false); + QCOMPARE(formats.at(1).start, 0); + QCOMPARE(formats.at(1).length, 5); + + highlighter->clearAllExtraFormats(); + + QVERIFY(firstBlock.layout()->formats().isEmpty()); + QVERIFY(emptyLineBlock.layout()->formats().isEmpty()); + formats = spacesLineBlock.layout()->formats(); + + QCOMPARE(formats.size(), 2); + QCOMPARE(formats.at(0).format.fontItalic(), false); + QCOMPARE(formats.at(0).format.fontOverline(), false); + QCOMPARE(formats.at(0).start, 6); + QCOMPARE(formats.at(0).length, 1); + + QCOMPARE(formats.at(1).format.fontItalic(), false); + QCOMPARE(formats.at(1).format.fontOverline(), false); + QCOMPARE(formats.at(1).start, 11); + QCOMPARE(formats.at(1).length, 1); + + QVERIFY(lastBlock.layout()->formats().isEmpty()); +} + +void tst_highlighter::test_incrementalApplyAdditionalFormats() +{ + const HighlightingResults newResults{HighlightingResult(), + HighlightingResult(1, 1, 5, 0), + HighlightingResult(2, 4, 7, 0), + HighlightingResult(4, 1, 8, 0), + HighlightingResult(6, 1, 8, 1)}; + + QCOMPARE(doc->blockCount(), 4); + QTextBlock firstBlock = doc->findBlockByNumber(0); + QTextBlock spacesLineBlock = doc->findBlockByNumber(1); + QTextBlock emptyLineBlock = doc->findBlockByNumber(2); + QTextBlock lastBlock = doc->findBlockByNumber(3); + + QFutureInterface<HighlightingResult> fiOld; + fiOld.reportResults(highlightingResults()); + SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter, + fiOld.future(), + 2, + 0, + formatHash); + auto formats = firstBlock.layout()->formats(); + QVERIFY(formats.isEmpty()); + + SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter, + fiOld.future(), + 0, + 2, + formatHash); + + formats = firstBlock.layout()->formats(); + QCOMPARE(formats.at(0).format.fontItalic(), true); + QCOMPARE(formats.at(0).format.fontOverline(), false); + QCOMPARE(formats.at(0).start, 0); + QCOMPARE(formats.at(0).length, 5); + + formats = spacesLineBlock.layout()->formats(); + QCOMPARE(formats.size(), 2); + QCOMPARE(formats.at(0).format.fontItalic(), false); + QCOMPARE(formats.at(0).format.fontOverline(), false); + QCOMPARE(formats.at(0).start, 6); + QCOMPARE(formats.at(0).length, 1); + + QCOMPARE(formats.at(1).format.fontItalic(), false); + QCOMPARE(formats.at(1).format.fontOverline(), false); + QCOMPARE(formats.at(1).start, 11); + QCOMPARE(formats.at(1).length, 1); + + SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter, + fiOld.future(), + 3, + 6, + formatHash); + + formats = firstBlock.layout()->formats(); + QCOMPARE(formats.at(0).format.fontItalic(), true); + QCOMPARE(formats.at(0).format.fontOverline(), false); + QCOMPARE(formats.at(0).start, 0); + QCOMPARE(formats.at(0).length, 5); + + formats = lastBlock.layout()->formats(); + QCOMPARE(formats.size(), 2); + QCOMPARE(formats.at(0).format.fontItalic(), false); + QCOMPARE(formats.at(0).format.fontOverline(), true); + QCOMPARE(formats.at(0).start, 0); + QCOMPARE(formats.at(0).length, 1); + + QCOMPARE(formats.at(1).format.fontItalic(), true); + QCOMPARE(formats.at(1).format.fontOverline(), false); + QCOMPARE(formats.at(1).start, 0); + QCOMPARE(formats.at(1).length, 5); + + QFutureInterface<HighlightingResult> fiNew; + fiNew.reportResults(newResults); + SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter, + fiNew.future(), + 0, + 3, + formatHash); + + // should still contain the highlight from oldResults + formats = emptyLineBlock.layout()->formats(); + QCOMPARE(formats.size(), 1); + QCOMPARE(formats.at(0).format.fontItalic(), false); + QCOMPARE(formats.at(0).format.fontOverline(), true); + QCOMPARE(formats.at(0).start, 0); + QCOMPARE(formats.at(0).length, 1); + + SemanticHighlighter::incrementalApplyExtraAdditionalFormats(highlighter, + fiNew.future(), + 3, + 4, + formatHash); + + // should have no results since the new results do not contain a highlight at that position + formats = emptyLineBlock.layout()->formats(); + QVERIFY(formats.isEmpty()); +} + +void tst_highlighter::cleanup() +{ + delete doc; + doc = nullptr; + highlighter = nullptr; +} + +} // namespace TextEditor + +QTEST_MAIN(TextEditor::tst_highlighter) + +#include "tst_highlighter.moc" diff --git a/tests/auto/texteditor/texteditor.qbs b/tests/auto/texteditor/texteditor.qbs new file mode 100644 index 00000000000..957bb448f16 --- /dev/null +++ b/tests/auto/texteditor/texteditor.qbs @@ -0,0 +1,6 @@ +import qbs + +Project { + name: "TextEditor autotests" + references: [ "highlighter/highlighter.qbs" ] +} |