diff --git a/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.cpp index 68833e98d54f9c085893b10f196ffb4bba6c872c..0c2e935e38053f113694d1ce75fdcc3da7764b03 100644 --- a/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.cpp +++ b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.cpp @@ -27,8 +27,8 @@ ** **************************************************************************/ -#include <qmljsast_p.h> -#include <qmljsengine_p.h> +#include <qmljs/parser/qmljsast_p.h> +#include <qmljs/parser/qmljsengine_p.h> #include "changeimportsvisitor.h" @@ -37,44 +37,67 @@ using namespace QmlJS::AST; using namespace QmlDesigner; using namespace QmlDesigner::Internal; -using namespace QmlDesigner::Internal; -ChangeImportsVisitor::ChangeImportsVisitor(TextModifier &textModifier, const QSet<Import> &addedImports, const QSet<Import> &removedImports, const QString &source): - QMLRewriter(textModifier), - CopyPasteUtil(source), - m_addedImports(addedImports), - m_removedImports(removedImports) -{ -} +ChangeImportsVisitor::ChangeImportsVisitor(TextModifier &textModifier, + const QString &source): + QMLRewriter(textModifier), m_source(source) +{} -bool ChangeImportsVisitor::visit(QmlJS::AST::UiProgram *ast) +bool ChangeImportsVisitor::add(QmlJS::AST::UiProgram *ast, const Import &import) { - if (ast->imports) - accept(ast->imports); + setDidRewriting(false); + if (!ast) + return false; + + if (ast->imports && ast->imports->import) { + int insertionPoint = 0; + if (ast->members && ast->members->member) { + insertionPoint = ast->members->member->firstSourceLocation().begin(); + } else { + insertionPoint = m_source.length(); + } + while (insertionPoint > 0) { + --insertionPoint; + const QChar c = m_source.at(insertionPoint); + if (!c.isSpace() && c != QLatin1Char(';')) + break; + } + replace(insertionPoint, 0, QLatin1String("\n") + import.toString(false)); + } else { + replace(0, 0, import.toString(false) + QLatin1String("\n\n")); + } + + setDidRewriting(true); - return false; + return true; } -bool ChangeImportsVisitor::visit(QmlJS::AST::UiImportList *ast) +bool ChangeImportsVisitor::remove(QmlJS::AST::UiProgram *ast, const Import &import) { + setDidRewriting(false); if (!ast) return false; - quint32 prevEnd = 0; - for (UiImportList *it = ast; it; it = it->next) { - UiImport *imp = it->import; - if (!imp) - continue; - - if (m_removedImports.remove(createImport(imp))) - replace(prevEnd, imp->lastSourceLocation().end() - prevEnd, ""); - - prevEnd = imp->lastSourceLocation().end(); + for (UiImportList *iter = ast->imports; iter; iter = iter->next) { + if (equals(iter->import, import)) { + int start = iter->firstSourceLocation().begin(); + int end = iter->lastSourceLocation().end(); + includeSurroundingWhitespace(start, end); + replace(start, end - start, QString()); + setDidRewriting(true); + } } - foreach (const Import &i, m_addedImports) { - replace(prevEnd, 0, i.toString(false) + "\n"); - } + return didRewriting(); +} - return false; +bool ChangeImportsVisitor::equals(QmlJS::AST::UiImport *ast, const Import &import) +{ + if (import.isLibraryImport()) { + return flatten(ast->importUri) == import.url(); + } else if (import.isFileImport()) { + return ast->fileName->asString() == import.file(); + } else { + return false; + } } diff --git a/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.h b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.h index 65ede8e1f14afb8fb9d5453d38ee51e3ccc883ff..ecf2ef4aa8de27e11f71b3919e875894978e3d3a 100644 --- a/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.h +++ b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.h @@ -32,27 +32,24 @@ #include <QtCore/QSet> -#include <model/copypasteutil.h> #include "import.h" #include "qmlrewriter.h" namespace QmlDesigner { namespace Internal { -class ChangeImportsVisitor: public QMLRewriter, protected QmlDesigner::Internal::CopyPasteUtil +class ChangeImportsVisitor: public QMLRewriter { public: - ChangeImportsVisitor(QmlDesigner::TextModifier &textModifier, - const QSet<QmlDesigner::Import> &addedImports, - const QSet<QmlDesigner::Import> &removedImports, const QString &source); + ChangeImportsVisitor(QmlDesigner::TextModifier &textModifier, const QString &source); -protected: - virtual bool visit(QmlJS::AST::UiProgram *ast); - virtual bool visit(QmlJS::AST::UiImportList *ast); + bool add(QmlJS::AST::UiProgram *ast, const Import &import); + bool remove(QmlJS::AST::UiProgram *ast, const Import &import); private: - QSet<QmlDesigner::Import> m_addedImports; - QSet<QmlDesigner::Import> m_removedImports; + static bool equals(QmlJS::AST::UiImport *ast, const Import &import); + + QString m_source; }; } // namespace Internal diff --git a/src/plugins/qmldesigner/core/filemanager/filemanager.pri b/src/plugins/qmldesigner/core/filemanager/filemanager.pri index 81f5b3fd789a5322c402fa8e6d1aa31ff3bbc905..a2a6933c03a2276c80b7a10e2d61b1b088ed84fa 100644 --- a/src/plugins/qmldesigner/core/filemanager/filemanager.pri +++ b/src/plugins/qmldesigner/core/filemanager/filemanager.pri @@ -12,7 +12,8 @@ SOURCES += \ $$PWD/astobjecttextextractor.cpp \ $$PWD/objectlengthcalculator.cpp \ $$PWD/firstdefinitionfinder.cpp \ - $$PWD/moveobjectbeforeobjectvisitor.cpp + $$PWD/moveobjectbeforeobjectvisitor.cpp \ + $$PWD/changeimportsvisitor.cpp HEADERS += \ $$PWD/qmlrewriter.h \ $$PWD/qmlrefactoring.h \ @@ -27,4 +28,5 @@ HEADERS += \ $$PWD/astobjecttextextractor.h \ $$PWD/objectlengthcalculator.h \ $$PWD/firstdefinitionfinder.h \ - $$PWD/moveobjectbeforeobjectvisitor.h + $$PWD/moveobjectbeforeobjectvisitor.h \ + $$PWD/changeimportsvisitor.h diff --git a/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.cpp b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.cpp index e4d4d210d55853688e2cfd58f6476a38c43aab51..a81402107506dab3c5ed096b6f5f6663e0dafe3c 100644 --- a/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.cpp +++ b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.cpp @@ -32,6 +32,7 @@ #include "addarraymembervisitor.h" #include "addobjectvisitor.h" #include "addpropertyvisitor.h" +#include "changeimportsvisitor.h" #include "changeobjecttypevisitor.h" #include "changepropertyvisitor.h" #include "moveobjectvisitor.h" @@ -70,11 +71,16 @@ bool QmlRefactoring::reparseDocument() } } -bool QmlRefactoring::changeImports(const QSet<QmlDesigner::Import> &/*addedImports*/, const QSet<QmlDesigner::Import> &/*removedImports*/) +bool QmlRefactoring::addImport(const Import &import) { -// ChangeImportsVisitor visit(*textModifier, addedImports, removedImports, qmlDocument->source()); -// visit(qmlDocument->program()); - return false; + ChangeImportsVisitor visitor(*textModifier, qmlDocument->source()); + return visitor.add(qmlDocument->qmlProgram(), import); +} + +bool QmlRefactoring::removeImport(const Import &import) +{ + ChangeImportsVisitor visitor(*textModifier, qmlDocument->source()); + return visitor.remove(qmlDocument->qmlProgram(), import); } bool QmlRefactoring::addToArrayMemberList(int parentLocation, const QString &propertyName, const QString &content) diff --git a/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.h b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.h index 4a802f2245decfba11db4ff5b34bbe7fe14cf505..8ef99a3a87e70d7c66da3714aa7de1b87130523b 100644 --- a/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.h +++ b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.h @@ -55,7 +55,8 @@ public: bool reparseDocument(); - bool changeImports(const QSet<QmlDesigner::Import> &addedImports, const QSet<QmlDesigner::Import> &removedImports); + bool addImport(const Import &import); + bool removeImport(const Import &import); bool addToArrayMemberList(int parentLocation, const QString &propertyName, const QString &content); bool addToObjectMemberList(int parentLocation, const QString &content); diff --git a/src/plugins/qmldesigner/core/include/import.h b/src/plugins/qmldesigner/core/include/import.h index f10f89b5f4c21b889015f06ad825de2c69698160..841ded0d9fcfce2213316f05db6d5981beeb1dcc 100644 --- a/src/plugins/qmldesigner/core/include/import.h +++ b/src/plugins/qmldesigner/core/include/import.h @@ -31,7 +31,6 @@ #define IMPORT_H #include <QtCore/QString> -#include <QtCore/QUrl> #include "corelib_global.h" @@ -40,7 +39,7 @@ namespace QmlDesigner { class CORESHARED_EXPORT Import { public: - static Import createLibraryImport(const QUrl &url, const QString &version = QString(), const QString &alias = QString()); + static Import createLibraryImport(const QString &url, const QString &version = QString(), const QString &alias = QString()); static Import createFileImport(const QString &file, const QString &version = QString(), const QString &alias = QString()); static Import empty(); @@ -50,7 +49,7 @@ public: bool hasVersion() const { return !m_version.isEmpty(); } bool hasAlias() const { return !m_alias.isEmpty(); } - QUrl url() const { return m_url; } + QString url() const { return m_url; } QString file() const { return m_file; } QString version() const { return m_version; } QString alias() const { return m_alias; } @@ -60,10 +59,10 @@ public: bool operator==(const Import &other) const; private: - Import(const QUrl &url, const QString &file, const QString &version, const QString &alias); + Import(const QString &url, const QString &file, const QString &version, const QString &alias); private: - QUrl m_url; + QString m_url; QString m_file; QString m_version; QString m_alias; diff --git a/src/plugins/qmldesigner/core/model/copypasteutil.cpp b/src/plugins/qmldesigner/core/model/copypasteutil.cpp deleted file mode 100644 index c51c0b3d67b1a810c61474e15edea5ebeaf0cfe2..0000000000000000000000000000000000000000 --- a/src/plugins/qmldesigner/core/model/copypasteutil.cpp +++ /dev/null @@ -1,61 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** Commercial Usage -** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. -** -** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** -**************************************************************************/ - -#include <qmljsast_p.h> -#include <qmljsengine_p.h> - -#include "copypasteutil.h" - -using namespace QmlJS; -using namespace QmlJS::AST; - -namespace QmlDesigner { -namespace Internal { - -Import CopyPasteUtil::createImport(QmlJS::AST::UiImport *ast) -{ - QString version; - if (ast->versionToken.isValid()) - version = textAt(ast->versionToken); - - QString alias; - if (ast->importId) - alias = ast->importId->asString(); - - if (ast->fileName) - return Import::createFileImport(ast->fileName->asString(), version, alias); - - if (ast->importUri && ast->importUri->name) - return Import::createLibraryImport(ast->importUri->name->asString(), version, alias); - - return Import::empty(); -} - -} // namespace Internal -} // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/core/model/copypasteutil.h b/src/plugins/qmldesigner/core/model/copypasteutil.h deleted file mode 100644 index d44783e2670c208e78bd5e9e4a7c1cfdeae7e285..0000000000000000000000000000000000000000 --- a/src/plugins/qmldesigner/core/model/copypasteutil.h +++ /dev/null @@ -1,63 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (qt-info@nokia.com) -** -** Commercial Usage -** -** Licensees holding valid Qt Commercial licenses may use this file in -** accordance with the Qt Commercial License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Nokia. -** -** 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 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 2.1 requirements -** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** If you are unsure which license is appropriate for your use, please -** contact the sales department at http://qt.nokia.com/contact. -** -**************************************************************************/ - -#ifndef COPYPASTEUTIL_H -#define COPYPASTEUTIL_H - -#include <qmljsastfwd_p.h> - -#include "import.h" - -namespace QmlDesigner { -namespace Internal { - -class CopyPasteUtil { -public: - CopyPasteUtil(const QString &originalSource): m_originalSource(originalSource) - {} - - Import createImport(QmlJS::AST::UiImport *ast); - -protected: - QString textAt(const QmlJS::AST::SourceLocation &loc) const - { return m_originalSource.mid(loc.offset, loc.length); } - - QString textAt(const QmlJS::AST::SourceLocation &firstSourceLocation, const QmlJS::AST::SourceLocation &lastSourceLocation) const - { return m_originalSource.mid(firstSourceLocation.offset, lastSourceLocation.end() - firstSourceLocation.offset); } - - QString originalSource() const { return m_originalSource; } - -private: - QString m_originalSource; -}; - -} // namespace Internal -} // namespace QmlDesigner - -#endif // COPYPASTEUTIL_H diff --git a/src/plugins/qmldesigner/core/model/import.cpp b/src/plugins/qmldesigner/core/model/import.cpp index c7c7abf4eb90843cfe85b7064cbb04779d640a74..d10cbfc27c81b0e582ab344ba04480671d1267a9 100644 --- a/src/plugins/qmldesigner/core/model/import.cpp +++ b/src/plugins/qmldesigner/core/model/import.cpp @@ -33,22 +33,22 @@ namespace QmlDesigner { -Import Import::createLibraryImport(const QUrl &url, const QString &version, const QString &alias) +Import Import::createLibraryImport(const QString &url, const QString &version, const QString &alias) { return Import(url, QString(), version, alias); } Import Import::createFileImport(const QString &file, const QString &version, const QString &alias) { - return Import(QUrl(), file, version, alias); + return Import(QString(), file, version, alias); } Import Import::empty() { - return Import(QUrl(), QString(), QString(), QString()); + return Import(QString(), QString(), QString(), QString()); } -Import::Import(const QUrl &url, const QString &file, const QString &version, const QString &alias): +Import::Import(const QString &url, const QString &file, const QString &version, const QString &alias): m_url(url), m_file(file), m_version(version), @@ -63,7 +63,7 @@ QString Import::toString(bool addSemicolon) const if (isFileImport()) result += '"' + file() + '"'; else if (isLibraryImport()) - result += url().toString(); + result += url(); else return QString(); @@ -86,7 +86,7 @@ bool Import::operator==(const Import &other) const uint qHash(const Import &import) { - return ::qHash(import.url().toString()) ^ ::qHash(import.file()) ^ ::qHash(import.version()) ^ ::qHash(import.alias()); + return ::qHash(import.url()) ^ ::qHash(import.file()) ^ ::qHash(import.version()) ^ ::qHash(import.alias()); } } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/core/model/modeltotextmerger.cpp b/src/plugins/qmldesigner/core/model/modeltotextmerger.cpp index 2141d6005c8803dc7d113a01d7075a41fd141ef2..25cf6a1a4c61d3ef1da7ae2efcdeb57708510a17 100644 --- a/src/plugins/qmldesigner/core/model/modeltotextmerger.cpp +++ b/src/plugins/qmldesigner/core/model/modeltotextmerger.cpp @@ -133,6 +133,18 @@ void ModelToTextMerger::nodeTypeChanged(const ModelNode &node,const QString &/*t schedule(new ChangeTypeRewriteAction(node)); } +void ModelToTextMerger::addImport(const Import &import) +{ + if (!import.isEmpty()) + schedule(new AddImportRewriteAction(import)); +} + +void ModelToTextMerger::removeImport(const Import &import) +{ + if (!import.isEmpty()) + schedule(new RemoveImportRewriteAction(import)); +} + void ModelToTextMerger::nodeReparented(const ModelNode &node, const NodeAbstractProperty &newPropertyParent, const NodeAbstractProperty &oldPropertyParent, AbstractView::PropertyChangeFlags propertyChange) { if (isInHierarchy(oldPropertyParent) && isInHierarchy(newPropertyParent)) { // the node is moved diff --git a/src/plugins/qmldesigner/core/model/modeltotextmerger.h b/src/plugins/qmldesigner/core/model/modeltotextmerger.h index a1fef610bb91f75900aa2ed4dce67770615b5b7d..dd4afbcb14cd564ee7508a5fb8ae2572bbcde60e 100644 --- a/src/plugins/qmldesigner/core/model/modeltotextmerger.h +++ b/src/plugins/qmldesigner/core/model/modeltotextmerger.h @@ -74,6 +74,9 @@ public: void nodeSlidAround(const ModelNode &movingNode, const ModelNode &inFrontOfNode); void nodeTypeChanged(const ModelNode &node,const QString &type, int majorVersion, int minorVersion); + void addImport(const Import &import); + void removeImport(const Import &import); + protected: RewriterView *view(); diff --git a/src/plugins/qmldesigner/core/model/rewriteaction.cpp b/src/plugins/qmldesigner/core/model/rewriteaction.cpp index 0288af04e626ef04a22ed07464d82b4347678878..37bc0219462c9397cd258c49230fea3107801a98 100644 --- a/src/plugins/qmldesigner/core/model/rewriteaction.cpp +++ b/src/plugins/qmldesigner/core/model/rewriteaction.cpp @@ -36,6 +36,37 @@ using namespace QmlDesigner; using namespace QmlDesigner::Internal; using namespace QmlDesigner; +namespace { // anonymous + +static inline QString toInfo(const Import &import) +{ + QString txt; + + if (import.isEmpty()) { + return QLatin1String("empty import"); + } else if (import.isFileImport()) { + txt = QLatin1String("import file \"%1\""); + txt = txt.arg(import.url()); + } else if (import.isLibraryImport()) { + txt = QLatin1String("import library \"%1\""); + txt = txt.arg(import.file()); + } else { + return QLatin1String("unknown type of import"); + } + + if (import.hasVersion()) + txt += QString::fromLatin1("with version \"%1\"").arg(import.version()); + else + txt += QLatin1String("without version"); + + if (import.hasAlias()) + txt += QString::fromLatin1("aliassed as \"%1\"").arg(import.alias()); + else + txt += QLatin1String("unaliassed"); + + return txt; +} + static inline QString toString(QmlRefactoring::PropertyType type) { switch (type) { @@ -46,6 +77,8 @@ static inline QString toString(QmlRefactoring::PropertyType type) } } +} // namespace anonymous + bool AddPropertyRewriteAction::execute(QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore) { const int nodeLocation = positionStore.nodeOffset(m_property.parentModelNode()); @@ -302,3 +335,39 @@ QString MoveNodeRewriteAction::info() const return QString("MoveNodeRewriteAction for an invalid node"); } } + +bool AddImportRewriteAction::execute(QmlDesigner::QmlRefactoring &refactoring, + ModelNodePositionStorage &/*positionStore*/) +{ + const bool result = refactoring.addImport(m_import); + + if (!result) + qDebug() << "*** AddImportRewriteAction::execute failed in changeImports (" + << m_import.toString() + << ") **" + << info(); + return result; +} + +QString AddImportRewriteAction::info() const +{ + return toInfo(m_import); +} + +bool RemoveImportRewriteAction::execute(QmlDesigner::QmlRefactoring &refactoring, + ModelNodePositionStorage &/*positionStore*/) +{ + const bool result = refactoring.addImport(m_import); + + if (!result) + qDebug() << "*** RemoveImportRewriteAction::execute failed in changeImports (" + << m_import.toString() + << ") **" + << info(); + return result; +} + +QString RemoveImportRewriteAction::info() const +{ + return toInfo(m_import); +} diff --git a/src/plugins/qmldesigner/core/model/rewriteaction.h b/src/plugins/qmldesigner/core/model/rewriteaction.h index 84deabd68bb0526e1a6073aec79d8d34fe1fd645..dbd0c6d01cc1d8dcd3712efd4fd85058bc155725 100644 --- a/src/plugins/qmldesigner/core/model/rewriteaction.h +++ b/src/plugins/qmldesigner/core/model/rewriteaction.h @@ -38,10 +38,12 @@ namespace QmlDesigner { namespace Internal { +class AddImportRewriteAction; class AddPropertyRewriteAction; class ChangeIdRewriteAction; class ChangePropertyRewriteAction; class ChangeTypeRewriteAction; +class RemoveImportRewriteAction; class RemoveNodeRewriteAction; class RemovePropertyRewriteAction; class ReparentNodeRewriteAction; @@ -53,10 +55,12 @@ public: virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore) = 0; virtual QString info() const = 0; + virtual AddImportRewriteAction const *asAddImportRewriteAction() const { return 0; } virtual AddPropertyRewriteAction const *asAddPropertyRewriteAction() const { return 0; } virtual ChangeIdRewriteAction const *asChangeIdRewriteAction() const { return 0; } virtual ChangePropertyRewriteAction const *asChangePropertyRewriteAction() const { return 0; } virtual ChangeTypeRewriteAction const *asChangeTypeRewriteAction() const { return 0; } + virtual RemoveImportRewriteAction const * asRemoveImportRewriteAction() const { return 0; } virtual RemoveNodeRewriteAction const *asRemoveNodeRewriteAction() const { return 0; } virtual RemovePropertyRewriteAction const *asRemovePropertyRewriteAction() const { return 0; } virtual ReparentNodeRewriteAction const *asReparentNodeRewriteAction() const { return 0; } @@ -255,6 +259,42 @@ private: ModelNode m_newTrailingNode; }; +class AddImportRewriteAction: public RewriteAction +{ +public: + AddImportRewriteAction(const Import &import): + m_import(import) + {} + + virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore); + virtual QString info() const; + + virtual AddImportRewriteAction const *asAddImportRewriteAction() const { return this; } + + Import import() const { return m_import; } + +private: + Import m_import; +}; + +class RemoveImportRewriteAction: public RewriteAction +{ +public: + RemoveImportRewriteAction(const Import &import): + m_import(import) + {} + + virtual bool execute(QmlDesigner::QmlRefactoring &refactoring, ModelNodePositionStorage &positionStore); + virtual QString info() const; + + virtual RemoveImportRewriteAction const *asRemoveImportRewriteAction() const { return this; } + + Import import() const { return m_import; } + +private: + Import m_import; +}; + } // namespace Internal } // namespace QmlDesigner diff --git a/src/plugins/qmldesigner/core/model/rewriteactioncompressor.cpp b/src/plugins/qmldesigner/core/model/rewriteactioncompressor.cpp index 6ccda0ff2cb22e9541f6364abd230230f3287ac4..d9d549032bda2e74a351ab1cd517f7a71c27f4e2 100644 --- a/src/plugins/qmldesigner/core/model/rewriteactioncompressor.cpp +++ b/src/plugins/qmldesigner/core/model/rewriteactioncompressor.cpp @@ -56,6 +56,7 @@ static bool nodeOrParentInSet(const ModelNode &node, const QSet<ModelNode> &node void RewriteActionCompressor::operator()(QList<RewriteAction *> &actions) const { + compressImports(actions); compressReparentActions(actions); compressPropertyActions(actions); compressAddEditRemoveNodeActions(actions); @@ -63,6 +64,47 @@ void RewriteActionCompressor::operator()(QList<RewriteAction *> &actions) const compressAddReparentActions(actions); } +void RewriteActionCompressor::compressImports(QList<RewriteAction *> &actions) const +{ + QHash<Import, RewriteAction *> addedImports; + QHash<Import, RewriteAction *> removedImports; + + QMutableListIterator<RewriteAction *> iter(actions); + iter.toBack(); + while (iter.hasPrevious()) { + RewriteAction *action = iter.previous(); + + if (RemoveImportRewriteAction const *removeImportAction = action->asRemoveImportRewriteAction()) { + const Import import = removeImportAction->import(); + if (removedImports.contains(import)) { + remove(iter); + } else if (RewriteAction *addImportAction = addedImports.value(import, 0)) { + actions.removeOne(addImportAction); + addedImports.remove(import); + delete addImportAction; + remove(iter); + } else { + removedImports.insert(import, action); + } + } else if (AddImportRewriteAction const *addImportAction = action->asAddImportRewriteAction()) { + const Import import = addImportAction->import(); + if (RewriteAction *duplicateAction = addedImports.value(import, 0)) { + actions.removeOne(duplicateAction); + addedImports.remove(import); + delete duplicateAction; + addedImports.insert(import, action); + } else if (RewriteAction *removeAction = removedImports.value(import, 0)) { + actions.removeOne(removeAction); + removedImports.remove(import); + delete removeAction; + remove(iter); + } else { + addedImports.insert(import, action); + } + } + } +} + void RewriteActionCompressor::compressReparentActions(QList<RewriteAction *> &actions) const { QSet<ModelNode> reparentedNodes; diff --git a/src/plugins/qmldesigner/core/model/rewriteactioncompressor.h b/src/plugins/qmldesigner/core/model/rewriteactioncompressor.h index 594d490a5b2d84b6ebbfdc97123ab1ac10833402..3d3673008edfc1c1dd087db6ef14864431fb034f 100644 --- a/src/plugins/qmldesigner/core/model/rewriteactioncompressor.h +++ b/src/plugins/qmldesigner/core/model/rewriteactioncompressor.h @@ -45,6 +45,8 @@ public: void operator()(QList<RewriteAction *> &actions) const; private: + void compressImports(QList<RewriteAction *> &actions) const; + void compressReparentActions(QList<RewriteAction *> &actions) const; void compressAddEditRemoveNodeActions(QList<RewriteAction *> &actions) const; void compressPropertyActions(QList<RewriteAction *> &actions) const; diff --git a/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp index e75b98a5c66f13a65aa93b266531d1f9f92a4cda..5ab495da12cc1b0decefd5dbde79ec15dd328a92 100644 --- a/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp +++ b/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp @@ -75,7 +75,7 @@ void TextToModelMerger::setupImports(QmlDomDocument &doc, foreach (const QmlDomImport &qmlImport, doc.imports()) { if (qmlImport.type() == QmlDomImport::Library) { - Import import(Import::createLibraryImport(QUrl(qmlImport.uri()), + Import import(Import::createLibraryImport(qmlImport.uri(), qmlImport.version(), qmlImport.qualifier()));