1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (qt-info@nokia.com)
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
16 ** GNU Lesser General Public License Usage
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.
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.
29 ** If you have questions regarding the use of this file, please contact
30 ** Nokia at qt-info@nokia.com.
32 **************************************************************************/
34 #include "highlightdefinition.h"
35 #include "keywordlist.h"
38 #include "specificrules.h"
39 #include "highlightermock.h"
42 #include <QtCore/QSharedPointer>
43 #include <QtCore/QScopedPointer>
44 #include <QtCore/QList>
45 #include <QtCore/QMetaType>
46 #include <QtGui/QPlainTextEdit>
47 #include <QtTest/QtTest>
49 using namespace TextEditor;
50 using namespace Internal;
52 Q_DECLARE_METATYPE(HighlightSequence)
53 Q_DECLARE_METATYPE(QList<int>)
54 Q_DECLARE_METATYPE(QList<HighlightSequence>)
56 //TESTED_COMPONENT=src/plugins/texteditor/generichighlighter
58 class tst_HighlighterEngine : public QObject
62 tst_HighlighterEngine();
68 void testSimpleLine();
69 void testSimpleLine_data();
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();
80 void testPersistentStates();
81 void testPersistentStates_data();
82 void testEditingPersistentStates0();
83 void testEditingPersistentStates1();
84 void testEditingPersistentStates2();
86 void testDynamicContexts();
87 void testDynamicContexts_data();
89 void testFirstNonSpace();
90 void testFirstNonSpace_data();
93 void createKeywords();
94 void createContexts();
95 void createItemDatas();
97 void setExpectedData(int state, const HighlightSequence &seq);
98 void setExpectedData(const QList<int> &states, const QList<HighlightSequence> &seqs);
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);
104 void clear(QList<int> *states, QList<HighlightSequence> *sequences) const;
106 QList<int> createlDefaultStatesList(int size) const;
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);
113 void setupForEditingLineContinue();
115 QSharedPointer<HighlightDefinition> m_definition;
116 QScopedPointer<HighlighterMock> m_highlighterMock;
117 QPlainTextEdit m_text;
120 tst_HighlighterEngine::tst_HighlighterEngine() :
121 m_definition(new HighlightDefinition)
124 void tst_HighlighterEngine::initTestCase()
126 /***********************************************************/
127 /*** Spaces are ignored when comparing text char formats ***/
128 /***********************************************************/
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());
153 void tst_HighlighterEngine::init()
155 m_highlighterMock->reset();
158 void tst_HighlighterEngine::createKeywords()
160 QSharedPointer<KeywordList> keywords = m_definition->createKeywordList("keywords");
161 keywords->addKeyword("int");
162 keywords->addKeyword("long");
165 void tst_HighlighterEngine::createContexts()
168 QSharedPointer<Context> normal = m_definition->createContext("Normal", true);
169 normal->setItemData("Normal Text");
170 normal->setLineEndContext("#stay");
171 normal->setDefinition(m_definition);
174 QSharedPointer<Context> afterHash = m_definition->createContext("AfterHash", false);
175 afterHash->setItemData("Error");
176 afterHash->setLineEndContext("#pop");
177 afterHash->setDefinition(m_definition);
180 QSharedPointer<Context> define = m_definition->createContext("Define", false);
181 define->setItemData("Preprocessor");
182 define->setLineEndContext("#pop");
183 define->setDefinition(m_definition);
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);
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);
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);
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);
210 QSharedPointer<Context> dummy = m_definition->createContext("Dummy", false);
211 dummy->setItemData("Dummy");
212 dummy->setLineEndContext("#pop");
213 dummy->setDefinition(m_definition);
216 QSharedPointer<Context> afterPlus = m_definition->createContext("AfterPlus", false);
217 afterPlus->setItemData("Char");
218 afterPlus->setLineEndContext("#pop");
219 afterPlus->setDefinition(m_definition);
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);
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);
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);
241 DetectCharRule *r = new DetectCharRule;
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.
248 DetectCharRule *r0 = new DetectCharRule;
250 r0->setContext("AfterHash");
251 r0->setFirstNonSpace("true");
252 r0->setLookAhead("true");
253 r0->setDefinition(m_definition);
254 normal->addRule(QSharedPointer<Rule>(r0));
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));
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));
274 LineContinueRule *r3 = new LineContinueRule;
275 r3->setItemData("Preprocessor");
276 r3->setContext("#stay");
277 r3->setDefinition(m_definition);
278 define->addRule(QSharedPointer<Rule>(r3));
280 LineContinueRule *r4 = new LineContinueRule;
281 r4->setItemData("Preprocessor");
282 r4->setContext("#stay");
283 r4->setDefinition(m_definition);
284 preprocessor->addRule(QSharedPointer<Rule>(r4));
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));
293 IntRule *r6 = new IntRule;
294 r6->setItemData("Decimal");
295 r6->setContext("#stay");
296 r6->setDefinition(m_definition);
297 normal->addRule(QSharedPointer<Rule>(r6));
299 StringDetectRule *r7 = new StringDetectRule;
300 r7->setItemData("Decimal");
301 r7->setContext("#stay");
303 r7->setInsensitive("true");
304 r7->setDefinition(m_definition);
305 r6->addChild(QSharedPointer<Rule>(r7));
307 StringDetectRule *r8 = new StringDetectRule;
308 r8->setItemData("Decimal");
309 r8->setContext("#stay");
311 r8->setInsensitive("true");
312 r8->setDefinition(m_definition);
313 r6->addChild(QSharedPointer<Rule>(r8));
315 HlCOctRule *r9 = new HlCOctRule;
316 r9->setItemData("Octal");
317 r9->setContext("#stay");
318 r9->setDefinition(m_definition);
319 normal->addRule(QSharedPointer<Rule>(r9));
321 Detect2CharsRule *r10 = new Detect2CharsRule;
324 r10->setItemData("Comment");
325 r10->setContext("SimpleComment");
326 r10->setDefinition(m_definition);
327 normal->addRule(QSharedPointer<Rule>(r10));
329 DetectIdentifierRule *r11 = new DetectIdentifierRule;
330 r11->setDefinition(m_definition);
331 simpleComment->addRule(QSharedPointer<Rule>(r11));
333 Detect2CharsRule *r12 = new Detect2CharsRule;
336 r12->setItemData("Comment");
337 r12->setContext("MultilineComment");
338 r12->setDefinition(m_definition);
339 normal->addRule(QSharedPointer<Rule>(r12));
341 Detect2CharsRule *r13 = new Detect2CharsRule;
344 r13->setItemData("Comment");
345 r13->setContext("#pop");
346 r13->setDefinition(m_definition);
347 multiComment->addRule(QSharedPointer<Rule>(r13));
349 Detect2CharsRule *r14 = new Detect2CharsRule;
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);
362 Detect2CharsRule *r15 = new Detect2CharsRule;
365 r15->setItemData("Other Comment");
366 r15->setContext("#pop");
367 r15->setDefinition(m_definition);
368 nestedComment->addRule(QSharedPointer<Rule>(r15));
370 DetectCharRule *r16 = new DetectCharRule;
372 r16->setItemData("Marker");
373 r16->setContext("Dummy");
374 r16->setDefinition(m_definition);
375 multiComment->addRule(QSharedPointer<Rule>(r16));
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));
384 DetectCharRule *r18 = new DetectCharRule;
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);
394 DetectCharRule *r19 = new DetectCharRule;
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);
404 DetectCharRule *r20 = new DetectCharRule;
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);
414 DetectCharRule *r22 = new DetectCharRule;
416 r22->setContext("#stay");
417 r22->setDefinition(m_definition);
418 normal->addRule(QSharedPointer<Rule>(r22));
420 DetectCharRule *r23 = new DetectCharRule;
422 r23->setContext("#stay");
423 r23->setItemData("Comment");
424 r23->setDefinition(m_definition);
425 normal->addRule(QSharedPointer<Rule>(r23));
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));
435 DetectCharRule *r25 = new DetectCharRule;
437 r25->setItemData("Preprocessor");
438 r25->setActive("true");
439 r25->setDefinition(m_definition);
440 dynamic->addRule(QSharedPointer<Rule>(r25));
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));
449 DetectCharRule *r27 = new DetectCharRule;
451 r27->setItemData("Error");
452 r27->setFirstNonSpace("true");
453 r27->setDefinition(m_definition);
454 normal->addRule(QSharedPointer<Rule>(r27));
457 void tst_HighlighterEngine::createItemDatas()
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");
487 void tst_HighlighterEngine::setExpectedData(int state, const HighlightSequence &seq)
489 m_highlighterMock->setExpectedBlockState(state);
490 m_highlighterMock->setExpectedHighlightSequence(seq);
493 void tst_HighlighterEngine::setExpectedData(const QList<int> &states,
494 const QList<HighlightSequence> &seqs)
496 m_highlighterMock->setExpectedBlockStates(states);
497 m_highlighterMock->setExpectedHighlightSequences(seqs);
500 void tst_HighlighterEngine::createColumns()
502 QTest::addColumn<QList<int> >("states");
503 QTest::addColumn<QList<HighlightSequence> >("sequences");
504 QTest::addColumn<QString>("lines");
507 void tst_HighlighterEngine::test()
509 QFETCH(QList<int>, states);
510 QFETCH(QList<HighlightSequence>, sequences);
511 QFETCH(QString, lines);
513 test(states, sequences, lines);
516 void tst_HighlighterEngine::test(int state, const HighlightSequence &seq, const QString &line)
518 setExpectedData(state, seq);
519 m_text.setPlainText(line);
522 void tst_HighlighterEngine::test(const QList<int> &states,
523 const QList<HighlightSequence> &seqs,
524 const QString &lines)
526 setExpectedData(states, seqs);
527 m_text.setPlainText(lines);
530 void tst_HighlighterEngine::clear(QList<int> *states, QList<HighlightSequence> *sequences) const
536 QList<int> tst_HighlighterEngine::createlDefaultStatesList(int size) const
539 for (int i = 0; i < size; ++i)
544 void tst_HighlighterEngine::addCharactersToBegin(QTextBlock block, const QString &s)
546 QTextCursor cursor = m_text.textCursor();
547 cursor.beginEditBlock();
548 cursor.setPosition(block.position());
549 cursor.insertText(s);
550 cursor.endEditBlock();
553 void tst_HighlighterEngine::addCharactersToEnd(QTextBlock block, const QString &s)
555 QTextCursor cursor = m_text.textCursor();
556 cursor.beginEditBlock();
557 cursor.setPosition(block.position() + block.length() - 1);
558 cursor.insertText(s);
559 cursor.endEditBlock();
562 void tst_HighlighterEngine::removeFirstCharacters(const QTextBlock &block, int n)
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();
572 void tst_HighlighterEngine::removeLastCharacters(const QTextBlock &block, int n)
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();
582 void tst_HighlighterEngine::testSimpleLine()
587 void tst_HighlighterEngine::testSimpleLine_data()
592 QList<HighlightSequence> sequences;
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());
600 seqd.add(8, 9, Formats::instance().baseNFormat());
601 HighlightSequence seqe(0, 4, Formats::instance().keywordFormat());
603 seqe.add(9, 12, Formats::instance().decimalFormat());
604 HighlightSequence seqf(seqe);
606 HighlightSequence seqg(seqf);
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());
623 QTest::newRow("case 0") << states << sequences << text;
627 text = "#define max 100";
628 QTest::newRow("case 1") << states << sequences << text;
633 QTest::newRow("case 2") << states << sequences << text;
638 QTest::newRow("case 3") << states << sequences << text;
642 text = "long i = 1LL";
643 QTest::newRow("case 4") << states << sequences << text;
645 text = "long i = 1ul";
646 QTest::newRow("case 5") << states << sequences << text;
650 text = "long i = 1ULL";
651 QTest::newRow("case 6") << states << sequences << text;
655 text = "long i = 1LLUL";
656 QTest::newRow("case 7") << states << sequences << text;
658 text = "long i = 1ULLL";
659 QTest::newRow("case 8") << states << sequences << text;
664 QTest::newRow("case 9") << states << sequences << text;
668 text = "int i = 0//int i;";
669 QTest::newRow("case 10") << states << sequences << text;
673 text = "int i = 0//";
674 QTest::newRow("case 11") << states << sequences << text;
677 sequences << seqk << seqk;
679 QTest::newRow("case 12") << createlDefaultStatesList(2) << sequences << text;
682 sequences << seql << seqm;
684 QTest::newRow("case 13") << createlDefaultStatesList(2) << sequences << text;
687 sequences << seqn << seqm;
688 text = "//int i;\ni;";
689 QTest::newRow("case 14") << createlDefaultStatesList(2) << sequences << text;
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.
696 QTest::newRow("case 15") << createlDefaultStatesList(2) << sequences << text;
699 void tst_HighlighterEngine::testLineContinue()
704 void tst_HighlighterEngine::testLineContinue_data()
709 QList<HighlightSequence> sequences;
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());
718 seqe.add(8, 9, Formats::instance().baseNFormat());
722 sequences << seqa << seqb;
723 lines = "#define max\\\n 100";
724 QTest::newRow("case 0") << states << sequences << lines;
726 clear(&states, &sequences);
728 sequences << seqa << seqc;
729 lines = "#define max\\\n 100\\";
730 QTest::newRow("case 1") << states << sequences << lines;
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;
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;
745 void tst_HighlighterEngine::setupForEditingLineContinue()
747 m_highlighterMock->startNoTestCalls();
748 m_text.setPlainText("#define max\\\n xxx\\\nzzz");
749 m_highlighterMock->endNoTestCalls();
752 void tst_HighlighterEngine::testEditingLineContinue0()
754 setupForEditingLineContinue();
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);
763 removeLastCharacters(m_text.document()->firstBlock(), 1);
766 void tst_HighlighterEngine::testEditingLineContinue1()
768 setupForEditingLineContinue();
770 setExpectedData(1, HighlightSequence(0, 6, Formats::instance().othersFormat()));
772 // In this case highlighting should be triggered only for the modified line.
773 removeFirstCharacters(m_text.document()->firstBlock().next(), 2);
776 void tst_HighlighterEngine::testEditingLineContinue2()
778 setupForEditingLineContinue();
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);
787 addCharactersToEnd(m_text.document()->firstBlock(), "ixum");
790 void tst_HighlighterEngine::testEditingLineContinue3()
792 setupForEditingLineContinue();
794 setExpectedData(1, HighlightSequence(0, 12, Formats::instance().othersFormat()));
796 // In this case highlighting should be triggered only for the modified line.
797 addCharactersToBegin(m_text.document()->firstBlock().next(), "ixum");
800 void tst_HighlighterEngine::testEditingLineContinue4()
802 setupForEditingLineContinue();
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);
813 m_highlighterMock->considerEmptyLines();
814 addCharactersToBegin(m_text.document()->firstBlock().next(), "\n");
817 void tst_HighlighterEngine::testEditingLineContinue5()
819 setupForEditingLineContinue();
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);
829 addCharactersToEnd(m_text.document()->firstBlock().next(), "x");
832 void tst_HighlighterEngine::testPersistentStates()
837 void tst_HighlighterEngine::testPersistentStates_data()
842 QList<HighlightSequence> sequences;
845 HighlightSequence seqa(0, 3, Formats::instance().keywordFormat());
847 seqa.add(6, 15, Formats::instance().commentFormat());
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());
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);
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());
881 text = "int i /* 000 */;";
882 QTest::newRow("case 0") << states << sequences << text;
884 clear(&states, &sequences);
886 sequences << seqb << seqc;
887 text = "/*int i;\ni;";
888 QTest::newRow("case 1") << states << sequences << text;
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;
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;
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;
908 clear(&states, &sequences);
911 text = "i/*bla @/#foo#/ dummy ";
912 QTest::newRow("case 5") << states << sequences << text;
914 clear(&states, &sequences);
916 sequences << seqg << seqc;
917 text = "i/*bla @/#foo#/ dummy \ni;";
918 QTest::newRow("case 6") << states << sequences << text;
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;
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;
932 clear(&states, &sequences);
936 QTest::newRow("case 9") << states << sequences << text;
938 clear(&states, &sequences);
942 QTest::newRow("case 10") << states << sequences << text;
944 clear(&states, &sequences);
948 QTest::newRow("case 11") << states << sequences << text;
950 clear(&states, &sequences);
954 QTest::newRow("case 12") << states << sequences << text;
957 void tst_HighlighterEngine::testEditingPersistentStates0()
959 m_highlighterMock->startNoTestCalls();
960 m_text.setPlainText("a b c /\ninside\n*/\na b c");
961 m_highlighterMock->endNoTestCalls();
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);
974 addCharactersToEnd(m_text.document()->firstBlock(), "*");
977 void tst_HighlighterEngine::testEditingPersistentStates1()
979 m_highlighterMock->startNoTestCalls();
980 m_text.setPlainText("/*abc\n/\nnesting\nnesting\n#/\n*/xyz");
981 m_highlighterMock->endNoTestCalls();
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());
992 sequences << seqa << seqb << seqc << seqd << seqe;
993 setExpectedData(states, sequences);
995 addCharactersToEnd(m_text.document()->firstBlock().next(), "#");
998 void tst_HighlighterEngine::testEditingPersistentStates2()
1000 m_highlighterMock->startNoTestCalls();
1001 m_text.setPlainText("/*abc\n/\nnesting\nnesting\n*/\n#/xyz");
1002 m_highlighterMock->endNoTestCalls();
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);
1016 addCharactersToEnd(m_text.document()->firstBlock().next(), "#");
1019 void tst_HighlighterEngine::testDynamicContexts()
1024 void tst_HighlighterEngine::testDynamicContexts_data()
1029 QList<HighlightSequence> sequences;
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());
1041 text = "a ---abcddeeff a ";
1042 QTest::newRow("case 0") << states << sequences << text;
1046 text = "a ---abcddeeff a beginddeeffend";
1047 QTest::newRow("case 1") << states << sequences << text;
1050 void tst_HighlighterEngine::testFirstNonSpace()
1055 void tst_HighlighterEngine::testFirstNonSpace_data()
1060 QList<HighlightSequence> sequences;
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);
1073 QTest::newRow("case 0") << states << sequences << text;
1078 QTest::newRow("case 1") << states << sequences << text;
1083 QTest::newRow("case 2") << states << sequences << text;
1088 QTest::newRow("case 3") << states << sequences << text;
1091 QTEST_MAIN(tst_HighlighterEngine)
1092 #include "tst_highlighterengine.moc"