Remove "All rights reserved" line from license headers.
[profile/ivi/qtdeclarative.git] / src / declarative / qml / qdeclarativerewrite.cpp
1 /****************************************************************************
2 **
3 ** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
4 ** Contact: http://www.qt-project.org/
5 **
6 ** This file is part of the QtDeclarative module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** GNU Lesser General Public License Usage
10 ** This file may be used under the terms of the GNU Lesser General Public
11 ** License version 2.1 as published by the Free Software Foundation and
12 ** appearing in the file LICENSE.LGPL included in the packaging of this
13 ** file. Please review the following information to ensure the GNU Lesser
14 ** General Public License version 2.1 requirements will be met:
15 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
16 **
17 ** In addition, as a special exception, Nokia gives you certain additional
18 ** rights. These rights are described in the Nokia Qt LGPL Exception
19 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
20 **
21 ** GNU General Public License Usage
22 ** Alternatively, this file may be used under the terms of the GNU General
23 ** Public License version 3.0 as published by the Free Software Foundation
24 ** and appearing in the file LICENSE.GPL included in the packaging of this
25 ** file. Please review the following information to ensure the GNU General
26 ** Public License version 3.0 requirements will be met:
27 ** http://www.gnu.org/copyleft/gpl.html.
28 **
29 ** Other Usage
30 ** Alternatively, this file may be used in accordance with the terms and
31 ** conditions contained in a signed written agreement between you and Nokia.
32 **
33 **
34 **
35 **
36 **
37 **
38 ** $QT_END_LICENSE$
39 **
40 ****************************************************************************/
41
42 #include "qdeclarativerewrite_p.h"
43
44 #include "qdeclarativeglobal_p.h"
45
46 #include <QtCore/qdebug.h>
47
48 QT_BEGIN_NAMESPACE
49
50 DEFINE_BOOL_CONFIG_OPTION(rewriteDump, QML_REWRITE_DUMP);
51
52 namespace QDeclarativeRewrite {
53
54 bool SharedBindingTester::isSharable(const QString &code)
55 {
56     Engine engine;
57     Lexer lexer(&engine);
58     Parser parser(&engine);
59     lexer.setCode(code, 0);
60     parser.parseStatement();
61     if (!parser.statement()) 
62         return false;
63
64     return isSharable(parser.statement());
65 }
66
67 bool SharedBindingTester::isSharable(AST::Node *node)
68 {
69     _sharable = true;
70     AST::Node::acceptChild(node, this);
71     return _sharable;
72 }
73
74 QString RewriteBinding::operator()(const QString &code, bool *ok, bool *sharable)
75 {
76     Engine engine;
77     Lexer lexer(&engine);
78     Parser parser(&engine);
79     lexer.setCode(code, 0);
80     parser.parseStatement();
81     if (!parser.statement()) {
82         if (ok) *ok = false;
83         return QString();
84     } else {
85         if (ok) *ok = true;
86         if (sharable) {
87             SharedBindingTester tester;
88             *sharable = tester.isSharable(parser.statement());
89         }
90     }
91     return rewrite(code, 0, parser.statement());
92 }
93
94 QString RewriteBinding::operator()(QDeclarativeJS::AST::Node *node, const QString &code, bool *sharable)
95 {
96     if (!node)
97         return code;
98
99     if (sharable) {
100         SharedBindingTester tester;
101         *sharable = tester.isSharable(node);
102     }
103
104     QDeclarativeJS::AST::ExpressionNode *expression = node->expressionCast();
105     QDeclarativeJS::AST::Statement *statement = node->statementCast();
106     if(!expression && !statement)
107         return code;
108
109     TextWriter w;
110     _writer = &w;
111     _position = expression ? expression->firstSourceLocation().begin() : statement->firstSourceLocation().begin();
112     _inLoop = 0;
113
114     accept(node);
115
116     unsigned startOfStatement = 0;
117     unsigned endOfStatement = (expression ? expression->lastSourceLocation().end() : statement->lastSourceLocation().end()) - _position;
118
119     QString startString = QLatin1String("(function ") + _name + QLatin1String("() { ");
120     if (expression)
121         startString += QLatin1String("return ");
122     _writer->replace(startOfStatement, 0, startString);
123     _writer->replace(endOfStatement, 0, QLatin1String(" })"));
124
125     if (rewriteDump()) {
126         qWarning() << "=============================================================";
127         qWarning() << "Rewrote:";
128         qWarning() << qPrintable(code);
129     }
130
131     QString codeCopy = code;
132     w.write(&codeCopy);
133
134     if (rewriteDump()) {
135         qWarning() << "To:";
136         qWarning() << qPrintable(codeCopy);
137         qWarning() << "=============================================================";
138     }
139
140     return codeCopy;
141 }
142
143 void RewriteBinding::accept(AST::Node *node)
144 {
145     AST::Node::acceptChild(node, this);
146 }
147
148 QString RewriteBinding::rewrite(QString code, unsigned position,
149                                 AST::Statement *node)
150 {
151     TextWriter w;
152     _writer = &w;
153     _position = position;
154     _inLoop = 0;
155
156     accept(node);
157
158     unsigned startOfStatement = node->firstSourceLocation().begin() - _position;
159     unsigned endOfStatement = node->lastSourceLocation().end() - _position;
160
161     _writer->replace(startOfStatement, 0, QLatin1String("(function ") + _name + QLatin1String("() { "));
162     _writer->replace(endOfStatement, 0, QLatin1String(" })"));
163
164     if (rewriteDump()) {
165         qWarning() << "=============================================================";
166         qWarning() << "Rewrote:";
167         qWarning() << qPrintable(code);
168     }
169
170     w.write(&code);
171
172     if (rewriteDump()) {
173         qWarning() << "To:";
174         qWarning() << qPrintable(code);
175         qWarning() << "=============================================================";
176     }
177
178     return code;
179 }
180
181 bool RewriteBinding::visit(AST::Block *ast)
182 {
183     for (AST::StatementList *it = ast->statements; it; it = it->next) {
184         if (! it->next) {
185             // we need to rewrite only the last statement of a block.
186             accept(it->statement);
187         }
188     }
189
190     return false;
191 }
192
193 bool RewriteBinding::visit(AST::ExpressionStatement *ast)
194 {
195     if (! _inLoop) {
196         unsigned startOfExpressionStatement = ast->firstSourceLocation().begin() - _position;
197         _writer->replace(startOfExpressionStatement, 0, QLatin1String("return "));
198     }
199
200     return false;
201 }
202
203 bool RewriteBinding::visit(AST::DoWhileStatement *)
204 {
205     ++_inLoop;
206     return true;
207 }
208
209 void RewriteBinding::endVisit(AST::DoWhileStatement *)
210 {
211     --_inLoop;
212 }
213
214 bool RewriteBinding::visit(AST::WhileStatement *)
215 {
216     ++_inLoop;
217     return true;
218 }
219
220 void RewriteBinding::endVisit(AST::WhileStatement *)
221 {
222     --_inLoop;
223 }
224
225 bool RewriteBinding::visit(AST::ForStatement *)
226 {
227     ++_inLoop;
228     return true;
229 }
230
231 void RewriteBinding::endVisit(AST::ForStatement *)
232 {
233     --_inLoop;
234 }
235
236 bool RewriteBinding::visit(AST::LocalForStatement *)
237 {
238     ++_inLoop;
239     return true;
240 }
241
242 void RewriteBinding::endVisit(AST::LocalForStatement *)
243 {
244     --_inLoop;
245 }
246
247 bool RewriteBinding::visit(AST::ForEachStatement *)
248 {
249     ++_inLoop;
250     return true;
251 }
252
253 void RewriteBinding::endVisit(AST::ForEachStatement *)
254 {
255     --_inLoop;
256 }
257
258 bool RewriteBinding::visit(AST::LocalForEachStatement *)
259 {
260     ++_inLoop;
261     return true;
262 }
263
264 void RewriteBinding::endVisit(AST::LocalForEachStatement *)
265 {
266     --_inLoop;
267 }
268
269 bool RewriteBinding::visit(AST::CaseBlock *ast)
270 {
271     // Process the initial sequence of the case clauses.
272     for (AST::CaseClauses *it = ast->clauses; it; it = it->next) {
273         // Return the value of the last statement in the block, if this is the last `case clause'
274         // of the switch statement.
275         bool returnTheValueOfLastStatement = (it->next == 0) && (ast->defaultClause == 0) && (ast->moreClauses == 0);
276
277         if (AST::CaseClause *clause = it->clause) {
278             accept(clause->expression);
279             rewriteCaseStatements(clause->statements, returnTheValueOfLastStatement);
280         }
281     }
282
283     // Process the default case clause
284     if (ast->defaultClause) {
285         // Return the value of the last statement in the block, if this is the last `case clause'
286         // of the switch statement.
287         bool rewriteTheLastStatement = (ast->moreClauses == 0);
288
289         rewriteCaseStatements(ast->defaultClause->statements, rewriteTheLastStatement);
290     }
291
292     // Process trailing `case clauses'
293     for (AST::CaseClauses *it = ast->moreClauses; it; it = it->next) {
294         // Return the value of the last statement in the block, if this is the last `case clause'
295         // of the switch statement.
296         bool returnTheValueOfLastStatement = (it->next == 0);
297
298         if (AST::CaseClause *clause = it->clause) {
299             accept(clause->expression);
300             rewriteCaseStatements(clause->statements, returnTheValueOfLastStatement);
301         }
302     }
303
304     return false;
305 }
306
307 void RewriteBinding::rewriteCaseStatements(AST::StatementList *statements, bool rewriteTheLastStatement)
308 {
309     for (AST::StatementList *it = statements; it; it = it->next) {
310         if (it->next && AST::cast<AST::BreakStatement *>(it->next->statement) != 0) {
311             // The value of the first statement followed by a `break'.
312             accept(it->statement);
313             break;
314         } else if (!it->next) {
315             if (rewriteTheLastStatement)
316                 accept(it->statement);
317             else if (AST::Block *block = AST::cast<AST::Block *>(it->statement))
318                 rewriteCaseStatements(block->statements, rewriteTheLastStatement);
319         }
320     }
321 }
322
323 QString RewriteSignalHandler::operator()(const QString &code, const QString &name)
324 {
325     return QStringLiteral("(function ") + name + QStringLiteral("() { ") + code + QStringLiteral(" })");
326 }
327
328 } // namespace QDeclarativeRewrite
329
330 QT_END_NAMESPACE