From ac9fc40645638091dcd32bcdbce7d75dc2140825 Mon Sep 17 00:00:00 2001 From: Erik Verbruggen <erik.verbruggen@nokia.com> Date: Wed, 6 Oct 2010 15:49:59 +0200 Subject: [PATCH] C++ Editor: check for method existing decl/def when inserting new ones. --- src/libs/cplusplus/CppRewriter.cpp | 2 + src/plugins/cppeditor/cppinsertdecldef.cpp | 91 ++++++++++--------- .../cpptools/cpprefactoringchanges.cpp | 3 +- .../cpptools/insertionpointlocator.cpp | 10 ++ 4 files changed, 60 insertions(+), 46 deletions(-) diff --git a/src/libs/cplusplus/CppRewriter.cpp b/src/libs/cplusplus/CppRewriter.cpp index d91f175a2a5..da87e756aed 100644 --- a/src/libs/cplusplus/CppRewriter.cpp +++ b/src/libs/cplusplus/CppRewriter.cpp @@ -132,6 +132,8 @@ public: { Function *funTy = control()->newFunction(0, 0); funTy->copy(type); + funTy->setConst(type->isConst()); + funTy->setVolatile(type->isVolatile()); funTy->setName(rewrite->rewriteName(type->name())); diff --git a/src/plugins/cppeditor/cppinsertdecldef.cpp b/src/plugins/cppeditor/cppinsertdecldef.cpp index cc8b93201d9..0df1a8ba802 100644 --- a/src/plugins/cppeditor/cppinsertdecldef.cpp +++ b/src/plugins/cppeditor/cppinsertdecldef.cpp @@ -29,12 +29,7 @@ #include "cppinsertdecldef.h" -#include <AST.h> -#include <ASTVisitor.h> -#include <CoreTypes.h> -#include <Names.h> -#include <Symbols.h> -#include <TranslationUnit.h> +#include <CPlusPlus.h> #include <cplusplus/ASTPath.h> #include <cplusplus/CppRewriter.h> #include <cplusplus/LookupContext.h> @@ -42,6 +37,7 @@ #include <cpptools/insertionpointlocator.h> #include <QtCore/QCoreApplication> +#include <QtCore/QDir> using namespace CPlusPlus; using namespace CppEditor; @@ -142,46 +138,49 @@ QList<CppQuickFixOperation::Ptr> DeclFromDef::match(const CppQuickFixState &stat Function *method = funDef->symbol; - if (ClassOrNamespace *targetBinding = state.context().lookupParent(method)) { - foreach (Symbol *s, targetBinding->symbols()) { - if (Class *clazz = s->asClass()) { - QList<CppQuickFixOperation::Ptr> results; - const QString fn = QString::fromUtf8(clazz->fileName(), clazz->fileNameLength()); + Scope *enclosingScope = method->enclosingScope(); + while (! (enclosingScope->isNamespace() || enclosingScope->isClass())) + enclosingScope = enclosingScope->enclosingScope(); + Q_ASSERT(enclosingScope != 0); + + 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, 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 of non-methods into namespaces + binding); + return singleResult( + new InsertDeclOperation(state, idx, fn, matchingClass, + InsertionPointLocator::Public, + decl)); + } } } @@ -217,9 +216,11 @@ public: , m_decl(decl) , m_loc(loc) { + const QString declFile = QString::fromUtf8(decl->fileName(), decl->fileNameLength()); + const QDir dir = QFileInfo(declFile).dir(); setDescription(QCoreApplication::translate("CppEditor::InsertDefOperation", "Add definition in %1") - .arg(m_loc.fileName())); + .arg(dir.relativeFilePath(m_loc.fileName()))); } void performChanges(CppRefactoringFile *, diff --git a/src/plugins/cpptools/cpprefactoringchanges.cpp b/src/plugins/cpptools/cpprefactoringchanges.cpp index b320b578b52..68b63f167de 100644 --- a/src/plugins/cpptools/cpprefactoringchanges.cpp +++ b/src/plugins/cpptools/cpprefactoringchanges.cpp @@ -104,7 +104,8 @@ CppRefactoringFile::CppRefactoringFile(TextEditor::BaseTextEditor *editor, CPlus 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 name = fileName(); const Snapshot &snapshot = refactoringChanges()->snapshot(); diff --git a/src/plugins/cpptools/insertionpointlocator.cpp b/src/plugins/cpptools/insertionpointlocator.cpp index 8d924a37fbd..1d6a894f67c 100644 --- a/src/plugins/cpptools/insertionpointlocator.cpp +++ b/src/plugins/cpptools/insertionpointlocator.cpp @@ -315,6 +315,7 @@ static bool isSourceFile(const QString &fileName) } /// Currently, we return the end of fileName.cpp +/// \todo take the definitions of the surrounding declarations into account QList<InsertionLocation> InsertionPointLocator::methodDefinition( Declaration *declaration) const { @@ -334,6 +335,15 @@ QList<InsertionLocation> InsertionPointLocator::methodDefinition( if (doc.isNull()) 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(); unsigned tokenCount = xUnit->tokenCount(); if (tokenCount < 2) // no tokens available -- GitLab