diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index 34bf7eacee961afb04c2ef5eda14060e7f8013f1..7322d1f8f391fb0ba0e95b96dc9311ed523c82d6 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -35,8 +35,13 @@ #include <QtCore/QDebug> #include <QtCore/QCoreApplication> +#include <QtGui/QColor> #include <QtGui/QApplication> +#ifndef NO_DECLARATIVE_BACKEND +# include <QtDeclarative/private/qmlstringconverters_p.h> // ### remove me +#endif + namespace QmlJS { namespace Messages { static const char *invalid_property_name = QT_TRANSLATE_NOOP("QmlJS::Check", "'%1' is not a valid property name"); @@ -144,30 +149,13 @@ bool Check::visit(UiScriptBinding *ast) // ### Fix the evaluator to accept statements! if (ExpressionStatement *expStmt = cast<ExpressionStatement *>(ast->statement)) { ExpressionNode *expr = expStmt->expression; - const SourceLocation loc = locationFromRange(expStmt->firstSourceLocation(), expStmt->lastSourceLocation()); - - // Qml is particularly strict with literals - if (cast<StringLiteral *>(expr) - && ! lhsValue->asStringValue()) { - errorOnWrongRhs(loc, lhsValue); - } else if ((expr->kind == Node::Kind_TrueLiteral - || expr->kind == Node::Kind_FalseLiteral) - && ! lhsValue->asBooleanValue()) { - errorOnWrongRhs(loc, lhsValue); - } else if (cast<NumericLiteral *>(expr) - && ! lhsValue->asNumberValue()) { - errorOnWrongRhs(loc, lhsValue); - } else if (UnaryMinusExpression *unaryMinus = cast<UnaryMinusExpression *>(expr)) { - if (cast<NumericLiteral *>(unaryMinus->expression) - && ! lhsValue->asNumberValue()) { - errorOnWrongRhs(loc, lhsValue); - } - } else { - Evaluate evaluator(&_context); - const Value *rhsValue = evaluator(expr); - - checkPropertyAssignment(loc, lhsValue, rhsValue, expr); - } + + Evaluate evaluator(&_context); + const Value *rhsValue = evaluator(expr); + + const SourceLocation loc = locationFromRange(expStmt->firstSourceLocation(), + expStmt->lastSourceLocation()); + checkPropertyAssignment(loc, lhsValue, rhsValue, expr); } } @@ -180,25 +168,53 @@ void Check::checkPropertyAssignment(const SourceLocation &location, const Interpreter::Value *rhsValue, ExpressionNode *ast) { - if (lhsValue->asEasingCurveNameValue()) { - const StringValue *rhsStringValue = rhsValue->asStringValue(); - if (!rhsStringValue) { - if (rhsValue->asUndefinedValue()) - warning(location, tr(Messages::value_might_be_undefined)); - else - error(location, tr(Messages::easing_curve_not_a_string)); - return; - } - - if (StringLiteral *string = cast<StringLiteral *>(ast)) { - const QString value = string->value->asString(); + UnaryMinusExpression *unaryMinus = cast<UnaryMinusExpression *>(ast); + + // Qml is particularly strict with literals + if (StringLiteral *stringLiteral = cast<StringLiteral *>(ast)) { + const QString string = stringLiteral->value->asString(); + + if (lhsValue->asStringValue()) { + // okay + } else if (lhsValue->asColorValue()) { +#ifndef NO_DECLARATIVE_BACKEND + bool ok = false; + QmlStringConverters::colorFromString(string, &ok); + if (!ok) + error(location, QCoreApplication::translate("QmlJS::Check", "not a valid color")); +#endif + } else if (lhsValue->asEasingCurveNameValue()) { // ### do something with easing-curve attributes. // ### Incomplete documentation at: http://qt.nokia.com/doc/4.7-snapshot/qml-propertyanimation.html#easing-prop // ### The implementation is at: src/declarative/util/qmlanimation.cpp - const QString curveName = value.left(value.indexOf(QLatin1Char('('))); + const QString curveName = string.left(string.indexOf(QLatin1Char('('))); if (!EasingCurveNameValue::curveNames().contains(curveName)) { error(location, tr(Messages::unknown_easing_curve_name)); } + } else { + errorOnWrongRhs(location, lhsValue); + } + } else if ((ast->kind == Node::Kind_TrueLiteral + || ast->kind == Node::Kind_FalseLiteral) + && ! lhsValue->asBooleanValue()) { + errorOnWrongRhs(location, lhsValue); + } else if (cast<NumericLiteral *>(ast) + && ! lhsValue->asNumberValue()) { + errorOnWrongRhs(location, lhsValue); + } else if (unaryMinus && cast<NumericLiteral *>(unaryMinus->expression) + && ! lhsValue->asNumberValue()) { + errorOnWrongRhs(location, lhsValue); + } else { + // rhs is not a literal + if (lhsValue->asEasingCurveNameValue()) { + const StringValue *rhsStringValue = rhsValue->asStringValue(); + if (!rhsStringValue) { + if (rhsValue->asUndefinedValue()) + warning(location, tr(Messages::value_might_be_undefined)); + else + error(location, tr(Messages::easing_curve_not_a_string)); + return; + } } } } diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp index 9a287b44e95f50a0324cbe7ddfcfe341226cf5d9..9d4461749f39f5151d0a5c500e70ee9e5cd5e59d 100644 --- a/src/libs/qmljs/qmljsinterpreter.cpp +++ b/src/libs/qmljs/qmljsinterpreter.cpp @@ -326,6 +326,10 @@ const Value *QmlObjectValue::propertyValue(const QMetaProperty &prop) const value = object; } break; + case QMetaType::QColor: { + value = engine()->colorValue(); + } break; + default: break; } // end of switch @@ -610,6 +614,10 @@ void ValueVisitor::visit(const EasingCurveNameValue *) { } +void ValueVisitor::visit(const ColorValue *) +{ +} + //////////////////////////////////////////////////////////////////////////////// // Value //////////////////////////////////////////////////////////////////////////////// @@ -671,6 +679,11 @@ const EasingCurveNameValue *Value::asEasingCurveNameValue() const return 0; } +const ColorValue *Value::asColorValue() const +{ + return 0; +} + //////////////////////////////////////////////////////////////////////////////// // Values //////////////////////////////////////////////////////////////////////////////// @@ -977,6 +990,16 @@ const EasingCurveNameValue *EasingCurveNameValue::asEasingCurveNameValue() const return this; } +void ColorValue::accept(ValueVisitor *visitor) const +{ + visitor->visit(this); +} + +const ColorValue *ColorValue::asColorValue() const +{ + return this; +} + MemberProcessor::MemberProcessor() { } @@ -1621,6 +1644,11 @@ const EasingCurveNameValue *Engine::easingCurveNameValue() const return &_easingCurveNameValue; } +const ColorValue *Engine::colorValue() const +{ + return &_colorValue; +} + const Value *Engine::newArray() { return arrayCtor()->construct(); diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h index a0ab3fbc4c34f27bc71ba165d53616f1e8bfb2ce..35137579e7adfcff52438cb968bc328d895befac 100644 --- a/src/libs/qmljs/qmljsinterpreter.h +++ b/src/libs/qmljs/qmljsinterpreter.h @@ -61,6 +61,7 @@ class ObjectValue; class FunctionValue; class Reference; class EasingCurveNameValue; +class ColorValue; typedef QList<const Value *> ValueList; @@ -82,6 +83,7 @@ public: virtual void visit(const FunctionValue *); virtual void visit(const Reference *); virtual void visit(const EasingCurveNameValue *); + virtual void visit(const ColorValue *); }; //////////////////////////////////////////////////////////////////////////////// @@ -105,6 +107,7 @@ public: virtual const FunctionValue *asFunctionValue() const; virtual const Reference *asReference() const; virtual const EasingCurveNameValue *asEasingCurveNameValue() const; + virtual const ColorValue *asColorValue() const; virtual void accept(ValueVisitor *) const = 0; @@ -167,6 +170,12 @@ template <> Q_INLINE_TEMPLATE const EasingCurveNameValue *value_cast(const Value else return 0; } +template <> Q_INLINE_TEMPLATE const ColorValue *value_cast(const Value *v) +{ + if (v) return v->asColorValue(); + else return 0; +} + //////////////////////////////////////////////////////////////////////////////// // Value nodes //////////////////////////////////////////////////////////////////////////////// @@ -326,6 +335,14 @@ public: virtual void accept(ValueVisitor *) const; }; +class QMLJS_EXPORT ColorValue: public Value +{ +public: + // Value interface + virtual const ColorValue *asColorValue() const; + virtual void accept(ValueVisitor *) const; +}; + class QMLJS_EXPORT ObjectValue: public Value { public: @@ -585,6 +602,7 @@ public: const BooleanValue *booleanValue() const; const StringValue *stringValue() const; const EasingCurveNameValue *easingCurveNameValue() const; + const ColorValue *colorValue() const; ObjectValue *newObject(const ObjectValue *prototype); ObjectValue *newObject(); @@ -674,6 +692,7 @@ private: BooleanValue _booleanValue; StringValue _stringValue; EasingCurveNameValue _easingCurveNameValue; + ColorValue _colorValue; QList<Value *> _registeredValues; ConvertToNumber _convertToNumber;