forked from qt-creator/qt-creator
Show how to simplify declarations. e.g.
static int i, *ptr = &i; will be replaced with static int i; static int *ptr = &i; using the editor's context menu > Simplify Declarations
This commit is contained in:
@@ -143,6 +143,111 @@ protected:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SimplifyDeclarations: protected ASTVisitor
|
||||||
|
{
|
||||||
|
CPPEditor *_editor;
|
||||||
|
Document::Ptr _doc;
|
||||||
|
QByteArray _source;
|
||||||
|
QTextCursor _textCursor;
|
||||||
|
unsigned _line;
|
||||||
|
unsigned _column;
|
||||||
|
|
||||||
|
public:
|
||||||
|
SimplifyDeclarations(CPPEditor *ed, Document::Ptr doc)
|
||||||
|
: ASTVisitor(doc->control()), _editor(ed),
|
||||||
|
_doc(doc), _source(doc->source())
|
||||||
|
{ }
|
||||||
|
|
||||||
|
void operator()(QTextCursor tc)
|
||||||
|
{
|
||||||
|
_textCursor = tc;
|
||||||
|
|
||||||
|
_line = _textCursor.blockNumber() + 1;
|
||||||
|
_column = _textCursor.columnNumber() + 1;
|
||||||
|
|
||||||
|
accept(_doc->translationUnit()->ast());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
QByteArray text(unsigned firstToken, unsigned lastToken) const
|
||||||
|
{
|
||||||
|
const unsigned begin = tokenAt(firstToken).begin();
|
||||||
|
const unsigned end = tokenAt(lastToken - 1).end();
|
||||||
|
return _source.mid(begin, end - begin);
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool visit(SimpleDeclarationAST *ast)
|
||||||
|
{
|
||||||
|
if (! ast->decl_specifier_seq) {
|
||||||
|
// e.g a ctor/dtor or a cast-function-id.
|
||||||
|
return true;
|
||||||
|
} if (! ast->declarators) {
|
||||||
|
// e.g.
|
||||||
|
// struct foo { int a; };
|
||||||
|
return true;
|
||||||
|
} else if (! ast->declarators->next) {
|
||||||
|
// e.g.
|
||||||
|
// int a;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned startLine, startColumn;
|
||||||
|
unsigned endLine, endColumn;
|
||||||
|
|
||||||
|
getTokenStartPosition(ast->firstToken(), &startLine, &startColumn);
|
||||||
|
getTokenEndPosition(ast->lastToken() - 1, &endLine, &endColumn);
|
||||||
|
|
||||||
|
if (_line < startLine || (_line == startLine && _column < startColumn))
|
||||||
|
return true;
|
||||||
|
else if (_line > endLine || (_line == endLine && _column >= endColumn))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
unsigned beginOfDeclSpecifiers = ast->decl_specifier_seq->firstToken();
|
||||||
|
unsigned endOfDeclSpecifiers = 0;
|
||||||
|
|
||||||
|
for (SpecifierAST *spec = ast->decl_specifier_seq; spec; spec = spec->next) {
|
||||||
|
if (spec->asClassSpecifier() != 0) {
|
||||||
|
// e.g.
|
||||||
|
// struct foo { int a; } x, y, z;
|
||||||
|
return true;
|
||||||
|
} else if (! spec->next)
|
||||||
|
endOfDeclSpecifiers = spec->lastToken();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QByteArray declSpecifiers =
|
||||||
|
text(beginOfDeclSpecifiers, endOfDeclSpecifiers);
|
||||||
|
|
||||||
|
QByteArray code;
|
||||||
|
for (DeclaratorListAST *it = ast->declarators; it; it = it->next) {
|
||||||
|
DeclaratorAST *decl = it->declarator;
|
||||||
|
|
||||||
|
const QByteArray declaratorText = text(decl->firstToken(), decl->lastToken());
|
||||||
|
code += declSpecifiers;
|
||||||
|
code += ' ';
|
||||||
|
code += declaratorText;
|
||||||
|
code += ';';
|
||||||
|
code += '\n';
|
||||||
|
}
|
||||||
|
|
||||||
|
const QString refactoredCode = QString::fromUtf8(code);
|
||||||
|
|
||||||
|
QTextCursor tc = _textCursor;
|
||||||
|
tc.beginEditBlock();
|
||||||
|
tc.setPosition(tc.document()->findBlockByNumber(startLine - 1).position() + startColumn - 1);
|
||||||
|
int startPos = tc.position();
|
||||||
|
tc.setPosition(tc.document()->findBlockByNumber(endLine - 1).position() + endColumn - 1,
|
||||||
|
QTextCursor::KeepAnchor);
|
||||||
|
tc.removeSelectedText();
|
||||||
|
tc.insertText(refactoredCode);
|
||||||
|
tc.setPosition(startPos);
|
||||||
|
tc.setPosition(tc.position() + refactoredCode.length(), QTextCursor::KeepAnchor);
|
||||||
|
_editor->indentInsertedText(tc);
|
||||||
|
tc.endEditBlock();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
} // end of anonymous namespace
|
} // end of anonymous namespace
|
||||||
|
|
||||||
static QualifiedNameId *qualifiedNameIdForSymbol(Symbol *s, const LookupContext &context)
|
static QualifiedNameId *qualifiedNameIdForSymbol(Symbol *s, const LookupContext &context)
|
||||||
@@ -411,6 +516,18 @@ void CPPEditor::reformatDocument()
|
|||||||
c.insertText(QString::fromUtf8(str.c_str(), str.length()));
|
c.insertText(QString::fromUtf8(str.c_str(), str.length()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPPEditor::simplifyDeclarations()
|
||||||
|
{
|
||||||
|
Snapshot snapshot = m_modelManager->snapshot();
|
||||||
|
const QByteArray plainText = toPlainText().toUtf8();
|
||||||
|
const QString fileName = file()->fileName();
|
||||||
|
const QByteArray preprocessedCode = snapshot.preprocessedCode(plainText, fileName);
|
||||||
|
Document::Ptr doc = snapshot.documentFromSource(preprocessedCode, fileName);
|
||||||
|
|
||||||
|
SimplifyDeclarations simplify(this, doc);
|
||||||
|
simplify(textCursor());
|
||||||
|
}
|
||||||
|
|
||||||
void CPPEditor::updateFileName()
|
void CPPEditor::updateFileName()
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
@@ -848,6 +965,11 @@ bool CPPEditor::isElectricCharacter(const QChar &ch) const
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CPPEditor::indentInsertedText(const QTextCursor &tc)
|
||||||
|
{
|
||||||
|
indent(tc.document(), tc, QChar::Null);
|
||||||
|
}
|
||||||
|
|
||||||
// Indent a code line based on previous
|
// Indent a code line based on previous
|
||||||
template <class Iterator>
|
template <class Iterator>
|
||||||
static void indentCPPBlock(const CPPEditor::TabSettings &ts,
|
static void indentCPPBlock(const CPPEditor::TabSettings &ts,
|
||||||
@@ -890,6 +1012,10 @@ void CPPEditor::contextMenuEvent(QContextMenuEvent *e)
|
|||||||
foreach (QAction *action, contextMenu->actions())
|
foreach (QAction *action, contextMenu->actions())
|
||||||
menu->addAction(action);
|
menu->addAction(action);
|
||||||
|
|
||||||
|
QAction *simplifyDeclarations = new QAction(tr("Simplify Declarations"), menu);
|
||||||
|
connect(simplifyDeclarations, SIGNAL(triggered()), this, SLOT(simplifyDeclarations()));
|
||||||
|
menu->addAction(simplifyDeclarations);
|
||||||
|
|
||||||
menu->exec(e->globalPos());
|
menu->exec(e->globalPos());
|
||||||
delete menu;
|
delete menu;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,8 @@ public:
|
|||||||
|
|
||||||
void unCommentSelection();
|
void unCommentSelection();
|
||||||
|
|
||||||
|
void indentInsertedText(const QTextCursor &tc);
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
virtual void setFontSettings(const TextEditor::FontSettings &);
|
virtual void setFontSettings(const TextEditor::FontSettings &);
|
||||||
virtual void setDisplaySettings(const TextEditor::DisplaySettings &);
|
virtual void setDisplaySettings(const TextEditor::DisplaySettings &);
|
||||||
@@ -119,6 +121,7 @@ private slots:
|
|||||||
void updateMethodBoxToolTip();
|
void updateMethodBoxToolTip();
|
||||||
void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
|
void onDocumentUpdated(CPlusPlus::Document::Ptr doc);
|
||||||
void reformatDocument();
|
void reformatDocument();
|
||||||
|
void simplifyDeclarations();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool sortedMethodOverview() const;
|
bool sortedMethodOverview() const;
|
||||||
|
|||||||
Reference in New Issue
Block a user