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 | #include <QFileInfo> |
43 | #include <QStringList> |
44 | #include <QtGlobal> |
45 | #include "declarativeparser/qdeclarativejsast_p.h" |
46 | #include "declarativeparser/qdeclarativejsastfwd_p.h" |
47 | #include "declarativeparser/qdeclarativejsengine_p.h" |
48 | |
49 | #include "node.h" |
50 | #include "qmlvisitor.h" |
51 | |
52 | QT_BEGIN_NAMESPACE |
53 | |
54 | QmlDocVisitor::QmlDocVisitor(const QString &filePath, const QString &code, |
55 | QDeclarativeJS::Engine *engine, Tree *tree, QSet<QString> &commands) |
56 | { |
57 | this->filePath = filePath; |
58 | this->name = QFileInfo(filePath).baseName(); |
59 | document = code; |
60 | this->engine = engine; |
61 | this->tree = tree; |
62 | this->commands = commands; |
63 | current = tree->root(); |
64 | } |
65 | |
66 | QmlDocVisitor::~QmlDocVisitor() |
67 | { |
68 | } |
69 | |
70 | QDeclarativeJS::AST::SourceLocation QmlDocVisitor::precedingComment(quint32 offset) const |
71 | { |
72 | QListIterator<QDeclarativeJS::AST::SourceLocation> it(engine->comments()); |
73 | it.toBack(); |
74 | |
75 | while (it.hasPrevious()) { |
76 | |
77 | QDeclarativeJS::AST::SourceLocation loc = it.previous(); |
78 | |
79 | if (loc.begin() <= lastEndOffset) |
80 | // Return if we reach the end of the preceding structure. |
81 | break; |
82 | |
83 | else if (usedComments.contains(loc.begin())) |
84 | // Return if we encounter a previously used comment. |
85 | break; |
86 | |
87 | else if (loc.begin() > lastEndOffset && loc.end() < offset) { |
88 | |
89 | // Only examine multiline comments in order to avoid snippet markers. |
90 | if (document.mid(loc.offset - 1, 1) == "*") { |
91 | QString comment = document.mid(loc.offset, loc.length); |
92 | if (comment.startsWith("!") || comment.startsWith( "*")) |
93 | return loc; |
94 | } |
95 | } |
96 | } |
97 | |
98 | return QDeclarativeJS::AST::SourceLocation(); |
99 | } |
100 | |
101 | void QmlDocVisitor::applyDocumentation(QDeclarativeJS::AST::SourceLocation location, |
102 | Node *node) |
103 | { |
104 | QDeclarativeJS::AST::SourceLocation loc = precedingComment(location.begin()); |
105 | |
106 | if (loc.isValid()) { |
107 | QString source = document.mid(loc.offset, loc.length); |
108 | |
109 | Location start(filePath); |
110 | start.setLineNo(loc.startLine); |
111 | start.setColumnNo(loc.startColumn); |
112 | Location finish(filePath); |
113 | finish.setLineNo(loc.startLine); |
114 | finish.setColumnNo(loc.startColumn); |
115 | |
116 | Doc doc(start, finish, source.mid(1), commands); |
117 | node->setDoc(doc); |
118 | |
119 | usedComments.insert(loc.offset); |
120 | } |
121 | } |
122 | |
123 | /*! |
124 | Visits element definitions, recording them in a tree structure. |
125 | */ |
126 | bool QmlDocVisitor::visit(QDeclarativeJS::AST::UiObjectDefinition *definition) |
127 | { |
128 | QString type = definition->qualifiedTypeNameId->name->asString(); |
129 | |
130 | if (current->type() == Node::Namespace) { |
131 | QmlClassNode *component = new QmlClassNode(current, name, 0); |
132 | component->setTitle(QLatin1String("QML ") + name + QLatin1String( " Component")); |
133 | |
134 | QmlClassNode::addInheritedBy(type, component); |
135 | component->setLink(Node::InheritsLink, type, type); |
136 | |
137 | applyDocumentation(definition->firstSourceLocation(), component); |
138 | |
139 | current = component; |
140 | } |
141 | |
142 | return true; |
143 | } |
144 | |
145 | void QmlDocVisitor::endVisit(QDeclarativeJS::AST::UiObjectDefinition *definition) |
146 | { |
147 | lastEndOffset = definition->lastSourceLocation().end(); |
148 | } |
149 | |
150 | bool QmlDocVisitor::visit(QDeclarativeJS::AST::UiImportList *imports) |
151 | { |
152 | // Note that the imports list can be traversed by iteration to obtain |
153 | // all the imports in the document at once, having found just one: |
154 | // *it = imports; it; it = it->next |
155 | |
156 | QString module = document.mid(imports->import->fileNameToken.offset, |
157 | imports->import->fileNameToken.length); |
158 | QString version = document.mid(imports->import->versionToken.offset, |
159 | imports->import->versionToken.length); |
160 | importList.append(QPair<QString, QString>(module, version)); |
161 | |
162 | return true; |
163 | } |
164 | |
165 | void QmlDocVisitor::endVisit(QDeclarativeJS::AST::UiImportList *definition) |
166 | { |
167 | lastEndOffset = definition->lastSourceLocation().end(); |
168 | } |
169 | |
170 | /*! |
171 | Visits public member declarations, such as signals and properties. |
172 | These only include custom signals and properties. |
173 | */ |
174 | bool QmlDocVisitor::visit(QDeclarativeJS::AST::UiPublicMember *member) |
175 | { |
176 | switch (member->type) { |
177 | case QDeclarativeJS::AST::UiPublicMember::Signal: |
178 | { |
179 | if (current->type() == Node::Fake) { |
180 | QmlClassNode *qmlClass = static_cast<QmlClassNode *>(current); |
181 | if (qmlClass) { |
182 | |
183 | QString name = member->name->asString(); |
184 | FunctionNode *qmlSignal = new FunctionNode(Node::QmlSignal, current, name, false); |
185 | |
186 | QList<Parameter> parameters; |
187 | for (QDeclarativeJS::AST::UiParameterList *it = member->parameters; it; it = it->next) { |
188 | if (it->type && it->name) |
189 | parameters.append(Parameter(it->type->asString(), "", it->name->asString())); |
190 | } |
191 | |
192 | qmlSignal->setParameters(parameters); |
193 | applyDocumentation(member->firstSourceLocation(), qmlSignal); |
194 | } |
195 | } |
196 | break; |
197 | } |
198 | case QDeclarativeJS::AST::UiPublicMember::Property: |
199 | { |
200 | QString type = member->memberType->asString(); |
201 | QString name = member->name->asString(); |
202 | |
203 | if (current->type() == Node::Fake) { |
204 | QmlClassNode *qmlClass = static_cast<QmlClassNode *>(current); |
205 | if (qmlClass) { |
206 | |
207 | QString name = member->name->asString(); |
208 | QmlPropGroupNode *qmlPropGroup = new QmlPropGroupNode(qmlClass, name, false); |
209 | if (member->isDefaultMember) |
210 | qmlPropGroup->setDefault(); |
211 | QmlPropertyNode *qmlPropNode = new QmlPropertyNode(qmlPropGroup, name, type, false); |
212 | qmlPropNode->setWritable(!member->isReadonlyMember); |
213 | applyDocumentation(member->firstSourceLocation(), qmlPropGroup); |
214 | } |
215 | } |
216 | break; |
217 | } |
218 | default: |
219 | return false; |
220 | } |
221 | |
222 | return true; |
223 | } |
224 | |
225 | void QmlDocVisitor::endVisit(QDeclarativeJS::AST::UiPublicMember *definition) |
226 | { |
227 | lastEndOffset = definition->lastSourceLocation().end(); |
228 | } |
229 | |
230 | bool QmlDocVisitor::visit(QDeclarativeJS::AST::IdentifierPropertyName *) |
231 | { |
232 | return true; |
233 | } |
234 | |
235 | QT_END_NAMESPACE |
236 |
Warning: That file was not part of the compilation database. It may have many parsing errors.