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 | |
60 | QT_BEGIN_NAMESPACE |
61 | |
62 | QmlCodeMarker::QmlCodeMarker() |
63 | { |
64 | } |
65 | |
66 | QmlCodeMarker::~QmlCodeMarker() |
67 | { |
68 | } |
69 | |
70 | /*! |
71 | Returns true if the \a code is recognized by the parser. |
72 | */ |
73 | bool 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 | */ |
91 | bool 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 | */ |
100 | bool 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 | */ |
108 | Atom::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 | */ |
117 | QString QmlCodeMarker::plainName(const Node *node) |
118 | { |
119 | QString name = node->name(); |
120 | if (node->type() == Node::QmlMethod) |
121 | name += "()"; |
122 | return name; |
123 | } |
124 | |
125 | QString 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 | |
143 | QString QmlCodeMarker::markedUpCode(const QString &code, |
144 | const Node *relative, |
145 | const Location &location) |
146 | { |
147 | return addMarkUp(code, relative, location); |
148 | } |
149 | |
150 | QString 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 | |
158 | QString 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 | |
176 | QString 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 | |
189 | QString QmlCodeMarker::functionBeginRegExp(const QString& funcName) |
190 | { |
191 | return "^"+ QRegExp::escape( "function "+ funcName) + "$"; |
192 | |
193 | } |
194 | |
195 | QString QmlCodeMarker::functionEndRegExp(const QString& /* funcName */) |
196 | { |
197 | return "^\\}$"; |
198 | } |
199 | |
200 | QString 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 | /* |
233 | Copied and pasted from src/declarative/qml/qdeclarativescriptparser.cpp. |
234 | */ |
235 | static 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 | /* |
244 | Copied and pasted from src/declarative/qml/qdeclarativescriptparser.cpp then |
245 | modified to return a list of removed pragmas. |
246 | |
247 | Searches for ".pragma <value>" declarations within \a script. Currently supported pragmas |
248 | are: |
249 | library |
250 | */ |
251 | QList<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 | |
302 | QT_END_NAMESPACE |
303 |
Warning: That file was not part of the compilation database. It may have many parsing errors.