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