qt5base-lts/tests/auto/gui/text/qsyntaxhighlighter/tst_qsyntaxhighlighter.cpp
Lars Knoll 6ae7a02104 Remove most compiler warnings about missing overrides
Remove around 1000 compiler warnings about missing overrides
in our auto tests.

This significantly reduce the compiler warning noise in our auto
tests, so that one can actually better see the real problems
inbetween.

Change-Id: Id0c04dba43fcaf55d8cd2b5c6697358857c31bf9
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
2020-09-11 00:20:47 +02:00

573 lines
15 KiB
C++

/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:GPL-EXCEPT$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3 as published by the Free Software
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QtTest/QtTest>
#include <QTextDocument>
#include <QTextLayout>
#include <QDebug>
#include <QAbstractTextDocumentLayout>
#include <QSyntaxHighlighter>
#ifndef QT_NO_WIDGETS
#include <QTextEdit>
#endif
class QTestDocumentLayout : public QAbstractTextDocumentLayout
{
Q_OBJECT
public:
inline QTestDocumentLayout(QTextDocument *doc)
: QAbstractTextDocumentLayout(doc), documentChangedCalled(false) {}
virtual void draw(QPainter *, const QAbstractTextDocumentLayout::PaintContext &) override {}
virtual int hitTest(const QPointF &, Qt::HitTestAccuracy ) const override { return 0; }
virtual void documentChanged(int, int, int) override { documentChangedCalled = true; }
virtual int pageCount() const override { return 1; }
virtual QSizeF documentSize() const override { return QSize(); }
virtual QRectF frameBoundingRect(QTextFrame *) const override { return QRectF(); }
virtual QRectF blockBoundingRect(const QTextBlock &) const override { return QRectF(); }
bool documentChangedCalled;
};
class tst_QSyntaxHighlighter : public QObject
{
Q_OBJECT
private slots:
void init();
void cleanup();
void basic();
void basicTwo();
void removeFormatsOnDelete();
void emptyBlocks();
void setCharFormat();
void highlightOnInit();
void highlightOnInitAndAppend();
void stopHighlightingWhenStateDoesNotChange();
void unindent();
void highlightToEndOfDocument();
void highlightToEndOfDocument2();
void preservePreeditArea();
void task108530();
void avoidUnnecessaryRehighlight();
void avoidUnnecessaryDelayedRehighlight();
void noContentsChangedDuringHighlight();
void rehighlight();
void rehighlightBlock();
#ifndef QT_NO_WIDGETS
void textEditParent();
#endif
private:
QTextDocument *doc;
QTestDocumentLayout *lout;
QTextCursor cursor;
};
void tst_QSyntaxHighlighter::init()
{
doc = new QTextDocument;
lout = new QTestDocumentLayout(doc);
doc->setDocumentLayout(lout);
cursor = QTextCursor(doc);
}
void tst_QSyntaxHighlighter::cleanup()
{
delete doc;
doc = 0;
}
class TestHighlighter : public QSyntaxHighlighter
{
public:
inline TestHighlighter(const QList<QTextLayout::FormatRange> &fmts, QTextDocument *parent)
: QSyntaxHighlighter(parent), formats(fmts), highlighted(false), callCount(0)
{
}
inline TestHighlighter(QObject *parent)
: QSyntaxHighlighter(parent) {}
inline TestHighlighter(QTextDocument *parent)
: QSyntaxHighlighter(parent), highlighted(false), callCount(0) {}
virtual void highlightBlock(const QString &text) override
{
for (int i = 0; i < formats.count(); ++i) {
const QTextLayout::FormatRange &range = formats.at(i);
setFormat(range.start, range.length, range.format);
}
highlighted = true;
highlightedText += text;
++callCount;
}
QList<QTextLayout::FormatRange> formats;
bool highlighted;
int callCount;
QString highlightedText;
};
void tst_QSyntaxHighlighter::basic()
{
QList<QTextLayout::FormatRange> formats;
QTextLayout::FormatRange range;
range.start = 0;
range.length = 2;
range.format.setForeground(Qt::blue);
formats.append(range);
range.start = 4;
range.length = 2;
range.format.setFontItalic(true);
formats.append(range);
range.start = 9;
range.length = 2;
range.format.setFontUnderline(true);
formats.append(range);
TestHighlighter *hl = new TestHighlighter(formats, doc);
lout->documentChangedCalled = false;
doc->setPlainText("Hello World");
QVERIFY(hl->highlighted);
QVERIFY(lout->documentChangedCalled);
QCOMPARE(doc->begin().layout()->formats(), formats);
}
class CommentTestHighlighter : public QSyntaxHighlighter
{
public:
inline CommentTestHighlighter(QTextDocument *parent)
: QSyntaxHighlighter(parent), highlighted(false) {}
inline void reset()
{
highlighted = false;
}
virtual void highlightBlock(const QString &text) override
{
QTextCharFormat commentFormat;
commentFormat.setForeground(Qt::darkGreen);
commentFormat.setFontWeight(QFont::StyleItalic);
commentFormat.setFontFixedPitch(true);
int textLength = text.length();
if (text.startsWith(QLatin1Char(';'))){
// The entire line is a comment
setFormat(0, textLength, commentFormat);
highlighted = true;
}
}
bool highlighted;
};
void tst_QSyntaxHighlighter::basicTwo()
{
// Done for task 104409
CommentTestHighlighter *hl = new CommentTestHighlighter(doc);
doc->setPlainText("; a test");
QVERIFY(hl->highlighted);
QVERIFY(lout->documentChangedCalled);
}
void tst_QSyntaxHighlighter::removeFormatsOnDelete()
{
QList<QTextLayout::FormatRange> formats;
QTextLayout::FormatRange range;
range.start = 0;
range.length = 9;
range.format.setForeground(Qt::blue);
formats.append(range);
TestHighlighter *hl = new TestHighlighter(formats, doc);
lout->documentChangedCalled = false;
doc->setPlainText("Hello World");
QVERIFY(hl->highlighted);
QVERIFY(lout->documentChangedCalled);
lout->documentChangedCalled = false;
QVERIFY(!doc->begin().layout()->formats().isEmpty());
delete hl;
QVERIFY(doc->begin().layout()->formats().isEmpty());
QVERIFY(lout->documentChangedCalled);
}
void tst_QSyntaxHighlighter::emptyBlocks()
{
TestHighlighter *hl = new TestHighlighter(doc);
cursor.insertText("Foo");
cursor.insertBlock();
cursor.insertBlock();
hl->highlighted = false;
cursor.insertBlock();
QVERIFY(hl->highlighted);
}
void tst_QSyntaxHighlighter::setCharFormat()
{
TestHighlighter *hl = new TestHighlighter(doc);
cursor.insertText("FooBar");
cursor.insertBlock();
cursor.insertText("Blah");
cursor.movePosition(QTextCursor::Start);
cursor.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
QTextCharFormat fmt;
fmt.setFontItalic(true);
hl->highlighted = false;
hl->callCount = 0;
cursor.mergeCharFormat(fmt);
QVERIFY(hl->highlighted);
QCOMPARE(hl->callCount, 2);
}
void tst_QSyntaxHighlighter::highlightOnInit()
{
cursor.insertText("Hello");
cursor.insertBlock();
cursor.insertText("World");
TestHighlighter *hl = new TestHighlighter(doc);
QTRY_VERIFY(hl->highlighted);
}
void tst_QSyntaxHighlighter::highlightOnInitAndAppend()
{
cursor.insertText("Hello");
cursor.insertBlock();
cursor.insertText("World");
TestHighlighter *hl = new TestHighlighter(doc);
cursor.insertBlock();
cursor.insertText("More text");
QTRY_VERIFY(hl->highlighted);
QVERIFY(hl->highlightedText.endsWith(doc->toPlainText().remove(QLatin1Char('\n'))));
}
class StateTestHighlighter : public QSyntaxHighlighter
{
public:
inline StateTestHighlighter(QTextDocument *parent)
: QSyntaxHighlighter(parent), state(0), highlighted(false) {}
inline void reset()
{
highlighted = false;
state = 0;
}
virtual void highlightBlock(const QString &text) override
{
highlighted = true;
if (text == QLatin1String("changestate"))
setCurrentBlockState(state++);
}
int state;
bool highlighted;
};
void tst_QSyntaxHighlighter::stopHighlightingWhenStateDoesNotChange()
{
cursor.insertText("state");
cursor.insertBlock();
cursor.insertText("changestate");
cursor.insertBlock();
cursor.insertText("keepstate");
cursor.insertBlock();
cursor.insertText("changestate");
cursor.insertBlock();
cursor.insertText("changestate");
StateTestHighlighter *hl = new StateTestHighlighter(doc);
QTRY_VERIFY(hl->highlighted);
hl->reset();
// turn the text of the first block into 'changestate'
cursor.movePosition(QTextCursor::Start);
cursor.insertText("change");
// verify that we highlighted only to the 'keepstate' block,
// not beyond
QCOMPARE(hl->state, 2);
}
void tst_QSyntaxHighlighter::unindent()
{
const QString spaces(" ");
const QString text("Foobar");
QString plainText;
for (int i = 0; i < 5; ++i) {
cursor.insertText(spaces + text);
cursor.insertBlock();
plainText += spaces;
plainText += text;
plainText += QLatin1Char('\n');
}
QCOMPARE(doc->toPlainText(), plainText);
TestHighlighter *hl = new TestHighlighter(doc);
QTRY_VERIFY(hl->highlighted);
hl->callCount = 0;
cursor.movePosition(QTextCursor::Start);
cursor.beginEditBlock();
plainText.clear();
for (int i = 0; i < 5; ++i) {
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, 4);
cursor.removeSelectedText();
cursor.movePosition(QTextCursor::NextBlock);
plainText += text;
plainText += QLatin1Char('\n');
}
cursor.endEditBlock();
QCOMPARE(doc->toPlainText(), plainText);
QCOMPARE(hl->callCount, 5);
}
void tst_QSyntaxHighlighter::highlightToEndOfDocument()
{
TestHighlighter *hl = new TestHighlighter(doc);
hl->callCount = 0;
cursor.movePosition(QTextCursor::Start);
cursor.beginEditBlock();
cursor.insertText("Hello");
cursor.insertBlock();
cursor.insertBlock();
cursor.insertText("World");
cursor.insertBlock();
cursor.endEditBlock();
QCOMPARE(hl->callCount, 4);
}
void tst_QSyntaxHighlighter::highlightToEndOfDocument2()
{
TestHighlighter *hl = new TestHighlighter(doc);
hl->callCount = 0;
cursor.movePosition(QTextCursor::End);
cursor.beginEditBlock();
QTextBlockFormat fmt;
fmt.setAlignment(Qt::AlignLeft);
cursor.setBlockFormat(fmt);
cursor.insertText("Three\nLines\nHere");
cursor.endEditBlock();
QCOMPARE(hl->callCount, 3);
}
void tst_QSyntaxHighlighter::preservePreeditArea()
{
QList<QTextLayout::FormatRange> formats;
QTextLayout::FormatRange range;
range.start = 0;
range.length = 8;
range.format.setForeground(Qt::blue);
formats << range;
range.start = 9;
range.length = 1;
range.format.setForeground(Qt::red);
formats << range;
TestHighlighter *hl = new TestHighlighter(formats, doc);
doc->setPlainText("Hello World");
cursor.movePosition(QTextCursor::Start);
QTextLayout *layout = cursor.block().layout();
layout->setPreeditArea(5, QString("foo"));
range.start = 5;
range.length = 3;
range.format.setFontUnderline(true);
formats.clear();
formats << range;
hl->callCount = 0;
cursor.beginEditBlock();
layout->setFormats(formats);
cursor.endEditBlock();
QCOMPARE(hl->callCount, 1);
formats = layout->formats();
QCOMPARE(formats.count(), 3);
range = formats.at(0);
QCOMPARE(range.start, 5);
QCOMPARE(range.length, 3);
QVERIFY(range.format.fontUnderline());
range = formats.at(1);
QCOMPARE(range.start, 0);
QCOMPARE(range.length, 8 + 3);
range = formats.at(2);
QCOMPARE(range.start, 9 + 3);
QCOMPARE(range.length, 1);
}
void tst_QSyntaxHighlighter::task108530()
{
TestHighlighter *hl = new TestHighlighter(doc);
cursor.insertText("test");
hl->callCount = 0;
hl->highlightedText.clear();
cursor.movePosition(QTextCursor::Start);
cursor.insertBlock();
QCOMPARE(hl->highlightedText, QString("test"));
QCOMPARE(hl->callCount, 2);
}
void tst_QSyntaxHighlighter::avoidUnnecessaryRehighlight()
{
TestHighlighter *hl = new TestHighlighter(doc);
QVERIFY(!hl->highlighted);
doc->setPlainText("Hello World");
QVERIFY(hl->highlighted);
hl->highlighted = false;
QCoreApplication::processEvents();
QVERIFY(!hl->highlighted);
}
void tst_QSyntaxHighlighter::avoidUnnecessaryDelayedRehighlight()
{
// Having text in the document before creating the highlighter starts the delayed rehighlight
cursor.insertText("Hello World");
TestHighlighter *hl = new TestHighlighter(doc);
QVERIFY(!hl->highlighted);
hl->rehighlight();
QVERIFY(hl->highlighted);
hl->highlighted = false;
// Process events, including delayed rehighlight emission
QCoreApplication::processEvents();
// Should be cancelled and no extra rehighlight should be done
QVERIFY(!hl->highlighted);
}
void tst_QSyntaxHighlighter::noContentsChangedDuringHighlight()
{
QList<QTextLayout::FormatRange> formats;
QTextLayout::FormatRange range;
range.start = 0;
range.length = 10;
range.format.setForeground(Qt::blue);
formats.append(range);
TestHighlighter *hl = new TestHighlighter(formats, doc);
lout->documentChangedCalled = false;
QTextCursor cursor(doc);
QSignalSpy contentsChangedSpy(doc, SIGNAL(contentsChanged()));
cursor.insertText("Hello World");
QCOMPARE(contentsChangedSpy.count(), 1);
QVERIFY(hl->highlighted);
QVERIFY(lout->documentChangedCalled);
}
void tst_QSyntaxHighlighter::rehighlight()
{
TestHighlighter *hl = new TestHighlighter(doc);
hl->callCount = 0;
doc->setPlainText("Hello");
hl->callCount = 0;
hl->rehighlight();
QCOMPARE(hl->callCount, 1);
}
void tst_QSyntaxHighlighter::rehighlightBlock()
{
TestHighlighter *hl = new TestHighlighter(doc);
cursor.movePosition(QTextCursor::Start);
cursor.beginEditBlock();
cursor.insertText("Hello");
cursor.insertBlock();
cursor.insertText("World");
cursor.endEditBlock();
hl->callCount = 0;
hl->highlightedText.clear();
QTextBlock block = doc->begin();
hl->rehighlightBlock(block);
QCOMPARE(hl->highlightedText, QString("Hello"));
QCOMPARE(hl->callCount, 1);
hl->callCount = 0;
hl->highlightedText.clear();
hl->rehighlightBlock(block.next());
QCOMPARE(hl->highlightedText, QString("World"));
QCOMPARE(hl->callCount, 1);
}
#ifndef QT_NO_WIDGETS
void tst_QSyntaxHighlighter::textEditParent()
{
QTextEdit textEdit;
TestHighlighter *hl = new TestHighlighter(&textEdit);
QCOMPARE(hl->document(), textEdit.document());
}
#endif
QTEST_MAIN(tst_QSyntaxHighlighter)
#include "tst_qsyntaxhighlighter.moc"