Mercurial > projects > qtd
annotate generator/typesystem.cpp @ 377:8f7d09e4efc0
add missing D files to the build system@
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Fri, 09 Jul 2010 22:54:51 +0600 |
parents | beaf4a2974d7 |
children |
rev | line source |
---|---|
1 | 1 /**************************************************************************** |
2 ** | |
3 ** Copyright (C) 1992-2008 Nokia. All rights reserved. | |
4 ** | |
5 ** This file is part of Qt Jambi. | |
6 ** | |
7 ** * Commercial Usage | |
8 * Licensees holding valid Qt Commercial licenses may use this file in | |
9 * accordance with the Qt Commercial License Agreement provided with the | |
10 * Software or, alternatively, in accordance with the terms contained in | |
11 * a written agreement between you and Nokia. | |
12 * | |
13 * | |
14 * GNU General Public License Usage | |
15 * Alternatively, this file may be used under the terms of the GNU | |
16 * General Public License versions 2.0 or 3.0 as published by the Free | |
17 * Software Foundation and appearing in the file LICENSE.GPL included in | |
18 * the packaging of this file. Please review the following information | |
19 * to ensure GNU General Public Licensing requirements will be met: | |
20 * http://www.fsf.org/licensing/licenses/info/GPLv2.html and | |
21 * http://www.gnu.org/copyleft/gpl.html. In addition, as a special | |
22 * exception, Nokia gives you certain additional rights. These rights | |
23 * are described in the Nokia Qt GPL Exception version 1.2, included in | |
24 * the file GPL_EXCEPTION.txt in this package. | |
25 * | |
26 * Qt for Windows(R) Licensees | |
27 * As a special exception, Nokia, as the sole copyright holder for Qt | |
28 * Designer, grants users of the Qt/Eclipse Integration plug-in the | |
29 * right for the Qt/Eclipse Integration to link to functionality | |
30 * provided by Qt Designer and its related libraries. | |
31 * | |
32 * | |
33 * If you are unsure which license is appropriate for your use, please | |
34 * contact the sales department at qt-sales@nokia.com. | |
35 | |
36 ** | |
37 ** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE | |
38 ** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
39 ** | |
40 ****************************************************************************/ | |
41 | |
42 #include "typesystem.h" | |
43 #include "generator.h" | |
44 | |
45 #include "customtypes.h" | |
46 | |
47 #include <reporthandler.h> | |
48 | |
49 #include <QtXml> | |
50 | |
51 QString strings_Object = QLatin1String("Object"); | |
52 QString strings_String = QLatin1String("string"); | |
53 QString strings_Thread = QLatin1String("Thread"); | |
54 QString strings_char = QLatin1String("char"); | |
55 QString strings_java_lang = QLatin1String("java.lang"); | |
56 QString strings_jchar = QLatin1String("jchar"); | |
57 QString strings_jobject = QLatin1String("jobject"); | |
58 | |
59 static void addRemoveFunctionToTemplates(TypeDatabase *db); | |
60 | |
61 class StackElement | |
62 { | |
63 public: | |
64 enum ElementType { | |
65 None = 0x0, | |
66 | |
67 // Type tags (0x1, ... , 0xff) | |
68 ObjectTypeEntry = 0x1, | |
69 ValueTypeEntry = 0x2, | |
70 InterfaceTypeEntry = 0x3, | |
71 NamespaceTypeEntry = 0x4, | |
72 ComplexTypeEntryMask = 0xf, | |
73 | |
74 // Non-complex type tags (0x10, 0x20, ... , 0xf0) | |
75 PrimitiveTypeEntry = 0x10, | |
76 EnumTypeEntry = 0x20, | |
77 TypeEntryMask = 0xff, | |
78 | |
79 // Simple tags (0x100, 0x200, ... , 0xf00) | |
80 ExtraIncludes = 0x100, | |
81 Include = 0x200, | |
82 ModifyFunction = 0x300, | |
83 ModifyField = 0x400, | |
84 Root = 0x500, | |
85 CustomMetaConstructor = 0x600, | |
86 CustomMetaDestructor = 0x700, | |
87 ArgumentMap = 0x800, | |
88 SuppressedWarning = 0x900, | |
89 Rejection = 0xa00, | |
90 LoadTypesystem = 0xb00, | |
91 RejectEnumValue = 0xc00, | |
92 Template = 0xd00, | |
93 TemplateInstanceEnum = 0xe00, | |
94 Replace = 0xf00, | |
95 SimpleMask = 0xf00, | |
96 // qtd stuff | |
97 AddClass = 0x1100, | |
42 | 98 PackageDepend = 0x1200, |
304 | 99 PrivateCopyConstructor = 0x1300, |
1 | 100 |
101 // Code snip tags (0x1000, 0x2000, ... , 0xf000) | |
102 InjectCode = 0x1000, | |
103 InjectCodeInFunction = 0x2000, | |
104 CodeSnipMask = 0xf000, | |
105 | |
106 // Function modifier tags (0x010000, 0x020000, ... , 0xf00000) | |
107 Access = 0x010000, | |
108 Removal = 0x020000, | |
109 Rename = 0x040000, | |
110 ModifyArgument = 0x080000, | |
148
ae34188ddd84
private signals of QAbstractItemModel are now accessible
eldar
parents:
44
diff
changeset
|
111 PrivateSignal = 0x100000, |
1 | 112 FunctionModifiers = 0xff0000, |
113 StoreResult = 0x110000, | |
114 | |
115 // Argument modifier tags (0x01000000 ... 0xf0000000) | |
116 ConversionRule = 0x01000000, | |
117 ReplaceType = 0x02000000, | |
118 ReplaceDefaultExpression = 0x04000000, | |
119 RemoveArgument = 0x08000000, | |
120 DefineOwnership = 0x10000000, | |
121 RemoveDefaultExpression = 0x20000000, | |
122 NoNullPointers = 0x40000000, | |
123 ReferenceCount = 0x80000000, | |
124 ArgumentModifiers = 0xff000000 | |
125 | |
126 }; | |
127 | |
128 StackElement(StackElement *p) : entry(0), type(None), parent(p){ } | |
129 | |
130 TypeEntry *entry; | |
131 ElementType type; | |
132 StackElement *parent; | |
133 | |
134 union { | |
135 TemplateInstance *templateInstance; | |
136 TemplateEntry *templateEntry; | |
137 CustomFunction *customFunction; | |
138 } value; | |
139 }; | |
140 | |
141 class Handler : public QXmlDefaultHandler | |
142 { | |
143 public: | |
4 | 144 Handler(TypeDatabase *database, const QString &source_dir, bool generate) |
145 : m_database(database), m_generate(generate ? TypeEntry::GenerateAll : TypeEntry::GenerateForSubclass), m_source_dir(source_dir) | |
1 | 146 { |
147 m_current_enum = 0; | |
148 current = 0; | |
149 | |
150 tagNames["rejection"] = StackElement::Rejection; | |
151 tagNames["primitive-type"] = StackElement::PrimitiveTypeEntry; | |
152 tagNames["object-type"] = StackElement::ObjectTypeEntry; | |
153 tagNames["value-type"] = StackElement::ValueTypeEntry; | |
154 tagNames["interface-type"] = StackElement::InterfaceTypeEntry; | |
155 tagNames["namespace-type"] = StackElement::NamespaceTypeEntry; | |
156 tagNames["enum-type"] = StackElement::EnumTypeEntry; | |
157 tagNames["extra-includes"] = StackElement::ExtraIncludes; | |
158 tagNames["include"] = StackElement::Include; | |
159 tagNames["inject-code"] = StackElement::InjectCode; | |
160 tagNames["modify-function"] = StackElement::ModifyFunction; | |
161 tagNames["modify-field"] = StackElement::ModifyField; | |
162 tagNames["access"] = StackElement::Access; | |
163 tagNames["remove"] = StackElement::Removal; | |
164 tagNames["rename"] = StackElement::Rename; | |
165 tagNames["typesystem"] = StackElement::Root; | |
166 tagNames["custom-constructor"] = StackElement::CustomMetaConstructor; | |
304 | 167 tagNames["private-copy-constructor"] = StackElement::PrivateCopyConstructor; |
1 | 168 tagNames["custom-destructor"] = StackElement::CustomMetaDestructor; |
169 tagNames["argument-map"] = StackElement::ArgumentMap; | |
170 tagNames["suppress-warning"] = StackElement::SuppressedWarning; | |
171 tagNames["load-typesystem"] = StackElement::LoadTypesystem; | |
172 tagNames["define-ownership"] = StackElement::DefineOwnership; | |
173 tagNames["replace-default-expression"] = StackElement::ReplaceDefaultExpression; | |
174 tagNames["reject-enum-value"] = StackElement::RejectEnumValue; | |
175 tagNames["replace-type"] = StackElement::ReplaceType; | |
176 tagNames["conversion-rule"] = StackElement::ConversionRule; | |
177 tagNames["modify-argument"] = StackElement::ModifyArgument; | |
178 tagNames["remove-argument"] = StackElement::RemoveArgument; | |
179 tagNames["remove-default-expression"] = StackElement::RemoveDefaultExpression; | |
180 tagNames["template"] = StackElement::Template; | |
181 tagNames["insert-template"] = StackElement::TemplateInstanceEnum; | |
182 tagNames["replace"] = StackElement::Replace; | |
183 tagNames["no-null-pointer"] = StackElement::NoNullPointers; | |
184 tagNames["reference-count"] = StackElement::ReferenceCount; | |
185 // qtd | |
186 tagNames["add-class"] = StackElement::AddClass; | |
187 tagNames["store-result"] = StackElement::StoreResult; | |
42 | 188 |
44 | 189 tagNames["depend"] = StackElement::PackageDepend; |
1 | 190 } |
191 | |
192 bool startElement(const QString &namespaceURI, const QString &localName, | |
193 const QString &qName, const QXmlAttributes &atts); | |
194 bool endElement(const QString &namespaceURI, const QString &localName, const QString &qName); | |
195 | |
196 QString errorString() const { return m_error; } | |
197 bool error(const QXmlParseException &exception); | |
198 bool fatalError(const QXmlParseException &exception); | |
199 bool warning(const QXmlParseException &exception); | |
200 | |
201 bool characters(const QString &ch); | |
202 | |
203 private: | |
204 void fetchAttributeValues(const QString &name, const QXmlAttributes &atts, | |
205 QHash<QString, QString> *acceptedAttributes); | |
206 | |
207 bool importFileElement(const QXmlAttributes &atts); | |
208 bool convertBoolean(const QString &, const QString &, bool); | |
209 | |
210 TypeDatabase *m_database; | |
211 StackElement* current; | |
212 QString m_defaultPackage; | |
213 QString m_defaultSuperclass; | |
214 QString m_error; | |
215 TypeEntry::CodeGeneration m_generate; | |
216 | |
217 EnumTypeEntry *m_current_enum; | |
218 | |
219 CodeSnipList m_code_snips; | |
220 FunctionModificationList m_function_mods; | |
221 FieldModificationList m_field_mods; | |
222 | |
223 QHash<QString, StackElement::ElementType> tagNames; | |
4 | 224 |
225 QString m_source_dir; | |
42 | 226 QStringList m_defaultDepends; |
1 | 227 }; |
228 | |
229 bool Handler::error(const QXmlParseException &e) | |
230 { | |
231 qWarning("Error: line=%d, column=%d, message=%s\n", | |
232 e.lineNumber(), e.columnNumber(), qPrintable(e.message())); | |
233 return false; | |
234 } | |
235 | |
236 bool Handler::fatalError(const QXmlParseException &e) | |
237 { | |
238 qWarning("Fatal error: line=%d, column=%d, message=%s\n", | |
239 e.lineNumber(), e.columnNumber(), qPrintable(e.message())); | |
240 | |
241 return false; | |
242 } | |
243 | |
244 bool Handler::warning(const QXmlParseException &e) | |
245 { | |
246 qWarning("Warning: line=%d, column=%d, message=%s\n", | |
247 e.lineNumber(), e.columnNumber(), qPrintable(e.message())); | |
248 | |
249 return false; | |
250 } | |
251 | |
252 void Handler::fetchAttributeValues(const QString &name, const QXmlAttributes &atts, | |
253 QHash<QString, QString> *acceptedAttributes) | |
254 { | |
255 Q_ASSERT(acceptedAttributes != 0); | |
256 | |
257 for (int i=0; i<atts.length(); ++i) { | |
258 QString key = atts.localName(i).toLower(); | |
259 QString val = atts.value(i); | |
260 | |
261 if (!acceptedAttributes->contains(key)) { | |
262 ReportHandler::warning(QString("Unknown attribute for '%1': '%2'").arg(name).arg(key)); | |
263 } else { | |
264 (*acceptedAttributes)[key] = val; | |
265 } | |
266 } | |
267 } | |
268 | |
269 bool Handler::endElement(const QString &, const QString &localName, const QString &) | |
270 { | |
271 QString tagName = localName.toLower(); | |
272 if(tagName == "import-file") | |
273 return true; | |
274 | |
275 if (!current) | |
276 return true; | |
277 | |
278 switch (current->type) { | |
279 case StackElement::ObjectTypeEntry: | |
280 case StackElement::ValueTypeEntry: | |
281 case StackElement::InterfaceTypeEntry: | |
282 case StackElement::NamespaceTypeEntry: | |
283 { | |
284 ComplexTypeEntry *centry = static_cast<ComplexTypeEntry *>(current->entry); | |
285 centry->setFunctionModifications(m_function_mods); | |
286 centry->setFieldModifications(m_field_mods); | |
287 centry->setCodeSnips(m_code_snips); | |
288 | |
289 if (centry->designatedInterface()) { | |
290 centry->designatedInterface()->setCodeSnips(m_code_snips); | |
291 centry->designatedInterface()->setFunctionModifications(m_function_mods); | |
292 } | |
293 m_code_snips = CodeSnipList(); | |
294 m_function_mods = FunctionModificationList(); | |
295 m_field_mods = FieldModificationList(); | |
296 } | |
297 break; | |
298 case StackElement::CustomMetaConstructor: | |
299 { | |
300 current->entry->setCustomConstructor(*current->value.customFunction); | |
301 delete current->value.customFunction; | |
302 } | |
303 break; | |
304 | 304 case StackElement::PrivateCopyConstructor: |
305 { | |
306 current->entry->setHasPrivateCopyConstructor(true); | |
307 } | |
308 break; | |
1 | 309 case StackElement::CustomMetaDestructor: |
310 { | |
311 current->entry->setCustomDestructor(*current->value.customFunction); | |
312 delete current->value.customFunction; | |
313 } | |
314 break; | |
315 case StackElement::EnumTypeEntry: | |
316 m_current_enum = 0; | |
317 break; | |
318 case StackElement::Template: | |
319 m_database->addTemplate(current->value.templateEntry); | |
320 break; | |
321 case StackElement::TemplateInstanceEnum: | |
322 if(current->parent->type == StackElement::InjectCode){ | |
323 m_code_snips.last().addTemplateInstance(current->value.templateInstance); | |
324 }else if(current->parent->type == StackElement::Template){ | |
325 current->parent->value.templateEntry->addTemplateInstance(current->value.templateInstance); | |
326 }else if(current->parent->type == StackElement::CustomMetaConstructor || current->parent->type == StackElement::CustomMetaConstructor){ | |
327 current->parent->value.customFunction->addTemplateInstance(current->value.templateInstance); | |
328 }else if(current->parent->type == StackElement::ConversionRule){ | |
329 m_function_mods.last().argument_mods.last().conversion_rules.last().addTemplateInstance(current->value.templateInstance); | |
330 }else if(current->parent->type == StackElement::InjectCodeInFunction){ | |
331 m_function_mods.last().snips.last().addTemplateInstance(current->value.templateInstance); | |
332 } | |
333 break; | |
334 default: | |
335 break; | |
336 } | |
337 | |
338 StackElement *child = current; | |
339 current=current->parent; | |
340 delete(child); | |
341 | |
342 return true; | |
343 } | |
344 | |
345 bool Handler::characters(const QString &ch) | |
346 { | |
347 if(current->type == StackElement::Template){ | |
348 current->value.templateEntry->addCode(ch); | |
349 return true; | |
350 } | |
351 | |
352 if (current->type == StackElement::CustomMetaConstructor || current->type == StackElement::CustomMetaDestructor){ | |
353 current->value.customFunction->addCode(ch); | |
354 return true; | |
355 } | |
356 | |
357 if (current->type == StackElement::ConversionRule){ | |
358 m_function_mods.last().argument_mods.last().conversion_rules.last().addCode(ch); | |
359 return true; | |
360 } | |
361 | |
362 if (current->parent){ | |
363 if ((current->type & StackElement::CodeSnipMask) != 0) { | |
364 switch (current->parent->type) { | |
365 case StackElement::Root: | |
366 ((TypeSystemTypeEntry *) current->parent->entry)->snips.last().addCode(ch); | |
367 break; | |
368 case StackElement::ModifyFunction: | |
369 m_function_mods.last().snips.last().addCode(ch); | |
370 break; | |
371 case StackElement::NamespaceTypeEntry: | |
372 case StackElement::ObjectTypeEntry: | |
373 case StackElement::ValueTypeEntry: | |
374 case StackElement::InterfaceTypeEntry: | |
375 m_code_snips.last().addCode(ch); | |
376 break; | |
377 default: | |
378 Q_ASSERT(false); | |
379 }; | |
380 return true; | |
381 } | |
382 } | |
383 | |
384 return true; | |
385 } | |
386 | |
387 bool Handler::importFileElement(const QXmlAttributes &atts) | |
388 { | |
389 QString fileName = atts.value("name"); | |
390 if(fileName.isEmpty()){ | |
391 m_error = "Required attribute 'name' missing for include-file tag."; | |
392 return false; | |
393 } | |
394 | |
395 QFile file(fileName); | |
396 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | |
397 file.setFileName(":/trolltech/generator/" + fileName); | |
398 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { | |
399 m_error = QString("Could not open file: '%1'").arg(fileName); | |
400 return false; | |
401 } | |
402 } | |
403 | |
404 QString quoteFrom = atts.value("quote-after-line"); | |
405 bool foundFromOk = quoteFrom.isEmpty(); | |
406 bool from = quoteFrom.isEmpty(); | |
407 | |
408 QString quoteTo = atts.value("quote-before-line"); | |
409 bool foundToOk = quoteTo.isEmpty(); | |
410 bool to = true; | |
411 | |
412 QTextStream in(&file); | |
413 while (!in.atEnd()) { | |
414 QString line = in.readLine(); | |
415 if(from && to && line.contains(quoteTo)) { | |
416 to = false; | |
417 foundToOk = true; | |
418 break; | |
419 } | |
420 if(from && to) | |
421 characters(line + "\n"); | |
422 if(!from && line.contains(quoteFrom)) { | |
423 from = true; | |
424 foundFromOk = true; | |
425 } | |
426 } | |
427 if(!foundFromOk || !foundToOk){ | |
428 QString fromError = QString("Could not find quote-after-line='%1' in file '%2'.").arg(quoteFrom).arg(fileName); | |
429 QString toError = QString("Could not find quote-before-line='%1' in file '%2'.").arg(quoteTo).arg(fileName); | |
430 | |
431 if(!foundToOk) | |
432 m_error = toError; | |
433 if(!foundFromOk) | |
434 m_error = fromError; | |
435 if(!foundFromOk && !foundToOk) | |
436 m_error = fromError + " " + toError; | |
437 return false; | |
438 } | |
439 | |
440 return true; | |
441 } | |
442 | |
443 bool Handler::convertBoolean(const QString &_value, const QString &attributeName, bool defaultValue) | |
444 { | |
445 QString value = _value.toLower(); | |
446 if (value == "true" || value == "yes") { | |
447 return true; | |
448 } else if (value == "false" || value == "no") { | |
449 return false; | |
450 } else { | |
451 QString warn = QString("Boolean value '%1' not supported in attribute '%2'. Use 'yes' or 'no'. Defaulting to '%3'.") | |
452 .arg(value).arg(attributeName).arg(defaultValue ? "yes" : "no"); | |
453 | |
454 ReportHandler::warning(warn); | |
455 return defaultValue; | |
456 } | |
457 } | |
458 | |
459 bool Handler::startElement(const QString &, const QString &n, | |
460 const QString &, const QXmlAttributes &atts) | |
461 { | |
462 QString tagName = n.toLower(); | |
463 if(tagName == "import-file"){ | |
464 return importFileElement(atts); | |
465 } | |
466 | |
467 StackElement *element = new StackElement(current); | |
468 | |
469 if (!tagNames.contains(tagName)) { | |
470 m_error = QString("Unknown tag name: '%1'").arg(tagName); | |
471 return false; | |
472 } | |
473 | |
474 element->type = tagNames[tagName]; | |
475 if (element->type & StackElement::TypeEntryMask) { | |
476 if (current->type != StackElement::Root) { | |
477 m_error = "Nested types not supported"; | |
478 return false; | |
479 } | |
480 | |
481 QHash<QString, QString> attributes; | |
482 attributes["name"] = QString(); | |
483 | |
484 switch (element->type) { | |
485 case StackElement::PrimitiveTypeEntry: | |
486 attributes["java-name"] = QString(); | |
487 attributes["jni-name"] = QString(); | |
488 attributes["preferred-conversion"] = "yes"; | |
489 attributes["preferred-java-type"] = "yes"; | |
490 break; | |
491 case StackElement::EnumTypeEntry: | |
492 attributes["flags"] = "no"; | |
493 attributes["upper-bound"] = QString(); | |
494 attributes["lower-bound"] = QString(); | |
495 attributes["force-integer"] = "no"; | |
496 attributes["extensible"] = "no"; | |
497 | |
498 break; | |
499 | |
500 case StackElement::ObjectTypeEntry: | |
501 case StackElement::ValueTypeEntry: | |
502 attributes["force-abstract"] = QString("no"); | |
503 attributes["deprecated"] = QString("no"); | |
504 attributes["wrap"] = QString(); | |
505 // fall throooough | |
506 case StackElement::InterfaceTypeEntry: | |
507 attributes["default-superclass"] = m_defaultSuperclass; | |
508 attributes["polymorphic-id-expression"] = QString(); | |
509 attributes["delete-in-main-thread"] = QString("no"); | |
510 // fall through | |
511 case StackElement::NamespaceTypeEntry: | |
512 attributes["java-name"] = QString(); | |
513 attributes["package"] = m_defaultPackage; | |
514 attributes["expense-cost"] = "1"; | |
515 attributes["expense-limit"] = "none"; | |
516 attributes["polymorphic-base"] = QString("no"); | |
517 attributes["generate"] = QString("yes"); | |
518 attributes["target-type"] = QString(); | |
519 attributes["generic-class"] = QString("no"); | |
520 break; | |
521 default: | |
522 ; // nada | |
523 }; | |
524 | |
525 fetchAttributeValues(tagName, atts, &attributes); | |
526 | |
527 QString name = attributes["name"]; | |
528 | |
529 // We need to be able to have duplicate primitive type entries, or it's not possible to | |
530 // cover all primitive java types (which we need to do in order to support fake | |
531 // meta objects) | |
532 if (element->type != StackElement::PrimitiveTypeEntry) { | |
533 TypeEntry *tmp = m_database->findType(name); | |
534 if (tmp != 0) { | |
535 ReportHandler::warning(QString("Duplicate type entry: '%1'").arg(name)); | |
536 } | |
537 } | |
538 | |
539 if (name.isEmpty()) { | |
540 m_error = "no 'name' attribute specified"; | |
541 return false; | |
542 } | |
543 switch (element->type) { | |
544 case StackElement::PrimitiveTypeEntry: | |
545 { | |
546 QString java_name = attributes["java-name"]; | |
547 QString jni_name = attributes["jni-name"]; | |
548 QString preferred_conversion = attributes["preferred-conversion"].toLower(); | |
549 QString preferred_java_type = attributes["preferred-java-type"].toLower(); | |
550 | |
551 if (java_name.isEmpty()) | |
552 java_name = name; | |
553 if (jni_name.isEmpty()) | |
554 jni_name = name; | |
555 | |
556 PrimitiveTypeEntry *type = new PrimitiveTypeEntry(name); | |
557 type->setCodeGeneration(m_generate); | |
558 type->setTargetLangName(java_name); | |
559 type->setJniName(jni_name); | |
560 | |
561 type->setPreferredConversion(convertBoolean(preferred_conversion, "preferred-conversion", true)); | |
562 type->setPreferredTargetLangType(convertBoolean(preferred_java_type, "preferred-java-type", true)); | |
563 | |
564 element->entry = type; | |
565 } | |
566 break; | |
567 case StackElement::EnumTypeEntry: { | |
568 QStringList names = name.split(QLatin1String("::")); | |
569 | |
570 if (names.size() == 1) { | |
571 m_current_enum = new EnumTypeEntry(QString(), name); | |
572 } | |
573 else | |
574 m_current_enum = | |
575 new EnumTypeEntry(QStringList(names.mid(0, names.size() - 1)).join("::"), | |
576 names.last()); | |
577 element->entry = m_current_enum; | |
578 m_current_enum->setCodeGeneration(m_generate); | |
579 m_current_enum->setTargetLangPackage(m_defaultPackage); | |
42 | 580 //m_current_enum->setDepends(m_defaultDepends); // For enums its not needed? |
1 | 581 m_current_enum->setUpperBound(attributes["upper-bound"]); |
582 m_current_enum->setLowerBound(attributes["lower-bound"]); | |
583 m_current_enum->setForceInteger(convertBoolean(attributes["force-integer"], "force-integer", false)); | |
584 m_current_enum->setExtensible(convertBoolean(attributes["extensible"], "extensible", false)); | |
585 | |
586 // put in the flags parallel... | |
587 if (!attributes["flags"].isEmpty() && attributes["flags"].toLower() != "no") { | |
588 FlagsTypeEntry *ftype = new FlagsTypeEntry("QFlags<" + name + ">"); | |
589 ftype->setOriginator(m_current_enum); | |
590 ftype->setOriginalName(attributes["flags"]); | |
591 ftype->setCodeGeneration(m_generate); | |
592 QString n = ftype->originalName(); | |
593 | |
594 QStringList lst = n.split("::"); | |
595 if (QStringList(lst.mid(0, lst.size() - 1)).join("::") != m_current_enum->javaQualifier()) { | |
596 ReportHandler::warning(QString("enum %1 and flags %2 differ in qualifiers") | |
597 .arg(m_current_enum->javaQualifier()) | |
598 .arg(lst.at(0))); | |
599 } | |
600 | |
601 ftype->setFlagsName(lst.last()); | |
602 m_current_enum->setFlags(ftype); | |
603 | |
604 m_database->addFlagsType(ftype); | |
605 m_database->addType(ftype); | |
606 } | |
607 } | |
608 break; | |
609 | |
610 case StackElement::InterfaceTypeEntry: | |
611 { | |
612 ObjectTypeEntry *otype = new ObjectTypeEntry(name); | |
613 QString javaName = attributes["java-name"]; | |
614 if (javaName.isEmpty()) | |
615 javaName = name; | |
616 InterfaceTypeEntry *itype = | |
617 new InterfaceTypeEntry(InterfaceTypeEntry::interfaceName(javaName)); | |
618 | |
619 if (!convertBoolean(attributes["generate"], "generate", true)) | |
620 itype->setCodeGeneration(TypeEntry::GenerateForSubclass); | |
621 else | |
622 itype->setCodeGeneration(m_generate); | |
623 otype->setDesignatedInterface(itype); | |
624 itype->setOrigin(otype); | |
625 element->entry = otype; | |
626 } | |
627 // fall through | |
628 case StackElement::NamespaceTypeEntry: | |
629 if (element->entry == 0) { | |
630 element->entry = new NamespaceTypeEntry(name); | |
631 } | |
632 // fall through | |
633 case StackElement::ObjectTypeEntry: | |
634 if (element->entry == 0) { | |
635 element->entry = new ObjectTypeEntry(name); | |
636 } | |
637 // fall through | |
638 case StackElement::ValueTypeEntry: | |
639 { | |
640 if (element->entry == 0) { | |
641 if(name == "QVariant") | |
642 element->entry = new VariantTypeEntry(name); | |
643 else | |
644 element->entry = new ValueTypeEntry(name); | |
645 } | |
646 | |
647 ComplexTypeEntry *ctype = static_cast<ComplexTypeEntry *>(element->entry); | |
648 ctype->setTargetLangPackage(attributes["package"]); | |
42 | 649 //ctype->setDepends(m_defaultDepends); |
1 | 650 ctype->setDefaultSuperclass(attributes["default-superclass"]); |
651 ctype->setGenericClass(convertBoolean(attributes["generic-class"], "generic-class", false)); | |
652 | |
653 // qtd | |
654 QString wrap = attributes["wrap"]; | |
655 ctype->setStructInD(wrap == "struct" ? true : false); | |
656 // | |
657 | |
658 if (!convertBoolean(attributes["generate"], "generate", true)) | |
659 element->entry->setCodeGeneration(TypeEntry::GenerateForSubclass); | |
660 else | |
661 element->entry->setCodeGeneration(m_generate); | |
662 | |
663 QString javaName = attributes["java-name"]; | |
664 if (!javaName.isEmpty()) | |
665 ctype->setTargetLangName(javaName); | |
666 | |
667 // The expense policy | |
668 QString limit = attributes["expense-limit"]; | |
669 if (!limit.isEmpty() && limit != "none") { | |
670 ExpensePolicy ep; | |
671 ep.limit = limit.toInt(); | |
672 ep.cost = attributes["expense-cost"]; | |
673 ctype->setExpensePolicy(ep); | |
674 } | |
675 | |
676 ctype->setIsPolymorphicBase(convertBoolean(attributes["polymorphic-base"], "polymorphic-base", false)); | |
677 ctype->setPolymorphicIdValue(attributes["polymorphic-id-expression"]); | |
678 | |
679 if (element->type == StackElement::ObjectTypeEntry || element->type == StackElement::ValueTypeEntry) { | |
680 if (convertBoolean(attributes["force-abstract"], "force-abstract", false)) | |
681 ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::ForceAbstract); | |
682 if (convertBoolean(attributes["deprecated"], "deprecated", false)) | |
683 ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::Deprecated); | |
684 } | |
685 | |
686 if (element->type == StackElement::InterfaceTypeEntry || | |
687 element->type == StackElement::ValueTypeEntry || | |
688 element->type == StackElement::ObjectTypeEntry) { | |
689 if (convertBoolean(attributes["delete-in-main-thread"], "delete-in-main-thread", false)) | |
690 ctype->setTypeFlags(ctype->typeFlags() | ComplexTypeEntry::DeleteInMainThread); | |
691 } | |
692 | |
693 QString targetType = attributes["target-type"]; | |
694 if (!targetType.isEmpty() && element->entry->isComplex()) | |
695 static_cast<ComplexTypeEntry *>(element->entry)->setTargetType(targetType); | |
696 | |
697 // ctype->setInclude(Include(Include::IncludePath, ctype->name())); | |
698 ctype = ctype->designatedInterface(); | |
699 if (ctype != 0) | |
42 | 700 { |
1 | 701 ctype->setTargetLangPackage(attributes["package"]); |
42 | 702 ctype->setDepends(m_defaultDepends); |
703 } | |
1 | 704 } |
705 break; | |
706 default: | |
707 Q_ASSERT(false); | |
708 }; | |
709 | |
710 if (element->entry) | |
711 m_database->addType(element->entry); | |
712 else | |
713 ReportHandler::warning(QString("Type: %1 was rejected by typesystem").arg(name)); | |
714 | |
715 } else if (element->type != StackElement::None) { | |
716 bool topLevel = element->type == StackElement::Root | |
717 || element->type == StackElement::SuppressedWarning | |
718 || element->type == StackElement::Rejection | |
719 || element->type == StackElement::LoadTypesystem | |
720 || element->type == StackElement::InjectCode | |
42 | 721 || element->type == StackElement::Template |
722 || element->type == StackElement::PackageDepend; | |
1 | 723 |
724 if (!topLevel && current->type == StackElement::Root) { | |
725 m_error = QString("Tag requires parent: '%1'").arg(tagName); | |
726 return false; | |
727 } | |
728 | |
729 StackElement topElement = current==0 ? StackElement(0) : *current; | |
730 element->entry = topElement.entry; | |
731 | |
732 QHash<QString, QString> attributes; | |
733 switch (element->type) { | |
734 case StackElement::Root: | |
735 attributes["package"] = QString(); | |
736 attributes["default-superclass"] = QString(); | |
737 break; | |
738 case StackElement::LoadTypesystem: | |
739 attributes["name"] = QString(); | |
740 attributes["generate"] = "yes"; | |
741 break; | |
742 case StackElement::NoNullPointers: | |
743 attributes["default-value"] = QString(); | |
744 break; | |
745 case StackElement::SuppressedWarning: | |
746 attributes["text"] = QString(); | |
747 break; | |
748 case StackElement::ReplaceDefaultExpression: | |
749 attributes["with"] = QString(); | |
750 break; | |
751 case StackElement::DefineOwnership: | |
752 attributes["class"] = "java"; | |
753 attributes["owner"] = ""; | |
754 break; | |
755 case StackElement::ModifyFunction: | |
756 attributes["signature"] = QString(); | |
757 attributes["access"] = QString(); | |
758 attributes["remove"] = QString(); | |
759 attributes["rename"] = QString(); | |
760 attributes["deprecated"] = QString("no"); | |
761 attributes["associated-to"] = QString(); | |
762 attributes["virtual-slot"] = QString("no"); | |
148
ae34188ddd84
private signals of QAbstractItemModel are now accessible
eldar
parents:
44
diff
changeset
|
763 attributes["allow-as-slot"] = QString("no"); |
ae34188ddd84
private signals of QAbstractItemModel are now accessible
eldar
parents:
44
diff
changeset
|
764 attributes["private-signal"] = QString("no"); |
1 | 765 break; |
766 case StackElement::ModifyArgument: | |
767 attributes["index"] = QString(); | |
768 attributes["replace-value"] = QString(); | |
769 attributes["invalidate-after-use"] = QString("no"); | |
770 break; | |
771 case StackElement::ModifyField: | |
772 attributes["name"] = QString(); | |
773 attributes["write"] = "true"; | |
774 attributes["read"] = "true"; | |
775 break; | |
776 case StackElement::Access: | |
777 attributes["modifier"] = QString(); | |
778 break; | |
779 case StackElement::Include: | |
780 attributes["file-name"] = QString(); | |
781 attributes["location"] = QString(); | |
361
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
782 attributes["protection"] = QString(); |
1 | 783 break; |
784 case StackElement::CustomMetaConstructor: | |
785 attributes["name"] = topElement.entry->name().toLower() + "_create"; | |
786 attributes["param-name"] = "copy"; | |
787 break; | |
788 case StackElement::CustomMetaDestructor: | |
789 attributes["name"] = topElement.entry->name().toLower() + "_delete"; | |
790 attributes["param-name"] = "copy"; | |
791 break; | |
792 case StackElement::ReplaceType: | |
793 attributes["modified-type"] = QString(); | |
794 break; | |
795 case StackElement::InjectCode: | |
796 attributes["class"] = "java"; | |
797 attributes["position"] = "beginning"; | |
798 break; | |
799 case StackElement::ConversionRule: | |
800 attributes["class"] = ""; | |
801 break; | |
802 case StackElement::RejectEnumValue: | |
803 attributes["name"] = ""; | |
804 break; | |
805 case StackElement::ArgumentMap: | |
806 attributes["index"] = "1"; | |
807 attributes["meta-name"] = QString(); | |
808 break; | |
809 case StackElement::Rename: | |
810 attributes["to"] = QString(); | |
811 break; | |
812 case StackElement::Rejection: | |
813 attributes["class"] = "*"; | |
814 attributes["function-name"] = "*"; | |
815 attributes["field-name"] = "*"; | |
816 attributes["enum-name"] = "*"; | |
817 break; | |
818 case StackElement::Removal: | |
819 attributes["class"] = "all"; | |
820 break; | |
821 case StackElement::Template: | |
822 attributes["name"] = QString(); | |
823 break; | |
824 case StackElement::TemplateInstanceEnum: | |
825 attributes["name"] = QString(); | |
826 break; | |
827 case StackElement::Replace: | |
828 attributes["from"] = QString(); | |
829 attributes["to"] = QString(); | |
830 break; | |
831 case StackElement::ReferenceCount: | |
832 attributes["action"] = QString(); | |
833 attributes["variable-name"] = QString(); | |
834 attributes["thread-safe"] = QString("no"); | |
835 attributes["declare-variable"] = QString(); | |
836 attributes["access"] = QString("private"); | |
837 attributes["conditional"] = QString(""); | |
838 break; | |
839 // qtd | |
840 case StackElement::AddClass: | |
841 attributes["name"] = QString(); | |
842 break; | |
42 | 843 case StackElement::PackageDepend: |
844 attributes["package"] = QString(); | |
845 break; | |
1 | 846 default: |
847 ; // nada | |
848 }; | |
849 | |
850 if (attributes.count() > 0) | |
851 fetchAttributeValues(tagName, atts, &attributes); | |
852 | |
853 switch (element->type) { | |
854 case StackElement::Root: | |
855 m_defaultPackage = attributes["package"]; | |
856 m_defaultSuperclass = attributes["default-superclass"]; | |
857 element->type = StackElement::Root; | |
858 element->entry = new TypeSystemTypeEntry(m_defaultPackage); | |
859 TypeDatabase::instance()->addType(element->entry); | |
860 break; | |
861 case StackElement::LoadTypesystem: | |
862 { | |
863 QString name = attributes["name"]; | |
864 if (name.isEmpty()) { | |
865 m_error = "No typesystem name specified"; | |
866 return false; | |
867 } | |
868 | |
4 | 869 if (!m_database->parseFile(name, m_source_dir, convertBoolean(attributes["generate"], "generate", true))) { |
1 | 870 m_error = QString("Failed to parse: '%1'").arg(name); |
871 return false; | |
872 } | |
873 } | |
874 break; | |
875 case StackElement::RejectEnumValue: { | |
876 if (!m_current_enum) { | |
877 m_error = "<reject-enum-value> node must be used inside a <enum-type> node"; | |
878 return false; | |
879 } | |
880 QString name = attributes["name"]; | |
881 | |
882 bool added = false; | |
883 if (!name.isEmpty()) { | |
884 added = true; | |
885 m_current_enum->addEnumValueRejection(name); | |
886 } | |
887 | |
888 } break; | |
889 case StackElement::ReplaceType: | |
890 { | |
891 if (topElement.type != StackElement::ModifyArgument) { | |
892 m_error = "Type replacement can only be specified for argument modifications"; | |
893 return false; | |
894 } | |
895 | |
896 if (attributes["modified-type"].isEmpty()) { | |
897 m_error = "Type replacement requires 'modified-type' attribute"; | |
898 return false; | |
899 } | |
900 | |
901 m_function_mods.last().argument_mods.last().modified_type = attributes["modified-type"]; | |
902 } | |
903 break; | |
904 case StackElement::ConversionRule: | |
905 { | |
906 if (topElement.type != StackElement::ModifyArgument) { | |
907 m_error = "Conversion rules can only be specified for argument modification"; | |
908 return false; | |
909 } | |
910 | |
911 static QHash<QString, TypeSystem::Language> languageNames; | |
912 if (languageNames.isEmpty()) { | |
913 languageNames["native"] = TypeSystem::NativeCode; | |
914 languageNames["shell"] = TypeSystem::ShellCode; | |
915 } | |
916 | |
917 CodeSnip snip; | |
918 QString languageAttribute = attributes["class"].toLower(); | |
919 TypeSystem::Language lang = languageNames.value(languageAttribute, TypeSystem::NoLanguage); | |
920 if (lang == TypeSystem::NoLanguage) { | |
921 m_error = QString("unsupported class attribute: '%1'").arg(languageAttribute); | |
922 return false; | |
923 } | |
924 | |
925 snip.language = lang; | |
926 m_function_mods.last().argument_mods.last().conversion_rules.append(snip); | |
927 } | |
928 | |
929 break; | |
930 case StackElement::StoreResult: | |
931 { | |
932 if (topElement.type != StackElement::ModifyFunction) { | |
933 m_error = QString::fromLatin1("result storage requires function" | |
934 " modification as parent, was %1") | |
935 .arg(topElement.type, 0, 16); | |
936 return false; | |
937 } | |
938 | |
939 m_function_mods.last().store_result = true; | |
940 } | |
941 break; | |
942 case StackElement::ModifyArgument: | |
943 { | |
944 if (topElement.type != StackElement::ModifyFunction) { | |
945 m_error = QString::fromLatin1("argument modification requires function" | |
946 " modification as parent, was %1") | |
947 .arg(topElement.type, 0, 16); | |
948 return false; | |
949 } | |
950 | |
951 QString index = attributes["index"]; | |
952 if (index == "return") | |
953 index = "0"; | |
954 else if (index == "this") | |
955 index = "-1"; | |
956 | |
957 bool ok = false; | |
958 int idx = index.toInt(&ok); | |
959 if (!ok) { | |
960 m_error = QString("Cannot convert '%1' to integer").arg(index); | |
961 return false; | |
962 } | |
963 | |
964 QString replace_value = attributes["replace-value"]; | |
965 | |
966 if (!replace_value.isEmpty() && idx != 0) { | |
967 m_error = QString("replace-value is only supported for return values (index=0)."); | |
968 return false; | |
969 } | |
970 | |
971 ArgumentModification argumentModification = ArgumentModification(idx); | |
972 argumentModification.replace_value = replace_value; | |
973 argumentModification.reset_after_use = convertBoolean(attributes["invalidate-after-use"], "invalidate-after-use", false); | |
974 m_function_mods.last().argument_mods.append(argumentModification); | |
975 } | |
976 break; | |
977 case StackElement::NoNullPointers: | |
978 { | |
979 if (topElement.type != StackElement::ModifyArgument) { | |
980 m_error = "no-null-pointer requires argument modification as parent"; | |
981 return false; | |
982 } | |
983 | |
984 m_function_mods.last().argument_mods.last().no_null_pointers = true; | |
985 if (m_function_mods.last().argument_mods.last().index == 0) { | |
986 m_function_mods.last().argument_mods.last().null_pointer_default_value = attributes["default-value"]; | |
987 } else if (!attributes["default-value"].isEmpty()) { | |
988 ReportHandler::warning("default values for null pointer guards are only effective for return values"); | |
989 } | |
990 } | |
991 break; | |
992 case StackElement::DefineOwnership: | |
993 { | |
994 if (topElement.type != StackElement::ModifyArgument) { | |
995 m_error = "define-ownership requires argument modification as parent"; | |
996 return false; | |
997 } | |
998 | |
999 static QHash<QString, TypeSystem::Language> languageNames; | |
1000 if (languageNames.isEmpty()) { | |
1001 languageNames["java"] = TypeSystem::TargetLangCode; | |
1002 languageNames["shell"] = TypeSystem::ShellCode; | |
1003 } | |
1004 | |
1005 QString classAttribute = attributes["class"].toLower(); | |
1006 TypeSystem::Language lang = languageNames.value(classAttribute, TypeSystem::NoLanguage); | |
1007 if (lang == TypeSystem::NoLanguage) { | |
1008 m_error = QString("unsupported class attribute: '%1'").arg(classAttribute); | |
1009 return false; | |
1010 } | |
1011 | |
1012 static QHash<QString, TypeSystem::Ownership> ownershipNames; | |
1013 if (ownershipNames.isEmpty()) { | |
1014 ownershipNames["java"] = TypeSystem::TargetLangOwnership; | |
1015 ownershipNames["c++"] = TypeSystem::CppOwnership; | |
1016 ownershipNames["default"] = TypeSystem::DefaultOwnership; | |
1017 } | |
1018 | |
1019 QString ownershipAttribute = attributes["owner"].toLower(); | |
1020 TypeSystem::Ownership owner = ownershipNames.value(ownershipAttribute, TypeSystem::InvalidOwnership); | |
1021 if (owner == TypeSystem::InvalidOwnership) { | |
1022 m_error = QString("unsupported owner attribute: '%1'").arg(ownershipAttribute); | |
1023 return false; | |
1024 } | |
1025 | |
1026 m_function_mods.last().argument_mods.last().ownerships[lang] = owner; | |
1027 } | |
1028 break; | |
1029 case StackElement::SuppressedWarning: | |
1030 if (attributes["text"].isEmpty()) | |
1031 ReportHandler::warning("Suppressed warning with no text specified"); | |
1032 else | |
1033 m_database->addSuppressedWarning(attributes["text"]); | |
1034 break; | |
1035 case StackElement::ArgumentMap: | |
1036 { | |
1037 if (!(topElement.type & StackElement::CodeSnipMask)) { | |
1038 m_error = "Argument maps requires code injection as parent"; | |
1039 return false; | |
1040 } | |
1041 | |
1042 bool ok; | |
1043 int pos = attributes["index"].toInt(&ok); | |
1044 if (!ok) { | |
1045 m_error = QString("Can't convert position '%1' to integer") | |
1046 .arg(attributes["position"]); | |
1047 return false; | |
1048 } | |
1049 | |
1050 if (pos <= 0) { | |
1051 m_error = QString("Argument position %1 must be a positive number").arg(pos); | |
1052 return false; | |
1053 } | |
1054 | |
1055 QString meta_name = attributes["meta-name"]; | |
1056 if (meta_name.isEmpty()) { | |
1057 ReportHandler::warning("Empty meta name in argument map"); | |
1058 } | |
1059 | |
1060 if (topElement.type == StackElement::InjectCodeInFunction) { | |
1061 m_function_mods.last().snips.last().argumentMap[pos] = meta_name; | |
1062 } else { | |
1063 ReportHandler::warning("Argument maps are only useful for injection of code " | |
1064 "into functions."); | |
1065 } | |
1066 } | |
1067 break; | |
1068 case StackElement::Removal: | |
1069 { | |
1070 if (topElement.type != StackElement::ModifyFunction) { | |
1071 m_error = "Function modification parent required"; | |
1072 return false; | |
1073 } | |
1074 | |
1075 static QHash<QString, TypeSystem::Language> languageNames; | |
1076 if (languageNames.isEmpty()) { | |
1077 languageNames["java"] = TypeSystem::TargetLangAndNativeCode; | |
1078 languageNames["all"] = TypeSystem::All; | |
1079 } | |
1080 | |
1081 QString languageAttribute = attributes["class"].toLower(); | |
1082 TypeSystem::Language lang = languageNames.value(languageAttribute, TypeSystem::NoLanguage); | |
1083 if (lang == TypeSystem::NoLanguage) { | |
1084 m_error = QString("unsupported class attribute: '%1'").arg(languageAttribute); | |
1085 return false; | |
1086 } | |
1087 | |
1088 m_function_mods.last().removal = lang; | |
1089 } | |
1090 break; | |
1091 case StackElement::Rename: | |
1092 case StackElement::Access: | |
1093 { | |
1094 if (topElement.type != StackElement::ModifyField | |
1095 && topElement.type != StackElement::ModifyFunction) { | |
1096 m_error = "Function or field modification parent required"; | |
1097 return false; | |
1098 } | |
1099 | |
1100 Modification *mod = 0; | |
1101 if (topElement.type == StackElement::ModifyFunction) | |
1102 mod = &m_function_mods.last(); | |
1103 else | |
1104 mod = &m_field_mods.last(); | |
1105 | |
1106 QString modifier; | |
1107 if (element->type == StackElement::Rename) { | |
1108 modifier = "rename"; | |
1109 QString renamed_to = attributes["to"]; | |
1110 if (renamed_to.isEmpty()) { | |
1111 m_error = "Rename modifier requires 'to' attribute"; | |
1112 return false; | |
1113 } | |
1114 | |
1115 if (topElement.type == StackElement::ModifyFunction) | |
1116 mod->setRenamedTo(renamed_to); | |
1117 else | |
1118 mod->setRenamedTo(renamed_to); | |
1119 } else { | |
1120 modifier = attributes["modifier"].toLower(); | |
1121 } | |
1122 | |
1123 if (modifier.isEmpty()) { | |
1124 m_error = "No access modification specified"; | |
1125 return false; | |
1126 } | |
1127 | |
1128 static QHash<QString, FunctionModification::Modifiers> modifierNames; | |
1129 if (modifierNames.isEmpty()) { | |
1130 modifierNames["private"] = Modification::Private; | |
1131 modifierNames["public"] = Modification::Public; | |
1132 modifierNames["protected"] = Modification::Protected; | |
1133 modifierNames["friendly"] = Modification::Friendly; | |
1134 modifierNames["rename"] = Modification::Rename; | |
1135 modifierNames["final"] = Modification::Final; | |
1136 modifierNames["non-final"] = Modification::NonFinal; | |
1137 } | |
1138 | |
1139 if (!modifierNames.contains(modifier)) { | |
1140 m_error = QString("Unknown access modifier: '%1'").arg(modifier); | |
1141 return false; | |
1142 } | |
1143 | |
1144 mod->modifiers |= modifierNames[modifier]; | |
1145 } | |
1146 break; | |
1147 case StackElement::RemoveArgument: | |
1148 if (topElement.type != StackElement::ModifyArgument) { | |
1149 m_error = "Removing argument requires argument modification as parent"; | |
1150 return false; | |
1151 } | |
1152 | |
1153 m_function_mods.last().argument_mods.last().removed = true; | |
1154 | |
1155 break; | |
1156 | |
1157 case StackElement::ModifyField: | |
1158 { | |
1159 QString name = attributes["name"]; | |
1160 if (name.isEmpty()) | |
1161 break; | |
1162 FieldModification fm; | |
1163 fm.name = name; | |
1164 fm.modifiers = 0; | |
1165 | |
1166 QString read = attributes["read"]; | |
1167 QString write = attributes["write"]; | |
1168 | |
1169 if (read == "true") fm.modifiers |= FieldModification::Readable; | |
1170 if (write == "true") fm.modifiers |= FieldModification::Writable; | |
1171 | |
1172 m_field_mods << fm; | |
1173 } | |
1174 break; | |
1175 case StackElement::AddClass: // qtd - fully :) | |
1176 { | |
1177 if (!(topElement.type & StackElement::ComplexTypeEntryMask)) { | |
1178 m_error = QString::fromLatin1("Add class to module requires complex type as parent" | |
1179 ", was=%1").arg(topElement.type, 0, 16); | |
1180 return false; | |
1181 } | |
1182 QString class_name = attributes["name"]; | |
1183 ComplexTypeEntry *ctype = static_cast<ComplexTypeEntry *>(topElement.entry); | |
1184 if(!class_name.isEmpty()) | |
1185 ctype->includedClasses << class_name; | |
1186 } | |
1187 break; | |
1188 case StackElement::ModifyFunction: | |
1189 { | |
1190 if (!(topElement.type & StackElement::ComplexTypeEntryMask)) { | |
1191 m_error = QString::fromLatin1("Modify function requires complex type as parent" | |
1192 ", was=%1").arg(topElement.type, 0, 16); | |
1193 return false; | |
1194 } | |
1195 QString signature = attributes["signature"]; | |
1196 | |
1197 signature = QMetaObject::normalizedSignature(signature.toLocal8Bit().constData()); | |
1198 if (signature.isEmpty()) { | |
1199 m_error = "No signature for modified function"; | |
1200 return false; | |
1201 } | |
1202 | |
1203 FunctionModification mod; | |
1204 mod.signature = signature; | |
1205 | |
1206 QString access = attributes["access"].toLower(); | |
1207 if (!access.isEmpty()) { | |
1208 if (access == QLatin1String("private")) | |
1209 mod.modifiers |= Modification::Private; | |
1210 else if (access == QLatin1String("protected")) | |
1211 mod.modifiers |= Modification::Protected; | |
1212 else if (access == QLatin1String("public")) | |
1213 mod.modifiers |= Modification::Public; | |
1214 else if (access == QLatin1String("final")) | |
1215 mod.modifiers |= Modification::Final; | |
1216 else if (access == QLatin1String("non-final")) | |
1217 mod.modifiers |= Modification::NonFinal; | |
1218 else { | |
1219 m_error = QString::fromLatin1("Bad access type '%1'").arg(access); | |
1220 return false; | |
1221 } | |
1222 } | |
1223 | |
1224 if (convertBoolean(attributes["deprecated"], "deprecated", false)) { | |
1225 mod.modifiers |= Modification::Deprecated; | |
1226 } | |
1227 | |
1228 QString remove = attributes["remove"].toLower(); | |
1229 if (!remove.isEmpty()) { | |
1230 if (remove == QLatin1String("all")) | |
1231 mod.removal = TypeSystem::All; | |
1232 else if (remove == QLatin1String("java")) | |
1233 mod.removal = TypeSystem::TargetLangAndNativeCode; | |
1234 else { | |
1235 m_error = QString::fromLatin1("Bad removal type '%1'").arg(remove); | |
1236 return false; | |
1237 } | |
1238 } | |
1239 | |
1240 QString rename = attributes["rename"]; | |
1241 if (!rename.isEmpty()) { | |
1242 mod.renamedToName = rename; | |
1243 mod.modifiers |= Modification::Rename; | |
1244 } | |
1245 | |
1246 QString association = attributes["associated-to"]; | |
1247 if (!association.isEmpty()) | |
1248 mod.association = association; | |
1249 | |
1250 mod.modifiers |= (convertBoolean(attributes["virtual-slot"], "virtual-slot", false) ? Modification::VirtualSlot : 0); | |
148
ae34188ddd84
private signals of QAbstractItemModel are now accessible
eldar
parents:
44
diff
changeset
|
1251 mod.modifiers |= (convertBoolean(attributes["allow-as-slot"], "allow-as-slot", false) ? Modification::AllowAsSlot : 0); |
ae34188ddd84
private signals of QAbstractItemModel are now accessible
eldar
parents:
44
diff
changeset
|
1252 mod.modifiers |= (convertBoolean(attributes["private-signal"], "private-signal", false) ? Modification::PrivateSignal : 0); |
1 | 1253 |
1254 m_function_mods << mod; | |
1255 } | |
1256 break; | |
1257 case StackElement::ReplaceDefaultExpression: | |
1258 if (!(topElement.type & StackElement::ModifyArgument)) { | |
1259 m_error = "Replace default expression only allowed as child of argument modification"; | |
1260 return false; | |
1261 } | |
1262 | |
1263 if (attributes["with"].isEmpty()) { | |
1264 m_error = "Default expression replaced with empty string. Use remove-default-expression instead."; | |
1265 return false; | |
1266 } | |
1267 | |
1268 m_function_mods.last().argument_mods.last().replaced_default_expression = attributes["with"]; | |
1269 break; | |
1270 case StackElement::RemoveDefaultExpression: | |
1271 m_function_mods.last().argument_mods.last().removed_default_expression = true; | |
1272 break; | |
1273 case StackElement::CustomMetaConstructor: | |
1274 case StackElement::CustomMetaDestructor: | |
1275 { | |
1276 CustomFunction *func = new CustomFunction(attributes["name"]); | |
1277 func->param_name = attributes["param-name"]; | |
1278 element->value.customFunction = func; | |
1279 } | |
1280 break; | |
1281 case StackElement::ReferenceCount: | |
1282 { | |
1283 if (topElement.type != StackElement::ModifyArgument) { | |
1284 m_error = "reference-count must be child of modify-argument"; | |
1285 return false; | |
1286 } | |
1287 | |
1288 ReferenceCount rc; | |
1289 rc.threadSafe = convertBoolean(attributes["thread-safe"], "thread-safe", false); | |
1290 | |
1291 static QHash<QString, ReferenceCount::Action> actions; | |
1292 if (actions.isEmpty()) { | |
1293 actions["add"] = ReferenceCount::Add; | |
1294 actions["add-all"] = ReferenceCount::AddAll; | |
1295 actions["remove"] = ReferenceCount::Remove; | |
1296 actions["set"] = ReferenceCount::Set; | |
1297 actions["ignore"] = ReferenceCount::Ignore; | |
1298 } | |
1299 rc.action = actions.value(attributes["action"].toLower(), ReferenceCount::Invalid); | |
1300 | |
1301 rc.variableName = attributes["variable-name"]; | |
1302 if (rc.action != ReferenceCount::Ignore && rc.variableName.isEmpty()) { | |
1303 m_error = "variable-name attribute must be specified"; | |
1304 return false; | |
1305 } | |
1306 | |
1307 rc.declareVariable = attributes["declare-variable"]; | |
1308 rc.conditional = attributes["conditional"]; | |
1309 | |
1310 static QHash<QString, int> accessRights; | |
1311 if (accessRights.isEmpty()) { | |
1312 accessRights["private"] = ReferenceCount::Private; | |
1313 accessRights["public"] = ReferenceCount::Public; | |
1314 accessRights["protected"] = ReferenceCount::Protected; | |
1315 accessRights["friendly"] = ReferenceCount::Friendly; | |
1316 } | |
1317 rc.access = accessRights.value(attributes["access"].toLower(), 0); | |
1318 if (rc.access == 0) { | |
1319 m_error = "unrecognized access value: " + attributes["access"]; | |
1320 return false; | |
1321 } | |
1322 | |
1323 if (rc.action == ReferenceCount::Invalid) { | |
1324 m_error = "unrecognized value for action attribute. supported actions:"; | |
1325 foreach (QString action, actions.keys()) | |
1326 m_error += " " + action; | |
1327 } | |
1328 | |
1329 m_function_mods.last().argument_mods.last().referenceCounts.append(rc); | |
1330 } | |
1331 break; | |
1332 case StackElement::InjectCode: | |
1333 { | |
1334 if (((topElement.type & StackElement::ComplexTypeEntryMask) == 0) | |
1335 && (topElement.type != StackElement::ModifyFunction) | |
1336 && (topElement.type != StackElement::Root)) { | |
1337 m_error = "wrong parent type for code injection"; | |
1338 return false; | |
1339 } | |
1340 | |
1341 static QHash<QString, TypeSystem::Language> languageNames; | |
1342 if (languageNames.isEmpty()) { | |
1343 languageNames["java"] = TypeSystem::TargetLangCode; | |
14 | 1344 languageNames["java-free"] = TypeSystem::TargetLangFreeCode; |
1 | 1345 languageNames["native"] = TypeSystem::NativeCode; |
1346 languageNames["shell"] = TypeSystem::ShellCode; | |
1347 languageNames["shell-declaration"] = TypeSystem::ShellDeclaration; | |
1348 languageNames["library-initializer"] = TypeSystem::PackageInitializer; | |
1349 languageNames["destructor-function"] = TypeSystem::DestructorFunction; | |
1350 languageNames["constructors"] = TypeSystem::Constructors; | |
1351 languageNames["interface"] = TypeSystem::Interface; | |
1352 } | |
1353 | |
1354 QString className = attributes["class"].toLower(); | |
1355 if (!languageNames.contains(className)) { | |
1356 m_error = QString("Invalid class specifier: '%1'").arg(className); | |
1357 return false; | |
1358 } | |
1359 | |
1360 | |
1361 static QHash<QString, CodeSnip::Position> positionNames; | |
1362 if (positionNames.isEmpty()) { | |
1363 positionNames["beginning"] = CodeSnip::Beginning; | |
1364 positionNames["end"] = CodeSnip::End; | |
1365 } | |
1366 | |
1367 QString position = attributes["position"].toLower(); | |
1368 if (!positionNames.contains(position)) { | |
1369 m_error = QString("Invalid position: '%1'").arg(position); | |
1370 return false; | |
1371 } | |
1372 | |
1373 CodeSnip snip; | |
1374 snip.language = languageNames[className]; | |
1375 snip.position = positionNames[position]; | |
1376 | |
1377 if (snip.language == TypeSystem::Interface && topElement.type != StackElement::InterfaceTypeEntry) { | |
1378 m_error = "Interface code injections must be direct child of an interface type entry"; | |
1379 return false; | |
1380 } | |
1381 | |
1382 if (topElement.type == StackElement::ModifyFunction) { | |
1383 FunctionModification mod = m_function_mods.last(); | |
1384 if (snip.language == TypeSystem::ShellDeclaration) { | |
1385 m_error = "no function implementation in shell declaration in which to inject code"; | |
1386 return false; | |
1387 } | |
1388 | |
1389 m_function_mods.last().snips << snip; | |
1390 element->type = StackElement::InjectCodeInFunction; | |
1391 } else if (topElement.type == StackElement::Root) { | |
1392 ((TypeSystemTypeEntry *) element->entry)->snips << snip; | |
1393 | |
1394 } else if (topElement.type != StackElement::Root) { | |
1395 m_code_snips << snip; | |
1396 } | |
1397 } | |
1398 break; | |
1399 case StackElement::Include: | |
1400 { | |
1401 QString location = attributes["location"].toLower(); | |
1402 | |
1403 static QHash<QString, Include::IncludeType> locationNames; | |
1404 if (locationNames.isEmpty()) { | |
1405 locationNames["global"] = Include::IncludePath; | |
1406 locationNames["local"] = Include::LocalPath; | |
1407 locationNames["java"] = Include::TargetLangImport; | |
1408 } | |
1409 | |
361
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1410 if (locationNames.isEmpty()) { |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1411 locationNames["global"] = Include::IncludePath; |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1412 locationNames["local"] = Include::LocalPath; |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1413 locationNames["java"] = Include::TargetLangImport; |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1414 } |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1415 |
1 | 1416 if (!locationNames.contains(location)) { |
1417 m_error = QString("Location not recognized: '%1'").arg(location); | |
1418 return false; | |
1419 } | |
1420 | |
1421 Include::IncludeType loc = locationNames[location]; | |
361
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1422 |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1423 QString protection = attributes["protection"]; |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1424 if (!protection.isEmpty()) { |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1425 if (loc != Include::TargetLangImport) { |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1426 m_error = QString("Protection attribute is allowed only if 'java' location is specified"); |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1427 return false; |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1428 } |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1429 |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1430 if (protection != "public" |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1431 || protection != "private" |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1432 || protection != "package") { |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1433 m_error = QString("Import protection is not recognized: '%1'").arg(protection); |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1434 } |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1435 } |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1436 |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1437 Include inc(loc, protection, attributes["file-name"]); |
1 | 1438 |
1439 ComplexTypeEntry *ctype = static_cast<ComplexTypeEntry *>(element->entry); | |
1440 if (topElement.type & StackElement::ComplexTypeEntryMask) { | |
1441 ctype->setInclude(inc); | |
1442 } else if (topElement.type == StackElement::ExtraIncludes) { | |
1443 ctype->addExtraInclude(inc); | |
1444 } else { | |
1445 m_error = "Only supported parents are complex types and extra-includes"; | |
1446 return false; | |
1447 } | |
1448 | |
1449 inc = ctype->include(); | |
1450 IncludeList lst = ctype->extraIncludes(); | |
1451 ctype = ctype->designatedInterface(); | |
1452 if (ctype != 0) { | |
1453 ctype->setExtraIncludes(lst); | |
1454 ctype->setInclude(inc); | |
1455 } | |
1456 } | |
1457 break; | |
1458 case StackElement::Rejection: | |
1459 { | |
1460 QString cls = attributes["class"]; | |
1461 QString function = attributes["function-name"]; | |
1462 QString field = attributes["field-name"]; | |
1463 QString enum_ = attributes["enum-name"]; | |
1464 if (cls == "*" && function == "*" && field == "*" && enum_ == "*") { | |
1465 m_error = "bad reject entry, neither 'class', 'function-name' nor " | |
1466 "'field' specified"; | |
1467 return false; | |
1468 } | |
1469 m_database->addRejection(cls, function, field, enum_); | |
1470 } | |
1471 break; | |
1472 case StackElement::Template: | |
1473 element->value.templateEntry = new TemplateEntry(attributes["name"]); | |
1474 break; | |
1475 case StackElement::TemplateInstanceEnum: | |
1476 if (!(topElement.type & StackElement::CodeSnipMask) && | |
1477 (topElement.type != StackElement::Template) && | |
1478 (topElement.type != StackElement::CustomMetaConstructor) && | |
1479 (topElement.type != StackElement::CustomMetaDestructor) && | |
1480 (topElement.type != StackElement::ConversionRule)) | |
1481 { | |
1482 m_error = "Can only insert templates into code snippets, templates, custom-constructors, custom-destructors or conversion-rule."; | |
1483 return false; | |
1484 } | |
1485 element->value.templateInstance = new TemplateInstance(attributes["name"]); | |
1486 break; | |
1487 case StackElement::Replace: | |
1488 if (topElement.type != StackElement::TemplateInstanceEnum) { | |
1489 m_error = "Can only insert replace rules into insert-template."; | |
1490 return false; | |
1491 } | |
1492 element->parent->value.templateInstance->addReplaceRule(attributes["from"],attributes["to"]); | |
1493 break; | |
42 | 1494 case StackElement::PackageDepend: |
1495 { | |
1496 QString package = attributes["package"]; | |
1497 if (package.isEmpty()) { | |
1498 m_error = "bad package depend entry"; | |
1499 return false; | |
1500 } | |
1501 m_defaultDepends << package; | |
1502 } | |
1503 break; | |
1 | 1504 default: |
1505 break; // nada | |
1506 }; | |
1507 } | |
1508 | |
1509 current = element; | |
1510 return true; | |
1511 } | |
1512 | |
1513 TypeDatabase *TypeDatabase::instance() | |
1514 { | |
1515 static TypeDatabase *db = new TypeDatabase(); | |
1516 return db; | |
1517 } | |
1518 | |
1519 TypeDatabase::TypeDatabase() : m_suppressWarnings(true), m_includeEclipseWarnings(false) | |
1520 { | |
1521 addType(new StringTypeEntry("QString")); | |
1522 | |
1523 StringTypeEntry *e = new StringTypeEntry("QLatin1String"); | |
1524 e->setPreferredConversion(false); | |
1525 addType(e); | |
1526 | |
1527 e = new StringTypeEntry("QStringRef"); | |
1528 e->setPreferredConversion(false); | |
1529 addType(e); | |
1530 | |
1531 e = new StringTypeEntry("QXmlStreamStringRef"); | |
1532 e->setPreferredConversion(false); | |
1533 addType(e); | |
1534 | |
1535 addType(new CharTypeEntry("QChar")); | |
1536 | |
1537 CharTypeEntry *c = new CharTypeEntry("QLatin1Char"); | |
1538 c->setPreferredConversion(false); | |
1539 addType(c); | |
1540 | |
1541 { | |
1542 VariantTypeEntry *qvariant = new VariantTypeEntry("QVariant"); | |
1543 qvariant->setCodeGeneration(TypeEntry::GenerateAll); | |
1544 addType(qvariant); | |
1545 } | |
1546 | |
1547 { | |
1548 JObjectWrapperTypeEntry *wrapper = new JObjectWrapperTypeEntry("JObjectWrapper"); | |
1549 wrapper->setCodeGeneration(TypeEntry::GenerateNothing); | |
1550 addType(wrapper); | |
1551 } | |
1552 | |
1553 addType(new ThreadTypeEntry()); | |
1554 addType(new VoidTypeEntry()); | |
1555 | |
1556 // Predefined containers... | |
1557 addType(new ContainerTypeEntry("QList", ContainerTypeEntry::ListContainer)); | |
1558 addType(new ContainerTypeEntry("QStringList", ContainerTypeEntry::StringListContainer)); | |
1559 addType(new ContainerTypeEntry("QLinkedList", ContainerTypeEntry::LinkedListContainer)); | |
1560 addType(new ContainerTypeEntry("QVector", ContainerTypeEntry::VectorContainer)); | |
1561 addType(new ContainerTypeEntry("QStack", ContainerTypeEntry::StackContainer)); | |
1562 addType(new ContainerTypeEntry("QSet", ContainerTypeEntry::SetContainer)); | |
1563 addType(new ContainerTypeEntry("QMap", ContainerTypeEntry::MapContainer)); | |
1564 addType(new ContainerTypeEntry("QHash", ContainerTypeEntry::HashContainer)); | |
1565 addType(new ContainerTypeEntry("QPair", ContainerTypeEntry::PairContainer)); | |
1566 addType(new ContainerTypeEntry("QQueue", ContainerTypeEntry::QueueContainer)); | |
1567 addType(new ContainerTypeEntry("QMultiMap", ContainerTypeEntry::MultiMapContainer)); | |
1568 | |
1569 // Custom types... | |
1570 // addType(new QModelIndexTypeEntry()); | |
1571 | |
1572 addRemoveFunctionToTemplates(this); | |
1573 } | |
1574 | |
4 | 1575 bool TypeDatabase::parseFile(const QString &filename, const QString &source_dir, bool generate) |
1 | 1576 { |
27
a9626891eca6
CMake: generator will work only for needed packages.
SokoL_SD
parents:
14
diff
changeset
|
1577 QString name(filename); |
a9626891eca6
CMake: generator will work only for needed packages.
SokoL_SD
parents:
14
diff
changeset
|
1578 QFileInfo info(name); |
a9626891eca6
CMake: generator will work only for needed packages.
SokoL_SD
parents:
14
diff
changeset
|
1579 if(!info.exists()) |
a9626891eca6
CMake: generator will work only for needed packages.
SokoL_SD
parents:
14
diff
changeset
|
1580 { |
a9626891eca6
CMake: generator will work only for needed packages.
SokoL_SD
parents:
14
diff
changeset
|
1581 Q_ASSERT(!source_dir.isEmpty()); |
4 | 1582 name = source_dir + "/" + filename; |
27
a9626891eca6
CMake: generator will work only for needed packages.
SokoL_SD
parents:
14
diff
changeset
|
1583 } |
4 | 1584 QFile file(name); |
1 | 1585 Q_ASSERT(file.exists()); |
1586 QXmlInputSource source(&file); | |
1587 | |
1588 int count = m_entries.size(); | |
1589 | |
1590 QXmlSimpleReader reader; | |
4 | 1591 Handler handler(this, source_dir, generate); |
1 | 1592 |
1593 reader.setContentHandler(&handler); | |
1594 reader.setErrorHandler(&handler); | |
1595 | |
1596 bool ok = reader.parse(&source, false); | |
1597 | |
1598 int newCount = m_entries.size(); | |
1599 | |
1600 ReportHandler::debugSparse(QString::fromLatin1("Parsed: '%1', %2 new entries") | |
1601 .arg(filename) | |
1602 .arg(newCount - count)); | |
1603 | |
1604 return ok; | |
1605 } | |
1606 | |
1607 QString PrimitiveTypeEntry::javaObjectName() const | |
1608 { | |
1609 static QHash<QString, QString> table; | |
1610 if (table.isEmpty()) { | |
1611 table["boolean"] = "Boolean"; | |
1612 table["byte"] = "Byte"; | |
1613 table["char"] = "Character"; | |
1614 table["short"] = "Short"; | |
1615 table["int"] = "Integer"; | |
1616 table["long"] = "Long"; | |
1617 table["float"] = "Float"; | |
1618 table["double"] = "Double"; | |
1619 } | |
1620 Q_ASSERT(table.contains(targetLangName())); | |
1621 return table[targetLangName()]; | |
1622 } | |
1623 | |
1624 ContainerTypeEntry *TypeDatabase::findContainerType(const QString &name) | |
1625 { | |
1626 QString template_name = name; | |
1627 | |
1628 int pos = name.indexOf('<'); | |
1629 if (pos > 0) | |
1630 template_name = name.left(pos); | |
1631 | |
1632 TypeEntry *type_entry = findType(template_name); | |
1633 if (type_entry && type_entry->isContainer()) | |
1634 return static_cast<ContainerTypeEntry *>(type_entry); | |
1635 return 0; | |
1636 } | |
1637 | |
1638 PrimitiveTypeEntry *TypeDatabase::findTargetLangPrimitiveType(const QString &java_name) | |
1639 { | |
1640 foreach (QList<TypeEntry *> entries, m_entries.values()) { | |
1641 foreach (TypeEntry *e, entries) { | |
1642 if (e && e->isPrimitive()) { | |
1643 PrimitiveTypeEntry *pe = static_cast<PrimitiveTypeEntry *>(e); | |
1644 if (pe->targetLangName() == java_name && pe->preferredConversion()) | |
1645 return pe; | |
1646 } | |
1647 } | |
1648 } | |
1649 | |
1650 return 0; | |
1651 } | |
1652 | |
1653 IncludeList TypeDatabase::extraIncludes(const QString &className) | |
1654 { | |
1655 ComplexTypeEntry *typeEntry = findComplexType(className); | |
1656 if (typeEntry != 0) | |
1657 return typeEntry->extraIncludes(); | |
1658 else | |
1659 return IncludeList(); | |
1660 } | |
1661 | |
1662 | |
1663 | |
1664 QString Include::toString() const | |
1665 { | |
1666 if (type == IncludePath) | |
1667 return "#include <" + name + '>'; | |
1668 else if (type == LocalPath) | |
1669 return "#include \"" + name + "\""; | |
361
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1670 else { |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1671 QString result; |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1672 if (!protection.isEmpty()) |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1673 result += protection + " "; |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1674 return result + "import " + name + ";"; |
beaf4a2974d7
Autogeneration of QMetaType. First attempts at fixing qRegisterMetaType etc
Max Samukha <maxter@maxter.com>
parents:
355
diff
changeset
|
1675 } |
1 | 1676 } |
1677 | |
1678 QString Modification::accessModifierString() const | |
1679 { | |
1680 if (isPrivate()) return "private"; | |
1681 if (isProtected()) return "protected"; | |
1682 if (isPublic()) return "public"; | |
1683 if (isFriendly()) return "friendly"; | |
1684 return QString(); | |
1685 } | |
1686 | |
1687 FunctionModificationList ComplexTypeEntry::functionModifications(const QString &signature) const | |
1688 { | |
1689 FunctionModificationList lst; | |
1690 for (int i=0; i<m_function_mods.count(); ++i) { | |
1691 FunctionModification mod = m_function_mods.at(i); | |
1692 if (mod.signature == signature) { | |
1693 lst << mod; | |
1694 } | |
1695 } | |
1696 | |
1697 return lst; | |
1698 } | |
1699 | |
1700 FieldModification ComplexTypeEntry::fieldModification(const QString &name) const | |
1701 { | |
1702 for (int i=0; i<m_field_mods.size(); ++i) | |
1703 if (m_field_mods.at(i).name == name) | |
1704 return m_field_mods.at(i); | |
1705 FieldModification mod; | |
1706 mod.name = name; | |
1707 mod.modifiers = FieldModification::Readable | FieldModification::Writable; | |
1708 return mod; | |
1709 } | |
1710 | |
1711 QString ContainerTypeEntry::javaPackage() const | |
1712 { | |
297 | 1713 return "qt.core"; |
1 | 1714 } |
1715 | |
1716 QString ContainerTypeEntry::targetLangName() const | |
1717 { | |
1718 | |
1719 switch (m_type) { | |
297 | 1720 case StringListContainer: return "QList"; |
1721 case ListContainer: return "QList"; | |
1722 case LinkedListContainer: return "QLinkedList"; | |
1723 case VectorContainer: return "QVector"; | |
1 | 1724 case StackContainer: return "Stack"; |
1725 case QueueContainer: return "Queue"; | |
1726 case SetContainer: return "Set"; | |
1727 case MapContainer: return "SortedMap"; | |
1728 case MultiMapContainer: return "SortedMap"; | |
1729 case HashContainer: return "HashMap"; | |
1730 // case MultiHashCollectio: return "MultiHash"; | |
1731 case PairContainer: return "QPair"; | |
1732 default: | |
1733 qWarning("bad type... %d", m_type); | |
1734 break; | |
1735 } | |
1736 return QString(); | |
1737 } | |
1738 | |
1739 QString ContainerTypeEntry::qualifiedCppName() const | |
1740 { | |
1741 if (m_type == StringListContainer) | |
1742 return "QStringList"; | |
1743 return ComplexTypeEntry::qualifiedCppName(); | |
1744 } | |
1745 | |
1746 QString EnumTypeEntry::javaQualifier() const | |
1747 { | |
1748 TypeEntry *te = TypeDatabase::instance()->findType(m_qualifier); | |
355
08c1ca7975ab
obviated redundant virtual dispatch callbacks
Max Samukha <maxter@spambox.com>
parents:
341
diff
changeset
|
1749 if (te != 0) |
1 | 1750 return te->targetLangName(); |
1751 else | |
1752 return m_qualifier; | |
1753 } | |
1754 | |
1755 QString EnumTypeEntry::jniName() const | |
1756 { | |
1757 return "jint"; | |
1758 } | |
1759 | |
1760 QString FlagsTypeEntry::jniName() const | |
1761 { | |
1762 return "jint"; | |
1763 } | |
1764 | |
1765 void EnumTypeEntry::addEnumValueRedirection(const QString &rejected, const QString &usedValue) | |
1766 { | |
1767 m_enum_redirections << EnumValueRedirection(rejected, usedValue); | |
1768 } | |
1769 | |
1770 QString EnumTypeEntry::enumValueRedirection(const QString &value) const | |
1771 { | |
1772 for (int i=0; i<m_enum_redirections.size(); ++i) | |
1773 if (m_enum_redirections.at(i).rejected == value) | |
1774 return m_enum_redirections.at(i).used; | |
1775 return QString(); | |
1776 } | |
1777 | |
1778 QString FlagsTypeEntry::qualifiedTargetLangName() const | |
1779 { | |
1780 return m_enum->javaQualifier() + "." + targetLangName(); | |
1781 } | |
1782 | |
1783 | |
1784 void TypeDatabase::addRejection(const QString &class_name, const QString &function_name, | |
1785 const QString &field_name, const QString &enum_name) | |
1786 { | |
1787 TypeRejection r; | |
1788 r.class_name = class_name; | |
1789 r.function_name = function_name; | |
1790 r.field_name = field_name; | |
1791 r.enum_name = enum_name; | |
1792 | |
1793 m_rejections << r; | |
1794 } | |
1795 | |
1796 bool TypeDatabase::isClassRejected(const QString &class_name) | |
1797 { | |
1798 if (!m_rebuild_classes.isEmpty()) | |
1799 return !m_rebuild_classes.contains(class_name); | |
1800 | |
1801 foreach (const TypeRejection &r, m_rejections) | |
1802 if (r.class_name == class_name && r.function_name == "*" && r.field_name == "*" && r.enum_name == "*") { | |
1803 return true; | |
1804 } | |
1805 return false; | |
1806 } | |
1807 | |
1808 bool TypeDatabase::isEnumRejected(const QString &class_name, const QString &enum_name) | |
1809 { | |
1810 foreach (const TypeRejection &r, m_rejections) { | |
1811 if (r.enum_name == enum_name | |
1812 && (r.class_name == class_name || r.class_name == "*")) { | |
1813 return true; | |
1814 } | |
1815 } | |
1816 | |
1817 return false; | |
1818 } | |
1819 | |
1820 bool TypeDatabase::isFunctionRejected(const QString &class_name, const QString &function_name) | |
1821 { | |
1822 foreach (const TypeRejection &r, m_rejections) | |
1823 if (r.function_name == function_name && | |
1824 (r.class_name == class_name || r.class_name == "*")) | |
1825 return true; | |
1826 return false; | |
1827 } | |
1828 | |
1829 | |
1830 bool TypeDatabase::isFieldRejected(const QString &class_name, const QString &field_name) | |
1831 { | |
1832 foreach (const TypeRejection &r, m_rejections) | |
1833 if (r.field_name == field_name && | |
1834 (r.class_name == class_name || r.class_name == "*")) | |
1835 return true; | |
1836 return false; | |
1837 } | |
1838 | |
1839 FlagsTypeEntry *TypeDatabase::findFlagsType(const QString &name) const | |
1840 { | |
1841 FlagsTypeEntry *fte = (FlagsTypeEntry *) findType(name); | |
1842 return fte ? fte : (FlagsTypeEntry *) m_flags_entries.value(name); | |
1843 } | |
1844 | |
1845 QString TypeDatabase::globalNamespaceClassName(const TypeEntry * /*entry*/) { | |
1846 return QLatin1String("Global"); | |
1847 } | |
1848 | |
1849 | |
1850 /*! | |
1851 * The Visual Studio 2002 compiler doesn't support these symbols, | |
1852 * which our typedefs unforntuatly expand to. | |
1853 */ | |
1854 QString fixCppTypeName(const QString &name) | |
1855 { | |
1856 if (name == "long long") return "qint64"; | |
1857 else if (name == "unsigned long long") return "quint64"; | |
1858 return name; | |
1859 } | |
1860 | |
1861 QString formattedCodeHelper(QTextStream &s, Indentor &indentor, QStringList &lines) { | |
1862 bool multilineComment = false; | |
1863 bool lastEmpty = true; | |
1864 QString lastLine; | |
1865 while (!lines.isEmpty()) { | |
1866 const QString line = lines.takeFirst().trimmed(); | |
1867 if (line.isEmpty()) { | |
1868 if (!lastEmpty) | |
1869 s << endl; | |
1870 lastEmpty = true; | |
1871 continue; | |
1872 } else { | |
1873 lastEmpty = false; | |
1874 } | |
1875 if (line.startsWith("/*")) | |
1876 multilineComment = true; | |
1877 | |
1878 if (multilineComment) { | |
1879 s << indentor; | |
1880 if (line.startsWith("*")) | |
1881 s << " "; | |
1882 s << line << endl; | |
1883 if (line.endsWith("*/")) | |
1884 multilineComment = false; | |
1885 } else if (line.startsWith("}")) { | |
1886 return line; | |
1887 } else if (line.endsWith("}")) { | |
1888 s << indentor << line << endl; | |
1889 return 0; | |
1890 } else if(line.endsWith("{")) { | |
1891 s << indentor << line << endl; | |
1892 QString tmp; | |
1893 { | |
1894 Indentation indent(indentor); | |
1895 tmp = formattedCodeHelper(s, indentor, lines); | |
1896 } | |
1897 if (!tmp.isNull()) { | |
1898 s << indentor << tmp << endl; | |
1899 } | |
1900 lastLine = tmp; | |
1901 continue; | |
1902 } else { | |
1903 s << indentor; | |
1904 if (!lastLine.isEmpty() && | |
1905 !lastLine.endsWith(";") && | |
1906 !line.startsWith("@") && | |
1907 !line.startsWith("//") && | |
1908 !lastLine.startsWith("//") && | |
1909 !lastLine.endsWith("}") && | |
1910 !line.startsWith("{")) | |
1911 s << " "; | |
1912 s << line << endl; | |
1913 } | |
1914 lastLine = line; | |
1915 } | |
1916 return 0; | |
1917 } | |
1918 | |
1919 | |
1920 QTextStream &CodeSnip::formattedCode(QTextStream &s, Indentor &indentor) const | |
1921 { | |
1922 QStringList lst(code().split("\n")); | |
1923 while (!lst.isEmpty()) { | |
1924 QString tmp = formattedCodeHelper(s, indentor, lst); | |
1925 if (!tmp.isNull()) { | |
1926 s << indentor << tmp << endl; | |
1927 } | |
1928 } | |
1929 s.flush(); | |
1930 return s; | |
1931 } | |
1932 | |
1933 QString TemplateInstance::expandCode() const{ | |
1934 TemplateEntry *templateEntry = TypeDatabase::instance()->findTemplate(m_name); | |
1935 if(templateEntry){ | |
1936 QString res = templateEntry->code(); | |
1937 foreach(QString key, replaceRules.keys()){ | |
1938 res.replace(key, replaceRules[key]); | |
1939 } | |
1940 return "// TEMPLATE - " + m_name + " - START" + res + "// TEMPLATE - " + m_name + " - END"; | |
1941 } | |
1942 else{ | |
1943 ReportHandler::warning("insert-template referring to non-existing template '" + m_name + "'"); | |
1944 } | |
1945 return QString(); | |
1946 } | |
1947 | |
1948 | |
1949 QString CodeSnipAbstract::code() const{ | |
1950 QString res; | |
1951 foreach(CodeSnipFragment *codeFrag, codeList){ | |
1952 res.append(codeFrag->code()); | |
1953 } | |
1954 return res; | |
1955 } | |
1956 | |
1957 QString CodeSnipFragment::code() const{ | |
1958 if(m_instance) | |
1959 return m_instance->expandCode(); | |
1960 else | |
1961 return m_code; | |
1962 } | |
1963 | |
1964 QString FunctionModification::toString() const | |
1965 { | |
1966 QString str = signature + QLatin1String("->"); | |
1967 if (modifiers & AccessModifierMask) { | |
1968 switch (modifiers & AccessModifierMask) { | |
1969 case Private: str += QLatin1String("private"); break; | |
1970 case Protected: str += QLatin1String("protected"); break; | |
1971 case Public: str += QLatin1String("public"); break; | |
1972 case Friendly: str += QLatin1String("friendly"); break; | |
1973 } | |
1974 } | |
1975 | |
1976 if (modifiers & Final) str += QLatin1String("final"); | |
1977 if (modifiers & NonFinal) str += QLatin1String("non-final"); | |
1978 | |
1979 if (modifiers & Readable) str += QLatin1String("readable"); | |
1980 if (modifiers & Writable) str += QLatin1String("writable"); | |
1981 | |
1982 if (modifiers & CodeInjection) { | |
1983 foreach (CodeSnip s, snips) { | |
1984 str += QLatin1String("\n//code injection:\n"); | |
1985 str += s.code(); | |
1986 } | |
1987 } | |
1988 | |
1989 if (modifiers & Rename) str += QLatin1String("renamed:") + renamedToName; | |
1990 | |
1991 if (modifiers & Deprecated) str += QLatin1String("deprecate"); | |
1992 | |
1993 if (modifiers & ReplaceExpression) str += QLatin1String("replace-expression"); | |
1994 | |
1995 return str; | |
1996 } | |
1997 | |
1998 static void removeFunction(ComplexTypeEntry *e, const char *signature) | |
1999 { | |
2000 FunctionModification mod; | |
2001 mod.signature = QMetaObject::normalizedSignature(signature); | |
2002 mod.removal = TypeSystem::All; | |
2003 | |
2004 e->addFunctionModification(mod); | |
2005 } | |
2006 | |
2007 | |
2008 | |
2009 | |
2010 static void injectCode(ComplexTypeEntry *e, | |
2011 const char *signature, | |
2012 const QByteArray &code, | |
2013 const ArgumentMap &args, | |
2014 TypeSystem::Language lang = TypeSystem::NativeCode) | |
2015 { | |
2016 CodeSnip snip; | |
2017 snip.language = lang; | |
2018 snip.position = CodeSnip::Beginning; | |
2019 snip.addCode(QString::fromLatin1(code)); | |
2020 snip.argumentMap = args; | |
2021 | |
2022 FunctionModification mod; | |
2023 mod.signature = QMetaObject::normalizedSignature(signature); | |
2024 mod.snips << snip; | |
2025 mod.modifiers = Modification::CodeInjection; | |
2026 e->addFunctionModification(mod); | |
2027 } | |
2028 | |
2029 | |
2030 static void addRemoveFunctionToTemplates(TypeDatabase *db) | |
2031 { | |
2032 ContainerTypeEntry *qvector = db->findContainerType(QLatin1String("QVector")); | |
2033 removeFunction(qvector, "constData() const"); | |
2034 removeFunction(qvector, "data() const"); | |
2035 removeFunction(qvector, "data()"); | |
2036 removeFunction(qvector, "first()"); | |
2037 removeFunction(qvector, "last()"); | |
2038 removeFunction(qvector, "operator[](int)"); | |
2039 removeFunction(qvector, "operator[](int) const"); | |
2040 removeFunction(qvector, "operator=(QVector<T>)"); | |
2041 | |
2042 ContainerTypeEntry *qlist = db->findContainerType(QLatin1String("QList")); | |
2043 removeFunction(qlist, "constData() const"); | |
2044 removeFunction(qlist, "data() const"); | |
2045 removeFunction(qlist, "data()"); | |
2046 removeFunction(qlist, "back()"); | |
2047 removeFunction(qlist, "front()"); | |
2048 removeFunction(qlist, "first()"); | |
2049 removeFunction(qlist, "last()"); | |
2050 removeFunction(qlist, "operator[](int)"); | |
2051 removeFunction(qlist, "operator[](int) const"); | |
2052 removeFunction(qlist, "operator=(QList<T>)"); | |
2053 | |
2054 ContainerTypeEntry *qqueue = db->findContainerType(QLatin1String("QQueue")); | |
2055 removeFunction(qqueue, "head() const"); | |
2056 | |
2057 | |
2058 ArgumentMap args1; | |
2059 args1[1] = QLatin1String("$1"); | |
2060 ArgumentMap args2 = args1; | |
2061 args2[2] = QLatin1String("$2"); | |
2062 | |
2063 QByteArray code = | |
2064 "\nif ($1 >= __qt_this->size() || $1 < 0) {" | |
2065 "\n __jni_env->ThrowNew(__jni_env->FindClass(\"java/lang/IndexOutOfBoundsException\")," | |
2066 "\n QString::fromLatin1(\"Accessing container of size %3 at %4\")" | |
2067 "\n .arg(__qt_this->size()).arg($1).toLatin1());" | |
2068 "\n return;" | |
2069 "\n}"; | |
2070 | |
2071 QByteArray code_with_return = QByteArray(code).replace("return;", "return 0;"); | |
2072 | |
2073 QByteArray code_index_length = | |
2074 "\nif ($1 < 0 || $2 < 0 || ($1 + $2) >= __qt_this->size()) {" | |
2075 "\n __jni_env->ThrowNew(__jni_env->FindClass(\"java/lang/IndexOutOfBoundsException\")," | |
2076 "\n QString::fromLatin1(\"Accessing container of size %3 from %4 to %5\")" | |
2077 "\n .arg(__qt_this->size()).arg($1).arg($1+$2).toLatin1());" | |
2078 "\n return;" | |
2079 "\n}"; | |
2080 | |
2081 QByteArray code_non_empty = | |
2082 "\nif (__qt_this->isEmpty()) {" | |
2083 "\n __jni_env->ThrowNew(__jni_env->FindClass(\"java/lang/IndexOutOfBoundsException\")," | |
2084 "\n QString::fromLatin1(\"Accessing empty container...\").toLatin1());" | |
2085 "\n return;" | |
2086 "\n}"; | |
2087 | |
2088 QByteArray code_two_indices = | |
2089 "\nif ($1 < 0 || $2 < 0 || $1 >= __qt_this->size() || $2 >= __qt_this->size()) {" | |
2090 "\n __jni_env->ThrowNew(__jni_env->FindClass(\"java/lang/IndexOutOfBoundsException\")," | |
2091 "\n QString::fromLatin1(\"Accessing container of size %3 from %4 to %5\")" | |
2092 "\n .arg(__qt_this->size()).arg($1).arg($1+$2).toLatin1());" | |
2093 "\n return;" | |
2094 "\n}"; | |
2095 /* qtd2 | |
2096 { // QVector safty... | |
2097 injectCode(qvector, "at(int) const", code_with_return, args1, TypeSystem::TargetLangCode); | |
2098 injectCode(qvector, "replace(int,T)", code, args1, TypeSystem::TargetLangCode); | |
2099 injectCode(qvector, "remove(int)", code, args1, TypeSystem::TargetLangCode); | |
2100 injectCode(qvector, "remove(int, int)", code_index_length, args2, TypeSystem::TargetLangCode); | |
2101 injectCode(qvector, "pop_back()", code_non_empty, ArgumentMap(), TypeSystem::TargetLangCode); | |
2102 injectCode(qvector, "pop_front()", code_non_empty, ArgumentMap(), TypeSystem::TargetLangCode); | |
2103 } | |
2104 | |
2105 { // QList safty... | |
2106 injectCode(qlist, "at(int) const", code_with_return, args1); | |
2107 injectCode(qlist, "replace(int, T)", code, args1); | |
2108 injectCode(qlist, "pop_back()", code_non_empty, ArgumentMap()); | |
2109 injectCode(qlist, "pop_front()", code_non_empty, ArgumentMap()); | |
2110 injectCode(qlist, "swap(int, int)", code_two_indices, args2); | |
2111 injectCode(qlist, "move(int, int)", code_two_indices, args2); | |
2112 injectCode(qlist, "removeAt(int)", code, args1); | |
2113 injectCode(qlist, "takeAt(int)", code_with_return, args1); | |
2114 } | |
2115 */ | |
2116 } |