1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #include "fakemetaobject.h"
27 #include <QCryptographicHash>
28
29 using namespace LanguageUtils;
30
FakeMetaEnum()31 FakeMetaEnum::FakeMetaEnum()
32 {}
33
FakeMetaEnum(const QString & name)34 FakeMetaEnum::FakeMetaEnum(const QString &name)
35 : m_name(name)
36 {}
37
isValid() const38 bool FakeMetaEnum::isValid() const
39 { return !m_name.isEmpty(); }
40
name() const41 QString FakeMetaEnum::name() const
42 { return m_name; }
43
setName(const QString & name)44 void FakeMetaEnum::setName(const QString &name)
45 { m_name = name; }
46
addKey(const QString & key)47 void FakeMetaEnum::addKey(const QString &key)
48 { m_keys.append(key); }
49
key(int index) const50 QString FakeMetaEnum::key(int index) const
51 { return m_keys.at(index); }
52
keyCount() const53 int FakeMetaEnum::keyCount() const
54 { return m_keys.size(); }
55
keys() const56 QStringList FakeMetaEnum::keys() const
57 { return m_keys; }
58
hasKey(const QString & key) const59 bool FakeMetaEnum::hasKey(const QString &key) const
60 { return m_keys.contains(key); }
61
addToHash(QCryptographicHash & hash) const62 void FakeMetaEnum::addToHash(QCryptographicHash &hash) const
63 {
64 int len = m_name.size();
65 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
66 hash.addData(reinterpret_cast<const char *>(m_name.constData()), len * sizeof(QChar));
67 len = m_keys.size();
68 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
69 foreach (const QString &key, m_keys) {
70 len = key.size();
71 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
72 hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
73 }
74 }
75
describe(int baseIndent) const76 QString FakeMetaEnum::describe(int baseIndent) const
77 {
78 QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
79 QString res = QLatin1String("Enum ");
80 res += name();
81 res += QLatin1String(": [");
82 for (int i = 0; i < keyCount(); ++i) {
83 res += newLine;
84 res += QLatin1String(" ");
85 res += key(i);
86 }
87 res += newLine;
88 res += QLatin1Char(']');
89 return res;
90 }
91
toString() const92 QString FakeMetaEnum::toString() const
93 {
94 return describe();
95 }
96
FakeMetaMethod(const QString & name,const QString & returnType)97 FakeMetaMethod::FakeMetaMethod(const QString &name, const QString &returnType)
98 : m_name(name)
99 , m_returnType(returnType)
100 , m_methodTy(FakeMetaMethod::Method)
101 , m_methodAccess(FakeMetaMethod::Public)
102 , m_revision(0)
103 {}
104
FakeMetaMethod()105 FakeMetaMethod::FakeMetaMethod()
106 : m_methodTy(FakeMetaMethod::Method)
107 , m_methodAccess(FakeMetaMethod::Public)
108 , m_revision(0)
109 {}
110
methodName() const111 QString FakeMetaMethod::methodName() const
112 { return m_name; }
113
setMethodName(const QString & name)114 void FakeMetaMethod::setMethodName(const QString &name)
115 { m_name = name; }
116
setReturnType(const QString & type)117 void FakeMetaMethod::setReturnType(const QString &type)
118 { m_returnType = type; }
119
parameterNames() const120 QStringList FakeMetaMethod::parameterNames() const
121 { return m_paramNames; }
122
parameterTypes() const123 QStringList FakeMetaMethod::parameterTypes() const
124 { return m_paramTypes; }
125
addParameter(const QString & name,const QString & type)126 void FakeMetaMethod::addParameter(const QString &name, const QString &type)
127 { m_paramNames.append(name); m_paramTypes.append(type); }
128
methodType() const129 int FakeMetaMethod::methodType() const
130 { return m_methodTy; }
131
setMethodType(int methodType)132 void FakeMetaMethod::setMethodType(int methodType)
133 { m_methodTy = methodType; }
134
access() const135 int FakeMetaMethod::access() const
136 { return m_methodAccess; }
137
revision() const138 int FakeMetaMethod::revision() const
139 { return m_revision; }
140
setRevision(int r)141 void FakeMetaMethod::setRevision(int r)
142 { m_revision = r; }
143
addToHash(QCryptographicHash & hash) const144 void FakeMetaMethod::addToHash(QCryptographicHash &hash) const
145 {
146 int len = m_name.size();
147 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
148 hash.addData(reinterpret_cast<const char *>(m_name.constData()), len * sizeof(QChar));
149 hash.addData(reinterpret_cast<const char *>(&m_methodAccess), sizeof(m_methodAccess));
150 hash.addData(reinterpret_cast<const char *>(&m_methodTy), sizeof(m_methodTy));
151 hash.addData(reinterpret_cast<const char *>(&m_revision), sizeof(m_revision));
152 len = m_paramNames.size();
153 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
154 foreach (const QString &pName, m_paramNames) {
155 len = pName.size();
156 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
157 hash.addData(reinterpret_cast<const char *>(pName.constData()), len * sizeof(QChar));
158 }
159 len = m_paramTypes.size();
160 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
161 foreach (const QString &pType, m_paramTypes) {
162 len = pType.size();
163 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
164 hash.addData(reinterpret_cast<const char *>(pType.constData()), len * sizeof(QChar));
165 }
166 len = m_returnType.size();
167 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
168 hash.addData(reinterpret_cast<const char *>(m_returnType.constData()), len * sizeof(QChar));
169 }
170
describe(int baseIndent) const171 QString FakeMetaMethod::describe(int baseIndent) const
172 {
173 QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
174 QString res = QLatin1String("Method {");
175 res += newLine;
176 res += QLatin1String(" methodName:");
177 res += methodName();
178 res += newLine;
179 res += QLatin1String(" methodType:");
180 res += QString::number(methodType());
181 res += newLine;
182 res += QLatin1String(" parameterNames:[");
183 foreach (const QString &pName, parameterNames()) {
184 res += newLine;
185 res += QLatin1String(" ");
186 res += pName;
187 }
188 res += QLatin1Char(']');
189 res += newLine;
190 res += QLatin1String(" parameterTypes:[");
191 foreach (const QString &pType, parameterTypes()) {
192 res += newLine;
193 res += QLatin1String(" ");
194 res += pType;
195 }
196 res += QLatin1Char(']');
197 res += newLine;
198 res += QLatin1Char('}');
199 return res;
200 }
201
toString() const202 QString FakeMetaMethod::toString() const
203 {
204 return describe();
205 }
206
207
FakeMetaProperty(const QString & name,const QString & type,bool isList,bool isWritable,bool isPointer,int revision)208 FakeMetaProperty::FakeMetaProperty(const QString &name, const QString &type, bool isList,
209 bool isWritable, bool isPointer, int revision)
210 : m_propertyName(name)
211 , m_type(type)
212 , m_isList(isList)
213 , m_isWritable(isWritable)
214 , m_isPointer(isPointer)
215 , m_revision(revision)
216 {}
217
name() const218 QString FakeMetaProperty::name() const
219 { return m_propertyName; }
220
typeName() const221 QString FakeMetaProperty::typeName() const
222 { return m_type; }
223
isList() const224 bool FakeMetaProperty::isList() const
225 { return m_isList; }
226
isWritable() const227 bool FakeMetaProperty::isWritable() const
228 { return m_isWritable; }
229
isPointer() const230 bool FakeMetaProperty::isPointer() const
231 { return m_isPointer; }
232
revision() const233 int FakeMetaProperty::revision() const
234 { return m_revision; }
235
addToHash(QCryptographicHash & hash) const236 void FakeMetaProperty::addToHash(QCryptographicHash &hash) const
237 {
238 int len = m_propertyName.size();
239 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
240 hash.addData(reinterpret_cast<const char *>(m_propertyName.constData()), len * sizeof(QChar));
241 hash.addData(reinterpret_cast<const char *>(&m_revision), sizeof(m_revision));
242 int flags = (m_isList ? (1 << 0) : 0)
243 + (m_isPointer ? (1 << 1) : 0)
244 + (m_isWritable ? (1 << 2) : 0);
245 hash.addData(reinterpret_cast<const char *>(&flags), sizeof(flags));
246 len = m_type.size();
247 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
248 hash.addData(reinterpret_cast<const char *>(m_type.constData()), len * sizeof(QChar));
249 }
250
describe(int baseIndent) const251 QString FakeMetaProperty::describe(int baseIndent) const
252 {
253 auto boolStr = [] (bool v) { return v ? QLatin1String("true") : QLatin1String("false"); };
254 QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
255 QString res = QLatin1String("Property {");
256 res += newLine;
257 res += QLatin1String(" name:");
258 res += name();
259 res += newLine;
260 res += QLatin1String(" typeName:");
261 res += typeName();
262 res += newLine;
263 res += QLatin1String(" typeName:");
264 res += QString::number(revision());
265 res += newLine;
266 res += QLatin1String(" isList:");
267 res += boolStr(isList());
268 res += newLine;
269 res += QLatin1String(" isPointer:");
270 res += boolStr(isPointer());
271 res += newLine;
272 res += QLatin1String(" isWritable:");
273 res += boolStr(isWritable());
274 res += newLine;
275 res += QLatin1Char('}');
276 return res;
277 }
278
toString() const279 QString FakeMetaProperty::toString() const
280 {
281 return describe();
282 }
283
284
FakeMetaObject()285 FakeMetaObject::FakeMetaObject() : m_isSingleton(false), m_isCreatable(true), m_isComposite(false)
286 {
287 }
288
className() const289 QString FakeMetaObject::className() const
290 { return m_className; }
setClassName(const QString & name)291 void FakeMetaObject::setClassName(const QString &name)
292 { m_className = name; }
293
addExport(const QString & name,const QString & package,ComponentVersion version)294 void FakeMetaObject::addExport(const QString &name, const QString &package, ComponentVersion version)
295 {
296 Export exp;
297 exp.type = name;
298 exp.package = package;
299 exp.version = version;
300 m_exports.append(exp);
301 }
302
setExportMetaObjectRevision(int exportIndex,int metaObjectRevision)303 void FakeMetaObject::setExportMetaObjectRevision(int exportIndex, int metaObjectRevision)
304 {
305 m_exports[exportIndex].metaObjectRevision = metaObjectRevision;
306 }
307
exports() const308 QList<FakeMetaObject::Export> FakeMetaObject::exports() const
309 { return m_exports; }
exportInPackage(const QString & package) const310 FakeMetaObject::Export FakeMetaObject::exportInPackage(const QString &package) const
311 {
312 foreach (const Export &exp, m_exports) {
313 if (exp.package == package)
314 return exp;
315 }
316 return Export();
317 }
318
setSuperclassName(const QString & superclass)319 void FakeMetaObject::setSuperclassName(const QString &superclass)
320 { m_superName = superclass; }
superclassName() const321 QString FakeMetaObject::superclassName() const
322 { return m_superName; }
323
addEnum(const FakeMetaEnum & fakeEnum)324 void FakeMetaObject::addEnum(const FakeMetaEnum &fakeEnum)
325 { m_enumNameToIndex.insert(fakeEnum.name(), m_enums.size()); m_enums.append(fakeEnum); }
enumeratorCount() const326 int FakeMetaObject::enumeratorCount() const
327 { return m_enums.size(); }
enumeratorOffset() const328 int FakeMetaObject::enumeratorOffset() const
329 { return 0; }
enumerator(int index) const330 FakeMetaEnum FakeMetaObject::enumerator(int index) const
331 { return m_enums.at(index); }
enumeratorIndex(const QString & name) const332 int FakeMetaObject::enumeratorIndex(const QString &name) const
333 { return m_enumNameToIndex.value(name, -1); }
334
addProperty(const FakeMetaProperty & property)335 void FakeMetaObject::addProperty(const FakeMetaProperty &property)
336 { m_propNameToIdx.insert(property.name(), m_props.size()); m_props.append(property); }
propertyCount() const337 int FakeMetaObject::propertyCount() const
338 { return m_props.size(); }
propertyOffset() const339 int FakeMetaObject::propertyOffset() const
340 { return 0; }
property(int index) const341 FakeMetaProperty FakeMetaObject::property(int index) const
342 { return m_props.at(index); }
propertyIndex(const QString & name) const343 int FakeMetaObject::propertyIndex(const QString &name) const
344 { return m_propNameToIdx.value(name, -1); }
345
addMethod(const FakeMetaMethod & method)346 void FakeMetaObject::addMethod(const FakeMetaMethod &method)
347 { m_methods.append(method); }
methodCount() const348 int FakeMetaObject::methodCount() const
349 { return m_methods.size(); }
methodOffset() const350 int FakeMetaObject::methodOffset() const
351 { return 0; }
method(int index) const352 FakeMetaMethod FakeMetaObject::method(int index) const
353 { return m_methods.at(index); }
methodIndex(const QString & name) const354 int FakeMetaObject::methodIndex(const QString &name) const //If performances becomes an issue, just use a nameToIdx hash
355 {
356 for (int i=0; i<m_methods.count(); i++)
357 if (m_methods[i].methodName() == name)
358 return i;
359 return -1;
360 }
361
defaultPropertyName() const362 QString FakeMetaObject::defaultPropertyName() const
363 { return m_defaultPropertyName; }
setDefaultPropertyName(const QString & defaultPropertyName)364 void FakeMetaObject::setDefaultPropertyName(const QString &defaultPropertyName)
365 { m_defaultPropertyName = defaultPropertyName; }
366
attachedTypeName() const367 QString FakeMetaObject::attachedTypeName() const
368 { return m_attachedTypeName; }
setAttachedTypeName(const QString & name)369 void FakeMetaObject::setAttachedTypeName(const QString &name)
370 { m_attachedTypeName = name; }
371
extensionTypeName() const372 QString FakeMetaObject::extensionTypeName() const
373 { return m_extensionTypeName; }
setExtensionTypeName(const QString & name)374 void FakeMetaObject::setExtensionTypeName(const QString &name)
375 { m_extensionTypeName = name; }
376
calculateFingerprint() const377 QByteArray FakeMetaObject::calculateFingerprint() const
378 {
379 QCryptographicHash hash(QCryptographicHash::Sha1);
380 int len = m_className.size();
381 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
382 hash.addData(reinterpret_cast<const char *>(m_className.constData()), len * sizeof(QChar));
383 len = m_attachedTypeName.size();
384 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
385 hash.addData(reinterpret_cast<const char *>(m_attachedTypeName.constData()), len * sizeof(QChar));
386 len = m_defaultPropertyName.size();
387 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
388 hash.addData(reinterpret_cast<const char *>(m_defaultPropertyName.constData()), len * sizeof(QChar));
389 len = m_enumNameToIndex.size();
390 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
391 {
392 QStringList keys(m_enumNameToIndex.keys());
393 keys.sort();
394 foreach (const QString &key, keys) {
395 len = key.size();
396 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
397 hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
398 int value = m_enumNameToIndex.value(key);
399 hash.addData(reinterpret_cast<const char *>(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint...
400 m_enums.at(value).addToHash(hash);
401 }
402 }
403 len = m_exports.size();
404 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
405 foreach (const Export &e, m_exports)
406 e.addToHash(hash); // normalize order?
407 len = m_exports.size();
408 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
409 foreach (const FakeMetaMethod &m, m_methods)
410 m.addToHash(hash); // normalize order?
411 {
412 QStringList keys(m_propNameToIdx.keys());
413 keys.sort();
414 foreach (const QString &key, keys) {
415 len = key.size();
416 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
417 hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
418 int value = m_propNameToIdx.value(key);
419 hash.addData(reinterpret_cast<const char *>(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint...
420 m_props.at(value).addToHash(hash);
421 }
422 }
423 len = m_superName.size();
424 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
425 hash.addData(reinterpret_cast<const char *>(m_superName.constData()), len * sizeof(QChar));
426
427 QByteArray res = hash.result();
428 res.append('F');
429 return res;
430 }
431
updateFingerprint()432 void FakeMetaObject::updateFingerprint()
433 {
434 m_fingerprint = calculateFingerprint();
435 }
436
fingerprint() const437 QByteArray FakeMetaObject::fingerprint() const
438 {
439 return m_fingerprint;
440 }
441
isSingleton() const442 bool FakeMetaObject::isSingleton() const
443 {
444 return m_isSingleton;
445 }
446
isCreatable() const447 bool FakeMetaObject::isCreatable() const
448 {
449 return m_isCreatable;
450 }
451
isComposite() const452 bool FakeMetaObject::isComposite() const
453 {
454 return m_isComposite;
455 }
456
setIsSingleton(bool value)457 void FakeMetaObject::setIsSingleton(bool value)
458 {
459 m_isSingleton = value;
460 }
461
setIsCreatable(bool value)462 void FakeMetaObject::setIsCreatable(bool value)
463 {
464 m_isCreatable = value;
465 }
466
setIsComposite(bool value)467 void FakeMetaObject::setIsComposite(bool value)
468 {
469 m_isSingleton = value;
470 }
471
toString() const472 QString FakeMetaObject::toString() const
473 {
474 return describe();
475 }
476
describe(bool printDetails,int baseIndent) const477 QString FakeMetaObject::describe(bool printDetails, int baseIndent) const
478 {
479 QString res = QString::fromLatin1("FakeMetaObject@%1")
480 .arg((quintptr)(void *)this, 0, 16);
481 if (!printDetails)
482 return res;
483 auto boolStr = [] (bool v) { return v ? QLatin1String("true") : QLatin1String("false"); };
484 QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
485 res += QLatin1Char('{');
486 res += newLine;
487 res += QLatin1String("className:");
488 res += className();
489 res += newLine;
490 res += QLatin1String("superClassName:");
491 res += superclassName();
492 res += newLine;
493 res += QLatin1String("isSingleton:");
494 res += boolStr(isSingleton());
495 res += newLine;
496 res += QLatin1String("isCreatable:");
497 res += boolStr(isCreatable());
498 res += newLine;
499 res += QLatin1String("isComposite:");
500 res += boolStr(isComposite());
501 res += newLine;
502 res += QLatin1String("defaultPropertyName:");
503 res += defaultPropertyName();
504 res += newLine;
505 res += QLatin1String("attachedTypeName:");
506 res += attachedTypeName();
507 res += newLine;
508 res += QLatin1String("fingerprint:");
509 res += QString::fromUtf8(fingerprint());
510
511 res += newLine;
512 res += QLatin1String("exports:[");
513 foreach (const Export &e, exports()) {
514 res += newLine;
515 res += QLatin1String(" ");
516 res += e.describe(baseIndent + 2);
517 }
518 res += QLatin1Char(']');
519
520 res += newLine;
521 res += QLatin1String("enums:[");
522 for (int iEnum = 0; iEnum < enumeratorCount() ; ++ iEnum) {
523 FakeMetaEnum e = enumerator(enumeratorOffset() + iEnum);
524 res += newLine;
525 res += QLatin1String(" ");
526 res += e.describe(baseIndent + 2);
527 }
528 res += QLatin1Char(']');
529
530 res += newLine;
531 res += QLatin1String("properties:[");
532 for (int iProp = 0; iProp < propertyCount() ; ++ iProp) {
533 FakeMetaProperty prop = property(propertyOffset() + iProp);
534 res += newLine;
535 res += QLatin1String(" ");
536 res += prop.describe(baseIndent + 2);
537 }
538 res += QLatin1Char(']');
539 res += QLatin1String("methods:[");
540 for (int iMethod = 0; iMethod < methodOffset() ; ++ iMethod) {
541 FakeMetaMethod m = method(methodOffset() + iMethod);
542 res += newLine;
543 res += QLatin1String(" ");
544 m.describe(baseIndent + 2);
545 }
546 res += QLatin1Char(']');
547 res += newLine;
548 res += QLatin1Char('}');
549 return res;
550 }
551
Export()552 FakeMetaObject::Export::Export()
553 : metaObjectRevision(0)
554 {}
isValid() const555 bool FakeMetaObject::Export::isValid() const
556 { return version.isValid() || !package.isEmpty() || !type.isEmpty(); }
557
addToHash(QCryptographicHash & hash) const558 void FakeMetaObject::Export::addToHash(QCryptographicHash &hash) const
559 {
560 int len = package.size();
561 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
562 hash.addData(reinterpret_cast<const char *>(package.constData()), len * sizeof(QChar));
563 len = type.size();
564 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
565 hash.addData(reinterpret_cast<const char *>(type.constData()), len * sizeof(QChar));
566 version.addToHash(hash);
567 hash.addData(reinterpret_cast<const char *>(&metaObjectRevision), sizeof(metaObjectRevision));
568 }
569
describe(int baseIndent) const570 QString FakeMetaObject::Export::describe(int baseIndent) const
571 {
572 QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
573 QString res = QLatin1String("Export {");
574 res += newLine;
575 res += QLatin1String(" package:");
576 res += package;
577 res += newLine;
578 res += QLatin1String(" type:");
579 res += type;
580 res += newLine;
581 res += QLatin1String(" version:");
582 res += version.toString();
583 res += newLine;
584 res += QLatin1String(" metaObjectRevision:");
585 res += QString::number(metaObjectRevision);
586 res += newLine;
587 res += QLatin1String(" isValid:");
588 res += QString::number(isValid());
589 res += newLine;
590 res += QLatin1Char('}');
591 return res;
592 }
593
toString() const594 QString FakeMetaObject::Export::toString() const
595 {
596 return describe();
597 }
598