Merge remote branch 'gerrit/api_changes' into merge-master
[profile/ivi/qtdeclarative.git] / tests / auto / qml / qqmlparser / tst_qqmlparser.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 test suite 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 <private/qqmljsengine_p.h>
43 #include <private/qqmljsparser_p.h>
44 #include <private/qqmljslexer_p.h>
45 #include <private/qqmljsastvisitor_p.h>
46 #include <private/qqmljsast_p.h>
47
48 #include <qtest.h>
49 #include <QDir>
50 #include <QDebug>
51 #include <cstdlib>
52
53 class tst_qqmlparser : public QObject
54 {
55     Q_OBJECT
56 public:
57     tst_qqmlparser();
58
59 private slots:
60     void initTestCase();
61     void qmlParser_data();
62     void qmlParser();
63
64 private:
65     QStringList excludedDirs;
66
67     QStringList findFiles(const QDir &);
68 };
69
70 namespace check {
71
72 using namespace QQmlJS;
73
74 class Check: public AST::Visitor
75 {
76     Engine *engine;
77     QList<AST::Node *> nodeStack;
78
79 public:
80     Check(Engine *engine)
81         : engine(engine)
82     {
83     }
84
85     void operator()(AST::Node *node)
86     {
87         AST::Node::accept(node, this);
88     }
89
90     void checkNode(AST::Node *node)
91     {
92         if (! nodeStack.isEmpty()) {
93             AST::Node *parent = nodeStack.last();
94             const quint32 parentBegin = parent->firstSourceLocation().begin();
95             const quint32 parentEnd = parent->lastSourceLocation().end();
96
97             QVERIFY(node->firstSourceLocation().begin() >= parentBegin);
98             QVERIFY(node->lastSourceLocation().end() <= parentEnd);
99         }
100     }
101
102     virtual bool preVisit(AST::Node *node)
103     {
104         checkNode(node);
105         nodeStack.append(node);
106         return true;
107     }
108
109     virtual void postVisit(AST::Node *)
110     {
111         nodeStack.removeLast();
112     }
113 };
114
115 }
116
117 tst_qqmlparser::tst_qqmlparser()
118 {
119 }
120
121 void tst_qqmlparser::initTestCase()
122 {
123     // Add directories you want excluded here
124
125     // These snippets are not expected to run on their own.
126     excludedDirs << "doc/src/snippets/qml/visualdatamodel_rootindex";
127     excludedDirs << "doc/src/snippets/qml/qtbinding";
128     excludedDirs << "doc/src/snippets/qml/imports";
129     excludedDirs << "doc/src/snippets/qtquick1/visualdatamodel_rootindex";
130     excludedDirs << "doc/src/snippets/qtquick1/qtbinding";
131     excludedDirs << "doc/src/snippets/qtquick1/imports";
132 }
133
134 QStringList tst_qqmlparser::findFiles(const QDir &d)
135 {
136     for (int ii = 0; ii < excludedDirs.count(); ++ii) {
137         QString s = excludedDirs.at(ii);
138         if (d.absolutePath().endsWith(s))
139             return QStringList();
140     }
141
142     QStringList rv;
143
144     QStringList files = d.entryList(QStringList() << QLatin1String("*.qml") << QLatin1String("*.js"),
145                                     QDir::Files);
146     foreach (const QString &file, files) {
147         rv << d.absoluteFilePath(file);
148     }
149
150     QStringList dirs = d.entryList(QDir::Dirs | QDir::NoDotAndDotDot |
151                                    QDir::NoSymLinks);
152     foreach (const QString &dir, dirs) {
153         QDir sub = d;
154         sub.cd(dir);
155         rv << findFiles(sub);
156     }
157
158     return rv;
159 }
160
161 /*
162 This test checks all the qml and js files in the QtQml UI source tree
163 and ensures that the subnode's source locations are inside parent node's source locations
164 */
165
166 void tst_qqmlparser::qmlParser_data()
167 {
168     QTest::addColumn<QString>("file");
169
170     QString examples = QLatin1String(SRCDIR) + "/../../../../examples/";
171     QString tests = QLatin1String(SRCDIR) + "/../../../../tests/";
172
173     QStringList files;
174     files << findFiles(QDir(examples));
175     files << findFiles(QDir(tests));
176
177     foreach (const QString &file, files)
178         QTest::newRow(qPrintable(file)) << file;
179 }
180
181 void tst_qqmlparser::qmlParser()
182 {
183     QFETCH(QString, file);
184
185     using namespace QQmlJS;
186
187     QString code;
188
189     QFile f(file);
190     if (f.open(QFile::ReadOnly))
191         code = QString::fromUtf8(f.readAll());
192
193     const bool qmlMode = file.endsWith(QLatin1String(".qml"));
194
195     Engine engine;
196     Lexer lexer(&engine);
197     lexer.setCode(code, 1, qmlMode);
198     Parser parser(&engine);
199     if (qmlMode)
200         parser.parse();
201     else
202         parser.parseProgram();
203
204     check::Check chk(&engine);
205     chk(parser.rootNode());
206 }
207
208 QTEST_MAIN(tst_qqmlparser)
209
210 #include "tst_qqmlparser.moc"