File indexing completed on 2024-05-12 04:37:44

0001 /*
0002     SPDX-FileCopyrightText: 2007-2008 David Nolden <david.nolden.kdevelop@art-master.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-only
0005 */
0006 
0007 #include "codecompletionhelper.h"
0008 
0009 #include "../duchain/duchain.h"
0010 #include "../duchain/declaration.h"
0011 #include "../duchain/duchainlock.h"
0012 #include "../duchain/types/functiontype.h"
0013 #include "../duchain/types/integraltype.h"
0014 
0015 #include <KTextEditor/Document>
0016 #include <KTextEditor/View>
0017 
0018 namespace KDevelop {
0019 void insertFunctionParenText(KTextEditor::View* view, const KTextEditor::Cursor& pos,
0020                              const DeclarationPointer& declaration, bool jumpForbidden)
0021 {
0022     bool spaceBeforeParen = false; ///@todo Take this from some astyle config or something
0023     bool spaceBetweenParens = false;
0024     bool spaceBetweenEmptyParens = false;
0025 
0026     KDevelop::DUChainReadLocker lock(KDevelop::DUChain::lock());
0027 
0028     bool haveArguments = false;
0029 
0030     if (!declaration)
0031         return;
0032 
0033     TypePtr<FunctionType> funcType = declaration->type<FunctionType>();
0034 
0035     if (declaration->kind() == Declaration::Type || (funcType && funcType->indexedArgumentsSize()))
0036         haveArguments = true;
0037 
0038     if (declaration->kind() == Declaration::Instance && !declaration->isFunctionDeclaration())
0039         haveArguments = true; //probably a constructor initializer
0040 
0041     //Need to have a paren behind
0042     QString suffix = view->document()->text(KTextEditor::Range(pos, pos + KTextEditor::Cursor(1, 0)));
0043     if (suffix.trimmed().startsWith(QLatin1Char('('))) {
0044         //Move the cursor behind the opening paren
0045         if (view)
0046             view->setCursorPosition(pos + KTextEditor::Cursor(0, suffix.indexOf(QLatin1Char('(')) + 1));
0047     } else {
0048         //We need to insert an opening paren
0049         QString openingParen;
0050         if (spaceBeforeParen)
0051             openingParen = QStringLiteral(" (");
0052         else
0053             openingParen = QStringLiteral("(");
0054 
0055         if (spaceBetweenParens && (haveArguments || spaceBetweenEmptyParens))
0056             openingParen += QLatin1Char(' ');
0057 
0058         QString closingParen;
0059         if (spaceBetweenParens && (haveArguments)) {
0060             closingParen = QStringLiteral(" )");
0061         } else
0062             closingParen = QStringLiteral(")");
0063 
0064         KTextEditor::Cursor jumpPos = pos + KTextEditor::Cursor(0, openingParen.length());
0065 
0066         // when function returns void, also add a semicolon
0067         if (funcType) {
0068             if (auto type = funcType->returnType().dynamicCast<IntegralType>()) {
0069                 if (type->dataType() == IntegralType::TypeVoid) {
0070                     const QChar nextChar = view->document()->characterAt(pos);
0071                     if (nextChar != QLatin1Char(';') && nextChar != QLatin1Char(')') && nextChar != QLatin1Char(',')) {
0072                         closingParen += QLatin1Char(';');
0073                     }
0074                 }
0075             }
0076         }
0077 
0078         //If no arguments, move the cursor behind the closing paren (or semicolon)
0079         if (!haveArguments)
0080             jumpPos += KTextEditor::Cursor(0, closingParen.length());
0081 
0082         lock.unlock();
0083         if (view) {
0084             view->document()->insertText(pos, openingParen + closingParen);
0085             if (!jumpForbidden) {
0086                 view->setCursorPosition(jumpPos);
0087             }
0088         }
0089     }
0090 }
0091 }