forked from qt-creator/qt-creator
		
	Refactoring changes: Cleanup and improvements.
Previously RefactoringFiles were usually passed around by value. However, since a RefactoringFile may sometimes own a QTextDocument (when it was read from a file), that's not great and caused the file to be reread after every copy. With this change RefactoringFile becomes noncopyable and is always owned by a shared pointer. This change also allowed having const RefactoringFiles which is useful because they can be safely used from other threads. See CppRefactoringChanges::fileNoEditor. Change-Id: I9045921d6d0f6349f9558ff2a3d8317ea172193b Reviewed-on: http://codereview.qt.nokia.com/3084 Reviewed-by: Leandro T. C. Melo <leandro.melo@nokia.com>
This commit is contained in:
		@@ -49,64 +49,101 @@ using namespace CPlusPlus;
 | 
			
		||||
using namespace CppTools;
 | 
			
		||||
using namespace Utils;
 | 
			
		||||
 | 
			
		||||
CppRefactoringChanges::CppRefactoringChanges(const Snapshot &snapshot)
 | 
			
		||||
    : m_snapshot(snapshot)
 | 
			
		||||
    , m_modelManager(Internal::CppModelManager::instance())
 | 
			
		||||
class CppTools::CppRefactoringChangesData : public TextEditor::RefactoringChangesData
 | 
			
		||||
{
 | 
			
		||||
    Q_ASSERT(m_modelManager);
 | 
			
		||||
    m_workingCopy = m_modelManager->workingCopy();
 | 
			
		||||
public:
 | 
			
		||||
    CppRefactoringChangesData(const Snapshot &snapshot)
 | 
			
		||||
        : m_snapshot(snapshot)
 | 
			
		||||
        , m_modelManager(Internal::CppModelManager::instance())
 | 
			
		||||
        , m_workingCopy(m_modelManager->workingCopy())
 | 
			
		||||
    {}
 | 
			
		||||
 | 
			
		||||
    virtual void indentSelection(const QTextCursor &selection,
 | 
			
		||||
                                 const QString &fileName,
 | 
			
		||||
                                 const TextEditor::BaseTextEditorWidget *textEditor) const
 | 
			
		||||
    {
 | 
			
		||||
        // ### shares code with CPPEditor::indent()
 | 
			
		||||
        QTextDocument *doc = selection.document();
 | 
			
		||||
 | 
			
		||||
        QTextBlock block = doc->findBlock(selection.selectionStart());
 | 
			
		||||
        const QTextBlock end = doc->findBlock(selection.selectionEnd()).next();
 | 
			
		||||
 | 
			
		||||
        const TextEditor::TabSettings &tabSettings =
 | 
			
		||||
            ProjectExplorer::actualTabSettings(fileName, textEditor);
 | 
			
		||||
        // TODO: add similar method like above one
 | 
			
		||||
        CppTools::QtStyleCodeFormatter codeFormatter(tabSettings,
 | 
			
		||||
            CppToolsSettings::instance()->cppCodeStylePreferences()->settings());
 | 
			
		||||
        codeFormatter.updateStateUntil(block);
 | 
			
		||||
 | 
			
		||||
        do {
 | 
			
		||||
            int indent;
 | 
			
		||||
            int padding;
 | 
			
		||||
            codeFormatter.indentFor(block, &indent, &padding);
 | 
			
		||||
            tabSettings.indentLine(block, indent + padding, padding);
 | 
			
		||||
            codeFormatter.updateLineStateChange(block);
 | 
			
		||||
            block = block.next();
 | 
			
		||||
        } while (block.isValid() && block != end);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void fileChanged(const QString &fileName)
 | 
			
		||||
    {
 | 
			
		||||
        m_modelManager->updateSourceFiles(QStringList(fileName));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    CPlusPlus::Snapshot m_snapshot;
 | 
			
		||||
    CPlusPlus::CppModelManagerInterface *m_modelManager;
 | 
			
		||||
    CPlusPlus::CppModelManagerInterface::WorkingCopy m_workingCopy;
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
CppRefactoringChanges::CppRefactoringChanges(const Snapshot &snapshot)
 | 
			
		||||
    : RefactoringChanges(new CppRefactoringChangesData(snapshot))
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CppRefactoringChangesData *CppRefactoringChanges::data() const
 | 
			
		||||
{
 | 
			
		||||
    return static_cast<CppRefactoringChangesData *>(m_data.data());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CppRefactoringFilePtr CppRefactoringChanges::file(TextEditor::BaseTextEditorWidget *editor, const Document::Ptr &document)
 | 
			
		||||
{
 | 
			
		||||
    CppRefactoringFilePtr result(new CppRefactoringFile(editor));
 | 
			
		||||
    result->setCppDocument(document);
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CppRefactoringFilePtr CppRefactoringChanges::file(const QString &fileName) const
 | 
			
		||||
{
 | 
			
		||||
    CppRefactoringFilePtr result(new CppRefactoringFile(fileName, m_data));
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CppRefactoringFileConstPtr CppRefactoringChanges::fileNoEditor(const QString &fileName) const
 | 
			
		||||
{
 | 
			
		||||
    QTextDocument *document = 0;
 | 
			
		||||
    if (data()->m_workingCopy.contains(fileName))
 | 
			
		||||
        document = new QTextDocument(data()->m_workingCopy.source(fileName));
 | 
			
		||||
    CppRefactoringFilePtr result(new CppRefactoringFile(document, fileName));
 | 
			
		||||
    result->m_data = m_data;
 | 
			
		||||
 | 
			
		||||
    Document::Ptr cppDocument = data()->m_snapshot.document(fileName);
 | 
			
		||||
    if (cppDocument)
 | 
			
		||||
        result->setCppDocument(cppDocument);
 | 
			
		||||
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
const Snapshot &CppRefactoringChanges::snapshot() const
 | 
			
		||||
{
 | 
			
		||||
    return m_snapshot;
 | 
			
		||||
    return data()->m_snapshot;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CppRefactoringFile CppRefactoringChanges::file(const QString &fileName)
 | 
			
		||||
CppRefactoringFile::CppRefactoringFile(const QString &fileName, const QSharedPointer<TextEditor::RefactoringChangesData> &data)
 | 
			
		||||
    : RefactoringFile(fileName, data)
 | 
			
		||||
{
 | 
			
		||||
    return CppRefactoringFile(fileName, this);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CppRefactoringChanges::indentSelection(const QTextCursor &selection,
 | 
			
		||||
                                            const QString &fileName,
 | 
			
		||||
                                            const TextEditor::BaseTextEditorWidget *textEditor) const
 | 
			
		||||
{
 | 
			
		||||
    // ### shares code with CPPEditor::indent()
 | 
			
		||||
    QTextDocument *doc = selection.document();
 | 
			
		||||
 | 
			
		||||
    QTextBlock block = doc->findBlock(selection.selectionStart());
 | 
			
		||||
    const QTextBlock end = doc->findBlock(selection.selectionEnd()).next();
 | 
			
		||||
 | 
			
		||||
    const TextEditor::TabSettings &tabSettings =
 | 
			
		||||
        ProjectExplorer::actualTabSettings(fileName, textEditor);
 | 
			
		||||
    // TODO: add similar method like above one
 | 
			
		||||
    CppTools::QtStyleCodeFormatter codeFormatter(tabSettings,
 | 
			
		||||
        CppToolsSettings::instance()->cppCodeStylePreferences()->settings());
 | 
			
		||||
    codeFormatter.updateStateUntil(block);
 | 
			
		||||
 | 
			
		||||
    do {
 | 
			
		||||
        int indent;
 | 
			
		||||
        int padding;
 | 
			
		||||
        codeFormatter.indentFor(block, &indent, &padding);
 | 
			
		||||
        tabSettings.indentLine(block, indent + padding, padding);
 | 
			
		||||
        codeFormatter.updateLineStateChange(block);
 | 
			
		||||
        block = block.next();
 | 
			
		||||
    } while (block.isValid() && block != end);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CppRefactoringChanges::fileChanged(const QString &fileName)
 | 
			
		||||
{
 | 
			
		||||
    m_modelManager->updateSourceFiles(QStringList(fileName));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
CppRefactoringFile::CppRefactoringFile()
 | 
			
		||||
{ }
 | 
			
		||||
 | 
			
		||||
CppRefactoringFile::CppRefactoringFile(const QString &fileName, CppRefactoringChanges *refactoringChanges)
 | 
			
		||||
    : RefactoringFile(fileName, refactoringChanges)
 | 
			
		||||
{
 | 
			
		||||
    const Snapshot &snapshot = refactoringChanges->snapshot();
 | 
			
		||||
    const Snapshot &snapshot = this->data()->m_snapshot;
 | 
			
		||||
    m_cppDocument = snapshot.document(fileName);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -124,7 +161,7 @@ Document::Ptr CppRefactoringFile::cppDocument() const
 | 
			
		||||
            !m_cppDocument->translationUnit()->ast()) {
 | 
			
		||||
        const QString source = document()->toPlainText();
 | 
			
		||||
        const QString name = fileName();
 | 
			
		||||
        const Snapshot &snapshot = refactoringChanges()->snapshot();
 | 
			
		||||
        const Snapshot &snapshot = data()->m_snapshot;
 | 
			
		||||
 | 
			
		||||
        const QByteArray contents = snapshot.preprocessedCode(source, name);
 | 
			
		||||
        m_cppDocument = snapshot.documentFromSource(contents, name);
 | 
			
		||||
@@ -233,7 +270,13 @@ const Token &CppRefactoringFile::tokenAt(unsigned index) const
 | 
			
		||||
    return cppDocument()->translationUnit()->tokenAt(index);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
CppRefactoringChanges *CppRefactoringFile::refactoringChanges() const
 | 
			
		||||
CppRefactoringChangesData *CppRefactoringFile::data() const
 | 
			
		||||
{
 | 
			
		||||
    return static_cast<CppRefactoringChanges *>(m_refactoringChanges);
 | 
			
		||||
    return static_cast<CppRefactoringChangesData *>(m_data.data());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void CppRefactoringFile::fileChanged()
 | 
			
		||||
{
 | 
			
		||||
    m_cppDocument.clear();
 | 
			
		||||
    RefactoringFile::fileChanged();
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -45,14 +45,14 @@
 | 
			
		||||
namespace CppTools {
 | 
			
		||||
 | 
			
		||||
class CppRefactoringChanges;
 | 
			
		||||
class CppRefactoringFile;
 | 
			
		||||
class CppRefactoringChangesData;
 | 
			
		||||
typedef QSharedPointer<CppRefactoringFile> CppRefactoringFilePtr;
 | 
			
		||||
typedef QSharedPointer<const CppRefactoringFile> CppRefactoringFileConstPtr;
 | 
			
		||||
 | 
			
		||||
class CPPTOOLS_EXPORT CppRefactoringFile: public TextEditor::RefactoringFile
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
    CppRefactoringFile();
 | 
			
		||||
    CppRefactoringFile(QTextDocument *document, const QString &fileName = QString());
 | 
			
		||||
    CppRefactoringFile(TextEditor::BaseTextEditorWidget *editor);
 | 
			
		||||
 | 
			
		||||
    CPlusPlus::Document::Ptr cppDocument() const;
 | 
			
		||||
    void setCppDocument(CPlusPlus::Document::Ptr document);
 | 
			
		||||
 | 
			
		||||
@@ -78,10 +78,12 @@ public:
 | 
			
		||||
    QString textOf(const CPlusPlus::AST *ast) const;
 | 
			
		||||
 | 
			
		||||
protected:
 | 
			
		||||
    CppRefactoringFile(const QString &fileName, CppRefactoringChanges *refactoringChanges);
 | 
			
		||||
    CppRefactoringFile(const QString &fileName, const QSharedPointer<TextEditor::RefactoringChangesData> &data);
 | 
			
		||||
    CppRefactoringFile(QTextDocument *document, const QString &fileName);
 | 
			
		||||
    CppRefactoringFile(TextEditor::BaseTextEditorWidget *editor);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    CppRefactoringChanges *refactoringChanges() const;
 | 
			
		||||
    CppRefactoringChangesData *data() const;
 | 
			
		||||
    virtual void fileChanged();
 | 
			
		||||
 | 
			
		||||
    mutable CPlusPlus::Document::Ptr m_cppDocument;
 | 
			
		||||
 | 
			
		||||
@@ -93,21 +95,16 @@ class CPPTOOLS_EXPORT CppRefactoringChanges: public TextEditor::RefactoringChang
 | 
			
		||||
public:
 | 
			
		||||
    CppRefactoringChanges(const CPlusPlus::Snapshot &snapshot);
 | 
			
		||||
 | 
			
		||||
    static CppRefactoringFilePtr file(TextEditor::BaseTextEditorWidget *editor,
 | 
			
		||||
                                      const CPlusPlus::Document::Ptr &document);
 | 
			
		||||
    CppRefactoringFilePtr file(const QString &fileName) const;
 | 
			
		||||
    // safe to use from non-gui threads
 | 
			
		||||
    CppRefactoringFileConstPtr fileNoEditor(const QString &fileName) const;
 | 
			
		||||
 | 
			
		||||
    const CPlusPlus::Snapshot &snapshot() const;
 | 
			
		||||
    CppRefactoringFile file(const QString &fileName);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    virtual void indentSelection(const QTextCursor &selection,
 | 
			
		||||
                                 const QString &fileName,
 | 
			
		||||
                                 const TextEditor::BaseTextEditorWidget *textEditor) const;
 | 
			
		||||
    virtual void fileChanged(const QString &fileName);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    CPlusPlus::Document::Ptr m_thisDocument;
 | 
			
		||||
    CPlusPlus::Snapshot m_snapshot;
 | 
			
		||||
    CPlusPlus::LookupContext m_context;
 | 
			
		||||
    CPlusPlus::CppModelManagerInterface *m_modelManager;
 | 
			
		||||
    CPlusPlus::CppModelManagerInterface::WorkingCopy m_workingCopy;
 | 
			
		||||
    CppRefactoringChangesData *data() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace CppTools
 | 
			
		||||
 
 | 
			
		||||
@@ -287,7 +287,7 @@ InsertionLocation::InsertionLocation(const QString &fileName,
 | 
			
		||||
    , m_column(column)
 | 
			
		||||
{}
 | 
			
		||||
 | 
			
		||||
InsertionPointLocator::InsertionPointLocator(CppRefactoringChanges *refactoringChanges)
 | 
			
		||||
InsertionPointLocator::InsertionPointLocator(const CppRefactoringChanges &refactoringChanges)
 | 
			
		||||
    : m_refactoringChanges(refactoringChanges)
 | 
			
		||||
{
 | 
			
		||||
}
 | 
			
		||||
@@ -297,7 +297,7 @@ InsertionLocation InsertionPointLocator::methodDeclarationInClass(
 | 
			
		||||
    const Class *clazz,
 | 
			
		||||
    AccessSpec xsSpec) const
 | 
			
		||||
{
 | 
			
		||||
    const Document::Ptr doc = m_refactoringChanges->file(fileName).cppDocument();
 | 
			
		||||
    const Document::Ptr doc = m_refactoringChanges.file(fileName)->cppDocument();
 | 
			
		||||
    if (doc) {
 | 
			
		||||
        FindInClass find(doc, clazz, xsSpec);
 | 
			
		||||
        return find();
 | 
			
		||||
@@ -434,11 +434,11 @@ QList<InsertionLocation> InsertionPointLocator::methodDefinition(
 | 
			
		||||
            target = candidate;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    Document::Ptr doc = m_refactoringChanges->file(target).cppDocument();
 | 
			
		||||
    Document::Ptr doc = m_refactoringChanges.file(target)->cppDocument();
 | 
			
		||||
    if (doc.isNull())
 | 
			
		||||
        return result;
 | 
			
		||||
 | 
			
		||||
    Snapshot simplified = m_refactoringChanges->snapshot().simplified(doc);
 | 
			
		||||
    Snapshot simplified = m_refactoringChanges.snapshot().simplified(doc);
 | 
			
		||||
    if (Symbol *s = simplified.findMatchingDefinition(declaration)) {
 | 
			
		||||
        if (Function *f = s->asFunction()) {
 | 
			
		||||
            if (f->isConst() == declaration->type().isConst()
 | 
			
		||||
 
 | 
			
		||||
@@ -39,11 +39,10 @@
 | 
			
		||||
#include <CPlusPlusForwardDeclarations.h>
 | 
			
		||||
 | 
			
		||||
#include <cplusplus/CppDocument.h>
 | 
			
		||||
#include <cpptools/cpprefactoringchanges.h>
 | 
			
		||||
 | 
			
		||||
namespace CppTools {
 | 
			
		||||
 | 
			
		||||
class CppRefactoringChanges;
 | 
			
		||||
 | 
			
		||||
class CPPTOOLS_EXPORT InsertionLocation
 | 
			
		||||
{
 | 
			
		||||
public:
 | 
			
		||||
@@ -100,7 +99,7 @@ public:
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    InsertionPointLocator(CppRefactoringChanges *refactoringChanges);
 | 
			
		||||
    InsertionPointLocator(const CppRefactoringChanges &refactoringChanges);
 | 
			
		||||
 | 
			
		||||
    InsertionLocation methodDeclarationInClass(const QString &fileName,
 | 
			
		||||
                                               const CPlusPlus::Class *clazz,
 | 
			
		||||
@@ -109,7 +108,7 @@ public:
 | 
			
		||||
    QList<InsertionLocation> methodDefinition(CPlusPlus::Declaration *declaration) const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    CppRefactoringChanges *m_refactoringChanges;
 | 
			
		||||
    CppRefactoringChanges m_refactoringChanges;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace CppTools
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user