Warning: That file was not part of the compilation database. It may have many parsing errors.

1/****************************************************************************
2**
3** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
4** Contact: http://www.qt-project.org/legal
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 Digia. For licensing terms and
14** conditions see http://qt.digia.com/licensing. For further information
15** use the contact form at http://qt.digia.com/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 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 2.1 requirements
23** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24**
25** In addition, as a special exception, Digia gives you certain additional
26** rights. These rights are described in the Digia Qt LGPL Exception
27** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28**
29** GNU General Public License Usage
30** Alternatively, this file may be used under the terms of the GNU
31** General Public License version 3.0 as published by the Free Software
32** Foundation and appearing in the file LICENSE.GPL included in the
33** packaging of this file. Please review the following information to
34** ensure the GNU General Public License version 3.0 requirements will be
35** met: http://www.gnu.org/copyleft/gpl.html.
36**
37**
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42/*
43 qmlcodemarker.cpp
44*/
45
46#include "declarativeparser/qdeclarativejsast_p.h"
47#include "declarativeparser/qdeclarativejsastfwd_p.h"
48#include "declarativeparser/qdeclarativejsengine_p.h"
49#include "declarativeparser/qdeclarativejslexer_p.h"
50#include "declarativeparser/qdeclarativejsnodepool_p.h"
51#include "declarativeparser/qdeclarativejsparser_p.h"
52
53#include "atom.h"
54#include "node.h"
55#include "qmlcodemarker.h"
56#include "qmlmarkupvisitor.h"
57#include "text.h"
58#include "tree.h"
59
60QT_BEGIN_NAMESPACE
61
62QmlCodeMarker::QmlCodeMarker()
63{
64}
65
66QmlCodeMarker::~QmlCodeMarker()
67{
68}
69
70/*!
71 Returns true if the \a code is recognized by the parser.
72 */
73bool QmlCodeMarker::recognizeCode(const QString &code)
74{
75 QDeclarativeJS::Engine engine;
76 QDeclarativeJS::Lexer lexer(&engine);
77 QDeclarativeJS::Parser parser(&engine);
78 QDeclarativeJS::NodePool m_nodePool("<QmlCodeMarker::recognizeCode>", &engine);
79
80 QString newCode = code;
81 extractPragmas(newCode);
82 lexer.setCode(newCode, 1);
83
84 return parser.parse();
85}
86
87/*!
88 Returns true if \a ext is any of a list of file extensions
89 for the QML language.
90 */
91bool QmlCodeMarker::recognizeExtension(const QString &ext)
92{
93 return ext == "qml";
94}
95
96/*!
97 Returns true if the \a language is recognized. Only "QML" is
98 recognized by this marker.
99 */
100bool QmlCodeMarker::recognizeLanguage(const QString &language)
101{
102 return language == "QML";
103}
104
105/*!
106 Returns the type of atom used to represent QML code in the documentation.
107*/
108Atom::Type QmlCodeMarker::atomType() const
109{
110 return Atom::Qml;
111}
112
113/*!
114 Returns the name of the \a node. Method names include are returned with a
115 trailing set of parentheses.
116 */
117QString QmlCodeMarker::plainName(const Node *node)
118{
119 QString name = node->name();
120 if (node->type() == Node::QmlMethod)
121 name += "()";
122 return name;
123}
124
125QString QmlCodeMarker::plainFullName(const Node *node, const Node *relative)
126{
127 if (node->name().isEmpty()) {
128 return "global";
129 }
130 else {
131 QString fullName;
132 while (node) {
133 fullName.prepend(plainName(node));
134 if (node->parent() == relative || node->parent()->name().isEmpty())
135 break;
136 fullName.prepend("::");
137 node = node->parent();
138 }
139 return fullName;
140 }
141}
142
143QString QmlCodeMarker::markedUpCode(const QString &code,
144 const Node *relative,
145 const Location &location)
146{
147 return addMarkUp(code, relative, location);
148}
149
150QString QmlCodeMarker::markedUpName(const Node *node)
151{
152 QString name = linkTag(node, taggedNode(node));
153 if (node->type() == Node::QmlMethod)
154 name += "()";
155 return name;
156}
157
158QString QmlCodeMarker::markedUpFullName(const Node *node, const Node *relative)
159{
160 if (node->name().isEmpty()) {
161 return "global";
162 }
163 else {
164 QString fullName;
165 for (;;) {
166 fullName.prepend(markedUpName(node));
167 if (node->parent() == relative || node->parent()->name().isEmpty())
168 break;
169 fullName.prepend("<@op>::</@op>");
170 node = node->parent();
171 }
172 return fullName;
173 }
174}
175
176QString QmlCodeMarker::markedUpIncludes(const QStringList& includes)
177{
178 QString code;
179
180 QStringList::ConstIterator inc = includes.begin();
181 while (inc != includes.end()) {
182 code += "import " + *inc + "\n";
183 ++inc;
184 }
185 Location location;
186 return addMarkUp(code, 0, location);
187}
188
189QString QmlCodeMarker::functionBeginRegExp(const QString& funcName)
190{
191 return "^" + QRegExp::escape("function " + funcName) + "$";
192
193}
194
195QString QmlCodeMarker::functionEndRegExp(const QString& /* funcName */)
196{
197 return "^\\}$";
198}
199
200QString QmlCodeMarker::addMarkUp(const QString &code,
201 const Node * /* relative */,
202 const Location &location)
203{
204 QDeclarativeJS::Engine engine;
205 QDeclarativeJS::Lexer lexer(&engine);
206
207 QString newCode = code;
208 QList<QDeclarativeJS::AST::SourceLocation> pragmas = extractPragmas(newCode);
209 lexer.setCode(newCode, 1);
210
211 QDeclarativeJS::Parser parser(&engine);
212 QDeclarativeJS::NodePool m_nodePool("<QmlCodeMarker::addMarkUp>", &engine);
213 QString output;
214
215 if (parser.parse()) {
216 QDeclarativeJS::AST::UiProgram *ast = parser.ast();
217 // Pass the unmodified code to the visitor so that pragmas and other
218 // unhandled source text can be output.
219 QmlMarkupVisitor visitor(code, pragmas, &engine);
220 QDeclarativeJS::AST::Node::accept(ast, &visitor);
221 output = visitor.markedUpCode();
222 } else {
223 location.warning(tr("Unable to parse QML: \"%1\" at line %2, column %3").arg(
224 parser.errorMessage()).arg(parser.errorLineNumber()).arg(
225 parser.errorColumnNumber()));
226 output = protect(code);
227 }
228
229 return output;
230}
231
232/*
233Copied and pasted from src/declarative/qml/qdeclarativescriptparser.cpp.
234*/
235static void replaceWithSpace(QString &str, int idx, int n)
236{
237 QChar *data = str.data() + idx;
238 const QChar space(QLatin1Char(' '));
239 for (int ii = 0; ii < n; ++ii)
240 *data++ = space;
241}
242
243/*
244Copied and pasted from src/declarative/qml/qdeclarativescriptparser.cpp then
245modified to return a list of removed pragmas.
246
247Searches for ".pragma <value>" declarations within \a script. Currently supported pragmas
248are:
249 library
250*/
251QList<QDeclarativeJS::AST::SourceLocation> QmlCodeMarker::extractPragmas(QString &script)
252{
253 const QString pragma(QLatin1String("pragma"));
254 const QString library(QLatin1String("library"));
255 QList<QDeclarativeJS::AST::SourceLocation> removed;
256
257 QDeclarativeJS::Lexer l(0);
258 l.setCode(script, 0);
259
260 int token = l.lex();
261
262 while (true) {
263 if (token != QDeclarativeJSGrammar::T_DOT)
264 return removed;
265
266 int startOffset = l.tokenOffset();
267 int startLine = l.currentLineNo();
268 int startColumn = l.currentColumnNo();
269
270 token = l.lex();
271
272 if (token != QDeclarativeJSGrammar::T_IDENTIFIER ||
273 l.currentLineNo() != startLine ||
274 script.mid(l.tokenOffset(), l.tokenLength()) != pragma)
275 return removed;
276
277 token = l.lex();
278
279 if (token != QDeclarativeJSGrammar::T_IDENTIFIER ||
280 l.currentLineNo() != startLine)
281 return removed;
282
283 QString pragmaValue = script.mid(l.tokenOffset(), l.tokenLength());
284 int endOffset = l.tokenLength() + l.tokenOffset();
285
286 token = l.lex();
287 if (l.currentLineNo() == startLine)
288 return removed;
289
290 if (pragmaValue == QLatin1String("library")) {
291 replaceWithSpace(script, startOffset, endOffset - startOffset);
292 removed.append(
293 QDeclarativeJS::AST::SourceLocation(
294 startOffset, endOffset - startOffset,
295 startLine, startColumn));
296 } else
297 return removed;
298 }
299 return removed;
300}
301
302QT_END_NAMESPACE
303

Warning: That file was not part of the compilation database. It may have many parsing errors.