forked from qt-creator/qt-creator
		
	Added import rewriting.
This commit is contained in:
		@@ -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)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ChangeImportsVisitor::visit(QmlJS::AST::UiProgram *ast)
 | 
			
		||||
{
 | 
			
		||||
    if (ast->imports)
 | 
			
		||||
        accept(ast->imports);
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ChangeImportsVisitor::visit(QmlJS::AST::UiImportList *ast)
 | 
			
		||||
ChangeImportsVisitor::ChangeImportsVisitor(TextModifier &textModifier,
 | 
			
		||||
                                           const QString &source):
 | 
			
		||||
        QMLRewriter(textModifier), m_source(source)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
bool ChangeImportsVisitor::add(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();
 | 
			
		||||
    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"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    foreach (const Import &i, m_addedImports) {
 | 
			
		||||
        replace(prevEnd, 0, i.toString(false) + "\n");
 | 
			
		||||
    }
 | 
			
		||||
    setDidRewriting(true);
 | 
			
		||||
 | 
			
		||||
    return false;
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool ChangeImportsVisitor::remove(QmlJS::AST::UiProgram *ast, const Import &import)
 | 
			
		||||
{
 | 
			
		||||
    setDidRewriting(false);
 | 
			
		||||
    if (!ast)
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return didRewriting();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
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;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
 
 | 
			
		||||
@@ -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()));
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user