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