C++ Editor: check for method existing decl/def when inserting new ones.

This commit is contained in:
Erik Verbruggen
2010-10-06 15:49:59 +02:00
parent 0555837c7f
commit ac9fc40645
4 changed files with 60 additions and 46 deletions

View File

@@ -132,6 +132,8 @@ public:
{ {
Function *funTy = control()->newFunction(0, 0); Function *funTy = control()->newFunction(0, 0);
funTy->copy(type); funTy->copy(type);
funTy->setConst(type->isConst());
funTy->setVolatile(type->isVolatile());
funTy->setName(rewrite->rewriteName(type->name())); funTy->setName(rewrite->rewriteName(type->name()));

View File

@@ -29,12 +29,7 @@
#include "cppinsertdecldef.h" #include "cppinsertdecldef.h"
#include <AST.h> #include <CPlusPlus.h>
#include <ASTVisitor.h>
#include <CoreTypes.h>
#include <Names.h>
#include <Symbols.h>
#include <TranslationUnit.h>
#include <cplusplus/ASTPath.h> #include <cplusplus/ASTPath.h>
#include <cplusplus/CppRewriter.h> #include <cplusplus/CppRewriter.h>
#include <cplusplus/LookupContext.h> #include <cplusplus/LookupContext.h>
@@ -42,6 +37,7 @@
#include <cpptools/insertionpointlocator.h> #include <cpptools/insertionpointlocator.h>
#include <QtCore/QCoreApplication> #include <QtCore/QCoreApplication>
#include <QtCore/QDir>
using namespace CPlusPlus; using namespace CPlusPlus;
using namespace CppEditor; using namespace CppEditor;
@@ -142,46 +138,49 @@ QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &stat
Function *method = funDef->symbol; Function *method = funDef->symbol;
if (ClassOrNamespace *targetBinding = state.context().lookupParent(method)) { Scope *enclosingScope = method->enclosingScope();
foreach (Symbol *s, targetBinding->symbols()) { while (! (enclosingScope->isNamespace() || enclosingScope->isClass()))
if (Class *clazz = s->asClass()) { enclosingScope = enclosingScope->enclosingScope();
QList<CppQuickFixOperation::Ptr> results; Q_ASSERT(enclosingScope != 0);
const QString fn = QString::fromUtf8(clazz->fileName(), clazz->fileNameLength());
const Name *functionName = method->name();
if (! functionName)
return noResult(); // warn, anonymous function names are not valid c++
if (! functionName->isQualifiedNameId())
return noResult(); // warn, trying to add a declaration for a global function
const QualifiedNameId *q = functionName->asQualifiedNameId();
if (!q->base())
return noResult();
if (ClassOrNamespace *binding = state.context().lookupType(q->base(), enclosingScope)) {
foreach (Symbol *s, binding->symbols()) {
if (Class *matchingClass = s->asClass()) {
for (Symbol *s = matchingClass->find(q->identifier()); s; s = s->next()) {
if (! s->name())
continue;
else if (! q->identifier()->isEqualTo(s->identifier()))
continue;
else if (! s->type()->isFunctionType())
continue;
if (s->type().isEqualTo(method->type()))
return noResult();
}
// a good candidate
const QString fn = QString::fromUtf8(matchingClass->fileName(),
matchingClass->fileNameLength());
const QString decl = generateDeclaration(state, const QString decl = generateDeclaration(state,
method, method,
targetBinding); binding);
results.append( return singleResult(
singleResult( new InsertDeclOperation(state, idx, fn, matchingClass,
new InsertDeclOperation(state, idx, fn, clazz,
InsertionPointLocator::Public, InsertionPointLocator::Public,
decl))); 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
} }
} }
@@ -217,9 +216,11 @@ public:
, m_decl(decl) , m_decl(decl)
, m_loc(loc) , m_loc(loc)
{ {
const QString declFile = QString::fromUtf8(decl->fileName(), decl->fileNameLength());
const QDir dir = QFileInfo(declFile).dir();
setDescription(QCoreApplication::translate("CppEditor::InsertDefOperation", setDescription(QCoreApplication::translate("CppEditor::InsertDefOperation",
"Add definition in %1") "Add definition in %1")
.arg(m_loc.fileName())); .arg(dir.relativeFilePath(m_loc.fileName())));
} }
void performChanges(CppRefactoringFile *, void performChanges(CppRefactoringFile *,

View File

@@ -104,7 +104,8 @@ CppRefactoringFile::CppRefactoringFile(TextEditor::BaseTextEditor *editor, CPlus
Document::Ptr CppRefactoringFile::cppDocument() const Document::Ptr CppRefactoringFile::cppDocument() const
{ {
if (!m_cppDocument) { if (!m_cppDocument || !m_cppDocument->translationUnit() ||
!m_cppDocument->translationUnit()->ast()) {
const QString source = document()->toPlainText(); const QString source = document()->toPlainText();
const QString name = fileName(); const QString name = fileName();
const Snapshot &snapshot = refactoringChanges()->snapshot(); const Snapshot &snapshot = refactoringChanges()->snapshot();

View File

@@ -315,6 +315,7 @@ static bool isSourceFile(const QString &fileName)
} }
/// Currently, we return the end of fileName.cpp /// Currently, we return the end of fileName.cpp
/// \todo take the definitions of the surrounding declarations into account
QList<InsertionLocation> InsertionPointLocator::methodDefinition( QList<InsertionLocation> InsertionPointLocator::methodDefinition(
Declaration *declaration) const Declaration *declaration) const
{ {
@@ -334,6 +335,15 @@ QList<InsertionLocation> InsertionPointLocator::methodDefinition(
if (doc.isNull()) if (doc.isNull())
return result; return result;
Snapshot simplified = m_refactoringChanges->snapshot().simplified(doc);
if (Symbol *s = simplified.findMatchingDefinition(declaration)) {
if (Function *f = s->asFunction()) {
if (f->isConst() == declaration->type().isConst()
&& f->isVolatile() == declaration->type().isVolatile())
return result;
}
}
TranslationUnit *xUnit = doc->translationUnit(); TranslationUnit *xUnit = doc->translationUnit();
unsigned tokenCount = xUnit->tokenCount(); unsigned tokenCount = xUnit->tokenCount();
if (tokenCount < 2) // no tokens available if (tokenCount < 2) // no tokens available