Implement strict mode for qmldir modules
[profile/ivi/qtdeclarative.git] / src / qml / qml / qqmlerror.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 QtQml 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 "qqmlerror.h"
43
44 #include <QtCore/qdebug.h>
45 #include <QtCore/qfile.h>
46 #include <QtCore/qstringlist.h>
47
48 QT_BEGIN_NAMESPACE
49
50 /*!
51     \class QQmlError
52     \since 5.0
53     \inmodule QtQml
54     \brief The QQmlError class encapsulates a QML error.
55
56     QQmlError includes a textual description of the error, as well
57     as location information (the file, line, and column). The toString()
58     method creates a single-line, human-readable string containing all of
59     this information, for example:
60     \code
61     file:///home/user/test.qml:7:8: Invalid property assignment: double expected
62     \endcode
63
64     You can use qDebug() or qWarning() to output errors to the console. This method
65     will attempt to open the file indicated by the error
66     and include additional contextual information.
67     \code
68     file:///home/user/test.qml:7:8: Invalid property assignment: double expected
69             y: "hello"
70                ^
71     \endcode
72
73     Note that the QtQuick 1 version is named QDeclarativeError
74
75     \sa QQuickView::errors(), QQmlComponent::errors()
76 */
77 class QQmlErrorPrivate
78 {
79 public:
80     QQmlErrorPrivate();
81
82     QUrl url;
83     QString description;
84     int line;
85     int column;
86 };
87
88 QQmlErrorPrivate::QQmlErrorPrivate()
89 : line(-1), column(-1)
90 {
91 }
92
93 /*!
94     Creates an empty error object.
95 */
96 QQmlError::QQmlError()
97 : d(0)
98 {
99 }
100
101 /*!
102     Creates a copy of \a other.
103 */
104 QQmlError::QQmlError(const QQmlError &other)
105 : d(0)
106 {
107     *this = other;
108 }
109
110 /*!
111     Assigns \a other to this error object.
112 */
113 QQmlError &QQmlError::operator=(const QQmlError &other)
114 {
115     if (!other.d) {
116         delete d;
117         d = 0;
118     } else {
119         if (!d) d = new QQmlErrorPrivate;
120         d->url = other.d->url;
121         d->description = other.d->description;
122         d->line = other.d->line;
123         d->column = other.d->column;
124     }
125     return *this;
126 }
127
128 /*!
129     \internal 
130 */
131 QQmlError::~QQmlError()
132 {
133     delete d; d = 0;
134 }
135
136 /*!
137     Returns true if this error is valid, otherwise false.
138 */
139 bool QQmlError::isValid() const
140 {
141     return d != 0;
142 }
143
144 /*!
145     Returns the url for the file that caused this error.
146 */
147 QUrl QQmlError::url() const
148 {
149     if (d) return d->url;
150     else return QUrl();
151 }
152
153 /*!
154     Sets the \a url for the file that caused this error.
155 */
156 void QQmlError::setUrl(const QUrl &url)
157 {
158     if (!d) d = new QQmlErrorPrivate;
159     d->url = url;
160 }
161
162 /*!
163     Returns the error description.
164 */
165 QString QQmlError::description() const
166 {
167     if (d) return d->description;
168     else return QString();
169 }
170
171 /*!
172     Sets the error \a description.
173 */
174 void QQmlError::setDescription(const QString &description)
175 {
176     if (!d) d = new QQmlErrorPrivate;
177     d->description = description;
178 }
179
180 /*!
181     Returns the error line number.
182 */
183 int QQmlError::line() const
184 {
185     if (d) return d->line;
186     else return -1;
187 }
188
189 /*!
190     Sets the error \a line number.
191 */
192 void QQmlError::setLine(int line)
193 {
194     if (!d) d = new QQmlErrorPrivate;
195     d->line = line;
196 }
197
198 /*!
199     Returns the error column number.
200 */
201 int QQmlError::column() const
202 {
203     if (d) return d->column;
204     else return -1;
205 }
206
207 /*!
208     Sets the error \a column number.
209 */
210 void QQmlError::setColumn(int column)
211 {
212     if (!d) d = new QQmlErrorPrivate;
213     d->column = column;
214 }
215
216 /*!
217     Returns the error as a human readable string.
218 */
219 QString QQmlError::toString() const
220 {
221     QString rv;
222     if (url().isEmpty()) {
223         rv = QLatin1String("<Unknown File>");
224     } else if (line() != -1) {
225         rv = url().toString() + QLatin1Char(':') + QString::number(line());
226         if(column() != -1) 
227             rv += QLatin1Char(':') + QString::number(column());
228     } else {
229         rv = url().toString();
230     }
231
232     rv += QLatin1String(": ") + description();
233
234     return rv;
235 }
236
237 /*!
238     \relates QQmlError
239     \fn QDebug operator<<(QDebug debug, const QQmlError &error)
240
241     Outputs a human readable version of \a error to \a debug.
242 */
243
244 QDebug operator<<(QDebug debug, const QQmlError &error)
245 {
246     debug << qPrintable(error.toString());
247
248     QUrl url = error.url();
249
250     if (error.line() > 0 && url.scheme() == QLatin1String("file")) {
251         QString file = url.toLocalFile();
252         QFile f(file);
253         if (f.open(QIODevice::ReadOnly)) {
254             QByteArray data = f.readAll();
255             QTextStream stream(data, QIODevice::ReadOnly);
256 #ifndef QT_NO_TEXTCODEC
257             stream.setCodec("UTF-8");
258 #endif
259             const QString code = stream.readAll();
260             const QStringList lines = code.split(QLatin1Char('\n'));
261
262             if (lines.count() >= error.line()) {
263                 const QString &line = lines.at(error.line() - 1);
264                 debug << "\n    " << qPrintable(line);
265
266                 if(error.column() > 0) {
267                     int column = qMax(0, error.column() - 1);
268                     column = qMin(column, line.length()); 
269
270                     QByteArray ind;
271                     ind.reserve(column);
272                     for (int i = 0; i < column; ++i) {
273                         const QChar ch = line.at(i);
274                         if (ch.isSpace())
275                             ind.append(ch.unicode());
276                         else
277                             ind.append(' ');
278                     }
279                     ind.append('^');
280                     debug << "\n    " << ind.constData();
281                 }
282             }
283         }
284     }
285     return debug;
286 }
287
288 QT_END_NAMESPACE