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,int value)47 void FakeMetaEnum::addKey(const QString &key, int value)
48 { m_keys.append(key); m_values.append(value); }
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 len = m_values.size();
75 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
76 foreach (int value, m_values)
77 hash.addData(reinterpret_cast<const char *>(&value), sizeof(value));
78 }
79
describe(int baseIndent) const80 QString FakeMetaEnum::describe(int baseIndent) const
81 {
82 QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
83 QString res = QLatin1String("Enum ");
84 res += name();
85 res += QLatin1String(":{");
86 for (int i = 0; i < keyCount(); ++i) {
87 res += newLine;
88 res += QLatin1String(" ");
89 res += key(i);
90 res += QLatin1String(": ");
91 res += QString::number(m_values.value(i, -1));
92 }
93 res += newLine;
94 res += QLatin1Char('}');
95 return res;
96 }
97
toString() const98 QString FakeMetaEnum::toString() const
99 {
100 return describe();
101 }
102
FakeMetaMethod(const QString & name,const QString & returnType)103 FakeMetaMethod::FakeMetaMethod(const QString &name, const QString &returnType)
104 : m_name(name)
105 , m_returnType(returnType)
106 , m_methodTy(FakeMetaMethod::Method)
107 , m_methodAccess(FakeMetaMethod::Public)
108 , m_revision(0)
109 {}
110
FakeMetaMethod()111 FakeMetaMethod::FakeMetaMethod()
112 : m_methodTy(FakeMetaMethod::Method)
113 , m_methodAccess(FakeMetaMethod::Public)
114 , m_revision(0)
115 {}
116
methodName() const117 QString FakeMetaMethod::methodName() const
118 { return m_name; }
119
setMethodName(const QString & name)120 void FakeMetaMethod::setMethodName(const QString &name)
121 { m_name = name; }
122
setReturnType(const QString & type)123 void FakeMetaMethod::setReturnType(const QString &type)
124 { m_returnType = type; }
125
parameterNames() const126 QStringList FakeMetaMethod::parameterNames() const
127 { return m_paramNames; }
128
parameterTypes() const129 QStringList FakeMetaMethod::parameterTypes() const
130 { return m_paramTypes; }
131
addParameter(const QString & name,const QString & type)132 void FakeMetaMethod::addParameter(const QString &name, const QString &type)
133 { m_paramNames.append(name); m_paramTypes.append(type); }
134
methodType() const135 int FakeMetaMethod::methodType() const
136 { return m_methodTy; }
137
setMethodType(int methodType)138 void FakeMetaMethod::setMethodType(int methodType)
139 { m_methodTy = methodType; }
140
access() const141 int FakeMetaMethod::access() const
142 { return m_methodAccess; }
143
revision() const144 int FakeMetaMethod::revision() const
145 { return m_revision; }
146
setRevision(int r)147 void FakeMetaMethod::setRevision(int r)
148 { m_revision = r; }
149
addToHash(QCryptographicHash & hash) const150 void FakeMetaMethod::addToHash(QCryptographicHash &hash) const
151 {
152 int len = m_name.size();
153 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
154 hash.addData(reinterpret_cast<const char *>(m_name.constData()), len * sizeof(QChar));
155 hash.addData(reinterpret_cast<const char *>(&m_methodAccess), sizeof(m_methodAccess));
156 hash.addData(reinterpret_cast<const char *>(&m_methodTy), sizeof(m_methodTy));
157 hash.addData(reinterpret_cast<const char *>(&m_revision), sizeof(m_revision));
158 len = m_paramNames.size();
159 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
160 foreach (const QString &pName, m_paramNames) {
161 len = pName.size();
162 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
163 hash.addData(reinterpret_cast<const char *>(pName.constData()), len * sizeof(QChar));
164 }
165 len = m_paramTypes.size();
166 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
167 foreach (const QString &pType, m_paramTypes) {
168 len = pType.size();
169 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
170 hash.addData(reinterpret_cast<const char *>(pType.constData()), len * sizeof(QChar));
171 }
172 len = m_returnType.size();
173 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
174 hash.addData(reinterpret_cast<const char *>(m_returnType.constData()), len * sizeof(QChar));
175 }
176
describe(int baseIndent) const177 QString FakeMetaMethod::describe(int baseIndent) const
178 {
179 QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
180 QString res = QLatin1String("Method {");
181 res += newLine;
182 res += QLatin1String(" methodName:");
183 res += methodName();
184 res += newLine;
185 res += QLatin1String(" methodType:");
186 res += methodType();
187 res += newLine;
188 res += QLatin1String(" parameterNames:[");
189 foreach (const QString &pName, parameterNames()) {
190 res += newLine;
191 res += QLatin1String(" ");
192 res += pName;
193 }
194 res += QLatin1Char(']');
195 res += newLine;
196 res += QLatin1String(" parameterTypes:[");
197 foreach (const QString &pType, parameterTypes()) {
198 res += newLine;
199 res += QLatin1String(" ");
200 res += pType;
201 }
202 res += QLatin1Char(']');
203 res += newLine;
204 res += QLatin1Char('}');
205 return res;
206 }
207
toString() const208 QString FakeMetaMethod::toString() const
209 {
210 return describe();
211 }
212
213
FakeMetaProperty(const QString & name,const QString & type,bool isList,bool isWritable,bool isPointer,int revision)214 FakeMetaProperty::FakeMetaProperty(const QString &name, const QString &type, bool isList,
215 bool isWritable, bool isPointer, int revision)
216 : m_propertyName(name)
217 , m_type(type)
218 , m_isList(isList)
219 , m_isWritable(isWritable)
220 , m_isPointer(isPointer)
221 , m_revision(revision)
222 {}
223
name() const224 QString FakeMetaProperty::name() const
225 { return m_propertyName; }
226
typeName() const227 QString FakeMetaProperty::typeName() const
228 { return m_type; }
229
isList() const230 bool FakeMetaProperty::isList() const
231 { return m_isList; }
232
isWritable() const233 bool FakeMetaProperty::isWritable() const
234 { return m_isWritable; }
235
isPointer() const236 bool FakeMetaProperty::isPointer() const
237 { return m_isPointer; }
238
revision() const239 int FakeMetaProperty::revision() const
240 { return m_revision; }
241
addToHash(QCryptographicHash & hash) const242 void FakeMetaProperty::addToHash(QCryptographicHash &hash) const
243 {
244 int len = m_propertyName.size();
245 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
246 hash.addData(reinterpret_cast<const char *>(m_propertyName.constData()), len * sizeof(QChar));
247 hash.addData(reinterpret_cast<const char *>(&m_revision), sizeof(m_revision));
248 int flags = (m_isList ? (1 << 0) : 0)
249 + (m_isPointer ? (1 << 1) : 0)
250 + (m_isWritable ? (1 << 2) : 0);
251 hash.addData(reinterpret_cast<const char *>(&flags), sizeof(flags));
252 len = m_type.size();
253 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
254 hash.addData(reinterpret_cast<const char *>(m_type.constData()), len * sizeof(QChar));
255 }
256
describe(int baseIndent) const257 QString FakeMetaProperty::describe(int baseIndent) const
258 {
259 auto boolStr = [] (bool v) { return v ? QLatin1String("true") : QLatin1String("false"); };
260 QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
261 QString res = QLatin1String("Property {");
262 res += newLine;
263 res += QLatin1String(" name:");
264 res += name();
265 res += newLine;
266 res += QLatin1String(" typeName:");
267 res += typeName();
268 res += newLine;
269 res += QLatin1String(" typeName:");
270 res += QString::number(revision());
271 res += newLine;
272 res += QLatin1String(" isList:");
273 res += boolStr(isList());
274 res += newLine;
275 res += QLatin1String(" isPointer:");
276 res += boolStr(isPointer());
277 res += newLine;
278 res += QLatin1String(" isWritable:");
279 res += boolStr(isWritable());
280 res += newLine;
281 res += QLatin1Char('}');
282 return res;
283 }
284
toString() const285 QString FakeMetaProperty::toString() const
286 {
287 return describe();
288 }
289
290
FakeMetaObject()291 FakeMetaObject::FakeMetaObject() : m_isSingleton(false), m_isCreatable(true), m_isComposite(false)
292 {
293 }
294
className() const295 QString FakeMetaObject::className() const
296 { return m_className; }
setClassName(const QString & name)297 void FakeMetaObject::setClassName(const QString &name)
298 { m_className = name; }
299
addExport(const QString & name,const QString & package,ComponentVersion version)300 void FakeMetaObject::addExport(const QString &name, const QString &package, ComponentVersion version)
301 {
302 Export exp;
303 exp.type = name;
304 exp.package = package;
305 exp.version = version;
306 m_exports.append(exp);
307 }
308
setExportMetaObjectRevision(int exportIndex,int metaObjectRevision)309 void FakeMetaObject::setExportMetaObjectRevision(int exportIndex, int metaObjectRevision)
310 {
311 m_exports[exportIndex].metaObjectRevision = metaObjectRevision;
312 }
313
exports() const314 QList<FakeMetaObject::Export> FakeMetaObject::exports() const
315 { return m_exports; }
exportInPackage(const QString & package) const316 FakeMetaObject::Export FakeMetaObject::exportInPackage(const QString &package) const
317 {
318 foreach (const Export &exp, m_exports) {
319 if (exp.package == package)
320 return exp;
321 }
322 return Export();
323 }
324
setSuperclassName(const QString & superclass)325 void FakeMetaObject::setSuperclassName(const QString &superclass)
326 { m_superName = superclass; }
superclassName() const327 QString FakeMetaObject::superclassName() const
328 { return m_superName; }
329
addEnum(const FakeMetaEnum & fakeEnum)330 void FakeMetaObject::addEnum(const FakeMetaEnum &fakeEnum)
331 { m_enumNameToIndex.insert(fakeEnum.name(), m_enums.size()); m_enums.append(fakeEnum); }
enumeratorCount() const332 int FakeMetaObject::enumeratorCount() const
333 { return m_enums.size(); }
enumeratorOffset() const334 int FakeMetaObject::enumeratorOffset() const
335 { return 0; }
enumerator(int index) const336 FakeMetaEnum FakeMetaObject::enumerator(int index) const
337 { return m_enums.at(index); }
enumeratorIndex(const QString & name) const338 int FakeMetaObject::enumeratorIndex(const QString &name) const
339 { return m_enumNameToIndex.value(name, -1); }
340
addProperty(const FakeMetaProperty & property)341 void FakeMetaObject::addProperty(const FakeMetaProperty &property)
342 { m_propNameToIdx.insert(property.name(), m_props.size()); m_props.append(property); }
propertyCount() const343 int FakeMetaObject::propertyCount() const
344 { return m_props.size(); }
propertyOffset() const345 int FakeMetaObject::propertyOffset() const
346 { return 0; }
property(int index) const347 FakeMetaProperty FakeMetaObject::property(int index) const
348 { return m_props.at(index); }
propertyIndex(const QString & name) const349 int FakeMetaObject::propertyIndex(const QString &name) const
350 { return m_propNameToIdx.value(name, -1); }
351
addMethod(const FakeMetaMethod & method)352 void FakeMetaObject::addMethod(const FakeMetaMethod &method)
353 { m_methods.append(method); }
methodCount() const354 int FakeMetaObject::methodCount() const
355 { return m_methods.size(); }
methodOffset() const356 int FakeMetaObject::methodOffset() const
357 { return 0; }
method(int index) const358 FakeMetaMethod FakeMetaObject::method(int index) const
359 { return m_methods.at(index); }
methodIndex(const QString & name) const360 int FakeMetaObject::methodIndex(const QString &name) const //If performances becomes an issue, just use a nameToIdx hash
361 {
362 for (int i=0; i<m_methods.count(); i++)
363 if (m_methods[i].methodName() == name)
364 return i;
365 return -1;
366 }
367
defaultPropertyName() const368 QString FakeMetaObject::defaultPropertyName() const
369 { return m_defaultPropertyName; }
setDefaultPropertyName(const QString & defaultPropertyName)370 void FakeMetaObject::setDefaultPropertyName(const QString &defaultPropertyName)
371 { m_defaultPropertyName = defaultPropertyName; }
372
attachedTypeName() const373 QString FakeMetaObject::attachedTypeName() const
374 { return m_attachedTypeName; }
setAttachedTypeName(const QString & name)375 void FakeMetaObject::setAttachedTypeName(const QString &name)
376 { m_attachedTypeName = name; }
377
calculateFingerprint() const378 QByteArray FakeMetaObject::calculateFingerprint() const
379 {
380 QCryptographicHash hash(QCryptographicHash::Sha1);
381 int len = m_className.size();
382 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
383 hash.addData(reinterpret_cast<const char *>(m_className.constData()), len * sizeof(QChar));
384 len = m_attachedTypeName.size();
385 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
386 hash.addData(reinterpret_cast<const char *>(m_attachedTypeName.constData()), len * sizeof(QChar));
387 len = m_defaultPropertyName.size();
388 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
389 hash.addData(reinterpret_cast<const char *>(m_defaultPropertyName.constData()), len * sizeof(QChar));
390 len = m_enumNameToIndex.size();
391 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
392 {
393 QStringList keys(m_enumNameToIndex.keys());
394 keys.sort();
395 foreach (const QString &key, keys) {
396 len = key.size();
397 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
398 hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
399 int value = m_enumNameToIndex.value(key);
400 hash.addData(reinterpret_cast<const char *>(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint...
401 m_enums.at(value).addToHash(hash);
402 }
403 }
404 len = m_exports.size();
405 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
406 foreach (const Export &e, m_exports)
407 e.addToHash(hash); // normalize order?
408 len = m_exports.size();
409 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
410 foreach (const FakeMetaMethod &m, m_methods)
411 m.addToHash(hash); // normalize order?
412 {
413 QStringList keys(m_propNameToIdx.keys());
414 keys.sort();
415 foreach (const QString &key, keys) {
416 len = key.size();
417 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
418 hash.addData(reinterpret_cast<const char *>(key.constData()), len * sizeof(QChar));
419 int value = m_propNameToIdx.value(key);
420 hash.addData(reinterpret_cast<const char *>(&value), sizeof(value)); // avoid? this adds order dependency to fingerprint...
421 m_props.at(value).addToHash(hash);
422 }
423 }
424 len = m_superName.size();
425 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
426 hash.addData(reinterpret_cast<const char *>(m_superName.constData()), len * sizeof(QChar));
427
428 QByteArray res = hash.result();
429 res.append('F');
430 return res;
431 }
432
updateFingerprint()433 void FakeMetaObject::updateFingerprint()
434 {
435 m_fingerprint = calculateFingerprint();
436 }
437
fingerprint() const438 QByteArray FakeMetaObject::fingerprint() const
439 {
440 return m_fingerprint;
441 }
442
isSingleton() const443 bool FakeMetaObject::isSingleton() const
444 {
445 return m_isSingleton;
446 }
447
isCreatable() const448 bool FakeMetaObject::isCreatable() const
449 {
450 return m_isCreatable;
451 }
452
isComposite() const453 bool FakeMetaObject::isComposite() const
454 {
455 return m_isComposite;
456 }
457
setIsSingleton(bool value)458 void FakeMetaObject::setIsSingleton(bool value)
459 {
460 m_isSingleton = value;
461 }
462
setIsCreatable(bool value)463 void FakeMetaObject::setIsCreatable(bool value)
464 {
465 m_isCreatable = value;
466 }
467
setIsComposite(bool value)468 void FakeMetaObject::setIsComposite(bool value)
469 {
470 m_isSingleton = value;
471 }
472
toString() const473 QString FakeMetaObject::toString() const
474 {
475 return describe();
476 }
477
describe(bool printDetails,int baseIndent) const478 QString FakeMetaObject::describe(bool printDetails, int baseIndent) const
479 {
480 QString res = QString::fromLatin1("FakeMetaObject@%1")
481 .arg((quintptr)(void *)this, 0, 16);
482 if (!printDetails)
483 return res;
484 auto boolStr = [] (bool v) { return v ? QLatin1String("true") : QLatin1String("false"); };
485 QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
486 res += QLatin1Char('{');
487 res += newLine;
488 res += QLatin1String("className:");
489 res += className();
490 res += newLine;
491 res += QLatin1String("superClassName:");
492 res += superclassName();
493 res += newLine;
494 res += QLatin1String("isSingleton:");
495 res += boolStr(isSingleton());
496 res += newLine;
497 res += QLatin1String("isCreatable:");
498 res += boolStr(isCreatable());
499 res += newLine;
500 res += QLatin1String("isComposite:");
501 res += boolStr(isComposite());
502 res += newLine;
503 res += QLatin1String("defaultPropertyName:");
504 res += defaultPropertyName();
505 res += newLine;
506 res += QLatin1String("attachedTypeName:");
507 res += attachedTypeName();
508 res += newLine;
509 res += QLatin1String("fingerprint:");
510 res += QString::fromUtf8(fingerprint());
511
512 res += newLine;
513 res += QLatin1String("exports:[");
514 foreach (const Export &e, exports()) {
515 res += newLine;
516 res += QLatin1String(" ");
517 res += e.describe(baseIndent + 2);
518 }
519 res += QLatin1Char(']');
520
521 res += newLine;
522 res += QLatin1String("enums:[");
523 for (int iEnum = 0; iEnum < enumeratorCount() ; ++ iEnum) {
524 FakeMetaEnum e = enumerator(enumeratorOffset() + iEnum);
525 res += newLine;
526 res += QLatin1String(" ");
527 res += e.describe(baseIndent + 2);
528 }
529 res += QLatin1Char(']');
530
531 res += newLine;
532 res += QLatin1String("properties:[");
533 for (int iProp = 0; iProp < propertyCount() ; ++ iProp) {
534 FakeMetaProperty prop = property(propertyOffset() + iProp);
535 res += newLine;
536 res += QLatin1String(" ");
537 res += prop.describe(baseIndent + 2);
538 }
539 res += QLatin1Char(']');
540 res += QLatin1String("methods:[");
541 for (int iMethod = 0; iMethod < methodOffset() ; ++ iMethod) {
542 FakeMetaMethod m = method(methodOffset() + iMethod);
543 res += newLine;
544 res += QLatin1String(" ");
545 m.describe(baseIndent + 2);
546 }
547 res += QLatin1Char(']');
548 res += newLine;
549 res += QLatin1Char('}');
550 return res;
551 }
552
Export()553 FakeMetaObject::Export::Export()
554 : metaObjectRevision(0)
555 {}
isValid() const556 bool FakeMetaObject::Export::isValid() const
557 { return version.isValid() || !package.isEmpty() || !type.isEmpty(); }
558
addToHash(QCryptographicHash & hash) const559 void FakeMetaObject::Export::addToHash(QCryptographicHash &hash) const
560 {
561 int len = package.size();
562 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
563 hash.addData(reinterpret_cast<const char *>(package.constData()), len * sizeof(QChar));
564 len = type.size();
565 hash.addData(reinterpret_cast<const char *>(&len), sizeof(len));
566 hash.addData(reinterpret_cast<const char *>(type.constData()), len * sizeof(QChar));
567 version.addToHash(hash);
568 hash.addData(reinterpret_cast<const char *>(&metaObjectRevision), sizeof(metaObjectRevision));
569 }
570
describe(int baseIndent) const571 QString FakeMetaObject::Export::describe(int baseIndent) const
572 {
573 QString newLine = QString::fromLatin1("\n") + QString::fromLatin1(" ").repeated(baseIndent);
574 QString res = QLatin1String("Export {");
575 res += newLine;
576 res += QLatin1String(" package:");
577 res += package;
578 res += newLine;
579 res += QLatin1String(" type:");
580 res += type;
581 res += newLine;
582 res += QLatin1String(" version:");
583 res += version.toString();
584 res += newLine;
585 res += QLatin1String(" metaObjectRevision:");
586 res += QString::number(metaObjectRevision);
587 res += newLine;
588 res += QLatin1String(" isValid:");
589 res += QString::number(isValid());
590 res += newLine;
591 res += QLatin1Char('}');
592 return res;
593 }
594
toString() const595 QString FakeMetaObject::Export::toString() const
596 {
597 return describe();
598 }
599