qmljsinterpreter.cpp 62 KB
Newer Older
1
2
3
4
/**************************************************************************
**
** This file is part of Qt Creator
**
con's avatar
con committed
5
** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
6
**
7
** Contact: Nokia Corporation (qt-info@nokia.com)
8
9
10
11
**
**
** GNU Lesser General Public License Usage
**
hjk's avatar
hjk committed
12
13
14
15
16
17
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
18
**
con's avatar
con committed
19
** In addition, as a special exception, Nokia gives you certain additional
hjk's avatar
hjk committed
20
** rights. These rights are described in the Nokia Qt LGPL Exception
con's avatar
con committed
21
22
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
hjk's avatar
hjk committed
23
24
25
26
27
** Other Usage
**
** Alternatively, this file may be used in accordance with the terms and
** conditions contained in a signed written agreement between you and Nokia.
**
con's avatar
con committed
28
** If you have questions regarding the use of this file, please contact
29
** Nokia at qt-info@nokia.com.
30
31
32
33
**
**************************************************************************/

#include "qmljsinterpreter.h"
34
#include "qmljsevaluate.h"
35
#include "qmljslink.h"
36
#include "qmljsbind.h"
37
#include "qmljsscopebuilder.h"
38
#include "qmljsscopechain.h"
39
#include "qmljsscopeastpath.h"
40
#include "qmljstypedescriptionreader.h"
41
#include "qmljsvalueowner.h"
42
#include "qmljscontext.h"
43
#include "parser/qmljsast_p.h"
44

45
#include <languageutils/fakemetaobject.h>
46
#include <utils/qtcassert.h>
47

48
#include <QtCore/QFile>
49
#include <QtCore/QDir>
50
51
#include <QtCore/QString>
#include <QtCore/QStringList>
52
53
#include <QtCore/QMetaObject>
#include <QtCore/QMetaProperty>
54
#include <QtCore/QXmlStreamReader>
55
#include <QtCore/QProcess>
56
57
#include <QtCore/QDebug>

58
59
#include <algorithm>

60
using namespace LanguageUtils;
61
using namespace QmlJS;
62
using namespace QmlJS::AST;
63

64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
/*!
    \class QmlJS::Value
    \brief Abstract base class for the result of a JS expression.
    \sa Evaluate ValueOwner ValueVisitor

    A Value represents a category of JavaScript values, such as number
    (NumberValue), string (StringValue) or functions with a
    specific signature (FunctionValue). It can also represent internal
    categories such as "a QML component instantiation defined in a file"
    (ASTObjectValue), "a QML component defined in C++"
    (CppComponentValue) or "no specific information is available"
    (UnknownValue).

    The Value class itself provides accept() for admitting
    \l{ValueVisitor}s and a do-nothing getSourceLocation().

    Value instances should be cast to a derived type either through the
    asXXX() helper functions such as asNumberValue() or via the
    value_cast() template function.

    Values are the result of many operations in the QmlJS code model:
    \list
    \o \l{Evaluate}
    \o Context::lookupType() and Context::lookupReference()
    \o ScopeChain::lookup()
    \o ObjectValue::lookupMember()
    \endlist
*/

Roberto Raggi's avatar
Roberto Raggi committed
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
namespace {

class LookupMember: public MemberProcessor
{
    QString _name;
    const Value *_value;

    bool process(const QString &name, const Value *value)
    {
        if (_value)
            return false;

        if (name == _name) {
            _value = value;
            return false;
        }

        return true;
    }

public:
    LookupMember(const QString &name)
        : _name(name), _value(0) {}

    const Value *value() const { return _value; }

    virtual bool processProperty(const QString &name, const Value *value)
    {
        return process(name, value);
    }

    virtual bool processEnumerator(const QString &name, const Value *value)
    {
        return process(name, value);
    }

    virtual bool processSignal(const QString &name, const Value *value)
    {
        return process(name, value);
    }

    virtual bool processSlot(const QString &name, const Value *value)
    {
        return process(name, value);
    }

    virtual bool processGeneratedSlot(const QString &name, const Value *value)
    {
        return process(name, value);
    }
};

145
146
class MetaFunction: public FunctionValue
{
147
    FakeMetaMethod _method;
148
149

public:
150
151
    MetaFunction(const FakeMetaMethod &method, ValueOwner *valueOwner)
        : FunctionValue(valueOwner), _method(method)
152
153
154
    {
    }

155
    virtual int namedArgumentCount() const
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
    {
        return _method.parameterNames().size();
    }

    virtual QString argumentName(int index) const
    {
        if (index < _method.parameterNames().size())
            return _method.parameterNames().at(index);

        return FunctionValue::argumentName(index);
    }

    virtual bool isVariadic() const
    {
        return false;
    }
};

Roberto Raggi's avatar
Roberto Raggi committed
174
175
} // end of anonymous namespace

176
CppComponentValue::CppComponentValue(FakeMetaObject::ConstPtr metaObject, const QString &className,
177
                               const QString &packageName, const ComponentVersion &componentVersion,
178
179
                               const ComponentVersion &importVersion, int metaObjectRevision,
                               ValueOwner *valueOwner)
180
    : ObjectValue(valueOwner),
181
      _metaObject(metaObject),
182
183
      _moduleName(packageName),
      _componentVersion(componentVersion),
184
185
      _importVersion(importVersion),
      _metaObjectRevision(metaObjectRevision)
186
{
187
    setClassName(className);
188
189
190
    int nEnums = metaObject->enumeratorCount();
    for (int i = 0; i < nEnums; ++i) {
        FakeMetaEnum fEnum = metaObject->enumerator(i);
191
        _enums[fEnum.name()] = new QmlEnumValue(this, i);
192
    }
193
}
Roberto Raggi's avatar
Roberto Raggi committed
194

195
CppComponentValue::~CppComponentValue()
196
197
198
199
200
201
202
203
204
205
206
207
{
    delete _metaSignatures;
    delete _signalScopes;
}

static QString generatedSlotName(const QString &base)
{
    QString slotName = QLatin1String("on");
    slotName += base.at(0).toUpper();
    slotName += base.midRef(1);
    return slotName;
}
Roberto Raggi's avatar
Roberto Raggi committed
208

Christian Kamm's avatar
Christian Kamm committed
209
210
211
212
213
const CppComponentValue *CppComponentValue::asCppComponentValue() const
{
    return this;
}

214
void CppComponentValue::processMembers(MemberProcessor *processor) const
215
{
Roberto Raggi's avatar
Roberto Raggi committed
216
    // process the meta enums
217
218
    for (int index = _metaObject->enumeratorOffset(); index < _metaObject->enumeratorCount(); ++index) {
        FakeMetaEnum e = _metaObject->enumerator(index);
219
220

        for (int i = 0; i < e.keyCount(); ++i) {
221
            processor->processEnumerator(e.key(i), valueOwner()->numberValue());
222
223
224
        }
    }

225
226
    // all explicitly defined signal names
    QSet<QString> explicitSignals;
227

228
229
230
231
232
233
234
235
236
237
238
239
240
    // make MetaFunction instances lazily when first needed
    QList<const Value *> *signatures = _metaSignatures;
    if (!signatures) {
        signatures = new QList<const Value *>;
        signatures->reserve(_metaObject->methodCount());
        for (int index = 0; index < _metaObject->methodCount(); ++index)
            signatures->append(new MetaFunction(_metaObject->method(index), valueOwner()));
        if (!_metaSignatures.testAndSetOrdered(0, signatures)) {
            delete signatures;
            signatures = _metaSignatures;
        }
    }

Roberto Raggi's avatar
Roberto Raggi committed
241
242
    // process the meta methods
    for (int index = 0; index < _metaObject->methodCount(); ++index) {
243
        const FakeMetaMethod method = _metaObject->method(index);
244
        if (_metaObjectRevision < method.revision())
245
246
            continue;

Christian Kamm's avatar
Christian Kamm committed
247
        const QString &methodName = _metaObject->method(index).methodName();
248
        const Value *signature = signatures->at(index);
249

250
        if (method.methodType() == FakeMetaMethod::Slot && method.access() == FakeMetaMethod::Public) {
Roberto Raggi's avatar
Roberto Raggi committed
251
            processor->processSlot(methodName, signature);
252

253
        } else if (method.methodType() == FakeMetaMethod::Signal && method.access() != FakeMetaMethod::Private) {
254
            // process the signal
Roberto Raggi's avatar
Roberto Raggi committed
255
            processor->processSignal(methodName, signature);
256
            explicitSignals.insert(methodName);
257

258
            // process the generated slot
259
            const QString &slotName = generatedSlotName(methodName);
Roberto Raggi's avatar
Roberto Raggi committed
260
            processor->processGeneratedSlot(slotName, signature);
261
        }
Roberto Raggi's avatar
Roberto Raggi committed
262
263
    }

264
265
    // process the meta properties
    for (int index = 0; index < _metaObject->propertyCount(); ++index) {
266
        const FakeMetaProperty prop = _metaObject->property(index);
267
        if (_metaObjectRevision < prop.revision())
268
            continue;
269
270

        const QString propertyName = prop.name();
271
        processor->processProperty(propertyName, valueForCppName(prop.typeName()));
272
273
274
275
276
277
278

        // every property always has a onXyzChanged slot, even if the NOTIFY
        // signal has a different name
        QString signalName = propertyName;
        signalName += QLatin1String("Changed");
        if (!explicitSignals.contains(signalName)) {
            // process the generated slot
279
            const QString &slotName = generatedSlotName(signalName);
280
            processor->processGeneratedSlot(slotName, valueOwner()->unknownValue());
281
282
283
        }
    }

284
285
286
    // look into attached types
    const QString &attachedTypeName = _metaObject->attachedTypeName();
    if (!attachedTypeName.isEmpty()) {
287
        const CppComponentValue *attachedType = valueOwner()->cppQmlTypes().objectByCppName(attachedTypeName);
288
        if (attachedType && attachedType != this) // ### only weak protection against infinite loops
289
290
            attachedType->processMembers(processor);
    }
291

292
293
294
    ObjectValue::processMembers(processor);
}

295
const Value *CppComponentValue::valueForCppName(const QString &typeName) const
296
{
297
    const CppQmlTypes &cppTypes = valueOwner()->cppQmlTypes();
Roberto Raggi's avatar
Roberto Raggi committed
298

299
    // check in the same package/version first
300
    const CppComponentValue *objectValue = cppTypes.objectByQualifiedName(
301
302
303
304
305
306
307
                _moduleName, typeName, _importVersion);
    if (objectValue)
        return objectValue;

    // fallback to plain cpp name
    objectValue = cppTypes.objectByCppName(typeName);
    if (objectValue)
308
        return objectValue;
Roberto Raggi's avatar
Roberto Raggi committed
309

310
311
312
313
314
315
316
    // try qml builtin type names
    if (const Value *v = valueOwner()->defaultValueForBuiltinType(typeName)) {
        if (!v->asUndefinedValue())
            return v;
    }

    // map other C++ types
317
    if (typeName == QLatin1String("QByteArray")
Christian Kamm's avatar
Christian Kamm committed
318
            || typeName == QLatin1String("QString")) {
Christian Kamm's avatar
Christian Kamm committed
319
        return valueOwner()->stringValue();
Christian Kamm's avatar
Christian Kamm committed
320
    } else if (typeName == QLatin1String("QUrl")) {
Christian Kamm's avatar
Christian Kamm committed
321
        return valueOwner()->urlValue();
322
    } else if (typeName == QLatin1String("long")) {
Christian Kamm's avatar
Christian Kamm committed
323
        return valueOwner()->intValue();
324
325
    }  else if (typeName == QLatin1String("float")
                || typeName == QLatin1String("qreal")) {
Christian Kamm's avatar
Christian Kamm committed
326
        return valueOwner()->realValue();
327
    } else if (typeName == QLatin1String("QFont")) {
Christian Kamm's avatar
Christian Kamm committed
328
        return valueOwner()->qmlFontObject();
329
330
331
    } else if (typeName == QLatin1String("QPoint")
            || typeName == QLatin1String("QPointF")
            || typeName == QLatin1String("QVector2D")) {
Christian Kamm's avatar
Christian Kamm committed
332
        return valueOwner()->qmlPointObject();
333
334
    } else if (typeName == QLatin1String("QSize")
            || typeName == QLatin1String("QSizeF")) {
Christian Kamm's avatar
Christian Kamm committed
335
        return valueOwner()->qmlSizeObject();
336
337
    } else if (typeName == QLatin1String("QRect")
            || typeName == QLatin1String("QRectF")) {
Christian Kamm's avatar
Christian Kamm committed
338
        return valueOwner()->qmlRectObject();
339
    } else if (typeName == QLatin1String("QVector3D")) {
Christian Kamm's avatar
Christian Kamm committed
340
        return valueOwner()->qmlVector3DObject();
341
    } else if (typeName == QLatin1String("QColor")) {
Christian Kamm's avatar
Christian Kamm committed
342
        return valueOwner()->colorValue();
343
    } else if (typeName == QLatin1String("QDeclarativeAnchorLine")) {
Christian Kamm's avatar
Christian Kamm committed
344
        return valueOwner()->anchorLineValue();
345
346
    }

Christian Kamm's avatar
Christian Kamm committed
347
    // might be an enum
348
    const CppComponentValue *base = this;
349
350
    const QStringList components = typeName.split(QLatin1String("::"));
    if (components.size() == 2) {
351
        base = valueOwner()->cppQmlTypes().objectByCppName(components.first());
352
353
    }
    if (base) {
354
        if (const QmlEnumValue *value = base->getEnumValue(components.last()))
Christian Kamm's avatar
Christian Kamm committed
355
            return value;
Christian Kamm's avatar
Christian Kamm committed
356
357
    }

358
359
    // may still be a cpp based value
    return valueOwner()->unknownValue();
360
}
361

362
const CppComponentValue *CppComponentValue::prototype() const
363
{
Christian Kamm's avatar
Christian Kamm committed
364
    Q_ASSERT(!_prototype || value_cast<CppComponentValue>(_prototype));
365
    return static_cast<const CppComponentValue *>(_prototype);
366
367
}

368
369
370
371
372
/*!
  \returns a list started by this object and followed by all its prototypes

  Prefer to use this over calling prototype() in a loop, as it avoids cycles.
*/
373
QList<const CppComponentValue *> CppComponentValue::prototypes() const
374
{
375
376
    QList<const CppComponentValue *> protos;
    for (const CppComponentValue *it = this; it; it = it->prototype()) {
377
378
379
380
381
382
383
        if (protos.contains(it))
            break;
        protos += it;
    }
    return protos;
}

384
FakeMetaObject::ConstPtr CppComponentValue::metaObject() const
385
{
386
    return _metaObject;
387
388
}

389
QString CppComponentValue::moduleName() const
390
{ return _moduleName; }
391

392
ComponentVersion CppComponentValue::componentVersion() const
393
{ return _componentVersion; }
394

395
ComponentVersion CppComponentValue::importVersion() const
396
397
{ return _importVersion; }

398
QString CppComponentValue::defaultPropertyName() const
399
400
{ return _metaObject->defaultPropertyName(); }

401
QString CppComponentValue::propertyType(const QString &propertyName) const
402
{
403
    foreach (const CppComponentValue *it, prototypes()) {
404
        FakeMetaObject::ConstPtr iter = it->_metaObject;
405
        int propIdx = iter->propertyIndex(propertyName);
406
        if (propIdx != -1) {
407
            return iter->property(propIdx).typeName();
408
409
410
411
412
        }
    }
    return QString();
}

413
bool CppComponentValue::isListProperty(const QString &propertyName) const
414
{
415
    foreach (const CppComponentValue *it, prototypes()) {
416
        FakeMetaObject::ConstPtr iter = it->_metaObject;
417
418
419
420
421
422
        int propIdx = iter->propertyIndex(propertyName);
        if (propIdx != -1) {
            return iter->property(propIdx).isList();
        }
    }
    return false;
423
424
}

425
FakeMetaEnum CppComponentValue::getEnum(const QString &typeName, const CppComponentValue **foundInScope) const
426
{
427
    foreach (const CppComponentValue *it, prototypes()) {
Christian Kamm's avatar
Christian Kamm committed
428
429
430
431
432
433
434
435
436
437
438
        FakeMetaObject::ConstPtr iter = it->_metaObject;
        const int index = iter->enumeratorIndex(typeName);
        if (index != -1) {
            if (foundInScope)
                *foundInScope = it;
            return iter->enumerator(index);
        }
    }
    if (foundInScope)
        *foundInScope = 0;
    return FakeMetaEnum();
439
440
}

441
const QmlEnumValue *CppComponentValue::getEnumValue(const QString &typeName, const CppComponentValue **foundInScope) const
442
{
443
    foreach (const CppComponentValue *it, prototypes()) {
Christian Kamm's avatar
Christian Kamm committed
444
445
446
447
448
449
450
451
452
        if (const QmlEnumValue *e = it->_enums.value(typeName)) {
            if (foundInScope)
                *foundInScope = it;
            return e;
        }
    }
    if (foundInScope)
        *foundInScope = 0;
    return 0;
453
454
}

455
const ObjectValue *CppComponentValue::signalScope(const QString &signalName) const
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
{
    QHash<QString, const ObjectValue *> *scopes = _signalScopes;
    if (!scopes) {
        scopes = new QHash<QString, const ObjectValue *>;
        // usually not all methods are signals
        scopes->reserve(_metaObject->methodCount() / 2);
        for (int index = 0; index < _metaObject->methodCount(); ++index) {
            const FakeMetaMethod &method = _metaObject->method(index);
            if (method.methodType() != FakeMetaMethod::Signal || method.access() == FakeMetaMethod::Private)
                continue;

            const QStringList &parameterNames = method.parameterNames();
            const QStringList &parameterTypes = method.parameterTypes();
            QTC_ASSERT(parameterNames.size() == parameterTypes.size(), continue);

            ObjectValue *scope = valueOwner()->newObject(/*prototype=*/0);
            for (int i = 0; i < parameterNames.size(); ++i) {
                const QString &name = parameterNames.at(i);
                const QString &type = parameterTypes.at(i);
                if (name.isEmpty())
                    continue;
                scope->setMember(name, valueForCppName(type));
            }
            scopes->insert(generatedSlotName(method.methodName()), scope);
        }
        if (!_signalScopes.testAndSetOrdered(0, scopes)) {
482
            delete scopes;
483
484
485
486
487
488
489
            scopes = _signalScopes;
        }
    }

    return scopes->value(signalName);
}

490
bool CppComponentValue::isWritable(const QString &propertyName) const
491
{
492
    foreach (const CppComponentValue *it, prototypes()) {
493
        FakeMetaObject::ConstPtr iter = it->_metaObject;
494
495
496
497
498
499
500
501
        int propIdx = iter->propertyIndex(propertyName);
        if (propIdx != -1) {
            return iter->property(propIdx).isWritable();
        }
    }
    return false;
}

502
bool CppComponentValue::isPointer(const QString &propertyName) const
503
{
504
    foreach (const CppComponentValue *it, prototypes()) {
505
        FakeMetaObject::ConstPtr iter = it->_metaObject;
506
507
508
509
510
511
512
513
        int propIdx = iter->propertyIndex(propertyName);
        if (propIdx != -1) {
            return iter->property(propIdx).isPointer();
        }
    }
    return false;
}

514
bool CppComponentValue::hasLocalProperty(const QString &typeName) const
515
516
517
518
519
520
521
{
    int idx = _metaObject->propertyIndex(typeName);
    if (idx == -1)
        return false;
    return true;
}

522
bool CppComponentValue::hasProperty(const QString &propertyName) const
523
{
524
    foreach (const CppComponentValue *it, prototypes()) {
525
        FakeMetaObject::ConstPtr iter = it->_metaObject;
526
527
528
529
530
531
532
533
        int propIdx = iter->propertyIndex(propertyName);
        if (propIdx != -1) {
            return true;
        }
    }
    return false;
}

534
bool CppComponentValue::isDerivedFrom(FakeMetaObject::ConstPtr base) const
535
{
536
    foreach (const CppComponentValue *it, prototypes()) {
537
        FakeMetaObject::ConstPtr iter = it->_metaObject;
538
539
540
541
542
543
        if (iter == base)
            return true;
    }
    return false;
}

544
QmlEnumValue::QmlEnumValue(const CppComponentValue *owner, int enumIndex)
545
546
    : _owner(owner)
    , _enumIndex(enumIndex)
Christian Kamm's avatar
Christian Kamm committed
547
{
548
    owner->valueOwner()->registerValue(this);
Christian Kamm's avatar
Christian Kamm committed
549
550
551
552
553
554
}

QmlEnumValue::~QmlEnumValue()
{
}

Christian Kamm's avatar
Christian Kamm committed
555
556
557
558
559
const QmlEnumValue *QmlEnumValue::asQmlEnumValue() const
{
    return this;
}

Christian Kamm's avatar
Christian Kamm committed
560
561
QString QmlEnumValue::name() const
{
562
    return _owner->metaObject()->enumerator(_enumIndex).name();
Christian Kamm's avatar
Christian Kamm committed
563
564
565
566
}

QStringList QmlEnumValue::keys() const
{
567
568
569
    return _owner->metaObject()->enumerator(_enumIndex).keys();
}

570
const CppComponentValue *QmlEnumValue::owner() const
571
572
{
    return _owner;
Christian Kamm's avatar
Christian Kamm committed
573
574
}

575
576
577
////////////////////////////////////////////////////////////////////////////////
// ValueVisitor
////////////////////////////////////////////////////////////////////////////////
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
ValueVisitor::ValueVisitor()
{
}

ValueVisitor::~ValueVisitor()
{
}

void ValueVisitor::visit(const NullValue *)
{
}

void ValueVisitor::visit(const UndefinedValue *)
{
}

594
595
596
597
void ValueVisitor::visit(const UnknownValue *)
{
}

Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
void ValueVisitor::visit(const NumberValue *)
{
}

void ValueVisitor::visit(const BooleanValue *)
{
}

void ValueVisitor::visit(const StringValue *)
{
}

void ValueVisitor::visit(const ObjectValue *)
{
}

void ValueVisitor::visit(const FunctionValue *)
{
}
617

Roberto Raggi's avatar
Roberto Raggi committed
618
619
620
void ValueVisitor::visit(const Reference *)
{
}
621

622
623
624
625
void ValueVisitor::visit(const ColorValue *)
{
}

626
627
628
629
void ValueVisitor::visit(const AnchorLineValue *)
{
}

630
631
632
////////////////////////////////////////////////////////////////////////////////
// Value
////////////////////////////////////////////////////////////////////////////////
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
633
634
635
636
637
638
639
640
Value::Value()
{
}

Value::~Value()
{
}

641
642
643
644
645
bool Value::getSourceLocation(QString *, int *, int *) const
{
    return false;
}

Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
646
647
648
649
650
651
652
653
654
655
const NullValue *Value::asNullValue() const
{
    return 0;
}

const UndefinedValue *Value::asUndefinedValue() const
{
    return 0;
}

656
657
658
659
660
const UnknownValue *Value::asUnknownValue() const
{
    return 0;
}

Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
661
662
663
664
665
const NumberValue *Value::asNumberValue() const
{
    return 0;
}

666
667
668
669
670
671
672
673
674
675
const IntValue *Value::asIntValue() const
{
    return 0;
}

const RealValue *Value::asRealValue() const
{
    return 0;
}

Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
676
677
678
679
680
681
682
683
684
685
const BooleanValue *Value::asBooleanValue() const
{
    return 0;
}

const StringValue *Value::asStringValue() const
{
    return 0;
}

Christian Kamm's avatar
Christian Kamm committed
686
687
688
689
690
const UrlValue *Value::asUrlValue() const
{
    return 0;
}

Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
691
692
693
694
695
696
697
698
699
const ObjectValue *Value::asObjectValue() const
{
    return 0;
}

const FunctionValue *Value::asFunctionValue() const
{
    return 0;
}
700

Roberto Raggi's avatar
Roberto Raggi committed
701
702
703
704
705
const Reference *Value::asReference() const
{
    return 0;
}

706
707
708
709
710
const ColorValue *Value::asColorValue() const
{
    return 0;
}

711
712
713
714
715
const AnchorLineValue *Value::asAnchorLineValue() const
{
    return 0;
}

Christian Kamm's avatar
Christian Kamm committed
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
const CppComponentValue *Value::asCppComponentValue() const
{
    return 0;
}

const ASTObjectValue *Value::asAstObjectValue() const
{
    return 0;
}

const QmlEnumValue *Value::asQmlEnumValue() const
{
    return 0;
}

const QmlPrototypeReference *Value::asQmlPrototypeReference() const
{
    return 0;
}

const ASTPropertyReference *Value::asAstPropertyReference() const
{
    return 0;
}

741
742
743
744
745
const ASTSignal *Value::asAstSignal() const
{
    return 0;
}

746
747
748
////////////////////////////////////////////////////////////////////////////////
// Values
////////////////////////////////////////////////////////////////////////////////
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
const NullValue *NullValue::asNullValue() const
{
    return this;
}

void NullValue::accept(ValueVisitor *visitor) const
{
    visitor->visit(this);
}

const UndefinedValue *UndefinedValue::asUndefinedValue() const
{
    return this;
}

764
void UnknownValue::accept(ValueVisitor *visitor) const
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
765
766
767
{
    visitor->visit(this);
}
768

769
770
771
772
773
774
775
776
777
const UnknownValue *UnknownValue::asUnknownValue() const
{
    return this;
}

void UndefinedValue::accept(ValueVisitor *visitor) const
{
    visitor->visit(this);
}
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
778
779
780
781
782
const NumberValue *NumberValue::asNumberValue() const
{
    return this;
}

783
784
785
786
787
788
789
790
791
792
const RealValue *RealValue::asRealValue() const
{
    return this;
}

const IntValue *IntValue::asIntValue() const
{
    return this;
}

Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
void NumberValue::accept(ValueVisitor *visitor) const
{
    visitor->visit(this);
}

const BooleanValue *BooleanValue::asBooleanValue() const
{
    return this;
}

void BooleanValue::accept(ValueVisitor *visitor) const
{
    visitor->visit(this);
}

const StringValue *StringValue::asStringValue() const
{
    return this;
}

Christian Kamm's avatar
Christian Kamm committed
813
814
815
816
817
const UrlValue *UrlValue::asUrlValue() const
{
    return this;
}

Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
818
819
820
821
822
void StringValue::accept(ValueVisitor *visitor) const
{
    visitor->visit(this);
}

823
824
Reference::Reference(ValueOwner *valueOwner)
    : _valueOwner(valueOwner)
Roberto Raggi's avatar
Roberto Raggi committed
825
{
826
    _valueOwner->registerValue(this);
Roberto Raggi's avatar
Roberto Raggi committed
827
828
829
830
831
832
}

Reference::~Reference()
{
}

833
ValueOwner *Reference::valueOwner() const
834
{
835
    return _valueOwner;
836
837
}

Roberto Raggi's avatar
Roberto Raggi committed
838
839
840
841
842
843
844
845
846
847
const Reference *Reference::asReference() const
{
    return this;
}

void Reference::accept(ValueVisitor *visitor) const
{
    visitor->visit(this);
}

848
const Value *Reference::value(ReferenceContext *) const
849
{
850
    return _valueOwner->undefinedValue();
851
}
Roberto Raggi's avatar
Roberto Raggi committed
852

853
854
855
856
857
858
859
860
861
862
void ColorValue::accept(ValueVisitor *visitor) const
{
    visitor->visit(this);
}

const ColorValue *ColorValue::asColorValue() const
{
    return this;
}

863
864
865
866
867
868
869
870
871
872
void AnchorLineValue::accept(ValueVisitor *visitor) const
{
    visitor->visit(this);
}

const AnchorLineValue *AnchorLineValue::asAnchorLineValue() const
{
    return this;
}

873
874
875
876
877
878
879
880
881
882
883
884
885
MemberProcessor::MemberProcessor()
{
}

MemberProcessor::~MemberProcessor()
{
}

bool MemberProcessor::processProperty(const QString &, const Value *)
{
    return true;
}

886
887
888
889
890
bool MemberProcessor::processEnumerator(const QString &, const Value *)
{
    return true;
}

891
892
893
894
895
896
897
898
899
900
bool MemberProcessor::processSignal(const QString &, const Value *)
{
    return true;
}

bool MemberProcessor::processSlot(const QString &, const Value *)
{
    return true;
}

901
902
903
904
905
bool MemberProcessor::processGeneratedSlot(const QString &, const Value *)
{
    return true;
}

906
907
ObjectValue::ObjectValue(ValueOwner *valueOwner)
    : _valueOwner(valueOwner),
908
      _prototype(0)
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
909
{
910
    valueOwner->registerValue(this);
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
911
912
913
914
915
916
}

ObjectValue::~ObjectValue()
{
}

917
ValueOwner *ObjectValue::valueOwner() const
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
918
{
919
    return _valueOwner;
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
920
921
922
923
924
925
926
927
928
929
930
931
}

QString ObjectValue::className() const
{
    return _className;
}

void ObjectValue::setClassName(const QString &className)
{
    _className = className;
}

932
933
934
935
936
const Value *ObjectValue::prototype() const
{
    return _prototype;
}

937
const ObjectValue *ObjectValue::prototype(const Context *context) const
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
938
{
Christian Kamm's avatar
Christian Kamm committed
939
    const ObjectValue *prototypeObject = value_cast<ObjectValue>(_prototype);
940
    if (! prototypeObject) {
Christian Kamm's avatar
Christian Kamm committed
941
942
        if (const Reference *prototypeReference = value_cast<Reference>(_prototype)) {
            prototypeObject = value_cast<ObjectValue>(context->lookupReference(prototypeReference));
943
944
945
946
947
948
949
950
        }
    }
    return prototypeObject;
}

void ObjectValue::setPrototype(const Value *prototype)
{
    _prototype = prototype;
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
951
952
}

953
void ObjectValue::setMember(const QString &name, const Value *value)
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
954
955
956
957
{
    _members[name] = value;
}

958
void ObjectValue::removeMember(const QString &name)
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
959
960
961
962
963
964
965
966
967
968
969
970
971
972
{
    _members.remove(name);
}

const ObjectValue *ObjectValue::asObjectValue() const
{
    return this;
}

void ObjectValue::accept(ValueVisitor *visitor) const
{
    visitor->visit(this);
}

973
bool ObjectValue::checkPrototype(const ObjectValue *, QSet<const ObjectValue *> *) const
974
{
975
#if 0
976
977
978
979
980
981
982
    const int previousSize = processed->size();
    processed->insert(this);

    if (previousSize != processed->size()) {
        if (this == proto)
            return false;

Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
983
        if (prototype() && ! prototype()->checkPrototype(proto, processed))
984
985
986
987
            return false;

        return true;
    }
988
#endif
989
990
991
    return false;
}

Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
992
993
994
995
996
997
998
void ObjectValue::processMembers(MemberProcessor *processor) const
{
    QHashIterator<QString, const Value *> it(_members);

    while (it.hasNext()) {
        it.next();

999
        if (! processor->processProperty(it.key(), it.value()))
Roberto Raggi's avatar
Cleanup    
Roberto Raggi committed
1000
            break;
For faster browsing, not all history is shown. View entire blame