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