Generate Getters and Setters functionality into KDevelop

Carlos Nihelton carlosnsoliveira at gmail.com
Tue Aug 30 00:16:28 UTC 2016


Hi KDevelopers!

I was trying to hack a bit inside KDevelop and decided to implement one 
feature into ClangRefactoring class to be able to automatically generate 
accessor and mutator member functions for a given member variable 
declaration. I think I'm doing right in recognizing the selected 
declaration as a member variable and I even got a function declaration 
QString by hand manipulation, although I'm quite sure this is not the 
right way to do it.

I stuck on how to generate the KDevelop::Declaration for the functions 
and how to insert them into code.

Can you guys give me some ideas?

void ClangRefactoring::fillContextMenu(ContextMenuExtension& extension, Context* context){

... [all the existing code]...

     /// If the declaration is a member variable, allows for adding  getter and
     /// setter member functions.
     
     auto memDecl = dynamic_cast<ClassMemberDeclaration*>(declaration);
     if(memDecl && !memDecl->isFunctionDeclaration()) {
         auto action = new QAction(i18n("Add getter and setter for %1",
             declaration->qualifiedIdentifier().toString()),this);
         action->setData(QVariant::fromValue(IndexedDeclaration(declaration)));
         connect(action, &QAction::triggered, this,
                 &ClangRefactoring::addGettersAndSetters);
         extension.addAction(ContextMenuExtension::RefactorGroup, action);
     }

... [all the existing code]...

}


void ClangRefactoring::addGettersAndSetters()
{
     QString error;
     
     QMessageBox::information(0, QStringLiteral("Action Triggered"),
         QStringLiteral("Add getters and setters"), QMessageBox::Ok);
     
     auto action = qobject_cast<QAction*>(sender());
     Q_ASSERT(action);

     auto iDecl = action->data().value<IndexedDeclaration>();
     if (!iDecl.isValid()) {
         iDecl = declarationUnderCursor(false);
     }
     
     DUChainReadLocker lock;
     auto decl = iDecl.data();
     if (!decl) {
         error = i18n("No declaration under cursor");
     }

     const auto headerUrl = decl->url();
     auto targetCppUrl = DocumentFinderHelpers::sourceForHeader(headerUrl.str());

     if (targetCppUrl.isEmpty() || targetCppUrl == headerUrl.str()) {
         // TODO: Create source file if it doesn't exist
         error = i18n("No source file available for %1.", headerUrl.str());
     }

     lock.unlock();
     const IndexedString indexedTargetUrl(targetCppUrl);
     auto topHeaderContext
         = DUChain::self()->waitForUpdate(headerUrl,
KDevelop::TopDUContext::AllDeclarationsAndContexts);
     auto targetTopContext
         = DUChain::self()->waitForUpdate(indexedTargetUrl,
KDevelop::TopDUContext::AllDeclarationsAndContexts);
     lock.lock();

     if (!targetTopContext) {
         error = i18n("Failed to update DUChain for %1.", targetCppUrl);
     }

     if (!topHeaderContext || !iDecl.data() || iDecl.data() != decl) {
         error = i18n("Declaration lost while updating.");
     }

     clangDebug() << "Analyzing " << decl->qualifiedIdentifier();

/// Hand manipulation - bad smell.
     auto classIdentifier = decl->context()->scopeIdentifier(true).toString();
     auto identifier = decl->identifier().toString();
     auto type = decl->abstractType()->toString();
     identifier.remove(QRegExp(QStringLiteral("^\\w_")));
     auto accessorIdentifier =
         identifier.replace(0,1,identifier.at(0).toUpper());
     accessorIdentifier.prepend(QStringLiteral("get"));
     

     
     QMessageBox::information(0, QStringLiteral("Action Triggered"),
         type+QLatin1Char(' ')+classIdentifier+QStringLiteral("::") +
accessorIdentifier+QStringLiteral("() const;"),
QMessageBox::Ok);

...
}

-- 
Atenciosamente,
Carlos Nihelton
Engenheiro Eletricista



More information about the KDevelop-devel mailing list