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 #pragma once
27
28 #include <qmljs/qmljs_global.h>
29 #include <qmljs/qmljsconstants.h>
30 #include <qmljs/qmljsimportdependencies.h>
31 #include <qmljs/parser/qmljsastfwd_p.h>
32
33 #include <languageutils/fakemetaobject.h>
34
35 #include <QFileInfoList>
36 #include <QHash>
37 #include <QList>
38 #include <QMutex>
39 #include <QSet>
40 #include <QSharedPointer>
41 #include <QString>
42
43 namespace QmlJS {
44 ////////////////////////////////////////////////////////////////////////////////
45 // Forward declarations
46 ////////////////////////////////////////////////////////////////////////////////
47 class ASTFunctionValue;
48 class ASTObjectValue;
49 class ASTPropertyReference;
50 class ASTSignal;
51 class ASTVariableReference;
52 class AnchorLineValue;
53 class BooleanValue;
54 class ColorValue;
55 class Context;
56 class CppComponentValue;
57 class Document;
58 class Function;
59 class FunctionValue;
60 class Imports;
61 class IntValue;
62 class JSImportScope;
63 class NameId;
64 class NullValue;
65 class NumberValue;
66 class ModuleApiInfo;
67 class ObjectValue;
68 class QmlEnumValue;
69 class QmlPrototypeReference;
70 class RealValue;
71 class Reference;
72 class ReferenceContext;
73 class StringValue;
74 class TypeScope;
75 class UndefinedValue;
76 class UnknownValue;
77 class UrlValue;
78 class Value;
79 class ValueOwner;
80 class MetaFunction;
81 typedef QSharedPointer<const Context> ContextPtr;
82
83 namespace Internal {
84 class QtObjectPrototypeReference;
85 } // namespace Internal
86
87 typedef QList<const Value *> ValueList;
88
89 ////////////////////////////////////////////////////////////////////////////////
90 // Value visitor
91 ////////////////////////////////////////////////////////////////////////////////
92 class QMLJS_EXPORT ValueVisitor
93 {
94 public:
95 ValueVisitor();
96 virtual ~ValueVisitor();
97
98 virtual void visit(const NullValue *);
99 virtual void visit(const UndefinedValue *);
100 virtual void visit(const UnknownValue *);
101 virtual void visit(const NumberValue *);
102 virtual void visit(const BooleanValue *);
103 virtual void visit(const StringValue *);
104 virtual void visit(const ObjectValue *);
105 virtual void visit(const FunctionValue *);
106 virtual void visit(const Reference *);
107 virtual void visit(const ColorValue *);
108 virtual void visit(const AnchorLineValue *);
109 };
110
111 ////////////////////////////////////////////////////////////////////////////////
112 // QML/JS value
113 ////////////////////////////////////////////////////////////////////////////////
114 class QMLJS_EXPORT Value
115 {
116 Value(const Value &other);
117 void operator = (const Value &other);
118
119 public:
120 Value();
121 virtual ~Value();
122
123 virtual const NullValue *asNullValue() const;
124 virtual const UndefinedValue *asUndefinedValue() const;
125 virtual const UnknownValue *asUnknownValue() const;
126 virtual const NumberValue *asNumberValue() const;
127 virtual const IntValue *asIntValue() const;
128 virtual const RealValue *asRealValue() const;
129 virtual const BooleanValue *asBooleanValue() const;
130 virtual const StringValue *asStringValue() const;
131 virtual const UrlValue *asUrlValue() const;
132 virtual const ObjectValue *asObjectValue() const;
133 virtual const FunctionValue *asFunctionValue() const;
134 virtual const Reference *asReference() const;
135 virtual const ColorValue *asColorValue() const;
136 virtual const AnchorLineValue *asAnchorLineValue() const;
137 virtual const CppComponentValue *asCppComponentValue() const;
138 virtual const ASTObjectValue *asAstObjectValue() const;
139 virtual const QmlEnumValue *asQmlEnumValue() const;
140 virtual const QmlPrototypeReference *asQmlPrototypeReference() const;
141 virtual const ASTPropertyReference *asAstPropertyReference() const;
142 virtual const ASTVariableReference *asAstVariableReference() const;
143 virtual const Internal::QtObjectPrototypeReference *asQtObjectPrototypeReference() const;
144 virtual const ASTSignal *asAstSignal() const;
145 virtual const ASTFunctionValue *asAstFunctionValue() const;
146 virtual const Function *asFunction() const;
147 virtual const MetaFunction *asMetaFunction() const;
148 virtual const JSImportScope *asJSImportScope() const;
149 virtual const TypeScope *asTypeScope() const;
150
151 virtual void accept(ValueVisitor *) const = 0;
152
153 virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
154 };
155
value_cast(const Value *)156 template <typename RetTy> const RetTy *value_cast(const Value *)
157 {
158 // Produce a good error message if a specialization is missing.
159 RetTy::ERROR_MissingValueCastSpecialization();
160 return 0;
161 }
162
value_cast(const Value * v)163 template <> Q_INLINE_TEMPLATE const NullValue *value_cast(const Value *v)
164 {
165 if (v) return v->asNullValue();
166 else return 0;
167 }
168
value_cast(const Value * v)169 template <> Q_INLINE_TEMPLATE const UndefinedValue *value_cast(const Value *v)
170 {
171 if (v) return v->asUndefinedValue();
172 else return 0;
173 }
174
value_cast(const Value * v)175 template <> Q_INLINE_TEMPLATE const UnknownValue *value_cast(const Value *v)
176 {
177 if (v) return v->asUnknownValue();
178 else return 0;
179 }
180
value_cast(const Value * v)181 template <> Q_INLINE_TEMPLATE const NumberValue *value_cast(const Value *v)
182 {
183 if (v) return v->asNumberValue();
184 else return 0;
185 }
186
value_cast(const Value * v)187 template <> Q_INLINE_TEMPLATE const IntValue *value_cast(const Value *v)
188 {
189 if (v) return v->asIntValue();
190 else return 0;
191 }
192
value_cast(const Value * v)193 template <> Q_INLINE_TEMPLATE const RealValue *value_cast(const Value *v)
194 {
195 if (v) return v->asRealValue();
196 else return 0;
197 }
198
value_cast(const Value * v)199 template <> Q_INLINE_TEMPLATE const BooleanValue *value_cast(const Value *v)
200 {
201 if (v) return v->asBooleanValue();
202 else return 0;
203 }
204
value_cast(const Value * v)205 template <> Q_INLINE_TEMPLATE const StringValue *value_cast(const Value *v)
206 {
207 if (v) return v->asStringValue();
208 else return 0;
209 }
210
value_cast(const Value * v)211 template <> Q_INLINE_TEMPLATE const UrlValue *value_cast(const Value *v)
212 {
213 if (v) return v->asUrlValue();
214 else return 0;
215 }
216
value_cast(const Value * v)217 template <> Q_INLINE_TEMPLATE const ObjectValue *value_cast(const Value *v)
218 {
219 if (v) return v->asObjectValue();
220 else return 0;
221 }
222
value_cast(const Value * v)223 template <> Q_INLINE_TEMPLATE const ASTFunctionValue *value_cast(const Value *v)
224 {
225 if (v) return v->asAstFunctionValue();
226 else return 0;
227 }
228
value_cast(const Value * v)229 template <> Q_INLINE_TEMPLATE const FunctionValue *value_cast(const Value *v)
230 {
231 if (v) return v->asFunctionValue();
232 else return 0;
233 }
234
value_cast(const Value * v)235 template <> Q_INLINE_TEMPLATE const Reference *value_cast(const Value *v)
236 {
237 if (v) return v->asReference();
238 else return 0;
239 }
240
value_cast(const Value * v)241 template <> Q_INLINE_TEMPLATE const ColorValue *value_cast(const Value *v)
242 {
243 if (v) return v->asColorValue();
244 else return 0;
245 }
246
value_cast(const Value * v)247 template <> Q_INLINE_TEMPLATE const AnchorLineValue *value_cast(const Value *v)
248 {
249 if (v) return v->asAnchorLineValue();
250 else return 0;
251 }
252
value_cast(const Value * v)253 template <> Q_INLINE_TEMPLATE const CppComponentValue *value_cast(const Value *v)
254 {
255 if (v) return v->asCppComponentValue();
256 else return 0;
257 }
258
value_cast(const Value * v)259 template <> Q_INLINE_TEMPLATE const ASTObjectValue *value_cast(const Value *v)
260 {
261 if (v) return v->asAstObjectValue();
262 else return 0;
263 }
264
value_cast(const Value * v)265 template <> Q_INLINE_TEMPLATE const QmlEnumValue *value_cast(const Value *v)
266 {
267 if (v) return v->asQmlEnumValue();
268 else return 0;
269 }
270
value_cast(const Value * v)271 template <> Q_INLINE_TEMPLATE const QmlPrototypeReference *value_cast(const Value *v)
272 {
273 if (v) return v->asQmlPrototypeReference();
274 else return 0;
275 }
276
value_cast(const Value * v)277 template <> Q_INLINE_TEMPLATE const ASTPropertyReference *value_cast(const Value *v)
278 {
279 if (v) return v->asAstPropertyReference();
280 else return 0;
281 }
282
value_cast(const Value * v)283 template <> Q_INLINE_TEMPLATE const Internal::QtObjectPrototypeReference *value_cast(const Value *v)
284 {
285 if (v) return v->asQtObjectPrototypeReference();
286 else return 0;
287 }
288
value_cast(const Value * v)289 template <> Q_INLINE_TEMPLATE const ASTVariableReference *value_cast(const Value *v)
290 {
291 if (v) return v->asAstVariableReference();
292 else return 0;
293 }
294
value_cast(const Value * v)295 template <> Q_INLINE_TEMPLATE const Function *value_cast(const Value *v)
296 {
297 if (v) return v->asFunction();
298 else return 0;
299 }
300
value_cast(const Value * v)301 template <> Q_INLINE_TEMPLATE const MetaFunction *value_cast(const Value *v)
302 {
303 if (v) return v->asMetaFunction();
304 else return 0;
305 }
306
value_cast(const Value * v)307 template <> Q_INLINE_TEMPLATE const JSImportScope *value_cast(const Value *v)
308 {
309 if (v) return v->asJSImportScope();
310 else return 0;
311 }
312
value_cast(const Value * v)313 template <> Q_INLINE_TEMPLATE const TypeScope *value_cast(const Value *v)
314 {
315 if (v) return v->asTypeScope();
316 else return 0;
317 }
318
value_cast(const Value * v)319 template <> Q_INLINE_TEMPLATE const ASTSignal *value_cast(const Value *v)
320 {
321 if (v) return v->asAstSignal();
322 else return 0;
323 }
324
325 ////////////////////////////////////////////////////////////////////////////////
326 // Value nodes
327 ////////////////////////////////////////////////////////////////////////////////
328 class QMLJS_EXPORT NullValue: public Value
329 {
330 public:
331 const NullValue *asNullValue() const override;
332 void accept(ValueVisitor *visitor) const override;
333 };
334
335 class QMLJS_EXPORT UndefinedValue: public Value
336 {
337 public:
338 const UndefinedValue *asUndefinedValue() const override;
339 void accept(ValueVisitor *visitor) const override;
340 };
341
342 class QMLJS_EXPORT UnknownValue: public Value
343 {
344 public:
345 const UnknownValue *asUnknownValue() const override;
346 void accept(ValueVisitor *) const override;
347 };
348
349 class QMLJS_EXPORT NumberValue: public Value
350 {
351 public:
352 const NumberValue *asNumberValue() const override;
353 void accept(ValueVisitor *visitor) const override;
354 };
355
356 class QMLJS_EXPORT RealValue: public NumberValue
357 {
358 public:
359 const RealValue *asRealValue() const override;
360 };
361
362 class QMLJS_EXPORT IntValue: public NumberValue
363 {
364 public:
365 const IntValue *asIntValue() const override;
366 };
367
368 class QMLJS_EXPORT BooleanValue: public Value
369 {
370 public:
371 const BooleanValue *asBooleanValue() const override;
372 void accept(ValueVisitor *visitor) const override;
373 };
374
375 class QMLJS_EXPORT StringValue: public Value
376 {
377 public:
378 const StringValue *asStringValue() const override;
379 void accept(ValueVisitor *visitor) const override;
380 };
381
382 class QMLJS_EXPORT UrlValue: public StringValue
383 {
384 public:
385 const UrlValue *asUrlValue() const override;
386 };
387
388 class PropertyInfo {
389 public:
390 enum PropertyFlag {
391 Readable = 1,
392 Writeable = 2,
393 ListType = 4,
394 PointerType= 8,
395 ValueType = 16,
396 PointerOrValue = PointerType|ValueType,
397 Default = Readable|Writeable|PointerOrValue
398 };
399
400 PropertyInfo(uint flags = Default);
401 uint flags;
isPointer()402 bool isPointer() const {
403 return (flags & PointerOrValue) == PointerType;
404 }
isValue()405 bool isValue() const {
406 return (flags & PointerOrValue) == ValueType;
407 }
canBePointer()408 bool canBePointer() const {
409 return (flags & PointerType) != 0;
410 }
canBeValue()411 bool canBeValue() const {
412 return (flags & ValueType) != 0;
413 }
isReadable()414 bool isReadable() const {
415 return (flags & Readable) != 0;
416 }
isWriteable()417 bool isWriteable() const {
418 return (flags & Writeable) != 0;
419 }
isList()420 bool isList() const {
421 return (flags & ListType) != 0;
422 }
423 QString toString() const;
424 };
425
426 class QMLJS_EXPORT MemberProcessor
427 {
428 MemberProcessor(const MemberProcessor &other);
429 void operator = (const MemberProcessor &other);
430
431 public:
432 MemberProcessor();
433 virtual ~MemberProcessor();
434
435 // Returns false to stop the processor.
436 virtual bool processProperty(const QString &name, const Value *value,
437 const PropertyInfo &propertyInfo);
438 virtual bool processEnumerator(const QString &name, const Value *value);
439 virtual bool processSignal(const QString &name, const Value *value);
440 virtual bool processSlot(const QString &name, const Value *value);
441 virtual bool processGeneratedSlot(const QString &name, const Value *value);
442 };
443
444 class QMLJS_EXPORT Reference: public Value
445 {
446 public:
447 Reference(ValueOwner *valueOwner);
448 ~Reference();
449
450 ValueOwner *valueOwner() const;
451
452 // Value interface
453 const Reference *asReference() const override;
454 void accept(ValueVisitor *) const override;
455
456 private:
457 virtual const Value *value(ReferenceContext *referenceContext) const;
458
459 ValueOwner *m_valueOwner;
460 friend class ReferenceContext;
461 };
462
463 class QMLJS_EXPORT ColorValue: public Value
464 {
465 public:
466 // Value interface
467 const ColorValue *asColorValue() const override;
468 void accept(ValueVisitor *) const override;
469 };
470
471 class QMLJS_EXPORT AnchorLineValue: public Value
472 {
473 public:
474 // Value interface
475 const AnchorLineValue *asAnchorLineValue() const override;
476 void accept(ValueVisitor *) const override;
477 };
478
479 class QMLJS_EXPORT PropertyData {
480 public:
481 const Value *value;
482 PropertyInfo propertyInfo;
483 PropertyData(const Value *value = 0,
484 PropertyInfo propertyInfo = PropertyInfo(PropertyInfo::Default))
value(value)485 : value(value), propertyInfo(propertyInfo)
486 { }
487 };
488
489 class QMLJS_EXPORT ObjectValue: public Value
490 {
491 public:
492 ObjectValue(ValueOwner *valueOwner, const QString &originId = QString());
493 ~ObjectValue();
494
495 ValueOwner *valueOwner() const;
496
497 QString className() const;
498 void setClassName(const QString &className);
499
500 // may return a reference, prototypes may form a cycle: use PrototypeIterator!
501 const Value *prototype() const;
502 // prototypes may form a cycle: use PrototypeIterator!
503 const ObjectValue *prototype(const Context *context) const;
prototype(const ContextPtr & context)504 const ObjectValue *prototype(const ContextPtr &context) const
505 { return prototype(context.data()); }
506 void setPrototype(const Value *prototype);
507
508 virtual void processMembers(MemberProcessor *processor) const;
509
510 virtual void setMember(const QString &name, const Value *value);
511 virtual void setPropertyInfo(const QString &name, const PropertyInfo &propertyInfo);
512 virtual void removeMember(const QString &name);
513
514 virtual const Value *lookupMember(const QString &name, const Context *context,
515 const ObjectValue **foundInObject = 0,
516 bool examinePrototypes = true) const;
517 virtual const Value *lookupMember(const QString &name, const ContextPtr &context,
518 const ObjectValue **foundInObject = 0,
519 bool examinePrototypes = true) const
520 { return lookupMember(name, context.data(), foundInObject, examinePrototypes); }
521
522 // Value interface
523 const ObjectValue *asObjectValue() const override;
524 void accept(ValueVisitor *visitor) const override;
originId()525 QString originId() const
526 { return m_originId; }
527
528
529 private:
530 bool checkPrototype(const ObjectValue *prototype, QSet<const ObjectValue *> *processed) const;
531
532 private:
533 ValueOwner *m_valueOwner;
534 QHash<QString, PropertyData> m_members;
535 QString m_className;
536 QString m_originId;
537
538 protected:
539 const Value *_prototype;
540 };
541
542 class QMLJS_EXPORT PrototypeIterator
543 {
544 public:
545 enum Error
546 {
547 NoError,
548 ReferenceResolutionError,
549 CycleError
550 };
551
552 PrototypeIterator(const ObjectValue *start, const Context *context);
553 PrototypeIterator(const ObjectValue *start, const ContextPtr &context);
554
555 bool hasNext();
556 const ObjectValue *peekNext();
557 const ObjectValue *next();
558 Error error() const;
559
560 QList<const ObjectValue *> all();
561
562 private:
563 const ObjectValue *m_current;
564 const ObjectValue *m_next;
565 QList<const ObjectValue *> m_prototypes;
566 const Context *m_context;
567 Error m_error;
568 };
569
570 class QMLJS_EXPORT QmlEnumValue: public NumberValue
571 {
572 public:
573 QmlEnumValue(const CppComponentValue *owner, int index);
574 ~QmlEnumValue();
575
576 const QmlEnumValue *asQmlEnumValue() const override;
577
578 QString name() const;
579 QStringList keys() const;
580 const CppComponentValue *owner() const;
581
582 private:
583 const CppComponentValue *m_owner;
584 int m_enumIndex;
585 };
586
587
588 // A ObjectValue based on a FakeMetaObject.
589 // May only have other CppComponentValue as ancestors.
590 class QMLJS_EXPORT CppComponentValue: public ObjectValue
591 {
592 public:
593 CppComponentValue(LanguageUtils::FakeMetaObject::ConstPtr metaObject, const QString &className,
594 const QString &moduleName, const LanguageUtils::ComponentVersion &componentVersion,
595 const LanguageUtils::ComponentVersion &importVersion, int metaObjectRevision,
596 ValueOwner *valueOwner, const QString &originId);
597 ~CppComponentValue();
598
599 const CppComponentValue *asCppComponentValue() const override;
600
601 void processMembers(MemberProcessor *processor) const override;
602 const Value *valueForCppName(const QString &typeName) const;
603
604 using ObjectValue::prototype;
605 const CppComponentValue *prototype() const;
606 QList<const CppComponentValue *> prototypes() const;
607
608 LanguageUtils::FakeMetaObject::ConstPtr metaObject() const;
609
610 QString moduleName() const;
611 LanguageUtils::ComponentVersion componentVersion() const;
612 LanguageUtils::ComponentVersion importVersion() const;
613
614 QString defaultPropertyName() const;
615 QString propertyType(const QString &propertyName) const;
616 bool isListProperty(const QString &name) const;
617 bool isWritable(const QString &propertyName) const;
618 bool isPointer(const QString &propertyName) const;
619 bool hasLocalProperty(const QString &typeName) const;
620 bool hasProperty(const QString &typeName) const;
621
622 LanguageUtils::FakeMetaEnum getEnum(const QString &typeName, const CppComponentValue **foundInScope = 0) const;
623 const QmlEnumValue *getEnumValue(const QString &typeName, const CppComponentValue **foundInScope = 0) const;
624
625 const ObjectValue *signalScope(const QString &signalName) const;
626 protected:
627 bool isDerivedFrom(LanguageUtils::FakeMetaObject::ConstPtr base) const;
628
629 private:
630 LanguageUtils::FakeMetaObject::ConstPtr m_metaObject;
631 const QString m_moduleName;
632 // _componentVersion is the version of the export
633 // _importVersion is the version it's imported as, used to find correct prototypes
634 // needed in cases when B 1.0 has A 1.1 as prototype when imported as 1.1
635 const LanguageUtils::ComponentVersion m_componentVersion;
636 const LanguageUtils::ComponentVersion m_importVersion;
637 mutable QAtomicPointer< QList<const Value *> > m_metaSignatures;
638 mutable QAtomicPointer< QHash<QString, const ObjectValue *> > m_signalScopes;
639 QHash<QString, const QmlEnumValue * > m_enums;
640 int m_metaObjectRevision;
641 };
642
643 class QMLJS_EXPORT FunctionValue: public ObjectValue
644 {
645 public:
646 FunctionValue(ValueOwner *valueOwner);
647 ~FunctionValue();
648
649 virtual const Value *returnValue() const;
650
651 // Access to the names of arguments
652 // Named arguments can be optional (usually known for builtins only)
653 virtual int namedArgumentCount() const;
654 virtual QString argumentName(int index) const;
655
656 // The number of optional named arguments
657 // Example: JSON.stringify(value[, replacer[, space]])
658 // has namedArgumentCount = 3
659 // and optionalNamedArgumentCount = 2
660 virtual int optionalNamedArgumentCount() const;
661
662 // Whether the function accepts an unlimited number of arguments
663 // after the named ones. Defaults to false.
664 // Example: Math.max(...)
665 virtual bool isVariadic() const;
666
667 virtual const Value *argument(int index) const;
668
669 // Value interface
670 const FunctionValue *asFunctionValue() const override;
671 void accept(ValueVisitor *visitor) const override;
672 };
673
674 class QMLJS_EXPORT Function: public FunctionValue
675 {
676 public:
677 Function(ValueOwner *valueOwner);
678 ~Function();
679
680 void addArgument(const Value *argument, const QString &name = QString());
681 void setReturnValue(const Value *returnValue);
682 void setVariadic(bool variadic);
683 void setOptionalNamedArgumentCount(int count);
684
685 // FunctionValue interface
686 const Value *returnValue() const override;
687 int namedArgumentCount() const override;
688 int optionalNamedArgumentCount() const override;
689 const Value *argument(int index) const override;
690 QString argumentName(int index) const override;
691 bool isVariadic() const override;
692 const Function *asFunction() const override;
693
694 private:
695 ValueList m_arguments;
696 QStringList m_argumentNames;
697 const Value *m_returnValue;
698 int m_optionalNamedArgumentCount;
699 bool m_isVariadic;
700 };
701
702
703 ////////////////////////////////////////////////////////////////////////////////
704 // typing environment
705 ////////////////////////////////////////////////////////////////////////////////
706
707 class QMLJS_EXPORT CppQmlTypesLoader
708 {
709 public:
710 typedef QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> BuiltinObjects;
711
712 /** Loads a set of qmltypes files into the builtin objects list
713 and returns errors and warnings
714 */
715 static BuiltinObjects loadQmlTypes(const QFileInfoList &qmltypesFiles,
716 QStringList *errors, QStringList *warnings);
717
718 static BuiltinObjects defaultQtObjects;
719 static BuiltinObjects defaultLibraryObjects;
720
721 // parses the contents of a qmltypes file and fills the newObjects map
722 static void parseQmlTypeDescriptions(const QByteArray &contents,
723 BuiltinObjects *newObjects,
724 QList<ModuleApiInfo> *newModuleApis,
725 QStringList *newDependencies,
726 QString *errorMessage,
727 QString *warningMessage,
728 const QString &fileName);
729 };
730
731 class QMLJS_EXPORT FakeMetaObjectWithOrigin
732 {
733 public:
734 LanguageUtils::FakeMetaObject::ConstPtr fakeMetaObject;
735 QString originId;
736 FakeMetaObjectWithOrigin(LanguageUtils::FakeMetaObject::ConstPtr fakeMetaObject,
737 const QString &originId);
738 bool operator ==(const FakeMetaObjectWithOrigin &o) const;
739 };
740
741 QMLJS_EXPORT uint qHash(const FakeMetaObjectWithOrigin &fmoo);
742
743 class QMLJS_EXPORT CppQmlTypes
744 {
745 public:
746 CppQmlTypes(ValueOwner *valueOwner);
747
748 // package name for objects that should be always available
749 static const QLatin1String defaultPackage;
750 // package name for objects with their raw cpp name
751 static const QLatin1String cppPackage;
752
753 template <typename T>
754 void load(const QString &originId, const T &fakeMetaObjects, const QString &overridePackage = QString());
755
756 QList<const CppComponentValue *> createObjectsForImport(const QString &package, LanguageUtils::ComponentVersion version);
757 bool hasModule(const QString &module) const;
758
759 static QString qualifiedName(const QString &module, const QString &type,
760 LanguageUtils::ComponentVersion version);
761 const CppComponentValue *objectByQualifiedName(const QString &fullyQualifiedName) const;
762 const CppComponentValue *objectByQualifiedName(
763 const QString &package, const QString &type,
764 LanguageUtils::ComponentVersion version) const;
765 const CppComponentValue *objectByCppName(const QString &cppName) const;
766
767 void setCppContextProperties(const ObjectValue *contextProperties);
768 const ObjectValue *cppContextProperties() const;
769
770 private:
771 // "Package.CppName ImportVersion" -> CppComponentValue
772 QHash<QString, const CppComponentValue *> m_objectsByQualifiedName;
773 QHash<QString, QSet<FakeMetaObjectWithOrigin> > m_fakeMetaObjectsByPackage;
774 const ObjectValue *m_cppContextProperties;
775 ValueOwner *m_valueOwner;
776 };
777
778 class ConvertToNumber: protected ValueVisitor // ECMAScript ToInt()
779 {
780 public:
781 ConvertToNumber(ValueOwner *valueOwner);
782
783 const Value *operator()(const Value *value);
784
785 protected:
786 const Value *switchResult(const Value *value);
787
788 void visit(const NullValue *) override;
789 void visit(const UndefinedValue *) override;
790 void visit(const NumberValue *) override;
791 void visit(const BooleanValue *) override;
792 void visit(const StringValue *) override;
793 void visit(const ObjectValue *) override;
794 void visit(const FunctionValue *) override;
795
796 private:
797 ValueOwner *m_valueOwner;
798 const Value *m_result;
799 };
800
801 class ConvertToString: protected ValueVisitor // ECMAScript ToString
802 {
803 public:
804 ConvertToString(ValueOwner *valueOwner);
805
806 const Value *operator()(const Value *value);
807
808 protected:
809 const Value *switchResult(const Value *value);
810
811 void visit(const NullValue *) override;
812 void visit(const UndefinedValue *) override;
813 void visit(const NumberValue *) override;
814 void visit(const BooleanValue *) override;
815 void visit(const StringValue *) override;
816 void visit(const ObjectValue *) override;
817 void visit(const FunctionValue *) override;
818
819 private:
820 ValueOwner *m_valueOwner;
821 const Value *m_result;
822 };
823
824 class ConvertToObject: protected ValueVisitor // ECMAScript ToObject
825 {
826 public:
827 ConvertToObject(ValueOwner *valueOwner);
828
829 const Value *operator()(const Value *value);
830
831 protected:
832 const Value *switchResult(const Value *value);
833
834 void visit(const NullValue *) override;
835 void visit(const UndefinedValue *) override;
836 void visit(const NumberValue *) override;
837 void visit(const BooleanValue *) override;
838 void visit(const StringValue *) override;
839 void visit(const ObjectValue *) override;
840 void visit(const FunctionValue *) override;
841
842 private:
843 ValueOwner *m_valueOwner;
844 const Value *m_result;
845 };
846
847 class QMLJS_EXPORT TypeId: protected ValueVisitor
848 {
849 QString _result;
850
851 public:
852 QString operator()(const Value *value);
853
854 protected:
855 void visit(const NullValue *) override;
856 void visit(const UndefinedValue *) override;
857 void visit(const NumberValue *) override;
858 void visit(const BooleanValue *) override;
859 void visit(const StringValue *) override;
860 void visit(const ObjectValue *object) override;
861 void visit(const FunctionValue *object) override;
862 void visit(const ColorValue *) override;
863 void visit(const AnchorLineValue *) override;
864 };
865
866 // internal
867 class QMLJS_EXPORT QmlPrototypeReference: public Reference
868 {
869 public:
870 QmlPrototypeReference(AST::UiQualifiedId *qmlTypeName, const Document *doc, ValueOwner *valueOwner);
871 ~QmlPrototypeReference();
872
873 const QmlPrototypeReference *asQmlPrototypeReference() const override;
874
875 AST::UiQualifiedId *qmlTypeName() const;
876 const Document *document() const;
877
878 private:
879 const Value *value(ReferenceContext *referenceContext) const override;
880
881 AST::UiQualifiedId *m_qmlTypeName;
882 const Document *m_doc;
883 };
884
885 class QMLJS_EXPORT ASTVariableReference: public Reference
886 {
887 AST::VariableDeclaration *m_ast;
888 const Document *m_doc;
889
890 public:
891 ASTVariableReference(AST::VariableDeclaration *ast, const Document *doc, ValueOwner *valueOwner);
892 ~ASTVariableReference();
893 const ASTVariableReference *asAstVariableReference() const override;
894 const AST::VariableDeclaration *ast() const;
895 private:
896 const Value *value(ReferenceContext *referenceContext) const override;
897 bool getSourceLocation(QString *fileName, int *line, int *column) const override;
898 };
899
900 class QMLJS_EXPORT ASTFunctionValue: public FunctionValue
901 {
902 AST::FunctionExpression *m_ast;
903 const Document *m_doc;
904 QList<QString> m_argumentNames;
905 bool m_isVariadic;
906
907 public:
908 ASTFunctionValue(AST::FunctionExpression *ast, const Document *doc, ValueOwner *valueOwner);
909 ~ASTFunctionValue();
910
911 AST::FunctionExpression *ast() const;
912
913 int namedArgumentCount() const override;
914 QString argumentName(int index) const override;
915 bool isVariadic() const override;
916 const ASTFunctionValue *asAstFunctionValue() const override;
917
918 bool getSourceLocation(QString *fileName, int *line, int *column) const override;
919 };
920
921 class QMLJS_EXPORT ASTPropertyReference: public Reference
922 {
923 AST::UiPublicMember *m_ast;
924 const Document *m_doc;
925 QString m_onChangedSlotName;
926
927 public:
928 ASTPropertyReference(AST::UiPublicMember *ast, const Document *doc, ValueOwner *valueOwner);
929 ~ASTPropertyReference();
930
931 const ASTPropertyReference *asAstPropertyReference() const override;
932
ast()933 AST::UiPublicMember *ast() const { return m_ast; }
onChangedSlotName()934 QString onChangedSlotName() const { return m_onChangedSlotName; }
935
936 bool getSourceLocation(QString *fileName, int *line, int *column) const override;
937
938 private:
939 const Value *value(ReferenceContext *referenceContext) const override;
940 };
941
942 class QMLJS_EXPORT ASTSignal: public FunctionValue
943 {
944 AST::UiPublicMember *m_ast;
945 const Document *m_doc;
946 QString m_slotName;
947 const ObjectValue *m_bodyScope;
948
949 public:
950 ASTSignal(AST::UiPublicMember *ast, const Document *doc, ValueOwner *valueOwner);
951 ~ASTSignal();
952
953 const ASTSignal *asAstSignal() const override;
954
ast()955 AST::UiPublicMember *ast() const { return m_ast; }
slotName()956 QString slotName() const { return m_slotName; }
bodyScope()957 const ObjectValue *bodyScope() const { return m_bodyScope; }
958
959 // FunctionValue interface
960 int namedArgumentCount() const override;
961 const Value *argument(int index) const override;
962 QString argumentName(int index) const override;
963
964 // Value interface
965 bool getSourceLocation(QString *fileName, int *line, int *column) const override;
966 };
967
968 class QMLJS_EXPORT ASTObjectValue: public ObjectValue
969 {
970 AST::UiQualifiedId *m_typeName;
971 AST::UiObjectInitializer *m_initializer;
972 const Document *m_doc;
973 QList<ASTPropertyReference *> m_properties;
974 QList<ASTSignal *> m_signals;
975 ASTPropertyReference *m_defaultPropertyRef;
976
977 public:
978 ASTObjectValue(AST::UiQualifiedId *typeName,
979 AST::UiObjectInitializer *initializer,
980 const Document *doc,
981 ValueOwner *valueOwner);
982 ~ASTObjectValue();
983
984 const ASTObjectValue *asAstObjectValue() const override;
985
986 bool getSourceLocation(QString *fileName, int *line, int *column) const override;
987 void processMembers(MemberProcessor *processor) const override;
988
989 QString defaultPropertyName() const;
990
991 AST::UiObjectInitializer *initializer() const;
992 AST::UiQualifiedId *typeName() const;
993 const Document *document() const;
994 };
995
996 class QMLJS_EXPORT ImportInfo
997 {
998 public:
999 ImportInfo();
1000
1001 static ImportInfo moduleImport(QString uri, LanguageUtils::ComponentVersion version,
1002 const QString &as, AST::UiImport *ast = 0);
1003 static ImportInfo pathImport(const QString &docPath, const QString &path,
1004 LanguageUtils::ComponentVersion version,
1005 const QString &as, AST::UiImport *ast = 0);
1006 static ImportInfo invalidImport(AST::UiImport *ast = 0);
1007 static ImportInfo implicitDirectoryImport(const QString &directory);
1008 static ImportInfo qrcDirectoryImport(const QString &directory);
1009
1010 bool isValid() const;
1011 ImportType::Enum type() const;
1012
1013 // LibraryImport: uri with ',' separator
1014 // Other: non-absolute path
1015 QString name() const;
1016
1017 // LibraryImport: uri with '/' separator
1018 // Other: absoluteFilePath
1019 QString path() const;
1020
1021 // null if the import has no 'as', otherwise the target id
1022 QString as() const;
1023
1024 LanguageUtils::ComponentVersion version() const;
1025 AST::UiImport *ast() const;
1026
1027 private:
1028 ImportType::Enum m_type;
1029 LanguageUtils::ComponentVersion m_version;
1030 QString m_name;
1031 QString m_path;
1032 QString m_as;
1033 AST::UiImport *m_ast;
1034 };
1035
1036 class QMLJS_EXPORT Import {
1037 public:
1038 Import();
1039 Import(const Import &other);
1040
1041 // const!
1042 ObjectValue *object;
1043 ImportInfo info;
1044 DependencyInfo::ConstPtr deps;
1045 // uri imports: path to library, else empty
1046 QString libraryPath;
1047 // whether the import succeeded
1048 bool valid;
1049 mutable bool used;
1050 };
1051
1052 class Imports;
1053
1054 class QMLJS_EXPORT TypeScope: public ObjectValue
1055 {
1056 public:
1057 TypeScope(const Imports *imports, ValueOwner *valueOwner);
1058
1059 virtual const Value *lookupMember(const QString &name, const Context *context,
1060 const ObjectValue **foundInObject = 0,
1061 bool examinePrototypes = true) const override;
1062 void processMembers(MemberProcessor *processor) const override;
1063 const TypeScope *asTypeScope() const override;
1064 private:
1065 const Imports *m_imports;
1066 };
1067
1068 class QMLJS_EXPORT JSImportScope: public ObjectValue
1069 {
1070 public:
1071 JSImportScope(const Imports *imports, ValueOwner *valueOwner);
1072
1073 virtual const Value *lookupMember(const QString &name, const Context *context,
1074 const ObjectValue **foundInObject = 0,
1075 bool examinePrototypes = true) const override;
1076 void processMembers(MemberProcessor *processor) const override;
1077 const JSImportScope *asJSImportScope() const override;
1078 private:
1079 const Imports *m_imports;
1080 };
1081
1082 class QMLJS_EXPORT Imports
1083 {
1084 public:
1085 Imports(ValueOwner *valueOwner);
1086
1087 void append(const Import &import);
1088 void setImportFailed();
1089
1090 ImportInfo info(const QString &name, const Context *context) const;
1091 QString nameForImportedObject(const ObjectValue *value, const Context *context) const;
1092 bool importFailed() const;
1093
1094 const QList<Import> &all() const;
1095
1096 const TypeScope *typeScope() const;
1097 const JSImportScope *jsImportScope() const;
1098
1099 #ifdef QT_DEBUG
1100 void dump() const;
1101 #endif
1102
1103 private:
1104 // holds imports in the order they appeared,
1105 // lookup order is back to front
1106 QList<Import> m_imports;
1107 TypeScope *m_typeScope;
1108 JSImportScope *m_jsImportScope;
1109 bool m_importFailed;
1110 };
1111
1112 class QMLJS_EXPORT MetaFunction: public FunctionValue
1113 {
1114 LanguageUtils::FakeMetaMethod m_method;
1115
1116 public:
1117 MetaFunction(const LanguageUtils::FakeMetaMethod &method, ValueOwner *valueOwner);
1118
1119 int namedArgumentCount() const override;
1120 QString argumentName(int index) const override;
1121 bool isVariadic() const override;
1122 const MetaFunction *asMetaFunction() const override;
1123 const LanguageUtils::FakeMetaMethod &fakeMetaMethod() const;
1124 };
1125
1126 class QMLJS_EXPORT CustomImportsProvider : public QObject
1127 {
1128 Q_OBJECT
1129 public:
1130 explicit CustomImportsProvider(QObject *parent = nullptr);
1131 virtual ~CustomImportsProvider();
1132
1133 static const QList<CustomImportsProvider *> allProviders();
1134
1135 virtual QList<Import> imports(ValueOwner *valueOwner, const Document *context) const = 0;
1136 };
1137
1138 } // namespace QmlJS
1139