|
@@
-1,2634
+1,2634
|
|
1
|
/****************************************************************************
|
|
1
|
/****************************************************************************
|
|
2
|
**
|
|
2
|
**
|
|
3
|
** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
3
|
** Copyright (C) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
|
|
4
|
** All rights reserved.
|
|
4
|
** All rights reserved.
|
|
5
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
5
|
** Contact: Nokia Corporation (qt-info@nokia.com)
|
|
6
|
**
|
|
6
|
**
|
|
7
|
** This file is part of the Qt Script Generator project on Qt Labs.
|
|
7
|
** This file is part of the Qt Script Generator project on Qt Labs.
|
|
8
|
**
|
|
8
|
**
|
|
9
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
9
|
** $QT_BEGIN_LICENSE:LGPL$
|
|
10
|
** No Commercial Usage
|
|
10
|
** No Commercial Usage
|
|
11
|
** This file contains pre-release code and may not be distributed.
|
|
11
|
** This file contains pre-release code and may not be distributed.
|
|
12
|
** You may use this file in accordance with the terms and conditions
|
|
12
|
** You may use this file in accordance with the terms and conditions
|
|
13
|
** contained in the Technology Preview License Agreement accompanying
|
|
13
|
** contained in the Technology Preview License Agreement accompanying
|
|
14
|
** this package.
|
|
14
|
** this package.
|
|
15
|
**
|
|
15
|
**
|
|
16
|
** GNU Lesser General Public License Usage
|
|
16
|
** GNU Lesser General Public License Usage
|
|
17
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
17
|
** Alternatively, this file may be used under the terms of the GNU Lesser
|
|
18
|
** General Public License version 2.1 as published by the Free Software
|
|
18
|
** General Public License version 2.1 as published by the Free Software
|
|
19
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
19
|
** Foundation and appearing in the file LICENSE.LGPL included in the
|
|
20
|
** packaging of this file. Please review the following information to
|
|
20
|
** packaging of this file. Please review the following information to
|
|
21
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
21
|
** ensure the GNU Lesser General Public License version 2.1 requirements
|
|
22
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
22
|
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
|
|
23
|
**
|
|
23
|
**
|
|
24
|
** In addition, as a special exception, Nokia gives you certain additional
|
|
24
|
** In addition, as a special exception, Nokia gives you certain additional
|
|
25
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
25
|
** rights. These rights are described in the Nokia Qt LGPL Exception
|
|
26
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
26
|
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
|
|
27
|
**
|
|
27
|
**
|
|
28
|
** If you have questions regarding the use of this file, please contact
|
|
28
|
** If you have questions regarding the use of this file, please contact
|
|
29
|
** Nokia at qt-info@nokia.com.
|
|
29
|
** Nokia at qt-info@nokia.com.
|
|
30
|
**
|
|
30
|
**
|
|
31
|
**
|
|
31
|
**
|
|
32
|
**
|
|
32
|
**
|
|
33
|
**
|
|
33
|
**
|
|
34
|
**
|
|
34
|
**
|
|
35
|
**
|
|
35
|
**
|
|
36
|
**
|
|
36
|
**
|
|
37
|
**
|
|
37
|
**
|
|
38
|
** $QT_END_LICENSE$
|
|
38
|
** $QT_END_LICENSE$
|
|
39
|
**
|
|
39
|
**
|
|
40
|
****************************************************************************/
|
|
40
|
****************************************************************************/
|
|
41
|
|
|
41
|
|
|
42
|
#include "abstractmetabuilder.h"
|
|
42
|
#include "abstractmetabuilder.h"
|
|
43
|
#include "reporthandler.h"
|
|
43
|
#include "reporthandler.h"
|
|
44
|
|
|
44
|
|
|
45
|
#include "ast.h"
|
|
45
|
#include "ast.h"
|
|
46
|
#include "binder.h"
|
|
46
|
#include "binder.h"
|
|
47
|
#include "control.h"
|
|
47
|
#include "control.h"
|
|
48
|
#include "default_visitor.h"
|
|
48
|
#include "default_visitor.h"
|
|
49
|
#include "dumptree.h"
|
|
49
|
#include "dumptree.h"
|
|
50
|
#include "lexer.h"
|
|
50
|
#include "lexer.h"
|
|
51
|
#include "parser.h"
|
|
51
|
#include "parser.h"
|
|
52
|
#include "tokens.h"
|
|
52
|
#include "tokens.h"
|
|
53
|
|
|
53
|
|
|
54
|
#include <QtCore/QDebug>
|
|
54
|
#include <QtCore/QDebug>
|
|
55
|
#include <QtCore/QFile>
|
|
55
|
#include <QtCore/QFile>
|
|
56
|
#include <QtCore/QFileInfo>
|
|
56
|
#include <QtCore/QFileInfo>
|
|
57
|
#include <QtCore/QTextCodec>
|
|
57
|
#include <QtCore/QTextCodec>
|
|
58
|
#include <QtCore/QTextStream>
|
|
58
|
#include <QtCore/QTextStream>
|
|
59
|
#include <QtCore/QVariant>
|
|
59
|
#include <QtCore/QVariant>
|
|
60
|
|
|
60
|
|
|
61
|
static QString strip_template_args(const QString &name)
|
|
61
|
static QString strip_template_args(const QString &name)
|
|
62
|
{
|
|
62
|
{
|
|
63
|
int pos = name.indexOf('<');
|
|
63
|
int pos = name.indexOf('<');
|
|
64
|
return pos < 0 ? name : name.left(pos);
|
|
64
|
return pos < 0 ? name : name.left(pos);
|
|
65
|
}
|
|
65
|
}
|
|
66
|
|
|
66
|
|
|
67
|
static QHash<QString, QString> *operator_names;
|
|
67
|
static QHash<QString, QString> *operator_names;
|
|
68
|
QString rename_operator(const QString &oper)
|
|
68
|
QString rename_operator(const QString &oper)
|
|
69
|
{
|
|
69
|
{
|
|
70
|
QString op = oper.trimmed();
|
|
70
|
QString op = oper.trimmed();
|
|
71
|
if (!operator_names) {
|
|
71
|
if (!operator_names) {
|
|
72
|
operator_names = new QHash<QString, QString>;
|
|
72
|
operator_names = new QHash<QString, QString>;
|
|
73
|
|
|
73
|
|
|
74
|
operator_names->insert("+", "__add__");
|
|
74
|
operator_names->insert("+", "__add__");
|
|
75
|
operator_names->insert("-", "__sub__");
|
|
75
|
operator_names->insert("-", "__sub__");
|
|
76
|
operator_names->insert("*", "__mul__");
|
|
76
|
operator_names->insert("*", "__mul__");
|
|
77
|
operator_names->insert("/", "__div__");
|
|
77
|
operator_names->insert("/", "__div__");
|
|
78
|
operator_names->insert("%", "__mod__");
|
|
78
|
operator_names->insert("%", "__mod__");
|
|
79
|
operator_names->insert("&", "__and__");
|
|
79
|
operator_names->insert("&", "__and__");
|
|
80
|
operator_names->insert("|", "__or__");
|
|
80
|
operator_names->insert("|", "__or__");
|
|
81
|
operator_names->insert("^", "__xor__");
|
|
81
|
operator_names->insert("^", "__xor__");
|
|
82
|
operator_names->insert("~", "__negate__");
|
|
82
|
operator_names->insert("~", "__negate__");
|
|
83
|
operator_names->insert("<<", "__lshift__");
|
|
83
|
operator_names->insert("<<", "__lshift__");
|
|
84
|
operator_names->insert(">>", "__rshift__");
|
|
84
|
operator_names->insert(">>", "__rshift__");
|
|
85
|
|
|
85
|
|
|
86
|
// assigments
|
|
86
|
// assigments
|
|
87
|
operator_names->insert("=", "assign");
|
|
87
|
operator_names->insert("=", "assign");
|
|
88
|
operator_names->insert("+=", "__iadd__");
|
|
88
|
operator_names->insert("+=", "__iadd__");
|
|
89
|
operator_names->insert("-=", "__isub__");
|
|
89
|
operator_names->insert("-=", "__isub__");
|
|
90
|
operator_names->insert("*=", "__imul__");
|
|
90
|
operator_names->insert("*=", "__imul__");
|
|
91
|
operator_names->insert("/=", "__idiv__");
|
|
91
|
operator_names->insert("/=", "__idiv__");
|
|
92
|
operator_names->insert("%=", "__imod__");
|
|
92
|
operator_names->insert("%=", "__imod__");
|
|
93
|
operator_names->insert("&=", "__iand__");
|
|
93
|
operator_names->insert("&=", "__iand__");
|
|
94
|
operator_names->insert("|=", "__ior__");
|
|
94
|
operator_names->insert("|=", "__ior__");
|
|
95
|
operator_names->insert("^=", "__ixor__");
|
|
95
|
operator_names->insert("^=", "__ixor__");
|
|
96
|
operator_names->insert("<<=", "__ilshift__");
|
|
96
|
operator_names->insert("<<=", "__ilshift__");
|
|
97
|
operator_names->insert(">>=", "__irshift__");
|
|
97
|
operator_names->insert(">>=", "__irshift__");
|
|
98
|
|
|
98
|
|
|
99
|
// Logical
|
|
99
|
// Logical
|
|
100
|
operator_names->insert("&&", "logical_and");
|
|
100
|
operator_names->insert("&&", "logical_and");
|
|
101
|
operator_names->insert("||", "logical_or");
|
|
101
|
operator_names->insert("||", "logical_or");
|
|
102
|
operator_names->insert("!", "not");
|
|
102
|
operator_names->insert("!", "not");
|
|
103
|
|
|
103
|
|
|
104
|
// incr/decr
|
|
104
|
// incr/decr
|
|
105
|
operator_names->insert("++", "increment");
|
|
105
|
operator_names->insert("++", "increment");
|
|
106
|
operator_names->insert("--", "decrement");
|
|
106
|
operator_names->insert("--", "decrement");
|
|
107
|
|
|
107
|
|
|
108
|
// compare
|
|
108
|
// compare
|
|
109
|
operator_names->insert("<", "less");
|
|
109
|
operator_names->insert("<", "less");
|
|
110
|
operator_names->insert(">", "greater");
|
|
110
|
operator_names->insert(">", "greater");
|
|
111
|
operator_names->insert("<=", "less_or_equal");
|
|
111
|
operator_names->insert("<=", "less_or_equal");
|
|
112
|
operator_names->insert(">=", "greater_or_equal");
|
|
112
|
operator_names->insert(">=", "greater_or_equal");
|
|
113
|
operator_names->insert("!=", "not_equal");
|
|
113
|
operator_names->insert("!=", "not_equal");
|
|
114
|
operator_names->insert("==", "equal");
|
|
114
|
operator_names->insert("==", "equal");
|
|
115
|
|
|
115
|
|
|
116
|
// other
|
|
116
|
// other
|
|
117
|
operator_names->insert("[]", "subscript");
|
|
117
|
operator_names->insert("[]", "subscript");
|
|
118
|
operator_names->insert("->", "pointer");
|
|
118
|
operator_names->insert("->", "pointer");
|
|
119
|
}
|
|
119
|
}
|
|
120
|
|
|
120
|
|
|
121
|
if (!operator_names->contains(op)) {
|
|
121
|
if (!operator_names->contains(op)) {
|
|
122
|
TypeDatabase *tb = TypeDatabase::instance();
|
|
122
|
TypeDatabase *tb = TypeDatabase::instance();
|
|
123
|
|
|
123
|
|
|
124
|
TypeParser::Info typeInfo = TypeParser::parse(op);
|
|
124
|
TypeParser::Info typeInfo = TypeParser::parse(op);
|
|
125
|
QString cast_to_name = typeInfo.qualified_name.join("::");
|
|
125
|
QString cast_to_name = typeInfo.qualified_name.join("::");
|
|
126
|
TypeEntry *te = tb->findType(cast_to_name);
|
|
126
|
TypeEntry *te = tb->findType(cast_to_name);
|
|
127
|
if ((te && te->codeGeneration() == TypeEntry::GenerateNothing)
|
|
127
|
if ((te && te->codeGeneration() == TypeEntry::GenerateNothing)
|
|
128
|
|| tb->isClassRejected(cast_to_name)) {
|
|
128
|
|| tb->isClassRejected(cast_to_name)) {
|
|
129
|
return QString();
|
|
129
|
return QString();
|
|
130
|
} else if (te) {
|
|
130
|
} else if (te) {
|
|
131
|
return "operator_cast_" + typeInfo.qualified_name.join("_");
|
|
131
|
return "operator_cast_" + typeInfo.qualified_name.join("_");
|
|
132
|
} else {
|
|
132
|
} else {
|
|
133
|
ReportHandler::warning(QString("unknown operator '%1'").arg(op));
|
|
133
|
ReportHandler::warning(QString("unknown operator '%1'").arg(op));
|
|
134
|
return "operator " + op;
|
|
134
|
return "operator " + op;
|
|
135
|
}
|
|
135
|
}
|
|
136
|
}
|
|
136
|
}
|
|
137
|
|
|
137
|
|
|
138
|
QString r = operator_names->value(op);
|
|
138
|
QString r = operator_names->value(op);
|
|
139
|
if (r.startsWith("__")) {
|
|
139
|
if (r.startsWith("__")) {
|
|
140
|
return r;
|
|
140
|
return r;
|
|
141
|
} else {
|
|
141
|
} else {
|
|
142
|
return "operator_" + r;
|
|
142
|
return "operator_" + r;
|
|
143
|
}
|
|
143
|
}
|
|
144
|
}
|
|
144
|
}
|
|
145
|
|
|
145
|
|
|
146
|
AbstractMetaBuilder::AbstractMetaBuilder()
|
|
146
|
AbstractMetaBuilder::AbstractMetaBuilder()
|
|
147
|
: m_current_class(0)
|
|
147
|
: m_current_class(0)
|
|
148
|
{
|
|
148
|
{
|
|
149
|
}
|
|
149
|
}
|
|
150
|
|
|
150
|
|
|
151
|
void AbstractMetaBuilder::checkFunctionModifications()
|
|
151
|
void AbstractMetaBuilder::checkFunctionModifications()
|
|
152
|
{
|
|
152
|
{
|
|
153
|
TypeDatabase *types = TypeDatabase::instance();
|
|
153
|
TypeDatabase *types = TypeDatabase::instance();
|
|
154
|
SingleTypeEntryHash entryHash = types->entries();
|
|
154
|
SingleTypeEntryHash entryHash = types->entries();
|
|
155
|
QList<TypeEntry *> entries = entryHash.values();
|
|
155
|
QList<TypeEntry *> entries = entryHash.values();
|
|
156
|
foreach (TypeEntry *entry, entries) {
|
|
156
|
foreach (TypeEntry *entry, entries) {
|
|
157
|
if (entry == 0)
|
|
157
|
if (entry == 0)
|
|
158
|
continue;
|
|
158
|
continue;
|
|
159
|
if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
|
|
159
|
if (!entry->isComplex() || entry->codeGeneration() == TypeEntry::GenerateNothing)
|
|
160
|
continue;
|
|
160
|
continue;
|
|
161
|
|
|
161
|
|
|
162
|
ComplexTypeEntry *centry = static_cast<ComplexTypeEntry *>(entry);
|
|
162
|
ComplexTypeEntry *centry = static_cast<ComplexTypeEntry *>(entry);
|
|
163
|
FunctionModificationList modifications = centry->functionModifications();
|
|
163
|
FunctionModificationList modifications = centry->functionModifications();
|
|
164
|
|
|
164
|
|
|
165
|
foreach (FunctionModification modification, modifications) {
|
|
165
|
foreach (FunctionModification modification, modifications) {
|
|
166
|
QString signature = modification.signature;
|
|
166
|
QString signature = modification.signature;
|
|
167
|
|
|
167
|
|
|
168
|
QString name = signature.trimmed();
|
|
168
|
QString name = signature.trimmed();
|
|
169
|
name = name.mid(0, signature.indexOf("("));
|
|
169
|
name = name.mid(0, signature.indexOf("("));
|
|
170
|
|
|
170
|
|
|
171
|
AbstractMetaClass *clazz = m_meta_classes.findClass(centry->qualifiedCppName());
|
|
171
|
AbstractMetaClass *clazz = m_meta_classes.findClass(centry->qualifiedCppName());
|
|
172
|
if (clazz == 0)
|
|
172
|
if (clazz == 0)
|
|
173
|
continue;
|
|
173
|
continue;
|
|
174
|
|
|
174
|
|
|
175
|
AbstractMetaFunctionList functions = clazz->functions();
|
|
175
|
AbstractMetaFunctionList functions = clazz->functions();
|
|
176
|
bool found = false;
|
|
176
|
bool found = false;
|
|
177
|
QStringList possibleSignatures;
|
|
177
|
QStringList possibleSignatures;
|
|
178
|
foreach (AbstractMetaFunction *function, functions) {
|
|
178
|
foreach (AbstractMetaFunction *function, functions) {
|
|
179
|
if (function->minimalSignature() == signature && function->implementingClass() == clazz) {
|
|
179
|
if (function->minimalSignature() == signature && function->implementingClass() == clazz) {
|
|
180
|
found = true;
|
|
180
|
found = true;
|
|
181
|
break;
|
|
181
|
break;
|
|
182
|
}
|
|
182
|
}
|
|
183
|
|
|
183
|
|
|
184
|
if (function->originalName() == name)
|
|
184
|
if (function->originalName() == name)
|
|
185
|
possibleSignatures.append(function->minimalSignature() + " in " + function->implementingClass()->name());
|
|
185
|
possibleSignatures.append(function->minimalSignature() + " in " + function->implementingClass()->name());
|
|
186
|
}
|
|
186
|
}
|
|
187
|
|
|
187
|
|
|
188
|
if (!found) {
|
|
188
|
if (!found) {
|
|
189
|
QString warning
|
|
189
|
QString warning
|
|
190
|
= QString("signature '%1' for function modification in '%2' not found. Possible candidates: %3")
|
|
190
|
= QString("signature '%1' for function modification in '%2' not found. Possible candidates: %3")
|
|
191
|
.arg(signature)
|
|
191
|
.arg(signature)
|
|
192
|
.arg(clazz->qualifiedCppName())
|
|
192
|
.arg(clazz->qualifiedCppName())
|
|
193
|
.arg(possibleSignatures.join(", "));
|
|
193
|
.arg(possibleSignatures.join(", "));
|
|
194
|
|
|
194
|
|
|
195
|
ReportHandler::warning(warning);
|
|
195
|
ReportHandler::warning(warning);
|
|
196
|
}
|
|
196
|
}
|
|
197
|
}
|
|
197
|
}
|
|
198
|
}
|
|
198
|
}
|
|
199
|
}
|
|
199
|
}
|
|
200
|
|
|
200
|
|
|
201
|
AbstractMetaClass *AbstractMetaBuilder::argumentToClass(ArgumentModelItem argument)
|
|
201
|
AbstractMetaClass *AbstractMetaBuilder::argumentToClass(ArgumentModelItem argument)
|
|
202
|
{
|
|
202
|
{
|
|
203
|
AbstractMetaClass *returned = 0;
|
|
203
|
AbstractMetaClass *returned = 0;
|
|
204
|
bool ok = false;
|
|
204
|
bool ok = false;
|
|
205
|
AbstractMetaType *type = translateType(argument->type(), &ok);
|
|
205
|
AbstractMetaType *type = translateType(argument->type(), &ok);
|
|
206
|
if (ok && type != 0 && type->typeEntry() != 0 && type->typeEntry()->isComplex()) {
|
|
206
|
if (ok && type != 0 && type->typeEntry() != 0 && type->typeEntry()->isComplex()) {
|
|
207
|
const TypeEntry *entry = type->typeEntry();
|
|
207
|
const TypeEntry *entry = type->typeEntry();
|
|
208
|
returned = m_meta_classes.findClass(entry->name());
|
|
208
|
returned = m_meta_classes.findClass(entry->name());
|
|
209
|
}
|
|
209
|
}
|
|
210
|
delete type;
|
|
210
|
delete type;
|
|
211
|
return returned;
|
|
211
|
return returned;
|
|
212
|
}
|
|
212
|
}
|
|
213
|
|
|
213
|
|
|
214
|
/**
|
|
214
|
/**
|
|
215
|
* Checks the argument of a hash function and flags the type if it is a complex type
|
|
215
|
* Checks the argument of a hash function and flags the type if it is a complex type
|
|
216
|
*/
|
|
216
|
*/
|
|
217
|
void AbstractMetaBuilder::registerHashFunction(FunctionModelItem function_item)
|
|
217
|
void AbstractMetaBuilder::registerHashFunction(FunctionModelItem function_item)
|
|
218
|
{
|
|
218
|
{
|
|
219
|
ArgumentList arguments = function_item->arguments();
|
|
219
|
ArgumentList arguments = function_item->arguments();
|
|
220
|
if (arguments.size() == 1) {
|
|
220
|
if (arguments.size() == 1) {
|
|
221
|
if (AbstractMetaClass *cls = argumentToClass(arguments.at(0)))
|
|
221
|
if (AbstractMetaClass *cls = argumentToClass(arguments.at(0)))
|
|
222
|
cls->setHasHashFunction(true);
|
|
222
|
cls->setHasHashFunction(true);
|
|
223
|
}
|
|
223
|
}
|
|
224
|
}
|
|
224
|
}
|
|
225
|
|
|
225
|
|
|
226
|
/**
|
|
226
|
/**
|
|
227
|
* Check if a class has a debug stream operator that can be used as toString
|
|
227
|
* Check if a class has a debug stream operator that can be used as toString
|
|
228
|
*/
|
|
228
|
*/
|
|
229
|
|
|
229
|
|
|
230
|
void AbstractMetaBuilder::registerToStringCapability(FunctionModelItem function_item)
|
|
230
|
void AbstractMetaBuilder::registerToStringCapability(FunctionModelItem function_item)
|
|
231
|
{
|
|
231
|
{
|
|
232
|
ArgumentList arguments = function_item->arguments();
|
|
232
|
ArgumentList arguments = function_item->arguments();
|
|
233
|
if (arguments.size() == 2) {
|
|
233
|
if (arguments.size() == 2) {
|
|
234
|
if (arguments.at(0)->type().toString() == "QDebug"){
|
|
234
|
if (arguments.at(0)->type().toString() == "QDebug"){
|
|
235
|
ArgumentModelItem arg = arguments.at(1);
|
|
235
|
ArgumentModelItem arg = arguments.at(1);
|
|
236
|
if (AbstractMetaClass *cls = argumentToClass(arg)) {
|
|
236
|
if (AbstractMetaClass *cls = argumentToClass(arg)) {
|
|
237
|
if (arg->type().indirections() < 2) {
|
|
237
|
if (arg->type().indirections() < 2 && cls->name()!="QObject") {
|
|
238
|
cls->setToStringCapability(function_item);
|
|
238
|
cls->setToStringCapability(function_item);
|
|
239
|
}
|
|
239
|
}
|
|
240
|
}
|
|
240
|
}
|
|
241
|
}
|
|
241
|
}
|
|
242
|
}
|
|
242
|
}
|
|
243
|
}
|
|
243
|
}
|
|
244
|
|
|
244
|
|
|
245
|
void AbstractMetaBuilder::traverseCompareOperator(FunctionModelItem item) {
|
|
245
|
void AbstractMetaBuilder::traverseCompareOperator(FunctionModelItem item) {
|
|
246
|
ArgumentList arguments = item->arguments();
|
|
246
|
ArgumentList arguments = item->arguments();
|
|
247
|
if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
|
|
247
|
if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
|
|
248
|
AbstractMetaClass *comparer_class = argumentToClass(arguments.at(0));
|
|
248
|
AbstractMetaClass *comparer_class = argumentToClass(arguments.at(0));
|
|
249
|
AbstractMetaClass *compared_class = argumentToClass(arguments.at(1));
|
|
249
|
AbstractMetaClass *compared_class = argumentToClass(arguments.at(1));
|
|
250
|
if (comparer_class != 0 && compared_class != 0) {
|
|
250
|
if (comparer_class != 0 && compared_class != 0) {
|
|
251
|
AbstractMetaClass *old_current_class = m_current_class;
|
|
251
|
AbstractMetaClass *old_current_class = m_current_class;
|
|
252
|
m_current_class = comparer_class;
|
|
252
|
m_current_class = comparer_class;
|
|
253
|
|
|
253
|
|
|
254
|
AbstractMetaFunction *meta_function = traverseFunction(item);
|
|
254
|
AbstractMetaFunction *meta_function = traverseFunction(item);
|
|
255
|
if (meta_function != 0 && !meta_function->isInvalid()) {
|
|
255
|
if (meta_function != 0 && !meta_function->isInvalid()) {
|
|
256
|
// Strip away first argument, since that is the containing object
|
|
256
|
// Strip away first argument, since that is the containing object
|
|
257
|
AbstractMetaArgumentList arguments = meta_function->arguments();
|
|
257
|
AbstractMetaArgumentList arguments = meta_function->arguments();
|
|
258
|
arguments.pop_front();
|
|
258
|
arguments.pop_front();
|
|
259
|
meta_function->setArguments(arguments);
|
|
259
|
meta_function->setArguments(arguments);
|
|
260
|
|
|
260
|
|
|
261
|
meta_function->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
|
|
261
|
meta_function->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
|
|
262
|
|
|
262
|
|
|
263
|
meta_function->setOriginalAttributes(meta_function->attributes());
|
|
263
|
meta_function->setOriginalAttributes(meta_function->attributes());
|
|
264
|
setupFunctionDefaults(meta_function, comparer_class);
|
|
264
|
setupFunctionDefaults(meta_function, comparer_class);
|
|
265
|
|
|
265
|
|
|
266
|
comparer_class->addFunction(meta_function);
|
|
266
|
comparer_class->addFunction(meta_function);
|
|
267
|
} else if (meta_function != 0) {
|
|
267
|
} else if (meta_function != 0) {
|
|
268
|
delete meta_function;
|
|
268
|
delete meta_function;
|
|
269
|
}
|
|
269
|
}
|
|
270
|
|
|
270
|
|
|
271
|
m_current_class = old_current_class;
|
|
271
|
m_current_class = old_current_class;
|
|
272
|
}
|
|
272
|
}
|
|
273
|
}
|
|
273
|
}
|
|
274
|
}
|
|
274
|
}
|
|
275
|
|
|
275
|
|
|
276
|
void AbstractMetaBuilder::traverseStreamOperator(FunctionModelItem item)
|
|
276
|
void AbstractMetaBuilder::traverseStreamOperator(FunctionModelItem item)
|
|
277
|
{
|
|
277
|
{
|
|
278
|
ArgumentList arguments = item->arguments();
|
|
278
|
ArgumentList arguments = item->arguments();
|
|
279
|
if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
|
|
279
|
if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
|
|
280
|
AbstractMetaClass *streamClass = argumentToClass(arguments.at(0));
|
|
280
|
AbstractMetaClass *streamClass = argumentToClass(arguments.at(0));
|
|
281
|
AbstractMetaClass *streamedClass = argumentToClass(arguments.at(1));
|
|
281
|
AbstractMetaClass *streamedClass = argumentToClass(arguments.at(1));
|
|
282
|
|
|
282
|
|
|
283
|
if (streamClass != 0 && streamedClass != 0
|
|
283
|
if (streamClass != 0 && streamedClass != 0
|
|
284
|
&& (streamClass->name() == "QDataStream" || streamClass->name() == "QTextStream")) {
|
|
284
|
&& (streamClass->name() == "QDataStream" || streamClass->name() == "QTextStream")) {
|
|
285
|
AbstractMetaClass *old_current_class = m_current_class;
|
|
285
|
AbstractMetaClass *old_current_class = m_current_class;
|
|
286
|
m_current_class = streamedClass;
|
|
286
|
m_current_class = streamedClass;
|
|
287
|
AbstractMetaFunction *streamFunction = traverseFunction(item);
|
|
287
|
AbstractMetaFunction *streamFunction = traverseFunction(item);
|
|
288
|
|
|
288
|
|
|
289
|
if (streamFunction != 0 && !streamFunction->isInvalid()) {
|
|
289
|
if (streamFunction != 0 && !streamFunction->isInvalid()) {
|
|
290
|
QString name = item->name();
|
|
290
|
QString name = item->name();
|
|
291
|
streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
|
|
291
|
streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
|
|
292
|
|
|
292
|
|
|
293
|
if (name.endsWith("<<"))
|
|
293
|
if (name.endsWith("<<"))
|
|
294
|
streamFunction->setName("writeTo");
|
|
294
|
streamFunction->setName("writeTo");
|
|
295
|
else
|
|
295
|
else
|
|
296
|
streamFunction->setName("readFrom");
|
|
296
|
streamFunction->setName("readFrom");
|
|
297
|
|
|
297
|
|
|
298
|
// Strip away last argument, since that is the containing object
|
|
298
|
// Strip away last argument, since that is the containing object
|
|
299
|
AbstractMetaArgumentList arguments = streamFunction->arguments();
|
|
299
|
AbstractMetaArgumentList arguments = streamFunction->arguments();
|
|
300
|
arguments.pop_back();
|
|
300
|
arguments.pop_back();
|
|
301
|
streamFunction->setArguments(arguments);
|
|
301
|
streamFunction->setArguments(arguments);
|
|
302
|
|
|
302
|
|
|
303
|
*streamFunction += AbstractMetaAttributes::Final;
|
|
303
|
*streamFunction += AbstractMetaAttributes::Final;
|
|
304
|
*streamFunction += AbstractMetaAttributes::Public;
|
|
304
|
*streamFunction += AbstractMetaAttributes::Public;
|
|
305
|
streamFunction->setOriginalAttributes(streamFunction->attributes());
|
|
305
|
streamFunction->setOriginalAttributes(streamFunction->attributes());
|
|
306
|
|
|
306
|
|
|
307
|
streamFunction->setType(0);
|
|
307
|
streamFunction->setType(0);
|
|
308
|
|
|
308
|
|
|
309
|
setupFunctionDefaults(streamFunction, streamedClass);
|
|
309
|
setupFunctionDefaults(streamFunction, streamedClass);
|
|
310
|
|
|
310
|
|
|
311
|
streamedClass->addFunction(streamFunction);
|
|
311
|
streamedClass->addFunction(streamFunction);
|
|
312
|
streamedClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
|
|
312
|
streamedClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include());
|
|
313
|
|
|
313
|
|
|
314
|
m_current_class = old_current_class;
|
|
314
|
m_current_class = old_current_class;
|
|
315
|
}
|
|
315
|
}
|
|
316
|
}
|
|
316
|
}
|
|
317
|
}
|
|
317
|
}
|
|
318
|
}
|
|
318
|
}
|
|
319
|
|
|
319
|
|
|
320
|
void AbstractMetaBuilder::traverseBinaryArithmeticOperator(FunctionModelItem item)
|
|
320
|
void AbstractMetaBuilder::traverseBinaryArithmeticOperator(FunctionModelItem item)
|
|
321
|
{
|
|
321
|
{
|
|
322
|
ArgumentList arguments = item->arguments();
|
|
322
|
ArgumentList arguments = item->arguments();
|
|
323
|
if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
|
|
323
|
if (arguments.size() == 2 && item->accessPolicy() == CodeModel::Public) {
|
|
324
|
AbstractMetaClass *aClass = argumentToClass(arguments.at(0));
|
|
324
|
AbstractMetaClass *aClass = argumentToClass(arguments.at(0));
|
|
325
|
AbstractMetaClass *bClass = argumentToClass(arguments.at(1));
|
|
325
|
AbstractMetaClass *bClass = argumentToClass(arguments.at(1));
|
|
326
|
|
|
326
|
|
|
327
|
if (!aClass) return;
|
|
327
|
if (!aClass) return;
|
|
328
|
|
|
328
|
|
|
329
|
AbstractMetaClass *old_current_class = m_current_class;
|
|
329
|
AbstractMetaClass *old_current_class = m_current_class;
|
|
330
|
m_current_class = aClass;
|
|
330
|
m_current_class = aClass;
|
|
331
|
AbstractMetaFunction *streamFunction = traverseFunction(item);
|
|
331
|
AbstractMetaFunction *streamFunction = traverseFunction(item);
|
|
332
|
if (streamFunction != 0 && !streamFunction->isInvalid()) {
|
|
332
|
if (streamFunction != 0 && !streamFunction->isInvalid()) {
|
|
333
|
QString name = rename_operator(item->name().mid(8));
|
|
333
|
QString name = rename_operator(item->name().mid(8));
|
|
334
|
if (name.isEmpty()) return;
|
|
334
|
if (name.isEmpty()) return;
|
|
335
|
|
|
335
|
|
|
336
|
streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
|
|
336
|
streamFunction->setFunctionType(AbstractMetaFunction::GlobalScopeFunction);
|
|
337
|
streamFunction->setName(name);
|
|
337
|
streamFunction->setName(name);
|
|
338
|
|
|
338
|
|
|
339
|
// Strip away the first argument, since that is the operator object
|
|
339
|
// Strip away the first argument, since that is the operator object
|
|
340
|
AbstractMetaArgumentList arguments = streamFunction->arguments();
|
|
340
|
AbstractMetaArgumentList arguments = streamFunction->arguments();
|
|
341
|
arguments.removeFirst();
|
|
341
|
arguments.removeFirst();
|
|
342
|
streamFunction->setArguments(arguments);
|
|
342
|
streamFunction->setArguments(arguments);
|
|
343
|
|
|
343
|
|
|
344
|
*streamFunction += AbstractMetaAttributes::Final;
|
|
344
|
*streamFunction += AbstractMetaAttributes::Final;
|
|
345
|
*streamFunction += AbstractMetaAttributes::Public;
|
|
345
|
*streamFunction += AbstractMetaAttributes::Public;
|
|
346
|
streamFunction->setOriginalAttributes(streamFunction->attributes());
|
|
346
|
streamFunction->setOriginalAttributes(streamFunction->attributes());
|
|
347
|
|
|
347
|
|
|
348
|
setupFunctionDefaults(streamFunction, aClass);
|
|
348
|
setupFunctionDefaults(streamFunction, aClass);
|
|
349
|
|
|
349
|
|
|
350
|
aClass->addFunction(streamFunction);
|
|
350
|
aClass->addFunction(streamFunction);
|
|
351
|
if (bClass) {
|
|
351
|
if (bClass) {
|
|
352
|
aClass->typeEntry()->addExtraInclude(bClass->typeEntry()->include());
|
|
352
|
aClass->typeEntry()->addExtraInclude(bClass->typeEntry()->include());
|
|
353
|
}
|
|
353
|
}
|
|
354
|
|
|
354
|
|
|
355
|
m_current_class = old_current_class;
|
|
355
|
m_current_class = old_current_class;
|
|
356
|
}
|
|
356
|
}
|
|
357
|
}
|
|
357
|
}
|
|
358
|
}
|
|
358
|
}
|
|
359
|
|
|
359
|
|
|
360
|
void AbstractMetaBuilder::fixQObjectForScope(TypeDatabase *types,
|
|
360
|
void AbstractMetaBuilder::fixQObjectForScope(TypeDatabase *types,
|
|
361
|
NamespaceModelItem scope)
|
|
361
|
NamespaceModelItem scope)
|
|
362
|
{
|
|
362
|
{
|
|
363
|
foreach (ClassModelItem item, scope->classes()) {
|
|
363
|
foreach (ClassModelItem item, scope->classes()) {
|
|
364
|
QString qualified_name = item->qualifiedName().join("::");
|
|
364
|
QString qualified_name = item->qualifiedName().join("::");
|
|
365
|
TypeEntry *entry = types->findType(qualified_name);
|
|
365
|
TypeEntry *entry = types->findType(qualified_name);
|
|
366
|
if (entry) {
|
|
366
|
if (entry) {
|
|
367
|
if (isQObject(qualified_name) && entry->isComplex()) {
|
|
367
|
if (isQObject(qualified_name) && entry->isComplex()) {
|
|
368
|
((ComplexTypeEntry *) entry)->setQObject(true);
|
|
368
|
((ComplexTypeEntry *) entry)->setQObject(true);
|
|
369
|
}
|
|
369
|
}
|
|
370
|
}
|
|
370
|
}
|
|
371
|
}
|
|
371
|
}
|
|
372
|
|
|
372
|
|
|
373
|
foreach (NamespaceModelItem item, scope->namespaceMap().values()) {
|
|
373
|
foreach (NamespaceModelItem item, scope->namespaceMap().values()) {
|
|
374
|
if (scope != item)
|
|
374
|
if (scope != item)
|
|
375
|
fixQObjectForScope(types, item);
|
|
375
|
fixQObjectForScope(types, item);
|
|
376
|
}
|
|
376
|
}
|
|
377
|
}
|
|
377
|
}
|
|
378
|
|
|
378
|
|
|
379
|
static bool class_less_than(AbstractMetaClass *a, AbstractMetaClass *b)
|
|
379
|
static bool class_less_than(AbstractMetaClass *a, AbstractMetaClass *b)
|
|
380
|
{
|
|
380
|
{
|
|
381
|
return a->name() < b->name();
|
|
381
|
return a->name() < b->name();
|
|
382
|
}
|
|
382
|
}
|
|
383
|
|
|
383
|
|
|
384
|
|
|
384
|
|
|
385
|
void AbstractMetaBuilder::sortLists()
|
|
385
|
void AbstractMetaBuilder::sortLists()
|
|
386
|
{
|
|
386
|
{
|
|
387
|
qSort(m_meta_classes.begin(), m_meta_classes.end(), class_less_than);
|
|
387
|
qSort(m_meta_classes.begin(), m_meta_classes.end(), class_less_than);
|
|
388
|
foreach (AbstractMetaClass *cls, m_meta_classes) {
|
|
388
|
foreach (AbstractMetaClass *cls, m_meta_classes) {
|
|
389
|
cls->sortFunctions();
|
|
389
|
cls->sortFunctions();
|
|
390
|
}
|
|
390
|
}
|
|
391
|
}
|
|
391
|
}
|
|
392
|
|
|
392
|
|
|
393
|
bool AbstractMetaBuilder::build()
|
|
393
|
bool AbstractMetaBuilder::build()
|
|
394
|
{
|
|
394
|
{
|
|
395
|
Q_ASSERT(!m_file_name.isEmpty());
|
|
395
|
Q_ASSERT(!m_file_name.isEmpty());
|
|
396
|
|
|
396
|
|
|
397
|
QFile file(m_file_name);
|
|
397
|
QFile file(m_file_name);
|
|
398
|
|
|
398
|
|
|
399
|
if (!file.open(QFile::ReadOnly))
|
|
399
|
if (!file.open(QFile::ReadOnly))
|
|
400
|
return false;
|
|
400
|
return false;
|
|
401
|
|
|
401
|
|
|
402
|
QTextStream stream(&file);
|
|
402
|
QTextStream stream(&file);
|
|
403
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
|
403
|
stream.setCodec(QTextCodec::codecForName("UTF-8"));
|
|
404
|
QByteArray contents = stream.readAll().toUtf8();
|
|
404
|
QByteArray contents = stream.readAll().toUtf8();
|
|
405
|
file.close();
|
|
405
|
file.close();
|
|
406
|
|
|
406
|
|
|
407
|
Control control;
|
|
407
|
Control control;
|
|
408
|
Parser p(&control);
|
|
408
|
Parser p(&control);
|
|
409
|
pool __pool;
|
|
409
|
pool __pool;
|
|
410
|
|
|
410
|
|
|
411
|
TranslationUnitAST *ast = p.parse(contents, contents.size(), &__pool);
|
|
411
|
TranslationUnitAST *ast = p.parse(contents, contents.size(), &__pool);
|
|
412
|
|
|
412
|
|
|
413
|
CodeModel model;
|
|
413
|
CodeModel model;
|
|
414
|
Binder binder(&model, p.location());
|
|
414
|
Binder binder(&model, p.location());
|
|
415
|
m_dom = binder.run(ast);
|
|
415
|
m_dom = binder.run(ast);
|
|
416
|
|
|
416
|
|
|
417
|
pushScope(model_dynamic_cast<ScopeModelItem>(m_dom));
|
|
417
|
pushScope(model_dynamic_cast<ScopeModelItem>(m_dom));
|
|
418
|
|
|
418
|
|
|
419
|
QHash<QString, ClassModelItem> typeMap = m_dom->classMap();
|
|
419
|
QHash<QString, ClassModelItem> typeMap = m_dom->classMap();
|
|
420
|
|
|
420
|
|
|
421
|
|
|
421
|
|
|
422
|
// fix up QObject's in the type system..
|
|
422
|
// fix up QObject's in the type system..
|
|
423
|
TypeDatabase *types = TypeDatabase::instance();
|
|
423
|
TypeDatabase *types = TypeDatabase::instance();
|
|
424
|
fixQObjectForScope(types, model_dynamic_cast<NamespaceModelItem>(m_dom));
|
|
424
|
fixQObjectForScope(types, model_dynamic_cast<NamespaceModelItem>(m_dom));
|
|
425
|
|
|
425
|
|
|
426
|
|
|
426
|
|
|
427
|
// Start the generation...
|
|
427
|
// Start the generation...
|
|
428
|
foreach (ClassModelItem item, typeMap.values()) {
|
|
428
|
foreach (ClassModelItem item, typeMap.values()) {
|
|
429
|
AbstractMetaClass *cls = traverseClass(item);
|
|
429
|
AbstractMetaClass *cls = traverseClass(item);
|
|
430
|
addAbstractMetaClass(cls);
|
|
430
|
addAbstractMetaClass(cls);
|
|
431
|
}
|
|
431
|
}
|
|
432
|
|
|
432
|
|
|
433
|
|
|
433
|
|
|
434
|
QHash<QString, NamespaceModelItem> namespaceMap = m_dom->namespaceMap();
|
|
434
|
QHash<QString, NamespaceModelItem> namespaceMap = m_dom->namespaceMap();
|
|
435
|
foreach (NamespaceModelItem item, namespaceMap.values()) {
|
|
435
|
foreach (NamespaceModelItem item, namespaceMap.values()) {
|
|
436
|
AbstractMetaClass *meta_class = traverseNamespace(item);
|
|
436
|
AbstractMetaClass *meta_class = traverseNamespace(item);
|
|
437
|
if (meta_class)
|
|
437
|
if (meta_class)
|
|
438
|
m_meta_classes << meta_class;
|
|
438
|
m_meta_classes << meta_class;
|
|
439
|
}
|
|
439
|
}
|
|
440
|
|
|
440
|
|
|
441
|
|
|
441
|
|
|
442
|
// Some trickery to support global-namespace enums...
|
|
442
|
// Some trickery to support global-namespace enums...
|
|
443
|
QHash<QString, EnumModelItem> enumMap = m_dom->enumMap();
|
|
443
|
QHash<QString, EnumModelItem> enumMap = m_dom->enumMap();
|
|
444
|
m_current_class = 0;
|
|
444
|
m_current_class = 0;
|
|
445
|
foreach (EnumModelItem item, enumMap) {
|
|
445
|
foreach (EnumModelItem item, enumMap) {
|
|
446
|
AbstractMetaEnum *meta_enum = traverseEnum(item, 0, QSet<QString>());
|
|
446
|
AbstractMetaEnum *meta_enum = traverseEnum(item, 0, QSet<QString>());
|
|
447
|
|
|
447
|
|
|
448
|
if (meta_enum) {
|
|
448
|
if (meta_enum) {
|
|
449
|
QString package = meta_enum->typeEntry()->javaPackage();
|
|
449
|
QString package = meta_enum->typeEntry()->javaPackage();
|
|
450
|
QString globalName = TypeDatabase::globalNamespaceClassName(meta_enum->typeEntry());
|
|
450
|
QString globalName = TypeDatabase::globalNamespaceClassName(meta_enum->typeEntry());
|
|
451
|
|
|
451
|
|
|
452
|
AbstractMetaClass *global = m_meta_classes.findClass(package + "." + globalName);
|
|
452
|
AbstractMetaClass *global = m_meta_classes.findClass(package + "." + globalName);
|
|
453
|
if (!global) {
|
|
453
|
if (!global) {
|
|
454
|
ComplexTypeEntry *gte = new ObjectTypeEntry(globalName);
|
|
454
|
ComplexTypeEntry *gte = new ObjectTypeEntry(globalName);
|
|
455
|
gte->setTargetLangPackage(meta_enum->typeEntry()->javaPackage());
|
|
455
|
gte->setTargetLangPackage(meta_enum->typeEntry()->javaPackage());
|
|
456
|
gte->setCodeGeneration(meta_enum->typeEntry()->codeGeneration());
|
|
456
|
gte->setCodeGeneration(meta_enum->typeEntry()->codeGeneration());
|
|
457
|
global = createMetaClass();
|
|
457
|
global = createMetaClass();
|
|
458
|
global->setTypeEntry(gte);
|
|
458
|
global->setTypeEntry(gte);
|
|
459
|
*global += AbstractMetaAttributes::Final;
|
|
459
|
*global += AbstractMetaAttributes::Final;
|
|
460
|
*global += AbstractMetaAttributes::Public;
|
|
460
|
*global += AbstractMetaAttributes::Public;
|
|
461
|
*global += AbstractMetaAttributes::Fake;
|
|
461
|
*global += AbstractMetaAttributes::Fake;
|
|
462
|
|
|
462
|
|
|
463
|
m_meta_classes << global;
|
|
463
|
m_meta_classes << global;
|
|
464
|
}
|
|
464
|
}
|
|
465
|
|
|
465
|
|
|
466
|
global->addEnum(meta_enum);
|
|
466
|
global->addEnum(meta_enum);
|
|
467
|
meta_enum->setEnclosingClass(global);
|
|
467
|
meta_enum->setEnclosingClass(global);
|
|
468
|
meta_enum->typeEntry()->setQualifier(globalName);
|
|
468
|
meta_enum->typeEntry()->setQualifier(globalName);
|
|
469
|
|
|
469
|
|
|
470
|
// Global enums should be public despite not having public
|
|
470
|
// Global enums should be public despite not having public
|
|
471
|
// identifiers so we'll fix the original attributes here.
|
|
471
|
// identifiers so we'll fix the original attributes here.
|
|
472
|
meta_enum->setOriginalAttributes(meta_enum->attributes());
|
|
472
|
meta_enum->setOriginalAttributes(meta_enum->attributes());
|
|
473
|
}
|
|
473
|
}
|
|
474
|
|
|
474
|
|
|
475
|
|
|
475
|
|
|
476
|
}
|
|
476
|
}
|
|
477
|
|
|
477
|
|
|
478
|
|
|
478
|
|
|
479
|
// Go through all typedefs to see if we have defined any
|
|
479
|
// Go through all typedefs to see if we have defined any
|
|
480
|
// specific typedefs to be used as classes.
|
|
480
|
// specific typedefs to be used as classes.
|
|
481
|
TypeAliasList typeAliases = m_dom->typeAliases();
|
|
481
|
TypeAliasList typeAliases = m_dom->typeAliases();
|
|
482
|
foreach (TypeAliasModelItem typeAlias, typeAliases) {
|
|
482
|
foreach (TypeAliasModelItem typeAlias, typeAliases) {
|
|
483
|
AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
|
|
483
|
AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
|
|
484
|
addAbstractMetaClass(cls);
|
|
484
|
addAbstractMetaClass(cls);
|
|
485
|
}
|
|
485
|
}
|
|
486
|
|
|
486
|
|
|
487
|
|
|
487
|
|
|
488
|
|
|
488
|
|
|
489
|
|
|
489
|
|
|
490
|
foreach (AbstractMetaClass *cls, m_meta_classes) {
|
|
490
|
foreach (AbstractMetaClass *cls, m_meta_classes) {
|
|
491
|
if (!cls->isInterface() && !cls->isNamespace()) {
|
|
491
|
if (!cls->isInterface() && !cls->isNamespace()) {
|
|
492
|
setupInheritance(cls);
|
|
492
|
setupInheritance(cls);
|
|
493
|
}
|
|
493
|
}
|
|
494
|
}
|
|
494
|
}
|
|
495
|
|
|
495
|
|
|
496
|
|
|
496
|
|
|
497
|
foreach (AbstractMetaClass *cls, m_meta_classes) {
|
|
497
|
foreach (AbstractMetaClass *cls, m_meta_classes) {
|
|
498
|
cls->fixFunctions();
|
|
498
|
cls->fixFunctions();
|
|
499
|
|
|
499
|
|
|
500
|
if (cls->typeEntry() == 0) {
|
|
500
|
if (cls->typeEntry() == 0) {
|
|
501
|
ReportHandler::warning(QString("class '%1' does not have an entry in the type system")
|
|
501
|
ReportHandler::warning(QString("class '%1' does not have an entry in the type system")
|
|
502
|
.arg(cls->name()));
|
|
502
|
.arg(cls->name()));
|
|
503
|
} else {
|
|
503
|
} else {
|
|
504
|
if (!cls->hasConstructors() && !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace())
|
|
504
|
if (!cls->hasConstructors() && !cls->isFinalInCpp() && !cls->isInterface() && !cls->isNamespace())
|
|
505
|
cls->addDefaultConstructor();
|
|
505
|
cls->addDefaultConstructor();
|
|
506
|
}
|
|
506
|
}
|
|
507
|
|
|
507
|
|
|
508
|
if (cls->isAbstract() && !cls->isInterface()) {
|
|
508
|
if (cls->isAbstract() && !cls->isInterface()) {
|
|
509
|
cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + "$ConcreteWrapper");
|
|
509
|
cls->typeEntry()->setLookupName(cls->typeEntry()->targetLangName() + "$ConcreteWrapper");
|
|
510
|
}
|
|
510
|
}
|
|
511
|
}
|
|
511
|
}
|
|
512
|
|
|
512
|
|
|
513
|
QList<TypeEntry *> entries = TypeDatabase::instance()->entries().values();
|
|
513
|
QList<TypeEntry *> entries = TypeDatabase::instance()->entries().values();
|
|
514
|
foreach (const TypeEntry *entry, entries) {
|
|
514
|
foreach (const TypeEntry *entry, entries) {
|
|
515
|
if (entry->isPrimitive())
|
|
515
|
if (entry->isPrimitive())
|
|
516
|
continue;
|
|
516
|
continue;
|
|
517
|
|
|
517
|
|
|
518
|
if ((entry->isValue() || entry->isObject())
|
|
518
|
if ((entry->isValue() || entry->isObject())
|
|
519
|
&& !entry->isString()
|
|
519
|
&& !entry->isString()
|
|
520
|
&& !entry->isChar()
|
|
520
|
&& !entry->isChar()
|
|
521
|
&& !entry->isContainer()
|
|
521
|
&& !entry->isContainer()
|
|
522
|
&& !entry->isCustom()
|
|
522
|
&& !entry->isCustom()
|
|
523
|
&& !entry->isVariant()
|
|
523
|
&& !entry->isVariant()
|
|
524
|
&& !m_meta_classes.findClass(entry->qualifiedCppName())) {
|
|
524
|
&& !m_meta_classes.findClass(entry->qualifiedCppName())) {
|
|
525
|
ReportHandler::warning(QString("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
|
|
525
|
ReportHandler::warning(QString("type '%1' is specified in typesystem, but not defined. This could potentially lead to compilation errors.")
|
|
526
|
.arg(entry->qualifiedCppName()));
|
|
526
|
.arg(entry->qualifiedCppName()));
|
|
527
|
}
|
|
527
|
}
|
|
528
|
|
|
528
|
|
|
529
|
if (entry->isEnum()) {
|
|
529
|
if (entry->isEnum()) {
|
|
530
|
QString pkg = entry->javaPackage();
|
|
530
|
QString pkg = entry->javaPackage();
|
|
531
|
QString name = (pkg.isEmpty() ? QString() : pkg + ".")
|
|
531
|
QString name = (pkg.isEmpty() ? QString() : pkg + ".")
|
|
532
|
+ ((EnumTypeEntry *) entry)->javaQualifier();
|
|
532
|
+ ((EnumTypeEntry *) entry)->javaQualifier();
|
|
533
|
AbstractMetaClass *cls = m_meta_classes.findClass(name);
|
|
533
|
AbstractMetaClass *cls = m_meta_classes.findClass(name);
|
|
534
|
|
|
534
|
|
|
535
|
if (!cls) {
|
|
535
|
if (!cls) {
|
|
536
|
ReportHandler::warning(QString("namespace '%1' for enum '%2' is not declared")
|
|
536
|
ReportHandler::warning(QString("namespace '%1' for enum '%2' is not declared")
|
|
537
|
.arg(name).arg(entry->targetLangName()));
|
|
537
|
.arg(name).arg(entry->targetLangName()));
|
|
538
|
} else {
|
|
538
|
} else {
|
|
539
|
AbstractMetaEnum *e = cls->findEnum(entry->targetLangName());
|
|
539
|
AbstractMetaEnum *e = cls->findEnum(entry->targetLangName());
|
|
540
|
if (!e)
|
|
540
|
if (!e)
|
|
541
|
ReportHandler::warning(QString("enum '%1' is specified in typesystem, "
|
|
541
|
ReportHandler::warning(QString("enum '%1' is specified in typesystem, "
|
|
542
|
"but not declared")
|
|
542
|
"but not declared")
|
|
543
|
.arg(entry->qualifiedCppName()));
|
|
543
|
.arg(entry->qualifiedCppName()));
|
|
544
|
}
|
|
544
|
}
|
|
545
|
}
|
|
545
|
}
|
|
546
|
}
|
|
546
|
}
|
|
547
|
|
|
547
|
|
|
548
|
{
|
|
548
|
{
|
|
549
|
FunctionList hash_functions = m_dom->findFunctions("qHash");
|
|
549
|
FunctionList hash_functions = m_dom->findFunctions("qHash");
|
|
550
|
foreach (FunctionModelItem item, hash_functions) {
|
|
550
|
foreach (FunctionModelItem item, hash_functions) {
|
|
551
|
registerHashFunction(item);
|
|
551
|
registerHashFunction(item);
|
|
552
|
}
|
|
552
|
}
|
|
553
|
}
|
|
553
|
}
|
|
554
|
|
|
554
|
|
|
555
|
{
|
|
555
|
{
|
|
556
|
FunctionList hash_functions = m_dom->findFunctions("operator<<");
|
|
556
|
FunctionList hash_functions = m_dom->findFunctions("operator<<");
|
|
557
|
foreach (FunctionModelItem item, hash_functions) {
|
|
557
|
foreach (FunctionModelItem item, hash_functions) {
|
|
558
|
registerToStringCapability(item);
|
|
558
|
registerToStringCapability(item);
|
|
559
|
}
|
|
559
|
}
|
|
560
|
}
|
|
560
|
}
|
|
561
|
|
|
561
|
|
|
562
|
{
|
|
562
|
{
|
|
563
|
FunctionList compare_operators = m_dom->findFunctions("operator==")
|
|
563
|
FunctionList compare_operators = m_dom->findFunctions("operator==")
|
|
564
|
+ m_dom->findFunctions("operator<=")
|
|
564
|
+ m_dom->findFunctions("operator<=")
|
|
565
|
+ m_dom->findFunctions("operator>=")
|
|
565
|
+ m_dom->findFunctions("operator>=")
|
|
566
|
+ m_dom->findFunctions("operator<")
|
|
566
|
+ m_dom->findFunctions("operator<")
|
|
567
|
+ m_dom->findFunctions("operator>");
|
|
567
|
+ m_dom->findFunctions("operator>");
|
|
568
|
foreach (FunctionModelItem item, compare_operators) {
|
|
568
|
foreach (FunctionModelItem item, compare_operators) {
|
|
569
|
traverseCompareOperator(item);
|
|
569
|
traverseCompareOperator(item);
|
|
570
|
}
|
|
570
|
}
|
|
571
|
}
|
|
571
|
}
|
|
572
|
|
|
572
|
|
|
573
|
{
|
|
573
|
{
|
|
574
|
FunctionList stream_operators =
|
|
574
|
FunctionList stream_operators =
|
|
575
|
m_dom->findFunctions("operator+") + m_dom->findFunctions("operator-")
|
|
575
|
m_dom->findFunctions("operator+") + m_dom->findFunctions("operator-")
|
|
576
|
+ m_dom->findFunctions("operator/") + m_dom->findFunctions("operator*")
|
|
576
|
+ m_dom->findFunctions("operator/") + m_dom->findFunctions("operator*")
|
|
577
|
+ m_dom->findFunctions("operator&") + m_dom->findFunctions("operator|")
|
|
577
|
+ m_dom->findFunctions("operator&") + m_dom->findFunctions("operator|")
|
|
578
|
+ m_dom->findFunctions("operator%") + m_dom->findFunctions("operator^");
|
|
578
|
+ m_dom->findFunctions("operator%") + m_dom->findFunctions("operator^");
|
|
579
|
foreach (FunctionModelItem item, stream_operators) {
|
|
579
|
foreach (FunctionModelItem item, stream_operators) {
|
|
580
|
traverseBinaryArithmeticOperator(item);
|
|
580
|
traverseBinaryArithmeticOperator(item);
|
|
581
|
}
|
|
581
|
}
|
|
582
|
}
|
|
582
|
}
|
|
583
|
{
|
|
583
|
{
|
|
584
|
FunctionList stream_operators = m_dom->findFunctions("operator<<") + m_dom->findFunctions("operator>>");
|
|
584
|
FunctionList stream_operators = m_dom->findFunctions("operator<<") + m_dom->findFunctions("operator>>");
|
|
585
|
foreach (FunctionModelItem item, stream_operators) {
|
|
585
|
foreach (FunctionModelItem item, stream_operators) {
|
|
586
|
traverseStreamOperator(item);
|
|
586
|
traverseStreamOperator(item);
|
|
587
|
}
|
|
587
|
}
|
|
588
|
}
|
|
588
|
}
|
|
589
|
|
|
589
|
|
|
590
|
figureOutEnumValues();
|
|
590
|
figureOutEnumValues();
|
|
591
|
figureOutDefaultEnumArguments();
|
|
591
|
figureOutDefaultEnumArguments();
|
|
592
|
checkFunctionModifications();
|
|
592
|
checkFunctionModifications();
|
|
593
|
|
|
593
|
|
|
594
|
foreach (AbstractMetaClass *cls, m_meta_classes) {
|
|
594
|
foreach (AbstractMetaClass *cls, m_meta_classes) {
|
|
595
|
setupEquals(cls);
|
|
595
|
setupEquals(cls);
|
|
596
|
setupComparable(cls);
|
|
596
|
setupComparable(cls);
|
|
597
|
setupClonable(cls);
|
|
597
|
setupClonable(cls);
|
|
598
|
}
|
|
598
|
}
|
|
599
|
|
|
599
|
|
|
600
|
dumpLog();
|
|
600
|
dumpLog();
|
|
601
|
|
|
601
|
|
|
602
|
sortLists();
|
|
602
|
sortLists();
|
|
603
|
|
|
603
|
|
|
604
|
return true;
|
|
604
|
return true;
|
|
605
|
}
|
|
605
|
}
|
|
606
|
|
|
606
|
|
|
607
|
|
|
607
|
|
|
608
|
void AbstractMetaBuilder::addAbstractMetaClass(AbstractMetaClass *cls)
|
|
608
|
void AbstractMetaBuilder::addAbstractMetaClass(AbstractMetaClass *cls)
|
|
609
|
{
|
|
609
|
{
|
|
610
|
if (!cls)
|
|
610
|
if (!cls)
|
|
611
|
return;
|
|
611
|
return;
|
|
612
|
|
|
612
|
|
|
613
|
cls->setOriginalAttributes(cls->attributes());
|
|
613
|
cls->setOriginalAttributes(cls->attributes());
|
|
614
|
if (cls->typeEntry()->isContainer()) {
|
|
614
|
if (cls->typeEntry()->isContainer()) {
|
|
615
|
m_templates << cls;
|
|
615
|
m_templates << cls;
|
|
616
|
} else {
|
|
616
|
} else {
|
|
617
|
m_meta_classes << cls;
|
|
617
|
m_meta_classes << cls;
|
|
618
|
if (cls->typeEntry()->designatedInterface()) {
|
|
618
|
if (cls->typeEntry()->designatedInterface()) {
|
|
619
|
AbstractMetaClass *interface = cls->extractInterface();
|
|
619
|
AbstractMetaClass *interface = cls->extractInterface();
|
|
620
|
m_meta_classes << interface;
|
|
620
|
m_meta_classes << interface;
|
|
621
|
ReportHandler::debugSparse(QString(" -> interface '%1'").arg(interface->name()));
|
|
621
|
ReportHandler::debugSparse(QString(" -> interface '%1'").arg(interface->name()));
|
|
622
|
}
|
|
622
|
}
|
|
623
|
}
|
|
623
|
}
|
|
624
|
}
|
|
624
|
}
|
|
625
|
|
|
625
|
|
|
626
|
|
|
626
|
|
|
627
|
AbstractMetaClass *AbstractMetaBuilder::traverseNamespace(NamespaceModelItem namespace_item)
|
|
627
|
AbstractMetaClass *AbstractMetaBuilder::traverseNamespace(NamespaceModelItem namespace_item)
|
|
628
|
{
|
|
628
|
{
|
|
629
|
QString namespace_name = (!m_namespace_prefix.isEmpty() ? m_namespace_prefix + "::" : QString()) + namespace_item->name();
|
|
629
|
QString namespace_name = (!m_namespace_prefix.isEmpty() ? m_namespace_prefix + "::" : QString()) + namespace_item->name();
|
|
630
|
NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespace_name);
|
|
630
|
NamespaceTypeEntry *type = TypeDatabase::instance()->findNamespaceType(namespace_name);
|
|
631
|
|
|
631
|
|
|
632
|
if (TypeDatabase::instance()->isClassRejected(namespace_name)) {
|
|
632
|
if (TypeDatabase::instance()->isClassRejected(namespace_name)) {
|
|
633
|
m_rejected_classes.insert(namespace_name, GenerationDisabled);
|
|
633
|
m_rejected_classes.insert(namespace_name, GenerationDisabled);
|
|
634
|
return 0;
|
|
634
|
return 0;
|
|
635
|
}
|
|
635
|
}
|
|
636
|
|
|
636
|
|
|
637
|
if (!type) {
|
|
637
|
if (!type) {
|
|
638
|
ReportHandler::warning(QString("namespace '%1' does not have a type entry")
|
|
638
|
ReportHandler::warning(QString("namespace '%1' does not have a type entry")
|
|
639
|
.arg(namespace_name));
|
|
639
|
.arg(namespace_name));
|
|
640
|
return 0;
|
|
640
|
return 0;
|
|
641
|
}
|
|
641
|
}
|
|
642
|
|
|
642
|
|
|
643
|
AbstractMetaClass *meta_class = createMetaClass();
|
|
643
|
AbstractMetaClass *meta_class = createMetaClass();
|
|
644
|
meta_class->setTypeEntry(type);
|
|
644
|
meta_class->setTypeEntry(type);
|
|
645
|
|
|
645
|
|
|
646
|
*meta_class += AbstractMetaAttributes::Public;
|
|
646
|
*meta_class += AbstractMetaAttributes::Public;
|
|
647
|
|
|
647
|
|
|
648
|
m_current_class = meta_class;
|
|
648
|
m_current_class = meta_class;
|
|
649
|
|
|
649
|
|
|
650
|
ReportHandler::debugSparse(QString("namespace '%1.%2'")
|
|
650
|
ReportHandler::debugSparse(QString("namespace '%1.%2'")
|
|
651
|
.arg(meta_class->package())
|
|
651
|
.arg(meta_class->package())
|
|
652
|
.arg(namespace_item->name()));
|
|
652
|
.arg(namespace_item->name()));
|
|
653
|
|
|
653
|
|
|
654
|
traverseEnums(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class, namespace_item->enumsDeclarations());
|
|
654
|
traverseEnums(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class, namespace_item->enumsDeclarations());
|
|
655
|
traverseFunctions(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class);
|
|
655
|
traverseFunctions(model_dynamic_cast<ScopeModelItem>(namespace_item), meta_class);
|
|
656
|
// traverseClasses(model_dynamic_cast<ScopeModelItem>(namespace_item));
|
|
656
|
// traverseClasses(model_dynamic_cast<ScopeModelItem>(namespace_item));
|
|
657
|
|
|
657
|
|
|
658
|
pushScope(model_dynamic_cast<ScopeModelItem>(namespace_item));
|
|
658
|
pushScope(model_dynamic_cast<ScopeModelItem>(namespace_item));
|
|
659
|
m_namespace_prefix = currentScope()->qualifiedName().join("::");
|
|
659
|
m_namespace_prefix = currentScope()->qualifiedName().join("::");
|
|
660
|
|
|
660
|
|
|
661
|
|
|
661
|
|
|
662
|
ClassList classes = namespace_item->classes();
|
|
662
|
ClassList classes = namespace_item->classes();
|
|
663
|
foreach (ClassModelItem cls, classes) {
|
|
663
|
foreach (ClassModelItem cls, classes) {
|
|
664
|
AbstractMetaClass *mjc = traverseClass(cls);
|
|
664
|
AbstractMetaClass *mjc = traverseClass(cls);
|
|
665
|
addAbstractMetaClass(mjc);
|
|
665
|
addAbstractMetaClass(mjc);
|
|
666
|
}
|
|
666
|
}
|
|
667
|
|
|
667
|
|
|
668
|
// Go through all typedefs to see if we have defined any
|
|
668
|
// Go through all typedefs to see if we have defined any
|
|
669
|
// specific typedefs to be used as classes.
|
|
669
|
// specific typedefs to be used as classes.
|
|
670
|
TypeAliasList typeAliases = namespace_item->typeAliases();
|
|
670
|
TypeAliasList typeAliases = namespace_item->typeAliases();
|
|
671
|
foreach (TypeAliasModelItem typeAlias, typeAliases) {
|
|
671
|
foreach (TypeAliasModelItem typeAlias, typeAliases) {
|
|
672
|
AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
|
|
672
|
AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
|
|
673
|
addAbstractMetaClass(cls);
|
|
673
|
addAbstractMetaClass(cls);
|
|
674
|
}
|
|
674
|
}
|
|
675
|
|
|
675
|
|
|
676
|
|
|
676
|
|
|
677
|
|
|
677
|
|
|
678
|
// Traverse namespaces recursively
|
|
678
|
// Traverse namespaces recursively
|
|
679
|
QList<NamespaceModelItem> inner_namespaces = namespace_item->namespaceMap().values();
|
|
679
|
QList<NamespaceModelItem> inner_namespaces = namespace_item->namespaceMap().values();
|
|
680
|
foreach (const NamespaceModelItem &ni, inner_namespaces) {
|
|
680
|
foreach (const NamespaceModelItem &ni, inner_namespaces) {
|
|
681
|
AbstractMetaClass *mjc = traverseNamespace(ni);
|
|
681
|
AbstractMetaClass *mjc = traverseNamespace(ni);
|
|
682
|
addAbstractMetaClass(mjc);
|
|
682
|
addAbstractMetaClass(mjc);
|
|
683
|
}
|
|
683
|
}
|
|
684
|
|
|
684
|
|
|
685
|
m_current_class = 0;
|
|
685
|
m_current_class = 0;
|
|
686
|
|
|
686
|
|
|
687
|
|
|
687
|
|
|
688
|
popScope();
|
|
688
|
popScope();
|
|
689
|
m_namespace_prefix = currentScope()->qualifiedName().join("::");
|
|
689
|
m_namespace_prefix = currentScope()->qualifiedName().join("::");
|
|
690
|
|
|
690
|
|
|
691
|
if (!type->include().isValid()) {
|
|
691
|
if (!type->include().isValid()) {
|
|
692
|
QFileInfo info(namespace_item->fileName());
|
|
692
|
QFileInfo info(namespace_item->fileName());
|
|
693
|
type->setInclude(Include(Include::IncludePath, info.fileName()));
|
|
693
|
type->setInclude(Include(Include::IncludePath, info.fileName()));
|
|
694
|
}
|
|
694
|
}
|
|
695
|
|
|
695
|
|
|
696
|
return meta_class;
|
|
696
|
return meta_class;
|
|
697
|
}
|
|
697
|
}
|
|
698
|
|
|
698
|
|
|
699
|
struct Operator
|
|
699
|
struct Operator
|
|
700
|
{
|
|
700
|
{
|
|
701
|
enum Type { Plus, ShiftLeft, None };
|
|
701
|
enum Type { Plus, ShiftLeft, None };
|
|
702
|
|
|
702
|
|
|
703
|
Operator() : type(None) { }
|
|
703
|
Operator() : type(None) { }
|
|
704
|
|
|
704
|
|
|
705
|
int calculate(int x) {
|
|
705
|
int calculate(int x) {
|
|
706
|
switch (type) {
|
|
706
|
switch (type) {
|
|
707
|
case Plus: return x + value;
|
|
707
|
case Plus: return x + value;
|
|
708
|
case ShiftLeft: return x << value;
|
|
708
|
case ShiftLeft: return x << value;
|
|
709
|
case None: return x;
|
|
709
|
case None: return x;
|
|
710
|
}
|
|
710
|
}
|
|
711
|
return x;
|
|
711
|
return x;
|
|
712
|
}
|
|
712
|
}
|
|
713
|
|
|
713
|
|
|
714
|
Type type;
|
|
714
|
Type type;
|
|
715
|
int value;
|
|
715
|
int value;
|
|
716
|
};
|
|
716
|
};
|
|
717
|
|
|
717
|
|
|
718
|
|
|
718
|
|
|
719
|
|
|
719
|
|
|
720
|
Operator findOperator(QString *s) {
|
|
720
|
Operator findOperator(QString *s) {
|
|
721
|
const char *names[] = {
|
|
721
|
const char *names[] = {
|
|
722
|
"+",
|
|
722
|
"+",
|
|
723
|
"<<"
|
|
723
|
"<<"
|
|
724
|
};
|
|
724
|
};
|
|
725
|
|
|
725
|
|
|
726
|
for (int i=0; i<Operator::None; ++i) {
|
|
726
|
for (int i=0; i<Operator::None; ++i) {
|
|
727
|
QString name = QLatin1String(names[i]);
|
|
727
|
QString name = QLatin1String(names[i]);
|
|
728
|
QString str = *s;
|
|
728
|
QString str = *s;
|
|
729
|
int splitPoint = str.indexOf(name);
|
|
729
|
int splitPoint = str.indexOf(name);
|
|
730
|
if (splitPoint > 0) {
|
|
730
|
if (splitPoint > 0) {
|
|
731
|
bool ok;
|
|
731
|
bool ok;
|
|
732
|
QString right = str.mid(splitPoint + name.length());
|
|
732
|
QString right = str.mid(splitPoint + name.length());
|
|
733
|
Operator op;
|
|
733
|
Operator op;
|
|
734
|
op.value = right.toInt(&ok);
|
|
734
|
op.value = right.toInt(&ok);
|
|
735
|
if (ok) {
|
|
735
|
if (ok) {
|
|
736
|
op.type = Operator::Type(i);
|
|
736
|
op.type = Operator::Type(i);
|
|
737
|
*s = str.left(splitPoint).trimmed();
|
|
737
|
*s = str.left(splitPoint).trimmed();
|
|
738
|
return op;
|
|
738
|
return op;
|
|
739
|
}
|
|
739
|
}
|
|
740
|
}
|
|
740
|
}
|
|
741
|
}
|
|
741
|
}
|
|
742
|
return Operator();
|
|
742
|
return Operator();
|
|
743
|
}
|
|
743
|
}
|
|
744
|
|
|
744
|
|
|
745
|
int AbstractMetaBuilder::figureOutEnumValue(const QString &stringValue,
|
|
745
|
int AbstractMetaBuilder::figureOutEnumValue(const QString &stringValue,
|
|
746
|
int oldValuevalue,
|
|
746
|
int oldValuevalue,
|
|
747
|
AbstractMetaEnum *meta_enum,
|
|
747
|
AbstractMetaEnum *meta_enum,
|
|
748
|
AbstractMetaFunction *meta_function)
|
|
748
|
AbstractMetaFunction *meta_function)
|
|
749
|
{
|
|
749
|
{
|
|
750
|
if (stringValue.isEmpty())
|
|
750
|
if (stringValue.isEmpty())
|
|
751
|
return oldValuevalue;
|
|
751
|
return oldValuevalue;
|
|
752
|
|
|
752
|
|
|
753
|
QStringList stringValues = stringValue.split("|");
|
|
753
|
QStringList stringValues = stringValue.split("|");
|
|
754
|
|
|
754
|
|
|
755
|
int returnValue = 0;
|
|
755
|
int returnValue = 0;
|
|
756
|
|
|
756
|
|
|
757
|
bool matched = false;
|
|
757
|
bool matched = false;
|
|
758
|
|
|
758
|
|
|
759
|
for (int i=0; i<stringValues.size(); ++i) {
|
|
759
|
for (int i=0; i<stringValues.size(); ++i) {
|
|
760
|
QString s = stringValues.at(i).trimmed();
|
|
760
|
QString s = stringValues.at(i).trimmed();
|
|
761
|
|
|
761
|
|
|
762
|
bool ok;
|
|
762
|
bool ok;
|
|
763
|
int v;
|
|
763
|
int v;
|
|
764
|
|
|
764
|
|
|
765
|
Operator op = findOperator(&s);
|
|
765
|
Operator op = findOperator(&s);
|
|
766
|
|
|
766
|
|
|
767
|
if (s.length() > 0 && s.at(0) == QLatin1Char('0'))
|
|
767
|
if (s.length() > 0 && s.at(0) == QLatin1Char('0'))
|
|
768
|
v = s.toUInt(&ok, 0);
|
|
768
|
v = s.toUInt(&ok, 0);
|
|
769
|
else
|
|
769
|
else
|
|
770
|
v = s.toInt(&ok);
|
|
770
|
v = s.toInt(&ok);
|
|
771
|
|
|
771
|
|
|
772
|
if (ok) {
|
|
772
|
if (ok) {
|
|
773
|
matched = true;
|
|
773
|
matched = true;
|
|
774
|
|
|
774
|
|
|
775
|
} else if (m_enum_values.contains(s)) {
|
|
775
|
} else if (m_enum_values.contains(s)) {
|
|
776
|
v = m_enum_values[s]->value();
|
|
776
|
v = m_enum_values[s]->value();
|
|
777
|
matched = true;
|
|
777
|
matched = true;
|
|
778
|
|
|
778
|
|
|
779
|
} else {
|
|
779
|
} else {
|
|
780
|
AbstractMetaEnumValue *ev = 0;
|
|
780
|
AbstractMetaEnumValue *ev = 0;
|
|
781
|
|
|
781
|
|
|
782
|
if (meta_enum && (ev = meta_enum->values().find(s))) {
|
|
782
|
if (meta_enum && (ev = meta_enum->values().find(s))) {
|
|
783
|
v = ev->value();
|
|
783
|
v = ev->value();
|
|
784
|
matched = true;
|
|
784
|
matched = true;
|
|
785
|
|
|
785
|
|
|
786
|
} else if (meta_enum && (ev = meta_enum->enclosingClass()->findEnumValue(s, meta_enum))) {
|
|
786
|
} else if (meta_enum && (ev = meta_enum->enclosingClass()->findEnumValue(s, meta_enum))) {
|
|
787
|
v = ev->value();
|
|
787
|
v = ev->value();
|
|
788
|
matched = true;
|
|
788
|
matched = true;
|
|
789
|
|
|
789
|
|
|
790
|
} else {
|
|
790
|
} else {
|
|
791
|
if (meta_enum)
|
|
791
|
if (meta_enum)
|
|
792
|
ReportHandler::warning("unhandled enum value: " + s + " in "
|
|
792
|
ReportHandler::warning("unhandled enum value: " + s + " in "
|
|
793
|
+ meta_enum->enclosingClass()->name() + "::"
|
|
793
|
+ meta_enum->enclosingClass()->name() + "::"
|
|
794
|
+ meta_enum->name());
|
|
794
|
+ meta_enum->name());
|
|
795
|
else
|
|
795
|
else
|
|
796
|
ReportHandler::warning("unhandled enum value: Unknown enum");
|
|
796
|
ReportHandler::warning("unhandled enum value: Unknown enum");
|
|
797
|
}
|
|
797
|
}
|
|
798
|
}
|
|
798
|
}
|
|
799
|
|
|
799
|
|
|
800
|
if (matched)
|
|
800
|
if (matched)
|
|
801
|
returnValue |= op.calculate(v);
|
|
801
|
returnValue |= op.calculate(v);
|
|
802
|
}
|
|
802
|
}
|
|
803
|
|
|
803
|
|
|
804
|
if (!matched) {
|
|
804
|
if (!matched) {
|
|
805
|
QString warn = QString("unmatched enum %1").arg(stringValue);
|
|
805
|
QString warn = QString("unmatched enum %1").arg(stringValue);
|
|
806
|
|
|
806
|
|
|
807
|
if (meta_function != 0) {
|
|
807
|
if (meta_function != 0) {
|
|
808
|
warn += QString(" when parsing default value of '%1' in class '%2'")
|
|
808
|
warn += QString(" when parsing default value of '%1' in class '%2'")
|
|
809
|
.arg(meta_function->name())
|
|
809
|
.arg(meta_function->name())
|
|
810
|
.arg(meta_function->implementingClass()->name());
|
|
810
|
.arg(meta_function->implementingClass()->name());
|
|
811
|
}
|
|
811
|
}
|
|
812
|
|
|
812
|
|
|
813
|
ReportHandler::warning(warn);
|
|
813
|
ReportHandler::warning(warn);
|
|
814
|
returnValue = oldValuevalue;
|
|
814
|
returnValue = oldValuevalue;
|
|
815
|
}
|
|
815
|
}
|
|
816
|
|
|
816
|
|
|
817
|
return returnValue;
|
|
817
|
return returnValue;
|
|
818
|
}
|
|
818
|
}
|
|
819
|
|
|
819
|
|
|
820
|
void AbstractMetaBuilder::figureOutEnumValuesForClass(AbstractMetaClass *meta_class,
|
|
820
|
void AbstractMetaBuilder::figureOutEnumValuesForClass(AbstractMetaClass *meta_class,
|
|
821
|
QSet<AbstractMetaClass *> *classes)
|
|
821
|
QSet<AbstractMetaClass *> *classes)
|
|
822
|
{
|
|
822
|
{
|
|
823
|
AbstractMetaClass *base = meta_class->baseClass();
|
|
823
|
AbstractMetaClass *base = meta_class->baseClass();
|
|
824
|
|
|
824
|
|
|
825
|
if (base != 0 && !classes->contains(base))
|
|
825
|
if (base != 0 && !classes->contains(base))
|
|
826
|
figureOutEnumValuesForClass(base, classes);
|
|
826
|
figureOutEnumValuesForClass(base, classes);
|
|
827
|
|
|
827
|
|
|
828
|
if (classes->contains(meta_class))
|
|
828
|
if (classes->contains(meta_class))
|
|
829
|
return;
|
|
829
|
return;
|
|
830
|
|
|
830
|
|
|
831
|
AbstractMetaEnumList enums = meta_class->enums();
|
|
831
|
AbstractMetaEnumList enums = meta_class->enums();
|
|
832
|
foreach (AbstractMetaEnum *e, enums) {
|
|
832
|
foreach (AbstractMetaEnum *e, enums) {
|
|
833
|
if (!e) {
|
|
833
|
if (!e) {
|
|
834
|
ReportHandler::warning("bad enum in class " + meta_class->name());
|
|
834
|
ReportHandler::warning("bad enum in class " + meta_class->name());
|
|
835
|
continue;
|
|
835
|
continue;
|
|
836
|
}
|
|
836
|
}
|
|
837
|
AbstractMetaEnumValueList lst = e->values();
|
|
837
|
AbstractMetaEnumValueList lst = e->values();
|
|
838
|
int value = 0;
|
|
838
|
int value = 0;
|
|
839
|
for (int i=0; i<lst.size(); ++i) {
|
|
839
|
for (int i=0; i<lst.size(); ++i) {
|
|
840
|
value = figureOutEnumValue(lst.at(i)->stringValue(), value, e);
|
|
840
|
value = figureOutEnumValue(lst.at(i)->stringValue(), value, e);
|
|
841
|
lst.at(i)->setValue(value);
|
|
841
|
lst.at(i)->setValue(value);
|
|
842
|
value++;
|
|
842
|
value++;
|
|
843
|
}
|
|
843
|
}
|
|
844
|
|
|
844
|
|
|
845
|
// Check for duplicate values...
|
|
845
|
// Check for duplicate values...
|
|
846
|
EnumTypeEntry *ete = e->typeEntry();
|
|
846
|
EnumTypeEntry *ete = e->typeEntry();
|
|
847
|
if (!ete->forceInteger()) {
|
|
847
|
if (!ete->forceInteger()) {
|
|
848
|
QHash<int, AbstractMetaEnumValue *> entries;
|
|
848
|
QHash<int, AbstractMetaEnumValue *> entries;
|
|
849
|
foreach (AbstractMetaEnumValue *v, lst) {
|
|
849
|
foreach (AbstractMetaEnumValue *v, lst) {
|
|
850
|
|
|
850
|
|
|
851
|
bool vRejected = ete->isEnumValueRejected(v->name());
|
|
851
|
bool vRejected = ete->isEnumValueRejected(v->name());
|
|
852
|
|
|
852
|
|
|
853
|
AbstractMetaEnumValue *current = entries.value(v->value());
|
|
853
|
AbstractMetaEnumValue *current = entries.value(v->value());
|
|
854
|
if (current) {
|
|
854
|
if (current) {
|
|
855
|
bool currentRejected = ete->isEnumValueRejected(current->name());
|
|
855
|
bool currentRejected = ete->isEnumValueRejected(current->name());
|
|
856
|
if (!currentRejected && !vRejected) {
|
|
856
|
if (!currentRejected && !vRejected) {
|
|
857
|
ReportHandler::warning(
|
|
857
|
ReportHandler::warning(
|
|
858
|
QString("duplicate enum values: %1::%2, %3 and %4 are %5, already rejected: (%6)")
|
|
858
|
QString("duplicate enum values: %1::%2, %3 and %4 are %5, already rejected: (%6)")
|
|
859
|
.arg(meta_class->name())
|
|
859
|
.arg(meta_class->name())
|
|
860
|
.arg(e->name())
|
|
860
|
.arg(e->name())
|
|
861
|
.arg(v->name())
|
|
861
|
.arg(v->name())
|
|
862
|
.arg(entries[v->value()]->name())
|
|
862
|
.arg(entries[v->value()]->name())
|
|
863
|
.arg(v->value())
|
|
863
|
.arg(v->value())
|
|
864
|
.arg(ete->enumValueRejections().join(", ")));
|
|
864
|
.arg(ete->enumValueRejections().join(", ")));
|
|
865
|
continue;
|
|
865
|
continue;
|
|
866
|
}
|
|
866
|
}
|
|
867
|
}
|
|
867
|
}
|
|
868
|
|
|
868
|
|
|
869
|
if (!vRejected)
|
|
869
|
if (!vRejected)
|
|
870
|
entries[v->value()] = v;
|
|
870
|
entries[v->value()] = v;
|
|
871
|
}
|
|
871
|
}
|
|
872
|
|
|
872
|
|
|
873
|
// Entries now contain all the original entries, no
|
|
873
|
// Entries now contain all the original entries, no
|
|
874
|
// rejected ones... Use this to generate the enumValueRedirection table.
|
|
874
|
// rejected ones... Use this to generate the enumValueRedirection table.
|
|
875
|
foreach (AbstractMetaEnumValue *reject, lst) {
|
|
875
|
foreach (AbstractMetaEnumValue *reject, lst) {
|
|
876
|
if (!ete->isEnumValueRejected(reject->name()))
|
|
876
|
if (!ete->isEnumValueRejected(reject->name()))
|
|
877
|
continue;
|
|
877
|
continue;
|
|
878
|
|
|
878
|
|
|
879
|
AbstractMetaEnumValue *used = entries.value(reject->value());
|
|
879
|
AbstractMetaEnumValue *used = entries.value(reject->value());
|
|
880
|
if (!used) {
|
|
880
|
if (!used) {
|
|
881
|
ReportHandler::warning(
|
|
881
|
ReportHandler::warning(
|
|
882
|
QString::fromLatin1("Rejected enum has no alternative...: %1::%2")
|
|
882
|
QString::fromLatin1("Rejected enum has no alternative...: %1::%2")
|
|
883
|
.arg(meta_class->name())
|
|
883
|
.arg(meta_class->name())
|
|
884
|
.arg(reject->name()));
|
|
884
|
.arg(reject->name()));
|
|
885
|
continue;
|
|
885
|
continue;
|
|
886
|
}
|
|
886
|
}
|
|
887
|
ete->addEnumValueRedirection(reject->name(), used->name());
|
|
887
|
ete->addEnumValueRedirection(reject->name(), used->name());
|
|
888
|
}
|
|
888
|
}
|
|
889
|
|
|
889
|
|
|
890
|
}
|
|
890
|
}
|
|
891
|
}
|
|
891
|
}
|
|
892
|
|
|
892
|
|
|
893
|
|
|
893
|
|
|
894
|
|
|
894
|
|
|
895
|
*classes += meta_class;
|
|
895
|
*classes += meta_class;
|
|
896
|
}
|
|
896
|
}
|
|
897
|
|
|
897
|
|
|
898
|
|
|
898
|
|
|
899
|
void AbstractMetaBuilder::figureOutEnumValues()
|
|
899
|
void AbstractMetaBuilder::figureOutEnumValues()
|
|
900
|
{
|
|
900
|
{
|
|
901
|
// Keep a set of classes that we already traversed. We use this to
|
|
901
|
// Keep a set of classes that we already traversed. We use this to
|
|
902
|
// enforce that we traverse base classes prior to subclasses.
|
|
902
|
// enforce that we traverse base classes prior to subclasses.
|
|
903
|
QSet<AbstractMetaClass *> classes;
|
|
903
|
QSet<AbstractMetaClass *> classes;
|
|
904
|
foreach (AbstractMetaClass *c, m_meta_classes) {
|
|
904
|
foreach (AbstractMetaClass *c, m_meta_classes) {
|
|
905
|
figureOutEnumValuesForClass(c, &classes);
|
|
905
|
figureOutEnumValuesForClass(c, &classes);
|
|
906
|
}
|
|
906
|
}
|
|
907
|
}
|
|
907
|
}
|
|
908
|
|
|
908
|
|
|
909
|
void AbstractMetaBuilder::figureOutDefaultEnumArguments()
|
|
909
|
void AbstractMetaBuilder::figureOutDefaultEnumArguments()
|
|
910
|
{
|
|
910
|
{
|
|
911
|
foreach (AbstractMetaClass *meta_class, m_meta_classes) {
|
|
911
|
foreach (AbstractMetaClass *meta_class, m_meta_classes) {
|
|
912
|
foreach (AbstractMetaFunction *meta_function, meta_class->functions()) {
|
|
912
|
foreach (AbstractMetaFunction *meta_function, meta_class->functions()) {
|
|
913
|
foreach (AbstractMetaArgument *arg, meta_function->arguments()) {
|
|
913
|
foreach (AbstractMetaArgument *arg, meta_function->arguments()) {
|
|
914
|
|
|
914
|
|
|
915
|
QString expr = arg->defaultValueExpression();
|
|
915
|
QString expr = arg->defaultValueExpression();
|
|
916
|
if (expr.isEmpty())
|
|
916
|
if (expr.isEmpty())
|
|
917
|
continue;
|
|
917
|
continue;
|
|
918
|
|
|
918
|
|
|
919
|
if (!meta_function->replacedDefaultExpression(meta_function->implementingClass(),
|
|
919
|
if (!meta_function->replacedDefaultExpression(meta_function->implementingClass(),
|
|
920
|
arg->argumentIndex()+1).isEmpty()) {
|
|
920
|
arg->argumentIndex()+1).isEmpty()) {
|
|
921
|
continue;
|
|
921
|
continue;
|
|
922
|
}
|
|
922
|
}
|
|
923
|
|
|
923
|
|
|
924
|
QString new_expr = expr;
|
|
924
|
QString new_expr = expr;
|
|
925
|
if (arg->type()->isEnum()) {
|
|
925
|
if (arg->type()->isEnum()) {
|
|
926
|
QStringList lst = expr.split(QLatin1String("::"));
|
|
926
|
QStringList lst = expr.split(QLatin1String("::"));
|
|
927
|
if (lst.size() == 1) {
|
|
927
|
if (lst.size() == 1) {
|
|
928
|
QVector<AbstractMetaClass *> classes(1, meta_class);
|
|
928
|
QVector<AbstractMetaClass *> classes(1, meta_class);
|
|
929
|
AbstractMetaEnum *e = 0;
|
|
929
|
AbstractMetaEnum *e = 0;
|
|
930
|
while (!classes.isEmpty() && e == 0) {
|
|
930
|
while (!classes.isEmpty() && e == 0) {
|
|
931
|
if (classes.front() != 0) {
|
|
931
|
if (classes.front() != 0) {
|
|
932
|
classes << classes.front()->baseClass();
|
|
932
|
classes << classes.front()->baseClass();
|
|
933
|
|
|
933
|
|
|
934
|
AbstractMetaClassList interfaces = classes.front()->interfaces();
|
|
934
|
AbstractMetaClassList interfaces = classes.front()->interfaces();
|
|
935
|
foreach (AbstractMetaClass *interface, interfaces)
|
|
935
|
foreach (AbstractMetaClass *interface, interfaces)
|
|
936
|
classes << interface->primaryInterfaceImplementor();
|
|
936
|
classes << interface->primaryInterfaceImplementor();
|
|
937
|
|
|
937
|
|
|
938
|
e = classes.front()->findEnumForValue(expr);
|
|
938
|
e = classes.front()->findEnumForValue(expr);
|
|
939
|
}
|
|
939
|
}
|
|
940
|
|
|
940
|
|
|
941
|
classes.pop_front();
|
|
941
|
classes.pop_front();
|
|
942
|
}
|
|
942
|
}
|
|
943
|
|
|
943
|
|
|
944
|
if (e != 0) {
|
|
944
|
if (e != 0) {
|
|
945
|
new_expr = QString("%1.%2")
|
|
945
|
new_expr = QString("%1.%2")
|
|
946
|
.arg(e->typeEntry()->qualifiedTargetLangName())
|
|
946
|
.arg(e->typeEntry()->qualifiedTargetLangName())
|
|
947
|
.arg(expr);
|
|
947
|
.arg(expr);
|
|
948
|
} else {
|
|
948
|
} else {
|
|
949
|
ReportHandler::warning("Cannot find enum constant for value '" + expr + "' in '" + meta_class->name() + "' or any of its super classes");
|
|
949
|
ReportHandler::warning("Cannot find enum constant for value '" + expr + "' in '" + meta_class->name() + "' or any of its super classes");
|
|
950
|
}
|
|
950
|
}
|
|
951
|
} else if (lst.size() == 2) {
|
|
951
|
} else if (lst.size() == 2) {
|
|
952
|
AbstractMetaClass *cl = m_meta_classes.findClass(lst.at(0));
|
|
952
|
AbstractMetaClass *cl = m_meta_classes.findClass(lst.at(0));
|
|
953
|
if (!cl) {
|
|
953
|
if (!cl) {
|
|
954
|
ReportHandler::warning("missing required class for enums: " + lst.at(0));
|
|
954
|
ReportHandler::warning("missing required class for enums: " + lst.at(0));
|
|
955
|
continue;
|
|
955
|
continue;
|
|
956
|
}
|
|
956
|
}
|
|
957
|
new_expr = QString("%1.%2.%3")
|
|
957
|
new_expr = QString("%1.%2.%3")
|
|
958
|
.arg(cl->typeEntry()->qualifiedTargetLangName())
|
|
958
|
.arg(cl->typeEntry()->qualifiedTargetLangName())
|
|
959
|
.arg(arg->type()->name())
|
|
959
|
.arg(arg->type()->name())
|
|
960
|
.arg(lst.at(1));
|
|
960
|
.arg(lst.at(1));
|
|
961
|
} else {
|
|
961
|
} else {
|
|
962
|
ReportHandler::warning("bad default value passed to enum " + expr);
|
|
962
|
ReportHandler::warning("bad default value passed to enum " + expr);
|
|
963
|
}
|
|
963
|
}
|
|
964
|
|
|
964
|
|
|
965
|
} else if(arg->type()->isFlags()) {
|
|
965
|
} else if(arg->type()->isFlags()) {
|
|
966
|
const FlagsTypeEntry *flagsEntry =
|
|
966
|
const FlagsTypeEntry *flagsEntry =
|
|
967
|
static_cast<const FlagsTypeEntry *>(arg->type()->typeEntry());
|
|
967
|
static_cast<const FlagsTypeEntry *>(arg->type()->typeEntry());
|
|
968
|
EnumTypeEntry *enumEntry = flagsEntry->originator();
|
|
968
|
EnumTypeEntry *enumEntry = flagsEntry->originator();
|
|
969
|
AbstractMetaEnum *meta_enum = m_meta_classes.findEnum(enumEntry);
|
|
969
|
AbstractMetaEnum *meta_enum = m_meta_classes.findEnum(enumEntry);
|
|
970
|
if (!meta_enum) {
|
|
970
|
if (!meta_enum) {
|
|
971
|
ReportHandler::warning("unknown required enum " + enumEntry->qualifiedCppName());
|
|
971
|
ReportHandler::warning("unknown required enum " + enumEntry->qualifiedCppName());
|
|
972
|
continue;
|
|
972
|
continue;
|
|
973
|
}
|
|
973
|
}
|
|
974
|
|
|
974
|
|
|
975
|
int value = figureOutEnumValue(expr, 0, meta_enum, meta_function);
|
|
975
|
int value = figureOutEnumValue(expr, 0, meta_enum, meta_function);
|
|
976
|
new_expr = QString::number(value);
|
|
976
|
new_expr = QString::number(value);
|
|
977
|
|
|
977
|
|
|
978
|
} else if (arg->type()->isPrimitive()) {
|
|
978
|
} else if (arg->type()->isPrimitive()) {
|
|
979
|
AbstractMetaEnumValue *value = 0;
|
|
979
|
AbstractMetaEnumValue *value = 0;
|
|
980
|
if (expr.contains("::"))
|
|
980
|
if (expr.contains("::"))
|
|
981
|
value = m_meta_classes.findEnumValue(expr);
|
|
981
|
value = m_meta_classes.findEnumValue(expr);
|
|
982
|
if (!value)
|
|
982
|
if (!value)
|
|
983
|
value = meta_class->findEnumValue(expr, 0);
|
|
983
|
value = meta_class->findEnumValue(expr, 0);
|
|
984
|
|
|
984
|
|
|
985
|
if (value) {
|
|
985
|
if (value) {
|
|
986
|
new_expr = QString::number(value->value());
|
|
986
|
new_expr = QString::number(value->value());
|
|
987
|
} else if (expr.contains(QLatin1Char('+'))) {
|
|
987
|
} else if (expr.contains(QLatin1Char('+'))) {
|
|
988
|
new_expr = QString::number(figureOutEnumValue(expr, 0, 0));
|
|
988
|
new_expr = QString::number(figureOutEnumValue(expr, 0, 0));
|
|
989
|
|
|
989
|
|
|
990
|
}
|
|
990
|
}
|
|
991
|
|
|
991
|
|
|
992
|
|
|
992
|
|
|
993
|
|
|
993
|
|
|
994
|
}
|
|
994
|
}
|
|
995
|
|
|
995
|
|
|
996
|
arg->setDefaultValueExpression(new_expr);
|
|
996
|
arg->setDefaultValueExpression(new_expr);
|
|
997
|
}
|
|
997
|
}
|
|
998
|
}
|
|
998
|
}
|
|
999
|
}
|
|
999
|
}
|
|
1000
|
}
|
|
1000
|
}
|
|
1001
|
|
|
1001
|
|
|
1002
|
|
|
1002
|
|
|
1003
|
AbstractMetaEnum *AbstractMetaBuilder::traverseEnum(EnumModelItem enum_item, AbstractMetaClass *enclosing, const QSet<QString> &enumsDeclarations)
|
|
1003
|
AbstractMetaEnum *AbstractMetaBuilder::traverseEnum(EnumModelItem enum_item, AbstractMetaClass *enclosing, const QSet<QString> &enumsDeclarations)
|
|
1004
|
{
|
|
1004
|
{
|
|
1005
|
// Skipping private enums.
|
|
1005
|
// Skipping private enums.
|
|
1006
|
if (enum_item->accessPolicy() == CodeModel::Private) {
|
|
1006
|
if (enum_item->accessPolicy() == CodeModel::Private) {
|
|
1007
|
return 0;
|
|
1007
|
return 0;
|
|
1008
|
}
|
|
1008
|
}
|
|
1009
|
|
|
1009
|
|
|
1010
|
QString qualified_name = enum_item->qualifiedName().join("::");
|
|
1010
|
QString qualified_name = enum_item->qualifiedName().join("::");
|
|
1011
|
|
|
1011
|
|
|
1012
|
TypeEntry *type_entry = TypeDatabase::instance()->findType(qualified_name);
|
|
1012
|
TypeEntry *type_entry = TypeDatabase::instance()->findType(qualified_name);
|
|
1013
|
QString enum_name = enum_item->name();
|
|
1013
|
QString enum_name = enum_item->name();
|
|
1014
|
|
|
1014
|
|
|
1015
|
QString class_name;
|
|
1015
|
QString class_name;
|
|
1016
|
if (m_current_class)
|
|
1016
|
if (m_current_class)
|
|
1017
|
class_name = m_current_class->typeEntry()->qualifiedCppName();
|
|
1017
|
class_name = m_current_class->typeEntry()->qualifiedCppName();
|
|
1018
|
|
|
1018
|
|
|
1019
|
if (TypeDatabase::instance()->isEnumRejected(class_name, enum_name)) {
|
|
1019
|
if (TypeDatabase::instance()->isEnumRejected(class_name, enum_name)) {
|
|
1020
|
m_rejected_enums.insert(qualified_name, GenerationDisabled);
|
|
1020
|
m_rejected_enums.insert(qualified_name, GenerationDisabled);
|
|
1021
|
return 0;
|
|
1021
|
return 0;
|
|
1022
|
}
|
|
1022
|
}
|
|
1023
|
|
|
1023
|
|
|
1024
|
if (!type_entry || !type_entry->isEnum()) {
|
|
1024
|
if (!type_entry || !type_entry->isEnum()) {
|
|
1025
|
QString context = m_current_class ? m_current_class->name() : QLatin1String("");
|
|
1025
|
QString context = m_current_class ? m_current_class->name() : QLatin1String("");
|
|
1026
|
ReportHandler::warning(QString("enum '%1' does not have a type entry or is not an enum")
|
|
1026
|
ReportHandler::warning(QString("enum '%1' does not have a type entry or is not an enum")
|
|
1027
|
.arg(qualified_name));
|
|
1027
|
.arg(qualified_name));
|
|
1028
|
m_rejected_enums.insert(qualified_name, NotInTypeSystem);
|
|
1028
|
m_rejected_enums.insert(qualified_name, NotInTypeSystem);
|
|
1029
|
return 0;
|
|
1029
|
return 0;
|
|
1030
|
}
|
|
1030
|
}
|
|
1031
|
|
|
1031
|
|
|
1032
|
AbstractMetaEnum *meta_enum = createMetaEnum();
|
|
1032
|
AbstractMetaEnum *meta_enum = createMetaEnum();
|
|
1033
|
if ( enumsDeclarations.contains(qualified_name)
|
|
1033
|
if ( enumsDeclarations.contains(qualified_name)
|
|
1034
|
|| enumsDeclarations.contains(enum_name)) {
|
|
1034
|
|| enumsDeclarations.contains(enum_name)) {
|
|
1035
|
meta_enum->setHasQEnumsDeclaration(true);
|
|
1035
|
meta_enum->setHasQEnumsDeclaration(true);
|
|
1036
|
}
|
|
1036
|
}
|
|
1037
|
|
|
1037
|
|
|
1038
|
meta_enum->setTypeEntry((EnumTypeEntry *) type_entry);
|
|
1038
|
meta_enum->setTypeEntry((EnumTypeEntry *) type_entry);
|
|
1039
|
switch (enum_item->accessPolicy()) {
|
|
1039
|
switch (enum_item->accessPolicy()) {
|
|
1040
|
case CodeModel::Public: *meta_enum += AbstractMetaAttributes::Public; break;
|
|
1040
|
case CodeModel::Public: *meta_enum += AbstractMetaAttributes::Public; break;
|
|
1041
|
case CodeModel::Protected: *meta_enum += AbstractMetaAttributes::Protected; break;
|
|
1041
|
case CodeModel::Protected: *meta_enum += AbstractMetaAttributes::Protected; break;
|
|
1042
|
// case CodeModel::Private: *meta_enum += AbstractMetaAttributes::Private; break;
|
|
1042
|
// case CodeModel::Private: *meta_enum += AbstractMetaAttributes::Private; break;
|
|
1043
|
default: break;
|
|
1043
|
default: break;
|
|
1044
|
}
|
|
1044
|
}
|
|
1045
|
|
|
1045
|
|
|
1046
|
ReportHandler::debugMedium(QString(" - traversing enum %1").arg(meta_enum->fullName()));
|
|
1046
|
ReportHandler::debugMedium(QString(" - traversing enum %1").arg(meta_enum->fullName()));
|
|
1047
|
|
|
1047
|
|
|
1048
|
foreach (EnumeratorModelItem value, enum_item->enumerators()) {
|
|
1048
|
foreach (EnumeratorModelItem value, enum_item->enumerators()) {
|
|
1049
|
|
|
1049
|
|
|
1050
|
AbstractMetaEnumValue *meta_enum_value = createMetaEnumValue();
|
|
1050
|
AbstractMetaEnumValue *meta_enum_value = createMetaEnumValue();
|
|
1051
|
meta_enum_value->setName(value->name());
|
|
1051
|
meta_enum_value->setName(value->name());
|
|
1052
|
// Deciding the enum value...
|
|
1052
|
// Deciding the enum value...
|
|
1053
|
|
|
1053
|
|
|
1054
|
meta_enum_value->setStringValue(value->value());
|
|
1054
|
meta_enum_value->setStringValue(value->value());
|
|
1055
|
meta_enum->addEnumValue(meta_enum_value);
|
|
1055
|
meta_enum->addEnumValue(meta_enum_value);
|
|
1056
|
|
|
1056
|
|
|
1057
|
ReportHandler::debugFull(" - " + meta_enum_value->name() + " = "
|
|
1057
|
ReportHandler::debugFull(" - " + meta_enum_value->name() + " = "
|
|
1058
|
+ meta_enum_value->value());
|
|
1058
|
+ meta_enum_value->value());
|
|
1059
|
|
|
1059
|
|
|
1060
|
// Add into global register...
|
|
1060
|
// Add into global register...
|
|
1061
|
if (enclosing)
|
|
1061
|
if (enclosing)
|
|
1062
|
m_enum_values[enclosing->name() + "::" + meta_enum_value->name()] = meta_enum_value;
|
|
1062
|
m_enum_values[enclosing->name() + "::" + meta_enum_value->name()] = meta_enum_value;
|
|
1063
|
else
|
|
1063
|
else
|
|
1064
|
m_enum_values[meta_enum_value->name()] = meta_enum_value;
|
|
1064
|
m_enum_values[meta_enum_value->name()] = meta_enum_value;
|
|
1065
|
}
|
|
1065
|
}
|
|
1066
|
|
|
1066
|
|
|
1067
|
QFileInfo info(enum_item->fileName());
|
|
1067
|
QFileInfo info(enum_item->fileName());
|
|
1068
|
meta_enum->typeEntry()->setInclude(Include(Include::IncludePath, info.fileName()));
|
|
1068
|
meta_enum->typeEntry()->setInclude(Include(Include::IncludePath, info.fileName()));
|
|
1069
|
|
|
1069
|
|
|
1070
|
m_enums << meta_enum;
|
|
1070
|
m_enums << meta_enum;
|
|
1071
|
|
|
1071
|
|
|
1072
|
return meta_enum;
|
|
1072
|
return meta_enum;
|
|
1073
|
}
|
|
1073
|
}
|
|
1074
|
|
|
1074
|
|
|
1075
|
AbstractMetaClass *AbstractMetaBuilder::traverseTypeAlias(TypeAliasModelItem typeAlias)
|
|
1075
|
AbstractMetaClass *AbstractMetaBuilder::traverseTypeAlias(TypeAliasModelItem typeAlias)
|
|
1076
|
{
|
|
1076
|
{
|
|
1077
|
QString class_name = strip_template_args(typeAlias->name());
|
|
1077
|
QString class_name = strip_template_args(typeAlias->name());
|
|
1078
|
|
|
1078
|
|
|
1079
|
QString full_class_name = class_name;
|
|
1079
|
QString full_class_name = class_name;
|
|
1080
|
// we have an inner class
|
|
1080
|
// we have an inner class
|
|
1081
|
if (m_current_class) {
|
|
1081
|
if (m_current_class) {
|
|
1082
|
full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
|
|
1082
|
full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
|
|
1083
|
+ "::" + full_class_name;
|
|
1083
|
+ "::" + full_class_name;
|
|
1084
|
}
|
|
1084
|
}
|
|
1085
|
|
|
1085
|
|
|
1086
|
// If we haven't specified anything for the typedef, then we don't care
|
|
1086
|
// If we haven't specified anything for the typedef, then we don't care
|
|
1087
|
ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
|
|
1087
|
ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
|
|
1088
|
if (type == 0)
|
|
1088
|
if (type == 0)
|
|
1089
|
return 0;
|
|
1089
|
return 0;
|
|
1090
|
|
|
1090
|
|
|
1091
|
if (type->isObject())
|
|
1091
|
if (type->isObject())
|
|
1092
|
static_cast<ObjectTypeEntry *>(type)->setQObject(isQObject(strip_template_args(typeAlias->type().qualifiedName().join("::"))));
|
|
1092
|
static_cast<ObjectTypeEntry *>(type)->setQObject(isQObject(strip_template_args(typeAlias->type().qualifiedName().join("::"))));
|
|
1093
|
|
|
1093
|
|
|
1094
|
AbstractMetaClass *meta_class = createMetaClass();
|
|
1094
|
AbstractMetaClass *meta_class = createMetaClass();
|
|
1095
|
meta_class->setTypeAlias(true);
|
|
1095
|
meta_class->setTypeAlias(true);
|
|
1096
|
meta_class->setTypeEntry(type);
|
|
1096
|
meta_class->setTypeEntry(type);
|
|
1097
|
meta_class->setBaseClassNames(QStringList() << typeAlias->type().qualifiedName().join("::"));
|
|
1097
|
meta_class->setBaseClassNames(QStringList() << typeAlias->type().qualifiedName().join("::"));
|
|
1098
|
*meta_class += AbstractMetaAttributes::Public;
|
|
1098
|
*meta_class += AbstractMetaAttributes::Public;
|
|
1099
|
|
|
1099
|
|
|
1100
|
// Set the default include file name
|
|
1100
|
// Set the default include file name
|
|
1101
|
if (!type->include().isValid()) {
|
|
1101
|
if (!type->include().isValid()) {
|
|
1102
|
QFileInfo info(typeAlias->fileName());
|
|
1102
|
QFileInfo info(typeAlias->fileName());
|
|
1103
|
type->setInclude(Include(Include::IncludePath, info.fileName()));
|
|
1103
|
type->setInclude(Include(Include::IncludePath, info.fileName()));
|
|
1104
|
}
|
|
1104
|
}
|
|
1105
|
|
|
1105
|
|
|
1106
|
return meta_class;
|
|
1106
|
return meta_class;
|
|
1107
|
}
|
|
1107
|
}
|
|
1108
|
|
|
1108
|
|
|
1109
|
AbstractMetaClass *AbstractMetaBuilder::traverseClass(ClassModelItem class_item)
|
|
1109
|
AbstractMetaClass *AbstractMetaBuilder::traverseClass(ClassModelItem class_item)
|
|
1110
|
{
|
|
1110
|
{
|
|
1111
|
QString class_name = strip_template_args(class_item->name());
|
|
1111
|
QString class_name = strip_template_args(class_item->name());
|
|
1112
|
QString full_class_name = class_name;
|
|
1112
|
QString full_class_name = class_name;
|
|
1113
|
|
|
1113
|
|
|
1114
|
// we have inner an class
|
|
1114
|
// we have inner an class
|
|
1115
|
if (m_current_class) {
|
|
1115
|
if (m_current_class) {
|
|
1116
|
full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
|
|
1116
|
full_class_name = strip_template_args(m_current_class->typeEntry()->qualifiedCppName())
|
|
1117
|
+ "::" + full_class_name;
|
|
1117
|
+ "::" + full_class_name;
|
|
1118
|
}
|
|
1118
|
}
|
|
1119
|
|
|
1119
|
|
|
1120
|
ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
|
|
1120
|
ComplexTypeEntry *type = TypeDatabase::instance()->findComplexType(full_class_name);
|
|
1121
|
RejectReason reason = NoReason;
|
|
1121
|
RejectReason reason = NoReason;
|
|
1122
|
|
|
1122
|
|
|
1123
|
if (full_class_name == "QMetaTypeId") {
|
|
1123
|
if (full_class_name == "QMetaTypeId") {
|
|
1124
|
// QtScript: record which types have been declared
|
|
1124
|
// QtScript: record which types have been declared
|
|
1125
|
int lpos = class_item->name().indexOf('<');
|
|
1125
|
int lpos = class_item->name().indexOf('<');
|
|
1126
|
int rpos = class_item->name().lastIndexOf('>');
|
|
1126
|
int rpos = class_item->name().lastIndexOf('>');
|
|
1127
|
if ((lpos != -1) && (rpos != -1)) {
|
|
1127
|
if ((lpos != -1) && (rpos != -1)) {
|
|
1128
|
QString declared_typename = class_item->name().mid(lpos+1, rpos - lpos-1);
|
|
1128
|
QString declared_typename = class_item->name().mid(lpos+1, rpos - lpos-1);
|
|
1129
|
m_qmetatype_declared_typenames.insert(declared_typename);
|
|
1129
|
m_qmetatype_declared_typenames.insert(declared_typename);
|
|
1130
|
}
|
|
1130
|
}
|
|
1131
|
}
|
|
1131
|
}
|
|
1132
|
|
|
1132
|
|
|
1133
|
if (TypeDatabase::instance()->isClassRejected(full_class_name)) {
|
|
1133
|
if (TypeDatabase::instance()->isClassRejected(full_class_name)) {
|
|
1134
|
reason = GenerationDisabled;
|
|
1134
|
reason = GenerationDisabled;
|
|
1135
|
} else if (!type) {
|
|
1135
|
} else if (!type) {
|
|
1136
|
TypeEntry *te = TypeDatabase::instance()->findType(full_class_name);
|
|
1136
|
TypeEntry *te = TypeDatabase::instance()->findType(full_class_name);
|
|
1137
|
if (te && !te->isComplex())
|
|
1137
|
if (te && !te->isComplex())
|
|
1138
|
reason = RedefinedToNotClass;
|
|
1138
|
reason = RedefinedToNotClass;
|
|
1139
|
else
|
|
1139
|
else
|
|
1140
|
reason = NotInTypeSystem;
|
|
1140
|
reason = NotInTypeSystem;
|
|
1141
|
} else if (type->codeGeneration() == TypeEntry::GenerateNothing) {
|
|
1141
|
} else if (type->codeGeneration() == TypeEntry::GenerateNothing) {
|
|
1142
|
reason = GenerationDisabled;
|
|
1142
|
reason = GenerationDisabled;
|
|
1143
|
}
|
|
1143
|
}
|
|
1144
|
|
|
1144
|
|
|
1145
|
if (reason != NoReason) {
|
|
1145
|
if (reason != NoReason) {
|
|
1146
|
m_rejected_classes.insert(full_class_name, reason);
|
|
1146
|
m_rejected_classes.insert(full_class_name, reason);
|
|
1147
|
return 0;
|
|
1147
|
return 0;
|
|
1148
|
}
|
|
1148
|
}
|
|
1149
|
|
|
1149
|
|
|
1150
|
if (type->isObject()) {
|
|
1150
|
if (type->isObject()) {
|
|
1151
|
((ObjectTypeEntry *)type)->setQObject(isQObject(full_class_name));
|
|
1151
|
((ObjectTypeEntry *)type)->setQObject(isQObject(full_class_name));
|
|
1152
|
}
|
|
1152
|
}
|
|
1153
|
|
|
1153
|
|
|
1154
|
AbstractMetaClass *meta_class = createMetaClass();
|
|
1154
|
AbstractMetaClass *meta_class = createMetaClass();
|
|
1155
|
meta_class->setTypeEntry(type);
|
|
1155
|
meta_class->setTypeEntry(type);
|
|
1156
|
meta_class->setBaseClassNames(class_item->baseClasses());
|
|
1156
|
meta_class->setBaseClassNames(class_item->baseClasses());
|
|
1157
|
*meta_class += AbstractMetaAttributes::Public;
|
|
1157
|
*meta_class += AbstractMetaAttributes::Public;
|
|
1158
|
|
|
1158
|
|
|
1159
|
AbstractMetaClass *old_current_class = m_current_class;
|
|
1159
|
AbstractMetaClass *old_current_class = m_current_class;
|
|
1160
|
m_current_class = meta_class;
|
|
1160
|
m_current_class = meta_class;
|
|
1161
|
|
|
1161
|
|
|
1162
|
if (type->isContainer()) {
|
|
1162
|
if (type->isContainer()) {
|
|
1163
|
ReportHandler::debugSparse(QString("container: '%1'").arg(full_class_name));
|
|
1163
|
ReportHandler::debugSparse(QString("container: '%1'").arg(full_class_name));
|
|
1164
|
} else {
|
|
1164
|
} else {
|
|
1165
|
ReportHandler::debugSparse(QString("class: '%1'").arg(meta_class->fullName()));
|
|
1165
|
ReportHandler::debugSparse(QString("class: '%1'").arg(meta_class->fullName()));
|
|
1166
|
}
|
|
1166
|
}
|
|
1167
|
|
|
1167
|
|
|
1168
|
TemplateParameterList template_parameters = class_item->templateParameters();
|
|
1168
|
TemplateParameterList template_parameters = class_item->templateParameters();
|
|
1169
|
QList<TypeEntry *> template_args;
|
|
1169
|
QList<TypeEntry *> template_args;
|
|
1170
|
template_args.clear();
|
|
1170
|
template_args.clear();
|
|
1171
|
for (int i=0; i<template_parameters.size(); ++i) {
|
|
1171
|
for (int i=0; i<template_parameters.size(); ++i) {
|
|
1172
|
const TemplateParameterModelItem ¶m = template_parameters.at(i);
|
|
1172
|
const TemplateParameterModelItem ¶m = template_parameters.at(i);
|
|
1173
|
TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name());
|
|
1173
|
TemplateArgumentEntry *param_type = new TemplateArgumentEntry(param->name());
|
|
1174
|
param_type->setOrdinal(i);
|
|
1174
|
param_type->setOrdinal(i);
|
|
1175
|
template_args.append(param_type);
|
|
1175
|
template_args.append(param_type);
|
|
1176
|
}
|
|
1176
|
}
|
|
1177
|
meta_class->setTemplateArguments(template_args);
|
|
1177
|
meta_class->setTemplateArguments(template_args);
|
|
1178
|
|
|
1178
|
|
|
1179
|
parseQ_Property(meta_class, class_item->propertyDeclarations());
|
|
1179
|
parseQ_Property(meta_class, class_item->propertyDeclarations());
|
|
1180
|
|
|
1180
|
|
|
1181
|
traverseFunctions(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
|
|
1181
|
traverseFunctions(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
|
|
1182
|
traverseEnums(model_dynamic_cast<ScopeModelItem>(class_item), meta_class, class_item->enumsDeclarations());
|
|
1182
|
traverseEnums(model_dynamic_cast<ScopeModelItem>(class_item), meta_class, class_item->enumsDeclarations());
|
|
1183
|
traverseFields(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
|
|
1183
|
traverseFields(model_dynamic_cast<ScopeModelItem>(class_item), meta_class);
|
|
1184
|
|
|
1184
|
|
|
1185
|
// Inner classes
|
|
1185
|
// Inner classes
|
|
1186
|
{
|
|
1186
|
{
|
|
1187
|
QList<ClassModelItem> inner_classes = class_item->classMap().values();
|
|
1187
|
QList<ClassModelItem> inner_classes = class_item->classMap().values();
|
|
1188
|
foreach (const ClassModelItem &ci, inner_classes) {
|
|
1188
|
foreach (const ClassModelItem &ci, inner_classes) {
|
|
1189
|
AbstractMetaClass *cl = traverseClass(ci);
|
|
1189
|
AbstractMetaClass *cl = traverseClass(ci);
|
|
1190
|
if (cl) {
|
|
1190
|
if (cl) {
|
|
1191
|
cl->setEnclosingClass(meta_class);
|
|
1191
|
cl->setEnclosingClass(meta_class);
|
|
1192
|
m_meta_classes << cl;
|
|
1192
|
m_meta_classes << cl;
|
|
1193
|
}
|
|
1193
|
}
|
|
1194
|
}
|
|
1194
|
}
|
|
1195
|
|
|
1195
|
|
|
1196
|
}
|
|
1196
|
}
|
|
1197
|
|
|
1197
|
|
|
1198
|
// Go through all typedefs to see if we have defined any
|
|
1198
|
// Go through all typedefs to see if we have defined any
|
|
1199
|
// specific typedefs to be used as classes.
|
|
1199
|
// specific typedefs to be used as classes.
|
|
1200
|
TypeAliasList typeAliases = class_item->typeAliases();
|
|
1200
|
TypeAliasList typeAliases = class_item->typeAliases();
|
|
1201
|
foreach (TypeAliasModelItem typeAlias, typeAliases) {
|
|
1201
|
foreach (TypeAliasModelItem typeAlias, typeAliases) {
|
|
1202
|
AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
|
|
1202
|
AbstractMetaClass *cls = traverseTypeAlias(typeAlias);
|
|
1203
|
if (cls != 0) {
|
|
1203
|
if (cls != 0) {
|
|
1204
|
cls->setEnclosingClass(meta_class);
|
|
1204
|
cls->setEnclosingClass(meta_class);
|
|
1205
|
addAbstractMetaClass(cls);
|
|
1205
|
addAbstractMetaClass(cls);
|
|
1206
|
}
|
|
1206
|
}
|
|
1207
|
}
|
|
1207
|
}
|
|
1208
|
|
|
1208
|
|
|
1209
|
|
|
1209
|
|
|
1210
|
m_current_class = old_current_class;
|
|
1210
|
m_current_class = old_current_class;
|
|
1211
|
|
|
1211
|
|
|
1212
|
// Set the default include file name
|
|
1212
|
// Set the default include file name
|
|
1213
|
if (!type->include().isValid()) {
|
|
1213
|
if (!type->include().isValid()) {
|
|
1214
|
QFileInfo info(class_item->fileName());
|
|
1214
|
QFileInfo info(class_item->fileName());
|
|
1215
|
type->setInclude(Include(Include::IncludePath, info.fileName()));
|
|
1215
|
type->setInclude(Include(Include::IncludePath, info.fileName()));
|
|
1216
|
}
|
|
1216
|
}
|
|
1217
|
|
|
1217
|
|
|
1218
|
return meta_class;
|
|
1218
|
return meta_class;
|
|
1219
|
}
|
|
1219
|
}
|
|
1220
|
|
|
1220
|
|
|
1221
|
AbstractMetaField *AbstractMetaBuilder::traverseField(VariableModelItem field, const AbstractMetaClass *cls)
|
|
1221
|
AbstractMetaField *AbstractMetaBuilder::traverseField(VariableModelItem field, const AbstractMetaClass *cls)
|
|
1222
|
{
|
|
1222
|
{
|
|
1223
|
QString field_name = field->name();
|
|
1223
|
QString field_name = field->name();
|
|
1224
|
QString class_name = m_current_class->typeEntry()->qualifiedCppName();
|
|
1224
|
QString class_name = m_current_class->typeEntry()->qualifiedCppName();
|
|
1225
|
|
|
1225
|
|
|
1226
|
// Ignore friend decl.
|
|
1226
|
// Ignore friend decl.
|
|
1227
|
if (field->isFriend())
|
|
1227
|
if (field->isFriend())
|
|
1228
|
return 0;
|
|
1228
|
return 0;
|
|
1229
|
|
|
1229
|
|
|
1230
|
if (field->accessPolicy() == CodeModel::Private)
|
|
1230
|
if (field->accessPolicy() == CodeModel::Private)
|
|
1231
|
return 0;
|
|
1231
|
return 0;
|
|
1232
|
|
|
1232
|
|
|
1233
|
if (TypeDatabase::instance()->isFieldRejected(class_name, field_name)) {
|
|
1233
|
if (TypeDatabase::instance()->isFieldRejected(class_name, field_name)) {
|
|
1234
|
m_rejected_fields.insert(class_name + "::" + field_name, GenerationDisabled);
|
|
1234
|
m_rejected_fields.insert(class_name + "::" + field_name, GenerationDisabled);
|
|
1235
|
return 0;
|
|
1235
|
return 0;
|
|
1236
|
}
|
|
1236
|
}
|
|
1237
|
|
|
1237
|
|
|
1238
|
|
|
1238
|
|
|
1239
|
AbstractMetaField *meta_field = createMetaField();
|
|
1239
|
AbstractMetaField *meta_field = createMetaField();
|
|
1240
|
meta_field->setName(field_name);
|
|
1240
|
meta_field->setName(field_name);
|
|
1241
|
meta_field->setEnclosingClass(cls);
|
|
1241
|
meta_field->setEnclosingClass(cls);
|
|
1242
|
|
|
1242
|
|
|
1243
|
bool ok;
|
|
1243
|
bool ok;
|
|
1244
|
TypeInfo field_type = field->type();
|
|
1244
|
TypeInfo field_type = field->type();
|
|
1245
|
AbstractMetaType *meta_type = translateType(field_type, &ok);
|
|
1245
|
AbstractMetaType *meta_type = translateType(field_type, &ok);
|
|
1246
|
|
|
1246
|
|
|
1247
|
if (!meta_type || !ok) {
|
|
1247
|
if (!meta_type || !ok) {
|
|
1248
|
ReportHandler::warning(QString("skipping field '%1::%2' with unmatched type '%3'")
|
|
1248
|
ReportHandler::warning(QString("skipping field '%1::%2' with unmatched type '%3'")
|
|
1249
|
.arg(m_current_class->name())
|
|
1249
|
.arg(m_current_class->name())
|
|
1250
|
.arg(field_name)
|
|
1250
|
.arg(field_name)
|
|
1251
|
.arg(TypeInfo::resolveType(field_type, currentScope()->toItem()).qualifiedName().join("::")));
|
|
1251
|
.arg(TypeInfo::resolveType(field_type, currentScope()->toItem()).qualifiedName().join("::")));
|
|
1252
|
delete meta_field;
|
|
1252
|
delete meta_field;
|
|
1253
|
return 0;
|
|
1253
|
return 0;
|
|
1254
|
}
|
|
1254
|
}
|
|
1255
|
|
|
1255
|
|
|
1256
|
meta_field->setType(meta_type);
|
|
1256
|
meta_field->setType(meta_type);
|
|
1257
|
|
|
1257
|
|
|
1258
|
uint attr = 0;
|
|
1258
|
uint attr = 0;
|
|
1259
|
if (field->isStatic())
|
|
1259
|
if (field->isStatic())
|
|
1260
|
attr |= AbstractMetaAttributes::Static;
|
|
1260
|
attr |= AbstractMetaAttributes::Static;
|
|
1261
|
|
|
1261
|
|
|
1262
|
CodeModel::AccessPolicy policy = field->accessPolicy();
|
|
1262
|
CodeModel::AccessPolicy policy = field->accessPolicy();
|
|
1263
|
if (policy == CodeModel::Public)
|
|
1263
|
if (policy == CodeModel::Public)
|
|
1264
|
attr |= AbstractMetaAttributes::Public;
|
|
1264
|
attr |= AbstractMetaAttributes::Public;
|
|
1265
|
else if (policy == CodeModel::Protected)
|
|
1265
|
else if (policy == CodeModel::Protected)
|
|
1266
|
attr |= AbstractMetaAttributes::Protected;
|
|
1266
|
attr |= AbstractMetaAttributes::Protected;
|
|
1267
|
else
|
|
1267
|
else
|
|
1268
|
attr |= AbstractMetaAttributes::Private;
|
|
1268
|
attr |= AbstractMetaAttributes::Private;
|
|
1269
|
meta_field->setAttributes(attr);
|
|
1269
|
meta_field->setAttributes(attr);
|
|
1270
|
|
|
1270
|
|
|
1271
|
return meta_field;
|
|
1271
|
return meta_field;
|
|
1272
|
}
|
|
1272
|
}
|
|
1273
|
|
|
1273
|
|
|
1274
|
void AbstractMetaBuilder::traverseFields(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
|
|
1274
|
void AbstractMetaBuilder::traverseFields(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
|
|
1275
|
{
|
|
1275
|
{
|
|
1276
|
foreach (VariableModelItem field, scope_item->variables()) {
|
|
1276
|
foreach (VariableModelItem field, scope_item->variables()) {
|
|
1277
|
AbstractMetaField *meta_field = traverseField(field, meta_class);
|
|
1277
|
AbstractMetaField *meta_field = traverseField(field, meta_class);
|
|
1278
|
|
|
1278
|
|
|
1279
|
if (meta_field) {
|
|
1279
|
if (meta_field) {
|
|
1280
|
meta_field->setOriginalAttributes(meta_field->attributes());
|
|
1280
|
meta_field->setOriginalAttributes(meta_field->attributes());
|
|
1281
|
meta_class->addField(meta_field);
|
|
1281
|
meta_class->addField(meta_field);
|
|
1282
|
}
|
|
1282
|
}
|
|
1283
|
}
|
|
1283
|
}
|
|
1284
|
}
|
|
1284
|
}
|
|
1285
|
|
|
1285
|
|
|
1286
|
void AbstractMetaBuilder::setupFunctionDefaults(AbstractMetaFunction *meta_function, AbstractMetaClass *meta_class)
|
|
1286
|
void AbstractMetaBuilder::setupFunctionDefaults(AbstractMetaFunction *meta_function, AbstractMetaClass *meta_class)
|
|
1287
|
{
|
|
1287
|
{
|
|
1288
|
// Set the default value of the declaring class. This may be changed
|
|
1288
|
// Set the default value of the declaring class. This may be changed
|
|
1289
|
// in fixFunctions later on
|
|
1289
|
// in fixFunctions later on
|
|
1290
|
meta_function->setDeclaringClass(meta_class);
|
|
1290
|
meta_function->setDeclaringClass(meta_class);
|
|
1291
|
|
|
1291
|
|
|
1292
|
// Some of the queries below depend on the implementing class being set
|
|
1292
|
// Some of the queries below depend on the implementing class being set
|
|
1293
|
// to function properly. Such as function modifications
|
|
1293
|
// to function properly. Such as function modifications
|
|
1294
|
meta_function->setImplementingClass(meta_class);
|
|
1294
|
meta_function->setImplementingClass(meta_class);
|
|
1295
|
|
|
1295
|
|
|
1296
|
if (meta_function->name() == "operator_equal")
|
|
1296
|
if (meta_function->name() == "operator_equal")
|
|
1297
|
meta_class->setHasEqualsOperator(true);
|
|
1297
|
meta_class->setHasEqualsOperator(true);
|
|
1298
|
|
|
1298
|
|
|
1299
|
if (!meta_function->isFinalInTargetLang()
|
|
1299
|
if (!meta_function->isFinalInTargetLang()
|
|
1300
|
&& meta_function->isRemovedFrom(meta_class, TypeSystem::TargetLangCode)) {
|
|
1300
|
&& meta_function->isRemovedFrom(meta_class, TypeSystem::TargetLangCode)) {
|
|
1301
|
*meta_function += AbstractMetaAttributes::FinalInCpp;
|
|
1301
|
*meta_function += AbstractMetaAttributes::FinalInCpp;
|
|
1302
|
}
|
|
1302
|
}
|
|
1303
|
}
|
|
1303
|
}
|
|
1304
|
|
|
1304
|
|
|
1305
|
void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
|
|
1305
|
void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scope_item, AbstractMetaClass *meta_class)
|
|
1306
|
{
|
|
1306
|
{
|
|
1307
|
foreach (FunctionModelItem function, scope_item->functions()) {
|
|
1307
|
foreach (FunctionModelItem function, scope_item->functions()) {
|
|
1308
|
AbstractMetaFunction *meta_function = traverseFunction(function);
|
|
1308
|
AbstractMetaFunction *meta_function = traverseFunction(function);
|
|
1309
|
|
|
1309
|
|
|
1310
|
if (meta_function) {
|
|
1310
|
if (meta_function) {
|
|
1311
|
meta_function->setOriginalAttributes(meta_function->attributes());
|
|
1311
|
meta_function->setOriginalAttributes(meta_function->attributes());
|
|
1312
|
if (meta_class->isNamespace())
|
|
1312
|
if (meta_class->isNamespace())
|
|
1313
|
*meta_function += AbstractMetaAttributes::Static;
|
|
1313
|
*meta_function += AbstractMetaAttributes::Static;
|
|
1314
|
|
|
1314
|
|
|
1315
|
if (QPropertySpec *read = meta_class->propertySpecForRead(meta_function->name())) {
|
|
1315
|
if (QPropertySpec *read = meta_class->propertySpecForRead(meta_function->name())) {
|
|
1316
|
if (read->type() == meta_function->type()->typeEntry()) {
|
|
1316
|
if (read->type() == meta_function->type()->typeEntry()) {
|
|
1317
|
*meta_function += AbstractMetaAttributes::PropertyReader;
|
|
1317
|
*meta_function += AbstractMetaAttributes::PropertyReader;
|
|
1318
|
meta_function->setPropertySpec(read);
|
|
1318
|
meta_function->setPropertySpec(read);
|
|
1319
|
// printf("%s is reader for %s\n",
|
|
1319
|
// printf("%s is reader for %s\n",
|
|
1320
|
// qPrintable(meta_function->name()),
|
|
1320
|
// qPrintable(meta_function->name()),
|
|
1321
|
// qPrintable(read->name()));
|
|
1321
|
// qPrintable(read->name()));
|
|
1322
|
}
|
|
1322
|
}
|
|
1323
|
} else if (QPropertySpec *write =
|
|
1323
|
} else if (QPropertySpec *write =
|
|
1324
|
meta_class->propertySpecForWrite(meta_function->name())) {
|
|
1324
|
meta_class->propertySpecForWrite(meta_function->name())) {
|
|
1325
|
if (write->type() == meta_function->arguments().at(0)->type()->typeEntry()) {
|
|
1325
|
if (write->type() == meta_function->arguments().at(0)->type()->typeEntry()) {
|
|
1326
|
*meta_function += AbstractMetaAttributes::PropertyWriter;
|
|
1326
|
*meta_function += AbstractMetaAttributes::PropertyWriter;
|
|
1327
|
meta_function->setPropertySpec(write);
|
|
1327
|
meta_function->setPropertySpec(write);
|
|
1328
|
// printf("%s is writer for %s\n",
|
|
1328
|
// printf("%s is writer for %s\n",
|
|
1329
|
// qPrintable(meta_function->name()),
|
|
1329
|
// qPrintable(meta_function->name()),
|
|
1330
|
// qPrintable(write->name()));
|
|
1330
|
// qPrintable(write->name()));
|
|
1331
|
}
|
|
1331
|
}
|
|
1332
|
} else if (QPropertySpec *reset =
|
|
1332
|
} else if (QPropertySpec *reset =
|
|
1333
|
meta_class->propertySpecForReset(meta_function->name())) {
|
|
1333
|
meta_class->propertySpecForReset(meta_function->name())) {
|
|
1334
|
*meta_function += AbstractMetaAttributes::PropertyResetter;
|
|
1334
|
*meta_function += AbstractMetaAttributes::PropertyResetter;
|
|
1335
|
meta_function->setPropertySpec(reset);
|
|
1335
|
meta_function->setPropertySpec(reset);
|
|
1336
|
// printf("%s is resetter for %s\n",
|
|
1336
|
// printf("%s is resetter for %s\n",
|
|
1337
|
// qPrintable(meta_function->name()),
|
|
1337
|
// qPrintable(meta_function->name()),
|
|
1338
|
// qPrintable(reset->name()));
|
|
1338
|
// qPrintable(reset->name()));
|
|
1339
|
}
|
|
1339
|
}
|
|
1340
|
|
|
1340
|
|
|
1341
|
|
|
1341
|
|
|
1342
|
bool isInvalidDestructor = meta_function->isDestructor() && meta_function->isPrivate();
|
|
1342
|
bool isInvalidDestructor = meta_function->isDestructor() && meta_function->isPrivate();
|
|
1343
|
bool isInvalidConstructor = meta_function->isConstructor()
|
|
1343
|
bool isInvalidConstructor = meta_function->isConstructor()
|
|
1344
|
&& (meta_function->isPrivate() || meta_function->isInvalid());
|
|
1344
|
&& (meta_function->isPrivate() || meta_function->isInvalid());
|
|
1345
|
if ((isInvalidDestructor || isInvalidConstructor)
|
|
1345
|
if ((isInvalidDestructor || isInvalidConstructor)
|
|
1346
|
&& !meta_class->hasNonPrivateConstructor()) {
|
|
1346
|
&& !meta_class->hasNonPrivateConstructor()) {
|
|
1347
|
*meta_class += AbstractMetaAttributes::Final;
|
|
1347
|
*meta_class += AbstractMetaAttributes::Final;
|
|
1348
|
} else if (meta_function->isConstructor() && !meta_function->isPrivate()) {
|
|
1348
|
} else if (meta_function->isConstructor() && !meta_function->isPrivate()) {
|
|
1349
|
*meta_class -= AbstractMetaAttributes::Final;
|
|
1349
|
*meta_class -= AbstractMetaAttributes::Final;
|
|
1350
|
meta_class->setHasNonPrivateConstructor(true);
|
|
1350
|
meta_class->setHasNonPrivateConstructor(true);
|
|
1351
|
}
|
|
1351
|
}
|
|
1352
|
|
|
1352
|
|
|
1353
|
// Classes with virtual destructors should always have a shell class
|
|
1353
|
// Classes with virtual destructors should always have a shell class
|
|
1354
|
// (since we aren't registering the destructors, we need this extra check)
|
|
1354
|
// (since we aren't registering the destructors, we need this extra check)
|
|
1355
|
if (meta_function->isDestructor() && !meta_function->isFinal())
|
|
1355
|
if (meta_function->isDestructor() && !meta_function->isFinal())
|
|
1356
|
meta_class->setForceShellClass(true);
|
|
1356
|
meta_class->setForceShellClass(true);
|
|
1357
|
|
|
1357
|
|
|
1358
|
if (!meta_function->isDestructor()
|
|
1358
|
if (!meta_function->isDestructor()
|
|
1359
|
&& !meta_function->isInvalid()
|
|
1359
|
&& !meta_function->isInvalid()
|
|
1360
|
&& (!meta_function->isConstructor() || !meta_function->isPrivate())) {
|
|
1360
|
&& (!meta_function->isConstructor() || !meta_function->isPrivate())) {
|
|
1361
|
|
|
1361
|
|
|
1362
|
if (meta_class->typeEntry()->designatedInterface() && !meta_function->isPublic()
|
|
1362
|
if (meta_class->typeEntry()->designatedInterface() && !meta_function->isPublic()
|
|
1363
|
&& !meta_function->isPrivate()) {
|
|
1363
|
&& !meta_function->isPrivate()) {
|
|
1364
|
QString warn = QString("non-public function '%1' in interface '%2'")
|
|
1364
|
QString warn = QString("non-public function '%1' in interface '%2'")
|
|
1365
|
.arg(meta_function->name()).arg(meta_class->name());
|
|
1365
|
.arg(meta_function->name()).arg(meta_class->name());
|
|
1366
|
ReportHandler::warning(warn);
|
|
1366
|
ReportHandler::warning(warn);
|
|
1367
|
|
|
1367
|
|
|
1368
|
meta_function->setVisibility(AbstractMetaClass::Public);
|
|
1368
|
meta_function->setVisibility(AbstractMetaClass::Public);
|
|
1369
|
}
|
|
1369
|
}
|
|
1370
|
|
|
1370
|
|
|
1371
|
setupFunctionDefaults(meta_function, meta_class);
|
|
1371
|
setupFunctionDefaults(meta_function, meta_class);
|
|
1372
|
|
|
1372
|
|
|
1373
|
if (meta_function->isSignal() && meta_class->hasSignal(meta_function)) {
|
|
1373
|
if (meta_function->isSignal() && meta_class->hasSignal(meta_function)) {
|
|
1374
|
QString warn = QString("signal '%1' in class '%2' is overloaded.")
|
|
1374
|
QString warn = QString("signal '%1' in class '%2' is overloaded.")
|
|
1375
|
.arg(meta_function->name()).arg(meta_class->name());
|
|
1375
|
.arg(meta_function->name()).arg(meta_class->name());
|
|
1376
|
ReportHandler::warning(warn);
|
|
1376
|
ReportHandler::warning(warn);
|
|
1377
|
}
|
|
1377
|
}
|
|
1378
|
|
|
1378
|
|
|
1379
|
if (meta_function->isSignal() && !meta_class->isQObject()) {
|
|
1379
|
if (meta_function->isSignal() && !meta_class->isQObject()) {
|
|
1380
|
QString warn = QString("signal '%1' in non-QObject class '%2'")
|
|
1380
|
QString warn = QString("signal '%1' in non-QObject class '%2'")
|
|
1381
|
.arg(meta_function->name()).arg(meta_class->name());
|
|
1381
|
.arg(meta_function->name()).arg(meta_class->name());
|
|
1382
|
ReportHandler::warning(warn);
|
|
1382
|
ReportHandler::warning(warn);
|
|
1383
|
}
|
|
1383
|
}
|
|
1384
|
|
|
1384
|
|
|
1385
|
meta_class->addFunction(meta_function);
|
|
1385
|
meta_class->addFunction(meta_function);
|
|
1386
|
} else if (meta_function->isDestructor() && !meta_function->isPublic()) {
|
|
1386
|
} else if (meta_function->isDestructor() && !meta_function->isPublic()) {
|
|
1387
|
meta_class->setHasPublicDestructor(false);
|
|
1387
|
meta_class->setHasPublicDestructor(false);
|
|
1388
|
}
|
|
1388
|
}
|
|
1389
|
}
|
|
1389
|
}
|
|
1390
|
}
|
|
1390
|
}
|
|
1391
|
}
|
|
1391
|
}
|
|
1392
|
|
|
1392
|
|
|
1393
|
bool AbstractMetaBuilder::setupInheritance(AbstractMetaClass *meta_class)
|
|
1393
|
bool AbstractMetaBuilder::setupInheritance(AbstractMetaClass *meta_class)
|
|
1394
|
{
|
|
1394
|
{
|
|
1395
|
Q_ASSERT(!meta_class->isInterface());
|
|
1395
|
Q_ASSERT(!meta_class->isInterface());
|
|
1396
|
|
|
1396
|
|
|
1397
|
if (m_setup_inheritance_done.contains(meta_class))
|
|
1397
|
if (m_setup_inheritance_done.contains(meta_class))
|
|
1398
|
return true;
|
|
1398
|
return true;
|
|
1399
|
m_setup_inheritance_done.insert(meta_class);
|
|
1399
|
m_setup_inheritance_done.insert(meta_class);
|
|
1400
|
|
|
1400
|
|
|
1401
|
QStringList base_classes = meta_class->baseClassNames();
|
|
1401
|
QStringList base_classes = meta_class->baseClassNames();
|
|
1402
|
|
|
1402
|
|
|
1403
|
TypeDatabase *types = TypeDatabase::instance();
|
|
1403
|
TypeDatabase *types = TypeDatabase::instance();
|
|
1404
|
|
|
1404
|
|
|
1405
|
// we only support our own containers and ONLY if there is only one baseclass
|
|
1405
|
// we only support our own containers and ONLY if there is only one baseclass
|
|
1406
|
if (base_classes.size() == 1 && base_classes.first().count('<') == 1) {
|
|
1406
|
if (base_classes.size() == 1 && base_classes.first().count('<') == 1) {
|
|
1407
|
QStringList scope = meta_class->typeEntry()->qualifiedCppName().split("::");
|
|
1407
|
QStringList scope = meta_class->typeEntry()->qualifiedCppName().split("::");
|
|
1408
|
scope.removeLast();
|
|
1408
|
scope.removeLast();
|
|
1409
|
for (int i=scope.size(); i>=0; --i) {
|
|
1409
|
for (int i=scope.size(); i>=0; --i) {
|
|
1410
|
QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join("::") + "::" : QString();
|
|
1410
|
QString prefix = i > 0 ? QStringList(scope.mid(0, i)).join("::") + "::" : QString();
|
|
1411
|
QString complete_name = prefix + base_classes.first();
|
|
1411
|
QString complete_name = prefix + base_classes.first();
|
|
1412
|
TypeParser::Info info = TypeParser::parse(complete_name);
|
|
1412
|
TypeParser::Info info = TypeParser::parse(complete_name);
|
|
1413
|
QString base_name = info.qualified_name.join("::");
|
|
1413
|
QString base_name = info.qualified_name.join("::");
|
|
1414
|
|
|
1414
|
|
|
1415
|
AbstractMetaClass *templ = 0;
|
|
1415
|
AbstractMetaClass *templ = 0;
|
|
1416
|
foreach (AbstractMetaClass *c, m_templates) {
|
|
1416
|
foreach (AbstractMetaClass *c, m_templates) {
|
|
1417
|
if (c->typeEntry()->name() == base_name) {
|
|
1417
|
if (c->typeEntry()->name() == base_name) {
|
|
1418
|
templ = c;
|
|
1418
|
templ = c;
|
|
1419
|
break;
|
|
1419
|
break;
|
|
1420
|
}
|
|
1420
|
}
|
|
1421
|
}
|
|
1421
|
}
|
|
1422
|
|
|
1422
|
|
|
1423
|
if (templ == 0)
|
|
1423
|
if (templ == 0)
|
|
1424
|
templ = m_meta_classes.findClass(base_name);
|
|
1424
|
templ = m_meta_classes.findClass(base_name);
|
|
1425
|
|
|
1425
|
|
|
1426
|
if (templ) {
|
|
1426
|
if (templ) {
|
|
1427
|
setupInheritance(templ);
|
|
1427
|
setupInheritance(templ);
|
|
1428
|
inheritTemplate(meta_class, templ, info);
|
|
1428
|
inheritTemplate(meta_class, templ, info);
|
|
1429
|
return true;
|
|
1429
|
return true;
|
|
1430
|
}
|
|
1430
|
}
|
|
1431
|
}
|
|
1431
|
}
|
|
1432
|
|
|
1432
|
|
|
1433
|
ReportHandler::warning(QString("template baseclass '%1' of '%2' is not known")
|
|
1433
|
ReportHandler::warning(QString("template baseclass '%1' of '%2' is not known")
|
|
1434
|
.arg(base_classes.first())
|
|
1434
|
.arg(base_classes.first())
|
|
1435
|
.arg(meta_class->name()));
|
|
1435
|
.arg(meta_class->name()));
|
|
1436
|
return false;
|
|
1436
|
return false;
|
|
1437
|
}
|
|
1437
|
}
|
|
1438
|
|
|
1438
|
|
|
1439
|
int primary = -1;
|
|
1439
|
int primary = -1;
|
|
1440
|
int primaries = 0;
|
|
1440
|
int primaries = 0;
|
|
1441
|
for (int i=0; i<base_classes.size(); ++i) {
|
|
1441
|
for (int i=0; i<base_classes.size(); ++i) {
|
|
1442
|
|
|
1442
|
|
|
1443
|
if (types->isClassRejected(base_classes.at(i)))
|
|
1443
|
if (types->isClassRejected(base_classes.at(i)))
|
|
1444
|
continue;
|
|
1444
|
continue;
|
|
1445
|
|
|
1445
|
|
|
1446
|
TypeEntry *base_class_entry = types->findType(base_classes.at(i));
|
|
1446
|
TypeEntry *base_class_entry = types->findType(base_classes.at(i));
|
|
1447
|
if (!base_class_entry) {
|
|
1447
|
if (!base_class_entry) {
|
|
1448
|
ReportHandler::warning(QString("class '%1' inherits from unknown base class '%2'")
|
|
1448
|
ReportHandler::warning(QString("class '%1' inherits from unknown base class '%2'")
|
|
1449
|
.arg(meta_class->name()).arg(base_classes.at(i)));
|
|
1449
|
.arg(meta_class->name()).arg(base_classes.at(i)));
|
|
1450
|
}
|
|
1450
|
}
|
|
1451
|
|
|
1451
|
|
|
1452
|
// true for primary base class
|
|
1452
|
// true for primary base class
|
|
1453
|
else if (!base_class_entry->designatedInterface()) {
|
|
1453
|
else if (!base_class_entry->designatedInterface()) {
|
|
1454
|
if (primaries > 0) {
|
|
1454
|
if (primaries > 0) {
|
|
1455
|
ReportHandler::warning(QString("class '%1' has multiple primary base classes"
|
|
1455
|
ReportHandler::warning(QString("class '%1' has multiple primary base classes"
|
|
1456
|
" '%2' and '%3'")
|
|
1456
|
" '%2' and '%3'")
|
|
1457
|
.arg(meta_class->name())
|
|
1457
|
.arg(meta_class->name())
|
|
1458
|
.arg(base_classes.at(primary))
|
|
1458
|
.arg(base_classes.at(primary))
|
|
1459
|
.arg(base_class_entry->name()));
|
|
1459
|
.arg(base_class_entry->name()));
|
|
1460
|
return false;
|
|
1460
|
return false;
|
|
1461
|
}
|
|
1461
|
}
|
|
1462
|
primaries++;
|
|
1462
|
primaries++;
|
|
1463
|
primary = i;
|
|
1463
|
primary = i;
|
|
1464
|
}
|
|
1464
|
}
|
|
1465
|
}
|
|
1465
|
}
|
|
1466
|
|
|
1466
|
|
|
1467
|
if (primary >= 0) {
|
|
1467
|
if (primary >= 0) {
|
|
1468
|
AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(primary));
|
|
1468
|
AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(primary));
|
|
1469
|
if (!base_class) {
|
|
1469
|
if (!base_class) {
|
|
1470
|
ReportHandler::warning(QString("unknown baseclass for '%1': '%2'")
|
|
1470
|
ReportHandler::warning(QString("unknown baseclass for '%1': '%2'")
|
|
1471
|
.arg(meta_class->name())
|
|
1471
|
.arg(meta_class->name())
|
|
1472
|
.arg(base_classes.at(primary)));
|
|
1472
|
.arg(base_classes.at(primary)));
|
|
1473
|
return false;
|
|
1473
|
return false;
|
|
1474
|
}
|
|
1474
|
}
|
|
1475
|
meta_class->setBaseClass(base_class);
|
|
1475
|
meta_class->setBaseClass(base_class);
|
|
1476
|
|
|
1476
|
|
|
1477
|
if (meta_class->typeEntry()->designatedInterface() != 0 && meta_class->isQObject()) {
|
|
1477
|
if (meta_class->typeEntry()->designatedInterface() != 0 && meta_class->isQObject()) {
|
|
1478
|
ReportHandler::warning(QString("QObject extended by interface type '%1'. This is not supported and the generated Java code will not compile.")
|
|
1478
|
ReportHandler::warning(QString("QObject extended by interface type '%1'. This is not supported and the generated Java code will not compile.")
|
|
1479
|
.arg(meta_class->name()));
|
|
1479
|
.arg(meta_class->name()));
|
|
1480
|
} else if (meta_class->typeEntry()->designatedInterface() != 0 && base_class != 0 && !base_class->isInterface()) {
|
|
1480
|
} else if (meta_class->typeEntry()->designatedInterface() != 0 && base_class != 0 && !base_class->isInterface()) {
|
|
1481
|
ReportHandler::warning(QString("object type '%1' extended by interface type '%2'. The resulting API will be less expressive than the original.")
|
|
1481
|
ReportHandler::warning(QString("object type '%1' extended by interface type '%2'. The resulting API will be less expressive than the original.")
|
|
1482
|
.arg(base_class->name())
|
|
1482
|
.arg(base_class->name())
|
|
1483
|
.arg(meta_class->name()));
|
|
1483
|
.arg(meta_class->name()));
|
|
1484
|
}
|
|
1484
|
}
|
|
1485
|
|
|
1485
|
|
|
1486
|
}
|
|
1486
|
}
|
|
1487
|
|
|
1487
|
|
|
1488
|
for (int i=0; i<base_classes.size(); ++i) {
|
|
1488
|
for (int i=0; i<base_classes.size(); ++i) {
|
|
1489
|
if (types->isClassRejected(base_classes.at(i)))
|
|
1489
|
if (types->isClassRejected(base_classes.at(i)))
|
|
1490
|
continue;
|
|
1490
|
continue;
|
|
1491
|
|
|
1491
|
|
|
1492
|
if (i != primary) {
|
|
1492
|
if (i != primary) {
|
|
1493
|
AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(i));
|
|
1493
|
AbstractMetaClass *base_class = m_meta_classes.findClass(base_classes.at(i));
|
|
1494
|
if (base_class == 0) {
|
|
1494
|
if (base_class == 0) {
|
|
1495
|
ReportHandler::warning(QString("class not found for setup inheritance '%1'").arg(base_classes.at(i)));
|
|
1495
|
ReportHandler::warning(QString("class not found for setup inheritance '%1'").arg(base_classes.at(i)));
|
|
1496
|
return false;
|
|
1496
|
return false;
|
|
1497
|
}
|
|
1497
|
}
|
|
1498
|
|
|
1498
|
|
|
1499
|
setupInheritance(base_class);
|
|
1499
|
setupInheritance(base_class);
|
|
1500
|
|
|
1500
|
|
|
1501
|
QString interface_name = InterfaceTypeEntry::interfaceName(base_class->name());
|
|
1501
|
QString interface_name = InterfaceTypeEntry::interfaceName(base_class->name());
|
|
1502
|
AbstractMetaClass *iface = m_meta_classes.findClass(interface_name);
|
|
1502
|
AbstractMetaClass *iface = m_meta_classes.findClass(interface_name);
|
|
1503
|
if (!iface) {
|
|
1503
|
if (!iface) {
|
|
1504
|
ReportHandler::warning(QString("unknown interface for '%1': '%2'")
|
|
1504
|
ReportHandler::warning(QString("unknown interface for '%1': '%2'")
|
|
1505
|
.arg(meta_class->name())
|
|
1505
|
.arg(meta_class->name())
|
|
1506
|
.arg(interface_name));
|
|
1506
|
.arg(interface_name));
|
|
1507
|
return false;
|
|
1507
|
return false;
|
|
1508
|
}
|
|
1508
|
}
|
|
1509
|
meta_class->addInterface(iface);
|
|
1509
|
meta_class->addInterface(iface);
|
|
1510
|
|
|
1510
|
|
|
1511
|
AbstractMetaClassList interfaces = iface->interfaces();
|
|
1511
|
AbstractMetaClassList interfaces = iface->interfaces();
|
|
1512
|
foreach (AbstractMetaClass *iface, interfaces)
|
|
1512
|
foreach (AbstractMetaClass *iface, interfaces)
|
|
1513
|
meta_class->addInterface(iface);
|
|
1513
|
meta_class->addInterface(iface);
|
|
1514
|
}
|
|
1514
|
}
|
|
1515
|
}
|
|
1515
|
}
|
|
1516
|
|
|
1516
|
|
|
1517
|
return true;
|
|
1517
|
return true;
|
|
1518
|
}
|
|
1518
|
}
|
|
1519
|
|
|
1519
|
|
|
1520
|
void AbstractMetaBuilder::traverseEnums(ScopeModelItem scope_item, AbstractMetaClass *meta_class, const QStringList &enumsDeclarations)
|
|
1520
|
void AbstractMetaBuilder::traverseEnums(ScopeModelItem scope_item, AbstractMetaClass *meta_class, const QStringList &enumsDeclarations)
|
|
1521
|
{
|
|
1521
|
{
|
|
1522
|
EnumList enums = scope_item->enums();
|
|
1522
|
EnumList enums = scope_item->enums();
|
|
1523
|
foreach (EnumModelItem enum_item, enums) {
|
|
1523
|
foreach (EnumModelItem enum_item, enums) {
|
|
1524
|
AbstractMetaEnum *meta_enum = traverseEnum(enum_item, meta_class, QSet<QString>::fromList(enumsDeclarations));
|
|
1524
|
AbstractMetaEnum *meta_enum = traverseEnum(enum_item, meta_class, QSet<QString>::fromList(enumsDeclarations));
|
|
1525
|
if (meta_enum) {
|
|
1525
|
if (meta_enum) {
|
|
1526
|
meta_enum->setOriginalAttributes(meta_enum->attributes());
|
|
1526
|
meta_enum->setOriginalAttributes(meta_enum->attributes());
|
|
1527
|
meta_class->addEnum(meta_enum);
|
|
1527
|
meta_class->addEnum(meta_enum);
|
|
1528
|
meta_enum->setEnclosingClass(meta_class);
|
|
1528
|
meta_enum->setEnclosingClass(meta_class);
|
|
1529
|
}
|
|
1529
|
}
|
|
1530
|
}
|
|
1530
|
}
|
|
1531
|
}
|
|
1531
|
}
|
|
1532
|
|
|
1532
|
|
|
1533
|
AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(FunctionModelItem function_item)
|
|
1533
|
AbstractMetaFunction *AbstractMetaBuilder::traverseFunction(FunctionModelItem function_item)
|
|
1534
|
{
|
|
1534
|
{
|
|
1535
|
QString function_name = function_item->name();
|
|
1535
|
QString function_name = function_item->name();
|
|
1536
|
QString class_name = m_current_class->typeEntry()->qualifiedCppName();
|
|
1536
|
QString class_name = m_current_class->typeEntry()->qualifiedCppName();
|
|
1537
|
|
|
1537
|
|
|
1538
|
if (TypeDatabase::instance()->isFunctionRejected(class_name, function_name)) {
|
|
1538
|
if (TypeDatabase::instance()->isFunctionRejected(class_name, function_name)) {
|
|
1539
|
m_rejected_functions.insert(class_name + "::" + function_name, GenerationDisabled);
|
|
1539
|
m_rejected_functions.insert(class_name + "::" + function_name, GenerationDisabled);
|
|
1540
|
return 0;
|
|
1540
|
return 0;
|
|
1541
|
}
|
|
1541
|
}
|
|
1542
|
|
|
1542
|
|
|
1543
|
|
|
1543
|
|
|
1544
|
Q_ASSERT(function_item->functionType() == CodeModel::Normal
|
|
1544
|
Q_ASSERT(function_item->functionType() == CodeModel::Normal
|
|
1545
|
|| function_item->functionType() == CodeModel::Signal
|
|
1545
|
|| function_item->functionType() == CodeModel::Signal
|
|
1546
|
|| function_item->functionType() == CodeModel::Slot);
|
|
1546
|
|| function_item->functionType() == CodeModel::Slot);
|
|
1547
|
|
|
1547
|
|
|
1548
|
if (function_item->isFriend())
|
|
1548
|
if (function_item->isFriend())
|
|
1549
|
return 0;
|
|
1549
|
return 0;
|
|
1550
|
|
|
1550
|
|
|
1551
|
|
|
1551
|
|
|
1552
|
QString cast_type;
|
|
1552
|
QString cast_type;
|
|
1553
|
|
|
1553
|
|
|
1554
|
if (function_name.startsWith("operator")) {
|
|
1554
|
if (function_name.startsWith("operator")) {
|
|
1555
|
function_name = rename_operator(function_name.mid(8));
|
|
1555
|
function_name = rename_operator(function_name.mid(8));
|
|
1556
|
if (function_name.isEmpty()) {
|
|
1556
|
if (function_name.isEmpty()) {
|
|
1557
|
m_rejected_functions.insert(class_name + "::" + function_name,
|
|
1557
|
m_rejected_functions.insert(class_name + "::" + function_name,
|
|
1558
|
GenerationDisabled);
|
|
1558
|
GenerationDisabled);
|
|
1559
|
return 0;
|
|
1559
|
return 0;
|
|
1560
|
}
|
|
1560
|
}
|
|
1561
|
if (function_name.contains("_cast_"))
|
|
1561
|
if (function_name.contains("_cast_"))
|
|
1562
|
cast_type = function_name.mid(14).trimmed();
|
|
1562
|
cast_type = function_name.mid(14).trimmed();
|
|
1563
|
}
|
|
1563
|
}
|
|
1564
|
|
|
1564
|
|
|
1565
|
AbstractMetaFunction *meta_function = createMetaFunction();
|
|
1565
|
AbstractMetaFunction *meta_function = createMetaFunction();
|
|
1566
|
meta_function->setConstant(function_item->isConstant());
|
|
1566
|
meta_function->setConstant(function_item->isConstant());
|
|
1567
|
|
|
1567
|
|
|
1568
|
ReportHandler::debugMedium(QString(" - %2()").arg(function_name));
|
|
1568
|
ReportHandler::debugMedium(QString(" - %2()").arg(function_name));
|
|
1569
|
|
|
1569
|
|
|
1570
|
meta_function->setName(function_name);
|
|
1570
|
meta_function->setName(function_name);
|
|
1571
|
meta_function->setOriginalName(function_item->name());
|
|
1571
|
meta_function->setOriginalName(function_item->name());
|
|
1572
|
|
|
1572
|
|
|
1573
|
if (function_item->isAbstract())
|
|
1573
|
if (function_item->isAbstract())
|
|
1574
|
*meta_function += AbstractMetaAttributes::Abstract;
|
|
1574
|
*meta_function += AbstractMetaAttributes::Abstract;
|
|
1575
|
|
|
1575
|
|
|
1576
|
if (!meta_function->isAbstract())
|
|
1576
|
if (!meta_function->isAbstract())
|
|
1577
|
*meta_function += AbstractMetaAttributes::Native;
|
|
1577
|
*meta_function += AbstractMetaAttributes::Native;
|
|
1578
|
|
|
1578
|
|
|
1579
|
if (!function_item->isVirtual())
|
|
1579
|
if (!function_item->isVirtual())
|
|
1580
|
*meta_function += AbstractMetaAttributes::Final;
|
|
1580
|
*meta_function += AbstractMetaAttributes::Final;
|
|
1581
|
|
|
1581
|
|
|
1582
|
if (function_item->isInvokable())
|
|
1582
|
if (function_item->isInvokable())
|
|
1583
|
*meta_function += AbstractMetaAttributes::Invokable;
|
|
1583
|
*meta_function += AbstractMetaAttributes::Invokable;
|
|
1584
|
|
|
1584
|
|
|
1585
|
if (function_item->isStatic()) {
|
|
1585
|
if (function_item->isStatic()) {
|
|
1586
|
*meta_function += AbstractMetaAttributes::Static;
|
|
1586
|
*meta_function += AbstractMetaAttributes::Static;
|
|
1587
|
*meta_function += AbstractMetaAttributes::Final;
|
|
1587
|
*meta_function += AbstractMetaAttributes::Final;
|
|
1588
|
}
|
|
1588
|
}
|
|
1589
|
|
|
1589
|
|
|
1590
|
// Access rights
|
|
1590
|
// Access rights
|
|
1591
|
if (function_item->accessPolicy() == CodeModel::Public)
|
|
1591
|
if (function_item->accessPolicy() == CodeModel::Public)
|
|
1592
|
*meta_function += AbstractMetaAttributes::Public;
|
|
1592
|
*meta_function += AbstractMetaAttributes::Public;
|
|
1593
|
else if (function_item->accessPolicy() == CodeModel::Private)
|
|
1593
|
else if (function_item->accessPolicy() == CodeModel::Private)
|
|
1594
|
*meta_function += AbstractMetaAttributes::Private;
|
|
1594
|
*meta_function += AbstractMetaAttributes::Private;
|
|
1595
|
else
|
|
1595
|
else
|
|
1596
|
*meta_function += AbstractMetaAttributes::Protected;
|
|
1596
|
*meta_function += AbstractMetaAttributes::Protected;
|
|
1597
|
|
|
1597
|
|
|
1598
|
|
|
1598
|
|
|
1599
|
QString stripped_class_name = class_name;
|
|
1599
|
QString stripped_class_name = class_name;
|
|
1600
|
int cc_pos = stripped_class_name.lastIndexOf("::");
|
|
1600
|
int cc_pos = stripped_class_name.lastIndexOf("::");
|
|
1601
|
if (cc_pos > 0)
|
|
1601
|
if (cc_pos > 0)
|
|
1602
|
stripped_class_name = stripped_class_name.mid(cc_pos + 2);
|
|
1602
|
stripped_class_name = stripped_class_name.mid(cc_pos + 2);
|
|
1603
|
|
|
1603
|
|
|
1604
|
TypeInfo function_type = function_item->type();
|
|
1604
|
TypeInfo function_type = function_item->type();
|
|
1605
|
if (function_name.startsWith('~')) {
|
|
1605
|
if (function_name.startsWith('~')) {
|
|
1606
|
meta_function->setFunctionType(AbstractMetaFunction::DestructorFunction);
|
|
1606
|
meta_function->setFunctionType(AbstractMetaFunction::DestructorFunction);
|
|
1607
|
meta_function->setInvalid(true);
|
|
1607
|
meta_function->setInvalid(true);
|
|
1608
|
} else if (strip_template_args(function_name) == stripped_class_name) {
|
|
1608
|
} else if (strip_template_args(function_name) == stripped_class_name) {
|
|
1609
|
meta_function->setFunctionType(AbstractMetaFunction::ConstructorFunction);
|
|
1609
|
meta_function->setFunctionType(AbstractMetaFunction::ConstructorFunction);
|
|
1610
|
meta_function->setName(m_current_class->name());
|
|
1610
|
meta_function->setName(m_current_class->name());
|
|
1611
|
} else {
|
|
1611
|
} else {
|
|
1612
|
bool ok;
|
|
1612
|
bool ok;
|
|
1613
|
AbstractMetaType *type = 0;
|
|
1613
|
AbstractMetaType *type = 0;
|
|
1614
|
|
|
1614
|
|
|
1615
|
if (!cast_type.isEmpty()) {
|
|
1615
|
if (!cast_type.isEmpty()) {
|
|
1616
|
TypeInfo info;
|
|
1616
|
TypeInfo info;
|
|
1617
|
info.setQualifiedName(QStringList(cast_type));
|
|
1617
|
info.setQualifiedName(QStringList(cast_type));
|
|
1618
|
type = translateType(info, &ok);
|
|
1618
|
type = translateType(info, &ok);
|
|
1619
|
} else {
|
|
1619
|
} else {
|
|
1620
|
type = translateType(function_type, &ok);
|
|
1620
|
type = translateType(function_type, &ok);
|
|
1621
|
}
|
|
1621
|
}
|
|
1622
|
|
|
1622
|
|
|
1623
|
if (!ok) {
|
|
1623
|
if (!ok) {
|
|
1624
|
ReportHandler::warning(QString("skipping function '%1::%2', unmatched return type '%3'")
|
|
1624
|
ReportHandler::warning(QString("skipping function '%1::%2', unmatched return type '%3'")
|
|
1625
|
.arg(class_name)
|
|
1625
|
.arg(class_name)
|
|
1626
|
.arg(function_item->name())
|
|
1626
|
.arg(function_item->name())
|
|
1627
|
.arg(function_item->type().toString()));
|
|
1627
|
.arg(function_item->type().toString()));
|
|
1628
|
m_rejected_functions[class_name + "::" + function_name] =
|
|
1628
|
m_rejected_functions[class_name + "::" + function_name] =
|
|
1629
|
UnmatchedReturnType;
|
|
1629
|
UnmatchedReturnType;
|
|
1630
|
meta_function->setInvalid(true);
|
|
1630
|
meta_function->setInvalid(true);
|
|
1631
|
return meta_function;
|
|
1631
|
return meta_function;
|
|
1632
|
}
|
|
1632
|
}
|
|
1633
|
meta_function->setType(type);
|
|
1633
|
meta_function->setType(type);
|
|
1634
|
|
|
1634
|
|
|
1635
|
if (function_item->functionType() == CodeModel::Signal)
|
|
1635
|
if (function_item->functionType() == CodeModel::Signal)
|
|
1636
|
meta_function->setFunctionType(AbstractMetaFunction::SignalFunction);
|
|
1636
|
meta_function->setFunctionType(AbstractMetaFunction::SignalFunction);
|
|
1637
|
else if (function_item->functionType() == CodeModel::Slot)
|
|
1637
|
else if (function_item->functionType() == CodeModel::Slot)
|
|
1638
|
meta_function->setFunctionType(AbstractMetaFunction::SlotFunction);
|
|
1638
|
meta_function->setFunctionType(AbstractMetaFunction::SlotFunction);
|
|
1639
|
}
|
|
1639
|
}
|
|
1640
|
|
|
1640
|
|
|
1641
|
ArgumentList arguments = function_item->arguments();
|
|
1641
|
ArgumentList arguments = function_item->arguments();
|
|
1642
|
AbstractMetaArgumentList meta_arguments;
|
|
1642
|
AbstractMetaArgumentList meta_arguments;
|
|
1643
|
|
|
1643
|
|
|
1644
|
int first_default_argument = 0;
|
|
1644
|
int first_default_argument = 0;
|
|
1645
|
for (int i=0; i<arguments.size(); ++i) {
|
|
1645
|
for (int i=0; i<arguments.size(); ++i) {
|
|
1646
|
ArgumentModelItem arg = arguments.at(i);
|
|
1646
|
ArgumentModelItem arg = arguments.at(i);
|
|
1647
|
|
|
1647
|
|
|
1648
|
bool ok;
|
|
1648
|
bool ok;
|
|
1649
|
AbstractMetaType *meta_type = translateType(arg->type(), &ok);
|
|
1649
|
AbstractMetaType *meta_type = translateType(arg->type(), &ok);
|
|
1650
|
if (!meta_type || !ok) {
|
|
1650
|
if (!meta_type || !ok) {
|
|
1651
|
ReportHandler::warning(QString("skipping function '%1::%2', "
|
|
1651
|
ReportHandler::warning(QString("skipping function '%1::%2', "
|
|
1652
|
"unmatched parameter type '%3'")
|
|
1652
|
"unmatched parameter type '%3'")
|
|
1653
|
.arg(class_name)
|
|
1653
|
.arg(class_name)
|
|
1654
|
.arg(function_item->name())
|
|
1654
|
.arg(function_item->name())
|
|
1655
|
.arg(arg->type().toString()));
|
|
1655
|
.arg(arg->type().toString()));
|
|
1656
|
m_rejected_functions[class_name + "::" + function_name] =
|
|
1656
|
m_rejected_functions[class_name + "::" + function_name] =
|
|
1657
|
UnmatchedArgumentType;
|
|
1657
|
UnmatchedArgumentType;
|
|
1658
|
meta_function->setInvalid(true);
|
|
1658
|
meta_function->setInvalid(true);
|
|
1659
|
return meta_function;
|
|
1659
|
return meta_function;
|
|
1660
|
}
|
|
1660
|
}
|
|
1661
|
AbstractMetaArgument *meta_argument = createMetaArgument();
|
|
1661
|
AbstractMetaArgument *meta_argument = createMetaArgument();
|
|
1662
|
meta_argument->setType(meta_type);
|
|
1662
|
meta_argument->setType(meta_type);
|
|
1663
|
meta_argument->setName(arg->name());
|
|
1663
|
meta_argument->setName(arg->name());
|
|
1664
|
meta_argument->setArgumentIndex(i);
|
|
1664
|
meta_argument->setArgumentIndex(i);
|
|
1665
|
meta_arguments << meta_argument;
|
|
1665
|
meta_arguments << meta_argument;
|
|
1666
|
}
|
|
1666
|
}
|
|
1667
|
|
|
1667
|
|
|
1668
|
meta_function->setArguments(meta_arguments);
|
|
1668
|
meta_function->setArguments(meta_arguments);
|
|
1669
|
|
|
1669
|
|
|
1670
|
// Find the correct default values
|
|
1670
|
// Find the correct default values
|
|
1671
|
for (int i=0; i<arguments.size(); ++i) {
|
|
1671
|
for (int i=0; i<arguments.size(); ++i) {
|
|
1672
|
ArgumentModelItem arg = arguments.at(i);
|
|
1672
|
ArgumentModelItem arg = arguments.at(i);
|
|
1673
|
AbstractMetaArgument *meta_arg = meta_arguments.at(i);
|
|
1673
|
AbstractMetaArgument *meta_arg = meta_arguments.at(i);
|
|
1674
|
if (arg->defaultValue()) {
|
|
1674
|
if (arg->defaultValue()) {
|
|
1675
|
QString expr = arg->defaultValueExpression();
|
|
1675
|
QString expr = arg->defaultValueExpression();
|
|
1676
|
if (!expr.isEmpty())
|
|
1676
|
if (!expr.isEmpty())
|
|
1677
|
meta_arg->setOriginalDefaultValueExpression(expr);
|
|
1677
|
meta_arg->setOriginalDefaultValueExpression(expr);
|
|
1678
|
|
|
1678
|
|
|
1679
|
expr = translateDefaultValue(arg, meta_arg->type(), meta_function, m_current_class, i);
|
|
1679
|
expr = translateDefaultValue(arg, meta_arg->type(), meta_function, m_current_class, i);
|
|
1680
|
if (expr.isEmpty()) {
|
|
1680
|
if (expr.isEmpty()) {
|
|
1681
|
first_default_argument = i;
|
|
1681
|
first_default_argument = i;
|
|
1682
|
} else {
|
|
1682
|
} else {
|
|
1683
|
meta_arg->setDefaultValueExpression(expr);
|
|
1683
|
meta_arg->setDefaultValueExpression(expr);
|
|
1684
|
}
|
|
1684
|
}
|
|
1685
|
|
|
1685
|
|
|
1686
|
if (meta_arg->type()->isEnum() || meta_arg->type()->isFlags()) {
|
|
1686
|
if (meta_arg->type()->isEnum() || meta_arg->type()->isFlags()) {
|
|
1687
|
m_enum_default_arguments
|
|
1687
|
m_enum_default_arguments
|
|
1688
|
<< QPair<AbstractMetaArgument *, AbstractMetaFunction *>(meta_arg, meta_function);
|
|
1688
|
<< QPair<AbstractMetaArgument *, AbstractMetaFunction *>(meta_arg, meta_function);
|
|
1689
|
}
|
|
1689
|
}
|
|
1690
|
|
|
1690
|
|
|
1691
|
}
|
|
1691
|
}
|
|
1692
|
}
|
|
1692
|
}
|
|
1693
|
|
|
1693
|
|
|
1694
|
// If we where not able to translate the default argument make it
|
|
1694
|
// If we where not able to translate the default argument make it
|
|
1695
|
// reset all default arguments before this one too.
|
|
1695
|
// reset all default arguments before this one too.
|
|
1696
|
for (int i=0; i<first_default_argument; ++i)
|
|
1696
|
for (int i=0; i<first_default_argument; ++i)
|
|
1697
|
meta_arguments[i]->setDefaultValueExpression(QString());
|
|
1697
|
meta_arguments[i]->setDefaultValueExpression(QString());
|
|
1698
|
|
|
1698
|
|
|
1699
|
if (ReportHandler::debugLevel() == ReportHandler::FullDebug)
|
|
1699
|
if (ReportHandler::debugLevel() == ReportHandler::FullDebug)
|
|
1700
|
foreach(AbstractMetaArgument *arg, meta_arguments)
|
|
1700
|
foreach(AbstractMetaArgument *arg, meta_arguments)
|
|
1701
|
ReportHandler::debugFull(" - " + arg->toString());
|
|
1701
|
ReportHandler::debugFull(" - " + arg->toString());
|
|
1702
|
|
|
1702
|
|
|
1703
|
return meta_function;
|
|
1703
|
return meta_function;
|
|
1704
|
}
|
|
1704
|
}
|
|
1705
|
|
|
1705
|
|
|
1706
|
|
|
1706
|
|
|
1707
|
AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, bool *ok, bool resolveType, bool resolveScope)
|
|
1707
|
AbstractMetaType *AbstractMetaBuilder::translateType(const TypeInfo &_typei, bool *ok, bool resolveType, bool resolveScope)
|
|
1708
|
{
|
|
1708
|
{
|
|
1709
|
Q_ASSERT(ok);
|
|
1709
|
Q_ASSERT(ok);
|
|
1710
|
*ok = true;
|
|
1710
|
*ok = true;
|
|
1711
|
|
|
1711
|
|
|
1712
|
// 1. Test the type info without resolving typedefs in case this is present in the
|
|
1712
|
// 1. Test the type info without resolving typedefs in case this is present in the
|
|
1713
|
// type system
|
|
1713
|
// type system
|
|
1714
|
TypeInfo typei;
|
|
1714
|
TypeInfo typei;
|
|
1715
|
if (resolveType) {
|
|
1715
|
if (resolveType) {
|
|
1716
|
bool isok;
|
|
1716
|
bool isok;
|
|
1717
|
AbstractMetaType *t = translateType(_typei, &isok, false, resolveScope);
|
|
1717
|
AbstractMetaType *t = translateType(_typei, &isok, false, resolveScope);
|
|
1718
|
if (t != 0 && isok)
|
|
1718
|
if (t != 0 && isok)
|
|
1719
|
return t;
|
|
1719
|
return t;
|
|
1720
|
}
|
|
1720
|
}
|
|
1721
|
|
|
1721
|
|
|
1722
|
if (!resolveType)
|
|
1722
|
if (!resolveType)
|
|
1723
|
typei = _typei;
|
|
1723
|
typei = _typei;
|
|
1724
|
else {
|
|
1724
|
else {
|
|
1725
|
// Go through all parts of the current scope (including global namespace)
|
|
1725
|
// Go through all parts of the current scope (including global namespace)
|
|
1726
|
// to resolve typedefs. The parser does not properly resolve typedefs in
|
|
1726
|
// to resolve typedefs. The parser does not properly resolve typedefs in
|
|
1727
|
// the global scope when they are referenced from inside a namespace.
|
|
1727
|
// the global scope when they are referenced from inside a namespace.
|
|
1728
|
// This is a work around to fix this bug since fixing it in resolveType
|
|
1728
|
// This is a work around to fix this bug since fixing it in resolveType
|
|
1729
|
// seemed non-trivial
|
|
1729
|
// seemed non-trivial
|
|
1730
|
int i = m_scopes.size() - 1;
|
|
1730
|
int i = m_scopes.size() - 1;
|
|
1731
|
while (i >= 0) {
|
|
1731
|
while (i >= 0) {
|
|
1732
|
typei = TypeInfo::resolveType(_typei, m_scopes.at(i--)->toItem());
|
|
1732
|
typei = TypeInfo::resolveType(_typei, m_scopes.at(i--)->toItem());
|
|
1733
|
if (typei.qualifiedName().join("::") != _typei.qualifiedName().join("::"))
|
|
1733
|
if (typei.qualifiedName().join("::") != _typei.qualifiedName().join("::"))
|
|
1734
|
break;
|
|
1734
|
break;
|
|
1735
|
}
|
|
1735
|
}
|
|
1736
|
|
|
1736
|
|
|
1737
|
}
|
|
1737
|
}
|
|
1738
|
|
|
1738
|
|
|
1739
|
if (typei.isFunctionPointer()) {
|
|
1739
|
if (typei.isFunctionPointer()) {
|
|
1740
|
*ok = false;
|
|
1740
|
*ok = false;
|
|
1741
|
return 0;
|
|
1741
|
return 0;
|
|
1742
|
}
|
|
1742
|
}
|
|
1743
|
|
|
1743
|
|
|
1744
|
TypeParser::Info typeInfo = TypeParser::parse(typei.toString());
|
|
1744
|
TypeParser::Info typeInfo = TypeParser::parse(typei.toString());
|
|
1745
|
if (typeInfo.is_busted) {
|
|
1745
|
if (typeInfo.is_busted) {
|
|
1746
|
*ok = false;
|
|
1746
|
*ok = false;
|
|
1747
|
return 0;
|
|
1747
|
return 0;
|
|
1748
|
}
|
|
1748
|
}
|
|
1749
|
|
|
1749
|
|
|
1750
|
// 2. Handle pointers specified as arrays with unspecified size
|
|
1750
|
// 2. Handle pointers specified as arrays with unspecified size
|
|
1751
|
bool array_of_unspecified_size = false;
|
|
1751
|
bool array_of_unspecified_size = false;
|
|
1752
|
if (typeInfo.arrays.size() > 0) {
|
|
1752
|
if (typeInfo.arrays.size() > 0) {
|
|
1753
|
array_of_unspecified_size = true;
|
|
1753
|
array_of_unspecified_size = true;
|
|
1754
|
for (int i=0; i<typeInfo.arrays.size(); ++i)
|
|
1754
|
for (int i=0; i<typeInfo.arrays.size(); ++i)
|
|
1755
|
array_of_unspecified_size = array_of_unspecified_size && typeInfo.arrays.at(i).isEmpty();
|
|
1755
|
array_of_unspecified_size = array_of_unspecified_size && typeInfo.arrays.at(i).isEmpty();
|
|
1756
|
|
|
1756
|
|
|
1757
|
if (!array_of_unspecified_size) {
|
|
1757
|
if (!array_of_unspecified_size) {
|
|
1758
|
TypeInfo newInfo;
|
|
1758
|
TypeInfo newInfo;
|
|
1759
|
//newInfo.setArguments(typei.arguments());
|
|
1759
|
//newInfo.setArguments(typei.arguments());
|
|
1760
|
newInfo.setIndirections(typei.indirections());
|
|
1760
|
newInfo.setIndirections(typei.indirections());
|
|
1761
|
newInfo.setConstant(typei.isConstant());
|
|
1761
|
newInfo.setConstant(typei.isConstant());
|
|
1762
|
newInfo.setFunctionPointer(typei.isFunctionPointer());
|
|
1762
|
newInfo.setFunctionPointer(typei.isFunctionPointer());
|
|
1763
|
newInfo.setQualifiedName(typei.qualifiedName());
|
|
1763
|
newInfo.setQualifiedName(typei.qualifiedName());
|
|
1764
|
newInfo.setReference(typei.isReference());
|
|
1764
|
newInfo.setReference(typei.isReference());
|
|
1765
|
newInfo.setVolatile(typei.isVolatile());
|
|
1765
|
newInfo.setVolatile(typei.isVolatile());
|
|
1766
|
|
|
1766
|
|
|
1767
|
AbstractMetaType *elementType = translateType(newInfo, ok);
|
|
1767
|
AbstractMetaType *elementType = translateType(newInfo, ok);
|
|
1768
|
if (!(*ok))
|
|
1768
|
if (!(*ok))
|
|
1769
|
return 0;
|
|
1769
|
return 0;
|
|
1770
|
|
|
1770
|
|
|
1771
|
for (int i=typeInfo.arrays.size()-1; i>=0; --i) {
|
|
1771
|
for (int i=typeInfo.arrays.size()-1; i>=0; --i) {
|
|
1772
|
QString s = typeInfo.arrays.at(i);
|
|
1772
|
QString s = typeInfo.arrays.at(i);
|
|
1773
|
bool isok;
|
|
1773
|
bool isok;
|
|
1774
|
|
|
1774
|
|
|
1775
|
int elems = s.toInt(&isok);
|
|
1775
|
int elems = s.toInt(&isok);
|
|
1776
|
if (!isok)
|
|
1776
|
if (!isok)
|
|
1777
|
return 0;
|
|
1777
|
return 0;
|
|
1778
|
|
|
1778
|
|
|
1779
|
AbstractMetaType *arrayType = createMetaType();
|
|
1779
|
AbstractMetaType *arrayType = createMetaType();
|
|
1780
|
arrayType->setArrayElementCount(elems);
|
|
1780
|
arrayType->setArrayElementCount(elems);
|
|
1781
|
arrayType->setArrayElementType(elementType);
|
|
1781
|
arrayType->setArrayElementType(elementType);
|
|
1782
|
arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry()));
|
|
1782
|
arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry()));
|
|
1783
|
decideUsagePattern(arrayType);
|
|
1783
|
decideUsagePattern(arrayType);
|
|
1784
|
|
|
1784
|
|
|
1785
|
elementType = arrayType;
|
|
1785
|
elementType = arrayType;
|
|
1786
|
}
|
|
1786
|
}
|
|
1787
|
|
|
1787
|
|
|
1788
|
return elementType;
|
|
1788
|
return elementType;
|
|
1789
|
} else {
|
|
1789
|
} else {
|
|
1790
|
typeInfo.indirections += typeInfo.arrays.size();
|
|
1790
|
typeInfo.indirections += typeInfo.arrays.size();
|
|
1791
|
}
|
|
1791
|
}
|
|
1792
|
}
|
|
1792
|
}
|
|
1793
|
|
|
1793
|
|
|
1794
|
QStringList qualifier_list = typeInfo.qualified_name;
|
|
1794
|
QStringList qualifier_list = typeInfo.qualified_name;
|
|
1795
|
if (qualifier_list.isEmpty()) {
|
|
1795
|
if (qualifier_list.isEmpty()) {
|
|
1796
|
ReportHandler::warning(QString("horribly broken type '%1'").arg(_typei.toString()));
|
|
1796
|
ReportHandler::warning(QString("horribly broken type '%1'").arg(_typei.toString()));
|
|
1797
|
*ok = false;
|
|
1797
|
*ok = false;
|
|
1798
|
return 0;
|
|
1798
|
return 0;
|
|
1799
|
}
|
|
1799
|
}
|
|
1800
|
|
|
1800
|
|
|
1801
|
QString qualified_name = qualifier_list.join("::");
|
|
1801
|
QString qualified_name = qualifier_list.join("::");
|
|
1802
|
QString name = qualifier_list.takeLast();
|
|
1802
|
QString name = qualifier_list.takeLast();
|
|
1803
|
|
|
1803
|
|
|
1804
|
// 3. Special case 'void' type
|
|
1804
|
// 3. Special case 'void' type
|
|
1805
|
if (name == "void" && typeInfo.indirections == 0) {
|
|
1805
|
if (name == "void" && typeInfo.indirections == 0) {
|
|
1806
|
return 0;
|
|
1806
|
return 0;
|
|
1807
|
}
|
|
1807
|
}
|
|
1808
|
|
|
1808
|
|
|
1809
|
// 4. Special case QFlags (include instantiation in name)
|
|
1809
|
// 4. Special case QFlags (include instantiation in name)
|
|
1810
|
if (qualified_name == "QFlags")
|
|
1810
|
if (qualified_name == "QFlags")
|
|
1811
|
qualified_name = typeInfo.toString();
|
|
1811
|
qualified_name = typeInfo.toString();
|
|
1812
|
|
|
1812
|
|
|
1813
|
// 5. Try to find the type
|
|
1813
|
// 5. Try to find the type
|
|
1814
|
const TypeEntry *type = TypeDatabase::instance()->findType(qualified_name);
|
|
1814
|
const TypeEntry *type = TypeDatabase::instance()->findType(qualified_name);
|
|
1815
|
|
|
1815
|
|
|
1816
|
// 6. No? Try looking it up as a flags type
|
|
1816
|
// 6. No? Try looking it up as a flags type
|
|
1817
|
if (!type)
|
|
1817
|
if (!type)
|
|
1818
|
type = TypeDatabase::instance()->findFlagsType(qualified_name);
|
|
1818
|
type = TypeDatabase::instance()->findFlagsType(qualified_name);
|
|
1819
|
|
|
1819
|
|
|
1820
|
// 7. No? Try looking it up as a container type
|
|
1820
|
// 7. No? Try looking it up as a container type
|
|
1821
|
if (!type)
|
|
1821
|
if (!type)
|
|
1822
|
type = TypeDatabase::instance()->findContainerType(name);
|
|
1822
|
type = TypeDatabase::instance()->findContainerType(name);
|
|
1823
|
|
|
1823
|
|
|
1824
|
// 8. No? Check if the current class is a template and this type is one
|
|
1824
|
// 8. No? Check if the current class is a template and this type is one
|
|
1825
|
// of the parameters.
|
|
1825
|
// of the parameters.
|
|
1826
|
if (type == 0 && m_current_class != 0) {
|
|
1826
|
if (type == 0 && m_current_class != 0) {
|
|
1827
|
QList<TypeEntry *> template_args = m_current_class->templateArguments();
|
|
1827
|
QList<TypeEntry *> template_args = m_current_class->templateArguments();
|
|
1828
|
foreach (TypeEntry *te, template_args) {
|
|
1828
|
foreach (TypeEntry *te, template_args) {
|
|
1829
|
if (te->name() == qualified_name)
|
|
1829
|
if (te->name() == qualified_name)
|
|
1830
|
type = te;
|
|
1830
|
type = te;
|
|
1831
|
}
|
|
1831
|
}
|
|
1832
|
}
|
|
1832
|
}
|
|
1833
|
|
|
1833
|
|
|
1834
|
// 9. Try finding the type by prefixing it with the current
|
|
1834
|
// 9. Try finding the type by prefixing it with the current
|
|
1835
|
// context and all baseclasses of the current context
|
|
1835
|
// context and all baseclasses of the current context
|
|
1836
|
if (!type && !TypeDatabase::instance()->isClassRejected(qualified_name) && m_current_class != 0 && resolveScope) {
|
|
1836
|
if (!type && !TypeDatabase::instance()->isClassRejected(qualified_name) && m_current_class != 0 && resolveScope) {
|
|
1837
|
QStringList contexts;
|
|
1837
|
QStringList contexts;
|
|
1838
|
contexts.append(m_current_class->qualifiedCppName());
|
|
1838
|
contexts.append(m_current_class->qualifiedCppName());
|
|
1839
|
contexts.append(currentScope()->qualifiedName().join("::"));
|
|
1839
|
contexts.append(currentScope()->qualifiedName().join("::"));
|
|
1840
|
|
|
1840
|
|
|
1841
|
|
|
1841
|
|
|
1842
|
TypeInfo info = typei;
|
|
1842
|
TypeInfo info = typei;
|
|
1843
|
bool subclasses_done = false;
|
|
1843
|
bool subclasses_done = false;
|
|
1844
|
while (!contexts.isEmpty() && type == 0) {
|
|
1844
|
while (!contexts.isEmpty() && type == 0) {
|
|
1845
|
//type = TypeDatabase::instance()->findType(contexts.at(0) + "::" + qualified_name);
|
|
1845
|
//type = TypeDatabase::instance()->findType(contexts.at(0) + "::" + qualified_name);
|
|
1846
|
|
|
1846
|
|
|
1847
|
bool isok;
|
|
1847
|
bool isok;
|
|
1848
|
info.setQualifiedName(QStringList() << contexts.at(0) << qualified_name);
|
|
1848
|
info.setQualifiedName(QStringList() << contexts.at(0) << qualified_name);
|
|
1849
|
AbstractMetaType *t = translateType(info, &isok, true, false);
|
|
1849
|
AbstractMetaType *t = translateType(info, &isok, true, false);
|
|
1850
|
if (t != 0 && isok)
|
|
1850
|
if (t != 0 && isok)
|
|
1851
|
return t;
|
|
1851
|
return t;
|
|
1852
|
|
|
1852
|
|
|
1853
|
ClassModelItem item = m_dom->findClass(contexts.at(0));
|
|
1853
|
ClassModelItem item = m_dom->findClass(contexts.at(0));
|
|
1854
|
if (item != 0)
|
|
1854
|
if (item != 0)
|
|
1855
|
contexts += item->baseClasses();
|
|
1855
|
contexts += item->baseClasses();
|
|
1856
|
contexts.pop_front();
|
|
1856
|
contexts.pop_front();
|
|
1857
|
|
|
1857
|
|
|
1858
|
// 10. Last resort: Special cased prefix of Qt namespace since the meta object implicitly inherits this, so
|
|
1858
|
// 10. Last resort: Special cased prefix of Qt namespace since the meta object implicitly inherits this, so
|
|
1859
|
// enum types from there may be addressed without any scope resolution in properties.
|
|
1859
|
// enum types from there may be addressed without any scope resolution in properties.
|
|
1860
|
if (contexts.size() == 0 && !subclasses_done) {
|
|
1860
|
if (contexts.size() == 0 && !subclasses_done) {
|
|
1861
|
contexts << "Qt";
|
|
1861
|
contexts << "Qt";
|
|
1862
|
subclasses_done = true;
|
|
1862
|
subclasses_done = true;
|
|
1863
|
}
|
|
1863
|
}
|
|
1864
|
}
|
|
1864
|
}
|
|
1865
|
|
|
1865
|
|
|
1866
|
}
|
|
1866
|
}
|
|
1867
|
|
|
1867
|
|
|
1868
|
if (!type) {
|
|
1868
|
if (!type) {
|
|
1869
|
*ok = false;
|
|
1869
|
*ok = false;
|
|
1870
|
return 0;
|
|
1870
|
return 0;
|
|
1871
|
}
|
|
1871
|
}
|
|
1872
|
|
|
1872
|
|
|
1873
|
// Used to for diagnostics later...
|
|
1873
|
// Used to for diagnostics later...
|
|
1874
|
m_used_types << type;
|
|
1874
|
m_used_types << type;
|
|
1875
|
|
|
1875
|
|
|
1876
|
// These are only implicit and should not appear in code...
|
|
1876
|
// These are only implicit and should not appear in code...
|
|
1877
|
Q_ASSERT(!type->isInterface());
|
|
1877
|
Q_ASSERT(!type->isInterface());
|
|
1878
|
|
|
1878
|
|
|
1879
|
AbstractMetaType *meta_type = createMetaType();
|
|
1879
|
AbstractMetaType *meta_type = createMetaType();
|
|
1880
|
meta_type->setTypeEntry(type);
|
|
1880
|
meta_type->setTypeEntry(type);
|
|
1881
|
meta_type->setIndirections(typeInfo.indirections);
|
|
1881
|
meta_type->setIndirections(typeInfo.indirections);
|
|
1882
|
meta_type->setReference(typeInfo.is_reference);
|
|
1882
|
meta_type->setReference(typeInfo.is_reference);
|
|
1883
|
meta_type->setConstant(typeInfo.is_constant);
|
|
1883
|
meta_type->setConstant(typeInfo.is_constant);
|
|
1884
|
meta_type->setOriginalTypeDescription(_typei.toString());
|
|
1884
|
meta_type->setOriginalTypeDescription(_typei.toString());
|
|
1885
|
decideUsagePattern(meta_type);
|
|
1885
|
decideUsagePattern(meta_type);
|
|
1886
|
|
|
1886
|
|
|
1887
|
if (meta_type->typeEntry()->isContainer()) {
|
|
1887
|
if (meta_type->typeEntry()->isContainer()) {
|
|
1888
|
ContainerTypeEntry::Type container_type = static_cast<const ContainerTypeEntry *>(type)->type();
|
|
1888
|
ContainerTypeEntry::Type container_type = static_cast<const ContainerTypeEntry *>(type)->type();
|
|
1889
|
|
|
1889
|
|
|
1890
|
if (container_type == ContainerTypeEntry::StringListContainer) {
|
|
1890
|
if (container_type == ContainerTypeEntry::StringListContainer) {
|
|
1891
|
TypeInfo info;
|
|
1891
|
TypeInfo info;
|
|
1892
|
info.setQualifiedName(QStringList() << "QString");
|
|
1892
|
info.setQualifiedName(QStringList() << "QString");
|
|
1893
|
AbstractMetaType *targ_type = translateType(info, ok);
|
|
1893
|
AbstractMetaType *targ_type = translateType(info, ok);
|
|
1894
|
|
|
1894
|
|
|
1895
|
Q_ASSERT(*ok);
|
|
1895
|
Q_ASSERT(*ok);
|
|
1896
|
Q_ASSERT(targ_type);
|
|
1896
|
Q_ASSERT(targ_type);
|
|
1897
|
|
|
1897
|
|
|
1898
|
meta_type->addInstantiation(targ_type);
|
|
1898
|
meta_type->addInstantiation(targ_type);
|
|
1899
|
meta_type->setInstantiationInCpp(false);
|
|
1899
|
meta_type->setInstantiationInCpp(false);
|
|
1900
|
|
|
1900
|
|
|
1901
|
} else {
|
|
1901
|
} else {
|
|
1902
|
foreach (const TypeParser::Info &ta, typeInfo.template_instantiations) {
|
|
1902
|
foreach (const TypeParser::Info &ta, typeInfo.template_instantiations) {
|
|
1903
|
TypeInfo info;
|
|
1903
|
TypeInfo info;
|
|
1904
|
info.setConstant(ta.is_constant);
|
|
1904
|
info.setConstant(ta.is_constant);
|
|
1905
|
info.setReference(ta.is_reference);
|
|
1905
|
info.setReference(ta.is_reference);
|
|
1906
|
info.setIndirections(ta.indirections);
|
|
1906
|
info.setIndirections(ta.indirections);
|
|
1907
|
|
|
1907
|
|
|
1908
|
info.setFunctionPointer(false);
|
|
1908
|
info.setFunctionPointer(false);
|
|
1909
|
info.setQualifiedName(ta.instantiationName().split("::"));
|
|
1909
|
info.setQualifiedName(ta.instantiationName().split("::"));
|
|
1910
|
|
|
1910
|
|
|
1911
|
AbstractMetaType *targ_type = translateType(info, ok);
|
|
1911
|
AbstractMetaType *targ_type = translateType(info, ok);
|
|
1912
|
if (!(*ok)) {
|
|
1912
|
if (!(*ok)) {
|
|
1913
|
delete meta_type;
|
|
1913
|
delete meta_type;
|
|
1914
|
return 0;
|
|
1914
|
return 0;
|
|
1915
|
}
|
|
1915
|
}
|
|
1916
|
|
|
1916
|
|
|
1917
|
meta_type->addInstantiation(targ_type);
|
|
1917
|
meta_type->addInstantiation(targ_type);
|
|
1918
|
}
|
|
1918
|
}
|
|
1919
|
}
|
|
1919
|
}
|
|
1920
|
|
|
1920
|
|
|
1921
|
if (container_type == ContainerTypeEntry::ListContainer
|
|
1921
|
if (container_type == ContainerTypeEntry::ListContainer
|
|
1922
|
|| container_type == ContainerTypeEntry::VectorContainer
|
|
1922
|
|| container_type == ContainerTypeEntry::VectorContainer
|
|
1923
|
|| container_type == ContainerTypeEntry::StringListContainer) {
|
|
1923
|
|| container_type == ContainerTypeEntry::StringListContainer) {
|
|
1924
|
Q_ASSERT(meta_type->instantiations().size() == 1);
|
|
1924
|
Q_ASSERT(meta_type->instantiations().size() == 1);
|
|
1925
|
}
|
|
1925
|
}
|
|
1926
|
}
|
|
1926
|
}
|
|
1927
|
|
|
1927
|
|
|
1928
|
return meta_type;
|
|
1928
|
return meta_type;
|
|
1929
|
}
|
|
1929
|
}
|
|
1930
|
|
|
1930
|
|
|
1931
|
void AbstractMetaBuilder::decideUsagePattern(AbstractMetaType *meta_type)
|
|
1931
|
void AbstractMetaBuilder::decideUsagePattern(AbstractMetaType *meta_type)
|
|
1932
|
{
|
|
1932
|
{
|
|
1933
|
const TypeEntry *type = meta_type->typeEntry();
|
|
1933
|
const TypeEntry *type = meta_type->typeEntry();
|
|
1934
|
|
|
1934
|
|
|
1935
|
if (type->isPrimitive() && (meta_type->actualIndirections() == 0
|
|
1935
|
if (type->isPrimitive() && (meta_type->actualIndirections() == 0
|
|
1936
|
|| (meta_type->isConstant() && meta_type->isReference() && meta_type->indirections() == 0))) {
|
|
1936
|
|| (meta_type->isConstant() && meta_type->isReference() && meta_type->indirections() == 0))) {
|
|
1937
|
meta_type->setTypeUsagePattern(AbstractMetaType::PrimitivePattern);
|
|
1937
|
meta_type->setTypeUsagePattern(AbstractMetaType::PrimitivePattern);
|
|
1938
|
|
|
1938
|
|
|
1939
|
} else if (type->isVoid()) {
|
|
1939
|
} else if (type->isVoid()) {
|
|
1940
|
meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
|
|
1940
|
meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
|
|
1941
|
|
|
1941
|
|
|
1942
|
} else if (type->isString()
|
|
1942
|
} else if (type->isString()
|
|
1943
|
&& meta_type->indirections() == 0
|
|
1943
|
&& meta_type->indirections() == 0
|
|
1944
|
&& (meta_type->isConstant() == meta_type->isReference()
|
|
1944
|
&& (meta_type->isConstant() == meta_type->isReference()
|
|
1945
|
|| meta_type->isConstant())) {
|
|
1945
|
|| meta_type->isConstant())) {
|
|
1946
|
meta_type->setTypeUsagePattern(AbstractMetaType::StringPattern);
|
|
1946
|
meta_type->setTypeUsagePattern(AbstractMetaType::StringPattern);
|
|
1947
|
|
|
1947
|
|
|
1948
|
} else if (type->isChar()
|
|
1948
|
} else if (type->isChar()
|
|
1949
|
&& meta_type->indirections() == 0
|
|
1949
|
&& meta_type->indirections() == 0
|
|
1950
|
&& meta_type->isConstant() == meta_type->isReference()) {
|
|
1950
|
&& meta_type->isConstant() == meta_type->isReference()) {
|
|
1951
|
meta_type->setTypeUsagePattern(AbstractMetaType::CharPattern);
|
|
1951
|
meta_type->setTypeUsagePattern(AbstractMetaType::CharPattern);
|
|
1952
|
|
|
1952
|
|
|
1953
|
} else if (type->isJObjectWrapper()
|
|
1953
|
} else if (type->isJObjectWrapper()
|
|
1954
|
&& meta_type->indirections() == 0
|
|
1954
|
&& meta_type->indirections() == 0
|
|
1955
|
&& meta_type->isConstant() == meta_type->isReference()) {
|
|
1955
|
&& meta_type->isConstant() == meta_type->isReference()) {
|
|
1956
|
meta_type->setTypeUsagePattern(AbstractMetaType::JObjectWrapperPattern);
|
|
1956
|
meta_type->setTypeUsagePattern(AbstractMetaType::JObjectWrapperPattern);
|
|
1957
|
|
|
1957
|
|
|
1958
|
} else if (type->isVariant()
|
|
1958
|
} else if (type->isVariant()
|
|
1959
|
&& meta_type->indirections() == 0
|
|
1959
|
&& meta_type->indirections() == 0
|
|
1960
|
&& meta_type->isConstant() == meta_type->isReference()) {
|
|
1960
|
&& meta_type->isConstant() == meta_type->isReference()) {
|
|
1961
|
meta_type->setTypeUsagePattern(AbstractMetaType::VariantPattern);
|
|
1961
|
meta_type->setTypeUsagePattern(AbstractMetaType::VariantPattern);
|
|
1962
|
|
|
1962
|
|
|
1963
|
} else if (type->isEnum() && meta_type->actualIndirections() == 0) {
|
|
1963
|
} else if (type->isEnum() && meta_type->actualIndirections() == 0) {
|
|
1964
|
meta_type->setTypeUsagePattern(AbstractMetaType::EnumPattern);
|
|
1964
|
meta_type->setTypeUsagePattern(AbstractMetaType::EnumPattern);
|
|
1965
|
|
|
1965
|
|
|
1966
|
} else if (type->isObject()
|
|
1966
|
} else if (type->isObject()
|
|
1967
|
&& meta_type->indirections() == 0
|
|
1967
|
&& meta_type->indirections() == 0
|
|
1968
|
&& meta_type->isReference()) {
|
|
1968
|
&& meta_type->isReference()) {
|
|
1969
|
if (((ComplexTypeEntry *) type)->isQObject())
|
|
1969
|
if (((ComplexTypeEntry *) type)->isQObject())
|
|
1970
|
meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
|
|
1970
|
meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
|
|
1971
|
else
|
|
1971
|
else
|
|
1972
|
meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
|
|
1972
|
meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
|
|
1973
|
|
|
1973
|
|
|
1974
|
} else if (type->isObject()
|
|
1974
|
} else if (type->isObject()
|
|
1975
|
&& meta_type->indirections() == 1) {
|
|
1975
|
&& meta_type->indirections() == 1) {
|
|
1976
|
if (((ComplexTypeEntry *) type)->isQObject())
|
|
1976
|
if (((ComplexTypeEntry *) type)->isQObject())
|
|
1977
|
meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
|
|
1977
|
meta_type->setTypeUsagePattern(AbstractMetaType::QObjectPattern);
|
|
1978
|
else
|
|
1978
|
else
|
|
1979
|
meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
|
|
1979
|
meta_type->setTypeUsagePattern(AbstractMetaType::ObjectPattern);
|
|
1980
|
|
|
1980
|
|
|
1981
|
// const-references to pointers can be passed as pointers
|
|
1981
|
// const-references to pointers can be passed as pointers
|
|
1982
|
if (meta_type->isReference() && meta_type->isConstant()) {
|
|
1982
|
if (meta_type->isReference() && meta_type->isConstant()) {
|
|
1983
|
meta_type->setReference(false);
|
|
1983
|
meta_type->setReference(false);
|
|
1984
|
meta_type->setConstant(false);
|
|
1984
|
meta_type->setConstant(false);
|
|
1985
|
}
|
|
1985
|
}
|
|
1986
|
|
|
1986
|
|
|
1987
|
} else if (type->isContainer() && meta_type->indirections() == 0) {
|
|
1987
|
} else if (type->isContainer() && meta_type->indirections() == 0) {
|
|
1988
|
meta_type->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
|
|
1988
|
meta_type->setTypeUsagePattern(AbstractMetaType::ContainerPattern);
|
|
1989
|
|
|
1989
|
|
|
1990
|
} else if (type->isTemplateArgument()) {
|
|
1990
|
} else if (type->isTemplateArgument()) {
|
|
1991
|
|
|
1991
|
|
|
1992
|
} else if (type->isFlags()
|
|
1992
|
} else if (type->isFlags()
|
|
1993
|
&& meta_type->indirections() == 0
|
|
1993
|
&& meta_type->indirections() == 0
|
|
1994
|
&& (meta_type->isConstant() == meta_type->isReference())) {
|
|
1994
|
&& (meta_type->isConstant() == meta_type->isReference())) {
|
|
1995
|
meta_type->setTypeUsagePattern(AbstractMetaType::FlagsPattern);
|
|
1995
|
meta_type->setTypeUsagePattern(AbstractMetaType::FlagsPattern);
|
|
1996
|
|
|
1996
|
|
|
1997
|
} else if (type->isArray()) {
|
|
1997
|
} else if (type->isArray()) {
|
|
1998
|
meta_type->setTypeUsagePattern(AbstractMetaType::ArrayPattern);
|
|
1998
|
meta_type->setTypeUsagePattern(AbstractMetaType::ArrayPattern);
|
|
1999
|
|
|
1999
|
|
|
2000
|
} else if (type->isThread()) {
|
|
2000
|
} else if (type->isThread()) {
|
|
2001
|
Q_ASSERT(meta_type->indirections() == 1);
|
|
2001
|
Q_ASSERT(meta_type->indirections() == 1);
|
|
2002
|
meta_type->setTypeUsagePattern(AbstractMetaType::ThreadPattern);
|
|
2002
|
meta_type->setTypeUsagePattern(AbstractMetaType::ThreadPattern);
|
|
2003
|
|
|
2003
|
|
|
2004
|
} else if (type->isValue()
|
|
2004
|
} else if (type->isValue()
|
|
2005
|
&& meta_type->indirections() == 0
|
|
2005
|
&& meta_type->indirections() == 0
|
|
2006
|
&& (meta_type->isConstant() == meta_type->isReference()
|
|
2006
|
&& (meta_type->isConstant() == meta_type->isReference()
|
|
2007
|
|| !meta_type->isReference())) {
|
|
2007
|
|| !meta_type->isReference())) {
|
|
2008
|
meta_type->setTypeUsagePattern(AbstractMetaType::ValuePattern);
|
|
2008
|
meta_type->setTypeUsagePattern(AbstractMetaType::ValuePattern);
|
|
2009
|
|
|
2009
|
|
|
2010
|
} else {
|
|
2010
|
} else {
|
|
2011
|
meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
|
|
2011
|
meta_type->setTypeUsagePattern(AbstractMetaType::NativePointerPattern);
|
|
2012
|
ReportHandler::debugFull(QString("native pointer pattern for '%1'")
|
|
2012
|
ReportHandler::debugFull(QString("native pointer pattern for '%1'")
|
|
2013
|
.arg(meta_type->cppSignature()));
|
|
2013
|
.arg(meta_type->cppSignature()));
|
|
2014
|
}
|
|
2014
|
}
|
|
2015
|
}
|
|
2015
|
}
|
|
2016
|
|
|
2016
|
|
|
2017
|
QString AbstractMetaBuilder::translateDefaultValue(ArgumentModelItem item, AbstractMetaType *type,
|
|
2017
|
QString AbstractMetaBuilder::translateDefaultValue(ArgumentModelItem item, AbstractMetaType *type,
|
|
2018
|
AbstractMetaFunction *fnc, AbstractMetaClass *implementing_class,
|
|
2018
|
AbstractMetaFunction *fnc, AbstractMetaClass *implementing_class,
|
|
2019
|
int argument_index)
|
|
2019
|
int argument_index)
|
|
2020
|
{
|
|
2020
|
{
|
|
2021
|
QString function_name = fnc->name();
|
|
2021
|
QString function_name = fnc->name();
|
|
2022
|
QString class_name = implementing_class->name();
|
|
2022
|
QString class_name = implementing_class->name();
|
|
2023
|
|
|
2023
|
|
|
2024
|
QString replaced_expression = fnc->replacedDefaultExpression(implementing_class, argument_index + 1);
|
|
2024
|
QString replaced_expression = fnc->replacedDefaultExpression(implementing_class, argument_index + 1);
|
|
2025
|
if (fnc->removedDefaultExpression(implementing_class, argument_index +1))
|
|
2025
|
if (fnc->removedDefaultExpression(implementing_class, argument_index +1))
|
|
2026
|
return "";
|
|
2026
|
return "";
|
|
2027
|
if (!replaced_expression.isEmpty())
|
|
2027
|
if (!replaced_expression.isEmpty())
|
|
2028
|
return replaced_expression;
|
|
2028
|
return replaced_expression;
|
|
2029
|
|
|
2029
|
|
|
2030
|
QString expr = item->defaultValueExpression();
|
|
2030
|
QString expr = item->defaultValueExpression();
|
|
2031
|
if (type != 0 && type->isPrimitive()) {
|
|
2031
|
if (type != 0 && type->isPrimitive()) {
|
|
2032
|
if (type->name() == "boolean") {
|
|
2032
|
if (type->name() == "boolean") {
|
|
2033
|
if (expr == "false" || expr=="true") {
|
|
2033
|
if (expr == "false" || expr=="true") {
|
|
2034
|
return expr;
|
|
2034
|
return expr;
|
|
2035
|
} else {
|
|
2035
|
} else {
|
|
2036
|
bool ok = false;
|
|
2036
|
bool ok = false;
|
|
2037
|
int number = expr.toInt(&ok);
|
|
2037
|
int number = expr.toInt(&ok);
|
|
2038
|
if (ok && number)
|
|
2038
|
if (ok && number)
|
|
2039
|
return "true";
|
|
2039
|
return "true";
|
|
2040
|
else
|
|
2040
|
else
|
|
2041
|
return "false";
|
|
2041
|
return "false";
|
|
2042
|
}
|
|
2042
|
}
|
|
2043
|
} else if (expr == "ULONG_MAX") {
|
|
2043
|
} else if (expr == "ULONG_MAX") {
|
|
2044
|
return "Long.MAX_VALUE";
|
|
2044
|
return "Long.MAX_VALUE";
|
|
2045
|
} else if (expr == "QVariant::Invalid") {
|
|
2045
|
} else if (expr == "QVariant::Invalid") {
|
|
2046
|
return QString::number(QVariant::Invalid);
|
|
2046
|
return QString::number(QVariant::Invalid);
|
|
2047
|
} else {
|
|
2047
|
} else {
|
|
2048
|
// This can be an enum or flag so I need to delay the
|
|
2048
|
// This can be an enum or flag so I need to delay the
|
|
2049
|
// translation untill all namespaces are completly
|
|
2049
|
// translation untill all namespaces are completly
|
|
2050
|
// processed. This is done in figureOutEnumValues()
|
|
2050
|
// processed. This is done in figureOutEnumValues()
|
|
2051
|
return expr;
|
|
2051
|
return expr;
|
|
2052
|
}
|
|
2052
|
}
|
|
2053
|
} else if (type != 0 && (type->isFlags() || type->isEnum())) {
|
|
2053
|
} else if (type != 0 && (type->isFlags() || type->isEnum())) {
|
|
2054
|
// Same as with enum explanation above...
|
|
2054
|
// Same as with enum explanation above...
|
|
2055
|
return expr;
|
|
2055
|
return expr;
|
|
2056
|
|
|
2056
|
|
|
2057
|
} else {
|
|
2057
|
} else {
|
|
2058
|
|
|
2058
|
|
|
2059
|
// constructor or functioncall can be a bit tricky...
|
|
2059
|
// constructor or functioncall can be a bit tricky...
|
|
2060
|
if (expr == "QVariant()" || expr == "QModelIndex()") {
|
|
2060
|
if (expr == "QVariant()" || expr == "QModelIndex()") {
|
|
2061
|
return "null";
|
|
2061
|
return "null";
|
|
2062
|
} else if (expr == "QString()") {
|
|
2062
|
} else if (expr == "QString()") {
|
|
2063
|
return "null";
|
|
2063
|
return "null";
|
|
2064
|
} else if (expr.endsWith(")") && expr.contains("::")) {
|
|
2064
|
} else if (expr.endsWith(")") && expr.contains("::")) {
|
|
2065
|
TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
|
|
2065
|
TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
|
|
2066
|
if (typeEntry)
|
|
2066
|
if (typeEntry)
|
|
2067
|
return typeEntry->qualifiedTargetLangName() + "." + expr.right(expr.length() - expr.indexOf("::") - 2);
|
|
2067
|
return typeEntry->qualifiedTargetLangName() + "." + expr.right(expr.length() - expr.indexOf("::") - 2);
|
|
2068
|
} else if (expr.endsWith(")") && type != 0 && type->isValue()) {
|
|
2068
|
} else if (expr.endsWith(")") && type != 0 && type->isValue()) {
|
|
2069
|
int pos = expr.indexOf("(");
|
|
2069
|
int pos = expr.indexOf("(");
|
|
2070
|
|
|
2070
|
|
|
2071
|
TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(pos));
|
|
2071
|
TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(pos));
|
|
2072
|
if (typeEntry)
|
|
2072
|
if (typeEntry)
|
|
2073
|
return "new " + typeEntry->qualifiedTargetLangName() + expr.right(expr.length() - pos);
|
|
2073
|
return "new " + typeEntry->qualifiedTargetLangName() + expr.right(expr.length() - pos);
|
|
2074
|
else
|
|
2074
|
else
|
|
2075
|
return expr;
|
|
2075
|
return expr;
|
|
2076
|
} else if (expr == "0") {
|
|
2076
|
} else if (expr == "0") {
|
|
2077
|
return "null";
|
|
2077
|
return "null";
|
|
2078
|
} else if (type != 0 && (type->isObject() || type->isValue() || expr.contains("::"))) { // like Qt::black passed to a QColor
|
|
2078
|
} else if (type != 0 && (type->isObject() || type->isValue() || expr.contains("::"))) { // like Qt::black passed to a QColor
|
|
2079
|
TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
|
|
2079
|
TypeEntry *typeEntry = TypeDatabase::instance()->findType(expr.left(expr.indexOf("::")));
|
|
2080
|
|
|
2080
|
|
|
2081
|
expr = expr.right(expr.length() - expr.indexOf("::") - 2);
|
|
2081
|
expr = expr.right(expr.length() - expr.indexOf("::") - 2);
|
|
2082
|
if (typeEntry) {
|
|
2082
|
if (typeEntry) {
|
|
2083
|
return "new " + type->typeEntry()->qualifiedTargetLangName() +
|
|
2083
|
return "new " + type->typeEntry()->qualifiedTargetLangName() +
|
|
2084
|
"(" + typeEntry->qualifiedTargetLangName() + "." + expr + ")";
|
|
2084
|
"(" + typeEntry->qualifiedTargetLangName() + "." + expr + ")";
|
|
2085
|
}
|
|
2085
|
}
|
|
2086
|
}
|
|
2086
|
}
|
|
2087
|
}
|
|
2087
|
}
|
|
2088
|
|
|
2088
|
|
|
2089
|
QString warn = QString("unsupported default value '%3' of argument in function '%1', class '%2'")
|
|
2089
|
QString warn = QString("unsupported default value '%3' of argument in function '%1', class '%2'")
|
|
2090
|
.arg(function_name).arg(class_name).arg(item->defaultValueExpression());
|
|
2090
|
.arg(function_name).arg(class_name).arg(item->defaultValueExpression());
|
|
2091
|
ReportHandler::warning(warn);
|
|
2091
|
ReportHandler::warning(warn);
|
|
2092
|
|
|
2092
|
|
|
2093
|
return QString();
|
|
2093
|
return QString();
|
|
2094
|
}
|
|
2094
|
}
|
|
2095
|
|
|
2095
|
|
|
2096
|
|
|
2096
|
|
|
2097
|
bool AbstractMetaBuilder::isQObject(const QString &qualified_name)
|
|
2097
|
bool AbstractMetaBuilder::isQObject(const QString &qualified_name)
|
|
2098
|
{
|
|
2098
|
{
|
|
2099
|
if (qualified_name == "QObject")
|
|
2099
|
if (qualified_name == "QObject")
|
|
2100
|
return true;
|
|
2100
|
return true;
|
|
2101
|
|
|
2101
|
|
|
2102
|
ClassModelItem class_item = m_dom->findClass(qualified_name);
|
|
2102
|
ClassModelItem class_item = m_dom->findClass(qualified_name);
|
|
2103
|
|
|
2103
|
|
|
2104
|
if (!class_item) {
|
|
2104
|
if (!class_item) {
|
|
2105
|
QStringList names = qualified_name.split(QLatin1String("::"));
|
|
2105
|
QStringList names = qualified_name.split(QLatin1String("::"));
|
|
2106
|
NamespaceModelItem ns = model_dynamic_cast<NamespaceModelItem>(m_dom);
|
|
2106
|
NamespaceModelItem ns = model_dynamic_cast<NamespaceModelItem>(m_dom);
|
|
2107
|
for (int i=0; i<names.size() - 1 && ns; ++i)
|
|
2107
|
for (int i=0; i<names.size() - 1 && ns; ++i)
|
|
2108
|
ns = ns->namespaceMap().value(names.at(i));
|
|
2108
|
ns = ns->namespaceMap().value(names.at(i));
|
|
2109
|
if (ns && names.size() >= 2)
|
|
2109
|
if (ns && names.size() >= 2)
|
|
2110
|
class_item = ns->findClass(names.at(names.size() - 1));
|
|
2110
|
class_item = ns->findClass(names.at(names.size() - 1));
|
|
2111
|
}
|
|
2111
|
}
|
|
2112
|
|
|
2112
|
|
|
2113
|
bool isqobject = class_item && class_item->extendsClass("QObject");
|
|
2113
|
bool isqobject = class_item && class_item->extendsClass("QObject");
|
|
2114
|
|
|
2114
|
|
|
2115
|
if (class_item && !isqobject) {
|
|
2115
|
if (class_item && !isqobject) {
|
|
2116
|
QStringList baseClasses = class_item->baseClasses();
|
|
2116
|
QStringList baseClasses = class_item->baseClasses();
|
|
2117
|
for (int i=0; i<baseClasses.count(); ++i) {
|
|
2117
|
for (int i=0; i<baseClasses.count(); ++i) {
|
|
2118
|
|
|
2118
|
|
|
2119
|
isqobject = isQObject(baseClasses.at(i));
|
|
2119
|
isqobject = isQObject(baseClasses.at(i));
|
|
2120
|
if (isqobject)
|
|
2120
|
if (isqobject)
|
|
2121
|
break;
|
|
2121
|
break;
|
|
2122
|
}
|
|
2122
|
}
|
|
2123
|
}
|
|
2123
|
}
|
|
2124
|
|
|
2124
|
|
|
2125
|
return isqobject;
|
|
2125
|
return isqobject;
|
|
2126
|
}
|
|
2126
|
}
|
|
2127
|
|
|
2127
|
|
|
2128
|
|
|
2128
|
|
|
2129
|
bool AbstractMetaBuilder::isEnum(const QStringList &qualified_name)
|
|
2129
|
bool AbstractMetaBuilder::isEnum(const QStringList &qualified_name)
|
|
2130
|
{
|
|
2130
|
{
|
|
2131
|
CodeModelItem item = m_dom->model()->findItem(qualified_name, m_dom->toItem());
|
|
2131
|
CodeModelItem item = m_dom->model()->findItem(qualified_name, m_dom->toItem());
|
|
2132
|
return item && item->kind() == _EnumModelItem::__node_kind;
|
|
2132
|
return item && item->kind() == _EnumModelItem::__node_kind;
|
|
2133
|
}
|
|
2133
|
}
|
|
2134
|
|
|
2134
|
|
|
2135
|
AbstractMetaType *AbstractMetaBuilder::inheritTemplateType(const QList<AbstractMetaType *> &template_types,
|
|
2135
|
AbstractMetaType *AbstractMetaBuilder::inheritTemplateType(const QList<AbstractMetaType *> &template_types,
|
|
2136
|
AbstractMetaType *meta_type, bool *ok)
|
|
2136
|
AbstractMetaType *meta_type, bool *ok)
|
|
2137
|
{
|
|
2137
|
{
|
|
2138
|
if (ok != 0)
|
|
2138
|
if (ok != 0)
|
|
2139
|
*ok = true;
|
|
2139
|
*ok = true;
|
|
2140
|
if (!meta_type || (!meta_type->typeEntry()->isTemplateArgument() && !meta_type->hasInstantiations()))
|
|
2140
|
if (!meta_type || (!meta_type->typeEntry()->isTemplateArgument() && !meta_type->hasInstantiations()))
|
|
2141
|
return meta_type ? meta_type->copy() : 0;
|
|
2141
|
return meta_type ? meta_type->copy() : 0;
|
|
2142
|
|
|
2142
|
|
|
2143
|
AbstractMetaType *returned = meta_type->copy();
|
|
2143
|
AbstractMetaType *returned = meta_type->copy();
|
|
2144
|
returned->setOriginalTemplateType(meta_type->copy());
|
|
2144
|
returned->setOriginalTemplateType(meta_type->copy());
|
|
2145
|
|
|
2145
|
|
|
2146
|
if (returned->typeEntry()->isTemplateArgument()) {
|
|
2146
|
if (returned->typeEntry()->isTemplateArgument()) {
|
|
2147
|
const TemplateArgumentEntry *tae = static_cast<const TemplateArgumentEntry *>(returned->typeEntry());
|
|
2147
|
const TemplateArgumentEntry *tae = static_cast<const TemplateArgumentEntry *>(returned->typeEntry());
|
|
2148
|
|
|
2148
|
|
|
2149
|
// If the template is intantiated with void we special case this as rejecting the functions that use this
|
|
2149
|
// If the template is intantiated with void we special case this as rejecting the functions that use this
|
|
2150
|
// parameter from the instantiation.
|
|
2150
|
// parameter from the instantiation.
|
|
2151
|
if (template_types.size() <= tae->ordinal() || template_types.at(tae->ordinal())->typeEntry()->name() == "void") {
|
|
2151
|
if (template_types.size() <= tae->ordinal() || template_types.at(tae->ordinal())->typeEntry()->name() == "void") {
|
|
2152
|
if (ok != 0)
|
|
2152
|
if (ok != 0)
|
|
2153
|
*ok = false;
|
|
2153
|
*ok = false;
|
|
2154
|
return 0;
|
|
2154
|
return 0;
|
|
2155
|
}
|
|
2155
|
}
|
|
2156
|
|
|
2156
|
|
|
2157
|
AbstractMetaType *t = returned->copy();
|
|
2157
|
AbstractMetaType *t = returned->copy();
|
|
2158
|
t->setTypeEntry(template_types.at(tae->ordinal())->typeEntry());
|
|
2158
|
t->setTypeEntry(template_types.at(tae->ordinal())->typeEntry());
|
|
2159
|
t->setIndirections(template_types.at(tae->ordinal())->indirections() + t->indirections()
|
|
2159
|
t->setIndirections(template_types.at(tae->ordinal())->indirections() + t->indirections()
|
|
2160
|
? 1
|
|
2160
|
? 1
|
|
2161
|
: 0);
|
|
2161
|
: 0);
|
|
2162
|
decideUsagePattern(t);
|
|
2162
|
decideUsagePattern(t);
|
|
2163
|
|
|
2163
|
|
|
2164
|
delete returned;
|
|
2164
|
delete returned;
|
|
2165
|
returned = inheritTemplateType(template_types, t, ok);
|
|
2165
|
returned = inheritTemplateType(template_types, t, ok);
|
|
2166
|
if (ok != 0 && !(*ok))
|
|
2166
|
if (ok != 0 && !(*ok))
|
|
2167
|
return 0;
|
|
2167
|
return 0;
|
|
2168
|
}
|
|
2168
|
}
|
|
2169
|
|
|
2169
|
|
|
2170
|
if (returned->hasInstantiations()) {
|
|
2170
|
if (returned->hasInstantiations()) {
|
|
2171
|
QList<AbstractMetaType *> instantiations = returned->instantiations();
|
|
2171
|
QList<AbstractMetaType *> instantiations = returned->instantiations();
|
|
2172
|
for (int i=0; i<instantiations.count(); ++i) {
|
|
2172
|
for (int i=0; i<instantiations.count(); ++i) {
|
|
2173
|
instantiations[i] = inheritTemplateType(template_types, instantiations.at(i), ok);
|
|
2173
|
instantiations[i] = inheritTemplateType(template_types, instantiations.at(i), ok);
|
|
2174
|
if (ok != 0 && !(*ok))
|
|
2174
|
if (ok != 0 && !(*ok))
|
|
2175
|
return 0;
|
|
2175
|
return 0;
|
|
2176
|
}
|
|
2176
|
}
|
|
2177
|
returned->setInstantiations(instantiations);
|
|
2177
|
returned->setInstantiations(instantiations);
|
|
2178
|
}
|
|
2178
|
}
|
|
2179
|
|
|
2179
|
|
|
2180
|
return returned;
|
|
2180
|
return returned;
|
|
2181
|
}
|
|
2181
|
}
|
|
2182
|
|
|
2182
|
|
|
2183
|
bool AbstractMetaBuilder::inheritTemplate(AbstractMetaClass *subclass,
|
|
2183
|
bool AbstractMetaBuilder::inheritTemplate(AbstractMetaClass *subclass,
|
|
2184
|
const AbstractMetaClass *template_class,
|
|
2184
|
const AbstractMetaClass *template_class,
|
|
2185
|
const TypeParser::Info &info)
|
|
2185
|
const TypeParser::Info &info)
|
|
2186
|
{
|
|
2186
|
{
|
|
2187
|
QList<TypeParser::Info> targs = info.template_instantiations;
|
|
2187
|
QList<TypeParser::Info> targs = info.template_instantiations;
|
|
2188
|
|
|
2188
|
|
|
2189
|
QList<AbstractMetaType *> template_types;
|
|
2189
|
QList<AbstractMetaType *> template_types;
|
|
2190
|
foreach (const TypeParser::Info &i, targs) {
|
|
2190
|
foreach (const TypeParser::Info &i, targs) {
|
|
2191
|
TypeEntry *t = TypeDatabase::instance()->findType(i.qualified_name.join("::"));
|
|
2191
|
TypeEntry *t = TypeDatabase::instance()->findType(i.qualified_name.join("::"));
|
|
2192
|
|
|
2192
|
|
|
2193
|
if (t != 0) {
|
|
2193
|
if (t != 0) {
|
|
2194
|
AbstractMetaType *temporary_type = createMetaType();
|
|
2194
|
AbstractMetaType *temporary_type = createMetaType();
|
|
2195
|
temporary_type->setTypeEntry(t);
|
|
2195
|
temporary_type->setTypeEntry(t);
|
|
2196
|
temporary_type->setConstant(i.is_constant);
|
|
2196
|
temporary_type->setConstant(i.is_constant);
|
|
2197
|
temporary_type->setReference(i.is_reference);
|
|
2197
|
temporary_type->setReference(i.is_reference);
|
|
2198
|
temporary_type->setIndirections(i.indirections);
|
|
2198
|
temporary_type->setIndirections(i.indirections);
|
|
2199
|
template_types << temporary_type;
|
|
2199
|
template_types << temporary_type;
|
|
2200
|
}
|
|
2200
|
}
|
|
2201
|
}
|
|
2201
|
}
|
|
2202
|
|
|
2202
|
|
|
2203
|
AbstractMetaFunctionList funcs = subclass->functions();
|
|
2203
|
AbstractMetaFunctionList funcs = subclass->functions();
|
|
2204
|
foreach (const AbstractMetaFunction *function, template_class->functions()) {
|
|
2204
|
foreach (const AbstractMetaFunction *function, template_class->functions()) {
|
|
2205
|
|
|
2205
|
|
|
2206
|
if (function->isModifiedRemoved(TypeSystem::All))
|
|
2206
|
if (function->isModifiedRemoved(TypeSystem::All))
|
|
2207
|
continue;
|
|
2207
|
continue;
|
|
2208
|
|
|
2208
|
|
|
2209
|
AbstractMetaFunction *f = function->copy();
|
|
2209
|
AbstractMetaFunction *f = function->copy();
|
|
2210
|
f->setArguments(AbstractMetaArgumentList());
|
|
2210
|
f->setArguments(AbstractMetaArgumentList());
|
|
2211
|
|
|
2211
|
|
|
2212
|
bool ok = true;
|
|
2212
|
bool ok = true;
|
|
2213
|
AbstractMetaType *ftype = function->type();
|
|
2213
|
AbstractMetaType *ftype = function->type();
|
|
2214
|
f->setType(inheritTemplateType(template_types, ftype, &ok));
|
|
2214
|
f->setType(inheritTemplateType(template_types, ftype, &ok));
|
|
2215
|
if (!ok) {
|
|
2215
|
if (!ok) {
|
|
2216
|
delete f;
|
|
2216
|
delete f;
|
|
2217
|
continue;
|
|
2217
|
continue;
|
|
2218
|
}
|
|
2218
|
}
|
|
2219
|
|
|
2219
|
|
|
2220
|
foreach (AbstractMetaArgument *argument, function->arguments()) {
|
|
2220
|
foreach (AbstractMetaArgument *argument, function->arguments()) {
|
|
2221
|
AbstractMetaType *atype = argument->type();
|
|
2221
|
AbstractMetaType *atype = argument->type();
|
|
2222
|
|
|
2222
|
|
|
2223
|
AbstractMetaArgument *arg = argument->copy();
|
|
2223
|
AbstractMetaArgument *arg = argument->copy();
|
|
2224
|
arg->setType(inheritTemplateType(template_types, atype, &ok));
|
|
2224
|
arg->setType(inheritTemplateType(template_types, atype, &ok));
|
|
2225
|
if (!ok)
|
|
2225
|
if (!ok)
|
|
2226
|
break;
|
|
2226
|
break;
|
|
2227
|
f->addArgument(arg);
|
|
2227
|
f->addArgument(arg);
|
|
2228
|
}
|
|
2228
|
}
|
|
2229
|
|
|
2229
|
|
|
2230
|
if (!ok) {
|
|
2230
|
if (!ok) {
|
|
2231
|
delete f;
|
|
2231
|
delete f;
|
|
2232
|
continue ;
|
|
2232
|
continue ;
|
|
2233
|
}
|
|
2233
|
}
|
|
2234
|
|
|
2234
|
|
|
2235
|
// There is no base class in java to inherit from here, so the
|
|
2235
|
// There is no base class in java to inherit from here, so the
|
|
2236
|
// template instantiation is the class that implements the function..
|
|
2236
|
// template instantiation is the class that implements the function..
|
|
2237
|
f->setImplementingClass(subclass);
|
|
2237
|
f->setImplementingClass(subclass);
|
|
2238
|
|
|
2238
|
|
|
2239
|
// We also set it as the declaring class, since the superclass is
|
|
2239
|
// We also set it as the declaring class, since the superclass is
|
|
2240
|
// supposed to disappear. This allows us to make certain function modifications
|
|
2240
|
// supposed to disappear. This allows us to make certain function modifications
|
|
2241
|
// on the inherited functions.
|
|
2241
|
// on the inherited functions.
|
|
2242
|
f->setDeclaringClass(subclass);
|
|
2242
|
f->setDeclaringClass(subclass);
|
|
2243
|
|
|
2243
|
|
|
2244
|
|
|
2244
|
|
|
2245
|
if (f->isConstructor() && subclass->isTypeAlias()) {
|
|
2245
|
if (f->isConstructor() && subclass->isTypeAlias()) {
|
|
2246
|
f->setName(subclass->name());
|
|
2246
|
f->setName(subclass->name());
|
|
2247
|
} else if (f->isConstructor()) {
|
|
2247
|
} else if (f->isConstructor()) {
|
|
2248
|
delete f;
|
|
2248
|
delete f;
|
|
2249
|
continue;
|
|
2249
|
continue;
|
|
2250
|
}
|
|
2250
|
}
|
|
2251
|
|
|
2251
|
|
|
2252
|
// if the instantiation has a function named the same as an existing
|
|
2252
|
// if the instantiation has a function named the same as an existing
|
|
2253
|
// function we have shadowing so we need to skip it.
|
|
2253
|
// function we have shadowing so we need to skip it.
|
|
2254
|
bool found = false;
|
|
2254
|
bool found = false;
|
|
2255
|
for (int i=0; i<funcs.size(); ++i) {
|
|
2255
|
for (int i=0; i<funcs.size(); ++i) {
|
|
2256
|
if (funcs.at(i)->name() == f->name()) {
|
|
2256
|
if (funcs.at(i)->name() == f->name()) {
|
|
2257
|
found = true;
|
|
2257
|
found = true;
|
|
2258
|
continue;
|
|
2258
|
continue;
|
|
2259
|
}
|
|
2259
|
}
|
|
2260
|
}
|
|
2260
|
}
|
|
2261
|
if (found) {
|
|
2261
|
if (found) {
|
|
2262
|
delete f;
|
|
2262
|
delete f;
|
|
2263
|
continue;
|
|
2263
|
continue;
|
|
2264
|
}
|
|
2264
|
}
|
|
2265
|
|
|
2265
|
|
|
2266
|
ComplexTypeEntry *te = subclass->typeEntry();
|
|
2266
|
ComplexTypeEntry *te = subclass->typeEntry();
|
|
2267
|
FunctionModificationList mods = function->modifications(template_class);
|
|
2267
|
FunctionModificationList mods = function->modifications(template_class);
|
|
2268
|
for (int i=0; i<mods.size(); ++i) {
|
|
2268
|
for (int i=0; i<mods.size(); ++i) {
|
|
2269
|
FunctionModification mod = mods.at(i);
|
|
2269
|
FunctionModification mod = mods.at(i);
|
|
2270
|
mod.signature = f->minimalSignature();
|
|
2270
|
mod.signature = f->minimalSignature();
|
|
2271
|
|
|
2271
|
|
|
2272
|
// If we ever need it... Below is the code to do
|
|
2272
|
// If we ever need it... Below is the code to do
|
|
2273
|
// substitution of the template instantation type inside
|
|
2273
|
// substitution of the template instantation type inside
|
|
2274
|
// injected code..
|
|
2274
|
// injected code..
|
|
2275
|
#if 0
|
|
2275
|
#if 0
|
|
2276
|
if (mod.modifiers & Modification::CodeInjection) {
|
|
2276
|
if (mod.modifiers & Modification::CodeInjection) {
|
|
2277
|
for (int j=0; j<template_types.size(); ++j) {
|
|
2277
|
for (int j=0; j<template_types.size(); ++j) {
|
|
2278
|
CodeSnip &snip = mod.snips.last();
|
|
2278
|
CodeSnip &snip = mod.snips.last();
|
|
2279
|
QString code = snip.code();
|
|
2279
|
QString code = snip.code();
|
|
2280
|
code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j),
|
|
2280
|
code.replace(QString::fromLatin1("$$QT_TEMPLATE_%1$$").arg(j),
|
|
2281
|
template_types.at(j)->typeEntry()->qualifiedCppName());
|
|
2281
|
template_types.at(j)->typeEntry()->qualifiedCppName());
|
|
2282
|
snip.codeList.clear();
|
|
2282
|
snip.codeList.clear();
|
|
2283
|
snip.addCode(code);
|
|
2283
|
snip.addCode(code);
|
|
2284
|
}
|
|
2284
|
}
|
|
2285
|
}
|
|
2285
|
}
|
|
2286
|
#endif
|
|
2286
|
#endif
|
|
2287
|
te->addFunctionModification(mod);
|
|
2287
|
te->addFunctionModification(mod);
|
|
2288
|
}
|
|
2288
|
}
|
|
2289
|
|
|
2289
|
|
|
2290
|
subclass->addFunction(f);
|
|
2290
|
subclass->addFunction(f);
|
|
2291
|
}
|
|
2291
|
}
|
|
2292
|
|
|
2292
|
|
|
2293
|
// Clean up
|
|
2293
|
// Clean up
|
|
2294
|
foreach (AbstractMetaType *type, template_types) {
|
|
2294
|
foreach (AbstractMetaType *type, template_types) {
|
|
2295
|
delete type;
|
|
2295
|
delete type;
|
|
2296
|
}
|
|
2296
|
}
|
|
2297
|
|
|
2297
|
|
|
2298
|
|
|
2298
|
|
|
2299
|
{
|
|
2299
|
{
|
|
2300
|
subclass->setTemplateBaseClass(template_class);
|
|
2300
|
subclass->setTemplateBaseClass(template_class);
|
|
2301
|
|
|
2301
|
|
|
2302
|
subclass->setInterfaces(template_class->interfaces());
|
|
2302
|
subclass->setInterfaces(template_class->interfaces());
|
|
2303
|
subclass->setBaseClass(template_class->baseClass());
|
|
2303
|
subclass->setBaseClass(template_class->baseClass());
|
|
2304
|
}
|
|
2304
|
}
|
|
2305
|
|
|
2305
|
|
|
2306
|
return true;
|
|
2306
|
return true;
|
|
2307
|
}
|
|
2307
|
}
|
|
2308
|
|
|
2308
|
|
|
2309
|
void AbstractMetaBuilder::parseQ_Property(AbstractMetaClass *meta_class, const QStringList &declarations)
|
|
2309
|
void AbstractMetaBuilder::parseQ_Property(AbstractMetaClass *meta_class, const QStringList &declarations)
|
|
2310
|
{
|
|
2310
|
{
|
|
2311
|
for (int i=0; i<declarations.size(); ++i) {
|
|
2311
|
for (int i=0; i<declarations.size(); ++i) {
|
|
2312
|
QString p = declarations.at(i);
|
|
2312
|
QString p = declarations.at(i);
|
|
2313
|
|
|
2313
|
|
|
2314
|
QStringList l = p.split(QLatin1String(" "));
|
|
2314
|
QStringList l = p.split(QLatin1String(" "));
|
|
2315
|
|
|
2315
|
|
|
2316
|
|
|
2316
|
|
|
2317
|
QStringList qualifiedScopeName = currentScope()->qualifiedName();
|
|
2317
|
QStringList qualifiedScopeName = currentScope()->qualifiedName();
|
|
2318
|
bool ok = false;
|
|
2318
|
bool ok = false;
|
|
2319
|
AbstractMetaType *type = 0;
|
|
2319
|
AbstractMetaType *type = 0;
|
|
2320
|
QString scope;
|
|
2320
|
QString scope;
|
|
2321
|
for (int j=qualifiedScopeName.size(); j>=0; --j) {
|
|
2321
|
for (int j=qualifiedScopeName.size(); j>=0; --j) {
|
|
2322
|
scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join("::") + "::" : QString();
|
|
2322
|
scope = j > 0 ? QStringList(qualifiedScopeName.mid(0, j)).join("::") + "::" : QString();
|
|
2323
|
TypeInfo info;
|
|
2323
|
TypeInfo info;
|
|
2324
|
info.setQualifiedName((scope + l.at(0)).split("::"));
|
|
2324
|
info.setQualifiedName((scope + l.at(0)).split("::"));
|
|
2325
|
|
|
2325
|
|
|
2326
|
type = translateType(info, &ok);
|
|
2326
|
type = translateType(info, &ok);
|
|
2327
|
if (type != 0 && ok) {
|
|
2327
|
if (type != 0 && ok) {
|
|
2328
|
break;
|
|
2328
|
break;
|
|
2329
|
}
|
|
2329
|
}
|
|
2330
|
}
|
|
2330
|
}
|
|
2331
|
|
|
2331
|
|
|
2332
|
if (type == 0 || !ok) {
|
|
2332
|
if (type == 0 || !ok) {
|
|
2333
|
ReportHandler::warning(QString("Unable to decide type of property: '%1' in class '%2'")
|
|
2333
|
ReportHandler::warning(QString("Unable to decide type of property: '%1' in class '%2'")
|
|
2334
|
.arg(l.at(0)).arg(meta_class->name()));
|
|
2334
|
.arg(l.at(0)).arg(meta_class->name()));
|
|
2335
|
continue;
|
|
2335
|
continue;
|
|
2336
|
}
|
|
2336
|
}
|
|
2337
|
|
|
2337
|
|
|
2338
|
QString typeName = scope + l.at(0);
|
|
2338
|
QString typeName = scope + l.at(0);
|
|
2339
|
|
|
2339
|
|
|
2340
|
QPropertySpec *spec = new QPropertySpec(type->typeEntry());
|
|
2340
|
QPropertySpec *spec = new QPropertySpec(type->typeEntry());
|
|
2341
|
spec->setName(l.at(1));
|
|
2341
|
spec->setName(l.at(1));
|
|
2342
|
spec->setIndex(i);
|
|
2342
|
spec->setIndex(i);
|
|
2343
|
|
|
2343
|
|
|
2344
|
for (int pos=2; pos+1<l.size(); pos+=2) {
|
|
2344
|
for (int pos=2; pos+1<l.size(); pos+=2) {
|
|
2345
|
if (l.at(pos) == QLatin1String("READ"))
|
|
2345
|
if (l.at(pos) == QLatin1String("READ"))
|
|
2346
|
spec->setRead(l.at(pos+1));
|
|
2346
|
spec->setRead(l.at(pos+1));
|
|
2347
|
else if (l.at(pos) == QLatin1String("WRITE"))
|
|
2347
|
else if (l.at(pos) == QLatin1String("WRITE"))
|
|
2348
|
spec->setWrite(l.at(pos+1));
|
|
2348
|
spec->setWrite(l.at(pos+1));
|
|
2349
|
else if (l.at(pos) == QLatin1String("DESIGNABLE"))
|
|
2349
|
else if (l.at(pos) == QLatin1String("DESIGNABLE"))
|
|
2350
|
spec->setDesignable(l.at(pos+1));
|
|
2350
|
spec->setDesignable(l.at(pos+1));
|
|
2351
|
else if (l.at(pos) == QLatin1String("RESET"))
|
|
2351
|
else if (l.at(pos) == QLatin1String("RESET"))
|
|
2352
|
spec->setReset(l.at(pos+1));
|
|
2352
|
spec->setReset(l.at(pos+1));
|
|
2353
|
}
|
|
2353
|
}
|
|
2354
|
|
|
2354
|
|
|
2355
|
meta_class->addPropertySpec(spec);
|
|
2355
|
meta_class->addPropertySpec(spec);
|
|
2356
|
delete type;
|
|
2356
|
delete type;
|
|
2357
|
}
|
|
2357
|
}
|
|
2358
|
}
|
|
2358
|
}
|
|
2359
|
|
|
2359
|
|
|
2360
|
static void hide_functions(const AbstractMetaFunctionList &l) {
|
|
2360
|
static void hide_functions(const AbstractMetaFunctionList &l) {
|
|
2361
|
foreach (AbstractMetaFunction *f, l) {
|
|
2361
|
foreach (AbstractMetaFunction *f, l) {
|
|
2362
|
FunctionModification mod;
|
|
2362
|
FunctionModification mod;
|
|
2363
|
mod.signature = f->minimalSignature();
|
|
2363
|
mod.signature = f->minimalSignature();
|
|
2364
|
mod.modifiers = FunctionModification::Private;
|
|
2364
|
mod.modifiers = FunctionModification::Private;
|
|
2365
|
((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
|
|
2365
|
((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
|
|
2366
|
}
|
|
2366
|
}
|
|
2367
|
}
|
|
2367
|
}
|
|
2368
|
|
|
2368
|
|
|
2369
|
static void remove_function(AbstractMetaFunction *f) {
|
|
2369
|
static void remove_function(AbstractMetaFunction *f) {
|
|
2370
|
FunctionModification mod;
|
|
2370
|
FunctionModification mod;
|
|
2371
|
mod.removal = TypeSystem::All;
|
|
2371
|
mod.removal = TypeSystem::All;
|
|
2372
|
mod.signature = f->minimalSignature();
|
|
2372
|
mod.signature = f->minimalSignature();
|
|
2373
|
((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
|
|
2373
|
((ComplexTypeEntry *) f->implementingClass()->typeEntry())->addFunctionModification(mod);
|
|
2374
|
}
|
|
2374
|
}
|
|
2375
|
|
|
2375
|
|
|
2376
|
static AbstractMetaFunctionList filter_functions(const AbstractMetaFunctionList &lst, QSet<QString> *signatures)
|
|
2376
|
static AbstractMetaFunctionList filter_functions(const AbstractMetaFunctionList &lst, QSet<QString> *signatures)
|
|
2377
|
{
|
|
2377
|
{
|
|
2378
|
AbstractMetaFunctionList functions;
|
|
2378
|
AbstractMetaFunctionList functions;
|
|
2379
|
foreach (AbstractMetaFunction *f, lst) {
|
|
2379
|
foreach (AbstractMetaFunction *f, lst) {
|
|
2380
|
QString signature = f->minimalSignature();
|
|
2380
|
QString signature = f->minimalSignature();
|
|
2381
|
int start = signature.indexOf(QLatin1Char('(')) + 1;
|
|
2381
|
int start = signature.indexOf(QLatin1Char('(')) + 1;
|
|
2382
|
int end = signature.lastIndexOf(QLatin1Char(')'));
|
|
2382
|
int end = signature.lastIndexOf(QLatin1Char(')'));
|
|
2383
|
signature = signature.mid(start, end - start);
|
|
2383
|
signature = signature.mid(start, end - start);
|
|
2384
|
if (signatures->contains(signature)) {
|
|
2384
|
if (signatures->contains(signature)) {
|
|
2385
|
remove_function(f);
|
|
2385
|
remove_function(f);
|
|
2386
|
continue;
|
|
2386
|
continue;
|
|
2387
|
}
|
|
2387
|
}
|
|
2388
|
(*signatures) << signature;
|
|
2388
|
(*signatures) << signature;
|
|
2389
|
functions << f;
|
|
2389
|
functions << f;
|
|
2390
|
}
|
|
2390
|
}
|
|
2391
|
return functions;
|
|
2391
|
return functions;
|
|
2392
|
}
|
|
2392
|
}
|
|
2393
|
|
|
2393
|
|
|
2394
|
void AbstractMetaBuilder::setupEquals(AbstractMetaClass *cls)
|
|
2394
|
void AbstractMetaBuilder::setupEquals(AbstractMetaClass *cls)
|
|
2395
|
{
|
|
2395
|
{
|
|
2396
|
AbstractMetaFunctionList equals;
|
|
2396
|
AbstractMetaFunctionList equals;
|
|
2397
|
AbstractMetaFunctionList nequals;
|
|
2397
|
AbstractMetaFunctionList nequals;
|
|
2398
|
|
|
2398
|
|
|
2399
|
QString op_equals = QLatin1String("operator_equal");
|
|
2399
|
QString op_equals = QLatin1String("operator_equal");
|
|
2400
|
QString op_nequals = QLatin1String("operator_not_equal");
|
|
2400
|
QString op_nequals = QLatin1String("operator_not_equal");
|
|
2401
|
|
|
2401
|
|
|
2402
|
AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
|
|
2402
|
AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
|
|
2403
|
| AbstractMetaClass::NotRemovedFromTargetLang);
|
|
2403
|
| AbstractMetaClass::NotRemovedFromTargetLang);
|
|
2404
|
foreach (AbstractMetaFunction *f, functions) {
|
|
2404
|
foreach (AbstractMetaFunction *f, functions) {
|
|
2405
|
if (f->name() == op_equals)
|
|
2405
|
if (f->name() == op_equals)
|
|
2406
|
equals << f;
|
|
2406
|
equals << f;
|
|
2407
|
else if (f->name() == op_nequals)
|
|
2407
|
else if (f->name() == op_nequals)
|
|
2408
|
nequals << f;
|
|
2408
|
nequals << f;
|
|
2409
|
}
|
|
2409
|
}
|
|
2410
|
|
|
2410
|
|
|
2411
|
if (equals.size() || nequals.size()) {
|
|
2411
|
if (equals.size() || nequals.size()) {
|
|
2412
|
if (!cls->hasHashFunction()) {
|
|
2412
|
if (!cls->hasHashFunction()) {
|
|
2413
|
ReportHandler::warning(QString::fromLatin1("Class '%1' has equals operators but no qHash() function")
|
|
2413
|
ReportHandler::warning(QString::fromLatin1("Class '%1' has equals operators but no qHash() function")
|
|
2414
|
.arg(cls->name()));
|
|
2414
|
.arg(cls->name()));
|
|
2415
|
}
|
|
2415
|
}
|
|
2416
|
|
|
2416
|
|
|
2417
|
hide_functions(equals);
|
|
2417
|
hide_functions(equals);
|
|
2418
|
hide_functions(nequals);
|
|
2418
|
hide_functions(nequals);
|
|
2419
|
|
|
2419
|
|
|
2420
|
// We only need == if we have both == and !=, and one == for
|
|
2420
|
// We only need == if we have both == and !=, and one == for
|
|
2421
|
// each signature type, like QDateTime::==(QDate) and (QTime)
|
|
2421
|
// each signature type, like QDateTime::==(QDate) and (QTime)
|
|
2422
|
// if such a thing exists...
|
|
2422
|
// if such a thing exists...
|
|
2423
|
QSet<QString> func_signatures;
|
|
2423
|
QSet<QString> func_signatures;
|
|
2424
|
cls->setEqualsFunctions(filter_functions(equals, &func_signatures));
|
|
2424
|
cls->setEqualsFunctions(filter_functions(equals, &func_signatures));
|
|
2425
|
cls->setNotEqualsFunctions(filter_functions(nequals, &func_signatures));
|
|
2425
|
cls->setNotEqualsFunctions(filter_functions(nequals, &func_signatures));
|
|
2426
|
}
|
|
2426
|
}
|
|
2427
|
}
|
|
2427
|
}
|
|
2428
|
|
|
2428
|
|
|
2429
|
void AbstractMetaBuilder::setupComparable(AbstractMetaClass *cls)
|
|
2429
|
void AbstractMetaBuilder::setupComparable(AbstractMetaClass *cls)
|
|
2430
|
{
|
|
2430
|
{
|
|
2431
|
AbstractMetaFunctionList greater;
|
|
2431
|
AbstractMetaFunctionList greater;
|
|
2432
|
AbstractMetaFunctionList greaterEquals;
|
|
2432
|
AbstractMetaFunctionList greaterEquals;
|
|
2433
|
AbstractMetaFunctionList less;
|
|
2433
|
AbstractMetaFunctionList less;
|
|
2434
|
AbstractMetaFunctionList lessEquals;
|
|
2434
|
AbstractMetaFunctionList lessEquals;
|
|
2435
|
|
|
2435
|
|
|
2436
|
QString op_greater = QLatin1String("operator_greater");
|
|
2436
|
QString op_greater = QLatin1String("operator_greater");
|
|
2437
|
QString op_greater_eq = QLatin1String("operator_greater_or_equal");
|
|
2437
|
QString op_greater_eq = QLatin1String("operator_greater_or_equal");
|
|
2438
|
QString op_less = QLatin1String("operator_less");
|
|
2438
|
QString op_less = QLatin1String("operator_less");
|
|
2439
|
QString op_less_eq = QLatin1String("operator_less_or_equal");
|
|
2439
|
QString op_less_eq = QLatin1String("operator_less_or_equal");
|
|
2440
|
|
|
2440
|
|
|
2441
|
AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
|
|
2441
|
AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements
|
|
2442
|
| AbstractMetaClass::NotRemovedFromTargetLang);
|
|
2442
|
| AbstractMetaClass::NotRemovedFromTargetLang);
|
|
2443
|
foreach (AbstractMetaFunction *f, functions) {
|
|
2443
|
foreach (AbstractMetaFunction *f, functions) {
|
|
2444
|
if (f->name() == op_greater)
|
|
2444
|
if (f->name() == op_greater)
|
|
2445
|
greater << f;
|
|
2445
|
greater << f;
|
|
2446
|
else if (f->name() == op_greater_eq)
|
|
2446
|
else if (f->name() == op_greater_eq)
|
|
2447
|
greaterEquals << f;
|
|
2447
|
greaterEquals << f;
|
|
2448
|
else if (f->name() == op_less)
|
|
2448
|
else if (f->name() == op_less)
|
|
2449
|
less << f;
|
|
2449
|
less << f;
|
|
2450
|
else if (f->name() == op_less_eq)
|
|
2450
|
else if (f->name() == op_less_eq)
|
|
2451
|
lessEquals << f;
|
|
2451
|
lessEquals << f;
|
|
2452
|
}
|
|
2452
|
}
|
|
2453
|
|
|
2453
|
|
|
2454
|
bool hasEquals = cls->equalsFunctions().size() || cls->notEqualsFunctions().size();
|
|
2454
|
bool hasEquals = cls->equalsFunctions().size() || cls->notEqualsFunctions().size();
|
|
2455
|
|
|
2455
|
|
|
2456
|
// Conditions for comparable is:
|
|
2456
|
// Conditions for comparable is:
|
|
2457
|
// >, ==, < - The basic case
|
|
2457
|
// >, ==, < - The basic case
|
|
2458
|
// >, == - Less than becomes else case
|
|
2458
|
// >, == - Less than becomes else case
|
|
2459
|
// <, == - Greater than becomes else case
|
|
2459
|
// <, == - Greater than becomes else case
|
|
2460
|
// >=, <= - if (<= && >=) -> equal
|
|
2460
|
// >=, <= - if (<= && >=) -> equal
|
|
2461
|
bool mightBeComparable = greater.size() || greaterEquals.size() || less.size() || lessEquals.size()
|
|
2461
|
bool mightBeComparable = greater.size() || greaterEquals.size() || less.size() || lessEquals.size()
|
|
2462
|
|| greaterEquals.size() == 1 || lessEquals.size() == 1;
|
|
2462
|
|| greaterEquals.size() == 1 || lessEquals.size() == 1;
|
|
2463
|
|
|
2463
|
|
|
2464
|
if (mightBeComparable) {
|
|
2464
|
if (mightBeComparable) {
|
|
2465
|
QSet<QString> signatures;
|
|
2465
|
QSet<QString> signatures;
|
|
2466
|
|
|
2466
|
|
|
2467
|
// We only hide the original functions if we are able to make a compareTo() method
|
|
2467
|
// We only hide the original functions if we are able to make a compareTo() method
|
|
2468
|
bool wasComparable = false;
|
|
2468
|
bool wasComparable = false;
|
|
2469
|
|
|
2469
|
|
|
2470
|
// The three upper cases, prefer the <, == approach
|
|
2470
|
// The three upper cases, prefer the <, == approach
|
|
2471
|
if (hasEquals && (greater.size() || less.size())) {
|
|
2471
|
if (hasEquals && (greater.size() || less.size())) {
|
|
2472
|
cls->setLessThanFunctions(filter_functions(less, &signatures));
|
|
2472
|
cls->setLessThanFunctions(filter_functions(less, &signatures));
|
|
2473
|
cls->setGreaterThanFunctions(filter_functions(greater, &signatures));
|
|
2473
|
cls->setGreaterThanFunctions(filter_functions(greater, &signatures));
|
|
2474
|
filter_functions(greaterEquals, &signatures);
|
|
2474
|
filter_functions(greaterEquals, &signatures);
|
|
2475
|
filter_functions(lessEquals, &signatures);
|
|
2475
|
filter_functions(lessEquals, &signatures);
|
|
2476
|
wasComparable = true;
|
|
2476
|
wasComparable = true;
|
|
2477
|
} else if (hasEquals && (greaterEquals.size() || lessEquals.size())) {
|
|
2477
|
} else if (hasEquals && (greaterEquals.size() || lessEquals.size())) {
|
|
2478
|
cls->setLessThanEqFunctions(filter_functions(lessEquals, &signatures));
|
|
2478
|
cls->setLessThanEqFunctions(filter_functions(lessEquals, &signatures));
|
|
2479
|
cls->setGreaterThanEqFunctions(filter_functions(greaterEquals, &signatures));
|
|
2479
|
cls->setGreaterThanEqFunctions(filter_functions(greaterEquals, &signatures));
|
|
2480
|
wasComparable = true;
|
|
2480
|
wasComparable = true;
|
|
2481
|
} else if (greaterEquals.size() == 1 || lessEquals.size() == 1) {
|
|
2481
|
} else if (greaterEquals.size() == 1 || lessEquals.size() == 1) {
|
|
2482
|
cls->setGreaterThanEqFunctions(greaterEquals);
|
|
2482
|
cls->setGreaterThanEqFunctions(greaterEquals);
|
|
2483
|
cls->setLessThanEqFunctions(lessEquals);
|
|
2483
|
cls->setLessThanEqFunctions(lessEquals);
|
|
2484
|
filter_functions(less, &signatures);
|
|
2484
|
filter_functions(less, &signatures);
|
|
2485
|
filter_functions(greater, &signatures);
|
|
2485
|
filter_functions(greater, &signatures);
|
|
2486
|
wasComparable = true;
|
|
2486
|
wasComparable = true;
|
|
2487
|
}
|
|
2487
|
}
|
|
2488
|
|
|
2488
|
|
|
2489
|
if (wasComparable) {
|
|
2489
|
if (wasComparable) {
|
|
2490
|
hide_functions(greater);
|
|
2490
|
hide_functions(greater);
|
|
2491
|
hide_functions(greaterEquals);
|
|
2491
|
hide_functions(greaterEquals);
|
|
2492
|
hide_functions(less);
|
|
2492
|
hide_functions(less);
|
|
2493
|
hide_functions(lessEquals);
|
|
2493
|
hide_functions(lessEquals);
|
|
2494
|
}
|
|
2494
|
}
|
|
2495
|
}
|
|
2495
|
}
|
|
2496
|
|
|
2496
|
|
|
2497
|
}
|
|
2497
|
}
|
|
2498
|
|
|
2498
|
|
|
2499
|
void AbstractMetaBuilder::setupClonable(AbstractMetaClass *cls)
|
|
2499
|
void AbstractMetaBuilder::setupClonable(AbstractMetaClass *cls)
|
|
2500
|
{
|
|
2500
|
{
|
|
2501
|
QString op_assign = QLatin1String("operator_assign");
|
|
2501
|
QString op_assign = QLatin1String("operator_assign");
|
|
2502
|
|
|
2502
|
|
|
2503
|
AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements);
|
|
2503
|
AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::ClassImplements);
|
|
2504
|
foreach (AbstractMetaFunction *f, functions) {
|
|
2504
|
foreach (AbstractMetaFunction *f, functions) {
|
|
2505
|
if ((f->name() == op_assign || f->isConstructor()) && f->isPublic()) {
|
|
2505
|
if ((f->name() == op_assign || f->isConstructor()) && f->isPublic()) {
|
|
2506
|
AbstractMetaArgumentList arguments = f->arguments();
|
|
2506
|
AbstractMetaArgumentList arguments = f->arguments();
|
|
2507
|
if (arguments.size() == 1) {
|
|
2507
|
if (arguments.size() == 1) {
|
|
2508
|
if (cls->typeEntry()->qualifiedCppName() == arguments.at(0)->type()->typeEntry()->qualifiedCppName()) {
|
|
2508
|
if (cls->typeEntry()->qualifiedCppName() == arguments.at(0)->type()->typeEntry()->qualifiedCppName()) {
|
|
2509
|
if (cls->typeEntry()->isValue()) {
|
|
2509
|
if (cls->typeEntry()->isValue()) {
|
|
2510
|
cls->setHasCloneOperator(true);
|
|
2510
|
cls->setHasCloneOperator(true);
|
|
2511
|
return;
|
|
2511
|
return;
|
|
2512
|
}
|
|
2512
|
}
|
|
2513
|
}
|
|
2513
|
}
|
|
2514
|
}
|
|
2514
|
}
|
|
2515
|
}
|
|
2515
|
}
|
|
2516
|
}
|
|
2516
|
}
|
|
2517
|
}
|
|
2517
|
}
|
|
2518
|
|
|
2518
|
|
|
2519
|
static void write_reject_log_file(const QString &name,
|
|
2519
|
static void write_reject_log_file(const QString &name,
|
|
2520
|
const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects)
|
|
2520
|
const QMap<QString, AbstractMetaBuilder::RejectReason> &rejects)
|
|
2521
|
{
|
|
2521
|
{
|
|
2522
|
QFile f(name);
|
|
2522
|
QFile f(name);
|
|
2523
|
if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
2523
|
if (!f.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
|
2524
|
ReportHandler::warning(QString("failed to write log file: '%1'")
|
|
2524
|
ReportHandler::warning(QString("failed to write log file: '%1'")
|
|
2525
|
.arg(f.fileName()));
|
|
2525
|
.arg(f.fileName()));
|
|
2526
|
return;
|
|
2526
|
return;
|
|
2527
|
}
|
|
2527
|
}
|
|
2528
|
|
|
2528
|
|
|
2529
|
QTextStream s(&f);
|
|
2529
|
QTextStream s(&f);
|
|
2530
|
|
|
2530
|
|
|
2531
|
|
|
2531
|
|
|
2532
|
for (int reason=0; reason<AbstractMetaBuilder::NoReason; ++reason) {
|
|
2532
|
for (int reason=0; reason<AbstractMetaBuilder::NoReason; ++reason) {
|
|
2533
|
s << QString(72, '*') << endl;
|
|
2533
|
s << QString(72, '*') << endl;
|
|
2534
|
switch (reason) {
|
|
2534
|
switch (reason) {
|
|
2535
|
case AbstractMetaBuilder::NotInTypeSystem:
|
|
2535
|
case AbstractMetaBuilder::NotInTypeSystem:
|
|
2536
|
s << "Not in type system";
|
|
2536
|
s << "Not in type system";
|
|
2537
|
break;
|
|
2537
|
break;
|
|
2538
|
case AbstractMetaBuilder::GenerationDisabled:
|
|
2538
|
case AbstractMetaBuilder::GenerationDisabled:
|
|
2539
|
s << "Generation disabled by type system";
|
|
2539
|
s << "Generation disabled by type system";
|
|
2540
|
break;
|
|
2540
|
break;
|
|
2541
|
case AbstractMetaBuilder::RedefinedToNotClass:
|
|
2541
|
case AbstractMetaBuilder::RedefinedToNotClass:
|
|
2542
|
s << "Type redefined to not be a class";
|
|
2542
|
s << "Type redefined to not be a class";
|
|
2543
|
break;
|
|
2543
|
break;
|
|
2544
|
|
|
2544
|
|
|
2545
|
case AbstractMetaBuilder::UnmatchedReturnType:
|
|
2545
|
case AbstractMetaBuilder::UnmatchedReturnType:
|
|
2546
|
s << "Unmatched return type";
|
|
2546
|
s << "Unmatched return type";
|
|
2547
|
break;
|
|
2547
|
break;
|
|
2548
|
|
|
2548
|
|
|
2549
|
case AbstractMetaBuilder::UnmatchedArgumentType:
|
|
2549
|
case AbstractMetaBuilder::UnmatchedArgumentType:
|
|
2550
|
s << "Unmatched argument type";
|
|
2550
|
s << "Unmatched argument type";
|
|
2551
|
break;
|
|
2551
|
break;
|
|
2552
|
|
|
2552
|
|
|
2553
|
default:
|
|
2553
|
default:
|
|
2554
|
s << "unknown reason";
|
|
2554
|
s << "unknown reason";
|
|
2555
|
break;
|
|
2555
|
break;
|
|
2556
|
}
|
|
2556
|
}
|
|
2557
|
|
|
2557
|
|
|
2558
|
s << endl;
|
|
2558
|
s << endl;
|
|
2559
|
|
|
2559
|
|
|
2560
|
for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin();
|
|
2560
|
for (QMap<QString, AbstractMetaBuilder::RejectReason>::const_iterator it = rejects.constBegin();
|
|
2561
|
it != rejects.constEnd(); ++it) {
|
|
2561
|
it != rejects.constEnd(); ++it) {
|
|
2562
|
if (it.value() != reason)
|
|
2562
|
if (it.value() != reason)
|
|
2563
|
continue;
|
|
2563
|
continue;
|
|
2564
|
s << " - " << it.key() << endl;
|
|
2564
|
s << " - " << it.key() << endl;
|
|
2565
|
}
|
|
2565
|
}
|
|
2566
|
|
|
2566
|
|
|
2567
|
s << QString(72, '*') << endl << endl;
|
|
2567
|
s << QString(72, '*') << endl << endl;
|
|
2568
|
}
|
|
2568
|
}
|
|
2569
|
|
|
2569
|
|
|
2570
|
}
|
|
2570
|
}
|
|
2571
|
|
|
2571
|
|
|
2572
|
|
|
2572
|
|
|
2573
|
void AbstractMetaBuilder::dumpLog()
|
|
2573
|
void AbstractMetaBuilder::dumpLog()
|
|
2574
|
{
|
|
2574
|
{
|
|
2575
|
write_reject_log_file("mjb_rejected_classes.log", m_rejected_classes);
|
|
2575
|
write_reject_log_file("mjb_rejected_classes.log", m_rejected_classes);
|
|
2576
|
write_reject_log_file("mjb_rejected_enums.log", m_rejected_enums);
|
|
2576
|
write_reject_log_file("mjb_rejected_enums.log", m_rejected_enums);
|
|
2577
|
write_reject_log_file("mjb_rejected_functions.log", m_rejected_functions);
|
|
2577
|
write_reject_log_file("mjb_rejected_functions.log", m_rejected_functions);
|
|
2578
|
write_reject_log_file("mjb_rejected_fields.log", m_rejected_fields);
|
|
2578
|
write_reject_log_file("mjb_rejected_fields.log", m_rejected_fields);
|
|
2579
|
}
|
|
2579
|
}
|
|
2580
|
|
|
2580
|
|
|
2581
|
AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted() const
|
|
2581
|
AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted() const
|
|
2582
|
{
|
|
2582
|
{
|
|
2583
|
AbstractMetaClassList res;
|
|
2583
|
AbstractMetaClassList res;
|
|
2584
|
|
|
2584
|
|
|
2585
|
AbstractMetaClassList classes = m_meta_classes;
|
|
2585
|
AbstractMetaClassList classes = m_meta_classes;
|
|
2586
|
qSort(classes);
|
|
2586
|
qSort(classes);
|
|
2587
|
|
|
2587
|
|
|
2588
|
QSet<AbstractMetaClass*> noDependency;
|
|
2588
|
QSet<AbstractMetaClass*> noDependency;
|
|
2589
|
QHash<AbstractMetaClass*, QSet<AbstractMetaClass* >* > hash;
|
|
2589
|
QHash<AbstractMetaClass*, QSet<AbstractMetaClass* >* > hash;
|
|
2590
|
foreach (AbstractMetaClass *cls, classes) {
|
|
2590
|
foreach (AbstractMetaClass *cls, classes) {
|
|
2591
|
QSet<AbstractMetaClass* > *depends = new QSet<AbstractMetaClass* >();
|
|
2591
|
QSet<AbstractMetaClass* > *depends = new QSet<AbstractMetaClass* >();
|
|
2592
|
|
|
2592
|
|
|
2593
|
if (cls->baseClass())
|
|
2593
|
if (cls->baseClass())
|
|
2594
|
depends->insert(cls->baseClass());
|
|
2594
|
depends->insert(cls->baseClass());
|
|
2595
|
|
|
2595
|
|
|
2596
|
foreach (AbstractMetaClass *interface, cls->interfaces()) {
|
|
2596
|
foreach (AbstractMetaClass *interface, cls->interfaces()) {
|
|
2597
|
AbstractMetaClass *impl = interface->primaryInterfaceImplementor();
|
|
2597
|
AbstractMetaClass *impl = interface->primaryInterfaceImplementor();
|
|
2598
|
if (impl == cls)
|
|
2598
|
if (impl == cls)
|
|
2599
|
continue;
|
|
2599
|
continue;
|
|
2600
|
depends->insert(impl);
|
|
2600
|
depends->insert(impl);
|
|
2601
|
}
|
|
2601
|
}
|
|
2602
|
|
|
2602
|
|
|
2603
|
if (depends->empty()) {
|
|
2603
|
if (depends->empty()) {
|
|
2604
|
noDependency.insert(cls);
|
|
2604
|
noDependency.insert(cls);
|
|
2605
|
} else {
|
|
2605
|
} else {
|
|
2606
|
hash.insert(cls, depends);
|
|
2606
|
hash.insert(cls, depends);
|
|
2607
|
}
|
|
2607
|
}
|
|
2608
|
}
|
|
2608
|
}
|
|
2609
|
|
|
2609
|
|
|
2610
|
while (!noDependency.empty()) {
|
|
2610
|
while (!noDependency.empty()) {
|
|
2611
|
foreach (AbstractMetaClass *cls, noDependency.values()) {
|
|
2611
|
foreach (AbstractMetaClass *cls, noDependency.values()) {
|
|
2612
|
if(!cls->isInterface())
|
|
2612
|
if(!cls->isInterface())
|
|
2613
|
res.append(cls);
|
|
2613
|
res.append(cls);
|
|
2614
|
noDependency.remove(cls);
|
|
2614
|
noDependency.remove(cls);
|
|
2615
|
QHashIterator<AbstractMetaClass*, QSet<AbstractMetaClass* >* > i(hash);
|
|
2615
|
QHashIterator<AbstractMetaClass*, QSet<AbstractMetaClass* >* > i(hash);
|
|
2616
|
while (i.hasNext()) {
|
|
2616
|
while (i.hasNext()) {
|
|
2617
|
i.next();
|
|
2617
|
i.next();
|
|
2618
|
i.value()->remove(cls);
|
|
2618
|
i.value()->remove(cls);
|
|
2619
|
if (i.value()->empty()) {
|
|
2619
|
if (i.value()->empty()) {
|
|
2620
|
AbstractMetaClass *key = i.key();
|
|
2620
|
AbstractMetaClass *key = i.key();
|
|
2621
|
noDependency.insert(key);
|
|
2621
|
noDependency.insert(key);
|
|
2622
|
hash.remove(key);
|
|
2622
|
hash.remove(key);
|
|
2623
|
delete(i.value());
|
|
2623
|
delete(i.value());
|
|
2624
|
}
|
|
2624
|
}
|
|
2625
|
}
|
|
2625
|
}
|
|
2626
|
}
|
|
2626
|
}
|
|
2627
|
}
|
|
2627
|
}
|
|
2628
|
|
|
2628
|
|
|
2629
|
if (!noDependency.empty() || !hash.empty()) {
|
|
2629
|
if (!noDependency.empty() || !hash.empty()) {
|
|
2630
|
qWarning("dependency graph was cyclic.");
|
|
2630
|
qWarning("dependency graph was cyclic.");
|
|
2631
|
}
|
|
2631
|
}
|
|
2632
|
|
|
2632
|
|
|
2633
|
return res;
|
|
2633
|
return res;
|
|
2634
|
}
|
|
2634
|
}
|