aboutsummaryrefslogtreecommitdiffstats
path: root/src/libs/qmljs/qmljscheck.cpp
diff options
context:
space:
mode:
authorChristian Kamm <[email protected]>2010-02-23 17:02:50 +0100
committerChristian Kamm <[email protected]>2010-02-23 17:03:05 +0100
commitf0674aa7e9853cf5d3d48e3832a67de1b4033ad9 (patch)
tree6a7fff8a28473937e15eb5a7e67f8ec51705ddb7 /src/libs/qmljs/qmljscheck.cpp
parent04d90d9563f347af36db08602535da66ed1963aa (diff)
Add check for anchor line, changed value assignment checks into visitor.
Done-with: Erik Verbruggen
Diffstat (limited to 'src/libs/qmljs/qmljscheck.cpp')
-rw-r--r--src/libs/qmljs/qmljscheck.cpp174
1 files changed, 106 insertions, 68 deletions
diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp
index 8269f92c893..8a7592dfc0e 100644
--- a/src/libs/qmljs/qmljscheck.cpp
+++ b/src/libs/qmljs/qmljscheck.cpp
@@ -62,6 +62,108 @@ using namespace QmlJS;
using namespace QmlJS::AST;
using namespace QmlJS::Interpreter;
+
+namespace {
+
+class AssignmentCheck : public ValueVisitor
+{
+public:
+ DiagnosticMessage operator()(
+ const SourceLocation &location,
+ const Interpreter::Value *lhsValue,
+ const Interpreter::Value *rhsValue,
+ ExpressionNode *ast)
+ {
+ _message = DiagnosticMessage(DiagnosticMessage::Error, location, QString());
+ _rhsValue = rhsValue;
+ _ast = ast;
+
+ if (lhsValue)
+ lhsValue->accept(this);
+
+ return _message;
+ }
+
+ virtual void visit(const NumberValue *)
+ {
+ // ### Consider enums: elide: "ElideLeft" is valid, but currently elide is a NumberValue.
+ if (/*cast<StringLiteral *>(_ast)
+ ||*/ _ast->kind == Node::Kind_TrueLiteral
+ || _ast->kind == Node::Kind_FalseLiteral) {
+ _message.message = QCoreApplication::translate("QmlJS::Check", "numerical value expected");
+ }
+ }
+
+ virtual void visit(const BooleanValue *)
+ {
+ UnaryMinusExpression *unaryMinus = cast<UnaryMinusExpression *>(_ast);
+
+ if (cast<StringLiteral *>(_ast)
+ || cast<NumericLiteral *>(_ast)
+ || (unaryMinus && cast<NumericLiteral *>(unaryMinus->expression))) {
+ _message.message = QCoreApplication::translate("QmlJS::Check", "boolean value expected");
+ }
+ }
+
+ virtual void visit(const StringValue *)
+ {
+ UnaryMinusExpression *unaryMinus = cast<UnaryMinusExpression *>(_ast);
+
+ if (cast<NumericLiteral *>(_ast)
+ || (unaryMinus && cast<NumericLiteral *>(unaryMinus->expression))
+ || _ast->kind == Node::Kind_TrueLiteral
+ || _ast->kind == Node::Kind_FalseLiteral) {
+ _message.message = QCoreApplication::translate("QmlJS::Check", "string value expected");
+ }
+ }
+
+ virtual void visit(const EasingCurveNameValue *)
+ {
+ if (StringLiteral *stringLiteral = cast<StringLiteral *>(_ast)) {
+ const QString curveName = stringLiteral->value->asString();
+
+ // ### update when easing changes hit master
+ if (!EasingCurveNameValue::curveNames().contains(curveName)) {
+ _message.message = tr(Messages::unknown_easing_curve_name);
+ }
+ } else if (_rhsValue->asUndefinedValue()) {
+ _message.kind = DiagnosticMessage::Warning;
+ _message.message = tr(Messages::value_might_be_undefined);
+ } else if (! _rhsValue->asStringValue()) {
+ _message.message = tr(Messages::easing_curve_not_a_string);
+ }
+ }
+
+ virtual void visit(const ColorValue *)
+ {
+ if (StringLiteral *stringLiteral = cast<StringLiteral *>(_ast)) {
+ const QString colorString = stringLiteral->value->asString();
+
+#ifndef NO_DECLARATIVE_BACKEND
+ bool ok = false;
+ QmlStringConverters::colorFromString(colorString, &ok);
+ if (!ok)
+ _message.message = QCoreApplication::translate("QmlJS::Check", "not a valid color");
+#endif
+ } else {
+ visit((StringValue *)0);
+ }
+ }
+
+ virtual void visit(const AnchorLineValue *)
+ {
+ if (! (_rhsValue->asAnchorLineValue() || _rhsValue->asUndefinedValue()))
+ _message.message = QCoreApplication::translate("QmlJS::Check", "expected anchor line");
+ }
+
+ DiagnosticMessage _message;
+ const Value *_rhsValue;
+ ExpressionNode *_ast;
+};
+
+} // end of anonymous namespace
+
+
Check::Check(Document::Ptr doc, const Snapshot &snapshot)
: _doc(doc)
, _snapshot(snapshot)
@@ -131,17 +233,6 @@ void Check::visitQmlObject(Node *ast, UiQualifiedId *typeId,
_scopeBuilder.pop();
}
-void Check::errorOnWrongRhs(const SourceLocation &loc, const Value *lhsValue)
-{
- if (lhsValue->asBooleanValue()) {
- error(loc, QCoreApplication::translate("QmlJS::Check", "boolean value expected"));
- } else if (lhsValue->asNumberValue()) {
- error(loc, QCoreApplication::translate("QmlJS::Check", "numerical value expected"));
- } else if (lhsValue->asStringValue()) {
- error(loc, QCoreApplication::translate("QmlJS::Check", "string value expected"));
- }
-}
-
bool Check::visit(UiScriptBinding *ast)
{
// special case for id property
@@ -181,7 +272,10 @@ bool Check::visit(UiScriptBinding *ast)
const SourceLocation loc = locationFromRange(expStmt->firstSourceLocation(),
expStmt->lastSourceLocation());
- checkPropertyAssignment(loc, lhsValue, rhsValue, expr);
+ AssignmentCheck assignmentCheck;
+ DiagnosticMessage message = assignmentCheck(loc, lhsValue, rhsValue, expr);
+ if (! message.message.isEmpty())
+ _messages += message;
}
}
@@ -189,62 +283,6 @@ bool Check::visit(UiScriptBinding *ast)
return true;
}
-void Check::checkPropertyAssignment(const SourceLocation &location,
- const Interpreter::Value *lhsValue,
- const Interpreter::Value *rhsValue,
- ExpressionNode *ast)
-{
- 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 = 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;
- }
- }
- }
-}
-
bool Check::visit(UiArrayBinding *ast)
{
checkScopeObjectMember(ast->qualifiedId);