File indexing completed on 2024-05-19 04:39:55
0001 /* 0002 SPDX-FileCopyrightText: 2012 Miha Čančula <miha@noughmad.eu> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "kdevfilters.h" 0008 0009 #include <language/duchain/persistentsymboltable.h> 0010 #include <language/duchain/types/structuretype.h> 0011 #include <language/duchain/duchainlock.h> 0012 #include <language/duchain/duchain.h> 0013 #include <language/duchain/declaration.h> 0014 0015 using namespace KDevelop; 0016 0017 static 0018 QString safeString(const QVariant& variant) 0019 { 0020 if (variant.canConvert<Grantlee::SafeString>()) 0021 { 0022 return variant.value<Grantlee::SafeString>().get(); 0023 } 0024 else 0025 { 0026 return variant.toString(); 0027 } 0028 } 0029 0030 QStringList words(const QVariant& input) 0031 { 0032 QString string = safeString(input); 0033 if (string == string.toLower() && !string.contains(QLatin1Char('_'))) { 0034 return QStringList(string); 0035 } 0036 0037 if (string.contains(QLatin1Char('_'))) { 0038 return string.toLower().split(QLatin1Char('_')); 0039 } 0040 0041 int n = string.size(); 0042 QStringList ret; 0043 int last = 0; 0044 for (int i = 1; i < n; ++i) 0045 { 0046 if (string[i].isUpper()) 0047 { 0048 ret << string.mid(last, i-last).toLower(); 0049 last = i; 0050 } 0051 } 0052 ret << string.mid(last).toLower(); 0053 return ret; 0054 } 0055 0056 QVariant CamelCaseFilter::doFilter(const QVariant& input, const QVariant& /*argument*/, 0057 bool /*autoescape*/) const 0058 { 0059 QString ret; 0060 const auto words = ::words(input); 0061 for (const QString& word : words) { 0062 QString w = word; 0063 w[0] = w[0].toUpper(); 0064 ret += w; 0065 } 0066 return Grantlee::SafeString(ret); 0067 } 0068 0069 QVariant LowerCamelCaseFilter::doFilter(const QVariant& input, const QVariant& /*argument*/, 0070 bool /*autoescape*/) const 0071 { 0072 QString ret; 0073 const auto words = ::words(input); 0074 for (const QString& word : words) { 0075 QString w = word; 0076 w[0] = w[0].toUpper(); 0077 ret += w; 0078 } 0079 if (!ret.isEmpty()) 0080 { 0081 ret[0] = ret[0].toUpper(); 0082 } 0083 return Grantlee::SafeString(ret); 0084 } 0085 0086 QVariant UnderscoreFilter::doFilter(const QVariant& input, const QVariant& /*argument*/, 0087 bool /*autoescape*/) const 0088 { 0089 QString ret = words(input).join(QLatin1Char('_')); 0090 return Grantlee::SafeString(ret); 0091 } 0092 0093 QVariant UpperFirstFilter::doFilter(const QVariant& input, const QVariant& /*argument*/, 0094 bool /*autoescape*/) const 0095 { 0096 QString in = safeString(input); 0097 if (!in.isEmpty()) 0098 { 0099 in[0] = in[0].toUpper(); 0100 } 0101 return Grantlee::SafeString(in); 0102 } 0103 0104 0105 QVariant SplitLinesFilter::doFilter(const QVariant& input, const QVariant& argument, 0106 bool /*autoescape*/) const 0107 { 0108 QStringList retLines; 0109 QString start = safeString(argument); 0110 const QString inputString = safeString(input); 0111 const auto lines = inputString.splitRef(QLatin1Char('\n'), Qt::KeepEmptyParts); 0112 retLines.reserve(lines.size()); 0113 for (const auto& line : lines) { 0114 retLines << start + line; 0115 } 0116 return Grantlee::SafeString(retLines.join(QLatin1Char('\n'))); 0117 } 0118 0119 QVariant ArgumentTypeFilter::doFilter (const QVariant& input, const QVariant& /*argument*/, 0120 bool /*autoescape*/) const 0121 { 0122 auto type = safeString(input); 0123 0124 auto visit = [&type](const IndexedDeclaration& indexedDeclaration) { 0125 auto declaration = indexedDeclaration.declaration(); 0126 if (!declaration || declaration->isForwardDeclaration()) { 0127 return PersistentSymbolTable::VisitorState::Continue; 0128 } 0129 0130 // Check if it's a class/struct/etc 0131 if (declaration->type<StructureType>()) { 0132 type = QLatin1String("const %1&").arg(type); 0133 return PersistentSymbolTable::VisitorState::Break; 0134 } 0135 0136 return PersistentSymbolTable::VisitorState::Continue; 0137 }; 0138 0139 DUChainReadLocker locker(DUChain::lock()); 0140 PersistentSymbolTable::self().visitDeclarations(IndexedQualifiedIdentifier(QualifiedIdentifier(type)), visit); 0141 0142 return Grantlee::SafeString(type); 0143 } 0144 0145 KDevFilters::KDevFilters(QObject* parent, const QVariantList &) 0146 : QObject(parent) 0147 { 0148 } 0149 0150 KDevFilters::~KDevFilters() 0151 { 0152 0153 } 0154 0155 QHash< QString, Grantlee::Filter* > KDevFilters::filters(const QString& name) 0156 { 0157 Q_UNUSED(name); 0158 QHash< QString, Grantlee::Filter* > filters; 0159 0160 filters[QStringLiteral("camel_case")] = new CamelCaseFilter(); 0161 filters[QStringLiteral("camel_case_lower")] = new LowerCamelCaseFilter(); 0162 filters[QStringLiteral("underscores")] = new UnderscoreFilter(); 0163 filters[QStringLiteral("lines_prepend")] = new SplitLinesFilter(); 0164 filters[QStringLiteral("upper_first")] = new UpperFirstFilter(); 0165 filters[QStringLiteral("arg_type")] = new ArgumentTypeFilter(); 0166 0167 return filters; 0168 } 0169 0170 #include "moc_kdevfilters.cpp"