diff --git a/src/libs/qmljs/qmljscheck.cpp b/src/libs/qmljs/qmljscheck.cpp index 3cbe72b94b2c6bf9df7231c117e77efd987ba449..9ac19d8ed08657e0dfb7d5b3e425127a36ca7f4d 100644 --- a/src/libs/qmljs/qmljscheck.cpp +++ b/src/libs/qmljs/qmljscheck.cpp @@ -197,6 +197,7 @@ Check::Check(Document::Ptr doc, const Snapshot &snapshot, const Context *linkedC , _context(*linkedContextNoScope) , _scopeBuilder(&_context, doc, snapshot) , _ignoreTypeErrors(false) + , _lastValue(0) { } @@ -321,6 +322,63 @@ bool Check::visit(UiArrayBinding *ast) return true; } +bool Check::visit(IdentifierExpression *ast) +{ + // currently disabled: too many false negatives + return true; + + _lastValue = 0; + if (ast->name) { + Evaluate evaluator(&_context); + _lastValue = evaluator.reference(ast); + if (!_lastValue) + error(ast->identifierToken, tr("unknown identifier")); + if (const Reference *ref = value_cast<const Reference *>(_lastValue)) { + _lastValue = _context.lookupReference(ref); + if (!_lastValue) + error(ast->identifierToken, tr("could not resolve")); + } + } + return false; +} + +bool Check::visit(FieldMemberExpression *ast) +{ + // currently disabled: too many false negatives + return true; + + Node::accept(ast->base, this); + if (!_lastValue) + return false; + const ObjectValue *obj = _lastValue->asObjectValue(); + if (!obj) { + error(locationFromRange(ast->base->firstSourceLocation(), ast->base->lastSourceLocation()), + tr("does not have members")); + } + if (!obj || !ast->name) { + _lastValue = 0; + return false; + } + _lastValue = obj->lookupMember(ast->name->asString(), &_context); + if (!_lastValue) + error(ast->identifierToken, tr("unknown member")); + return false; +} + +bool Check::visit(FunctionDeclaration *ast) +{ + return visit(static_cast<FunctionExpression *>(ast)); +} + +bool Check::visit(FunctionExpression *ast) +{ + Node::accept(ast->formals, this); + _scopeBuilder.push(ast); + Node::accept(ast->body, this); + _scopeBuilder.pop(); + return false; +} + /// When something is changed here, also change ReadingContext::lookupProperty in /// texttomodelmerger.cpp /// ### Maybe put this into the context as a helper method. diff --git a/src/libs/qmljs/qmljscheck.h b/src/libs/qmljs/qmljscheck.h index 049b197e5f9b53a239b0990752bd7c57f4055e29..97297eac357eba0dc34ba88d630fa99e05a49fc9 100644 --- a/src/libs/qmljs/qmljscheck.h +++ b/src/libs/qmljs/qmljscheck.h @@ -56,6 +56,10 @@ protected: virtual bool visit(AST::UiObjectBinding *ast); virtual bool visit(AST::UiScriptBinding *ast); virtual bool visit(AST::UiArrayBinding *ast); + virtual bool visit(AST::IdentifierExpression *ast); + virtual bool visit(AST::FieldMemberExpression *ast); + virtual bool visit(AST::FunctionDeclaration *ast); + virtual bool visit(AST::FunctionExpression *ast); private: void visitQmlObject(AST::Node *ast, AST::UiQualifiedId *typeId, @@ -74,6 +78,8 @@ private: QList<DiagnosticMessage> _messages; bool _ignoreTypeErrors; + + const Interpreter::Value *_lastValue; }; QMLJS_EXPORT QColor toQColor(const QString &qmlColorString);