Commit 7a5df3c3 authored by Christian Kamm's avatar Christian Kamm

QuickFix: Move helpers from QuickFixData to RefactoringFile.

Makes them easy to use everywhere. Also when calling
QuickFixData::textOf and friends, it wasn't really clear which file
they would run on.
parent bbe64796
......@@ -113,13 +113,14 @@ private:
QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &state)
{
const QList<AST *> &path = state.path();
const CppRefactoringFile &file = state.currentFile();
FunctionDefinitionAST *funDef = 0;
int idx = 0;
for (; idx < path.size(); ++idx) {
AST *node = path.at(idx);
if (FunctionDefinitionAST *candidate = node->asFunctionDefinition()) {
if (!funDef && state.isCursorOn(candidate) && !state.isCursorOn(candidate->function_body))
if (!funDef && file.isCursorOn(candidate) && !file.isCursorOn(candidate->function_body))
funDef = candidate;
} else if (node->asClassSpecifier()) {
return noResult();
......
......@@ -86,100 +86,11 @@ const LookupContext &CppQuickFixState::context() const
return _context;
}
Scope *CppQuickFixState::scopeAt(unsigned index) const
const CppRefactoringFile CppQuickFixState::currentFile() const
{
unsigned line, column;
document()->translationUnit()->getTokenStartPosition(index, &line, &column);
return document()->scopeAt(line, column);
return CppRefactoringFile(editor(), document());
}
bool CppQuickFixState::isCursorOn(unsigned tokenIndex) const
{
QTextCursor tc = textCursor();
int cursorBegin = tc.selectionStart();
int start = startOf(tokenIndex);
int end = endOf(tokenIndex);
if (cursorBegin >= start && cursorBegin <= end)
return true;
return false;
}
bool CppQuickFixState::isCursorOn(const AST *ast) const
{
QTextCursor tc = textCursor();
int cursorBegin = tc.selectionStart();
int start = startOf(ast);
int end = endOf(ast);
if (cursorBegin >= start && cursorBegin <= end)
return true;
return false;
}
ChangeSet::Range CppQuickFixState::range(unsigned tokenIndex) const
{
const Token &token = tokenAt(tokenIndex);
unsigned line, column;
document()->translationUnit()->getPosition(token.begin(), &line, &column);
const int start = editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
return ChangeSet::Range(start, start + token.length());
}
ChangeSet::Range CppQuickFixState::range(AST *ast) const
{
return ChangeSet::Range(startOf(ast), endOf(ast));
}
int CppQuickFixState::startOf(unsigned index) const
{
unsigned line, column;
document()->translationUnit()->getPosition(tokenAt(index).begin(), &line, &column);
return editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
}
int CppQuickFixState::startOf(const AST *ast) const
{
return startOf(ast->firstToken());
}
int CppQuickFixState::endOf(unsigned index) const
{
unsigned line, column;
document()->translationUnit()->getPosition(tokenAt(index).end(), &line, &column);
return editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
}
int CppQuickFixState::endOf(const AST *ast) const
{
if (unsigned end = ast->lastToken())
return endOf(end - 1);
else
return 0;
}
void CppQuickFixState::startAndEndOf(unsigned index, int *start, int *end) const
{
unsigned line, column;
Token token(tokenAt(index));
document()->translationUnit()->getPosition(token.begin(), &line, &column);
*start = editor()->document()->findBlockByNumber(line - 1).position() + column - 1;
*end = *start + token.length();
}
QString CppQuickFixState::textOf(const AST *ast) const
{
return textOf(startOf(ast), endOf(ast));
}
const Token &CppQuickFixState::tokenAt(unsigned index) const
{
return document()->translationUnit()->tokenAt(index);
}
CppQuickFixOperation::CppQuickFixOperation(const CppQuickFixState &state, int priority)
: QuickFixOperation(priority)
......
......@@ -62,7 +62,6 @@ class CPPEDITOR_EXPORT CppQuickFixState: public TextEditor::QuickFixState
public:
CppQuickFixState(TextEditor::BaseTextEditor *editor);
typedef Utils::ChangeSet::Range Range;
const QList<CPlusPlus::AST *> &path() const;
CPlusPlus::Snapshot snapshot() const;
......@@ -70,27 +69,12 @@ public:
CppEditor::Internal::SemanticInfo semanticInfo() const;
const CPlusPlus::LookupContext &context() const;
using TextEditor::QuickFixState::range;
using TextEditor::QuickFixState::textOf;
using TextEditor::QuickFixState::charAt;
CPlusPlus::Scope *scopeAt(unsigned index) const;
bool isCursorOn(unsigned tokenIndex) const;
bool isCursorOn(const CPlusPlus::AST *ast) const;
Range range(unsigned tokenIndex) const;
Range range(CPlusPlus::AST *ast) const;
const CPlusPlus::Token &tokenAt(unsigned index) const;
const CppRefactoringFile currentFile() const;
int startOf(unsigned index) const;
int startOf(const CPlusPlus::AST *ast) const;
int endOf(unsigned index) const;
int endOf(const CPlusPlus::AST *ast) const;
void startAndEndOf(unsigned index, int *start, int *end) const;
QString textOf(const CPlusPlus::AST *ast) const;
bool isCursorOn(unsigned tokenIndex) const
{ return currentFile().isCursorOn(tokenIndex); }
bool isCursorOn(const CPlusPlus::AST *ast) const
{ return currentFile().isCursorOn(ast); }
private:
QList<CPlusPlus::AST *> _path;
......@@ -119,18 +103,6 @@ protected:
protected: // Utility functions forwarding to CppQuickFixState
typedef Utils::ChangeSet::Range Range;
bool isCursorOn(unsigned tokenIndex) const { return state().isCursorOn(tokenIndex); }
bool isCursorOn(const CPlusPlus::AST *ast) const { return state().isCursorOn(ast); }
Range range(int start, int end) const { return CppQuickFixState::range(start, end); }
Range range(unsigned tokenIndex) const { return state().range(tokenIndex); }
Range range(CPlusPlus::AST *ast) const { return state().range(ast); }
int startOf(unsigned index) const { return state().startOf(index); }
int startOf(const CPlusPlus::AST *ast) const { return state().startOf(ast); }
int endOf(unsigned index) const { return state().endOf(index); }
int endOf(const CPlusPlus::AST *ast) const { return state().endOf(ast); }
private:
CppQuickFixState _state;
};
......
This diff is collapsed.
......@@ -103,6 +103,14 @@ CppRefactoringFile::CppRefactoringFile(const QString &fileName, CppRefactoringCh
: RefactoringFile(fileName, refactoringChanges)
{ }
CppRefactoringFile::CppRefactoringFile(TextEditor::BaseTextEditor *editor, CPlusPlus::Document::Ptr document)
: RefactoringFile()
, m_cppDocument(document)
{
m_fileName = document->fileName();
m_editor = editor;
}
Document::Ptr CppRefactoringFile::cppDocument() const
{
if (!m_cppDocument) {
......
......@@ -48,6 +48,7 @@ class CPPEDITOR_EXPORT CppRefactoringFile: public TextEditor::RefactoringFile
public:
CppRefactoringFile();
CppRefactoringFile(const QString &fileName, CppRefactoringChanges *refactoringChanges);
CppRefactoringFile(TextEditor::BaseTextEditor *editor, CPlusPlus::Document::Ptr document);
CPlusPlus::Document::Ptr cppDocument() const;
......
......@@ -92,22 +92,22 @@ public:
"Move Component into '%1.qml'").arg(m_componentName));
}
virtual void performChanges(TextEditor::RefactoringFile *currentFile, QmlJSRefactoringChanges *refactoring)
virtual void performChanges(QmlJSRefactoringFile *currentFile, QmlJSRefactoringChanges *refactoring)
{
const QString newFileName = QFileInfo(fileName()).path()
+ QDir::separator() + m_componentName + QLatin1String(".qml");
QString imports;
UiProgram *prog = state().semanticInfo().document->qmlProgram();
UiProgram *prog = currentFile->qmljsDocument()->qmlProgram();
if (prog && prog->imports) {
const int start = startPosition(prog->imports->firstSourceLocation());
const int end = startPosition(prog->members->member->firstSourceLocation());
imports = state().textOf(start, end);
const int start = currentFile->startOf(prog->imports->firstSourceLocation());
const int end = currentFile->startOf(prog->members->member->firstSourceLocation());
imports = currentFile->textOf(start, end);
}
const int start = startPosition(m_objDef->firstSourceLocation());
const int end = startPosition(m_objDef->lastSourceLocation());
const QString txt = imports + state().textOf(start, end)
const int start = currentFile->startOf(m_objDef->firstSourceLocation());
const int end = currentFile->startOf(m_objDef->lastSourceLocation());
const QString txt = imports + currentFile->textOf(start, end)
+ QLatin1String("}\n");
// stop if we can't create the new file
......@@ -117,7 +117,7 @@ public:
Utils::ChangeSet changes;
changes.replace(start, end, m_componentName + QLatin1String(" {\n"));
currentFile->change(changes);
currentFile->indent(range(start, end + 1));
currentFile->indent(Range(start, end + 1));
}
};
......@@ -126,7 +126,7 @@ public:
QList<QmlJSQuickFixOperation::Ptr> ComponentFromObjectDef::match(const QmlJSQuickFixState &state)
{
QList<QmlJSQuickFixOperation::Ptr> result;
const int pos = state.textCursor().position();
const int pos = state.currentFile().cursor().position();
QList<Node *> path = state.semanticInfo().astPath(pos);
for (int i = path.size() - 1; i >= 0; --i) {
......
......@@ -67,9 +67,9 @@ Document::Ptr QmlJSQuickFixState::document() const
return _semanticInfo.document;
}
unsigned QmlJSQuickFixState::startPosition(const QmlJS::AST::SourceLocation &loc) const
const QmlJSRefactoringFile QmlJSQuickFixState::currentFile() const
{
return position(loc.startLine, loc.startColumn);
return QmlJSRefactoringFile(editor(), document());
}
QmlJSQuickFixOperation::QmlJSQuickFixOperation(const QmlJSQuickFixState &state, int priority)
......@@ -86,7 +86,7 @@ void QmlJSQuickFixOperation::perform()
{
QmlJSRefactoringChanges refactoring(ExtensionSystem::PluginManager::instance()->getObject<QmlJS::ModelManagerInterface>(),
_state.snapshot());
TextEditor::RefactoringFile current = refactoring.file(fileName());
QmlJSRefactoringFile current = refactoring.file(fileName());
performChanges(&current, &refactoring);
}
......
......@@ -64,7 +64,6 @@ class QmlJSQuickFixState: public TextEditor::QuickFixState
public:
/// Creates a new state for the given editor.
QmlJSQuickFixState(TextEditor::BaseTextEditor *editor);
typedef Utils::ChangeSet::Range Range;
Internal::SemanticInfo semanticInfo() const;
......@@ -74,11 +73,7 @@ public:
/// \returns the document of the editor
QmlJS::Document::Ptr document() const;
/*!
\returns the offset in the document for the start position of the given
source location.
*/
unsigned startPosition(const QmlJS::AST::SourceLocation &loc) const;
const QmlJSRefactoringFile currentFile() const;
private:
Internal::SemanticInfo _semanticInfo;
......@@ -108,7 +103,9 @@ public:
virtual void perform();
protected:
virtual void performChanges(TextEditor::RefactoringFile *currentFile, QmlJSRefactoringChanges *refactoring) = 0;
typedef Utils::ChangeSet::Range Range;
virtual void performChanges(QmlJSRefactoringFile *currentFile, QmlJSRefactoringChanges *refactoring) = 0;
/// \returns A const-reference to the state of the operation.
const QmlJSQuickFixState &state() const;
......@@ -116,15 +113,6 @@ protected:
/// \returns The name of the file for for which this operation is invoked.
QString fileName() const;
protected: // Utility functions forwarding to QmlJSQuickFixState
/// \see QmlJSQuickFixState#startPosition
unsigned startPosition(const QmlJS::AST::SourceLocation &loc) const
{ return state().startPosition(loc); }
/// \see QmlJSQuickFixState#range
static QmlJSQuickFixState::Range range(int start, int end)
{ return QmlJSQuickFixState::range(start, end); }
private:
QmlJSQuickFixState _state;
};
......
......@@ -56,7 +56,7 @@ public:
UiObjectInitializer *objectInitializer = 0;
const int pos = state.textCursor().position();
const int pos = state.currentFile().cursor().position();
if (QmlJS::AST::Node *member = state.semanticInfo().declaringMember(pos)) {
if (QmlJS::AST::UiObjectBinding *b = QmlJS::AST::cast<QmlJS::AST::UiObjectBinding *>(member)) {
......@@ -88,7 +88,7 @@ private:
"Split initializer"));
}
virtual void performChanges(TextEditor::RefactoringFile *currentFile, QmlJSRefactoringChanges *)
virtual void performChanges(QmlJSRefactoringFile *currentFile, QmlJSRefactoringChanges *)
{
Q_ASSERT(_objectInitializer != 0);
......@@ -99,17 +99,17 @@ private:
const QmlJS::AST::SourceLocation loc = member->firstSourceLocation();
// insert a newline at the beginning of this binding
changes.insert(startPosition(loc), QLatin1String("\n"));
changes.insert(currentFile->startOf(loc), QLatin1String("\n"));
}
}
// insert a newline before the closing brace
changes.insert(startPosition(_objectInitializer->rbraceToken),
changes.insert(currentFile->startOf(_objectInitializer->rbraceToken),
QLatin1String("\n"));
currentFile->change(changes);
currentFile->indent(range(startPosition(_objectInitializer->lbraceToken),
startPosition(_objectInitializer->rbraceToken)));
currentFile->indent(Range(currentFile->startOf(_objectInitializer->lbraceToken),
currentFile->startOf(_objectInitializer->rbraceToken)));
}
};
};
......
......@@ -45,6 +45,16 @@ QmlJSRefactoringChanges::QmlJSRefactoringChanges(ModelManagerInterface *modelMan
Q_ASSERT(modelManager);
}
const Snapshot &QmlJSRefactoringChanges::snapshot() const
{
return m_snapshot;
}
QmlJSRefactoringFile QmlJSRefactoringChanges::file(const QString &fileName)
{
return QmlJSRefactoringFile(fileName, this);
}
void QmlJSRefactoringChanges::indentSelection(const QTextCursor &selection) const
{
// ### shares code with QmlJSTextEditor::indent
......@@ -68,3 +78,43 @@ void QmlJSRefactoringChanges::fileChanged(const QString &fileName)
{
m_modelManager->updateSourceFiles(QStringList(fileName), true);
}
QmlJSRefactoringFile::QmlJSRefactoringFile()
{ }
QmlJSRefactoringFile::QmlJSRefactoringFile(const QString &fileName, QmlJSRefactoringChanges *refactoringChanges)
: RefactoringFile(fileName, refactoringChanges)
{ }
QmlJSRefactoringFile::QmlJSRefactoringFile(TextEditor::BaseTextEditor *editor, QmlJS::Document::Ptr document)
: RefactoringFile()
, m_qmljsDocument(document)
{
m_fileName = document->fileName();
m_editor = editor;
}
Document::Ptr QmlJSRefactoringFile::qmljsDocument() const
{
if (!m_qmljsDocument) {
const QString source = document()->toPlainText();
const QString name = fileName();
const Snapshot &snapshot = refactoringChanges()->snapshot();
m_qmljsDocument = snapshot.documentFromSource(source, name);
m_qmljsDocument->parse();
}
return m_qmljsDocument;
}
unsigned QmlJSRefactoringFile::startOf(const QmlJS::AST::SourceLocation &loc) const
{
return position(loc.startLine, loc.startColumn);
}
QmlJSRefactoringChanges *QmlJSRefactoringFile::refactoringChanges() const
{
return static_cast<QmlJSRefactoringChanges *>(m_refactoringChanges);
}
......@@ -40,12 +40,40 @@ class ModelManagerInterface;
namespace QmlJSEditor {
class QmlJSRefactoringChanges;
class QmlJSRefactoringFile: public TextEditor::RefactoringFile
{
public:
QmlJSRefactoringFile();
QmlJSRefactoringFile(const QString &fileName, QmlJSRefactoringChanges *refactoringChanges);
QmlJSRefactoringFile(TextEditor::BaseTextEditor *editor, QmlJS::Document::Ptr document);
QmlJS::Document::Ptr qmljsDocument() const;
/*!
\returns the offset in the document for the start position of the given
source location.
*/
unsigned startOf(const QmlJS::AST::SourceLocation &loc) const;
private:
QmlJSRefactoringChanges *refactoringChanges() const;
mutable QmlJS::Document::Ptr m_qmljsDocument;
};
class QmlJSRefactoringChanges: public TextEditor::RefactoringChanges
{
public:
QmlJSRefactoringChanges(QmlJS::ModelManagerInterface *modelManager,
const QmlJS::Snapshot &snapshot);
const QmlJS::Snapshot &snapshot() const;
QmlJSRefactoringFile file(const QString &fileName);
private:
virtual void indentSelection(const QTextCursor &selection) const;
virtual void fileChanged(const QString &fileName);
......
......@@ -41,7 +41,6 @@ using namespace TextEditor;
QuickFixState::QuickFixState(TextEditor::BaseTextEditor *editor)
: _editor(editor)
, _textCursor(editor->textCursor())
{
}
......@@ -54,45 +53,6 @@ TextEditor::BaseTextEditor *QuickFixState::editor() const
return _editor;
}
QTextCursor QuickFixState::textCursor() const
{
return _textCursor;
}
int QuickFixState::selectionStart() const
{
return _textCursor.selectionStart();
}
int QuickFixState::selectionEnd() const
{
return _textCursor.selectionEnd();
}
int QuickFixState::position(int line, int column) const
{
QTextDocument *doc = editor()->document();
return doc->findBlockByNumber(line - 1).position() + column - 1;
}
QChar QuickFixState::charAt(int offset) const
{
QTextDocument *doc = _textCursor.document();
return doc->characterAt(offset);
}
QString QuickFixState::textOf(int start, int end) const
{
QTextCursor tc = _textCursor;
tc.setPosition(start);
tc.setPosition(end, QTextCursor::KeepAnchor);
return tc.selectedText();
}
Utils::ChangeSet::Range QuickFixState::range(int start, int end)
{
return Utils::ChangeSet::Range(start, end);
}
QuickFixOperation::QuickFixOperation(int priority)
{
......
......@@ -56,42 +56,8 @@ public:
TextEditor::BaseTextEditor *editor() const;
/*!
\returns A QTextCursor positioned as the editor's visible cursor, including
possible selections.
*/
QTextCursor textCursor() const;
/// \returns The character offset in the document where the selection starts.
int selectionStart() const;
/// \returns The character offset in the document where the selection ends.
int selectionEnd() const;
/*!
Calculates the offset in the document for the given line and column.
\param line The line number, 1-based.
\param column The column number, 1-based.
\return The offset in the \c QTextDocument of the editor.
*/
int position(int line, int column) const;
/// \returns The character at the given offset in the editor's text document.
QChar charAt(int offset) const;
/*!
\returns The text between the given start- and end-offset in the editor's
text document.
*/
QString textOf(int start, int end) const;
/// Utility method to create a range.
static Utils::ChangeSet::Range range(int start, int end);
private:
TextEditor::BaseTextEditor *_editor;
QTextCursor _textCursor;
};
/*!
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment