File indexing completed on 2024-05-05 04:40:04

0001 /*
0002     SPDX-FileCopyrightText: 2010 Yannick Motta <yannick.motta@gmail.com>
0003     SPDX-FileCopyrightText: 2010 Benjamin Port <port.benjamin@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "manpageplugin.h"
0009 
0010 #include "manpagedocumentation.h"
0011 #include "manpagemodel.h"
0012 
0013 #include <interfaces/idocumentation.h>
0014 #include <interfaces/icore.h>
0015 #include <interfaces/iprojectcontroller.h>
0016 
0017 #include <language/duchain/duchain.h>
0018 #include <language/duchain/declaration.h>
0019 #include <language/duchain/duchainlock.h>
0020 #include <serialization/indexedstring.h>
0021 #include <language/duchain/parsingenvironment.h>
0022 
0023 #include <language/duchain/classdeclaration.h>
0024 #include <language/duchain/functiondeclaration.h>
0025 #include <language/duchain/classmemberdeclaration.h>
0026 #include <language/duchain/classfunctiondeclaration.h>
0027 
0028 #include <KPluginFactory>
0029 
0030 #include <QFile>
0031 #include <QStringListModel>
0032 
0033 
0034 using namespace KDevelop;
0035 
0036 K_PLUGIN_FACTORY_WITH_JSON(ManPageFactory, "kdevmanpage.json", registerPlugin<ManPagePlugin>(); )
0037 
0038 ManPagePlugin::ManPagePlugin(QObject* parent, const QVariantList& args)
0039     : IPlugin(QStringLiteral("kdevmanpage"), parent)
0040 {
0041     Q_UNUSED(args);
0042     ManPageDocumentation::s_provider = this;
0043     m_model = new ManPageModel(this);
0044 }
0045 
0046 ManPagePlugin::~ManPagePlugin()
0047 {
0048     delete m_model;
0049 }
0050 
0051 QString ManPagePlugin::name() const
0052 {
0053     return i18n("Man Page");
0054 }
0055 
0056 QIcon ManPagePlugin::icon() const
0057 {
0058     return QIcon::fromTheme(QStringLiteral("application-x-troff-man"));
0059 }
0060 
0061 ManPageModel* ManPagePlugin::model() const{
0062     return m_model;
0063 }
0064 
0065 IDocumentation::Ptr ManPagePlugin::documentationForDeclaration( Declaration* dec ) const
0066 {
0067     Q_ASSERT(dec);
0068     Q_ASSERT(dec->topContext());
0069     Q_ASSERT(dec->topContext()->parsingEnvironmentFile());
0070 
0071     static const IndexedString cppLanguage("C++"); // TODO remove because of new clang parser?
0072     static const IndexedString clangLanguage("Clang");
0073     const IndexedString declarationLanguage(dec->topContext()->parsingEnvironmentFile()->language());
0074     if (declarationLanguage != cppLanguage && declarationLanguage != clangLanguage)
0075         return {};
0076 
0077     // Don't show man-page documentation for files that are part of our project
0078     if (core()->projectController()->findProjectForUrl(dec->topContext()->url().toUrl()))
0079         return {};
0080 
0081     // Don't show man-page documentation for files that are not in /usr/include, because then we
0082     // most probably will be confusing the global function-name with a local one
0083     if (!dec->topContext()->url().str().startsWith(QLatin1String("/usr/")))
0084         return {};
0085 
0086     ///@todo Do more verification to make sure that we're showing the correct documentation for the declaration
0087 
0088     QString identifier;
0089     IDocumentation::Ptr result;
0090 
0091     // First, try to find help for qualified identifier like 'std::vector'
0092     {
0093         DUChainReadLocker lock;
0094         identifier = dec->qualifiedIdentifier().toString(RemoveTemplateInformation);
0095     }
0096 
0097     result = documentationForIdentifier(identifier);
0098     if (result.data())
0099         return result;
0100 
0101     // Second, try to find help for simple identifier like 'sin'
0102     {
0103         DUChainReadLocker lock;
0104         identifier = dec->identifier().toString(RemoveTemplateInformation);
0105     }
0106 
0107     result = documentationForIdentifier(identifier);
0108     if (result.data())
0109         return result;
0110 
0111     return {};
0112 }
0113 
0114 KDevelop::IDocumentation::Ptr ManPagePlugin::documentationForIdentifier(const QString& identifier) const
0115 {
0116     if (!m_model->containsIdentifier(identifier))
0117         return KDevelop::IDocumentation::Ptr(nullptr);
0118 
0119     if (m_model->identifierInSection(identifier, QStringLiteral("3")))
0120         return IDocumentation::Ptr(new ManPageDocumentation(identifier, QUrl(QLatin1String("man:(3)/") + identifier)));
0121 
0122     if (m_model->identifierInSection(identifier, QStringLiteral("2")))
0123         return IDocumentation::Ptr(new ManPageDocumentation(identifier, QUrl(QLatin1String("man:(2)/") + identifier)));
0124 
0125     return IDocumentation::Ptr(new ManPageDocumentation(identifier, QUrl(QLatin1String("man:/") + identifier)));
0126 }
0127 
0128 KDevelop::IDocumentation::Ptr ManPagePlugin::documentation(const QUrl& url) const
0129 {
0130     if (url.toString().startsWith(QLatin1String("man"))) {
0131         IDocumentation::Ptr newDoc(new ManPageDocumentation(url.path(), url));
0132         return newDoc;
0133     }
0134     return {};
0135 }
0136 
0137 QAbstractItemModel* ManPagePlugin::indexModel() const
0138 {
0139     return m_model->indexList();
0140 }
0141 
0142 IDocumentation::Ptr ManPagePlugin::documentationForIndex(const QModelIndex& index) const
0143 {
0144     QString name = index.data().toString();
0145     return IDocumentation::Ptr(new ManPageDocumentation(name, QUrl(QLatin1String("man:")+name)));
0146 }
0147 
0148 IDocumentation::Ptr ManPagePlugin::homePage() const
0149 {
0150     return IDocumentation::Ptr(new ManPageHomeDocumentation);
0151 }
0152 
0153 #include "manpageplugin.moc"
0154 #include "moc_manpageplugin.cpp"