C++: make InsertionPointLocator ready for re-use.

(cherry picked from commit 519f1d11947ff3109850e559fae868c4a55deb43)
This commit is contained in:
Erik Verbruggen
2010-09-27 18:01:04 +02:00
committed by Robert Loehning
parent 91208c827f
commit f39494e4c2
6 changed files with 345 additions and 93 deletions

View File

@@ -51,13 +51,13 @@ using CppEditor::CppRefactoringChanges;
namespace {
class Operation: public CppQuickFixOperation
class InsertDeclOperation: public CppQuickFixOperation
{
public:
Operation(const CppQuickFixState &state, int priority,
const QString &targetFileName, const Class *targetSymbol,
InsertionPointLocator::AccessSpec xsSpec,
const QString &decl)
InsertDeclOperation(const CppQuickFixState &state, int priority,
const QString &targetFileName, const Class *targetSymbol,
InsertionPointLocator::AccessSpec xsSpec,
const QString &decl)
: CppQuickFixOperation(state, priority)
, m_targetFileName(targetFileName)
, m_targetSymbol(targetSymbol)
@@ -81,12 +81,12 @@ public:
void performChanges(CppRefactoringFile *, CppRefactoringChanges *refactoring)
{
CppRefactoringFile targetFile = refactoring->file(m_targetFileName);
Document::Ptr targetDoc = targetFile.cppDocument();
InsertionPointLocator locator(targetDoc);
const InsertionLocation loc = locator.methodDeclarationInClass(m_targetSymbol, m_xsSpec);
InsertionPointLocator locator(state().snapshot());
const InsertionLocation loc = locator.methodDeclarationInClass(
m_targetFileName, m_targetSymbol, m_xsSpec);
Q_ASSERT(loc.isValid());
CppRefactoringFile targetFile = refactoring->file(m_targetFileName);
int targetPosition1 = targetFile.position(loc.line(), loc.column());
int targetPosition2 = qMax(0, targetFile.position(loc.line(), 1) - 1);
@@ -151,24 +151,36 @@ QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &stat
const QString decl = generateDeclaration(state,
method,
targetBinding);
results.append(singleResult(new Operation(state, idx, fn, clazz,
InsertionPointLocator::Public,
decl)));
results.append(singleResult(new Operation(state, idx, fn, clazz,
InsertionPointLocator::Protected,
decl)));
results.append(singleResult(new Operation(state, idx, fn, clazz,
InsertionPointLocator::Private,
decl)));
results.append(singleResult(new Operation(state, idx, fn, clazz,
InsertionPointLocator::PublicSlot,
decl)));
results.append(singleResult(new Operation(state, idx, fn, clazz,
InsertionPointLocator::ProtectedSlot,
decl)));
results.append(singleResult(new Operation(state, idx, fn, clazz,
InsertionPointLocator::PrivateSlot,
decl)));
results.append(
singleResult(
new InsertDeclOperation(state, idx, fn, clazz,
InsertionPointLocator::Public,
decl)));
results.append(
singleResult(
new InsertDeclOperation(state, idx, fn, clazz,
InsertionPointLocator::Protected,
decl)));
results.append(
singleResult(
new InsertDeclOperation(state, idx, fn, clazz,
InsertionPointLocator::Private,
decl)));
results.append(
singleResult(
new InsertDeclOperation(state, idx, fn, clazz,
InsertionPointLocator::PublicSlot,
decl)));
results.append(
singleResult(
new InsertDeclOperation(state, idx, fn, clazz,
InsertionPointLocator::ProtectedSlot,
decl)));
results.append(
singleResult(
new InsertDeclOperation(state, idx, fn, clazz,
InsertionPointLocator::PrivateSlot,
decl)));
return results;
} //! \todo support insertion of non-methods into namespaces
}
@@ -194,3 +206,171 @@ QString DeclFromDef::generateDeclaration(const CppQuickFixState &,
return decl;
}
namespace {
static inline bool hasFunctionType(DeclarationAST *decl)
{
if (decl->asFunctionDefinition())
return true;
if (SimpleDeclarationAST *ast = decl->asSimpleDeclaration())
if (ast->symbols && ast->symbols->value && !ast->symbols->next)
if (Declaration *decl = ast->symbols->value->asDeclaration())
if (FullySpecifiedType ty = decl->type())
return ty->asFunctionType();
return false;
}
static QPair<DeclarationAST *, DeclarationAST *> findSurroundingDeclarations(
DeclarationListAST *members,
DeclarationAST *decl)
{
bool found = false;
DeclarationAST *last = 0, *next = 0, *prev = 0;
DeclarationListAST *iter = members;
for (; iter; iter = iter->next) {
DeclarationAST *value = iter->value;
if (value == decl) {
prev = last;
found = true;
} else if (hasFunctionType(value)) {
if (found) {
next = value;
break;
} else {
last = value;
}
}
}
return qMakePair(prev, next);
}
} // anonymous namespace
QList<CppQuickFixOperation::Ptr> DefFromDecl::match(const CppQuickFixState &state)
{
#if 0
qDebug() << Q_FUNC_INFO;
const QList<AST *> &path = state.path();
const CppRefactoringFile &file = state.currentFile();
DeclaratorAST *declAST = 0;
ClassSpecifierAST *classSpec = 0;
int idx = path.size() - 1;
for (; idx >= 0; --idx) {
AST *node = path.at(idx);
if (ClassSpecifierAST *clazz = node->asClassSpecifier()) {
classSpec = clazz;
continue;
}
if (idx <= 1) continue;
DeclaratorIdAST *declId = node->asDeclaratorId();
if (!declId) continue;
if (!file.isCursorOn(declId)) continue;
DeclaratorAST *candidate = path.at(idx - 1)->asDeclarator();
if (!candidate) continue;
if (!candidate->postfix_declarator_list) continue;
if (!candidate->postfix_declarator_list->value) continue;
if (candidate->postfix_declarator_list->next) continue;
FunctionDeclaratorAST *funDecl = candidate->postfix_declarator_list->value->asFunctionDeclarator();
if (!funDecl) continue;
if (funDecl->symbol->asFunctionType())
declAST = candidate;
}
if (!declAST || !classSpec || !classSpec->symbol)
return noResult();
if (!declAST->symbols || !declAST->symbols->value || declAST->symbols->next)
return noResult();
Declaration *decl = declAST->symbols->value->asDeclaration();
if (!decl)
return noResult();
Function *funTy = decl->type()->asFunctionType();
if (!funTy)
return noResult();
qDebug() << "-> Found funTy.";
QPair<DeclarationAST *, DeclarationAST *> surroundingNodes =
findSurroundingDeclarations(classSpec->member_specifier_list, declAST);
qDebug() << "->("<<surroundingNodes.first<<","<<surroundingNodes.second<<")";
if (surroundingNodes.first)
if (SimpleDeclarationAST *sd = surroundingNodes.first->asSimpleDeclaration())
qDebug()<<"-->prev@"<<sd->symbols->value->line()<<sd->symbols->value->column();
if (surroundingNodes.second)
if (SimpleDeclarationAST *sd=surroundingNodes.second->asSimpleDeclaration())
qDebug()<<"-->next@"<<sd->symbols->value->line()<<sd->symbols->value->column();
#endif
// if (ClassOrNamespace *targetBinding = state.context().lookupParent(method)) {
// foreach (Symbol *s, targetBinding->symbols()) {
// if (Class *clazz = s->asClass()) {
// QList<CppQuickFixOperation::Ptr> results;
// const QLatin1String fn(clazz->fileName());
// const QString decl = generateDeclaration(state,
// method,
// targetBinding);
// results.append(
// singleResult(
// new InsertDeclOperation(state, idx, fn, clazz,
// InsertionPointLocator::Public,
// decl)));
// results.append(
// singleResult(
// new InsertDeclOperation(state, idx, fn, clazz,
// InsertionPointLocator::Protected,
// decl)));
// results.append(
// singleResult(
// new InsertDeclOperation(state, idx, fn, clazz,
// InsertionPointLocator::Private,
// decl)));
// results.append(
// singleResult(
// new InsertDeclOperation(state, idx, fn, clazz,
// InsertionPointLocator::PublicSlot,
// decl)));
// results.append(
// singleResult(
// new InsertDeclOperation(state, idx, fn, clazz,
// InsertionPointLocator::ProtectedSlot,
// decl)));
// results.append(
// singleResult(
// new InsertDeclOperation(state, idx, fn, clazz,
// InsertionPointLocator::PrivateSlot,
// decl)));
// return results;
// } //! \todo support insertion into namespaces
// }
// }
return noResult();
}
QString DefFromDecl::generateDefinition(const CppQuickFixState &,
Function *method,
ClassOrNamespace *targetBinding)
{
Q_UNUSED(targetBinding);
Overview oo;
oo.setShowFunctionSignatures(true);
oo.setShowReturnTypes(true);
oo.setShowArgumentNames(true);
QString decl;
decl += oo(method->type(), method->unqualifiedName());
decl += QLatin1String(";\n");
return decl;
}