OSDN Git Service

QmlJS: Support module apis defined by QML modules.
[qt-creator-jp/qt-creator-jp.git] / src / libs / qmljs / qmljsinterpreter.h
1 /**************************************************************************
2 **
3 ** This file is part of Qt Creator
4 **
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6 **
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
8 **
9 **
10 ** GNU Lesser General Public License Usage
11 **
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18 **
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
22 **
23 ** Other Usage
24 **
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
27 **
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at info@qt.nokia.com.
30 **
31 **************************************************************************/
32
33 #ifndef QMLJS_INTERPRETER_H
34 #define QMLJS_INTERPRETER_H
35
36 #include <languageutils/componentversion.h>
37 #include <languageutils/fakemetaobject.h>
38 #include <qmljs/qmljsdocument.h>
39 #include <qmljs/qmljs_global.h>
40 #include <qmljs/parser/qmljsastfwd_p.h>
41
42 #include <QtCore/QFileInfoList>
43 #include <QtCore/QList>
44 #include <QtCore/QString>
45 #include <QtCore/QHash>
46 #include <QtCore/QSet>
47 #include <QtCore/QMutex>
48
49 namespace QmlJS {
50
51 class NameId;
52 class Document;
53
54 ////////////////////////////////////////////////////////////////////////////////
55 // Forward declarations
56 ////////////////////////////////////////////////////////////////////////////////
57 class ValueOwner;
58 class Value;
59 class NullValue;
60 class UndefinedValue;
61 class UnknownValue;
62 class NumberValue;
63 class IntValue;
64 class RealValue;
65 class BooleanValue;
66 class StringValue;
67 class UrlValue;
68 class ObjectValue;
69 class FunctionValue;
70 class Reference;
71 class ColorValue;
72 class AnchorLineValue;
73 class Imports;
74 class TypeScope;
75 class JSImportScope;
76 class Context;
77 typedef QSharedPointer<const Context> ContextPtr;
78 class ReferenceContext;
79 class CppComponentValue;
80 class ASTObjectValue;
81 class QmlEnumValue;
82 class QmlPrototypeReference;
83 class ASTPropertyReference;
84 class ASTSignal;
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 ASTSignal *asAstSignal() const;
142
143     virtual void accept(ValueVisitor *) const = 0;
144
145     virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
146 };
147
148 template <typename _RetTy> const _RetTy *value_cast(const Value *)
149 {
150     // Produce a good error message if a specialization is missing.
151     _RetTy::ERROR_MissingValueCastSpecialization();
152     return 0;
153 }
154
155 template <> Q_INLINE_TEMPLATE const NullValue *value_cast(const Value *v)
156 {
157     if (v) return v->asNullValue();
158     else   return 0;
159 }
160
161 template <> Q_INLINE_TEMPLATE const UndefinedValue *value_cast(const Value *v)
162 {
163     if (v) return v->asUndefinedValue();
164     else   return 0;
165 }
166
167 template <> Q_INLINE_TEMPLATE const UnknownValue *value_cast(const Value *v)
168 {
169     if (v) return v->asUnknownValue();
170     else   return 0;
171 }
172
173 template <> Q_INLINE_TEMPLATE const NumberValue *value_cast(const Value *v)
174 {
175     if (v) return v->asNumberValue();
176     else   return 0;
177 }
178
179 template <> Q_INLINE_TEMPLATE const IntValue *value_cast(const Value *v)
180 {
181     if (v) return v->asIntValue();
182     else   return 0;
183 }
184
185 template <> Q_INLINE_TEMPLATE const RealValue *value_cast(const Value *v)
186 {
187     if (v) return v->asRealValue();
188     else   return 0;
189 }
190
191 template <> Q_INLINE_TEMPLATE const BooleanValue *value_cast(const Value *v)
192 {
193     if (v) return v->asBooleanValue();
194     else   return 0;
195 }
196
197 template <> Q_INLINE_TEMPLATE const StringValue *value_cast(const Value *v)
198 {
199     if (v) return v->asStringValue();
200     else   return 0;
201 }
202
203 template <> Q_INLINE_TEMPLATE const UrlValue *value_cast(const Value *v)
204 {
205     if (v) return v->asUrlValue();
206     else   return 0;
207 }
208
209 template <> Q_INLINE_TEMPLATE const ObjectValue *value_cast(const Value *v)
210 {
211     if (v) return v->asObjectValue();
212     else   return 0;
213 }
214
215 template <> Q_INLINE_TEMPLATE const FunctionValue *value_cast(const Value *v)
216 {
217     if (v) return v->asFunctionValue();
218     else   return 0;
219 }
220
221 template <> Q_INLINE_TEMPLATE const Reference *value_cast(const Value *v)
222 {
223     if (v) return v->asReference();
224     else   return 0;
225 }
226
227 template <> Q_INLINE_TEMPLATE const ColorValue *value_cast(const Value *v)
228 {
229     if (v) return v->asColorValue();
230     else   return 0;
231 }
232
233 template <> Q_INLINE_TEMPLATE const AnchorLineValue *value_cast(const Value *v)
234 {
235     if (v) return v->asAnchorLineValue();
236     else   return 0;
237 }
238
239 template <> Q_INLINE_TEMPLATE const CppComponentValue *value_cast(const Value *v)
240 {
241     if (v) return v->asCppComponentValue();
242     else   return 0;
243 }
244
245 template <> Q_INLINE_TEMPLATE const ASTObjectValue *value_cast(const Value *v)
246 {
247     if (v) return v->asAstObjectValue();
248     else   return 0;
249 }
250
251 template <> Q_INLINE_TEMPLATE const QmlEnumValue *value_cast(const Value *v)
252 {
253     if (v) return v->asQmlEnumValue();
254     else   return 0;
255 }
256
257 template <> Q_INLINE_TEMPLATE const QmlPrototypeReference *value_cast(const Value *v)
258 {
259     if (v) return v->asQmlPrototypeReference();
260     else   return 0;
261 }
262
263 template <> Q_INLINE_TEMPLATE const ASTPropertyReference *value_cast(const Value *v)
264 {
265     if (v) return v->asAstPropertyReference();
266     else   return 0;
267 }
268
269 template <> Q_INLINE_TEMPLATE const ASTSignal *value_cast(const Value *v)
270 {
271     if (v) return v->asAstSignal();
272     else   return 0;
273 }
274
275 ////////////////////////////////////////////////////////////////////////////////
276 // Value nodes
277 ////////////////////////////////////////////////////////////////////////////////
278 class QMLJS_EXPORT NullValue: public Value
279 {
280 public:
281     virtual const NullValue *asNullValue() const;
282     virtual void accept(ValueVisitor *visitor) const;
283 };
284
285 class QMLJS_EXPORT UndefinedValue: public Value
286 {
287 public:
288     virtual const UndefinedValue *asUndefinedValue() const;
289     virtual void accept(ValueVisitor *visitor) const;
290 };
291
292 class QMLJS_EXPORT UnknownValue: public Value
293 {
294 public:
295     virtual const UnknownValue *asUnknownValue() const;
296     virtual void accept(ValueVisitor *) const;
297 };
298
299 class QMLJS_EXPORT NumberValue: public Value
300 {
301 public:
302     virtual const NumberValue *asNumberValue() const;
303     virtual void accept(ValueVisitor *visitor) const;
304 };
305
306 class QMLJS_EXPORT RealValue: public NumberValue
307 {
308 public:
309     virtual const RealValue *asRealValue() const;
310 };
311
312 class QMLJS_EXPORT IntValue: public NumberValue
313 {
314 public:
315     virtual const IntValue *asIntValue() const;
316 };
317
318 class QMLJS_EXPORT BooleanValue: public Value
319 {
320 public:
321     virtual const BooleanValue *asBooleanValue() const;
322     virtual void accept(ValueVisitor *visitor) const;
323 };
324
325 class QMLJS_EXPORT StringValue: public Value
326 {
327 public:
328     virtual const StringValue *asStringValue() const;
329     virtual void accept(ValueVisitor *visitor) const;
330 };
331
332 class QMLJS_EXPORT UrlValue: public StringValue
333 {
334 public:
335     virtual const UrlValue *asUrlValue() const;
336 };
337
338 class QMLJS_EXPORT MemberProcessor
339 {
340     MemberProcessor(const MemberProcessor &other);
341     void operator = (const MemberProcessor &other);
342
343 public:
344     MemberProcessor();
345     virtual ~MemberProcessor();
346
347     // Returns false to stop the processor.
348     virtual bool processProperty(const QString &name, const Value *value);
349     virtual bool processEnumerator(const QString &name, const Value *value);
350     virtual bool processSignal(const QString &name, const Value *value);
351     virtual bool processSlot(const QString &name, const Value *value);
352     virtual bool processGeneratedSlot(const QString &name, const Value *value);
353 };
354
355 class QMLJS_EXPORT Reference: public Value
356 {
357 public:
358     Reference(ValueOwner *valueOwner);
359     virtual ~Reference();
360
361     ValueOwner *valueOwner() const;
362
363     // Value interface
364     virtual const Reference *asReference() const;
365     virtual void accept(ValueVisitor *) const;
366
367 private:
368     virtual const Value *value(ReferenceContext *referenceContext) const;
369
370     ValueOwner *_valueOwner;
371     friend class ReferenceContext;
372 };
373
374 class QMLJS_EXPORT ColorValue: public Value
375 {
376 public:
377     // Value interface
378     virtual const ColorValue *asColorValue() const;
379     virtual void accept(ValueVisitor *) const;
380 };
381
382 class QMLJS_EXPORT AnchorLineValue: public Value
383 {
384 public:
385     // Value interface
386     virtual const AnchorLineValue *asAnchorLineValue() const;
387     virtual void accept(ValueVisitor *) const;
388 };
389
390 class QMLJS_EXPORT ObjectValue: public Value
391 {
392 public:
393     ObjectValue(ValueOwner *valueOwner);
394     virtual ~ObjectValue();
395
396     ValueOwner *valueOwner() const;
397
398     QString className() const;
399     void setClassName(const QString &className);
400
401     // may return a reference, prototypes may form a cycle: use PrototypeIterator!
402     const Value *prototype() const;
403     // prototypes may form a cycle: use PrototypeIterator!
404     const ObjectValue *prototype(const Context *context) const;
405     const ObjectValue *prototype(const ContextPtr &context) const
406     { return prototype(context.data()); }
407     void setPrototype(const Value *prototype);
408
409     virtual void processMembers(MemberProcessor *processor) const;
410
411     virtual void setMember(const QString &name, const Value *value);
412     virtual void removeMember(const QString &name);
413
414     virtual const Value *lookupMember(const QString &name, const Context *context,
415                                       const ObjectValue **foundInObject = 0,
416                                       bool examinePrototypes = true) const;
417     const Value *lookupMember(const QString &name, const ContextPtr &context,
418                               const ObjectValue **foundInObject = 0,
419                               bool examinePrototypes = true) const
420     { return lookupMember(name, context.data(), foundInObject, examinePrototypes); }
421
422     // Value interface
423     virtual const ObjectValue *asObjectValue() const;
424     virtual void accept(ValueVisitor *visitor) const;
425
426 private:
427     bool checkPrototype(const ObjectValue *prototype, QSet<const ObjectValue *> *processed) const;
428
429 private:
430     ValueOwner *_valueOwner;
431     QHash<QString, const Value *> _members;
432     QString _className;
433
434 protected:
435     const Value *_prototype;
436 };
437
438 class QMLJS_EXPORT PrototypeIterator
439 {
440 public:
441     enum Error
442     {
443         NoError,
444         ReferenceResolutionError,
445         CycleError
446     };
447
448     PrototypeIterator(const ObjectValue *start, const Context *context);
449     PrototypeIterator(const ObjectValue *start, const ContextPtr &context);
450
451     bool hasNext();
452     const ObjectValue *peekNext();
453     const ObjectValue *next();
454     Error error() const;
455
456     QList<const ObjectValue *> all();
457
458 private:
459     const ObjectValue *m_current;
460     const ObjectValue *m_next;
461     QList<const ObjectValue *> m_prototypes;
462     const Context *m_context;
463     Error m_error;
464 };
465
466 class QMLJS_EXPORT QmlEnumValue: public NumberValue
467 {
468 public:
469     QmlEnumValue(const CppComponentValue *owner, int index);
470     virtual ~QmlEnumValue();
471
472     virtual const QmlEnumValue *asQmlEnumValue() const;
473
474     QString name() const;
475     QStringList keys() const;
476     const CppComponentValue *owner() const;
477
478 private:
479     const CppComponentValue *_owner;
480     int _enumIndex;
481 };
482
483
484 // A ObjectValue based on a FakeMetaObject.
485 // May only have other CppComponentValue as ancestors.
486 class QMLJS_EXPORT CppComponentValue: public ObjectValue
487 {
488 public:
489     CppComponentValue(LanguageUtils::FakeMetaObject::ConstPtr metaObject, const QString &className,
490                    const QString &moduleName, const LanguageUtils::ComponentVersion &componentVersion,
491                    const LanguageUtils::ComponentVersion &importVersion, int metaObjectRevision,
492                    ValueOwner *valueOwner);
493     virtual ~CppComponentValue();
494
495     virtual const CppComponentValue *asCppComponentValue() const;
496
497     virtual void processMembers(MemberProcessor *processor) const;
498     const Value *valueForCppName(const QString &typeName) const;
499
500     using ObjectValue::prototype;
501     const CppComponentValue *prototype() const;
502
503     const CppComponentValue *attachedType() const;
504     void setAttachedType(CppComponentValue *value);
505
506     LanguageUtils::FakeMetaObject::ConstPtr metaObject() const;
507
508     QString moduleName() const;
509     LanguageUtils::ComponentVersion componentVersion() const;
510     LanguageUtils::ComponentVersion importVersion() const;
511
512     QString defaultPropertyName() const;
513     QString propertyType(const QString &propertyName) const;
514     bool isListProperty(const QString &name) const;
515     bool isWritable(const QString &propertyName) const;
516     bool isPointer(const QString &propertyName) const;
517     bool hasLocalProperty(const QString &typeName) const;
518     bool hasProperty(const QString &typeName) const;
519
520     LanguageUtils::FakeMetaEnum getEnum(const QString &typeName, const CppComponentValue **foundInScope = 0) const;
521     const QmlEnumValue *getEnumValue(const QString &typeName, const CppComponentValue **foundInScope = 0) const;
522
523     const ObjectValue *signalScope(const QString &signalName) const;
524 protected:
525     bool isDerivedFrom(LanguageUtils::FakeMetaObject::ConstPtr base) const;
526
527 private:
528     CppComponentValue *_attachedType;
529     LanguageUtils::FakeMetaObject::ConstPtr _metaObject;
530     const QString _moduleName;
531     // _componentVersion is the version of the export
532     // _importVersion is the version it's imported as, used to find correct prototypes
533     // needed in cases when B 1.0 has A 1.1 as prototype when imported as 1.1
534     const LanguageUtils::ComponentVersion _componentVersion;
535     const LanguageUtils::ComponentVersion _importVersion;
536     mutable QAtomicPointer< QList<const Value *> > _metaSignatures;
537     mutable QAtomicPointer< QHash<QString, const ObjectValue *> > _signalScopes;
538     QHash<QString, const QmlEnumValue * > _enums;
539     int _metaObjectRevision;
540 };
541
542 class QMLJS_EXPORT Activation
543 {
544 public:
545     explicit Activation(Context *parentContext = 0);
546     virtual ~Activation();
547
548     Context *context() const;
549     Context *parentContext() const;
550
551     bool calledAsConstructor() const;
552     void setCalledAsConstructor(bool calledAsConstructor);
553
554     bool calledAsFunction() const;
555     void setCalledAsFunction(bool calledAsFunction);
556
557     ObjectValue *thisObject() const;
558     void setThisObject(ObjectValue *thisObject);
559
560     ValueList arguments() const;
561     void setArguments(const ValueList &arguments);
562
563 private:
564     ObjectValue *_thisObject;
565     ValueList _arguments;
566     bool _calledAsFunction;
567     Context *_parentContext;
568 };
569
570
571 class QMLJS_EXPORT FunctionValue: public ObjectValue
572 {
573 public:
574     FunctionValue(ValueOwner *valueOwner);
575     virtual ~FunctionValue();
576
577     // [[construct]]
578     const Value *construct(const ValueList &actuals = ValueList()) const;
579
580     // [[call]]
581     const Value *call(const ValueList &actuals = ValueList()) const;
582
583     const Value *call(const ObjectValue *thisObject,
584                       const ValueList &actuals = ValueList()) const;
585
586
587     virtual const Value *returnValue() const;
588
589     virtual int argumentCount() const;
590     virtual const Value *argument(int index) const;
591     virtual QString argumentName(int index) const;
592     virtual bool isVariadic() const;
593
594     virtual const Value *invoke(const Activation *activation) const;
595
596     // Value interface
597     virtual const FunctionValue *asFunctionValue() const;
598     virtual void accept(ValueVisitor *visitor) const;
599 };
600
601 class QMLJS_EXPORT Function: public FunctionValue
602 {
603 public:
604     Function(ValueOwner *valueOwner);
605     virtual ~Function();
606
607     void addArgument(const Value *argument, const QString &name = QString());
608     void setReturnValue(const Value *returnValue);
609
610     // FunctionValue interface
611     virtual const Value *returnValue() const;
612     virtual int argumentCount() const;
613     virtual const Value *argument(int index) const;
614     virtual QString argumentName(int index) const;
615     virtual const Value *invoke(const Activation *activation) const;
616
617 private:
618     ValueList _arguments;
619     QStringList _argumentNames;
620     const Value *_returnValue;
621 };
622
623
624 ////////////////////////////////////////////////////////////////////////////////
625 // typing environment
626 ////////////////////////////////////////////////////////////////////////////////
627
628 class QMLJS_EXPORT CppQmlTypesLoader
629 {
630 public:
631     typedef QHash<QString, LanguageUtils::FakeMetaObject::ConstPtr> BuiltinObjects;
632
633     /** Loads a set of qmltypes files into the builtin objects list
634         and returns errors and warnings
635     */
636     static BuiltinObjects loadQmlTypes(const QFileInfoList &qmltypesFiles,
637                              QStringList *errors, QStringList *warnings);
638
639     static BuiltinObjects defaultQtObjects;
640     static BuiltinObjects defaultLibraryObjects;
641
642     // parses the contents of a qmltypes file and fills the newObjects map
643     static void parseQmlTypeDescriptions(
644         const QByteArray &qmlTypes,
645         BuiltinObjects *newObjects,
646         QList<ModuleApiInfo> *newModuleApis, QString *errorMessage, QString *warningMessage);
647 };
648
649 class QMLJS_EXPORT CppQmlTypes
650 {
651 public:
652     CppQmlTypes(ValueOwner *valueOwner);
653
654     // package name for objects that should be always available
655     static const QLatin1String defaultPackage;
656     // package name for objects with their raw cpp name
657     static const QLatin1String cppPackage;
658
659     template <typename T>
660     void load(const T &fakeMetaObjects, const QString &overridePackage = QString());
661
662     QList<const CppComponentValue *> createObjectsForImport(const QString &package, LanguageUtils::ComponentVersion version);
663     bool hasModule(const QString &module) const;
664
665     static QString qualifiedName(const QString &module, const QString &type,
666                                  LanguageUtils::ComponentVersion version);
667     const CppComponentValue *objectByQualifiedName(const QString &fullyQualifiedName) const;
668     const CppComponentValue *objectByQualifiedName(
669             const QString &package, const QString &type,
670             LanguageUtils::ComponentVersion version) const;
671     const CppComponentValue *objectByCppName(const QString &cppName) const;
672
673 private:
674     // "Package.CppName ImportVersion" ->  CppComponentValue
675     QHash<QString, const CppComponentValue *> _objectsByQualifiedName;
676     QHash<QString, QSet<LanguageUtils::FakeMetaObject::ConstPtr> > _fakeMetaObjectsByPackage;
677     ValueOwner *_valueOwner;
678 };
679
680 class ConvertToNumber: protected ValueVisitor // ECMAScript ToInt()
681 {
682 public:
683     ConvertToNumber(ValueOwner *valueOwner);
684
685     const Value *operator()(const Value *value);
686
687 protected:
688     const Value *switchResult(const Value *value);
689
690     virtual void visit(const NullValue *);
691     virtual void visit(const UndefinedValue *);
692     virtual void visit(const NumberValue *);
693     virtual void visit(const BooleanValue *);
694     virtual void visit(const StringValue *);
695     virtual void visit(const ObjectValue *);
696     virtual void visit(const FunctionValue *);
697
698 private:
699     ValueOwner *_valueOwner;
700     const Value *_result;
701 };
702
703 class ConvertToString: protected ValueVisitor // ECMAScript ToString
704 {
705 public:
706     ConvertToString(ValueOwner *valueOwner);
707
708     const Value *operator()(const Value *value);
709
710 protected:
711     const Value *switchResult(const Value *value);
712
713     virtual void visit(const NullValue *);
714     virtual void visit(const UndefinedValue *);
715     virtual void visit(const NumberValue *);
716     virtual void visit(const BooleanValue *);
717     virtual void visit(const StringValue *);
718     virtual void visit(const ObjectValue *);
719     virtual void visit(const FunctionValue *);
720
721 private:
722     ValueOwner *_valueOwner;
723     const Value *_result;
724 };
725
726 class ConvertToObject: protected ValueVisitor // ECMAScript ToObject
727 {
728 public:
729     ConvertToObject(ValueOwner *valueOwner);
730
731     const Value *operator()(const Value *value);
732
733 protected:
734     const Value *switchResult(const Value *value);
735
736     virtual void visit(const NullValue *);
737     virtual void visit(const UndefinedValue *);
738     virtual void visit(const NumberValue *);
739     virtual void visit(const BooleanValue *);
740     virtual void visit(const StringValue *);
741     virtual void visit(const ObjectValue *);
742     virtual void visit(const FunctionValue *);
743
744 private:
745     ValueOwner *_valueOwner;
746     const Value *_result;
747 };
748
749 class QMLJS_EXPORT TypeId: protected ValueVisitor
750 {
751     QString _result;
752
753 public:
754     QString operator()(const Value *value);
755
756 protected:
757     virtual void visit(const NullValue *);
758     virtual void visit(const UndefinedValue *);
759     virtual void visit(const NumberValue *);
760     virtual void visit(const BooleanValue *);
761     virtual void visit(const StringValue *);
762     virtual void visit(const ObjectValue *object);
763     virtual void visit(const FunctionValue *object);
764     virtual void visit(const ColorValue *);
765     virtual void visit(const AnchorLineValue *);
766 };
767
768 // internal
769 class QMLJS_EXPORT QmlPrototypeReference: public Reference
770 {
771 public:
772     QmlPrototypeReference(AST::UiQualifiedId *qmlTypeName, const Document *doc, ValueOwner *valueOwner);
773     virtual ~QmlPrototypeReference();
774
775     virtual const QmlPrototypeReference *asQmlPrototypeReference() const;
776
777     AST::UiQualifiedId *qmlTypeName() const;
778
779 private:    
780     virtual const Value *value(ReferenceContext *referenceContext) const;
781
782     AST::UiQualifiedId *_qmlTypeName;
783     const Document *_doc;
784 };
785
786 class QMLJS_EXPORT ASTVariableReference: public Reference
787 {
788     AST::VariableDeclaration *_ast;
789     const Document *_doc;
790
791 public:
792     ASTVariableReference(AST::VariableDeclaration *ast, const Document *doc, ValueOwner *valueOwner);
793     virtual ~ASTVariableReference();
794
795 private:
796     virtual const Value *value(ReferenceContext *referenceContext) const;
797     virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
798 };
799
800 class QMLJS_EXPORT ASTFunctionValue: public FunctionValue
801 {
802     AST::FunctionExpression *_ast;
803     const Document *_doc;
804     QList<QString> _argumentNames;
805
806 public:
807     ASTFunctionValue(AST::FunctionExpression *ast, const Document *doc, ValueOwner *valueOwner);
808     virtual ~ASTFunctionValue();
809
810     AST::FunctionExpression *ast() const;
811
812     virtual int argumentCount() const;
813     virtual QString argumentName(int index) const;
814
815     virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
816 };
817
818 class QMLJS_EXPORT ASTPropertyReference: public Reference
819 {
820     AST::UiPublicMember *_ast;
821     const Document *_doc;
822     QString _onChangedSlotName;
823
824 public:
825     ASTPropertyReference(AST::UiPublicMember *ast, const Document *doc, ValueOwner *valueOwner);
826     virtual ~ASTPropertyReference();
827
828     virtual const ASTPropertyReference *asAstPropertyReference() const;
829
830     AST::UiPublicMember *ast() const { return _ast; }
831     QString onChangedSlotName() const { return _onChangedSlotName; }
832
833     virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
834
835 private:
836     virtual const Value *value(ReferenceContext *referenceContext) const;
837 };
838
839 class QMLJS_EXPORT ASTSignal: public FunctionValue
840 {
841     AST::UiPublicMember *_ast;
842     const Document *_doc;
843     QString _slotName;
844     const ObjectValue *_bodyScope;
845
846 public:
847     ASTSignal(AST::UiPublicMember *ast, const Document *doc, ValueOwner *valueOwner);
848     virtual ~ASTSignal();
849
850     virtual const ASTSignal *asAstSignal() const;
851
852     AST::UiPublicMember *ast() const { return _ast; }
853     QString slotName() const { return _slotName; }
854     const ObjectValue *bodyScope() const { return _bodyScope; }
855
856     // FunctionValue interface
857     virtual int argumentCount() const;
858     virtual const Value *argument(int index) const;
859     virtual QString argumentName(int index) const;
860
861     // Value interface
862     virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
863 };
864
865 class QMLJS_EXPORT ASTObjectValue: public ObjectValue
866 {
867     AST::UiQualifiedId *_typeName;
868     AST::UiObjectInitializer *_initializer;
869     const Document *_doc;
870     QList<ASTPropertyReference *> _properties;
871     QList<ASTSignal *> _signals;
872     ASTPropertyReference *_defaultPropertyRef;
873
874 public:
875     ASTObjectValue(AST::UiQualifiedId *typeName,
876                    AST::UiObjectInitializer *initializer,
877                    const Document *doc,
878                    ValueOwner *valueOwner);
879     virtual ~ASTObjectValue();
880
881     virtual const ASTObjectValue *asAstObjectValue() const;
882
883     bool getSourceLocation(QString *fileName, int *line, int *column) const;
884     virtual void processMembers(MemberProcessor *processor) const;
885
886     QString defaultPropertyName() const;
887
888     AST::UiObjectInitializer *initializer() const;
889     AST::UiQualifiedId *typeName() const;
890     const Document *document() const;
891 };
892
893 class QMLJS_EXPORT ImportInfo
894 {
895 public:
896     enum Type {
897         InvalidImport,
898         ImplicitDirectoryImport,
899         LibraryImport,
900         FileImport,
901         DirectoryImport,
902         UnknownFileImport // refers a file/directory that wasn't found
903     };
904
905     ImportInfo();
906
907     static ImportInfo moduleImport(QString uri, LanguageUtils::ComponentVersion version,
908                                    const QString &as, AST::UiImport *ast = 0);
909     static ImportInfo pathImport(const QString &docPath, const QString &path,
910                                  LanguageUtils::ComponentVersion version,
911                                  const QString &as, AST::UiImport *ast = 0);
912     static ImportInfo invalidImport(AST::UiImport *ast = 0);
913     static ImportInfo implicitDirectoryImport(const QString &directory);
914
915     bool isValid() const;
916     Type type() const;
917
918     // LibraryImport: uri with ',' separator
919     // Other: non-absolute path
920     QString name() const;
921
922     // LibraryImport: uri with QDir::separator separator
923     // Other: absoluteFilePath
924     QString path() const;
925
926     // null if the import has no 'as', otherwise the target id
927     QString as() const;
928
929     LanguageUtils::ComponentVersion version() const;
930     AST::UiImport *ast() const;
931
932 private:
933     Type _type;
934     QString _name;
935     QString _path;
936     LanguageUtils::ComponentVersion _version;
937     QString _as;
938     AST::UiImport *_ast;
939 };
940
941 class QMLJS_EXPORT Import {
942 public:
943     Import();
944
945     // const!
946     ObjectValue *object;
947     ImportInfo info;
948     // uri imports: path to library, else empty
949     QString libraryPath;
950     // whether the import succeeded
951     bool valid;
952 };
953
954 class Imports;
955
956 class QMLJS_EXPORT TypeScope: public ObjectValue
957 {
958 public:
959     TypeScope(const Imports *imports, ValueOwner *valueOwner);
960
961     virtual const Value *lookupMember(const QString &name, const Context *context,
962                                       const ObjectValue **foundInObject = 0,
963                                       bool examinePrototypes = true) const;
964     virtual void processMembers(MemberProcessor *processor) const;
965
966 private:
967     const Imports *_imports;
968 };
969
970 class QMLJS_EXPORT JSImportScope: public ObjectValue
971 {
972 public:
973     JSImportScope(const Imports *imports, ValueOwner *valueOwner);
974
975     virtual const Value *lookupMember(const QString &name, const Context *context,
976                                       const ObjectValue **foundInObject = 0,
977                                       bool examinePrototypes = true) const;
978     virtual void processMembers(MemberProcessor *processor) const;
979
980 private:
981     const Imports *_imports;
982 };
983
984 class QMLJS_EXPORT Imports
985 {
986 public:
987     Imports(ValueOwner *valueOwner);
988
989     void append(const Import &import);
990     void setImportFailed();
991
992     ImportInfo info(const QString &name, const Context *context) const;
993     QString nameForImportedObject(const ObjectValue *value, const Context *context) const;
994     bool importFailed() const;
995
996     QList<Import> all() const;
997
998     const TypeScope *typeScope() const;
999     const JSImportScope *jsImportScope() const;
1000
1001 #ifdef QT_DEBUG
1002     void dump() const;
1003 #endif
1004
1005 private:
1006     // holds imports in the order they appeared,
1007     // lookup order is back to front
1008     QList<Import> _imports;
1009     TypeScope *_typeScope;
1010     JSImportScope *_jsImportScope;
1011     bool _importFailed;
1012 };
1013
1014 } // namespace QmlJS
1015
1016 #endif // QMLJS_INTERPRETER_H