File indexing completed on 2024-04-28 04:38:20
0001 /* 0002 SPDX-FileCopyrightText: 2010 Milian Wolff <mail@milianw.de> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "codeutilsplugin.h" 0008 0009 #include <QAction> 0010 #include <QVariantList> 0011 0012 #include <KLocalizedString> 0013 #include <KPluginFactory> 0014 #include <KActionCollection> 0015 0016 #include <KTextEditor/Document> 0017 #include <KTextEditor/View> 0018 #include <QStandardPaths> 0019 0020 #include <interfaces/icore.h> 0021 #include <interfaces/idocumentcontroller.h> 0022 #include <interfaces/context.h> 0023 #include <interfaces/ilanguagecontroller.h> 0024 0025 #include <language/duchain/duchainutils.h> 0026 #include <language/duchain/declaration.h> 0027 #include <language/duchain/duchainlock.h> 0028 #include <language/duchain/abstractfunctiondeclaration.h> 0029 #include <language/duchain/topducontext.h> 0030 #include <language/duchain/types/functiontype.h> 0031 #include <language/codegen/templaterenderer.h> 0032 #include <language/codegen/codedescription.h> 0033 #include <language/interfaces/ilanguagesupport.h> 0034 #include <debug.h> 0035 0036 0037 using namespace KDevelop; 0038 using namespace KTextEditor; 0039 0040 K_PLUGIN_FACTORY_WITH_JSON(CodeUtilsPluginFactory, "kdevcodeutils.json", registerPlugin<CodeUtilsPlugin>(); ) 0041 0042 CodeUtilsPlugin::CodeUtilsPlugin ( QObject* parent, const QVariantList& ) 0043 : IPlugin ( QStringLiteral("kdevcodeutils"), parent ) 0044 { 0045 setXMLFile( QStringLiteral("kdevcodeutils.rc") ); 0046 0047 QAction* action = actionCollection()->addAction( QStringLiteral("document_declaration") ); 0048 // i18n: action name; 'Document' is a verb 0049 action->setText(i18nc("@action", "Document Declaration")); 0050 actionCollection()->setDefaultShortcut(action, i18nc("default shortcut for \"Document Declaration\"", "Alt+Shift+d")); 0051 connect( action, &QAction::triggered, this, &CodeUtilsPlugin::documentDeclaration ); 0052 action->setToolTip(i18nc("@info:tooltip", "Add Doxygen skeleton for declaration under cursor.")); 0053 // i18n: translate title same as the action name 0054 action->setWhatsThis(i18nc("@info:whatthis", 0055 "Adds a basic Doxygen comment skeleton in front of " 0056 "the declaration under the cursor, e.g. with all the " 0057 "parameter of a function." ) ); 0058 action->setIcon( QIcon::fromTheme( QStringLiteral("documentinfo") ) ); 0059 } 0060 0061 void CodeUtilsPlugin::documentDeclaration() 0062 { 0063 View* view = ICore::self()->documentController()->activeTextDocumentView(); 0064 if ( !view ) { 0065 return; 0066 } 0067 0068 DUChainReadLocker lock; 0069 TopDUContext* topCtx = DUChainUtils::standardContextForUrl(view->document()->url()); 0070 if ( !topCtx ) { 0071 return; 0072 } 0073 0074 Declaration* dec = DUChainUtils::declarationInLine( KTextEditor::Cursor( view->cursorPosition() ), 0075 topCtx ); 0076 if ( !dec || dec->isForwardDeclaration() ) { 0077 return; 0078 } 0079 // finally - we found the declaration :) 0080 int line = dec->range().start.line; 0081 Cursor insertPos( line, 0 ); 0082 0083 TemplateRenderer renderer; 0084 renderer.setEmptyLinesPolicy(TemplateRenderer::TrimEmptyLines); 0085 renderer.addVariable(QStringLiteral("brief"), i18n( "..." )); 0086 0087 /* 0088 QString indentation = textDoc->line( insertPos.line() ); 0089 if (!indentation.isEmpty()) { 0090 int lastSpace = 0; 0091 while (indentation.at(lastSpace).isSpace()) { 0092 ++lastSpace; 0093 } 0094 indentation.truncate(lastSpace); 0095 } 0096 */ 0097 0098 if (dec->isFunctionDeclaration()) 0099 { 0100 FunctionDescription description = FunctionDescription(DeclarationPointer(dec)); 0101 renderer.addVariable(QStringLiteral("function"), QVariant::fromValue(description)); 0102 qCDebug(PLUGIN_CODEUTILS) << "Found function" << description.name << "with" << description.arguments.size() << "arguments"; 0103 } 0104 0105 lock.unlock(); 0106 0107 // TODO: Choose the template based on the language 0108 QLatin1String templateName = QLatin1String("doxygen_cpp"); 0109 auto languages = core()->languageController()->languagesForUrl(view->document()->url()); 0110 if (!languages.isEmpty()) 0111 { 0112 QString languageName = languages.first()->name(); 0113 if (languageName == QLatin1String("Php")) 0114 { 0115 templateName = QLatin1String("phpdoc_php"); 0116 } 0117 else if (languageName == QLatin1String("Python")) 0118 { 0119 templateName = QLatin1String("rest_python"); 0120 // Python docstrings appear inside functions and classes, not above them 0121 insertPos = Cursor(line+1, 0); 0122 } 0123 } 0124 0125 const QString fileName = QStandardPaths::locate(QStandardPaths::GenericDataLocation, QLatin1String("kdevcodeutils/templates/") + templateName + QLatin1String(".txt")); 0126 if (fileName.isEmpty()) 0127 { 0128 qCWarning(PLUGIN_CODEUTILS) << "No suitable template found" << fileName; 0129 return; 0130 } 0131 0132 const QString comment = renderer.renderFile(QUrl::fromLocalFile(fileName)); 0133 view->insertTemplate(insertPos, comment); 0134 } 0135 0136 CodeUtilsPlugin::~CodeUtilsPlugin() 0137 { 0138 } 0139 0140 #include "codeutilsplugin.moc" 0141 #include "moc_codeutilsplugin.cpp"