diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.cpp b/src/plugins/qmljsinspector/qmljsclientproxy.cpp index 571d85c8e74b4253a0903693edaf56b35e6bbb8d..9d253c3e852ef21dba70d20da0575eff8ecc9831 100644 --- a/src/plugins/qmljsinspector/qmljsclientproxy.cpp +++ b/src/plugins/qmljsinspector/qmljsclientproxy.cpp @@ -256,12 +256,22 @@ bool ClientProxy::setBindingForObject(int objectDebugId, qDebug() << Q_FUNC_INFO; if (propertyName == QLatin1String("id") || objectDebugId == -1) - return 0; + return false; + + qDebug() << "setBindingForObject():" << objectDebugId << propertyName << value << "isLiteral:" << isLiteralValue; - qDebug() << "executeBinding():" << objectDebugId << propertyName << value << "isLiteral:" << isLiteralValue; return m_client->setBindingForObject(objectDebugId, propertyName, value.toString(), isLiteralValue); } +bool ClientProxy::setMethodBodyForObject(int objectDebugId, const QString &methodName, const QString &methodBody) +{ + if (objectDebugId == -1) + return 0; + + qDebug() << "setMethodBodyForObject():" << objectDebugId << methodName; + return m_client->setMethodBody(objectDebugId, methodName, methodBody); +} + void ClientProxy::queryEngineContext(int id) { if (id < 0) diff --git a/src/plugins/qmljsinspector/qmljsclientproxy.h b/src/plugins/qmljsinspector/qmljsclientproxy.h index 4f5b5ef0dd095944943582de209d4b3513a0c1ad..40fd32185f3bf5cb801fc4d5a3a00d7b518054bf 100644 --- a/src/plugins/qmljsinspector/qmljsclientproxy.h +++ b/src/plugins/qmljsinspector/qmljsclientproxy.h @@ -60,6 +60,8 @@ public: const QVariant &value, bool isLiteralValue); + bool setMethodBodyForObject(int objectDebugId, const QString &methodName, const QString &methodBody); + // returns the object references for the given url. QList<QDeclarativeDebugObjectReference> objectReferences(const QUrl &url = QUrl()) const; QDeclarativeDebugObjectReference objectReferenceForId(int debugId) const; diff --git a/src/plugins/qmljsinspector/qmljsdelta.cpp b/src/plugins/qmljsinspector/qmljsdelta.cpp index 0966ebd28bcb979bd32bc420e12a2785577c0fef..6492c7ed97c7704e3e116cf66feadd00066f6e86 100644 --- a/src/plugins/qmljsinspector/qmljsdelta.cpp +++ b/src/plugins/qmljsinspector/qmljsdelta.cpp @@ -32,6 +32,7 @@ #include <qmljs/parser/qmljsast_p.h> #include <qmljs/parser/qmljsastvisitor_p.h> +#include <typeinfo> #include <QtCore/QDebug> using namespace QmlJS; @@ -75,6 +76,29 @@ QString ScriptBindingParser::scriptCode(UiScriptBinding *script) const return QString(); } + +QString ScriptBindingParser::methodName(UiSourceElement *source) const +{ + if (source) { + if (FunctionDeclaration *declaration = cast<FunctionDeclaration*>(source->sourceElement)) { + return declaration->name->asString(); + } + } + return QString(); +} + +QString ScriptBindingParser::methodCode(UiSourceElement *source) const +{ + if (source) { + if (FunctionDeclaration *declaration = cast<FunctionDeclaration*>(source->sourceElement)) { + const int begin = declaration->lbraceToken.begin() + 1; + const int end = declaration->rbraceToken.end() - 1; + return doc->source().mid(begin, end - begin); + } + } + return QString(); +} + static bool isLiteralValue(ExpressionNode *expr) { if (cast<NumericLiteral*>(expr)) @@ -287,14 +311,33 @@ static QString propertyName(UiQualifiedId *id) return s; } +QDeclarativeDebugObjectReference Delta::objectReferenceForUiObject(const ScriptBindingParser &bindingParser, UiObjectMember *object) +{ + if (UiScriptBinding *idBinding = bindingParser.id(object)) { + if (ExpressionStatement *s = cast<ExpressionStatement *>(idBinding->statement)) { + if (IdentifierExpression *idExpr = cast<IdentifierExpression *>(s->expression)) { + const QString idString = idExpr->name->asString(); + + const QList<QDeclarativeDebugObjectReference> refs = ClientProxy::instance()->objectReferences(_url); + foreach (const QDeclarativeDebugObjectReference &ref, refs) { + if (ref.idString() == idString) + return ref; + } + } + } + } + return QDeclarativeDebugObjectReference(); +} + + void Delta::operator()(Document::Ptr doc, Document::Ptr previousDoc) { _doc = doc; _previousDoc = previousDoc; _changes.clear(); - const QUrl url = QUrl::fromLocalFile(doc->fileName()); - const QList<QDeclarativeDebugObjectReference> references = ClientProxy::instance()->objectReferences(url); + _url = QUrl::fromLocalFile(doc->fileName()); + const QList<QDeclarativeDebugObjectReference> references = ClientProxy::instance()->objectReferences(_url); ScriptBindingParser bindingParser(doc, references); bindingParser.process(); @@ -334,35 +377,56 @@ void Delta::operator()(Document::Ptr doc, Document::Ptr previousDoc) if (scriptCode != previousScriptCode) { const QString property = propertyName(script->qualifiedId); - qDebug() << "property:" << qPrintable(property) << scriptCode; - - if (UiScriptBinding *idBinding = bindingParser.id(object)) { - if (ExpressionStatement *s = cast<ExpressionStatement *>(idBinding->statement)) { - if (IdentifierExpression *idExpr = cast<IdentifierExpression *>(s->expression)) { - const QString idString = idExpr->name->asString(); - qDebug() << "the enclosing object id is:" << idString; - - const QList<QDeclarativeDebugObjectReference> refs = ClientProxy::instance()->objectReferences(url); - foreach (const QDeclarativeDebugObjectReference &ref, refs) { - if (ref.idString() == idString) { - updateScriptBinding(ref, script, property, scriptCode); - break; - } - } - } - } - } + QDeclarativeDebugObjectReference ref = objectReferenceForUiObject(bindingParser, object); + if (ref.debugId() != -1) + updateScriptBinding(ref, script, property, scriptCode); } } } } + } else if (UiSourceElement *uiSource = cast<UiSourceElement*>(objectMemberIt->member)) { + + for (UiObjectMemberList *previousObjectMemberIt = objectMembers(previousObject); + previousObjectMemberIt; previousObjectMemberIt = previousObjectMemberIt->next) + { + if (UiSourceElement *previousSource = cast<UiSourceElement*>(previousObjectMemberIt->member)) { + if (compare(uiSource, previousSource)) + { + const QString methodCode = bindingParser.methodCode(uiSource); + const QString previousMethodCode = previousBindingParser.methodCode(previousSource); + + if (methodCode != previousMethodCode) { + const QString methodName = bindingParser.methodName(uiSource); + qDebug() << methodName << methodCode; + QDeclarativeDebugObjectReference ref = objectReferenceForUiObject(bindingParser, object); + if (ref.debugId() != -1) + updateMethodBody(ref, script, methodName, methodCode); + } + } + } + } + } } } } +void Delta::updateMethodBody(const QDeclarativeDebugObjectReference &objectReference, + UiScriptBinding *scriptBinding, + const QString &methodName, + const QString &methodBody) +{ + Change change; + change.script = scriptBinding; + change.ref = objectReference; + change.isLiteral = false; + _changes.append(change); + + ClientProxy::instance()->setMethodBodyForObject(objectReference.debugId(), methodName, methodBody); // ### remove +} + void Delta::updateScriptBinding(const QDeclarativeDebugObjectReference &objectReference, UiScriptBinding *scriptBinding, const QString &propertyName, @@ -371,7 +435,6 @@ void Delta::updateScriptBinding(const QDeclarativeDebugObjectReference &objectRe qDebug() << "update script:" << propertyName << scriptCode << scriptBinding; QVariant expr = scriptCode; - //qDebug() << " " << scriptBinding->statement->kind << typeid(*scriptBinding->statement).name(); const bool isLiteral = isLiteralValue(scriptBinding); if (isLiteral) @@ -401,6 +464,27 @@ bool Delta::compare(UiQualifiedId *id, UiQualifiedId *other) return false; } +bool Delta::compare(UiSourceElement *source, UiSourceElement *other) +{ + if (source == other) + return true; + + else if (source && other) { + if (source->sourceElement && other->sourceElement) { + FunctionDeclaration *decl = cast<FunctionDeclaration*>(source->sourceElement); + FunctionDeclaration *otherDecl = cast<FunctionDeclaration*>(other->sourceElement); + if (decl && otherDecl + && decl->name && otherDecl->name + && decl->name->asString() == otherDecl->name->asString()) + { + return true; + } + } + } + + return false; +} + UiObjectMemberList *Delta::objectMembers(UiObjectMember *object) { if (UiObjectDefinition *def = cast<UiObjectDefinition *>(object)) diff --git a/src/plugins/qmljsinspector/qmljsdelta.h b/src/plugins/qmljsinspector/qmljsdelta.h index ef8b9454b61b8cd84c9b52ae6e130f5793916c0f..6d462bced79cf34c4655dcc5d6a1ca5f77a1ec04 100644 --- a/src/plugins/qmljsinspector/qmljsdelta.h +++ b/src/plugins/qmljsinspector/qmljsdelta.h @@ -66,6 +66,8 @@ public: QString header(UiObjectMember *member) const; QString scriptCode(UiScriptBinding *script) const; + QString methodName(UiSourceElement *source) const; + QString methodCode(UiSourceElement *source) const; protected: QDeclarativeDebugObjectReference objectReference(const QString &id) const; @@ -112,14 +114,21 @@ private: QmlJS::AST::UiScriptBinding *scriptBinding, const QString &propertyName, const QString &scriptCode); + void updateMethodBody(const QDeclarativeDebugObjectReference &objectReference, + UiScriptBinding *scriptBinding, + const QString &methodName, + const QString &methodBody); + bool compare(UiSourceElement *source, UiSourceElement *other); bool compare(QmlJS::AST::UiQualifiedId *id, QmlJS::AST::UiQualifiedId *other); QmlJS::AST::UiObjectMemberList *objectMembers(QmlJS::AST::UiObjectMember *object); + QDeclarativeDebugObjectReference objectReferenceForUiObject(const ScriptBindingParser &bindingParser, UiObjectMember *object); private: QmlJS::Document::Ptr _doc; QmlJS::Document::Ptr _previousDoc; QList<Change> _changes; + QUrl _url; }; } // namespace Internal diff --git a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp index 9cb2b354a76889c39c1b720a8a4fe561ea75e7b9..865e481192aac712da0cbf5e6f3efbf3ca0fcd94 100644 --- a/src/plugins/qmljsinspector/qmljslivetextpreview.cpp +++ b/src/plugins/qmljsinspector/qmljslivetextpreview.cpp @@ -42,12 +42,12 @@ void QmlJSLiveTextPreview::updateDocuments() return; m_snapshot = modelManager()->snapshot(); + setEditor(Core::EditorManager::instance()->currentEditor()); // initial update foreach (QmlJS::Document::Ptr doc, m_snapshot) { documentChanged(doc); } - connect(modelManager(), SIGNAL(documentChangedOnDisk(QmlJS::Document::Ptr)), SLOT(documentChanged(QmlJS::Document::Ptr))); } @@ -108,10 +108,10 @@ void QmlJSLiveTextPreview::documentChanged(QmlJS::Document::Ptr doc) Core::ICore *core = Core::ICore::instance(); const int dbgcontext = core->uniqueIDManager()->uniqueIdentifier(Debugger::Constants::C_DEBUGMODE); - if (! core->hasContext(dbgcontext)) + if (!core->hasContext(dbgcontext)) return; - if (doc && m_previousDoc) { + if (doc && m_previousDoc && doc->fileName() == m_previousDoc->fileName()) { qDebug() << "Doc, prevDoc:" << doc->fileName() << m_previousDoc->fileName(); Delta delta;