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
52QT_BEGIN_NAMESPACE
53
54QmlDocVisitor::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
66QmlDocVisitor::~QmlDocVisitor()
67{
68}
69
70QDeclarativeJS::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
101void 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*/
126bool 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
145void QmlDocVisitor::endVisit(QDeclarativeJS::AST::UiObjectDefinition *definition)
146{
147 lastEndOffset = definition->lastSourceLocation().end();
148}
149
150bool 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
165void 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*/
174bool 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
225void QmlDocVisitor::endVisit(QDeclarativeJS::AST::UiPublicMember *definition)
226{
227 lastEndOffset = definition->lastSourceLocation().end();
228}
229
230bool QmlDocVisitor::visit(QDeclarativeJS::AST::IdentifierPropertyName *)
231{
232 return true;
233}
234
235QT_END_NAMESPACE
236

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