File indexing completed on 2024-04-21 15:24:06

0001 /*
0002     SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
0003     SPDX-FileCopyrightText: 2008 Niko Sams <niko.sams@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-or-later
0006 */
0007 
0008 #include "helpers.h"
0009 #include "item.h"
0010 
0011 #include <QList>
0012 #include <QVariant>
0013 #include <QTextFormat>
0014 #include <QStringList>
0015 
0016 #include <language/duchain/declaration.h>
0017 #include <language/duchain/abstractfunctiondeclaration.h>
0018 #include <language/duchain/duchainutils.h>
0019 #include <language/duchain/ducontext.h>
0020 #include <language/duchain/types/functiontype.h>
0021 #include <language/duchain/types/integraltype.h>
0022 
0023 #include <KTextEditor/ConfigInterface>
0024 #include <KTextEditor/Document>
0025 
0026 using namespace KDevelop;
0027 namespace Php
0028 {
0029 
0030 void createArgumentList(const NormalDeclarationCompletionItem& item, QString& ret, QList<QVariant>* highlighting,
0031                         bool phpTypeHinting)
0032 {
0033     ///@todo also highlight the matches of the previous arguments, they are given by ViableFunction
0034     Declaration* dec(item.declaration().data());
0035 
0036     int textFormatStart = 0;
0037     QTextFormat normalFormat(QTextFormat::CharFormat);
0038     QTextFormat highlightFormat; //highlightFormat is invalid, so kate uses the match-quality dependent color.
0039 
0040     AbstractFunctionDeclaration* decl = dynamic_cast<AbstractFunctionDeclaration*>(dec);
0041     FunctionType::Ptr functionType = dec->type<FunctionType>();
0042 
0043     if (functionType && decl) {
0044 
0045         QVector<Declaration*> parameters;
0046         if (DUChainUtils::argumentContext(dec))
0047             parameters = DUChainUtils::argumentContext(dec)->localDeclarations();
0048 
0049         uint defaultParamNum = 0;
0050 
0051         int firstDefaultParam = parameters.count() - decl->defaultParametersSize();
0052 
0053         ret = '(';
0054         bool first = true;
0055         int num = 0;
0056 
0057         foreach(Declaration* dec, parameters) {
0058             if (first)
0059                 first = false;
0060             else
0061                 ret += QLatin1String(", ");
0062 
0063             bool doHighlight = false;
0064             QTextFormat doFormat = normalFormat;
0065 
0066 //       if( num < f.matchedArguments )
0067 //       {
0068             doHighlight = true;
0069             doFormat = QTextFormat(QTextFormat::CharFormat);
0070 
0071 //         if( parameterConversion != conversions.end() ) {
0072 //           //Interpolate the color
0073 //           quint64 badMatchColor = 0xff7777ff; //Full blue
0074 //           quint64 goodMatchColor = 0xff77ff77; //Full green
0075 //
0076 //           uint totalColor = (badMatchColor*(Cpp::MaximumConversionResult-(*parameterConversion).rank) + goodMatchColor*(*parameterConversion).rank)/Cpp::MaximumConversionResult;
0077 //
0078 //           doFormat.setBackground( QBrush(totalColor) );
0079 //
0080 //           ++parameterConversion;
0081 //         }
0082 //       }
0083 
0084             if (doHighlight) {
0085                 if (highlighting && ret.length() != textFormatStart) {
0086                     //Add a default-highlighting for the passed text
0087                     *highlighting <<  QVariant(textFormatStart);
0088                     *highlighting << QVariant(ret.length() - textFormatStart);
0089                     *highlighting << QVariant(normalFormat);
0090                     textFormatStart = ret.length();
0091                 }
0092             }
0093 
0094             if (num < functionType->arguments().count()) {
0095                 if (AbstractType::Ptr type = functionType->arguments().at(num)) {
0096                     // when php-like type hinting is requested only add types for arrays and classes
0097                     if (!phpTypeHinting
0098                             || (type->whichType() == AbstractType::TypeIntegral
0099                                 && type.staticCast<IntegralType>()->dataType() == IntegralType::TypeArray)
0100                             || type->whichType() == AbstractType::TypeStructure) {
0101                         ret += type->toString() + ' ';
0102                     }
0103                 }
0104             }
0105 
0106             ret += '$' + dec->identifier().toString();
0107 
0108             if (doHighlight) {
0109                 if (highlighting && ret.length() != textFormatStart) {
0110                     *highlighting <<  QVariant(textFormatStart);
0111                     *highlighting << QVariant(ret.length() - textFormatStart);
0112                     *highlighting << doFormat;
0113                     textFormatStart = ret.length();
0114                 }
0115             }
0116 
0117 
0118             if (num >= firstDefaultParam) {
0119                 IndexedString defaultStr = decl->defaultParameters()[defaultParamNum];
0120                 if (!defaultStr.isEmpty()) {
0121                     ret += " = " + defaultStr.str();
0122                 }
0123                 ++defaultParamNum;
0124             }
0125 
0126             ++num;
0127         }
0128         ret += ')';
0129 
0130         if (highlighting && ret.length() != textFormatStart) {
0131             *highlighting <<  QVariant(textFormatStart);
0132             *highlighting << QVariant(ret.length());
0133             *highlighting << normalFormat;
0134             textFormatStart = ret.length();
0135         }
0136         return;
0137     }
0138 }
0139 
0140 QStringList getMethodTokens(QString text)
0141 {
0142     QStringList tokens;
0143 
0144 
0145     text = text.trimmed();
0146     if (text.endsWith(QStringLiteral("function"), Qt::CaseInsensitive)) {
0147         tokens << QStringLiteral("function");
0148         text = text.left(text.length() - 8);
0149     }
0150 
0151     QStringList possibleTokens;
0152     possibleTokens << QStringLiteral("private");
0153     possibleTokens << QStringLiteral("public");
0154     possibleTokens << QStringLiteral("protected");
0155     possibleTokens << QStringLiteral("static");
0156     possibleTokens << QStringLiteral("abstract");
0157     possibleTokens << QStringLiteral("final");
0158 
0159     while (!possibleTokens.isEmpty()) {
0160         bool foundAnything = false;
0161         text = text.trimmed();
0162         foreach(const QString &token, possibleTokens) {
0163             if (text.endsWith(token, Qt::CaseInsensitive)) {
0164                 tokens << token;
0165                 text = text.left(text.length() - token.length());
0166                 foundAnything = true;
0167                 possibleTokens.removeOne(token);
0168                 break;
0169             }
0170         }
0171         if (!foundAnything) {
0172             break;
0173         }
0174     }
0175 
0176     return tokens;
0177 }
0178 
0179 const QString indentString(KTextEditor::Document *document)
0180 {
0181     KTextEditor::ConfigInterface *iface = qobject_cast<KTextEditor::ConfigInterface *>(document);
0182     if (!iface)
0183         return QStringLiteral("    ");
0184     if (iface->configValue(QStringLiteral("replace-tabs")).toBool()) {
0185         QVariant iWidth = iface->configValue(QStringLiteral("indent-width"));
0186         if (iWidth.isValid())
0187             return QString(iWidth.toUInt(), ' ');
0188         /*
0189          * Provide a default implementation if current KatePart
0190          * does not handle "indent-width".
0191          */
0192         return QStringLiteral("    ");
0193     }
0194     return QStringLiteral("\t");
0195 }
0196 
0197 QString getIndentation( const QString &line ) {
0198     return line.left(line.indexOf(QRegExp("\\S"), 0));
0199 }
0200 
0201 }