diff --git a/interfaces/iplugin.h b/interfaces/iplugin.h index 7eb3138031..936afd6fb4 100644 --- a/interfaces/iplugin.h +++ b/interfaces/iplugin.h @@ -1,281 +1,281 @@ /* This file is part of the KDE project Copyright 1999-2001 Bernd Gehrmann Copyright 2004,2007 Alexander Dymo Copyright 2006 Adam Treat Copyright 2007 Andreas Pakulat This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_IPLUGIN_H #define KDEVPLATFORM_IPLUGIN_H #include #include #include #include "interfacesexport.h" namespace Sublime { class MainWindow; } /** * This macro adds an extension interface to register with the extension manager * Call this macro for all interfaces your plugin implements in its constructor */ #define KDEV_USE_EXTENSION_INTERFACE(Extension) \ _Pragma("message(\"Using deprecated function: KDEV_USE_EXTENSION_INTERFACE. Just remove the use of it.\")") namespace KDevelop { class ICore; class ConfigPage; class Context; class ContextMenuExtension; struct ProjectConfigOptions; /** * The base class for all KDevelop plugins. * * Plugin is a component which is loaded into KDevelop shell at startup or by * request. Each plugin should have corresponding .desktop file with a * description. The .desktop file template looks like: * @code * [Desktop Entry] * Type=Service * Exec=blubb * Name= * GenericName= * Comment= * Icon= * ServiceTypes=KDevelop/Plugin * X-KDE-Library= * X-KDE-PluginInfo-Name= * X-KDE-PluginInfo-Author= * X-KDE-PluginInfo-Version= * X-KDE-PluginInfo-License= * X-KDE-PluginInfo-Category= * X-KDevelop-Version= * X-KDevelop-Category= * X-KDevelop-Mode=GUI * X-KDevelop-LoadMode= - * X-KDevelop-Language= + * X-KDevelop-Languages= * X-KDevelop-SupportedMimeTypes= * X-KDevelop-Interfaces= * X-KDevelop-IOptional= * X-KDevelop-IRequired= * @endcode * Description of parameters in .desktop file: * - Name is a translatable name of a plugin, it is used in the plugin * selection list (required); * - GenericName is a translatable generic name of a plugin, it should * describe in general what the plugin can do (required); * - Comment is a short description about the plugin (optional); * - Icon is a plugin icon (preferred); * X-KDE-librarythis is the name of the .so file to load for this plugin (required); * - X-KDE-PluginInfo-Name is a non-translatable user-readable plugin * identifier used in KTrader queries (required); * - X-KDE-PluginInfo-Author is a non-translateable name of the plugin * author (optional); * - X-KDE-PluginInfo-Version is version number of the plugin (optional); * - X-KDE-PluginInfo-License is a license (optional). can be: GPL, * LGPL, BSD, Artistic, QPL or Custom. If this property is not set, license is * considered as unknown; * - X-KDE-PluginInfo-Category is used to categorize plugins (optional). can be: * Core, Project Management, Version Control, Utilities, Documentation, * Language Support, Debugging, Other * If this property is not set, "Other" is assumed * - X-KDevelop-Version is the KDevPlatform API version this plugin * works with (required); * - X-KDevelop-Interfaces is a list of extension interfaces that this * plugin implements (optional); * - X-KDevelop-IRequired is a list of extension interfaces that this * plugin depends on (optional); A list entry can also be of the form @c interface@pluginname, * in which case a plugin of the given name is required which implements the interface. * - X-KDevelop-IOptional is a list of extension interfaces that this * plugin will use if they are available (optional); - * - X-KDevelop-Language is the name of the language the plugin provides + * - X-KDevelop-Languages is a list of the names of the languages the plugin provides * support for (optional); * - X-KDevelop-SupportedMimeTypes is a list of mimetypes that the * language-parser in this plugin supports (optional); * - X-KDevelop-Mode is either GUI or NoGUI to indicate whether a plugin can run * with the GUI components loaded or not (required); * - X-KDevelop-Category is a scope of a plugin (see below for * explanation) (required); * - X-KDevelop-LoadMode can be set to AlwaysOn in which case the plugin will * never be unloaded even if requested via the API. (optional); * * Plugin scope can be either: * - Global * - Project * . * Global plugins are plugins which require only the shell to be loaded and do not operate on * the Project interface and/or do not use project wide information.\n * Core plugins are global plugins which offer some important "core" functionality and thus * are not selectable by user in plugin configuration pages.\n * Project plugins require a project to be loaded and are usually loaded/unloaded along with * the project. * If your plugin uses the Project interface and/or operates on project-related * information then this is a project plugin. * * * @sa Core class documentation for information about features available to * plugins from shell applications. */ class KDEVPLATFORMINTERFACES_EXPORT IPlugin: public QObject, public KXMLGUIClient { Q_OBJECT public: /**Constructs a plugin. * @param componentName The component name for this plugin. * @param parent The parent object for the plugin. */ IPlugin(const QString &componentName, QObject *parent); /**Destructs a plugin.*/ ~IPlugin() override; /** * Signal the plugin that it should cleanup since it will be unloaded soon. */ Q_SCRIPTABLE virtual void unload(); /** * Provides access to the ICore implementation */ Q_SCRIPTABLE ICore *core() const; /** * Convenience API to access an interface inherited by this plugin * * @return Instance to the specified interface, or nullptr */ template inline Extension* extension() { return qobject_cast(this); } /** * Ask the plugin for a ContextActionContainer, which contains actions * that will be merged into the context menu. * @param context the context describing where the context menu was requested * @returns a container describing which actions to merge into which context menu part */ virtual ContextMenuExtension contextMenuExtension( KDevelop::Context* context ); /** * Can create a new KXMLGUIClient, and set it up correctly with all the plugins per-window GUI actions. * * The caller owns the created object, including all contained actions. The object is destroyed as soon as * the mainwindow is closed. * * The default implementation calls the convenience function @ref createActionsForMainWindow and uses it to fill a custom KXMLGUIClient. * * Only override this version if you need more specific features of KXMLGUIClient, or other special per-window handling. * * @param window The main window the actions are created for */ virtual KXMLGUIClient* createGUIForMainWindow( Sublime::MainWindow* window ); /** * This function allows allows setting up plugin actions conveniently. Unless createGUIForMainWindow was overridden, * this is called for each new mainwindow, and the plugin should add its actions to @p actions, and write its KXMLGui xml file * into @p xmlFile. * * @param window The main window the actions are created for * @param xmlFile Change this to the xml file that needed for merging the actions into the GUI * @param actions Add your actions here. A new set of actions has to be created for each mainwindow. */ virtual void createActionsForMainWindow( Sublime::MainWindow* window, QString& xmlFile, KActionCollection& actions ); /** * This function is necessary because there is no proper way to signal errors from plugin constructor. * @returns True if the plugin has encountered an error (and therefore has an error description), * false otherwise. */ bool hasError() const; /** * Description of the last encountered error, of an empty string if none. */ QString errorDescription() const; /** * Set a @p description of the errror encountered. An empty error * description implies no error in the plugin. */ void setErrorDescription(QString const& description); /** * Get the global config page with the \p number, config pages from 0 to * configPages()-1 are available if configPages() > 0. * * @param number index of config page * @param parent parent widget for config page * @return newly created config page or NULL, if the number is out of bounds, default implementation returns NULL. * This config page should inherit from ProjectConfigPage, but it is not a strict requirement. * The default implementation returns @c nullptr. * @see perProjectConfigPages(), ProjectConfigPage */ virtual ConfigPage* configPage(int number, QWidget *parent); /** * Get the number of available config pages for global settings. * @return number of global config pages. The default implementation returns zero. * @see configPage() */ virtual int configPages() const; /** * Get the number of available config pages for per project settings. * @return number of per project config pages. The default implementation returns zero. * @see perProjectConfigPage() */ virtual int perProjectConfigPages() const; /** * Get the per project config page with the \p number, config pages from 0 to * perProjectConfigPages()-1 are available if perProjectConfigPages() > 0. * * @param number index of config page * @param options The options used to initialize the ProjectConfigPage * @param parent parent widget for config page * @return newly created config page or NULL, if the number is out of bounds, default implementation returns NULL. * This config page should inherit from ProjectConfigPage, but it is not a strict requirement. * The default implementation returns @c nullptr. * @see perProjectConfigPages(), ProjectConfigPage */ virtual ConfigPage* perProjectConfigPage(int number, const KDevelop::ProjectConfigOptions& options, QWidget* parent); protected: /** * Initialize the XML GUI State. */ virtual void initializeGuiState(); private: friend class IPluginPrivate; class IPluginPrivate* const d; }; } #endif diff --git a/interfaces/kdevelopplugin.desktop b/interfaces/kdevelopplugin.desktop index f82cfaa4a2..bb02c3bfff 100644 --- a/interfaces/kdevelopplugin.desktop +++ b/interfaces/kdevelopplugin.desktop @@ -1,104 +1,105 @@ [Desktop Entry] Type=ServiceType X-KDE-ServiceType=KDevelop/Plugin X-KDE-Derived=KPluginInfo Name=KDevelop Plugin Name[ast]=Complementu de KDevelop Name[bg]=KDevelop приставка Name[bs]=KDevelop dodatak Name[ca]=Connector KDevelop Name[ca@valencia]=Connector KDevelop Name[cs]=Modul KDevelop Name[da]=KDevelop-plugin Name[de]=KDevelop-Modul Name[el]=Πρόσθετο του KDevelop Name[en_GB]=KDevelop Plugin Name[es]=Complemento de KDevelop Name[et]=KDevelopi plugin Name[fi]=KDevelop-liitännäinen Name[fr]=Module externe pour KDevelop Name[ga]=Breiseán KDevelop Name[gl]=Complemento para KDevelop Name[hr]=KDevelop priključak Name[hu]=KDevelop bővítmény Name[it]=Estensione KDevelop Name[ja]=KDevelop プラグイン Name[kk]=KDevelop плагині Name[lv]=KDevelop spraudnis Name[nb]=KDevelop programtillegg Name[nds]=KDevelop-Moduul Name[nl]=Plugin van KDevelop Name[pa]=KDevelop ਪਲੱਗਇਨ Name[pl]=Wtyczka do KDevelopa Name[pt]='Plugin' do KDevelop Name[pt_BR]=Extensão do KDevelop Name[ro]=Modul KDevelop Name[ru]=Расширение KDevelop Name[sk]=Plugin KDevelop Name[sl]=Vstavek za KDevelop Name[sv]=KDevelop-insticksprogram Name[tr]=KDevelop Eklentisi Name[ug]=KDevelop قىستۇرمىسى Name[uk]=Додаток KDevelop Name[x-test]=xxKDevelop Pluginxx Name[zh_CN]=KDevelop 插件 Name[zh_TW]=KDevelop 外掛程式 # mandatory, versioning - prevent DLL hell [PropertyDef::X-KDevelop-Version] Type=int # optional, determines whether a plugin is loaded only after # a project is opened, or is a global plugin. # If it is not set, the plugin can only be loaded by the # user or via requesting one of its dependencies # allowed values: Global, Project [PropertyDef::X-KDevelop-Category] Type=QString # mandatory, GUI-Operation Mode, determines whether a plugin # can work without having a mainwindow/partcontroller # running # allowed values: GUI, NoGUI [PropertyDef::X-KDevelop-Mode] Type=QString # optional, Interfaces that a plugin implements # usually values start with org.kdevelop [PropertyDef::X-KDevelop-Interfaces] Type=QStringList # optional, interfaces that this plugin depends # on [PropertyDef::X-KDevelop-IRequired] Type=QStringList # optional, interfaces that this plugin can use, # but the plugin still works if the interfaces are # not available. [PropertyDef::X-KDevelop-IOptional] Type=QStringList # optional, mimetypes supported by a language plugin [PropertyDef::X-KDevelop-SupportedMimeTypes] Type=QStringList -# optional, language supported by a language plugin -[PropertyDef::X-KDevelop-Language] -Type=QString +# optional, languages supported by a language plugin +# Example language names: "C", "C++", "Objective-C", "CMake" +[PropertyDef::X-KDevelop-Languages] +Type=QStringList # optional, defines whether the plugin can be disabled # by the user. Possible values are "AlwaysOn" and "UserSelectable". # If the property is missing then UserSelectable is assumed [PropertyDef::X-KDevelop-LoadMode] Type=QString # optional, list of filters for "projectfiles" for the project plugin # For example: Makefile,Makefile.* for Makefile's [PropertyDef::X-KDevelop-ProjectFilesFilter] Type=QStringList # optional, description for the projectfiles filter [PropertyDef::X-KDevelop-ProjectFilesFilterDescription] Type=QString diff --git a/language/codegen/sourcefiletemplate.h b/language/codegen/sourcefiletemplate.h index abbcc22cad..9c8d0438a0 100644 --- a/language/codegen/sourcefiletemplate.h +++ b/language/codegen/sourcefiletemplate.h @@ -1,316 +1,316 @@ /* * This file is part of KDevelop * Copyright 2012 Miha Čančula * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KDEVPLATFORM_SOURCEFILETEMPLATE_H #define KDEVPLATFORM_SOURCEFILETEMPLATE_H #include #include #include #include class QStringList; class KArchiveDirectory; namespace KDevelop { class TemplateRenderer; /** * Represents a source file template archive * * @section TemplateStructure Template Archive Structure * * Source file templates in KDevPlatform are archive files. * The archive must contain at least one .desktop file with the template's description. * If multiple such files are present, the one with the same base name as the archive itself will be used. * * The description file must contain a @c [General] section with the following keys: * @li @c Name - The user-visible name of this template * @li @c Comment - A short user-visible comment * @li @c Category - The category of this template. It can be nested, in which case levels are separated * with forward slashes. The top-level category is usually the language followed by the framework. * @li @c Type An optional type, which then adds some more default wizard pages and configuration. * Currently supported are @c Class and @c Test. - * @li @c Language The @c X-KDevelop-Language id of a language plugin which is then asked for a custom - * createClassHelper. + * @li @c Language The @c X-KDevelop-Languages compatible id of a language plugin which is then asked + * for a custom @ref ICreateClassHelper object. * @li @c Files - List of files generated by this template. These are not actual file names, but names * of config groups describing those files. * @li @c OptionsFile (optional) - If the template uses custom configuration options, specify a path to * the options file here. @ref CustomOptions * * For each file name in the @c Files array, TemplateClassGenerator expects a section with the same name. * this section should contain three keys: * @li @c Name - User-visible name for this file. This will be show the user in the dialog and can be translated. * @li @c File - The input file name in the template archive. The template for this file will be read from here. * @li @c OutputFile - The suggested output file name. This will be renderer as a template, so it can contain variables. * * An example template description is below. It shows all features described above. * * @code * [General] * Name=Example * Comment=Example description for a C++ Class * Category=C++/Basic * Type=Class * Language=C++ * Options=options.kcfg * Files=Header,Implementation * * [Header] * Name=Header * File=class.h * OutputFile={{ name }}.h * * [Implementation] * Name=Implementation * File=class.cpp * OutputFile={{ name }}.cpp * @endcode * * @section CustomOptions * * Templates can expose additional configurations options. * This is done through a file with the same syntax and .kcfg files used by KConfig XT. * The name of this file is specified with the @c OptionsFile key in the [General] section of the description file. * * @note * The options are not parsed by TemplateClassGenerator. * Instead, hasCustomOptions() returns true if the template specifies a custom options file, * and customOptions() returns the full text of that file. * The parsing is done by TemplateOptionsPage. * * The file can (and should) provide a type, name, label and default value for each configuration option. * So far, only variables with types String, Int and Bool are recognized. * Label is the user-visible string that will be shown next to the input field. * The default value will be rendered as a template, so it can contain variables. * * After the user configures the options, they will be available to the template as context variables. * The variable name will match the option name, and its value will be the one set by the user. * * An example options.kcfg file for a class template is included below. * * @code * * * * * * * {{ name }}Private * * * * d * * * * @endcode * * In this example, if the class name is Example, the default value for the private class name will be ExamplePrivate. * After the user accepts the option values, the template will access them through the @c private_class_name * and @c private_member_name variables. * * For more information regarding the XML file format, refer to the KConfig XT documentation. */ class KDEVPLATFORMLANGUAGE_EXPORT SourceFileTemplate { public: /** * Describes a single output file in this template */ struct OutputFile { /** * A unique identifier, equal to the list element in the @c OutputFiles entry */ QString identifier; /** * The name of the input file within the archive, equal to the @c File entry */ QString fileName; /** * User-visible label, equal to the @c Name entry in this file's group in the template description file */ QString label; /** * The default output file name, equal to the @c OutputFile entry * * @note The output name can contain template variables, so make sure to pass it through * TemplateRenderer::render before using it or showing it to the user. */ QString outputName; }; /** * Describes one configuration option */ struct ConfigOption { /** * The type of this option. * * Currently supported are Int, String and Bool */ QString type; /** * A unique identifier for this option */ QString name; /** * User-visible label */ QString label; /** * A context description for the option, shown to the user as a tooltip */ QString context; /** * The default value of this option */ QVariant value; /** * The maximum value of this entry, as a string * * This is applicable only to integers */ QString maxValue; /** * The minimum value of this entry, as a string * * This is applicable only to integers */ QString minValue; }; /** * Creates a SourceFileTemplate representing the template archive with * description file @p templateDescription. * * @param templateDescription template description file, used to find the * archive and read information */ explicit SourceFileTemplate(const QString& templateDescription); /** * Copy constructor * * Creates a SourceFileTemplate representing the same template archive as @p other. * This new objects shares no data with the @p other, so they can be read and deleted independently. * * @param other the template to copy */ SourceFileTemplate(const SourceFileTemplate& other); /** * Creates an invalid SourceFileTemplate */ SourceFileTemplate(); /** * Destroys this SourceFileTemplate */ ~SourceFileTemplate(); SourceFileTemplate& operator=(const SourceFileTemplate& other); void setTemplateDescription(const QString& templateDescription); /** * Returns true if this SourceFileTemplate represents an actual template archive, and false otherwise */ bool isValid() const; /** * The name of this template, corresponds to the @c Name entry in the description file */ QString name() const; /** * The top-level directory in the template archive * * @sa KArchive::directory() */ const KArchiveDirectory* directory() const; /** * The list of all output files in this template */ QList outputFiles() const; /** * @return true if the template uses any custom options, false otherwise **/ bool hasCustomOptions() const; /** * Return the custom options this template exposes **/ QHash > customOptions(TemplateRenderer* renderer) const; /** * @return The type of this template. * * This can be any string, but TemplateClassAssistant only supports @c Class and @c Test so far. */ QString type() const; /** - * aA optional @c X-KDevelop-Language by which a language plugin for this template can be found. + * An optional @c X-KDevelop-Languages compatible id by which a language plugin for this template can be found. */ QString languageName() const; /** * The category of this template. */ QStringList category() const; /** * @return the list of base classes specified by this template. * If this is not a class template, or if it specifies no default base classes, an empty list is returned. * * Each element is the full inheritance description, such as "public QObject". */ QStringList defaultBaseClasses() const; /** * Add an additional search location where the code will look for archives * * @param location Absolute path to a directory with archives. Has to end with a '/' */ void addAdditionalSearchLocation(const QString& location); private: class SourceFileTemplatePrivate* const d; }; } Q_DECLARE_TYPEINFO(KDevelop::SourceFileTemplate::OutputFile, Q_MOVABLE_TYPE); Q_DECLARE_TYPEINFO(KDevelop::SourceFileTemplate::ConfigOption, Q_MOVABLE_TYPE); #endif // KDEVPLATFORM_SOURCEFILETEMPLATE_H diff --git a/plugins/patchreview/kdevpatchreview.json b/plugins/patchreview/kdevpatchreview.json index 722a2c1efd..090ff53c8a 100644 --- a/plugins/patchreview/kdevpatchreview.json +++ b/plugins/patchreview/kdevpatchreview.json @@ -1,81 +1,81 @@ { "KPlugin": { "Authors": [ { "Name": "David Nolden", "Name[x-test]": "xxDavid Noldenxx" } ], "Category": "Utilities", "Description": "This plugin allows reviewing patches directly in the editor.", "Description[ar]": "تسمح هذه الملحقة بمراجعة الرّقعة مباشرةً في المحرّر.", "Description[ca@valencia]": "Este connector permet revisar pedaços directament en l'editor.", "Description[ca]": "Aquest connector permet revisar pedaços directament en l'editor.", "Description[de]": "Dieses Modul ermöglicht es, Patches direkt im Editor durchzusehen.", "Description[es]": "Este complemento permite la revisión de parches directamente en el editor.", "Description[fi]": "Tämä liitännäinen salli korjausten katselmoinnin suoraan editorissa.", "Description[fr]": "Ce module permet de passer en revue des correctifs directement dans l'éditeur.", "Description[gl]": "Este complemento permite revisar parches directamente no editor.", "Description[it]": "Questa estensione permette di rivedere le patch direttamente nell'editor.", "Description[nl]": "Deze plugin laat patches herzien direct in de editor.", "Description[pl]": "Ta wtyczka pozwala na przeglądanie poprawek bezpośrednio w edytorze.", "Description[pt]": "Este 'plugin' permite a revisão das modificações directamente no editor.", "Description[pt_BR]": "Este plugin permite obter as modificações diretamente no editor.", "Description[sk]": "Tento plugin umožňuje zhodnotenie záplat priamo v editore.", "Description[sl]": "Vstavek omogoča pregled popravkov neposredno v urejevalniku.", "Description[sv]": "Insticksprogrammet gör det möjligt att direkt granska programfixar i editorn.", "Description[tr]": "Bu eklenti yamaların doğrudan düzenleyici içerisinde gözden geçirilmesini sağlar.", "Description[uk]": "За допомогою цього додатка ви зможете рецензувати латки безпосередньо у редакторі.", "Description[x-test]": "xxThis plugin allows reviewing patches directly in the editor.xx", "Description[zh_CN]": "此插件允许在编辑器中直接审阅补丁。", "Icon": "applications-engineering", "Id": "kdevpatchreview", "License": "GPL", "Name": "Patch Review", "Name[ar]": "مراجعة الرّقع", "Name[bg]": "Преглед на кръпки", "Name[bs]": "Pregled zakrpa", "Name[ca@valencia]": "Revisió del pedaç", "Name[ca]": "Revisió del pedaç", "Name[da]": "Gennemgang af rettelser", "Name[de]": "Patch-Durchsicht", "Name[el]": "Επιθεώρηση διορθώσεων", "Name[es]": "Revisión de parches", "Name[et]": "Paikade ülevaatamine", "Name[fi]": "Korjauksen katselmointi", "Name[fr]": "Revue de correction", "Name[gl]": "Revisor de parches", "Name[hu]": "Javítócsomag átnézés", "Name[it]": "Revisione patch", "Name[kk]": "Жамау шолуы", "Name[nb]": "Lappegjennomgang", "Name[nds]": "Plasternakiek", "Name[nl]": "Patchoverzicht", "Name[pl]": "Przeglądanie poprawek", "Name[pt]": "Revisão da Modificação", "Name[pt_BR]": "Revisão da Modificação", "Name[ru]": "Рецензирование патчей", "Name[sk]": "Zhodnotenie záplaty", "Name[sl]": "Pregled popravkov", "Name[sv]": "Granska programfixar", "Name[tr]": "Yama Gözden Geçirmesi", "Name[ug]": "ياماق باھالاش", "Name[uk]": "Рецензування латки", "Name[x-test]": "xxPatch Reviewxx", "Name[zh_CN]": "补丁审阅", "Name[zh_TW]": "修補檢視", "ServiceTypes": [ "KDevelop/Plugin" ] }, "X-KDevelop-Interfaces": [ "org.kdevelop.IPatchReview", "ILanguageSupport" ], - "X-KDevelop-Language": "Diff", + "X-KDevelop-Languages": ["Diff"], "X-KDevelop-Mode": "GUI", "X-KDevelop-SupportedMimeTypes": [ "text/x-diff", "text/x-patch" ] } diff --git a/shell/languagecontroller.cpp b/shell/languagecontroller.cpp index d58cdd85f1..4ad93bed8f 100644 --- a/shell/languagecontroller.cpp +++ b/shell/languagecontroller.cpp @@ -1,363 +1,381 @@ /*************************************************************************** * Copyright 2006 Adam Treat * * Copyright 2007 Alexander Dymo * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU Library General Public License as * * published by the Free Software Foundation; either version 2 of the * * License, or (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License for more details. * * * * You should have received a copy of the GNU Library General Public * * License along with this program; if not, write to the * * Free Software Foundation, Inc., * * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * ***************************************************************************/ #include "languagecontroller.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "problemmodelset.h" #include "core.h" #include "settings/languagepreferences.h" #include "completionsettings.h" #include "debug.h" namespace { QString KEY_SupportedMimeTypes() { return QStringLiteral("X-KDevelop-SupportedMimeTypes"); } QString KEY_ILanguageSupport() { return QStringLiteral("ILanguageSupport"); } } #if QT_VERSION < 0x050600 inline uint qHash(const QMimeType& mime, uint seed = 0) { return qHash(mime.name(), seed); } #endif namespace KDevelop { typedef QHash LanguageHash; typedef QHash > LanguageCache; struct LanguageControllerPrivate { LanguageControllerPrivate(LanguageController *controller) : dataMutex(QMutex::Recursive) , backgroundParser(new BackgroundParser(controller)) , staticAssistantsManager(nullptr) , m_cleanedUp(false) , problemModelSet(new ProblemModelSet(controller)) , m_controller(controller) {} void documentActivated(KDevelop::IDocument *document) { QUrl url = document->url(); if (!url.isValid()) { return; } activeLanguages.clear(); QList languages = m_controller->languagesForUrl(url); foreach (const auto lang, languages) { activeLanguages << lang; } } QList activeLanguages; mutable QMutex dataMutex; LanguageHash languages; //Maps language-names to languages LanguageCache languageCache; //Maps mimetype-names to languages typedef QMultiHash MimeTypeCache; MimeTypeCache mimeTypeCache; //Maps mimetypes to languages BackgroundParser *backgroundParser; StaticAssistantsManager* staticAssistantsManager; bool m_cleanedUp; void addLanguageSupport(ILanguageSupport* support, const QStringList& mimetypes); void addLanguageSupport(ILanguageSupport* support); ProblemModelSet *problemModelSet; private: LanguageController *m_controller; }; void LanguageControllerPrivate::addLanguageSupport(ILanguageSupport* languageSupport, const QStringList& mimetypes) { Q_ASSERT(!languages.contains(languageSupport->name())); languages.insert(languageSupport->name(), languageSupport); foreach(const QString& mimeTypeName, mimetypes) { qCDebug(SHELL) << "adding supported mimetype:" << mimeTypeName << "language:" << languageSupport->name(); languageCache[mimeTypeName] << languageSupport; QMimeType mime = QMimeDatabase().mimeTypeForName(mimeTypeName); if (mime.isValid()) { mimeTypeCache.insert(mime, languageSupport); } else { qWarning() << "could not create mime-type" << mimeTypeName; } } } void LanguageControllerPrivate::addLanguageSupport(KDevelop::ILanguageSupport* languageSupport) { if (languages.contains(languageSupport->name())) return; Q_ASSERT(dynamic_cast(languageSupport)); KPluginMetaData info = Core::self()->pluginController()->pluginInfo(dynamic_cast(languageSupport)); QStringList mimetypes = KPluginMetaData::readStringList(info.rawData(), KEY_SupportedMimeTypes()); addLanguageSupport(languageSupport, mimetypes); } LanguageController::LanguageController(QObject *parent) : ILanguageController(parent) { setObjectName(QStringLiteral("LanguageController")); d = new LanguageControllerPrivate(this); } LanguageController::~LanguageController() { delete d; } void LanguageController::initialize() { d->backgroundParser->loadSettings(); d->staticAssistantsManager = new StaticAssistantsManager(this); // make sure the DUChain is setup before we try to access it from different threads at the same time DUChain::self(); connect(Core::self()->documentController(), &IDocumentController::documentActivated, this, [&] (IDocument* document) { d->documentActivated(document); }); } void LanguageController::cleanup() { QMutexLocker lock(&d->dataMutex); d->m_cleanedUp = true; } QList LanguageController::activeLanguages() { QMutexLocker lock(&d->dataMutex); return d->activeLanguages; } StaticAssistantsManager* LanguageController::staticAssistantsManager() const { return d->staticAssistantsManager; } ICompletionSettings *LanguageController::completionSettings() const { return &CompletionSettings::self(); } ProblemModelSet* LanguageController::problemModelSet() const { return d->problemModelSet; } QList LanguageController::loadedLanguages() const { QMutexLocker lock(&d->dataMutex); QList ret; if(d->m_cleanedUp) return ret; foreach(ILanguageSupport* lang, d->languages) ret << lang; return ret; } ILanguageSupport* LanguageController::language(const QString &name) const { QMutexLocker lock(&d->dataMutex); if(d->m_cleanedUp) return nullptr; if(d->languages.contains(name)) return d->languages[name]; - QVariantMap constraints; - constraints.insert(QStringLiteral("X-KDevelop-Language"), name); - QList supports = Core::self()->pluginController()->allPluginsForExtension(KEY_ILanguageSupport(), constraints); + // temporary support for deprecated-in-5.1 "X-KDevelop-Language" as fallback + // remove in later version + const QString keys[2] = { + QStringLiteral("X-KDevelop-Languages"), + QStringLiteral("X-KDevelop-Language") + }; + QList supports; + for (const auto& key : keys) { + QVariantMap constraints; + constraints.insert(key, name); + supports = Core::self()->pluginController()->allPluginsForExtension(KEY_ILanguageSupport(), constraints); + if (key == keys[1]) { + for (auto support : supports) { + qWarning() << "Plugin" << Core::self()->pluginController()->pluginInfo(support).name() << " has deprecated (since 5.1) metadata key \"X-KDevelop-Language\", needs porting to: \"X-KDevelop-Languages\": ["<extension(); if(languageSupport) { d->addLanguageSupport(languageSupport); return languageSupport; } } return nullptr; } bool isNumeric(const QString& str) { int len = str.length(); if(len == 0) return false; for(int a = 0; a < len; ++a) if(!str[a].isNumber()) return false; return true; } QList LanguageController::languagesForUrl(const QUrl &url) { QMutexLocker lock(&d->dataMutex); QList languages; if(d->m_cleanedUp) return languages; const QString fileName = url.fileName(); ///TODO: cache regexp or simple string pattern for endsWith matching QRegExp exp("", Qt::CaseInsensitive, QRegExp::Wildcard); ///non-crashy part: Use the mime-types of known languages for(LanguageControllerPrivate::MimeTypeCache::const_iterator it = d->mimeTypeCache.constBegin(); it != d->mimeTypeCache.constEnd(); ++it) { foreach(const QString& pattern, it.key().globPatterns()) { if(pattern.startsWith('*')) { const QStringRef subPattern = pattern.midRef(1); if (!subPattern.contains('*')) { //optimize: we can skip the expensive QRegExp in this case //and do a simple string compare (much faster) if (fileName.endsWith(subPattern)) { languages << *it; } continue; } } exp.setPattern(pattern); if(int position = exp.indexIn(fileName)) { if(position != -1 && exp.matchedLength() + position == fileName.length()) languages << *it; } } } if(!languages.isEmpty()) return languages; //Never use findByUrl from within a background thread, and never load a language support //from within the backgruond thread. Both is unsafe, and can lead to crashes if(!languages.isEmpty() || QThread::currentThread() != thread()) return languages; QMimeType mimeType; if (url.isLocalFile()) { mimeType = QMimeDatabase().mimeTypeForFile(url.toLocalFile()); } else { // remote file, only look at the extension mimeType = QMimeDatabase().mimeTypeForUrl(url); } if (mimeType.isDefault()) { // ask the document controller about a more concrete mimetype IDocument* doc = ICore::self()->documentController()->documentForUrl(url); if (doc) { mimeType = doc->mimeType(); } } languages = languagesForMimetype(mimeType.name()); return languages; } QList LanguageController::languagesForMimetype(const QString& mimetype) { QMutexLocker lock(&d->dataMutex); QList languages; LanguageCache::ConstIterator it = d->languageCache.constFind(mimetype); if (it != d->languageCache.constEnd()) { languages = it.value(); } else { QVariantMap constraints; constraints.insert(KEY_SupportedMimeTypes(), mimetype); QList supports = Core::self()->pluginController()->allPluginsForExtension(KEY_ILanguageSupport(), constraints); if (supports.isEmpty()) { qCDebug(SHELL) << "no languages for mimetype:" << mimetype; d->languageCache.insert(mimetype, QList()); } else { foreach (IPlugin *support, supports) { ILanguageSupport* languageSupport = support->extension(); qCDebug(SHELL) << "language-support:" << languageSupport; if(languageSupport) { d->addLanguageSupport(languageSupport); languages << languageSupport; } } } } return languages; } QList LanguageController::mimetypesForLanguageName(const QString& languageName) { QMutexLocker lock(&d->dataMutex); QList mimetypes; for (LanguageCache::ConstIterator iter = d->languageCache.constBegin(); iter != d->languageCache.constEnd(); ++iter) { foreach (ILanguageSupport* language, iter.value()) { if (language->name() == languageName) { mimetypes << iter.key(); break; } } } return mimetypes; } BackgroundParser *LanguageController::backgroundParser() const { return d->backgroundParser; } void LanguageController::addLanguageSupport(ILanguageSupport* languageSupport, const QStringList& mimetypes) { d->addLanguageSupport(languageSupport, mimetypes); } } #include "moc_languagecontroller.cpp"