1 /****************************************************************************
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtSCriptTools module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
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
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 #include "qscriptxmlparser_p.h"
44 #include <QtCore/qstringlist.h>
45 #include <QtCore/qxmlstream.h>
46 #include <QtCore/qdebug.h>
50 static void tokenUntil(QXmlStreamReader
&reader
, QXmlStreamReader::TokenType target
,
51 QList
<int> &lineNumbers
)
54 while (!reader
.atEnd()) {
55 QXmlStreamReader::TokenType t
= reader
.readNext();
56 if ((t
== target
) && (level
== 0))
58 if (t
== QXmlStreamReader::StartElement
) {
60 QString line
= reader
.attributes().value(QLatin1String("line")).toString();
62 lineNumbers
.append(line
.toInt());
63 } else if (t
== QXmlStreamReader::EndElement
) {
67 // Q_ASSERT_X(false, "QScriptXmlParser", "premature end of file");
70 QScriptXmlParser::Result
QScriptXmlParser::parse(const QString
&xml
)
72 QMap
<QString
, int> functionsInfo
;
73 QList
<int> lineNumbers
;
74 QXmlStreamReader
reader(xml
);
75 reader
.readNext(); // StartDocument
76 reader
.readNext(); // <program>
77 reader
.readNext(); // <source-elements>
78 while (reader
.readNext() == QXmlStreamReader::StartElement
) {
79 // qDebug() << reader.name().toString();
80 int line
= reader
.attributes().value(QLatin1String("line")).toString().toInt();
81 lineNumbers
.append(line
);
82 if (reader
.name() == QLatin1String("function-declaration")) {
83 // extract the line number, name and formal parameters
84 reader
.readNext(); // <name>
85 reader
.readNext(); // Characters
86 QString name
= reader
.text().toString();
87 reader
.readNext(); // </name>
88 reader
.readNext(); // <formal-parameter-list>
89 QStringList formalParameters
;
90 while (reader
.readNext() == QXmlStreamReader::StartElement
) {
91 reader
.readNext(); // Characters
92 formalParameters
.append(reader
.text().toString());
93 reader
.readNext(); // </identifier>
95 reader
.readNext(); // <function-body>
96 tokenUntil(reader
, QXmlStreamReader::EndElement
, lineNumbers
);
99 signature
.append(name
);
100 signature
.append(QLatin1Char('('));
101 for (int i
= 0; i
< formalParameters
.size(); ++i
) {
103 signature
.append(QLatin1String(", "));
104 signature
.append(formalParameters
.at(i
));
106 signature
.append(QLatin1Char(')'));
107 functionsInfo
.insert(signature
, line
);
108 } else if (reader
.name() == QLatin1String("expression-statement")) {
110 if ((reader
.name() == QLatin1String("binary-expression"))
111 && reader
.attributes().value(QLatin1String("op")) == QLatin1String("=")) {
112 // try to match a statement of the form Foo.prototype.bar = function() { ... }
113 // this can be generalized...
114 QString first
, second
, third
;
115 reader
.readNext(); // LHS
116 if (reader
.name() == QLatin1String("field-member-expression")) {
118 if (reader
.name() == QLatin1String("field-member-expression")) {
120 if (reader
.name() == QLatin1String("identifier")) {
122 first
= reader
.text().toString();
124 tokenUntil(reader
, QXmlStreamReader::EndElement
, lineNumbers
);
126 if (reader
.name() == QLatin1String("identifier")) {
128 second
= reader
.text().toString();
130 tokenUntil(reader
, QXmlStreamReader::EndElement
, lineNumbers
);
131 } else if (reader
.name() == QLatin1String("identifier")) {
133 first
= reader
.text().toString();
135 tokenUntil(reader
, QXmlStreamReader::EndElement
, lineNumbers
);
137 if (reader
.name() == QLatin1String("identifier")) {
139 if (second
.isEmpty())
140 second
= reader
.text().toString();
142 third
= reader
.text().toString();
144 tokenUntil(reader
, QXmlStreamReader::EndElement
, lineNumbers
);
146 tokenUntil(reader
, QXmlStreamReader::EndElement
, lineNumbers
);
147 reader
.readNext(); // RHS
148 if (reader
.name() == QLatin1String("function-expression")) {
149 if (!first
.isEmpty()) {
150 QString signature
= first
;
151 if (!second
.isEmpty()) {
152 signature
.append(QLatin1Char('.'));
153 signature
.append(second
);
154 if (!third
.isEmpty()) {
155 signature
.append(QLatin1Char('.'));
156 signature
.append(third
);
159 signature
.append(QLatin1String("()"));
160 functionsInfo
.insert(signature
, line
);
163 tokenUntil(reader
, QXmlStreamReader::EndElement
, lineNumbers
);
165 tokenUntil(reader
, QXmlStreamReader::EndElement
, lineNumbers
);
167 tokenUntil(reader
, QXmlStreamReader::EndElement
, lineNumbers
);
169 reader
.readNext(); // </source-elements>
170 reader
.readNext(); // </program>
171 reader
.readNext(); // EndDocument
172 Q_ASSERT(reader
.atEnd());
173 return Result(functionsInfo
, lineNumbers
.toSet());