summaryrefslogtreecommitdiff
path: root/src/libs/qmljs/qmljsdelta.cpp
diff options
context:
space:
mode:
authorKai Koehne <kai.koehne@theqtcompany.com>2015-04-24 15:17:13 +0200
committerhjk <hjk@theqtcompany.com>2015-04-24 13:26:37 +0000
commit40dc289360099d321bbab5292a19fae5c42a4ed8 (patch)
tree87ca7dfbe1f0510ed18d1a15abfa676e6e0f587b /src/libs/qmljs/qmljsdelta.cpp
parent7b0c8b160a0e15edc40504a65a4f3fca52308153 (diff)
downloadqt-creator-40dc289360099d321bbab5292a19fae5c42a4ed8.tar.gz
Remove QmLJSDelta class
The class was only used for the Apply on Save functionality in the QML Debugger, which got nuked in 3bf81efbe73ac2a731. Change-Id: I1842cc07d61fe84f8da23210ebac04dd4d567fce Reviewed-by: Marco Benelli <marco.benelli@theqtcompany.com> Reviewed-by: hjk <hjk@theqtcompany.com>
Diffstat (limited to 'src/libs/qmljs/qmljsdelta.cpp')
-rw-r--r--src/libs/qmljs/qmljsdelta.cpp582
1 files changed, 0 insertions, 582 deletions
diff --git a/src/libs/qmljs/qmljsdelta.cpp b/src/libs/qmljs/qmljsdelta.cpp
deleted file mode 100644
index d9be242e60..0000000000
--- a/src/libs/qmljs/qmljsdelta.cpp
+++ /dev/null
@@ -1,582 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2015 The Qt Company Ltd.
-** Contact: http://www.qt.io/licensing
-**
-** This file is part of Qt Creator.
-**
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms and
-** conditions see http://www.qt.io/terms-conditions. For further information
-** use the contact form at http://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 or version 3 as published by the Free
-** Software Foundation and appearing in the file LICENSE.LGPLv21 and
-** LICENSE.LGPLv3 included in the packaging of this file. Please review the
-** following information to ensure the GNU Lesser General Public License
-** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, The Qt Company gives you certain additional
-** rights. These rights are described in The Qt Company LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-****************************************************************************/
-
-#include "qmljsdelta.h"
-#include "qmljsutils.h"
-#include <qmljs/parser/qmljsast_p.h>
-
-
-#include <typeinfo>
-#include <QDebug>
-#include <QStringList>
-
-
-using namespace QmlJS::AST;
-
-namespace {
-using namespace QmlJS;
-
-enum {
- debug = false
-};
-
-/*!
- Build a hash of the parents
- */
-struct BuildParentHash : public Visitor
-{
- virtual void postVisit(Node* );
- virtual bool preVisit(Node* );
- QHash<UiObjectMember *, UiObjectMember *> parent;
-private:
- QList<UiObjectMember *> stack;
-};
-
-bool BuildParentHash::preVisit(Node* ast)
-{
- if (ast->uiObjectMemberCast())
- stack.append(ast->uiObjectMemberCast());
- return true;
-}
-
-void BuildParentHash::postVisit(Node* ast)
-{
- if (ast->uiObjectMemberCast()) {
- stack.removeLast();
- if (!stack.isEmpty())
- parent.insert(ast->uiObjectMemberCast(), stack.last());
- }
-}
-
-static QString label(UiQualifiedId *id)
-{
- QString str;
- for (; id ; id = id->next) {
- if (id->name.isEmpty())
- return QString();
- if (!str.isEmpty())
- str += QLatin1Char('.');
- str += id->name;
- }
- return str;
-}
-
-//return a label string for a AST node that is suitable to compare them.
-static QString label(UiObjectMember *member, Document::Ptr doc)
-{
- QString str;
- if (!member)
- return str;
-
- if (UiObjectDefinition* foo = cast<UiObjectDefinition *>(member)) {
- str = label(foo->qualifiedTypeNameId);
- } else if (UiObjectBinding *foo = cast<UiObjectBinding *>(member)) {
- str = label(foo->qualifiedId) + QLatin1Char(' ') + label(foo->qualifiedTypeNameId);
- } else if (UiArrayBinding *foo = cast<UiArrayBinding *>(member)) {
- str = label(foo->qualifiedId) + QLatin1String("[]");
- } else if (UiScriptBinding *foo = cast<UiScriptBinding *>(member)) {
- str = label(foo->qualifiedId) + QLatin1Char(':');
- if (foo->statement) {
- quint32 start = foo->statement->firstSourceLocation().begin();
- quint32 end = foo->statement->lastSourceLocation().end();
- str += doc->source().midRef(start, end-start);
- }
- } else {
- quint32 start = member->firstSourceLocation().begin();
- quint32 end = member->lastSourceLocation().end();
- str = doc->source().mid(start, end-start);
- }
- return str;
-}
-
-/* Find nodes in the tree that have the given label */
-struct FindObjectMemberWithLabel : public Visitor
-{
- virtual void endVisit(UiObjectDefinition *ast) ;
- virtual void endVisit(UiObjectBinding *ast) ;
-
- QList<UiObjectMember *> found;
- QString ref_label;
- Document::Ptr doc;
-};
-
-void FindObjectMemberWithLabel::endVisit(UiObjectDefinition* ast)
-{
- if (label(ast, doc) == ref_label)
- found.append(ast);
-}
-void FindObjectMemberWithLabel::endVisit(UiObjectBinding* ast)
-{
- if (label(ast, doc) == ref_label)
- found.append(ast);
-}
-
-/*
- bidirrection mapping between the old and the new tree nodes
-*/
-struct Map {
- typedef UiObjectMember *T1;
- typedef UiObjectMember *T2;
- QHash<T1, T2> way1;
- QHash<T2, T1> way2;
- void insert(T1 t1, T2 t2) {
- way1.insert(t1, t2);
- way2.insert(t2, t1);
- }
- int count() { return way1.count(); }
- void operator+=(const Map &other) {
- way1.unite(other.way1);
- way2.unite(other.way2);
- }
- bool contains(T1 t1, T2 t2) {
- return way1.value(t1) == t2;
- }
-};
-
-//return the list of children node of an ast node
-static QList<UiObjectMember *> children(UiObjectMember *ast)
-{
- QList<UiObjectMember *> ret;
- if (UiObjectInitializer * foo = QmlJS::initializerOfObject(ast)) {
- UiObjectMemberList* list = foo->members;
- while (list) {
- ret.append(list->member);
- list = list->next;
- }
- } else if (UiArrayBinding *foo = cast<UiArrayBinding *>(ast)) {
- UiArrayMemberList* list = foo->members;
- while (list) {
- ret.append(list->member);
- list = list->next;
- }
- }
- return ret;
-}
-
-/* build a mapping between nodes of two subtree of an ast. x and y are the root of the two subtrees */
-static Map buildMapping_helper(UiObjectMember *x, UiObjectMember *y, const Map &M, Document::Ptr doc1, Document::Ptr doc2) {
- Map M2;
- if (M.way1.contains(x))
- return M2;
- if (M.way2.contains(y))
- return M2;
- if (label(x, doc1) != label(y, doc2))
- return M2;
- M2.insert(x, y);
- QList<UiObjectMember *> list1 = children(x);
- QList<UiObjectMember *> list2 = children(y);
- for (int i = 0; i < list1.count(); i++) {
- QString l = label(list1[i], doc1);
- int foundJ = -1;
- Map M3;
- for (int j = 0; j < list2.count(); j++) {
- if (l != label(list2[j], doc2))
- continue;
- Map M4 = buildMapping_helper(list1[i], list2[j], M, doc1, doc2);
- if (M4.count() > M3.count()) {
- M3 = M4;
- foundJ = j;
- }
- }
- if (foundJ != -1) {
- list2.removeAt(foundJ);
- M2 += M3;
- }
- }
- return M2;
-}
-
-/* given two AST, build a mapping between the corresponding nodes of the two tree
-*/
-static Map buildMapping(Document::Ptr doc1, Document::Ptr doc2)
-{
- Map M;
- QList<UiObjectMember *> todo;
- todo.append(doc1->qmlProgram()->members->member);
- while (!todo.isEmpty()) {
- UiObjectMember *x = todo.takeFirst();
- todo += children(x);
-
- if (M.way1.contains(x))
- continue;
-
- //If this is too slow, we could use some sort of indexing
- FindObjectMemberWithLabel v3;
- v3.ref_label = label(x, doc1);
- v3.doc = doc2;
- doc2->qmlProgram()->accept(&v3);
- Map M2;
- foreach (UiObjectMember *y, v3.found) {
- if (M.way2.contains(y))
- continue;
- Map M3 = buildMapping_helper(x, y, M, doc1, doc2);
- if (M3.count() > M2.count())
- M2 = M3;
- }
- M += M2;
- }
- return M;
-}
-
-
-static QString _scriptCode(UiScriptBinding *script, Document::Ptr doc)
-{
- if (script) {
- const int begin = script->statement->firstSourceLocation().begin();
- const int end = script->statement->lastSourceLocation().end();
- return doc->source().mid(begin, end - begin);
- }
- return QString();
-}
-
-static QString _methodCode(UiSourceElement *source, Document::Ptr doc)
-{
- 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 QString _propertyName(UiQualifiedId *id)
-{
- QString s;
-
- for (; id; id = id->next) {
- if (id->name.isEmpty())
- return QString();
-
- s += id->name;
-
- if (id->next)
- s += QLatin1Char('.');
- }
-
- return s;
-}
-
-static QString _methodName(UiSourceElement *source)
-{
- if (source) {
- if (FunctionDeclaration *declaration = cast<FunctionDeclaration*>(source->sourceElement))
- return declaration->name.toString();
- }
- return QString();
-}
-
-static UiObjectMemberList *objectMembers(UiObjectMember *object)
-{
- if (UiObjectInitializer *init = QmlJS::initializerOfObject(object))
- return init->members;
-
- return 0;
-}
-
-
-static QHash<QString, UiObjectMember*> extractProperties(UiObjectMember *object)
-{
- QHash<QString, UiObjectMember*> result;
- for (UiObjectMemberList *objectMemberIt = objectMembers(object); objectMemberIt; objectMemberIt = objectMemberIt->next) {
- if (UiScriptBinding *script = cast<UiScriptBinding *>(objectMemberIt->member)) {
- const QString property = _propertyName(script->qualifiedId);
- result.insert(property, script);
- } else if (UiObjectDefinition *uiObject = cast<UiObjectDefinition *>(objectMemberIt->member)) {
- const QString l = label(uiObject->qualifiedTypeNameId);
- if (!l.isEmpty() && !l[0].isUpper()) {
- QHash<QString, UiObjectMember *> recursiveResult = extractProperties(uiObject);
- for (QHash<QString, UiObjectMember *>::const_iterator it = recursiveResult.constBegin();
- it != recursiveResult.constEnd(); ++it) {
- result.insert(l + QLatin1Char('.') + it.key(), it.value());
- }
- }
- } else if (UiSourceElement *uiSource = cast<UiSourceElement*>(objectMemberIt->member)) {
- const QString methodName = _methodName(uiSource);
- result.insert(methodName, uiSource);
- }
- }
- return result;
-}
-
-} //end namespace
-
-namespace QmlJS {
-
-void Delta::insert(UiObjectMember *member, UiObjectMember *parentMember, const QList<DebugId> &debugReferences, const Document::Ptr &doc)
-{
- if (!member || !parentMember)
- return;
-
- bool accepted = false;
- // initialized with garbage
- unsigned begin = 1, end = 2, startColumn = 3, startLine = 4;
-
- // create new objects
- if (UiObjectDefinition* uiObjectDef = cast<UiObjectDefinition *>(member)) {
- begin = uiObjectDef->firstSourceLocation().begin();
- end = uiObjectDef->lastSourceLocation().end();
- startColumn = uiObjectDef->firstSourceLocation().startColumn;
- startLine = uiObjectDef->firstSourceLocation().startLine;
- accepted = true;
- }
-
- if (UiObjectBinding* uiObjectBind = cast<UiObjectBinding *>(member)) {
- SourceLocation definitionLocation = uiObjectBind->qualifiedTypeNameId->identifierToken;
- begin = definitionLocation.begin();
- end = uiObjectBind->lastSourceLocation().end();
- startColumn = definitionLocation.startColumn;
- startLine = definitionLocation.startLine;
- accepted = true;
- }
-
- if (accepted) {
- QString qmlText = QString(startColumn - 1, QLatin1Char(' '));
- qmlText += doc->source().midRef(begin, end - begin);
-
- QStringList importList;
- for (UiHeaderItemList *it = doc->qmlProgram()->headers; it; it = it->next) {
- UiImport *import = AST::cast<UiImport *>(it->headerItem);
- if (!import)
- continue;
- unsigned importBegin = import->firstSourceLocation().begin();
- unsigned importEnd = import->lastSourceLocation().end();
-
- importList << doc->source().mid(importBegin, importEnd - importBegin);
- }
-
- // encode editorRevision, lineNumber in URL. See ClientProxy::buildDebugIdHashRecursive
- // Also, a relative URL is expected (no "file://" prepending!)
- QString filename = doc->fileName() + QLatin1Char('_') + QString::number(doc->editorRevision())
- + QLatin1Char(':') + QString::number(startLine-importList.count());
- foreach (DebugId debugId, debugReferences) {
- if (debugId != -1) {
- int order = 0;
- // skip children which are not objects
- foreach (const UiObjectMember *child, children(parentMember)) {
- if (child == member) break;
- if (child->kind == AST::Node::Kind_UiObjectDefinition)
- order++;
- }
- createObject(qmlText, debugId, importList, filename, order);
- }
- }
- newObjects += member;
- }
-}
-
-void Delta::update(UiObjectMember* oldObject, const QmlJS::Document::Ptr& oldDoc,
- UiObjectMember* newObject, const QmlJS::Document::Ptr& newDoc,
- const QList<DebugId>& debugReferences)
-{
- Q_ASSERT (oldObject && newObject);
-
- const QHash<QString, UiObjectMember *> oldProperties = extractProperties(oldObject);
- const QHash<QString, UiObjectMember *> newProperties = extractProperties(newObject);
-
- for (QHash<QString, UiObjectMember *>::const_iterator it = newProperties.constBegin();
- it != newProperties.constEnd(); ++it) {
-
- UiObjectMember *oldMember = oldProperties.value(it.key());
- if (UiScriptBinding *script = cast<UiScriptBinding *>(*it)) {
- const QString property = it.key();
- const QString scriptCode = _scriptCode(script, newDoc);
- UiScriptBinding *previousScript = cast<UiScriptBinding *>(oldMember);
- if (!previousScript || _scriptCode(previousScript, oldDoc) != scriptCode) {
- if (debugReferences.count()==0)
- notifyUnsyncronizableElementChange(newObject);
- foreach (DebugId ref, debugReferences) {
- if (ref != -1)
- updateScriptBinding(ref, newObject, script, property, scriptCode);
- }
- }
- } else if (UiSourceElement *uiSource = cast<UiSourceElement*>(*it)) {
- const QString methodName = it.key();
- const QString methodCode = _methodCode(uiSource, newDoc);
- UiSourceElement *previousSource = cast<UiSourceElement*>(oldMember);
-
- if (!previousSource || _methodCode(previousSource, oldDoc) != methodCode) {
- if (debugReferences.count()==0)
- notifyUnsyncronizableElementChange(newObject);
- foreach (DebugId ref, debugReferences) {
- if (ref != -1)
- updateMethodBody(ref, newObject, script, methodName, methodCode);
- }
- }
- }
- }
-
- //reset property that are not present in the new object.
- for (QHash<QString, UiObjectMember *>::const_iterator it2 = oldProperties.constBegin();
- it2 != oldProperties.constEnd(); ++it2) {
-
- if (!newProperties.contains(it2.key())) {
- if (cast<UiScriptBinding *>(*it2)) {
- foreach (DebugId ref, debugReferences) {
- if (ref != -1)
- resetBindingForObject(ref, it2.key());
- }
- }
- }
- }
-}
-
-void Delta::remove(const QList<DebugId>& debugReferences)
-{
- foreach (DebugId ref, debugReferences) {
- if (ref != -1)
- removeObject(ref);
- }
-}
-
-void Delta::reparent(const QList <DebugId> &member, const QList<DebugId> &newParent)
-{
- if (member.length() != newParent.length()) return;
-
- for (int i=0; i<member.length(); i++)
- reparentObject(member.at(i), newParent.at(i));
-}
-
-
-Delta::DebugIdMap Delta::operator()(const Document::Ptr &doc1, const Document::Ptr &doc2, const DebugIdMap &debugIds)
-{
- Q_ASSERT(doc1->qmlProgram());
- Q_ASSERT(doc2->qmlProgram());
-
- m_previousDoc = doc1;
- m_currentDoc = doc2;
-
- Delta::DebugIdMap newDebuggIds;
-
- Map M = buildMapping(doc1, doc2);
-
- BuildParentHash parents2;
- doc2->qmlProgram()->accept(&parents2);
- BuildParentHash parents1;
- doc1->qmlProgram()->accept(&parents1);
-
- QList<UiObjectMember *> todo;
- todo.append(doc2->qmlProgram()->members->member);
- //UiObjectMemberList *list = 0;
- while (!todo.isEmpty()) {
- UiObjectMember *y = todo.takeFirst();
- todo += children(y);
-
- if (!cast<UiObjectDefinition *>(y) && !cast<UiObjectBinding *>(y))
- continue;
-
- if (!M.way2.contains(y)) {
- UiObjectMember* parent = parents2.parent.value(y);
- if (parent) {
- if ( parent->kind == QmlJS::AST::Node::Kind_UiArrayBinding )
- parent = parents2.parent.value(parent);
-
- if (M.way2.contains(parent) && newDebuggIds.value(parent).count() > 0) {
- if (debug)
- qDebug () << "Delta::operator(): insert " << label(y, doc2) << " to " << label(parent, doc2);
- insert(y, parent, newDebuggIds.value(parent), doc2);
- }
- }
- continue;
- }
- UiObjectMember *x = M.way2[y];
- Q_ASSERT(cast<UiObjectDefinition *>(x) || cast<UiObjectBinding *>(x) );
-
- {
- QList<DebugId> updateIds;
- if (debugIds.contains(x)) {
- updateIds = debugIds[x];
- newDebuggIds[y] = updateIds;
- }
- if (debug)
- qDebug () << "Delta::operator(): update " << label(x,doc1);
- update(x, doc1, y, doc2, updateIds);
- }
- //qDebug() << "Delta::operator(): match "<< label(x, doc1) << "with parent " << label(parents1.parent.value(x), doc1)
- // << " to "<< label(y, doc2) << "with parent " << label(parents2.parent.value(y), doc2);
-
- if (!M.contains(parents1.parent.value(x),parents2.parent.value(y))) {
- if (debug)
- qDebug () << "Delta::operator(): move " << label(y, doc2) << " from " << label(parents1.parent.value(x), doc1)
- << " to " << label(parents2.parent.value(y), doc2);
- reparent(newDebuggIds.value(y), newDebuggIds.value(parents2.parent.value(y)));
- continue;
- }
- }
-
- todo.append(doc1->qmlProgram()->members->member);
- while (!todo.isEmpty()) {
- UiObjectMember *x = todo.takeFirst();
- todo += children(x);
- if (!cast<UiObjectDefinition *>(x))
- continue;
- if (!M.way1.contains(x)) {
- if (debug)
- qDebug () << "Delta::operator(): remove " << label(x, doc1);
- QList<DebugId> ids = debugIds.value(x);
- if (!ids.isEmpty())
- remove(ids);
- continue;
- }
- }
- return newDebuggIds;
-}
-
-Document::Ptr Delta::document() const
-{
- return m_currentDoc;
-}
-
-Document::Ptr Delta::previousDocument() const
-{
- return m_previousDoc;
-}
-
-void Delta::createObject(const QString &, DebugId, const QStringList &, const QString&, int)
-{}
-void Delta::removeObject(int)
-{}
-void Delta::reparentObject(int, int)
-{}
-void Delta::resetBindingForObject(int, const QString &)
-{}
-void Delta::updateMethodBody(DebugId, UiObjectMember *, UiScriptBinding *, const QString &, const QString &)
-{}
-
-void Delta::updateScriptBinding(DebugId, UiObjectMember *, UiScriptBinding *, const QString &, const QString &)
-{}
-
-void Delta::notifyUnsyncronizableElementChange(UiObjectMember *)
-{}
-
-} //namespace QmlJs
-