comparison generator/metainfogenerator.cpp @ 1:e78566595089

initial import
author mandel
date Mon, 11 May 2009 16:01:50 +0000
parents
children 1349940724eb
comparison
equal deleted inserted replaced
0:36fb74dc547d 1:e78566595089
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 "metainfogenerator.h"
43 #include "reporthandler.h"
44 #include "cppimplgenerator.h"
45 #include "fileout.h"
46
47 #include <QDir>
48 #include <QMetaType>
49
50 MetaInfoGenerator::MetaInfoGenerator(PriGenerator *pri):
51 DGenerator(),
52 priGenerator(pri)
53
54 {
55 setFilenameStub("metainfo");
56 }
57
58 QString MetaInfoGenerator::subDirectoryForPackage(const QString &package, OutputDirectoryType type) const
59 {
60 switch (type) {
61 case CppDirectory:
62 return "cpp/" + QString(package).replace(".", "_") + "/";
63 case JavaDirectory:
64 return QString(package).replace(".", "/");
65 default:
66 return QString(); // kill nonsense warnings
67 }
68 }
69
70 QString MetaInfoGenerator::subDirectoryForClass(const AbstractMetaClass *cls, OutputDirectoryType type) const
71 {
72 Q_ASSERT(cls);
73 return subDirectoryForPackage(cls->package(), type);
74 }
75
76 void MetaInfoGenerator::generate()
77 {
78 buildSkipList();
79 writeCppFile();
80 writeHeaderFile();
81 writeLibraryInitializers();
82 }
83
84 bool MetaInfoGenerator::shouldGenerate(const TypeEntry *entry) const
85 {
86 return entry != 0 && !entry->isNamespace() && !entry->isEnum() && (entry->codeGeneration() & TypeEntry::GenerateCpp);
87 }
88
89 bool MetaInfoGenerator::shouldGenerate(const AbstractMetaClass *cls) const
90 {
91 return (!cls->isInterface() && cls->typeEntry()->isValue() && !cls->isNamespace()
92 && !cls->isAbstract() && (cls->typeEntry()->codeGeneration() & TypeEntry::GenerateCpp));
93 }
94
95 QString MetaInfoGenerator::fileNameForClass(const AbstractMetaClass *) const
96 {
97 return filenameStub() + ".cpp";
98 }
99
100 void MetaInfoGenerator::write(QTextStream &, const AbstractMetaClass *)
101 {
102 // not used
103 }
104
105 bool MetaInfoGenerator::generated(const AbstractMetaClass *cls) const
106 {
107 return generatedMetaInfo(cls->package());
108 }
109
110 bool MetaInfoGenerator::generatedMetaInfo(const QString &package) const
111 {
112 return (m_skip_list.value(package, 0x0) & GeneratedMetaInfo);
113 }
114
115 bool MetaInfoGenerator::generatedJavaClasses(const QString &package) const
116 {
117 return (m_skip_list.value(package, 0x0) & GeneratedJavaClasses);
118 }
119
120 static void metainfo_write_name_list(QTextStream &s, const char *var_name, const QList<QString> &strs,
121 int offset, int skip)
122 {
123 s << "static const char *" << var_name << "[] = {" << endl;
124 for (int i=offset; i<strs.size(); i += skip) {
125 s << " \"" << strs.at(i).toLatin1() << "\"";
126 if (i < strs.size() - 1)
127 s << ",";
128 s << endl;
129 }
130 s << "};" << endl << endl;
131 }
132
133 void MetaInfoGenerator::writeEnums(QTextStream &s, const QString &package)
134 {
135 TypeEntryHash entries = TypeDatabase::instance()->allEntries();
136 TypeEntryHash::iterator it;
137
138 QList<QString> strs;
139 for (it=entries.begin(); it!=entries.end(); ++it) {
140 QList<TypeEntry *> entries = it.value();
141 foreach (TypeEntry *entry, entries) {
142 if ((entry->isFlags() || entry->isEnum()) && entry->javaPackage() == package) {
143 EnumTypeEntry *eentry = entry->isEnum() ? static_cast<EnumTypeEntry *>(entry) : static_cast<FlagsTypeEntry *>(entry)->originator();
144
145 // The Qt flags names should map to the enum names, this is
146 // required for the designer plugin to find the enum type of
147 // a flags type since this functionality is not available in
148 // Qt. This may be a little bit inconsistent, but it saves
149 // us making yet another hash table for lookups. If it causes
150 // problems, make a new one for this particular purpose.
151 strs.append((eentry->javaPackage().isEmpty() ? QString() : eentry->javaPackage().replace('.', '/') + "/")
152 + eentry->javaQualifier() + "$" + eentry->targetLangName());
153 strs.append(entry->isFlags() ? static_cast<FlagsTypeEntry *>(entry)->originalName() : entry->qualifiedCppName());
154 }
155 }
156 }
157
158 Q_ASSERT(strs.size() % 2 == 0);
159
160 s << "static int enum_count = " << (strs.size() / 2) << ";" << endl;
161 if (strs.size() > 0) {
162 metainfo_write_name_list(s, "enumJavaNames", strs, 0, 2);
163 metainfo_write_name_list(s, "enumCppNames", strs, 1, 2);
164 } else {
165 s << "static const char **enumCppNames = 0;" << endl
166 << "static const char **enumJavaNames = 0;" << endl;
167 }
168 }
169
170 void MetaInfoGenerator::writeSignalsAndSlots(QTextStream &s, const QString &package)
171 {
172 AbstractMetaClassList classes = this->classes();
173
174 QList<QString> strs;
175 foreach (AbstractMetaClass *cls, classes) {
176 if (cls->package() == package) {
177 AbstractMetaFunctionList functions = cls->functions();
178 foreach (AbstractMetaFunction *f, functions) {
179 if (f->implementingClass() == cls && (f->isSignal() || f->isSlot())) {
180
181 AbstractMetaArgumentList arguments = f->arguments();
182 int numOverloads = arguments.size();
183 for (int i=arguments.size()-1; i>=0; --i) {
184 if (arguments.at(i)->defaultValueExpression().isEmpty()) {
185 numOverloads = arguments.size() - i - 1;
186 break;
187 }
188 }
189
190 for (int i=0; i<=numOverloads; ++i) {
191 Option option = Option(SkipAttributes | SkipReturnType | SkipName);
192 QString qtName;
193 {
194
195 QTextStream qtNameStream(&qtName);
196 CppGenerator::writeFunctionSignature(qtNameStream, f, 0, QString(),
197 Option(option | OriginalName | NormalizeAndFixTypeSignature | OriginalTypeDescription),
198 QString(), QStringList(), arguments.size() - i);
199 }
200 qtName = f->implementingClass()->qualifiedCppName() + "::" + qtName;
201 qtName = QMetaObject::normalizedSignature(qtName.toLatin1().constData());
202
203 QString javaFunctionName = functionSignature(f, 0, 0, option, arguments.size() - (f->isSignal() ? 0 : i));
204 QString javaObjectName = f->isSignal()
205 ? f->name()
206 : javaFunctionName;
207
208 javaFunctionName = f->implementingClass()->fullName() + "." + javaFunctionName;
209 javaObjectName = f->implementingClass()->fullName() + "." + javaObjectName;
210
211 QString javaSignature = "(";
212 for (int j=0; j < (arguments.size() - (f->isSignal() ? 0 : i)); ++j) {
213 AbstractMetaArgument *arg = arguments.at(j);
214 javaSignature += jni_signature(arg->type(), SlashesAndStuff);
215 }
216 javaSignature += ")" + jni_signature(f->type(), SlashesAndStuff);
217
218 strs.append(qtName);
219 strs.append(javaFunctionName);
220 strs.append(javaObjectName);
221 strs.append(javaSignature);
222 }
223 }
224 }
225 }
226 }
227
228 Q_ASSERT(strs.size() % 4 == 0);
229
230 s << "static int sns_count = " << (strs.size() / 4) << ";" << endl;
231 if (strs.size() > 0) {
232 metainfo_write_name_list(s, "qtNames", strs, 0, 4);
233 metainfo_write_name_list(s, "javaFunctionNames", strs, 1, 4);
234 metainfo_write_name_list(s, "javaObjectNames", strs, 2, 4);
235 metainfo_write_name_list(s, "javaSignatures", strs, 3, 4);
236 } else {
237 s << "static const char **qtNames = 0;" << endl
238 << "static const char **javaFunctionNames = 0;" << endl
239 << "static const char **javaObjectNames = 0;" << endl
240 << "static const char **javaSignatures = 0;" << endl;
241 }
242 }
243
244 void MetaInfoGenerator::writeRegisterSignalsAndSlots(QTextStream &s)
245 {
246 s << " for (int i=0;i<sns_count; ++i) {" << endl
247 << " registerQtToJava(qtNames[i], javaFunctionNames[i]);" << endl
248 << " if (getQtName(javaObjectNames[i]).length() < QByteArray(qtNames[i]).size())" << endl
249 << " registerJavaToQt(javaObjectNames[i], qtNames[i]);" << endl
250 << " registerJavaSignature(qtNames[i], javaSignatures[i]);" << endl
251 << " }" << endl;
252 }
253
254 void MetaInfoGenerator::writeRegisterEnums(QTextStream &s)
255 {
256 s << " for (int i=0;i<enum_count; ++i) {" << endl
257 << " registerQtToJava(enumCppNames[i], enumJavaNames[i]);" << endl
258 << " registerJavaToQt(enumJavaNames[i], enumCppNames[i]);" << endl
259 << " }" << endl;
260 }
261
262 void MetaInfoGenerator::buildSkipList()
263 {
264 AbstractMetaClassList classList = classes();
265 foreach (AbstractMetaClass *cls, classList) {
266 if (!m_skip_list.contains(cls->package()))
267 m_skip_list[cls->package()] = 0x0;
268
269 if (cls->typeEntry()->codeGeneration() & TypeEntry::GenerateCpp)
270 m_skip_list[cls->package()] |= GeneratedMetaInfo;
271
272 if (cls->typeEntry()->codeGeneration() & TypeEntry::GenerateTargetLang)
273 m_skip_list[cls->package()] |= GeneratedJavaClasses;
274 }
275 }
276
277 QStringList MetaInfoGenerator::writePolymorphicHandler(QTextStream &s, const QString &package,
278 const AbstractMetaClassList &classes)
279 {
280 QStringList handlers;
281 foreach (AbstractMetaClass *cls, classes) {
282 const ComplexTypeEntry *centry = cls->typeEntry();
283 if (!centry->isPolymorphicBase())
284 continue;
285
286 AbstractMetaClassList classList = this->classes();
287 bool first = true;
288 foreach (AbstractMetaClass *clazz, classList) {
289 if (clazz->package() == package && clazz->inheritsFrom(cls)) {
290 if (!clazz->typeEntry()->polymorphicIdValue().isEmpty()) {
291 // On first find, open the function
292 if (first) {
293 first = false;
294
295 QString handler = jni_signature(cls->fullName(), Underscores);
296 handlers.append(handler);
297
298 s << "static bool polymorphichandler_" << handler
299 << "(const void *ptr, char **class_name, char **package)" << endl
300 << "{" << endl
301 << " Q_ASSERT(ptr != 0);" << endl
302 << " " << cls->qualifiedCppName() << " *object = ("
303 << cls->qualifiedCppName() << " *)ptr;" << endl;
304 }
305
306 // For each, add case label
307 s << " if ("
308 << clazz->typeEntry()->polymorphicIdValue().replace("%1", "object")
309 << ") {" << endl
310 << " *class_name = \"" << clazz->name() << "\";" << endl
311 << " *package = \"" << clazz->package().replace(".", "/") << "/\";" << endl
312 << " return true;" << endl
313 << " }" << endl;
314 } else {
315 QString warning = QString("class '%1' inherits from polymorphic class '%2', but has no polymorphic id set")
316 .arg(clazz->name())
317 .arg(cls->name());
318
319 ReportHandler::warning(warning);
320 }
321 }
322 }
323
324 // Close the function if it has been opened
325 if (!first) {
326 s << " return false;" << endl
327 << "}" << endl;
328 }
329 }
330
331 return handlers;
332 }
333
334 #if defined(QTJAMBI_DEBUG_TOOLS)
335 void MetaInfoGenerator::writeNameLiteral(QTextStream &s, const TypeEntry *entry, const QString &fileName)
336 {
337 static QSet<QString> used;
338
339 if (!used.contains(fileName + ":" + entry->name())) {
340 s << "char __name_" << QString(entry->name()).replace(':', '_').replace(' ', '_') << "[] = \"" << entry->name() << "\";" << endl;
341 used.insert(fileName + ":" + entry->name());
342 }
343 }
344 #endif
345
346 void MetaInfoGenerator::writeCppFile()
347 {
348 TypeEntryHash entries = TypeDatabase::instance()->allEntries();
349 TypeEntryHash::iterator it;
350
351 AbstractMetaClassList classes_with_polymorphic_id;
352 AbstractMetaClassList classList = classes();
353 QHash<QString, FileOut *> fileHash;
354
355 // Seems continue is not supported by our foreach loop, so
356 foreach (AbstractMetaClass *cls, classList) {
357
358 FileOut *f = fileHash.value(cls->package(), 0);
359 if (f == 0 && generated(cls)) {
360 f = new FileOut(outputDirectory() + "/" + subDirectoryForClass(cls, CppDirectory) + "/" + cppFilename());
361
362 writeIncludeStatements(f->stream, classList, cls->package());
363 f->stream << endl;
364
365 #if defined(QTJAMBI_DEBUG_TOOLS)
366 // Write the generic destructors and constructors
367 f->stream << "template <typename T, const char *NAME>" << endl
368 << "void genericDestructor(void *t)" << endl
369 << "{" << endl
370 << " delete (T *) t;" << endl
371 << " qtjambi_increase_destructorFunctionCalledCount(QString::fromLatin1(NAME));" << endl
372 << "}" << endl << endl
373 << "template <typename T>" << endl
374 << "void *genericConstructor(const void *t)" << endl
375 << "{" << endl
376 << " if (!t)" << endl
377 << " return new T;" << endl
378 << " return new T(*reinterpret_cast<const T *>(t));" << endl
379 << "}" << endl;
380 #endif
381
382
383 fileHash.insert(cls->package(), f);
384
385 QString pro_file_name = cls->package().replace(".", "_") + "/" + cls->package().replace(".", "_") + ".pri";
386 priGenerator->addSource(pro_file_name, cppFilename());
387 }
388
389 if (!(cls->attributes() & AbstractMetaAttributes::Fake)) {
390 if (f != 0) {
391 if (cls->typeEntry()->isObject()
392 && !cls->typeEntry()->isQObject()
393 && !cls->isInterface()) {
394 writeDestructors(f->stream, cls);
395 }
396 writeCustomStructors(f->stream, cls->typeEntry());
397 }
398
399 if (cls->typeEntry()->isPolymorphicBase())
400 classes_with_polymorphic_id.append(cls);
401 }
402
403 #if defined(QTJAMBI_DEBUG_TOOLS)
404 if (cls->typeEntry()->isValue() && shouldGenerate(cls->typeEntry()))
405 writeNameLiteral(f->stream, cls->typeEntry(), f->name());
406 #endif
407 }
408
409 QHash<QString, QStringList> handlers_to_register;
410 foreach (QString package, fileHash.keys()) {
411 FileOut *f = fileHash.value(package, 0);
412 if (f != 0) {
413 writeSignalsAndSlots(f->stream, package);
414 writeEnums(f->stream, package);
415 handlers_to_register[package] = writePolymorphicHandler(f->stream, package, classes_with_polymorphic_id);
416 }
417 }
418
419 // Primitive types must be added to all packages, in case the other packages are
420 // not referenced from the generated code.
421 foreach (FileOut *f, fileHash.values()) {
422 for (it=entries.begin(); it!=entries.end(); ++it) {
423 QList<TypeEntry *> entries = it.value();
424 foreach (TypeEntry *entry, entries) {
425 if (shouldGenerate(entry) && entry->isPrimitive()) {
426 writeCustomStructors(f->stream, entry);
427 #if defined(QTJAMBI_DEBUG_TOOLS)
428 writeNameLiteral(f->stream, entry, f->name());
429 #endif
430 }
431 }
432 }
433
434 // Initialization function: Registers meta types
435 writeInitializationFunctionName(f->stream, fileHash.key(f, ""), true);
436 f->stream << endl << "{" << endl;
437 for (it=entries.begin(); it!=entries.end(); ++it) {
438 QList<TypeEntry *> entries = it.value();
439 foreach (TypeEntry *entry, entries) {
440 if (entry &&
441 ( (shouldGenerate(entry) && entry->isPrimitive())
442 || entry->isString()
443 || entry->isChar())) {
444 writeInitialization(f->stream, entry, 0);
445 }
446 }
447 }
448 writeRegisterSignalsAndSlots(f->stream);
449 writeRegisterEnums(f->stream);
450 }
451
452 foreach (AbstractMetaClass *cls, classList) {
453 FileOut *f = fileHash.value(cls->package(), 0);
454
455 if (f != 0) {
456 writeInitialization(f->stream, cls->typeEntry(), cls, shouldGenerate(cls));
457 }
458 }
459
460 foreach (QString package, fileHash.keys()) {
461 FileOut *f = fileHash.value(package, 0);
462 if (f != 0) {
463 foreach (QString handler, handlers_to_register.value(package, QStringList())) {
464 f->stream << " qtjambi_register_polymorphic_id(\"" << handler << "\","
465 << "polymorphichandler_" << handler << ");" << endl;
466 }
467
468 f->stream << "}" << endl << endl;
469 if( f->done() )
470 ++m_num_generated_written;
471 ++m_num_generated;
472
473 delete f;
474 }
475 }
476 }
477
478 void MetaInfoGenerator::writeHeaderFile()
479 {
480 AbstractMetaClassList classList = classes();
481 QHash<QString, bool> fileHash;
482
483 foreach (AbstractMetaClass *cls, classList) {
484 bool hasGenerated = fileHash.value(cls->package(), false);
485 if (!hasGenerated && generated(cls)) {
486 FileOut file(outputDirectory() + "/" + subDirectoryForClass(cls, CppDirectory) + "/" + headerFilename());
487 file.stream << "#ifndef " << filenameStub().toUpper() << "_H" << endl;
488 file.stream << "#define " << filenameStub().toUpper() << "_H" << endl << endl;
489 writeInitializationFunctionName(file.stream, cls->package(), true);
490 file.stream << ";" << endl << "#endif" << endl << endl;
491
492 fileHash.insert(cls->package(), true);
493
494 QString pro_file_name = cls->package().replace(".", "_") + "/" + cls->package().replace(".", "_") + ".pri";
495 priGenerator->addHeader(pro_file_name, headerFilename());
496
497 if( file.done() )
498 ++m_num_generated_written;
499 ++m_num_generated;
500 }
501 }
502 }
503
504 void MetaInfoGenerator::writeCodeBlock(QTextStream &s, const QString &code)
505 {
506 QStringList lines = code.split('\n');
507 QString indent;
508 foreach (QString str, lines) {
509 s << " " << indent << str.trimmed() << endl;
510 if (!str.trimmed().endsWith(";") && !str.trimmed().isEmpty())
511 indent = " ";
512 else
513 indent = "";
514 }
515 }
516
517 const AbstractMetaClass* MetaInfoGenerator::lookupClassWithPublicDestructor(const AbstractMetaClass *cls)
518 {
519 while (cls != 0) {
520 if (cls->hasPublicDestructor()) {
521 return cls;
522 } else {
523 cls = cls->baseClass();
524 }
525 }
526 return 0;
527 }
528
529 void MetaInfoGenerator::writeDestructors(QTextStream &s, const AbstractMetaClass *cls)
530 {
531 // We can only delete classes with public destructors
532 const AbstractMetaClass *clsWithPublicDestructor = lookupClassWithPublicDestructor(cls);
533 if(clsWithPublicDestructor != 0) {
534 const ComplexTypeEntry *entry = cls->typeEntry();
535 if ((entry->codeGeneration() & TypeEntry::GenerateCode) != 0) {
536 s << "void destructor_" << entry->javaPackage().replace(".", "_") << "_"
537 << entry->lookupName().replace(".", "_").replace("$", "_") << "(void *ptr)" << endl
538 << "{" << endl
539 << " delete reinterpret_cast<" << clsWithPublicDestructor->qualifiedCppName() << " *>(ptr);" << endl;
540
541 #if defined(QTJAMBI_DEBUG_TOOLS)
542 s << " qtjambi_increase_destructorFunctionCalledCount(QString::fromLatin1(\"" << cls->name() << "\"));" << endl;
543 #endif
544
545 s << "}" << endl << endl;
546 }
547 }
548 }
549
550 void MetaInfoGenerator::writeCustomStructors(QTextStream &s, const TypeEntry *entry)
551 {
552 if (!entry->preferredConversion())
553 return ;
554
555 CustomFunction customConstructor = entry->customConstructor();
556 CustomFunction customDestructor = entry->customDestructor();
557
558 if (!customConstructor.name.isEmpty() && !customDestructor.name.isEmpty()) {
559 s << "// Custom constructor and destructor for " << entry->qualifiedCppName() << endl
560 << "static void *" << customConstructor.name << "("
561 << "const " << entry->qualifiedCppName() << " *" << customConstructor.param_name
562 << ")" << endl
563 << "{" << endl;
564 writeCodeBlock(s, customConstructor.code());
565 s << "}" << endl << endl;
566
567 s << "static void " << customDestructor.name << "("
568 << "const " << entry->qualifiedCppName() << " *" << customDestructor.param_name
569 << ")" << endl
570 << "{" << endl;
571 writeCodeBlock(s, customDestructor.code());
572 s << "}" << endl << endl;
573 }
574 }
575
576 static void generateInitializer(QTextStream &s, const QString &package, CodeSnip::Position pos)
577 {
578 QList<CodeSnip> snips =
579 ((TypeSystemTypeEntry *) TypeDatabase::instance()->findType(package))->snips;
580
581 foreach (const CodeSnip &snip, snips)
582 if (snip.position == pos)
583 s << snip.code();
584 }
585
586 void MetaInfoGenerator::writeLibraryInitializers()
587 {
588 // from cppimplgenerator.cpp
589 extern QString jni_function_signature(QString package,
590 QString class_name,
591 const QString &function_name,
592 const QString &return_type,
593 const QString &mangled_arguments = QString(),
594 uint options = CppImplGenerator::StandardJNISignature);
595
596 // We need to generate a library initializer in Java for all packages
597 // that have generated classes in Java, and in C++ for all packages
598 // that have generated metainfo.
599
600 QList<QString> known_packages = m_skip_list.keys();
601 foreach (QString package, known_packages) {
602 if (generatedMetaInfo(package)) { // write cpp file
603
604 FileOut fileOut(outputDirectory() + "/" + subDirectoryForPackage(package, CppDirectory) + "/qtjambi_libraryinitializer.cpp");
605
606 QString signature = jni_function_signature(package, "QtJambi_LibraryInitializer",
607 "__qt_initLibrary", "void");
608 QTextStream &s = fileOut.stream;
609 s << "#include \"metainfo.h\"" << endl
610 << "#include \"qtjambi_global.h\"" << endl << endl
611 << signature << "(JNIEnv *, jclass)" << endl
612 << "{" << endl
613 << " ";
614 writeInitializationFunctionName(s, package, false);
615 s << ";" << endl
616 << "}" << endl << endl;
617
618 QString pro_file_name = QString(package).replace(".", "_");
619
620 priGenerator->addSource(pro_file_name + "/" + pro_file_name + ".pri", "qtjambi_libraryinitializer.cpp");
621
622 if( fileOut.done() )
623 ++m_num_generated_written;
624 ++m_num_generated;
625 }
626
627 if (generatedJavaClasses(package)) {
628
629 FileOut fileOut(outputDirectory() + "/" + subDirectoryForPackage(package, JavaDirectory) + "/QtJambi_LibraryInitializer.java");
630
631 QTextStream &s = fileOut.stream;
632 s << "package " << package << ";" << endl << endl
633 << "class QtJambi_LibraryInitializer" << endl
634 << "{" << endl
635 << " static {" << endl;
636
637 generateInitializer(s, package, CodeSnip::Beginning);
638
639 s << " qt.Utilities.loadJambiLibrary(\""
640 << QString(package).replace(".", "_") << "\");" << endl;
641
642 if (generatedMetaInfo(package))
643 s << " __qt_initLibrary();" << endl;
644
645 generateInitializer(s, package, CodeSnip::End);
646
647 s << " }" << endl;
648
649 if (generatedMetaInfo(package))
650 s << " private native static void __qt_initLibrary();" << endl;
651
652 s << " static void init() { };" << endl
653 << "}" << endl << endl;
654
655 if( fileOut.done() )
656 ++m_num_generated_written;
657 ++m_num_generated;
658 }
659 }
660 }
661
662 void MetaInfoGenerator::writeInclude(QTextStream &s, const Include &inc)
663 {
664 if (inc.name.isEmpty())
665 return;
666
667 s << "#include ";
668 if (inc.type == Include::LocalPath)
669 s << "\"" << inc.name << "\"";
670 else
671 s << "<" << inc.name << ">";
672 s << endl;
673 }
674
675 void MetaInfoGenerator::writeIncludeStatements(QTextStream &s, const AbstractMetaClassList &classList,
676 const QString &package)
677 {
678 writeInclude(s, Include(Include::LocalPath, headerFilename()));
679 writeInclude(s, Include(Include::IncludePath, "QMetaType"));
680 writeInclude(s, Include(Include::IncludePath, "QString"));
681 writeInclude(s, Include(Include::IncludePath, "QLatin1String"));
682 writeInclude(s, Include(Include::IncludePath, "QHash"));
683 writeInclude(s, Include(Include::IncludePath, "QReadWriteLock"));
684 writeInclude(s, Include(Include::IncludePath, "QReadLocker"));
685 writeInclude(s, Include(Include::IncludePath, "QWriteLocker"));
686 writeInclude(s, Include(Include::IncludePath, "qtjambi_cache.h"));
687 writeInclude(s, Include(Include::IncludePath, "qtjambi_core.h"));
688
689 #if defined(QTJAMBI_DEBUG_TOOLS)
690 writeInclude(s, Include(Include::IncludePath, "qtjambidebugtools_p.h"));
691 #endif
692
693 s << endl;
694
695 foreach (AbstractMetaClass *cls, classList) {
696 if (generated(cls) && !cls->isInterface() && cls->package() == package) {
697 const ComplexTypeEntry *ctype = cls->typeEntry();
698
699 Include inc = ctype->include();
700 writeInclude(s, inc);
701 }
702 }
703 }
704
705 void MetaInfoGenerator::writeInitializationFunctionName(QTextStream &s, const QString &package, bool fullSignature)
706 {
707 if (fullSignature)
708 s << "void ";
709 s << "__metainfo_init_" << QString(package).replace(".", "_") << "()";
710 }
711
712 void MetaInfoGenerator::writeInitialization(QTextStream &s, const TypeEntry *entry, const AbstractMetaClass *cls,
713 bool registerMetaType)
714 {
715 if (entry->codeGeneration() == TypeEntry::GenerateForSubclass)
716 return;
717
718 if (cls && cls->attributes() & AbstractMetaAttributes::Fake)
719 return;
720
721
722 QString constructorName = entry->customConstructor().name;
723 QString destructorName = entry->customDestructor().name;
724 #if defined(QTJAMBI_DEBUG_TOOLS)
725
726 if (constructorName.isEmpty())
727 constructorName = "genericConstructor<" + entry->qualifiedCppName() + ">";
728
729 if (destructorName.isEmpty())
730 destructorName = "genericDestructor<" + entry->qualifiedCppName() + ", __name_" + entry->name() + ">";
731
732 #endif
733
734
735 if (constructorName.isEmpty() != destructorName.isEmpty()) {
736 ReportHandler::warning(QString("specify either no custom functions, or both "
737 "constructor and destructor for type '%1'").arg(entry->name()));
738 }
739
740 QString javaPackage = entry->javaPackage();
741
742 QString javaName = entry->lookupName();
743 if(!javaPackage.isEmpty()){
744 javaName.prepend(javaPackage.replace(".", "/") + "/");
745 }
746
747
748 if (entry->isComplex()) {
749 const ComplexTypeEntry *centry = static_cast<const ComplexTypeEntry *>(entry);
750 if (centry->typeFlags() & ComplexTypeEntry::DeleteInMainThread)
751 s << " registerDeletionPolicy(\"" << javaName << "\", DeletionPolicyDeleteInMainThread);" << endl;
752 }
753
754 QString qtName = entry->qualifiedCppName();
755 if ((!entry->isInterface())
756 && (!entry->isPrimitive() || ((PrimitiveTypeEntry *) entry)->preferredTargetLangType()))
757 s << " registerQtToJava(\"" << qtName << "\", \"" << javaName << "\");" << endl;
758
759 if (!entry->preferredConversion())
760 return ;
761
762 s << " registerJavaToQt(\"" << javaName << "\", \"" << qtName << "\");" << endl;
763 if (entry->isComplex() && entry->isObject() && !((ComplexTypeEntry *)entry)->isQObject() && !entry->isInterface()) {
764 QString patchedName = QString(javaName).replace("/", "_").replace("$", "_");
765
766 if(lookupClassWithPublicDestructor(cls))
767 s << " registerDestructor(\"" << javaName << "\", destructor_" << patchedName << ");" << endl;
768 }
769
770 if (!registerMetaType)
771 return ;
772
773 int metaType = QMetaType::type(entry->name().toLocal8Bit().constData());
774 if (metaType != QMetaType::Void)
775 return ;
776
777
778 if (!constructorName.isEmpty() && !destructorName.isEmpty()) {
779 s << " QMetaType::registerType(\"" << entry->qualifiedCppName() << "\"," << endl
780 << " reinterpret_cast<QMetaType::Destructor>("
781 << destructorName
782 << ")," << endl
783 << " reinterpret_cast<QMetaType::Constructor>("
784 << constructorName
785 << "));" << endl;
786 } else {
787 // Look for default constructor, required for qRegisterMetaType
788 if (cls != 0) {
789 AbstractMetaFunctionList functions = cls->queryFunctions(AbstractMetaClass::WasPublic | AbstractMetaClass::Constructors);
790
791 bool hasDefaultConstructor = false;
792 foreach (AbstractMetaFunction *function, functions) {
793 // Default constructor has to be present
794 if (function->wasPublic() && function->actualMinimumArgumentCount() == 0)
795 hasDefaultConstructor = true;
796 }
797
798 if (!hasDefaultConstructor) {
799 ReportHandler::warning(QString("Value type '%1' is missing a default constructor. "
800 "The resulting C++ code will not compile. If necessary, use <custom-constructor> and "
801 "<custom-destructor> tags to provide the constructors.").arg(cls->fullName()));
802 }
803
804 }
805 s << " qRegisterMetaType<" << entry->qualifiedCppName() << ">(\"" << entry->qualifiedCppName() << "\");" << endl;
806 }
807
808 }