Warning, file /kdevelop/kdevelop/plugins/astyle/astyle_plugin.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 /*
0002     SPDX-FileCopyrightText: 2008 Cédric Pasteur <cedric.pasteur@free.fr>
0003     SPDX-FileCopyrightText: 2001 Matthias Hölzer-Klüpfel <mhk@caldera.de>
0004 
0005     SPDX-License-Identifier: GPL-2.0-or-later
0006 */
0007 
0008 #include "astyle_plugin.h"
0009 
0010 #include <KPluginFactory>
0011 
0012 #include "astyle_formatter.h"
0013 #include "astyle_stringiterator.h"
0014 #include "astyle_preferences.h"
0015 #include <KLocalizedString>
0016 
0017 #include <QMimeType>
0018 #include <QUrl>
0019 
0020 namespace {
0021 
0022 QString formattingCppSample()
0023 {
0024     return QStringLiteral(
0025         "void func(){\n"
0026         "\tif(isFoo(a,b))\n"
0027         "\tbar(a,b);\n"
0028         "if(isFoo)\n"
0029         "\ta=bar((b-c)*a,*d--);\n"
0030         "if(  isFoo( a,b ) )\n"
0031         "\tbar(a, b);\n"
0032         "if (isFoo) {isFoo=false;cat << isFoo <<endl;}\n"
0033         "if(isFoo)DoBar();if (isFoo){\n"
0034         "\tbar();\n"
0035         "}\n"
0036         "\telse if(isBar()){\n"
0037         "\tannotherBar();\n"
0038         "}\n"
0039         "int var = 1;\n"
0040         "int *ptr = &var;\n"
0041         "int& ref = i;\n"
0042         "\n"
0043         "QList<int>::const_iterator it = list.begin();\n"
0044         "}\n"
0045         "namespace A {\n"
0046         "namespace B {\n"
0047         "class someClass {\n"
0048         "void foo() {\n"
0049         "  if (true) {\n"
0050         "    func();\n"
0051         "  } else {\n"
0052         "    // bla\n"
0053         "  }\n"
0054         "}\n"
0055         "};\n"
0056         "}\n"
0057         "}\n");
0058 }
0059 
0060 QString formattingObjCSample()
0061 {
0062     return QStringLiteral(
0063         "void func(){\n"
0064         "\tif(isFoo(a,b))\n"
0065         "\tbar(a,b);\n"
0066         "if(isFoo)\n"
0067         "\ta=bar((b-c)*a,*d--);\n"
0068         "if(  isFoo( a,b ) )\n"
0069         "\tbar(a, b);\n"
0070         "if (isFoo) {isFoo=false;cat << isFoo <<endl;}\n"
0071         "if(isFoo)DoBar();if (isFoo){\n"
0072         "\tbar();\n"
0073         "}\n"
0074         "\telse if(isBar()){\n"
0075         "\tannotherBar();\n"
0076         "}\n"
0077         "int var = 1;\n"
0078         "int *ptr = &var;\n"
0079         "\n"
0080         "}\n"
0081         "@implementation someClass \n"
0082         "+ (someClass*) someClassWithFoo:(int)foo\n"
0083         "{\n"
0084         "  someClass *this;\n"
0085         "  if (foo) {\n"
0086         "    this = [[someClass alloc] initWith:foo];\n"
0087         "  } else {\n"
0088         "    // bla\n"
0089         "  }\n"
0090         "  return self;\n"
0091         "}\n"
0092         "@end\n");
0093 }
0094 
0095 QString indentingCppSample()
0096 {
0097     return QStringLiteral(
0098         "#define foobar(A)\\\n"
0099         "{Foo();Bar();}\n"
0100         "#define anotherFoo(B)\\\n"
0101         "return Bar()\n"
0102         "\n"
0103         "namespace Bar\n"
0104         "{\n"
0105         "class Foo\n"
0106         "{public:\n"
0107         "Foo();\n"
0108         "virtual ~Foo();\n"
0109         "};\n"
0110         "void bar(int foo)\n"
0111         "{\n"
0112         "switch (foo)\n"
0113         "{\n"
0114         "case 1:\n"
0115         "a+=1;\n"
0116         "break;\n"
0117         "case 2:\n"
0118         "{\n"
0119         "a += 2;\n"
0120         " break;\n"
0121         "}\n"
0122         "}\n"
0123         "if (isFoo)\n"
0124         "{\n"
0125         "bar();\n"
0126         "}\n"
0127         "else\n"
0128         "{\n"
0129         "anotherBar();\n"
0130         "}\n"
0131         "}\n"
0132         "int foo()\n"
0133         "\twhile(isFoo)\n"
0134         "\t\t{\n"
0135         "\t\t\t// ...\n"
0136         "\t\t\tgoto error;\n"
0137         "\t\t/* .... */\n"
0138         "\t\terror:\n"
0139         "\t\t\t//...\n"
0140         "\t\t}\n"
0141         "\t}\n"
0142         "fooArray[]={ red,\n"
0143         "\tgreen,\n"
0144         "\tdarkblue};\n"
0145         "fooFunction(barArg1,\n"
0146         "\tbarArg2,\n"
0147         "\tbarArg3);\n"
0148         "struct foo{ int bar() {} };\n");
0149 }
0150 
0151 QString indentingObjCSample()
0152 {
0153     return QStringLiteral(
0154         "#import <objc/Object.h>\n"
0155         "\n"
0156         "#define foobar(A)\\\n"
0157         "\t{Foo();Bar();}\n"
0158         "#define anotherFoo(B)\\\n"
0159         "\treturn Bar()\n"
0160         "\n"
0161         "@interface Foo : Bar {\n"
0162         "@private\n"
0163         "\tid Baz;\n"
0164         "}\n"
0165         "- (void) init;\n"
0166         "- (NSString*) description;\n"
0167         "@property (retain) id Baz;\n"
0168         "@end\n"
0169         "\n"
0170         "@interface Foo (Bar)\n"
0171         "- (void)bar:(int) foo;\n"
0172         "@end\n"
0173         "\n"
0174         "@implementation Foo (Bar)\n"
0175         "\n"
0176         "- (void) bar:(int) foo\n"
0177         "{\n"
0178         "\tswitch (foo) {\n"
0179         "case 1:\n"
0180         "a += 1;\n"
0181         "break;\n"
0182         "case 2: {\n"
0183         "a += 2;\n"
0184         "break;\n"
0185         "}\n"
0186         "}\n"
0187         "if (isFoo) {\n"
0188         "bar();\n"
0189         "} else {\n"
0190         "[anotherBar withFoo:self];\n"
0191         "}\n"
0192         "}\n"
0193         "\n"
0194         "@end\n"
0195         "int foo()\n"
0196         "while (isFoo)\n"
0197         "{\n"
0198         "\t// ...\n"
0199         "\tgoto error;\n"
0200         "\t/* .... */\n"
0201         "error:\n"
0202         "\t//...\n"
0203         "}\n"
0204         "\n"
0205         "fooArray[] = { red,\n"
0206         "\tgreen,\n"
0207         "\tdarkblue};\n"
0208         "fooFunction(barArg1,\n"
0209         "\tbarArg2,\n"
0210         "\tbarArg3);\n"
0211         "struct foo { int bar() {} };\n");
0212 }
0213 
0214 QString previewText(const QString& indentingSample, const QString& formattingSample)
0215 {
0216     return QLatin1String("// Indentation\n") + indentingSample + QLatin1String("\t// Formatting\n") + formattingSample;
0217 }
0218 
0219 } // unnamed namespace
0220 
0221 using namespace KDevelop;
0222 
0223 K_PLUGIN_FACTORY_WITH_JSON(AStyleFactory, "kdevastyle.json", registerPlugin<AStylePlugin>();)
0224 
0225 AStylePlugin::AStylePlugin(QObject *parent, const QVariantList&)
0226     : IPlugin(QStringLiteral("kdevastyle"), parent)
0227     , m_formatter(new AStyleFormatter())
0228 {
0229 }
0230 
0231 AStylePlugin::~AStylePlugin()
0232 {
0233 }
0234 
0235 QString AStylePlugin::name() const
0236 {
0237     // This needs to match the X-KDE-PluginInfo-Name entry from the .desktop file!
0238     return QStringLiteral("kdevastyle");
0239 }
0240 
0241 QString AStylePlugin::caption() const
0242 {
0243     return QStringLiteral("Artistic Style");
0244 }
0245 
0246 QString AStylePlugin::description() const
0247 {
0248     return i18n(
0249         "<b>Artistic Style</b> is a source code indenter, formatter,"
0250         " and beautifier for the C, C++, C# and Java programming languages."
0251         // Use <p> to prevent a line break within the link in QWhatsThis. Apparently the following excerpt
0252         // from QToolTip class documentation applies to QWhatsThis too: "Rich text displayed in a tool tip
0253         // is implicitly word-wrapped unless specified differently with <p style='white-space:pre'>."
0254         "<p style='margin-top:0;white-space:pre'>"
0255         "Home Page: <a href=\"http://astyle.sourceforge.net/\">http://astyle.sourceforge.net</a></p>");
0256 }
0257 
0258 QString AStylePlugin::formatSourceWithStyle(const SourceFormatterStyle& style,
0259                                             const QString& text,
0260                                             const QUrl& /*url*/,
0261                                             const QMimeType& mime,
0262                                             const QString& leftContext,
0263                                             const QString& rightContext) const
0264 {
0265     if(mime.inherits(QStringLiteral("text/x-java")))
0266         m_formatter->setJavaStyle();
0267     else if(mime.inherits(QStringLiteral("text/x-csharp")))
0268         m_formatter->setSharpStyle();
0269     else
0270         m_formatter->setCStyle();
0271 
0272     if (style.content().isEmpty()) {
0273         m_formatter->predefinedStyle(style.name());
0274     } else {
0275         m_formatter->loadStyle(style.content());
0276     }
0277 
0278     return m_formatter->formatSource(text, leftContext, rightContext);
0279 }
0280 
0281 static SourceFormatterStyle createPredefinedStyle(const QString& name, const QString& caption = QString())
0282 {
0283     SourceFormatterStyle st = SourceFormatterStyle( name );
0284     st.setCaption( caption.isEmpty() ? name : caption );
0285     AStyleFormatter fmt;
0286     fmt.predefinedStyle( name );
0287     st.setContent( fmt.saveStyle() );
0288     st.setMimeTypes(ISourceFormatter::mimeTypesSupportedByBuiltInStyles());
0289     st.setUsePreview(true);
0290     return st;
0291 }
0292 
0293 QVector<SourceFormatterStyle> AStylePlugin::predefinedStyles() const
0294 {
0295     static const QVector<SourceFormatterStyle> list = {
0296         createPredefinedStyle(QStringLiteral("ANSI")),
0297         createPredefinedStyle(QStringLiteral("GNU")),
0298         createPredefinedStyle(QStringLiteral("Java")),
0299         createPredefinedStyle(QStringLiteral("K&R"), QStringLiteral("Kernighan & Ritchie")),
0300         createPredefinedStyle(QStringLiteral("Linux")),
0301         createPredefinedStyle(QStringLiteral("Stroustrup")),
0302         createPredefinedStyle(QStringLiteral("Horstmann")),
0303         createPredefinedStyle(QStringLiteral("Whitesmith")),
0304         createPredefinedStyle(QStringLiteral("Banner")),
0305         createPredefinedStyle(QStringLiteral("1TBS")),
0306         createPredefinedStyle(QStringLiteral("KDELibs"), QStringLiteral("KDE Frameworks")),
0307         createPredefinedStyle(QStringLiteral("Qt")),
0308     };
0309     return list;
0310 }
0311 
0312 bool AStylePlugin::hasEditStyleWidget() const
0313 {
0314     return true;
0315 }
0316 
0317 SettingsWidgetPtr AStylePlugin::editStyleWidget(const QMimeType& mime) const
0318 {
0319     AStylePreferences::Language lang = AStylePreferences::CPP;
0320     if (mime.inherits(QStringLiteral("text/x-java")))
0321         lang = AStylePreferences::Java;
0322     else if (mime.inherits(QStringLiteral("text/x-csharp")))
0323         lang = AStylePreferences::CSharp;
0324     else if (mime.inherits(QStringLiteral("text/x-objcsrc")) || mime.inherits(QStringLiteral("text/x-objc++src"))) {
0325         // x-objc++src *should* inherit x-objcsrc but that is not always the case in practice
0326         lang = AStylePreferences::ObjC;
0327     }
0328     return SettingsWidgetPtr{new AStylePreferences(lang)};
0329 }
0330 
0331 QString AStylePlugin::previewText(const SourceFormatterStyle& /*style*/, const QMimeType& mime) const
0332 {
0333     if (mime.inherits(QStringLiteral("text/x-objcsrc")) || mime.inherits(QStringLiteral("text/x-objc++src"))) {
0334         static const QString text = ::previewText(indentingObjCSample(), formattingObjCSample());
0335         return text;
0336     } else {
0337         static const QString text = ::previewText(indentingCppSample(), formattingCppSample());
0338         return text;
0339     }
0340     // TODO: add previews for the other supported languages
0341 }
0342 
0343 AStylePlugin::Indentation AStylePlugin::indentation(const SourceFormatterStyle& style, const QUrl& url,
0344                                                     const QMimeType& mime) const
0345 {
0346     // Call formatSourceWithStyle() first to initialize the m_formatter data structures according to the arguments.
0347     formatSourceWithStyle(style, QString(), url, mime, QString(), QString());
0348 
0349     Indentation ret;
0350 
0351     ret.indentWidth = m_formatter->option(QStringLiteral("FillCount")).toInt();
0352     
0353     QString s = m_formatter->option(QStringLiteral("Fill")).toString();
0354     if(s == QLatin1String("Tabs"))
0355     {
0356         // Do tabs-only indentation
0357         ret.indentationTabWidth = ret.indentWidth;
0358     }else{
0359         // Don't use tabs at all
0360         ret.indentationTabWidth = -1;
0361     }
0362     
0363     return ret;
0364 }
0365 
0366 QString AStylePlugin::formattingSample(AStylePreferences::Language lang)
0367 {
0368    switch (lang) {
0369       case AStylePreferences::ObjC:
0370         return formattingObjCSample();
0371       default:
0372         return formattingCppSample();
0373    }
0374    Q_UNREACHABLE();
0375 }
0376 
0377 QString AStylePlugin::indentingSample(AStylePreferences::Language lang)
0378 {
0379    switch (lang) {
0380       case AStylePreferences::ObjC:
0381         return indentingObjCSample();
0382       default:
0383         return indentingCppSample();
0384    }
0385    Q_UNREACHABLE();
0386 }
0387 
0388 #include "astyle_plugin.moc"
0389 #include "moc_astyle_plugin.cpp"