Skip to content
Snippets Groups Projects
Commit b97bfaa7 authored by Leandro Melo's avatar Leandro Melo
Browse files

Generic highlighter: New unit tests for the highlighter engine.

parent 823064d9
Branches
Tags
No related merge requests found
TEMPLATE = subdirs
SUBDIRS += specificrules
SUBDIRS += specificrules highlighterengine
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef BASETEXTDOCUMENTLAYOUT_H
#define BASETEXTDOCUMENTLAYOUT_H
/*
Since the text editor plugin directory is not included in the search list of the pro file, this
file replaces the "real" basetextdocumentlayout.h file. The objective is to simply use
QTextBlockUserData instead of TextEditor::TextBlockUserData to avoid "external"
dependencies or intrusive defines.
*/
#include <QtGui/QTextBlockUserData>
typedef QTextBlockUserData TextBlockUserData;
#endif // BASETEXTDOCUMENTLAYOUT_H
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "formats.h"
#include <QtCore/Qt>
Formats::Formats()
{
m_keywordFormat.setForeground(Qt::darkGray);
m_dataTypeFormat.setForeground(Qt::gray);
m_decimalFormat.setForeground(Qt::lightGray);
m_baseNFormat.setForeground(Qt::red);
m_floatFormat.setForeground(Qt::green);
m_charFormat.setForeground(Qt::blue);
m_stringFormat.setForeground(Qt::cyan);
m_commentFormat.setForeground(Qt::magenta);
m_alertFormat.setForeground(Qt::yellow);
m_errorFormat.setForeground(Qt::darkRed);
m_functionFormat.setForeground(Qt::darkGreen);
m_regionMarkerFormat.setForeground(Qt::darkBlue);
m_othersFormat.setForeground(Qt::darkCyan);
}
Formats &Formats::instance()
{
static Formats formats;
return formats;
}
QString Formats::name(const QTextCharFormat &format) const
{
if (format == QTextCharFormat())
return "Default format";
else if (format == m_keywordFormat)
return "Keyword";
else if (format == m_dataTypeFormat)
return "Data type format";
else if (format == m_decimalFormat)
return "Decimal format";
else if (format == m_baseNFormat)
return "Base N format";
else if (format == m_floatFormat)
return "Float format";
else if (format == m_charFormat)
return "Char format";
else if (format == m_stringFormat)
return "String format";
else if (format == m_commentFormat)
return "Comment format";
else if (format == m_alertFormat)
return "Alert format";
else if (format == m_errorFormat)
return "Error format";
else if (format == m_functionFormat)
return "Function format";
else if (format == m_regionMarkerFormat)
return "Region Marker format";
else if (format == m_othersFormat)
return "Others format";
else
return "Unidentified format";
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef FORMATS_H
#define FORMATS_H
#include <QtGui/QTextCharFormat>
class Formats
{
public:
static Formats &instance();
const QTextCharFormat &keywordFormat() const { return m_keywordFormat; }
const QTextCharFormat &dataTypeFormat() const { return m_dataTypeFormat; }
const QTextCharFormat &decimalFormat() const { return m_decimalFormat; }
const QTextCharFormat &baseNFormat() const { return m_baseNFormat; }
const QTextCharFormat &floatFormat() const { return m_floatFormat; }
const QTextCharFormat &charFormat() const { return m_charFormat; }
const QTextCharFormat &stringFormat() const { return m_stringFormat; }
const QTextCharFormat &commentFormat() const { return m_commentFormat; }
const QTextCharFormat &alertFormat() const { return m_alertFormat; }
const QTextCharFormat &errorFormat() const { return m_errorFormat; }
const QTextCharFormat &functionFormat() const { return m_functionFormat; }
const QTextCharFormat &regionMarketFormat() const { return m_regionMarkerFormat; }
const QTextCharFormat &othersFormat() const { return m_othersFormat; }
QString name(const QTextCharFormat &format) const;
private:
Formats();
Q_DISABLE_COPY(Formats);
QTextCharFormat m_keywordFormat;
QTextCharFormat m_dataTypeFormat;
QTextCharFormat m_decimalFormat;
QTextCharFormat m_baseNFormat;
QTextCharFormat m_floatFormat;
QTextCharFormat m_charFormat;
QTextCharFormat m_stringFormat;
QTextCharFormat m_commentFormat;
QTextCharFormat m_alertFormat;
QTextCharFormat m_errorFormat;
QTextCharFormat m_functionFormat;
QTextCharFormat m_regionMarkerFormat;
QTextCharFormat m_othersFormat;
};
#endif // FORMATS_H
QT += gui testlib
GENERICHIGHLIGHTERDIR = ../../../../src/plugins/texteditor/generichighlighter
SOURCES += tst_highlighterengine.cpp \
highlightermock.cpp \
$$GENERICHIGHLIGHTERDIR/highlighter.cpp \
$$GENERICHIGHLIGHTERDIR/context.cpp \
$$GENERICHIGHLIGHTERDIR/dynamicrule.cpp \
$$GENERICHIGHLIGHTERDIR/rule.cpp \
$$GENERICHIGHLIGHTERDIR/specificrules.cpp \
$$GENERICHIGHLIGHTERDIR/progressdata.cpp \
$$GENERICHIGHLIGHTERDIR/highlightdefinition.cpp \
$$GENERICHIGHLIGHTERDIR/keywordlist.cpp \
$$GENERICHIGHLIGHTERDIR/itemdata.cpp \
formats.cpp
HEADERS += \
highlightermock.h \
basetextdocumentlayout.h \
formats.h
INCLUDEPATH += $$GENERICHIGHLIGHTERDIR
TARGET=tst_$$TARGET
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "highlightermock.h"
#include "context.h"
#include "highlightdefinition.h"
#include "formats.h"
#include <QtCore/QDebug>
#include <QtTest/QtTest>
namespace QTest {
template<>
char *toString(const QTextCharFormat &format)
{
QByteArray ba = Formats::instance().name(format).toLatin1();
return qstrdup(ba.data());
}
}
using namespace TextEditor;
using namespace Internal;
HighlighterMock::HighlighterMock(const QSharedPointer<Context> &defaultContext,
QTextDocument *parent) :
Highlighter(defaultContext, parent),
m_debugDetails(false),
m_statesCounter(0),
m_formatsCounter(0),
m_noTestCall(false),
m_considerEmptyLines(false)
{}
void HighlighterMock::reset()
{
m_states.clear();
m_statesCounter = 0;
m_formatSequence.clear();
m_formatsCounter = 0;
m_debugDetails = false;
m_noTestCall = false;
m_considerEmptyLines = false;
}
void HighlighterMock::showDebugDetails()
{ m_debugDetails = true; }
void HighlighterMock::considerEmptyLines()
{ m_considerEmptyLines = true; }
void HighlighterMock::startNoTestCalls()
{ m_noTestCall = true; }
void HighlighterMock::endNoTestCalls()
{ m_noTestCall = false; }
void HighlighterMock::setExpectedBlockState(const int state)
{ m_states << state; }
void HighlighterMock::setExpectedBlockStates(const QList<int> &states)
{ m_states = states; }
void HighlighterMock::setExpectedHighlightSequence(const HighlightSequence &format)
{ m_formatSequence << format; }
void HighlighterMock::setExpectedHighlightSequences(const QList<HighlightSequence> &formats)
{ m_formatSequence = formats; }
void HighlighterMock::highlightBlock(const QString &text)
{
Highlighter::highlightBlock(text);
if (text.isEmpty() && !m_considerEmptyLines)
return;
if (m_noTestCall)
return;
if (m_states.isEmpty() || m_formatSequence.isEmpty())
QFAIL("No expected data setup.");
if (m_debugDetails)
qDebug() << "Highlighting" << text;
if (m_states.size() <= m_statesCounter)
QFAIL("Expected state for current block not set.");
QCOMPARE(currentBlockState(), m_states.at(m_statesCounter++));
if (m_formatSequence.size() <= m_formatsCounter)
QFAIL("Expected highlight sequence for current block not set.");
for (int i = 0; i < text.length(); ++i) {
if (text.at(i).isSpace())
continue;
if (m_debugDetails)
qDebug() << "at offset" << i;
QCOMPARE(format(i), m_formatSequence.at(m_formatsCounter).m_formats.at(i));
}
++m_formatsCounter;
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef HIGHLIGHTERMOCK_H
#define HIGHLIGHTERMOCK_H
#include "highlighter.h"
#include <QtCore/QList>
namespace TextEditor {
namespace Internal {
class Context;
class HighlightDefinition;
}
}
struct HighlightSequence
{
HighlightSequence() {}
HighlightSequence(int from, int to, const QTextCharFormat &format = QTextCharFormat())
{ add(from, to, format); }
HighlightSequence(const HighlightSequence &sequence)
{ m_formats = sequence.m_formats; }
void add(int from, int to, const QTextCharFormat &format = QTextCharFormat())
{
for (int i = from; i < to; ++i)
m_formats.append(format);
}
QList<QTextCharFormat> m_formats;
};
class HighlighterMock : public TextEditor::Internal::Highlighter
{
public:
HighlighterMock(const QSharedPointer<TextEditor::Internal::Context> &defaultContext,
QTextDocument *parent = 0);
void reset();
void showDebugDetails();
void considerEmptyLines();
void startNoTestCalls();
void endNoTestCalls();
void setExpectedBlockState(const int state);
void setExpectedBlockStates(const QList<int> &states);
void setExpectedHighlightSequence(const HighlightSequence &format);
void setExpectedHighlightSequences(const QList<HighlightSequence> &formats);
protected:
virtual void highlightBlock(const QString &text);
private:
QList<int> m_states;
int m_statesCounter;
QList<HighlightSequence> m_formatSequence;
int m_formatsCounter;
bool m_debugDetails;
bool m_noTestCall;
bool m_considerEmptyLines;
};
#endif // HIGHLIGHTERMOCK_H
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "highlightdefinition.h"
#include "keywordlist.h"
#include "itemdata.h"
#include "context.h"
#include "specificrules.h"
#include "highlightermock.h"
#include "formats.h"
#include <QtCore/QSharedPointer>
#include <QtCore/QScopedPointer>
#include <QtCore/QList>
#include <QtCore/QMetaType>
#include <QtGui/QPlainTextEdit>
#include <QtTest/QtTest>
using namespace TextEditor;
using namespace Internal;
Q_DECLARE_METATYPE(HighlightSequence)
Q_DECLARE_METATYPE(QList<int>)
Q_DECLARE_METATYPE(QList<HighlightSequence>)
class tst_HighlighterEngine : public QObject
{
Q_OBJECT
public:
tst_HighlighterEngine();
private slots:
void initTestCase();
void init();
void testSimpleLine();
void testSimpleLine_data();
void testLineContinue();
void testLineContinue_data();
void testEditingLineContinue0();
void testEditingLineContinue1();
void testEditingLineContinue2();
void testEditingLineContinue3();
void testEditingLineContinue4();
void testEditingLineContinue5();
void testPersistentStates();
void testPersistentStates_data();
private:
void createKeywords();
void createContexts();
void createItemDatas();
void setExpectedData(int state, const HighlightSequence &seq);
void setExpectedData(const QList<int> &states, const QList<HighlightSequence> &seqs);
void createColumns();
void test();
void test(int state, const HighlightSequence &seq, const QString &line);
void test(const QList<int> &states, const QList<HighlightSequence> &seqs, const QString &lines);
void clear(QList<int> *states, QList<HighlightSequence> *sequences) const;
QList<int> createlDefaultStatesList(int size) const;
void addCharactersToBegin(QTextBlock block, const QString &s);
void addCharactersToEnd(QTextBlock block, const QString &s);
void removeFirstCharacters(const QTextBlock &block, int n);
void removeLastCharacters(const QTextBlock &block, int n);
void setupForEditingLineContinue();
QSharedPointer<HighlightDefinition> m_definition;
QScopedPointer<HighlighterMock> m_highlighterMock;
QPlainTextEdit m_text;
};
tst_HighlighterEngine::tst_HighlighterEngine() :
m_definition(new HighlightDefinition)
{}
void tst_HighlighterEngine::initTestCase()
{
QWARN("\n***********************************************************\
\n*** Spaces are ignored when comparing text char formats ***\
\n***********************************************************");
createKeywords();
createContexts();
createItemDatas();
m_highlighterMock.reset(new HighlighterMock(m_definition->initialContext()));
m_highlighterMock->setDocument(m_text.document());
m_highlighterMock->configureFormat(Highlighter::Keyword, Formats::instance().keywordFormat());
m_highlighterMock->configureFormat(Highlighter::DataType, Formats::instance().dataTypeFormat());
m_highlighterMock->configureFormat(Highlighter::Decimal, Formats::instance().decimalFormat());
m_highlighterMock->configureFormat(Highlighter::BaseN, Formats::instance().baseNFormat());
m_highlighterMock->configureFormat(Highlighter::Float, Formats::instance().floatFormat());
m_highlighterMock->configureFormat(Highlighter::Char, Formats::instance().charFormat());
m_highlighterMock->configureFormat(Highlighter::String, Formats::instance().stringFormat());
m_highlighterMock->configureFormat(Highlighter::Comment, Formats::instance().commentFormat());
m_highlighterMock->configureFormat(Highlighter::Alert, Formats::instance().alertFormat());
m_highlighterMock->configureFormat(Highlighter::Error, Formats::instance().errorFormat());
m_highlighterMock->configureFormat(Highlighter::Function, Formats::instance().functionFormat());
m_highlighterMock->configureFormat(Highlighter::RegionMarker,
Formats::instance().regionMarketFormat());
m_highlighterMock->configureFormat(Highlighter::Others, Formats::instance().othersFormat());
}
void tst_HighlighterEngine::init()
{
m_highlighterMock->reset();
}
void tst_HighlighterEngine::createKeywords()
{
QSharedPointer<KeywordList> keywords = m_definition->createKeywordList("keywords");
keywords->addKeyword("int");
keywords->addKeyword("long");
}
void tst_HighlighterEngine::createContexts()
{
// Normal context
QSharedPointer<Context> normal = m_definition->createContext("Normal", true);
normal->setItemData("Normal Text");
normal->setLineEndContext("#stay");
normal->setDefinition(m_definition);
// AfterHash context
QSharedPointer<Context> afterHash = m_definition->createContext("AfterHash", false);
afterHash->setItemData("Error");
afterHash->setLineEndContext("#pop");
afterHash->setDefinition(m_definition);
// Define context
QSharedPointer<Context> define = m_definition->createContext("Define", false);
define->setItemData("Preprocessor");
define->setLineEndContext("#pop");
define->setDefinition(m_definition);
// Preprocessor context
QSharedPointer<Context> preprocessor = m_definition->createContext("Preprocessor", false);
preprocessor->setItemData("Preprocessor");
preprocessor->setLineEndContext("#pop");
preprocessor->setDefinition(m_definition);
// SimpleComment context
QSharedPointer<Context> simpleComment = m_definition->createContext("SimpleComment", false);
simpleComment->setItemData("Comment");
simpleComment->setLineEndContext("#pop");
simpleComment->setDefinition(m_definition);
// MultilineComment context
QSharedPointer<Context> multiComment = m_definition->createContext("MultilineComment", false);
multiComment->setItemData("Comment");
multiComment->setLineEndContext("#stay");
multiComment->setDefinition(m_definition);
// NestedComment context
QSharedPointer<Context> nestedComment = m_definition->createContext("NestedComment", false);
nestedComment->setItemData("Other Comment");
nestedComment->setLineEndContext("#stay");
nestedComment->setDefinition(m_definition);
// Dummy context
QSharedPointer<Context> dummy = m_definition->createContext("Dummy", false);
dummy->setItemData("Dummy");
dummy->setLineEndContext("#pop");
dummy->setDefinition(m_definition);
// Rules
DetectCharRule *r0 = new DetectCharRule;
r0->setChar("#");
r0->setContext("AfterHash");
r0->setFirstNonSpace("true");
r0->setLookAhead("true");
r0->setDefinition(m_definition);
normal->addRule(QSharedPointer<Rule>(r0));
RegExprRule *r1 = new RegExprRule;
r1->setPattern("#\\s*define.*((?=\\\\))");
r1->setInsensitive("true");
r1->setContext("Define");
r1->setItemData("Preprocessor");
r1->setFirstNonSpace("true");
r1->setDefinition(m_definition);
afterHash->addRule(QSharedPointer<Rule>(r1));
RegExprRule *r2 = new RegExprRule;
r2->setPattern("#\\s*(?:define|undef)");
r2->setInsensitive("true");
r2->setContext("Preprocessor");
r2->setItemData("Preprocessor");
r2->setFirstNonSpace("true");
r2->setDefinition(m_definition);
afterHash->addRule(QSharedPointer<Rule>(r2));
LineContinueRule *r3 = new LineContinueRule;
r3->setItemData("Preprocessor");
r3->setContext("#stay");
r3->setDefinition(m_definition);
define->addRule(QSharedPointer<Rule>(r3));
LineContinueRule *r4 = new LineContinueRule;
r4->setItemData("Preprocessor");
r4->setContext("#stay");
r4->setDefinition(m_definition);
preprocessor->addRule(QSharedPointer<Rule>(r4));
KeywordRule *r5 = new KeywordRule(m_definition);
r5->setList("keywords");
r5->setItemData("Keyword");
r5->setContext("#stay");
r5->setDefinition(m_definition);
normal->addRule(QSharedPointer<Rule>(r5));
IntRule *r6 = new IntRule;
r6->setItemData("Decimal");
r6->setContext("#stay");
r6->setDefinition(m_definition);
normal->addRule(QSharedPointer<Rule>(r6));
StringDetectRule *r7 = new StringDetectRule;
r7->setItemData("Decimal");
r7->setContext("#stay");
r7->setString("LL");
r7->setInsensitive("true");
r7->setDefinition(m_definition);
r6->addChild(QSharedPointer<Rule>(r7));
StringDetectRule *r8 = new StringDetectRule;
r8->setItemData("Decimal");
r8->setContext("#stay");
r8->setString("UL");
r8->setInsensitive("true");
r8->setDefinition(m_definition);
r6->addChild(QSharedPointer<Rule>(r8));
HlCOctRule *r9 = new HlCOctRule;
r9->setItemData("Octal");
r9->setContext("#stay");
r9->setDefinition(m_definition);
normal->addRule(QSharedPointer<Rule>(r9));
Detect2CharsRule *r10 = new Detect2CharsRule;
r10->setChar("/");
r10->setChar1("/");
r10->setItemData("Comment");
r10->setContext("SimpleComment");
r10->setDefinition(m_definition);
normal->addRule(QSharedPointer<Rule>(r10));
DetectIdentifierRule *r11 = new DetectIdentifierRule;
r11->setDefinition(m_definition);
simpleComment->addRule(QSharedPointer<Rule>(r11));
Detect2CharsRule *r12 = new Detect2CharsRule;
r12->setChar("/");
r12->setChar1("*");
r12->setItemData("Comment");
r12->setContext("MultilineComment");
r12->setDefinition(m_definition);
normal->addRule(QSharedPointer<Rule>(r12));
Detect2CharsRule *r13 = new Detect2CharsRule;
r13->setChar("*");
r13->setChar1("/");
r13->setItemData("Comment");
r13->setContext("#pop");
r13->setDefinition(m_definition);
multiComment->addRule(QSharedPointer<Rule>(r13));
Detect2CharsRule *r14 = new Detect2CharsRule;
r14->setChar("/");
r14->setChar1("#");
r14->setItemData("Other Comment");
r14->setContext("NestedComment");
r14->setDefinition(m_definition);
QSharedPointer<Rule> sr14(r14);
multiComment->addRule(sr14);
Detect2CharsRule *r15 = new Detect2CharsRule;
r15->setChar("#");
r15->setChar1("/");
r15->setItemData("Other Comment");
r15->setContext("#pop");
r15->setDefinition(m_definition);
nestedComment->addRule(QSharedPointer<Rule>(r15));
DetectCharRule *r16 = new DetectCharRule;
r16->setChar("@");
r16->setItemData("Marker");
r16->setContext("Dummy");
r16->setDefinition(m_definition);
multiComment->addRule(QSharedPointer<Rule>(r16));
StringDetectRule *r17 = new StringDetectRule;
r17->setString("dummy");
r17->setItemData("Dummy");
r17->setContext("#stay");
r17->setDefinition(m_definition);
dummy->addRule(QSharedPointer<Rule>(r17));
dummy->addRule(sr14);
}
void tst_HighlighterEngine::createItemDatas()
{
QSharedPointer<ItemData> normalText = m_definition->createItemData("Normal Text");
normalText->setStyle("dsNormal");
QSharedPointer<ItemData> preprocessor = m_definition->createItemData("Preprocessor");
preprocessor->setStyle("dsOthers");
QSharedPointer<ItemData> error = m_definition->createItemData("Error");
error->setStyle("dsError");
QSharedPointer<ItemData> keyword = m_definition->createItemData("Keyword");
keyword->setStyle("dsKeyword");
QSharedPointer<ItemData> decimal = m_definition->createItemData("Decimal");
decimal->setStyle("dsDecVal");
QSharedPointer<ItemData> octal = m_definition->createItemData("Octal");
octal->setStyle("dsBaseN");
QSharedPointer<ItemData> comment = m_definition->createItemData("Comment");
comment->setStyle("dsComment");
QSharedPointer<ItemData> otherComment = m_definition->createItemData("Other Comment");
otherComment->setStyle("dsError");
QSharedPointer<ItemData> marker = m_definition->createItemData("Marker");
marker->setStyle("dsRegionMarker");
QSharedPointer<ItemData> dummy = m_definition->createItemData("Dummy");
dummy->setStyle("dsDataType");
}
void tst_HighlighterEngine::setExpectedData(int state, const HighlightSequence &seq)
{
m_highlighterMock->setExpectedBlockState(state);
m_highlighterMock->setExpectedHighlightSequence(seq);
}
void tst_HighlighterEngine::setExpectedData(const QList<int> &states,
const QList<HighlightSequence> &seqs)
{
m_highlighterMock->setExpectedBlockStates(states);
m_highlighterMock->setExpectedHighlightSequences(seqs);
}
void tst_HighlighterEngine::createColumns()
{
QTest::addColumn<QList<int> >("states");
QTest::addColumn<QList<HighlightSequence> >("sequences");
QTest::addColumn<QString>("lines");
}
void tst_HighlighterEngine::test()
{
QFETCH(QList<int>, states);
QFETCH(QList<HighlightSequence>, sequences);
QFETCH(QString, lines);
test(states, sequences, lines);
}
void tst_HighlighterEngine::test(int state, const HighlightSequence &seq, const QString &line)
{
setExpectedData(state, seq);
m_text.setPlainText(line);
}
void tst_HighlighterEngine::test(const QList<int> &states,
const QList<HighlightSequence> &seqs,
const QString &lines)
{
setExpectedData(states, seqs);
m_text.setPlainText(lines);
}
void tst_HighlighterEngine::clear(QList<int> *states, QList<HighlightSequence> *sequences) const
{
states->clear();
sequences->clear();
}
QList<int> tst_HighlighterEngine::createlDefaultStatesList(int size) const
{
QList<int> states;
for (int i = 0; i < size; ++i)
states.append(0);
return states;
}
void tst_HighlighterEngine::addCharactersToBegin(QTextBlock block, const QString &s)
{
QTextCursor cursor = m_text.textCursor();
cursor.beginEditBlock();
cursor.setPosition(block.position());
cursor.insertText(s);
cursor.endEditBlock();
}
void tst_HighlighterEngine::addCharactersToEnd(QTextBlock block, const QString &s)
{
QTextCursor cursor = m_text.textCursor();
cursor.beginEditBlock();
cursor.setPosition(block.position() + block.length() - 1);
cursor.insertText(s);
cursor.endEditBlock();
}
void tst_HighlighterEngine::removeFirstCharacters(const QTextBlock &block, int n)
{
QTextCursor cursor = m_text.textCursor();
cursor.beginEditBlock();
cursor.setPosition(block.position());
cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, n);
cursor.removeSelectedText();
cursor.endEditBlock();
}
void tst_HighlighterEngine::removeLastCharacters(const QTextBlock &block, int n)
{
QTextCursor cursor = m_text.textCursor();
cursor.beginEditBlock();
cursor.setPosition(block.position() + block.length() - 1);
cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, n);
cursor.removeSelectedText();
cursor.endEditBlock();
}
void tst_HighlighterEngine::testSimpleLine()
{
test();
}
void tst_HighlighterEngine::testSimpleLine_data()
{
createColumns();
QList<int> states;
QList<HighlightSequence> sequences;
QString text;
HighlightSequence seqa(0, 3);
HighlightSequence seqb(0, 15, Formats::instance().othersFormat());
HighlightSequence seqc(0, 1, Formats::instance().errorFormat());
HighlightSequence seqd(0, 3, Formats::instance().keywordFormat());
seqd.add(3, 8);
seqd.add(8, 9, Formats::instance().baseNFormat());
HighlightSequence seqe(0, 4, Formats::instance().keywordFormat());
seqe.add(4, 9);
seqe.add(9, 12, Formats::instance().decimalFormat());
HighlightSequence seqf(seqe);
seqf.add(12, 13);
HighlightSequence seqg(seqf);
seqg.add(13, 14);
HighlightSequence seqh(0, 8, Formats::instance().commentFormat());
HighlightSequence seqi(seqd);
seqi.add(9, 17, Formats::instance().commentFormat());
HighlightSequence seqj(seqd);
seqj.add(9, 11, Formats::instance().commentFormat());
HighlightSequence seqk(0, 3);
HighlightSequence seql(0, 3, Formats::instance().keywordFormat());
HighlightSequence seqm(0, 2);
HighlightSequence seqn(0, 8, Formats::instance().commentFormat());
states << 0;
sequences << seqa;
text = "abc";
QTest::newRow("case 0") << states << sequences << text;
sequences.clear();
sequences << seqb;
text = "#define max 100";
QTest::newRow("case 1") << states << sequences << text;
sequences.clear();
sequences << seqc;
text = "#";
QTest::newRow("case 2") << states << sequences << text;
sequences.clear();
sequences << seqd;
text = "int i = 0";
QTest::newRow("case 3") << states << sequences << text;
sequences.clear();
sequences << seqe;
text = "long i = 1LL";
QTest::newRow("case 4") << states << sequences << text;
text = "long i = 1ul";
QTest::newRow("case 5") << states << sequences << text;
sequences.clear();
sequences << seqf;
text = "long i = 1ULL";
QTest::newRow("case 6") << states << sequences << text;
sequences.clear();
sequences << seqg;
text = "long i = 1LLUL";
QTest::newRow("case 7") << states << sequences << text;
text = "long i = 1ULLL";
QTest::newRow("case 8") << states << sequences << text;
sequences.clear();
sequences << seqh;
text = "//int i;";
QTest::newRow("case 9") << states << sequences << text;
sequences.clear();
sequences << seqi;
text = "int i = 0//int i;";
QTest::newRow("case 10") << states << sequences << text;
sequences.clear();
sequences << seqj;
text = "int i = 0//";
QTest::newRow("case 11") << states << sequences << text;
sequences.clear();
sequences << seqk << seqk;
text = "bla\nbla";
QTest::newRow("case 12") << createlDefaultStatesList(2) << sequences << text;
sequences.clear();
sequences << seql << seqm;
text = "int\ni;";
QTest::newRow("case 13") << createlDefaultStatesList(2) << sequences << text;
sequences.clear();
sequences << seqn << seqm;
text = "//int i;\ni;";
QTest::newRow("case 14") << createlDefaultStatesList(2) << sequences << text;
}
void tst_HighlighterEngine::testLineContinue()
{
test();
}
void tst_HighlighterEngine::testLineContinue_data()
{
createColumns();
QList<int> states;
QList<HighlightSequence> sequences;
QString lines;
HighlightSequence seqa(0, 12, Formats::instance().othersFormat());
HighlightSequence seqb(0, 7, Formats::instance().othersFormat());
HighlightSequence seqc(0, 8, Formats::instance().othersFormat());
HighlightSequence seqd(0, 3, Formats::instance().othersFormat());
HighlightSequence seqe(0, 3, Formats::instance().keywordFormat());
seqe.add(3, 8);
seqe.add(8, 9, Formats::instance().baseNFormat());
seqe.add(9, 10);
states << 1 << 2;
sequences << seqa << seqb;
lines = "#define max\\\n 100";
QTest::newRow("case 0") << states << sequences << lines;
clear(&states, &sequences);
states << 1 << 1;
sequences << seqa << seqc;
lines = "#define max\\\n 100\\";
QTest::newRow("case 1") << states << sequences << lines;
clear(&states, &sequences);
states << 1 << 1 << 2;
sequences << seqa << seqc << seqd;
lines = "#define max\\\n 100\\\n000";
QTest::newRow("case 2") << states << sequences << lines;
clear(&states, &sequences);
states << 1 << 1 << 2 << 0;
sequences << seqa << seqc << seqd << seqe;
lines = "#define max\\\n 100\\\n000\nint i = 0;";
QTest::newRow("case 3") << states << sequences << lines;
}
void tst_HighlighterEngine::testPersistentStates()
{
test();
}
void tst_HighlighterEngine::testPersistentStates_data()
{
createColumns();
QList<int> states;
QList<HighlightSequence> sequences;
QString text;
HighlightSequence seqa(0, 3, Formats::instance().keywordFormat());
seqa.add(3, 6);
seqa.add(6, 15, Formats::instance().commentFormat());
seqa.add(15, 16);
HighlightSequence seqb(0, 8, Formats::instance().commentFormat());
HighlightSequence seqc(0, 2, Formats::instance().commentFormat());
HighlightSequence seqd(0, 9, Formats::instance().commentFormat());
seqd.add(9, 18, Formats::instance().errorFormat());
HighlightSequence seqe(0, 5, Formats::instance().errorFormat());
seqe.add(5, 8, Formats::instance().commentFormat());
HighlightSequence seqf(0, 2, Formats::instance().commentFormat());
seqf.add(2, 6);
HighlightSequence seqg(0, 1);
seqg.add(1, 7, Formats::instance().commentFormat());
seqg.add(7, 8, Formats::instance().regionMarketFormat());
seqg.add(8, 15, Formats::instance().errorFormat());
seqg.add(15, 16, Formats::instance().regionMarketFormat());
seqg.add(16, 21, Formats::instance().dataTypeFormat());
seqg.add(21, 22, Formats::instance().regionMarketFormat());
HighlightSequence seqh(0, 2);
states << 0;
sequences << seqa;
text = "int i /* = 0 */;";
QTest::newRow("case 0") << states << sequences << text;
clear(&states, &sequences);
states << 3 << 3;
sequences << seqb << seqc;
text = "/*int i;\ni;";
QTest::newRow("case 1") << states << sequences << text;
clear(&states, &sequences);
states << 3 << 3 << 3;
sequences << seqb << seqc << seqb;
text = "/*int i;\ni;\nint abc;";
QTest::newRow("case 2") << states << sequences << text;
clear(&states, &sequences);
states << 3 << 3 << 0;
sequences << seqb << seqc << seqc;
text = "/*int i;\ni;\n*/";
QTest::newRow("case 3") << states << sequences << text;
clear(&states, &sequences);
states << 4 << 3 << 0;
sequences << seqd << seqe << seqf;
text = "/*int i; /# int j;\nfoo#/bar\n*/f();";
QTest::newRow("case 4") << states << sequences << text;
clear(&states, &sequences);
states << 3;
sequences << seqg;
text = "i/*bla @/#foo#/ dummy ";
QTest::newRow("case 5") << states << sequences << text;
clear(&states, &sequences);
states << 3 << 3;
sequences << seqg << seqc;
text = "i/*bla @/#foo#/ dummy \ni;";
QTest::newRow("case 6") << states << sequences << text;
clear(&states, &sequences);
states << 3 << 3 << 0;
sequences << seqg << seqc << seqh;
text = "i/*bla @/#foo#/ dummy \ni;\n*/";
QTest::newRow("case 7") << states << sequences << text;
}
void tst_HighlighterEngine::setupForEditingLineContinue()
{
m_highlighterMock->startNoTestCalls();
m_text.setPlainText("#define max\\\n xxx\\\nzzz");
m_highlighterMock->endNoTestCalls();
}
void tst_HighlighterEngine::testEditingLineContinue0()
{
setupForEditingLineContinue();
QList<HighlightSequence> sequences;
HighlightSequence seqa(0, 11, Formats::instance().othersFormat());
HighlightSequence seqb(0, 8);
HighlightSequence seqc(0, 3);
sequences << seqa << seqb << seqc;
setExpectedData(createlDefaultStatesList(3), sequences);
removeLastCharacters(m_text.document()->firstBlock(), 1);
}
void tst_HighlighterEngine::testEditingLineContinue1()
{
setupForEditingLineContinue();
setExpectedData(1, HighlightSequence(0, 6, Formats::instance().othersFormat()));
// In this case highlighting should be triggered only for the modified line.
removeFirstCharacters(m_text.document()->firstBlock().next(), 2);
}
void tst_HighlighterEngine::testEditingLineContinue2()
{
setupForEditingLineContinue();
QList<HighlightSequence> sequences;
HighlightSequence seqa(0, 17, Formats::instance().othersFormat());
HighlightSequence seqb(0, 8);
HighlightSequence seqc(0, 3);
sequences << seqa << seqb << seqc;
setExpectedData(createlDefaultStatesList(3), sequences);
addCharactersToEnd(m_text.document()->firstBlock(), "ixum");
}
void tst_HighlighterEngine::testEditingLineContinue3()
{
setupForEditingLineContinue();
setExpectedData(1, HighlightSequence(0, 12, Formats::instance().othersFormat()));
// In this case highlighting should be triggered only for the modified line.
addCharactersToBegin(m_text.document()->firstBlock().next(), "ixum");
}
void tst_HighlighterEngine::testEditingLineContinue4()
{
setupForEditingLineContinue();
QList<int> states;
states << 2 << 0 << 0;
QList<HighlightSequence> sequences;
HighlightSequence seqa(0, 0);
HighlightSequence seqb(0, 8);
HighlightSequence seqc(0, 3);
sequences << seqa << seqb << seqc;
setExpectedData(states, sequences);
m_highlighterMock->considerEmptyLines();
addCharactersToBegin(m_text.document()->firstBlock().next(), "\n");
}
void tst_HighlighterEngine::testEditingLineContinue5()
{
setupForEditingLineContinue();
QList<int> states;
states << 2 << 0;
QList<HighlightSequence> sequences;
HighlightSequence seqa(0, 9, Formats::instance().othersFormat());
HighlightSequence seqb(0, 3);
sequences << seqa << seqb;
setExpectedData(states, sequences);
addCharactersToEnd(m_text.document()->firstBlock().next(), "x");
}
QTEST_MAIN(tst_HighlighterEngine)
#include "tst_highlighterengine.moc"
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment