OSDN Git Service

It's 2011 now.
[qt-creator-jp/qt-creator-jp.git] / tests / auto / generichighlighter / highlighterengine / tst_highlighterengine.cpp
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
8 **
9 ** No Commercial Usage
10 **
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
14 ** this package.
15 **
16 ** GNU Lesser General Public License Usage
17 **
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 as published by the Free Software
20 ** Foundation and appearing in the file LICENSE.LGPL included in the
21 ** packaging of this file.  Please review the following information to
22 ** ensure the GNU Lesser General Public License version 2.1 requirements
23 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 **
25 ** In addition, as a special exception, Nokia gives you certain additional
26 ** rights.  These rights are described in the Nokia Qt LGPL Exception
27 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 **
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
31 **
32 **************************************************************************/
33
34 #include "highlightdefinition.h"
35 #include "keywordlist.h"
36 #include "itemdata.h"
37 #include "context.h"
38 #include "specificrules.h"
39 #include "highlightermock.h"
40 #include "formats.h"
41
42 #include <QtCore/QSharedPointer>
43 #include <QtCore/QScopedPointer>
44 #include <QtCore/QList>
45 #include <QtCore/QMetaType>
46 #include <QtGui/QPlainTextEdit>
47 #include <QtTest/QtTest>
48
49 using namespace TextEditor;
50 using namespace Internal;
51
52 Q_DECLARE_METATYPE(HighlightSequence)
53 Q_DECLARE_METATYPE(QList<int>)
54 Q_DECLARE_METATYPE(QList<HighlightSequence>)
55
56 //TESTED_COMPONENT=src/plugins/texteditor/generichighlighter
57
58 class tst_HighlighterEngine : public QObject
59 {
60     Q_OBJECT
61 public:
62     tst_HighlighterEngine();
63
64 private slots:    
65     void initTestCase();
66     void init();
67
68     void testSimpleLine();
69     void testSimpleLine_data();
70
71     void testLineContinue();
72     void testLineContinue_data();
73     void testEditingLineContinue0();
74     void testEditingLineContinue1();
75     void testEditingLineContinue2();
76     void testEditingLineContinue3();
77     void testEditingLineContinue4();
78     void testEditingLineContinue5();
79
80     void testPersistentStates();
81     void testPersistentStates_data();
82     void testEditingPersistentStates0();
83     void testEditingPersistentStates1();
84     void testEditingPersistentStates2();
85
86     void testDynamicContexts();
87     void testDynamicContexts_data();
88
89     void testFirstNonSpace();
90     void testFirstNonSpace_data();
91
92 private:
93     void createKeywords();
94     void createContexts();
95     void createItemDatas();
96
97     void setExpectedData(int state, const HighlightSequence &seq);
98     void setExpectedData(const QList<int> &states, const QList<HighlightSequence> &seqs);
99     void createColumns();
100     void test();
101     void test(int state, const HighlightSequence &seq, const QString &line);
102     void test(const QList<int> &states, const QList<HighlightSequence> &seqs, const QString &lines);
103
104     void clear(QList<int> *states, QList<HighlightSequence> *sequences) const;
105
106     QList<int> createlDefaultStatesList(int size) const;
107
108     void addCharactersToBegin(QTextBlock block, const QString &s);
109     void addCharactersToEnd(QTextBlock block, const QString &s);
110     void removeFirstCharacters(const QTextBlock &block, int n);
111     void removeLastCharacters(const QTextBlock &block, int n);
112
113     void setupForEditingLineContinue();
114
115     QSharedPointer<HighlightDefinition> m_definition;
116     QScopedPointer<HighlighterMock> m_highlighterMock;
117     QPlainTextEdit m_text;
118 };
119
120 tst_HighlighterEngine::tst_HighlighterEngine() :
121     m_definition(new HighlightDefinition)
122 {}
123
124 void tst_HighlighterEngine::initTestCase()
125 {
126             /***********************************************************/
127             /*** Spaces are ignored when comparing text char formats ***/
128             /***********************************************************/
129
130     createKeywords();
131     createContexts();
132     createItemDatas();
133
134     m_highlighterMock.reset(new HighlighterMock());
135     m_highlighterMock->setDefaultContext(m_definition->initialContext());
136     m_highlighterMock->setDocument(m_text.document());
137     m_highlighterMock->configureFormat(Highlighter::Keyword, Formats::instance().keywordFormat());
138     m_highlighterMock->configureFormat(Highlighter::DataType, Formats::instance().dataTypeFormat());
139     m_highlighterMock->configureFormat(Highlighter::Decimal, Formats::instance().decimalFormat());
140     m_highlighterMock->configureFormat(Highlighter::BaseN, Formats::instance().baseNFormat());
141     m_highlighterMock->configureFormat(Highlighter::Float, Formats::instance().floatFormat());
142     m_highlighterMock->configureFormat(Highlighter::Char, Formats::instance().charFormat());
143     m_highlighterMock->configureFormat(Highlighter::String, Formats::instance().stringFormat());
144     m_highlighterMock->configureFormat(Highlighter::Comment, Formats::instance().commentFormat());
145     m_highlighterMock->configureFormat(Highlighter::Alert, Formats::instance().alertFormat());
146     m_highlighterMock->configureFormat(Highlighter::Error, Formats::instance().errorFormat());
147     m_highlighterMock->configureFormat(Highlighter::Function, Formats::instance().functionFormat());
148     m_highlighterMock->configureFormat(Highlighter::RegionMarker,
149                                        Formats::instance().regionMarketFormat());
150     m_highlighterMock->configureFormat(Highlighter::Others, Formats::instance().othersFormat());
151 }
152
153 void tst_HighlighterEngine::init()
154 {
155     m_highlighterMock->reset();
156 }
157
158 void tst_HighlighterEngine::createKeywords()
159 {
160     QSharedPointer<KeywordList> keywords = m_definition->createKeywordList("keywords");
161     keywords->addKeyword("int");
162     keywords->addKeyword("long");
163 }
164
165 void tst_HighlighterEngine::createContexts()
166 {
167     // Normal context
168     QSharedPointer<Context> normal = m_definition->createContext("Normal", true);
169     normal->setItemData("Normal Text");
170     normal->setLineEndContext("#stay");
171     normal->setDefinition(m_definition);
172
173     // AfterHash context
174     QSharedPointer<Context> afterHash = m_definition->createContext("AfterHash", false);
175     afterHash->setItemData("Error");
176     afterHash->setLineEndContext("#pop");
177     afterHash->setDefinition(m_definition);
178
179     // Define context
180     QSharedPointer<Context> define = m_definition->createContext("Define", false);
181     define->setItemData("Preprocessor");
182     define->setLineEndContext("#pop");
183     define->setDefinition(m_definition);
184
185     // Preprocessor context
186     QSharedPointer<Context> preprocessor = m_definition->createContext("Preprocessor", false);
187     preprocessor->setItemData("Preprocessor");
188     preprocessor->setLineEndContext("#pop");
189     preprocessor->setDefinition(m_definition);
190
191     // SimpleComment context
192     QSharedPointer<Context> simpleComment = m_definition->createContext("SimpleComment", false);
193     simpleComment->setItemData("Comment");
194     simpleComment->setLineEndContext("#pop");
195     simpleComment->setDefinition(m_definition);
196
197     // MultilineComment context
198     QSharedPointer<Context> multiComment = m_definition->createContext("MultilineComment", false);
199     multiComment->setItemData("Comment");
200     multiComment->setLineEndContext("#stay");
201     multiComment->setDefinition(m_definition);
202
203     // NestedComment context
204     QSharedPointer<Context> nestedComment = m_definition->createContext("NestedComment", false);
205     nestedComment->setItemData("Other Comment");
206     nestedComment->setLineEndContext("#stay");
207     nestedComment->setDefinition(m_definition);
208
209     // Dummy context
210     QSharedPointer<Context> dummy = m_definition->createContext("Dummy", false);
211     dummy->setItemData("Dummy");
212     dummy->setLineEndContext("#pop");
213     dummy->setDefinition(m_definition);
214
215     // AfterPlus context
216     QSharedPointer<Context> afterPlus = m_definition->createContext("AfterPlus", false);
217     afterPlus->setItemData("Char");
218     afterPlus->setLineEndContext("#pop");
219     afterPlus->setDefinition(m_definition);
220
221     // AfterMinus context
222     QSharedPointer<Context> afterMinus = m_definition->createContext("AfterMinus", false);
223     afterMinus->setItemData("String");
224     afterMinus->setLineEndContext("#pop#pop");
225     afterMinus->setDefinition(m_definition);
226
227     // AfterEqual context
228     QSharedPointer<Context> afterEqual = m_definition->createContext("AfterEqual", false);
229     afterEqual->setItemData("Float");
230     afterEqual->setLineEndContext("#pop#pop#pop");
231     afterEqual->setDefinition(m_definition);
232
233     // Dynamic context
234     QSharedPointer<Context> dynamic = m_definition->createContext("Dynamic", false);
235     dynamic->setItemData("Marker");
236     dynamic->setLineEndContext("#pop");
237     dynamic->setDynamic("true");
238     dynamic->setDefinition(m_definition);
239
240     // Rules
241     DetectCharRule *r = new DetectCharRule;
242     r->setChar("?");
243     r->setContext("#stay");
244     r->setItemData("Decimal");
245     r->setDefinition(m_definition);
246     normal->addRule(QSharedPointer<Rule>(r)); // Needs to be the first one added.
247
248     DetectCharRule *r0 = new DetectCharRule;
249     r0->setChar("#");
250     r0->setContext("AfterHash");
251     r0->setFirstNonSpace("true");
252     r0->setLookAhead("true");
253     r0->setDefinition(m_definition);
254     normal->addRule(QSharedPointer<Rule>(r0));
255
256     RegExprRule *r1 = new RegExprRule;
257     r1->setPattern("#\\s*define.*((?=\\\\))");
258     r1->setInsensitive("true");
259     r1->setContext("Define");
260     r1->setItemData("Preprocessor");
261     r1->setFirstNonSpace("true");
262     r1->setDefinition(m_definition);
263     afterHash->addRule(QSharedPointer<Rule>(r1));
264
265     RegExprRule *r2 = new RegExprRule;
266     r2->setPattern("#\\s*(?:define|undef)");
267     r2->setInsensitive("true");
268     r2->setContext("Preprocessor");
269     r2->setItemData("Preprocessor");
270     r2->setFirstNonSpace("true");
271     r2->setDefinition(m_definition);
272     afterHash->addRule(QSharedPointer<Rule>(r2));
273
274     LineContinueRule *r3 = new LineContinueRule;
275     r3->setItemData("Preprocessor");
276     r3->setContext("#stay");
277     r3->setDefinition(m_definition);
278     define->addRule(QSharedPointer<Rule>(r3));
279
280     LineContinueRule *r4 = new LineContinueRule;
281     r4->setItemData("Preprocessor");
282     r4->setContext("#stay");
283     r4->setDefinition(m_definition);
284     preprocessor->addRule(QSharedPointer<Rule>(r4));
285
286     KeywordRule *r5 = new KeywordRule(m_definition);
287     r5->setList("keywords");
288     r5->setItemData("Keyword");
289     r5->setContext("#stay");
290     r5->setDefinition(m_definition);
291     normal->addRule(QSharedPointer<Rule>(r5));
292
293     IntRule *r6 = new IntRule;
294     r6->setItemData("Decimal");
295     r6->setContext("#stay");
296     r6->setDefinition(m_definition);
297     normal->addRule(QSharedPointer<Rule>(r6));
298
299     StringDetectRule *r7 = new StringDetectRule;
300     r7->setItemData("Decimal");
301     r7->setContext("#stay");
302     r7->setString("LL");
303     r7->setInsensitive("true");
304     r7->setDefinition(m_definition);
305     r6->addChild(QSharedPointer<Rule>(r7));
306
307     StringDetectRule *r8 = new StringDetectRule;
308     r8->setItemData("Decimal");
309     r8->setContext("#stay");
310     r8->setString("UL");
311     r8->setInsensitive("true");
312     r8->setDefinition(m_definition);
313     r6->addChild(QSharedPointer<Rule>(r8));
314
315     HlCOctRule *r9 = new HlCOctRule;
316     r9->setItemData("Octal");
317     r9->setContext("#stay");
318     r9->setDefinition(m_definition);
319     normal->addRule(QSharedPointer<Rule>(r9));
320
321     Detect2CharsRule *r10 = new Detect2CharsRule;
322     r10->setChar("/");
323     r10->setChar1("/");
324     r10->setItemData("Comment");
325     r10->setContext("SimpleComment");
326     r10->setDefinition(m_definition);
327     normal->addRule(QSharedPointer<Rule>(r10));
328
329     DetectIdentifierRule *r11 = new DetectIdentifierRule;
330     r11->setDefinition(m_definition);
331     simpleComment->addRule(QSharedPointer<Rule>(r11));
332
333     Detect2CharsRule *r12 = new Detect2CharsRule;
334     r12->setChar("/");
335     r12->setChar1("*");
336     r12->setItemData("Comment");
337     r12->setContext("MultilineComment");
338     r12->setDefinition(m_definition);
339     normal->addRule(QSharedPointer<Rule>(r12));
340
341     Detect2CharsRule *r13 = new Detect2CharsRule;
342     r13->setChar("*");
343     r13->setChar1("/");
344     r13->setItemData("Comment");
345     r13->setContext("#pop");
346     r13->setDefinition(m_definition);
347     multiComment->addRule(QSharedPointer<Rule>(r13));
348
349     Detect2CharsRule *r14 = new Detect2CharsRule;
350     r14->setChar("/");
351     r14->setChar1("#");
352     r14->setItemData("Other Comment");
353     r14->setContext("NestedComment");
354     r14->setDefinition(m_definition);
355     QSharedPointer<Rule> sr14(r14);
356     multiComment->addRule(sr14);
357     dummy->addRule(sr14);
358     afterEqual->addRule(sr14);
359     afterMinus->addRule(sr14);
360     afterPlus->addRule(sr14);
361
362     Detect2CharsRule *r15 = new Detect2CharsRule;
363     r15->setChar("#");
364     r15->setChar1("/");
365     r15->setItemData("Other Comment");
366     r15->setContext("#pop");
367     r15->setDefinition(m_definition);
368     nestedComment->addRule(QSharedPointer<Rule>(r15));
369
370     DetectCharRule *r16 = new DetectCharRule;
371     r16->setChar("@");
372     r16->setItemData("Marker");
373     r16->setContext("Dummy");
374     r16->setDefinition(m_definition);
375     multiComment->addRule(QSharedPointer<Rule>(r16));
376
377     StringDetectRule *r17 = new StringDetectRule;
378     r17->setString("dummy");
379     r17->setItemData("Dummy");
380     r17->setContext("#stay");
381     r17->setDefinition(m_definition);
382     dummy->addRule(QSharedPointer<Rule>(r17));
383
384     DetectCharRule *r18 = new DetectCharRule;
385     r18->setChar("+");
386     r18->setContext("AfterPlus");
387     r18->setDefinition(m_definition);
388     QSharedPointer<Rule> sr18(r18);
389     multiComment->addRule(sr18);
390     nestedComment->addRule(sr18);
391     afterMinus->addRule(sr18);
392     afterEqual->addRule(sr18);
393
394     DetectCharRule *r19 = new DetectCharRule;
395     r19->setChar("-");
396     r19->setContext("AfterMinus");
397     r19->setDefinition(m_definition);
398     QSharedPointer<Rule> sr19(r19);
399     multiComment->addRule(sr19);
400     nestedComment->addRule(sr19);
401     afterPlus->addRule(sr19);
402     afterEqual->addRule(sr19);
403
404     DetectCharRule *r20 = new DetectCharRule;
405     r20->setChar("=");
406     r20->setContext("AfterEqual");
407     r20->setDefinition(m_definition);
408     QSharedPointer<Rule> sr20(r20);
409     multiComment->addRule(sr20);
410     nestedComment->addRule(sr20);
411     afterPlus->addRule(sr20);
412     afterMinus->addRule(sr20);
413
414     DetectCharRule *r22 = new DetectCharRule;
415     r22->setChar("$");
416     r22->setContext("#stay");
417     r22->setDefinition(m_definition);
418     normal->addRule(QSharedPointer<Rule>(r22));
419
420     DetectCharRule *r23 = new DetectCharRule;
421     r23->setChar("?");
422     r23->setContext("#stay");
423     r23->setItemData("Comment");
424     r23->setDefinition(m_definition);
425     normal->addRule(QSharedPointer<Rule>(r23));
426
427     RegExprRule *r24 = new RegExprRule;
428     r24->setInsensitive("true");
429     r24->setPattern("---([a-c]*)([d-f]*)");
430     r24->setDefinition(m_definition);
431     r24->setItemData("Dummy");
432     r24->setContext("Dynamic");
433     normal->addRule(QSharedPointer<Rule>(r24));
434
435     DetectCharRule *r25 = new DetectCharRule;
436     r25->setChar("1");
437     r25->setItemData("Preprocessor");
438     r25->setActive("true");
439     r25->setDefinition(m_definition);
440     dynamic->addRule(QSharedPointer<Rule>(r25));
441
442     StringDetectRule *r26 = new StringDetectRule;
443     r26->setString("begin%2end");
444     r26->setItemData("Error");
445     r26->setActive("true");
446     r26->setDefinition(m_definition);
447     dynamic->addRule(QSharedPointer<Rule>(r26));
448
449     DetectCharRule *r27 = new DetectCharRule;
450     r27->setChar("|");
451     r27->setItemData("Error");
452     r27->setFirstNonSpace("true");
453     r27->setDefinition(m_definition);
454     normal->addRule(QSharedPointer<Rule>(r27));
455 }
456
457 void tst_HighlighterEngine::createItemDatas()
458 {
459     QSharedPointer<ItemData> normalText = m_definition->createItemData("Normal Text");
460     normalText->setStyle("dsNormal");
461     QSharedPointer<ItemData> preprocessor = m_definition->createItemData("Preprocessor");
462     preprocessor->setStyle("dsOthers");
463     QSharedPointer<ItemData> error = m_definition->createItemData("Error");
464     error->setStyle("dsError");
465     QSharedPointer<ItemData> keyword = m_definition->createItemData("Keyword");
466     keyword->setStyle("dsKeyword");
467     QSharedPointer<ItemData> decimal = m_definition->createItemData("Decimal");
468     decimal->setStyle("dsDecVal");
469     QSharedPointer<ItemData> octal = m_definition->createItemData("Octal");
470     octal->setStyle("dsBaseN");
471     QSharedPointer<ItemData> comment = m_definition->createItemData("Comment");
472     comment->setStyle("dsComment");
473     QSharedPointer<ItemData> otherComment = m_definition->createItemData("Other Comment");
474     otherComment->setStyle("dsError");
475     QSharedPointer<ItemData> marker = m_definition->createItemData("Marker");
476     marker->setStyle("dsRegionMarker");
477     QSharedPointer<ItemData> dummy = m_definition->createItemData("Dummy");
478     dummy->setStyle("dsDataType");
479     QSharedPointer<ItemData> charStyle = m_definition->createItemData("Char");
480     charStyle->setStyle("dsChar");
481     QSharedPointer<ItemData> stringStyle = m_definition->createItemData("String");
482     stringStyle->setStyle("dsString");
483     QSharedPointer<ItemData> floatStyle = m_definition->createItemData("Float");
484     floatStyle->setStyle("dsFloat");
485 }
486
487 void tst_HighlighterEngine::setExpectedData(int state, const HighlightSequence &seq)
488 {
489     m_highlighterMock->setExpectedBlockState(state);
490     m_highlighterMock->setExpectedHighlightSequence(seq);
491 }
492
493 void tst_HighlighterEngine::setExpectedData(const QList<int> &states,
494                                             const QList<HighlightSequence> &seqs)
495 {
496     m_highlighterMock->setExpectedBlockStates(states);
497     m_highlighterMock->setExpectedHighlightSequences(seqs);
498 }
499
500 void tst_HighlighterEngine::createColumns()
501 {
502     QTest::addColumn<QList<int> >("states");
503     QTest::addColumn<QList<HighlightSequence> >("sequences");
504     QTest::addColumn<QString>("lines");
505 }
506
507 void tst_HighlighterEngine::test()
508 {
509     QFETCH(QList<int>, states);
510     QFETCH(QList<HighlightSequence>, sequences);
511     QFETCH(QString, lines);
512
513     test(states, sequences, lines);
514 }
515
516 void tst_HighlighterEngine::test(int state, const HighlightSequence &seq, const QString &line)
517 {
518     setExpectedData(state, seq);
519     m_text.setPlainText(line);
520 }
521
522 void tst_HighlighterEngine::test(const QList<int> &states,
523                                  const QList<HighlightSequence> &seqs,
524                                  const QString &lines)
525 {
526     setExpectedData(states, seqs);
527     m_text.setPlainText(lines);
528 }
529
530 void tst_HighlighterEngine::clear(QList<int> *states, QList<HighlightSequence> *sequences) const
531 {
532     states->clear();
533     sequences->clear();
534 }
535
536 QList<int> tst_HighlighterEngine::createlDefaultStatesList(int size) const
537 {
538     QList<int> states;
539     for (int i = 0; i < size; ++i)
540         states.append(0);
541     return states;
542 }
543
544 void tst_HighlighterEngine::addCharactersToBegin(QTextBlock block, const QString &s)
545 {
546     QTextCursor cursor = m_text.textCursor();
547     cursor.beginEditBlock();
548     cursor.setPosition(block.position());
549     cursor.insertText(s);
550     cursor.endEditBlock();
551 }
552
553 void tst_HighlighterEngine::addCharactersToEnd(QTextBlock block, const QString &s)
554 {
555     QTextCursor cursor = m_text.textCursor();
556     cursor.beginEditBlock();
557     cursor.setPosition(block.position() + block.length() - 1);
558     cursor.insertText(s);
559     cursor.endEditBlock();
560 }
561
562 void tst_HighlighterEngine::removeFirstCharacters(const QTextBlock &block, int n)
563 {
564     QTextCursor cursor = m_text.textCursor();
565     cursor.beginEditBlock();
566     cursor.setPosition(block.position());
567     cursor.movePosition(QTextCursor::NextCharacter, QTextCursor::KeepAnchor, n);
568     cursor.removeSelectedText();
569     cursor.endEditBlock();
570 }
571
572 void tst_HighlighterEngine::removeLastCharacters(const QTextBlock &block, int n)
573 {
574     QTextCursor cursor = m_text.textCursor();
575     cursor.beginEditBlock();
576     cursor.setPosition(block.position() + block.length() - 1);
577     cursor.movePosition(QTextCursor::PreviousCharacter, QTextCursor::KeepAnchor, n);
578     cursor.removeSelectedText();
579     cursor.endEditBlock();
580 }
581
582 void tst_HighlighterEngine::testSimpleLine()
583 {
584     test();
585 }
586
587 void tst_HighlighterEngine::testSimpleLine_data()
588 {
589     createColumns();
590
591     QList<int> states;
592     QList<HighlightSequence> sequences;
593     QString text;
594
595     HighlightSequence seqa(0, 3);
596     HighlightSequence seqb(0, 15, Formats::instance().othersFormat());
597     HighlightSequence seqc(0, 1, Formats::instance().errorFormat());
598     HighlightSequence seqd(0, 3, Formats::instance().keywordFormat());
599     seqd.add(3, 8);
600     seqd.add(8, 9, Formats::instance().baseNFormat());
601     HighlightSequence seqe(0, 4, Formats::instance().keywordFormat());
602     seqe.add(4, 9);
603     seqe.add(9, 12, Formats::instance().decimalFormat());
604     HighlightSequence seqf(seqe);
605     seqf.add(12, 13);
606     HighlightSequence seqg(seqf);
607     seqg.add(13, 14);
608     HighlightSequence seqh(0, 8, Formats::instance().commentFormat());
609     HighlightSequence seqi(seqd);
610     seqi.add(9, 17, Formats::instance().commentFormat());
611     HighlightSequence seqj(seqd);
612     seqj.add(9, 11, Formats::instance().commentFormat());    
613     HighlightSequence seqk(0, 3);
614     HighlightSequence seql(0, 3, Formats::instance().keywordFormat());
615     HighlightSequence seqm(0, 2);
616     HighlightSequence seqn(0, 8, Formats::instance().commentFormat());
617     HighlightSequence seqo(0, 1);
618     seqo.add(1, 2, Formats::instance().decimalFormat());
619
620     states << 0;
621     sequences << seqa;
622     text = "abc";
623     QTest::newRow("case 0") << states << sequences << text;
624
625     sequences.clear();
626     sequences << seqb;
627     text = "#define max 100";
628     QTest::newRow("case 1") << states << sequences << text;
629
630     sequences.clear();
631     sequences << seqc;
632     text = "#";
633     QTest::newRow("case 2") << states << sequences << text;
634
635     sequences.clear();
636     sequences << seqd;
637     text = "int i = 0";
638     QTest::newRow("case 3") << states << sequences << text;
639
640     sequences.clear();
641     sequences << seqe;
642     text = "long i = 1LL";
643     QTest::newRow("case 4") << states << sequences << text;
644
645     text = "long i = 1ul";
646     QTest::newRow("case 5") << states << sequences << text;
647
648     sequences.clear();
649     sequences << seqf;
650     text = "long i = 1ULL";
651     QTest::newRow("case 6") << states << sequences << text;
652
653     sequences.clear();
654     sequences << seqg;
655     text = "long i = 1LLUL";
656     QTest::newRow("case 7") << states << sequences << text;
657
658     text = "long i = 1ULLL";
659     QTest::newRow("case 8") << states << sequences << text;
660
661     sequences.clear();
662     sequences << seqh;
663     text = "//int i;";
664     QTest::newRow("case 9") << states << sequences << text;
665
666     sequences.clear();
667     sequences << seqi;
668     text = "int i = 0//int i;";
669     QTest::newRow("case 10") << states << sequences << text;
670
671     sequences.clear();
672     sequences << seqj;
673     text = "int i = 0//";
674     QTest::newRow("case 11") << states << sequences << text;
675
676     sequences.clear();
677     sequences << seqk << seqk;
678     text = "bla\nbla";
679     QTest::newRow("case 12") << createlDefaultStatesList(2) << sequences << text;
680
681     sequences.clear();
682     sequences << seql << seqm;
683     text = "int\ni;";
684     QTest::newRow("case 13") << createlDefaultStatesList(2) << sequences << text;
685
686     sequences.clear();
687     sequences << seqn << seqm;
688     text = "//int i;\ni;";
689     QTest::newRow("case 14") << createlDefaultStatesList(2) << sequences << text;
690
691     // Even when a matching rule does not take to another context, iteration over the rules
692     // should start over from the first rule in the current context.
693     sequences.clear();
694     sequences << seqo;
695     text = "$?";
696     QTest::newRow("case 15") << createlDefaultStatesList(2) << sequences << text;
697 }
698
699 void tst_HighlighterEngine::testLineContinue()
700 {
701     test();
702 }
703
704 void tst_HighlighterEngine::testLineContinue_data()
705 {
706     createColumns();
707
708     QList<int> states;
709     QList<HighlightSequence> sequences;
710     QString lines;
711
712     HighlightSequence seqa(0, 12, Formats::instance().othersFormat());
713     HighlightSequence seqb(0, 7, Formats::instance().othersFormat());
714     HighlightSequence seqc(0, 8, Formats::instance().othersFormat());
715     HighlightSequence seqd(0, 3, Formats::instance().othersFormat());
716     HighlightSequence seqe(0, 3, Formats::instance().keywordFormat());
717     seqe.add(3, 8);
718     seqe.add(8, 9, Formats::instance().baseNFormat());
719     seqe.add(9, 10);
720
721     states << 1 << 2;
722     sequences << seqa << seqb;
723     lines = "#define max\\\n    100";
724     QTest::newRow("case 0") << states << sequences << lines;
725
726     clear(&states, &sequences);
727     states << 1 << 1;
728     sequences << seqa << seqc;
729     lines = "#define max\\\n    100\\";
730     QTest::newRow("case 1") << states << sequences << lines;
731
732     clear(&states, &sequences);
733     states << 1 << 1 << 2;
734     sequences << seqa << seqc << seqd;
735     lines = "#define max\\\n    100\\\n000";
736     QTest::newRow("case 2") << states << sequences << lines;
737
738     clear(&states, &sequences);
739     states << 1 << 1 << 2 << 0;
740     sequences << seqa << seqc << seqd << seqe;
741     lines = "#define max\\\n    100\\\n000\nint i = 0;";
742     QTest::newRow("case 3") << states << sequences << lines;
743 }
744
745 void tst_HighlighterEngine::setupForEditingLineContinue()
746 {
747     m_highlighterMock->startNoTestCalls();
748     m_text.setPlainText("#define max\\\n    xxx\\\nzzz");
749     m_highlighterMock->endNoTestCalls();
750 }
751
752 void tst_HighlighterEngine::testEditingLineContinue0()
753 {
754     setupForEditingLineContinue();
755
756     QList<HighlightSequence> sequences;
757     HighlightSequence seqa(0, 11, Formats::instance().othersFormat());
758     HighlightSequence seqb(0, 8);
759     HighlightSequence seqc(0, 3);
760     sequences << seqa << seqb << seqc;
761     setExpectedData(createlDefaultStatesList(3), sequences);
762
763     removeLastCharacters(m_text.document()->firstBlock(), 1);
764 }
765
766 void tst_HighlighterEngine::testEditingLineContinue1()
767 {
768     setupForEditingLineContinue();
769
770     setExpectedData(1, HighlightSequence(0, 6, Formats::instance().othersFormat()));
771
772     // In this case highlighting should be triggered only for the modified line.
773     removeFirstCharacters(m_text.document()->firstBlock().next(), 2);
774 }
775
776 void tst_HighlighterEngine::testEditingLineContinue2()
777 {
778     setupForEditingLineContinue();
779
780     QList<HighlightSequence> sequences;
781     HighlightSequence seqa(0, 17, Formats::instance().othersFormat());
782     HighlightSequence seqb(0, 8);
783     HighlightSequence seqc(0, 3);
784     sequences << seqa << seqb << seqc;
785     setExpectedData(createlDefaultStatesList(3), sequences);
786
787     addCharactersToEnd(m_text.document()->firstBlock(), "ixum");
788 }
789
790 void tst_HighlighterEngine::testEditingLineContinue3()
791 {
792     setupForEditingLineContinue();
793
794     setExpectedData(1, HighlightSequence(0, 12, Formats::instance().othersFormat()));
795
796     // In this case highlighting should be triggered only for the modified line.
797     addCharactersToBegin(m_text.document()->firstBlock().next(), "ixum");
798 }
799
800 void tst_HighlighterEngine::testEditingLineContinue4()
801 {
802     setupForEditingLineContinue();
803
804     QList<int> states;
805     states << 2 << 0 << 0;
806     QList<HighlightSequence> sequences;
807     HighlightSequence seqa(0, 0);
808     HighlightSequence seqb(0, 8);
809     HighlightSequence seqc(0, 3);
810     sequences << seqa << seqb << seqc;
811     setExpectedData(states, sequences);
812
813     m_highlighterMock->considerEmptyLines();
814     addCharactersToBegin(m_text.document()->firstBlock().next(), "\n");
815 }
816
817 void tst_HighlighterEngine::testEditingLineContinue5()
818 {
819     setupForEditingLineContinue();
820
821     QList<int> states;
822     states << 2 << 0;
823     QList<HighlightSequence> sequences;
824     HighlightSequence seqa(0, 9, Formats::instance().othersFormat());
825     HighlightSequence seqb(0, 3);
826     sequences << seqa << seqb;
827     setExpectedData(states, sequences);
828
829     addCharactersToEnd(m_text.document()->firstBlock().next(), "x");
830 }
831
832 void tst_HighlighterEngine::testPersistentStates()
833 {
834     test();
835 }
836
837 void tst_HighlighterEngine::testPersistentStates_data()
838 {
839     createColumns();
840
841     QList<int> states;
842     QList<HighlightSequence> sequences;
843     QString text;
844
845     HighlightSequence seqa(0, 3, Formats::instance().keywordFormat());
846     seqa.add(3, 6);
847     seqa.add(6, 15, Formats::instance().commentFormat());
848     seqa.add(15, 16);
849     HighlightSequence seqb(0, 8, Formats::instance().commentFormat());
850     HighlightSequence seqc(0, 2, Formats::instance().commentFormat());
851     HighlightSequence seqd(0, 9, Formats::instance().commentFormat());
852     seqd.add(9, 18, Formats::instance().errorFormat());
853     HighlightSequence seqe(0, 5, Formats::instance().errorFormat());
854     seqe.add(5, 8, Formats::instance().commentFormat());
855     HighlightSequence seqf(0, 2, Formats::instance().commentFormat());
856     seqf.add(2, 6);
857     HighlightSequence seqg(0, 1);
858     seqg.add(1, 7, Formats::instance().commentFormat());
859     seqg.add(7, 8, Formats::instance().regionMarketFormat());
860     seqg.add(8, 15, Formats::instance().errorFormat());
861     seqg.add(15, 16, Formats::instance().regionMarketFormat());
862     seqg.add(16, 21, Formats::instance().dataTypeFormat());
863     seqg.add(21, 22, Formats::instance().regionMarketFormat());
864     HighlightSequence seqh(seqc);
865     seqh.add(2, 3);
866     HighlightSequence seqi(seqc);
867     seqi.add(2, 3, Formats::instance().charFormat());
868     seqi.add(3, 4, Formats::instance().stringFormat());
869     HighlightSequence seqj(seqc);
870     seqj.add(2, 3, Formats::instance().charFormat());
871     seqj.add(3, 4, Formats::instance().floatFormat());
872     HighlightSequence seqk(seqc);
873     seqk.add(2, 3, Formats::instance().charFormat());
874     seqk.add(3, 5, Formats::instance().errorFormat());
875     seqk.add(5, 6, Formats::instance().floatFormat());
876     HighlightSequence seql(seqk);
877     seql.add(6, 7, Formats::instance().stringFormat());
878
879     states << 0;
880     sequences << seqa;
881     text = "int i /* 000 */;";
882     QTest::newRow("case 0") << states << sequences << text;
883
884     clear(&states, &sequences);
885     states << 3 << 3;
886     sequences << seqb << seqc;
887     text = "/*int i;\ni;";
888     QTest::newRow("case 1") << states << sequences << text;
889
890     clear(&states, &sequences);
891     states << 3 << 3 << 3;
892     sequences << seqb << seqc << seqb;
893     text = "/*int i;\ni;\nint abc;";
894     QTest::newRow("case 2") << states << sequences << text;
895
896     clear(&states, &sequences);
897     states << 3 << 3 << 0;
898     sequences << seqb << seqc << seqc;
899     text = "/*int i;\ni;\n*/";
900     QTest::newRow("case 3") << states << sequences << text;
901
902     clear(&states, &sequences);
903     states << 4 << 3 << 0;
904     sequences << seqd << seqe << seqf;
905     text = "/*int i; /# int j;\nfoo#/bar\n*/f();";
906     QTest::newRow("case 4") << states << sequences << text;
907
908     clear(&states, &sequences);
909     states << 3;
910     sequences << seqg;
911     text = "i/*bla @/#foo#/ dummy ";
912     QTest::newRow("case 5") << states << sequences << text;
913
914     clear(&states, &sequences);
915     states << 3 << 3;
916     sequences << seqg << seqc;
917     text = "i/*bla @/#foo#/ dummy \ni;";
918     QTest::newRow("case 6") << states << sequences << text;
919
920     clear(&states, &sequences);
921     states << 3 << 3 << 0;
922     sequences << seqg << seqc << seqc;
923     text = "i/*bla @/#foo#/ dummy \ni;\n*/";
924     QTest::newRow("case 7") << states << sequences << text;
925
926     clear(&states, &sequences);
927     states << 3 << 3 << 0;
928     sequences << seqg << seqc << seqh;
929     text = "i/*bla @/#foo#/ dummy \ni;\n*/a";
930     QTest::newRow("case 8") << states << sequences << text;
931
932     clear(&states, &sequences);
933     states << 3;
934     sequences << seqi;
935     text = "/*+-";
936     QTest::newRow("case 9") << states << sequences << text;
937
938     clear(&states, &sequences);
939     states << 0;
940     sequences << seqj;
941     text = "/*+=";
942     QTest::newRow("case 10") << states << sequences << text;
943
944     clear(&states, &sequences);
945     states << 3;
946     sequences << seqk;
947     text = "/*+/#=";
948     QTest::newRow("case 11") << states << sequences << text;
949
950     clear(&states, &sequences);
951     states << 6;
952     sequences << seql;
953     text = "/*+/#=-";
954     QTest::newRow("case 12") << states << sequences << text;
955 }
956
957 void tst_HighlighterEngine::testEditingPersistentStates0()
958 {
959     m_highlighterMock->startNoTestCalls();
960     m_text.setPlainText("a b c /\ninside\n*/\na b c");
961     m_highlighterMock->endNoTestCalls();
962
963     QList<int> states;
964     states << 3 << 3 << 0 << 0;
965     QList<HighlightSequence> sequences;
966     HighlightSequence seqa(0, 6);
967     seqa.add(6, 8, Formats::instance().commentFormat());
968     HighlightSequence seqb(0, 6, Formats::instance().commentFormat());
969     HighlightSequence seqc(0, 2, Formats::instance().commentFormat());
970     HighlightSequence seqd(0, 5);
971     sequences << seqa << seqb << seqc << seqd;
972     setExpectedData(states, sequences);
973
974     addCharactersToEnd(m_text.document()->firstBlock(), "*");
975 }
976
977 void tst_HighlighterEngine::testEditingPersistentStates1()
978 {
979     m_highlighterMock->startNoTestCalls();
980     m_text.setPlainText("/*abc\n/\nnesting\nnesting\n#/\n*/xyz");
981     m_highlighterMock->endNoTestCalls();
982
983     QList<int> states;
984     states << 4 << 4 << 4 << 3 << 0;
985     QList<HighlightSequence> sequences;
986     HighlightSequence seqa(0, 2, Formats::instance().errorFormat());
987     HighlightSequence seqb(0, 7, Formats::instance().errorFormat());
988     HighlightSequence seqc(seqb);
989     HighlightSequence seqd(0, 2, Formats::instance().errorFormat());
990     HighlightSequence seqe(0, 2, Formats::instance().commentFormat());
991     seqe.add(2, 5);
992     sequences << seqa << seqb << seqc << seqd << seqe;
993     setExpectedData(states, sequences);
994
995     addCharactersToEnd(m_text.document()->firstBlock().next(), "#");
996 }
997
998 void tst_HighlighterEngine::testEditingPersistentStates2()
999 {
1000     m_highlighterMock->startNoTestCalls();
1001     m_text.setPlainText("/*abc\n/\nnesting\nnesting\n*/\n#/xyz");
1002     m_highlighterMock->endNoTestCalls();
1003
1004     QList<int> states;
1005     states << 4 << 4 << 4 << 4 << 3;
1006     QList<HighlightSequence> sequences;
1007     HighlightSequence seqa(0, 2, Formats::instance().errorFormat());
1008     HighlightSequence seqb(0, 7, Formats::instance().errorFormat());
1009     HighlightSequence seqc(seqb);
1010     HighlightSequence seqd(0, 2, Formats::instance().errorFormat());
1011     HighlightSequence seqe(seqd);
1012     seqe.add(2, 5, Formats::instance().commentFormat());
1013     sequences << seqa << seqb << seqc << seqd << seqe;
1014     setExpectedData(states, sequences);
1015
1016     addCharactersToEnd(m_text.document()->firstBlock().next(), "#");
1017 }
1018
1019 void tst_HighlighterEngine::testDynamicContexts()
1020 {
1021     test();
1022 }
1023
1024 void tst_HighlighterEngine::testDynamicContexts_data()
1025 {
1026     createColumns();
1027
1028     QList<int> states;
1029     QList<HighlightSequence> sequences;
1030     QString text;
1031
1032     HighlightSequence seqa(0, 2);
1033     seqa.add(2, 15, Formats::instance().dataTypeFormat());
1034     seqa.add(15, 16, Formats::instance().othersFormat());
1035     seqa.add(16, 17, Formats::instance().regionMarketFormat());
1036     HighlightSequence seqb(seqa);
1037     seqb.add(17, 31, Formats::instance().errorFormat());
1038
1039     states << 0;
1040     sequences << seqa;
1041     text = "a ---abcddeeff a ";
1042     QTest::newRow("case 0") << states << sequences << text;
1043
1044     sequences.clear();
1045     sequences << seqb;
1046     text = "a ---abcddeeff a beginddeeffend";
1047     QTest::newRow("case 1") << states << sequences << text;
1048 }
1049
1050 void tst_HighlighterEngine::testFirstNonSpace()
1051 {
1052     test();
1053 }
1054
1055 void tst_HighlighterEngine::testFirstNonSpace_data()
1056 {
1057     createColumns();
1058
1059     QList<int> states;
1060     QList<HighlightSequence> sequences;
1061     QString text;
1062
1063     HighlightSequence seqa(0, 1, Formats::instance().errorFormat());
1064     HighlightSequence seqb(0, 3);
1065     seqb.add(3, 4, Formats::instance().errorFormat());
1066     HighlightSequence seqc(0, 1);
1067     seqc.add(1, 2, Formats::instance().errorFormat());
1068     HighlightSequence seqd(0, 2);
1069
1070     states << 0;
1071     sequences << seqa;
1072     text = "|";
1073     QTest::newRow("case 0") << states << sequences << text;
1074
1075     sequences.clear();
1076     sequences << seqb;
1077     text = "   |";
1078     QTest::newRow("case 1") << states << sequences << text;
1079
1080     sequences.clear();
1081     sequences << seqc;
1082     text = "\t|";
1083     QTest::newRow("case 2") << states << sequences << text;
1084
1085     sequences.clear();
1086     sequences << seqd;
1087     text = "a|";
1088     QTest::newRow("case 3") << states << sequences << text;
1089 }
1090
1091 QTEST_MAIN(tst_HighlighterEngine)
1092 #include "tst_highlighterengine.moc"
1093