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:
Christian Kamm
2011-08-17 11:35:57 +02:00
parent a07acad516
commit 8a6d767a8f
30 changed files with 609 additions and 500 deletions

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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()

View File

@@ -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