1 /****************************************************************************
2 **
3 ** Copyright (C) 2019 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of the tools applications of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see https://www.qt.io/terms-conditions. For further
15 ** information use the contact form at https://www.qt.io/contact-us.
16 **
17 ** GNU General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU
19 ** General Public License version 3 as published by the Free Software
20 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21 ** included in the packaging of this file. Please review the following
22 ** information to ensure the GNU General Public License requirements will
23 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24 **
25 ** $QT_END_LICENSE$
26 **
27 ****************************************************************************/
28 
29 #include "qmlmarkupvisitor.h"
30 
31 #include <QtCore/qglobal.h>
32 #include <QtCore/qstringlist.h>
33 
34 #ifndef QT_NO_DECLARATIVE
35 #    include <private/qqmljsast_p.h>
36 #    include <private/qqmljsastfwd_p.h>
37 #    include <private/qqmljsengine_p.h>
38 #endif
39 
40 QT_BEGIN_NAMESPACE
41 
42 #ifndef QT_NO_DECLARATIVE
QmlMarkupVisitor(const QString & source,const QVector<QQmlJS::SourceLocation> & pragmas,QQmlJS::Engine * engine)43 QmlMarkupVisitor::QmlMarkupVisitor(const QString &source,
44                                    const QVector<QQmlJS::SourceLocation> &pragmas,
45                                    QQmlJS::Engine *engine)
46 {
47     this->source = source;
48     this->engine = engine;
49 
50     cursor = 0;
51     extraIndex = 0;
52 
53     // Merge the lists of locations of pragmas and comments in the source code.
54     int i = 0;
55     int j = 0;
56     const QList<QQmlJS::SourceLocation> comments = engine->comments();
57     while (i < comments.size() && j < pragmas.length()) {
58         if (comments[i].offset < pragmas[j].offset) {
59             extraTypes.append(Comment);
60             extraLocations.append(comments[i]);
61             ++i;
62         } else {
63             extraTypes.append(Pragma);
64             extraLocations.append(comments[j]);
65             ++j;
66         }
67     }
68 
69     while (i < comments.size()) {
70         extraTypes.append(Comment);
71         extraLocations.append(comments[i]);
72         ++i;
73     }
74 
75     while (j < pragmas.length()) {
76         extraTypes.append(Pragma);
77         extraLocations.append(pragmas[j]);
78         ++j;
79     }
80 }
81 
~QmlMarkupVisitor()82 QmlMarkupVisitor::~QmlMarkupVisitor() {}
83 
84 // The protect() function is a copy of the one from CppCodeMarker.
85 
86 static const QString samp = QLatin1String("&amp;");
87 static const QString slt = QLatin1String("&lt;");
88 static const QString sgt = QLatin1String("&gt;");
89 static const QString squot = QLatin1String("&quot;");
90 
protect(const QString & str)91 QString QmlMarkupVisitor::protect(const QString &str)
92 {
93     int n = str.length();
94     QString marked;
95     marked.reserve(n * 2 + 30);
96     const QChar *data = str.constData();
97     for (int i = 0; i != n; ++i) {
98         switch (data[i].unicode()) {
99         case '&':
100             marked += samp;
101             break;
102         case '<':
103             marked += slt;
104             break;
105         case '>':
106             marked += sgt;
107             break;
108         case '"':
109             marked += squot;
110             break;
111         default:
112             marked += data[i];
113         }
114     }
115     return marked;
116 }
117 
markedUpCode()118 QString QmlMarkupVisitor::markedUpCode()
119 {
120     if (int(cursor) < source.length())
121         addExtra(cursor, source.length());
122 
123     return output;
124 }
125 
hasError() const126 bool QmlMarkupVisitor::hasError() const
127 {
128     return hasRecursionDepthError;
129 }
130 
addExtra(quint32 start,quint32 finish)131 void QmlMarkupVisitor::addExtra(quint32 start, quint32 finish)
132 {
133     if (extraIndex >= extraLocations.length()) {
134         QString extra = source.mid(start, finish - start);
135         if (extra.trimmed().isEmpty())
136             output += extra;
137         else
138             output += protect(extra); // text that should probably have been caught by the parser
139 
140         cursor = finish;
141         return;
142     }
143 
144     while (extraIndex < extraLocations.length()) {
145         if (extraTypes[extraIndex] == Comment) {
146             if (extraLocations[extraIndex].offset - 2 >= start)
147                 break;
148         } else {
149             if (extraLocations[extraIndex].offset >= start)
150                 break;
151         }
152         extraIndex++;
153     }
154 
155     quint32 i = start;
156     while (i < finish && extraIndex < extraLocations.length()) {
157         quint32 j = extraLocations[extraIndex].offset - 2;
158         if (i <= j && j < finish) {
159             if (i < j)
160                 output += protect(source.mid(i, j - i));
161 
162             quint32 l = extraLocations[extraIndex].length;
163             if (extraTypes[extraIndex] == Comment) {
164                 if (source.mid(j, 2) == QLatin1String("/*"))
165                     l += 4;
166                 else
167                     l += 2;
168                 output += QLatin1String("<@comment>");
169                 output += protect(source.mid(j, l));
170                 output += QLatin1String("</@comment>");
171             } else
172                 output += protect(source.mid(j, l));
173 
174             extraIndex++;
175             i = j + l;
176         } else
177             break;
178     }
179 
180     QString extra = source.mid(i, finish - i);
181     if (extra.trimmed().isEmpty())
182         output += extra;
183     else
184         output += protect(extra); // text that should probably have been caught by the parser
185 
186     cursor = finish;
187 }
188 
addMarkedUpToken(QQmlJS::SourceLocation & location,const QString & tagName,const QHash<QString,QString> & attributes)189 void QmlMarkupVisitor::addMarkedUpToken(QQmlJS::SourceLocation &location,
190                                         const QString &tagName,
191                                         const QHash<QString, QString> &attributes)
192 {
193     if (!location.isValid())
194         return;
195 
196     if (cursor < location.offset)
197         addExtra(cursor, location.offset);
198     else if (cursor > location.offset)
199         return;
200 
201     output += QString(QLatin1String("<@%1")).arg(tagName);
202     for (const auto &key : attributes)
203         output += QString(QLatin1String(" %1=\"%2\"")).arg(key).arg(attributes[key]);
204     output += QString(QLatin1String(">%2</@%3>")).arg(protect(sourceText(location)), tagName);
205     cursor += location.length;
206 }
207 
sourceText(QQmlJS::SourceLocation & location)208 QString QmlMarkupVisitor::sourceText(QQmlJS::SourceLocation &location)
209 {
210     return source.mid(location.offset, location.length);
211 }
212 
addVerbatim(QQmlJS::SourceLocation first,QQmlJS::SourceLocation last)213 void QmlMarkupVisitor::addVerbatim(QQmlJS::SourceLocation first,
214                                    QQmlJS::SourceLocation last)
215 {
216     if (!first.isValid())
217         return;
218 
219     quint32 start = first.begin();
220     quint32 finish;
221     if (last.isValid())
222         finish = last.end();
223     else
224         finish = first.end();
225 
226     if (cursor < start)
227         addExtra(cursor, start);
228     else if (cursor > start)
229         return;
230 
231     QString text = source.mid(start, finish - start);
232     output += protect(text);
233     cursor = finish;
234 }
235 
visit(QQmlJS::AST::UiImport * uiimport)236 bool QmlMarkupVisitor::visit(QQmlJS::AST::UiImport *uiimport)
237 {
238     addVerbatim(uiimport->importToken);
239     if (!uiimport->importUri)
240         addMarkedUpToken(uiimport->fileNameToken, QLatin1String("headerfile"));
241     return false;
242 }
243 
endVisit(QQmlJS::AST::UiImport * uiimport)244 void QmlMarkupVisitor::endVisit(QQmlJS::AST::UiImport *uiimport)
245 {
246     if (uiimport->version)
247         addVerbatim(uiimport->version->firstSourceLocation(),
248                     uiimport->version->lastSourceLocation());
249     addVerbatim(uiimport->asToken);
250     addMarkedUpToken(uiimport->importIdToken, QLatin1String("headerfile"));
251     addVerbatim(uiimport->semicolonToken);
252 }
253 
visit(QQmlJS::AST::UiPublicMember * member)254 bool QmlMarkupVisitor::visit(QQmlJS::AST::UiPublicMember *member)
255 {
256     if (member->type == QQmlJS::AST::UiPublicMember::Property) {
257         addVerbatim(member->defaultToken);
258         addVerbatim(member->readonlyToken);
259         addVerbatim(member->propertyToken);
260         addVerbatim(member->typeModifierToken);
261         addMarkedUpToken(member->typeToken, QLatin1String("type"));
262         addMarkedUpToken(member->identifierToken, QLatin1String("name"));
263         addVerbatim(member->colonToken);
264         if (member->binding)
265             QQmlJS::AST::Node::accept(member->binding, this);
266         else if (member->statement)
267             QQmlJS::AST::Node::accept(member->statement, this);
268     } else {
269         addVerbatim(member->propertyToken);
270         addVerbatim(member->typeModifierToken);
271         addMarkedUpToken(member->typeToken, QLatin1String("type"));
272         // addVerbatim(member->identifierToken);
273         QQmlJS::AST::Node::accept(member->parameters, this);
274     }
275     addVerbatim(member->semicolonToken);
276     return false;
277 }
278 
visit(QQmlJS::AST::UiObjectInitializer * initializer)279 bool QmlMarkupVisitor::visit(QQmlJS::AST::UiObjectInitializer *initializer)
280 {
281     addVerbatim(initializer->lbraceToken, initializer->lbraceToken);
282     return true;
283 }
284 
endVisit(QQmlJS::AST::UiObjectInitializer * initializer)285 void QmlMarkupVisitor::endVisit(QQmlJS::AST::UiObjectInitializer *initializer)
286 {
287     addVerbatim(initializer->rbraceToken, initializer->rbraceToken);
288 }
289 
visit(QQmlJS::AST::UiObjectBinding * binding)290 bool QmlMarkupVisitor::visit(QQmlJS::AST::UiObjectBinding *binding)
291 {
292     QQmlJS::AST::Node::accept(binding->qualifiedId, this);
293     addVerbatim(binding->colonToken);
294     QQmlJS::AST::Node::accept(binding->qualifiedTypeNameId, this);
295     QQmlJS::AST::Node::accept(binding->initializer, this);
296     return false;
297 }
298 
visit(QQmlJS::AST::UiScriptBinding * binding)299 bool QmlMarkupVisitor::visit(QQmlJS::AST::UiScriptBinding *binding)
300 {
301     QQmlJS::AST::Node::accept(binding->qualifiedId, this);
302     addVerbatim(binding->colonToken);
303     QQmlJS::AST::Node::accept(binding->statement, this);
304     return false;
305 }
306 
visit(QQmlJS::AST::UiArrayBinding * binding)307 bool QmlMarkupVisitor::visit(QQmlJS::AST::UiArrayBinding *binding)
308 {
309     QQmlJS::AST::Node::accept(binding->qualifiedId, this);
310     addVerbatim(binding->colonToken);
311     addVerbatim(binding->lbracketToken);
312     QQmlJS::AST::Node::accept(binding->members, this);
313     addVerbatim(binding->rbracketToken);
314     return false;
315 }
316 
visit(QQmlJS::AST::UiArrayMemberList * list)317 bool QmlMarkupVisitor::visit(QQmlJS::AST::UiArrayMemberList *list)
318 {
319     for (QQmlJS::AST::UiArrayMemberList *it = list; it; it = it->next) {
320         QQmlJS::AST::Node::accept(it->member, this);
321         // addVerbatim(it->commaToken);
322     }
323     return false;
324 }
325 
visit(QQmlJS::AST::UiQualifiedId * id)326 bool QmlMarkupVisitor::visit(QQmlJS::AST::UiQualifiedId *id)
327 {
328     addMarkedUpToken(id->identifierToken, QLatin1String("name"));
329     return false;
330 }
331 
visit(QQmlJS::AST::ThisExpression * expression)332 bool QmlMarkupVisitor::visit(QQmlJS::AST::ThisExpression *expression)
333 {
334     addVerbatim(expression->thisToken);
335     return true;
336 }
337 
visit(QQmlJS::AST::IdentifierExpression * identifier)338 bool QmlMarkupVisitor::visit(QQmlJS::AST::IdentifierExpression *identifier)
339 {
340     addMarkedUpToken(identifier->identifierToken, QLatin1String("name"));
341     return false;
342 }
343 
visit(QQmlJS::AST::NullExpression * null)344 bool QmlMarkupVisitor::visit(QQmlJS::AST::NullExpression *null)
345 {
346     addMarkedUpToken(null->nullToken, QLatin1String("number"));
347     return true;
348 }
349 
visit(QQmlJS::AST::TrueLiteral * literal)350 bool QmlMarkupVisitor::visit(QQmlJS::AST::TrueLiteral *literal)
351 {
352     addMarkedUpToken(literal->trueToken, QLatin1String("number"));
353     return true;
354 }
355 
visit(QQmlJS::AST::FalseLiteral * literal)356 bool QmlMarkupVisitor::visit(QQmlJS::AST::FalseLiteral *literal)
357 {
358     addMarkedUpToken(literal->falseToken, QLatin1String("number"));
359     return true;
360 }
361 
visit(QQmlJS::AST::NumericLiteral * literal)362 bool QmlMarkupVisitor::visit(QQmlJS::AST::NumericLiteral *literal)
363 {
364     addMarkedUpToken(literal->literalToken, QLatin1String("number"));
365     return false;
366 }
367 
visit(QQmlJS::AST::StringLiteral * literal)368 bool QmlMarkupVisitor::visit(QQmlJS::AST::StringLiteral *literal)
369 {
370     addMarkedUpToken(literal->literalToken, QLatin1String("string"));
371     return true;
372 }
373 
visit(QQmlJS::AST::RegExpLiteral * literal)374 bool QmlMarkupVisitor::visit(QQmlJS::AST::RegExpLiteral *literal)
375 {
376     addVerbatim(literal->literalToken);
377     return true;
378 }
379 
visit(QQmlJS::AST::ArrayPattern * literal)380 bool QmlMarkupVisitor::visit(QQmlJS::AST::ArrayPattern *literal)
381 {
382     addVerbatim(literal->lbracketToken);
383     QQmlJS::AST::Node::accept(literal->elements, this);
384     addVerbatim(literal->rbracketToken);
385     return false;
386 }
387 
visit(QQmlJS::AST::ObjectPattern * literal)388 bool QmlMarkupVisitor::visit(QQmlJS::AST::ObjectPattern *literal)
389 {
390     addVerbatim(literal->lbraceToken);
391     return true;
392 }
393 
endVisit(QQmlJS::AST::ObjectPattern * literal)394 void QmlMarkupVisitor::endVisit(QQmlJS::AST::ObjectPattern *literal)
395 {
396     addVerbatim(literal->rbraceToken);
397 }
398 
visit(QQmlJS::AST::PatternElementList * list)399 bool QmlMarkupVisitor::visit(QQmlJS::AST::PatternElementList *list)
400 {
401     for (QQmlJS::AST::PatternElementList *it = list; it; it = it->next) {
402         QQmlJS::AST::Node::accept(it->element, this);
403         // addVerbatim(it->commaToken);
404     }
405     QQmlJS::AST::Node::accept(list->elision, this);
406     return false;
407 }
408 
visit(QQmlJS::AST::Elision * elision)409 bool QmlMarkupVisitor::visit(QQmlJS::AST::Elision *elision)
410 {
411     addVerbatim(elision->commaToken, elision->commaToken);
412     return true;
413 }
414 
visit(QQmlJS::AST::PatternProperty * list)415 bool QmlMarkupVisitor::visit(QQmlJS::AST::PatternProperty *list)
416 {
417     QQmlJS::AST::Node::accept(list->name, this);
418     addVerbatim(list->colonToken, list->colonToken);
419     QQmlJS::AST::Node::accept(list->initializer, this);
420     // addVerbatim(list->commaToken, list->commaToken);
421     return false;
422 }
423 
visit(QQmlJS::AST::ArrayMemberExpression * expression)424 bool QmlMarkupVisitor::visit(QQmlJS::AST::ArrayMemberExpression *expression)
425 {
426     QQmlJS::AST::Node::accept(expression->base, this);
427     addVerbatim(expression->lbracketToken);
428     QQmlJS::AST::Node::accept(expression->expression, this);
429     addVerbatim(expression->rbracketToken);
430     return false;
431 }
432 
visit(QQmlJS::AST::FieldMemberExpression * expression)433 bool QmlMarkupVisitor::visit(QQmlJS::AST::FieldMemberExpression *expression)
434 {
435     QQmlJS::AST::Node::accept(expression->base, this);
436     addVerbatim(expression->dotToken);
437     addMarkedUpToken(expression->identifierToken, QLatin1String("name"));
438     return false;
439 }
440 
visit(QQmlJS::AST::NewMemberExpression * expression)441 bool QmlMarkupVisitor::visit(QQmlJS::AST::NewMemberExpression *expression)
442 {
443     addVerbatim(expression->newToken);
444     QQmlJS::AST::Node::accept(expression->base, this);
445     addVerbatim(expression->lparenToken);
446     QQmlJS::AST::Node::accept(expression->arguments, this);
447     addVerbatim(expression->rparenToken);
448     return false;
449 }
450 
visit(QQmlJS::AST::NewExpression * expression)451 bool QmlMarkupVisitor::visit(QQmlJS::AST::NewExpression *expression)
452 {
453     addVerbatim(expression->newToken);
454     return true;
455 }
456 
visit(QQmlJS::AST::ArgumentList * list)457 bool QmlMarkupVisitor::visit(QQmlJS::AST::ArgumentList *list)
458 {
459     addVerbatim(list->commaToken, list->commaToken);
460     return true;
461 }
462 
visit(QQmlJS::AST::PostIncrementExpression * expression)463 bool QmlMarkupVisitor::visit(QQmlJS::AST::PostIncrementExpression *expression)
464 {
465     addVerbatim(expression->incrementToken);
466     return true;
467 }
468 
visit(QQmlJS::AST::PostDecrementExpression * expression)469 bool QmlMarkupVisitor::visit(QQmlJS::AST::PostDecrementExpression *expression)
470 {
471     addVerbatim(expression->decrementToken);
472     return true;
473 }
474 
visit(QQmlJS::AST::DeleteExpression * expression)475 bool QmlMarkupVisitor::visit(QQmlJS::AST::DeleteExpression *expression)
476 {
477     addVerbatim(expression->deleteToken);
478     return true;
479 }
480 
visit(QQmlJS::AST::VoidExpression * expression)481 bool QmlMarkupVisitor::visit(QQmlJS::AST::VoidExpression *expression)
482 {
483     addVerbatim(expression->voidToken);
484     return true;
485 }
486 
visit(QQmlJS::AST::TypeOfExpression * expression)487 bool QmlMarkupVisitor::visit(QQmlJS::AST::TypeOfExpression *expression)
488 {
489     addVerbatim(expression->typeofToken);
490     return true;
491 }
492 
visit(QQmlJS::AST::PreIncrementExpression * expression)493 bool QmlMarkupVisitor::visit(QQmlJS::AST::PreIncrementExpression *expression)
494 {
495     addVerbatim(expression->incrementToken);
496     return true;
497 }
498 
visit(QQmlJS::AST::PreDecrementExpression * expression)499 bool QmlMarkupVisitor::visit(QQmlJS::AST::PreDecrementExpression *expression)
500 {
501     addVerbatim(expression->decrementToken);
502     return true;
503 }
504 
visit(QQmlJS::AST::UnaryPlusExpression * expression)505 bool QmlMarkupVisitor::visit(QQmlJS::AST::UnaryPlusExpression *expression)
506 {
507     addVerbatim(expression->plusToken);
508     return true;
509 }
510 
visit(QQmlJS::AST::UnaryMinusExpression * expression)511 bool QmlMarkupVisitor::visit(QQmlJS::AST::UnaryMinusExpression *expression)
512 {
513     addVerbatim(expression->minusToken);
514     return true;
515 }
516 
visit(QQmlJS::AST::TildeExpression * expression)517 bool QmlMarkupVisitor::visit(QQmlJS::AST::TildeExpression *expression)
518 {
519     addVerbatim(expression->tildeToken);
520     return true;
521 }
522 
visit(QQmlJS::AST::NotExpression * expression)523 bool QmlMarkupVisitor::visit(QQmlJS::AST::NotExpression *expression)
524 {
525     addVerbatim(expression->notToken);
526     return true;
527 }
528 
visit(QQmlJS::AST::BinaryExpression * expression)529 bool QmlMarkupVisitor::visit(QQmlJS::AST::BinaryExpression *expression)
530 {
531     QQmlJS::AST::Node::accept(expression->left, this);
532     addMarkedUpToken(expression->operatorToken, QLatin1String("op"));
533     QQmlJS::AST::Node::accept(expression->right, this);
534     return false;
535 }
536 
visit(QQmlJS::AST::ConditionalExpression * expression)537 bool QmlMarkupVisitor::visit(QQmlJS::AST::ConditionalExpression *expression)
538 {
539     QQmlJS::AST::Node::accept(expression->expression, this);
540     addVerbatim(expression->questionToken);
541     QQmlJS::AST::Node::accept(expression->ok, this);
542     addVerbatim(expression->colonToken);
543     QQmlJS::AST::Node::accept(expression->ko, this);
544     return false;
545 }
546 
visit(QQmlJS::AST::Expression * expression)547 bool QmlMarkupVisitor::visit(QQmlJS::AST::Expression *expression)
548 {
549     QQmlJS::AST::Node::accept(expression->left, this);
550     addVerbatim(expression->commaToken);
551     QQmlJS::AST::Node::accept(expression->right, this);
552     return false;
553 }
554 
visit(QQmlJS::AST::Block * block)555 bool QmlMarkupVisitor::visit(QQmlJS::AST::Block *block)
556 {
557     addVerbatim(block->lbraceToken);
558     return true;
559 }
560 
endVisit(QQmlJS::AST::Block * block)561 void QmlMarkupVisitor::endVisit(QQmlJS::AST::Block *block)
562 {
563     addVerbatim(block->rbraceToken);
564 }
565 
visit(QQmlJS::AST::VariableStatement * statement)566 bool QmlMarkupVisitor::visit(QQmlJS::AST::VariableStatement *statement)
567 {
568     addVerbatim(statement->declarationKindToken);
569     QQmlJS::AST::Node::accept(statement->declarations, this);
570     // addVerbatim(statement->semicolonToken);
571     return false;
572 }
573 
visit(QQmlJS::AST::VariableDeclarationList * list)574 bool QmlMarkupVisitor::visit(QQmlJS::AST::VariableDeclarationList *list)
575 {
576     for (QQmlJS::AST::VariableDeclarationList *it = list; it; it = it->next) {
577         QQmlJS::AST::Node::accept(it->declaration, this);
578         addVerbatim(it->commaToken);
579     }
580     return false;
581 }
582 
visit(QQmlJS::AST::EmptyStatement * statement)583 bool QmlMarkupVisitor::visit(QQmlJS::AST::EmptyStatement *statement)
584 {
585     addVerbatim(statement->semicolonToken);
586     return true;
587 }
588 
visit(QQmlJS::AST::ExpressionStatement * statement)589 bool QmlMarkupVisitor::visit(QQmlJS::AST::ExpressionStatement *statement)
590 {
591     QQmlJS::AST::Node::accept(statement->expression, this);
592     addVerbatim(statement->semicolonToken);
593     return false;
594 }
595 
visit(QQmlJS::AST::IfStatement * statement)596 bool QmlMarkupVisitor::visit(QQmlJS::AST::IfStatement *statement)
597 {
598     addMarkedUpToken(statement->ifToken, QLatin1String("keyword"));
599     addVerbatim(statement->lparenToken);
600     QQmlJS::AST::Node::accept(statement->expression, this);
601     addVerbatim(statement->rparenToken);
602     QQmlJS::AST::Node::accept(statement->ok, this);
603     if (statement->ko) {
604         addMarkedUpToken(statement->elseToken, QLatin1String("keyword"));
605         QQmlJS::AST::Node::accept(statement->ko, this);
606     }
607     return false;
608 }
609 
visit(QQmlJS::AST::DoWhileStatement * statement)610 bool QmlMarkupVisitor::visit(QQmlJS::AST::DoWhileStatement *statement)
611 {
612     addMarkedUpToken(statement->doToken, QLatin1String("keyword"));
613     QQmlJS::AST::Node::accept(statement->statement, this);
614     addMarkedUpToken(statement->whileToken, QLatin1String("keyword"));
615     addVerbatim(statement->lparenToken);
616     QQmlJS::AST::Node::accept(statement->expression, this);
617     addVerbatim(statement->rparenToken);
618     addVerbatim(statement->semicolonToken);
619     return false;
620 }
621 
visit(QQmlJS::AST::WhileStatement * statement)622 bool QmlMarkupVisitor::visit(QQmlJS::AST::WhileStatement *statement)
623 {
624     addMarkedUpToken(statement->whileToken, QLatin1String("keyword"));
625     addVerbatim(statement->lparenToken);
626     QQmlJS::AST::Node::accept(statement->expression, this);
627     addVerbatim(statement->rparenToken);
628     QQmlJS::AST::Node::accept(statement->statement, this);
629     return false;
630 }
631 
visit(QQmlJS::AST::ForStatement * statement)632 bool QmlMarkupVisitor::visit(QQmlJS::AST::ForStatement *statement)
633 {
634     addMarkedUpToken(statement->forToken, QLatin1String("keyword"));
635     addVerbatim(statement->lparenToken);
636     QQmlJS::AST::Node::accept(statement->initialiser, this);
637     addVerbatim(statement->firstSemicolonToken);
638     QQmlJS::AST::Node::accept(statement->condition, this);
639     addVerbatim(statement->secondSemicolonToken);
640     QQmlJS::AST::Node::accept(statement->expression, this);
641     addVerbatim(statement->rparenToken);
642     QQmlJS::AST::Node::accept(statement->statement, this);
643     return false;
644 }
645 
visit(QQmlJS::AST::ForEachStatement * statement)646 bool QmlMarkupVisitor::visit(QQmlJS::AST::ForEachStatement *statement)
647 {
648     addMarkedUpToken(statement->forToken, QLatin1String("keyword"));
649     addVerbatim(statement->lparenToken);
650     QQmlJS::AST::Node::accept(statement->lhs, this);
651     addVerbatim(statement->inOfToken);
652     QQmlJS::AST::Node::accept(statement->expression, this);
653     addVerbatim(statement->rparenToken);
654     QQmlJS::AST::Node::accept(statement->statement, this);
655     return false;
656 }
657 
visit(QQmlJS::AST::ContinueStatement * statement)658 bool QmlMarkupVisitor::visit(QQmlJS::AST::ContinueStatement *statement)
659 {
660     addMarkedUpToken(statement->continueToken, QLatin1String("keyword"));
661     addMarkedUpToken(statement->identifierToken, QLatin1String("name"));
662     addVerbatim(statement->semicolonToken);
663     return false;
664 }
665 
visit(QQmlJS::AST::BreakStatement * statement)666 bool QmlMarkupVisitor::visit(QQmlJS::AST::BreakStatement *statement)
667 {
668     addMarkedUpToken(statement->breakToken, QLatin1String("keyword"));
669     addMarkedUpToken(statement->identifierToken, QLatin1String("name"));
670     addVerbatim(statement->semicolonToken);
671     return false;
672 }
673 
visit(QQmlJS::AST::ReturnStatement * statement)674 bool QmlMarkupVisitor::visit(QQmlJS::AST::ReturnStatement *statement)
675 {
676     addMarkedUpToken(statement->returnToken, QLatin1String("keyword"));
677     QQmlJS::AST::Node::accept(statement->expression, this);
678     addVerbatim(statement->semicolonToken);
679     return false;
680 }
681 
visit(QQmlJS::AST::WithStatement * statement)682 bool QmlMarkupVisitor::visit(QQmlJS::AST::WithStatement *statement)
683 {
684     addMarkedUpToken(statement->withToken, QLatin1String("keyword"));
685     addVerbatim(statement->lparenToken);
686     QQmlJS::AST::Node::accept(statement->expression, this);
687     addVerbatim(statement->rparenToken);
688     QQmlJS::AST::Node::accept(statement->statement, this);
689     return false;
690 }
691 
visit(QQmlJS::AST::CaseBlock * block)692 bool QmlMarkupVisitor::visit(QQmlJS::AST::CaseBlock *block)
693 {
694     addVerbatim(block->lbraceToken);
695     return true;
696 }
697 
endVisit(QQmlJS::AST::CaseBlock * block)698 void QmlMarkupVisitor::endVisit(QQmlJS::AST::CaseBlock *block)
699 {
700     addVerbatim(block->rbraceToken, block->rbraceToken);
701 }
702 
visit(QQmlJS::AST::SwitchStatement * statement)703 bool QmlMarkupVisitor::visit(QQmlJS::AST::SwitchStatement *statement)
704 {
705     addMarkedUpToken(statement->switchToken, QLatin1String("keyword"));
706     addVerbatim(statement->lparenToken);
707     QQmlJS::AST::Node::accept(statement->expression, this);
708     addVerbatim(statement->rparenToken);
709     QQmlJS::AST::Node::accept(statement->block, this);
710     return false;
711 }
712 
visit(QQmlJS::AST::CaseClause * clause)713 bool QmlMarkupVisitor::visit(QQmlJS::AST::CaseClause *clause)
714 {
715     addMarkedUpToken(clause->caseToken, QLatin1String("keyword"));
716     QQmlJS::AST::Node::accept(clause->expression, this);
717     addVerbatim(clause->colonToken);
718     QQmlJS::AST::Node::accept(clause->statements, this);
719     return false;
720 }
721 
visit(QQmlJS::AST::DefaultClause * clause)722 bool QmlMarkupVisitor::visit(QQmlJS::AST::DefaultClause *clause)
723 {
724     addMarkedUpToken(clause->defaultToken, QLatin1String("keyword"));
725     addVerbatim(clause->colonToken, clause->colonToken);
726     return true;
727 }
728 
visit(QQmlJS::AST::LabelledStatement * statement)729 bool QmlMarkupVisitor::visit(QQmlJS::AST::LabelledStatement *statement)
730 {
731     addMarkedUpToken(statement->identifierToken, QLatin1String("name"));
732     addVerbatim(statement->colonToken);
733     QQmlJS::AST::Node::accept(statement->statement, this);
734     return false;
735 }
736 
visit(QQmlJS::AST::ThrowStatement * statement)737 bool QmlMarkupVisitor::visit(QQmlJS::AST::ThrowStatement *statement)
738 {
739     addMarkedUpToken(statement->throwToken, QLatin1String("keyword"));
740     QQmlJS::AST::Node::accept(statement->expression, this);
741     addVerbatim(statement->semicolonToken);
742     return false;
743 }
744 
visit(QQmlJS::AST::Catch * c)745 bool QmlMarkupVisitor::visit(QQmlJS::AST::Catch *c)
746 {
747     addMarkedUpToken(c->catchToken, QLatin1String("keyword"));
748     addVerbatim(c->lparenToken);
749     addMarkedUpToken(c->identifierToken, QLatin1String("name"));
750     addVerbatim(c->rparenToken);
751     return false;
752 }
753 
visit(QQmlJS::AST::Finally * f)754 bool QmlMarkupVisitor::visit(QQmlJS::AST::Finally *f)
755 {
756     addMarkedUpToken(f->finallyToken, QLatin1String("keyword"));
757     QQmlJS::AST::Node::accept(f->statement, this);
758     return false;
759 }
760 
visit(QQmlJS::AST::TryStatement * statement)761 bool QmlMarkupVisitor::visit(QQmlJS::AST::TryStatement *statement)
762 {
763     addMarkedUpToken(statement->tryToken, QLatin1String("keyword"));
764     QQmlJS::AST::Node::accept(statement->statement, this);
765     QQmlJS::AST::Node::accept(statement->catchExpression, this);
766     QQmlJS::AST::Node::accept(statement->finallyExpression, this);
767     return false;
768 }
769 
visit(QQmlJS::AST::FunctionExpression * expression)770 bool QmlMarkupVisitor::visit(QQmlJS::AST::FunctionExpression *expression)
771 {
772     addMarkedUpToken(expression->functionToken, QLatin1String("keyword"));
773     addMarkedUpToken(expression->identifierToken, QLatin1String("name"));
774     addVerbatim(expression->lparenToken);
775     QQmlJS::AST::Node::accept(expression->formals, this);
776     addVerbatim(expression->rparenToken);
777     addVerbatim(expression->lbraceToken);
778     QQmlJS::AST::Node::accept(expression->body, this);
779     addVerbatim(expression->rbraceToken);
780     return false;
781 }
782 
visit(QQmlJS::AST::FunctionDeclaration * declaration)783 bool QmlMarkupVisitor::visit(QQmlJS::AST::FunctionDeclaration *declaration)
784 {
785     addMarkedUpToken(declaration->functionToken, QLatin1String("keyword"));
786     addMarkedUpToken(declaration->identifierToken, QLatin1String("name"));
787     addVerbatim(declaration->lparenToken);
788     QQmlJS::AST::Node::accept(declaration->formals, this);
789     addVerbatim(declaration->rparenToken);
790     addVerbatim(declaration->lbraceToken);
791     QQmlJS::AST::Node::accept(declaration->body, this);
792     addVerbatim(declaration->rbraceToken);
793     return false;
794 }
795 
visit(QQmlJS::AST::FormalParameterList * list)796 bool QmlMarkupVisitor::visit(QQmlJS::AST::FormalParameterList *list)
797 {
798     //    addVerbatim(list->commaToken);
799     QQmlJS::AST::Node::accept(list->element, this);
800     // addMarkedUpToken(list->identifierToken, QLatin1String("name"));
801     return false;
802 }
803 
visit(QQmlJS::AST::DebuggerStatement * statement)804 bool QmlMarkupVisitor::visit(QQmlJS::AST::DebuggerStatement *statement)
805 {
806     addVerbatim(statement->debuggerToken);
807     addVerbatim(statement->semicolonToken);
808     return true;
809 }
810 
811 // Elements and items are represented by UiObjectDefinition nodes.
812 
visit(QQmlJS::AST::UiObjectDefinition * definition)813 bool QmlMarkupVisitor::visit(QQmlJS::AST::UiObjectDefinition *definition)
814 {
815     QHash<QString, QString> attributes;
816     addMarkedUpToken(definition->qualifiedTypeNameId->identifierToken, QLatin1String("type"));
817     QQmlJS::AST::Node::accept(definition->initializer, this);
818     return false;
819 }
820 
throwRecursionDepthError()821 void QmlMarkupVisitor::throwRecursionDepthError()
822 {
823     hasRecursionDepthError = true;
824 }
825 
826 #endif
827 
828 QT_END_NAMESPACE
829