| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | /****************************************************************************
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2015-01-14 18:07:15 +01:00
										 |  |  | ** Copyright (C) 2015 The Qt Company Ltd. | 
					
						
							|  |  |  | ** Contact: http://www.qt.io/licensing
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** This file is part of Qt Creator. | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** Commercial License Usage | 
					
						
							|  |  |  | ** Licensees holding valid commercial Qt licenses may use this file in | 
					
						
							|  |  |  | ** accordance with the commercial license agreement provided with the | 
					
						
							|  |  |  | ** Software or, alternatively, in accordance with the terms contained in | 
					
						
							| 
									
										
										
										
											2015-01-14 18:07:15 +01:00
										 |  |  | ** a written agreement between you and The Qt Company.  For licensing terms and | 
					
						
							|  |  |  | ** conditions see http://www.qt.io/terms-conditions.  For further information
 | 
					
						
							| 
									
										
										
										
											2014-10-01 13:21:18 +02:00
										 |  |  | ** use the contact form at http://www.qt.io/contact-us.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 14:17:16 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2009-02-25 09:15:00 +01:00
										 |  |  | ** GNU Lesser General Public License Usage | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
					
						
							| 
									
										
										
										
											2014-10-01 13:21:18 +02:00
										 |  |  | ** General Public License version 2.1 or version 3 as published by the Free | 
					
						
							|  |  |  | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and | 
					
						
							|  |  |  | ** LICENSE.LGPLv3 included in the packaging of this file.  Please review the | 
					
						
							|  |  |  | ** following information to ensure the GNU Lesser General Public License | 
					
						
							|  |  |  | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
 | 
					
						
							|  |  |  | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2015-01-14 18:07:15 +01:00
										 |  |  | ** In addition, as a special exception, The Qt Company gives you certain additional | 
					
						
							|  |  |  | ** rights.  These rights are described in The Qt Company LGPL Exception | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ****************************************************************************/ | 
					
						
							| 
									
										
										
										
											2008-12-02 15:08:31 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | #include "cppcompletionassist.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-18 12:59:57 -03:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-08-19 15:46:50 +02:00
										 |  |  | #include "builtineditordocumentparser.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-18 12:59:57 -03:00
										 |  |  | #include "cppdoxygen.h"
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | #include "cppmodelmanager.h"
 | 
					
						
							| 
									
										
										
										
											2013-04-23 15:04:36 +02:00
										 |  |  | #include "cpptoolsconstants.h"
 | 
					
						
							| 
									
										
										
										
											2014-05-08 09:48:27 -04:00
										 |  |  | #include "cpptoolsreuse.h"
 | 
					
						
							| 
									
										
										
										
											2014-08-19 15:59:29 +02:00
										 |  |  | #include "editordocumenthandle.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <coreplugin/icore.h>
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | #include <cppeditor/cppeditorconstants.h>
 | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  | #include <texteditor/codeassist/assistproposalitem.h>
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | #include <texteditor/codeassist/genericproposal.h>
 | 
					
						
							|  |  |  | #include <texteditor/codeassist/ifunctionhintproposalmodel.h>
 | 
					
						
							|  |  |  | #include <texteditor/codeassist/functionhintproposal.h>
 | 
					
						
							|  |  |  | #include <texteditor/convenience.h>
 | 
					
						
							| 
									
										
										
										
											2010-10-27 17:38:22 +02:00
										 |  |  | #include <texteditor/snippets/snippet.h>
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | #include <texteditor/texteditorsettings.h>
 | 
					
						
							|  |  |  | #include <texteditor/completionsettings.h>
 | 
					
						
							| 
									
										
										
										
											2013-03-27 18:54:03 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 09:32:46 +01:00
										 |  |  | #include <utils/mimetypes/mimedatabase.h>
 | 
					
						
							| 
									
										
										
										
											2012-01-23 17:44:49 +01:00
										 |  |  | #include <utils/qtcassert.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-27 18:54:03 +01:00
										 |  |  | #include <cplusplus/BackwardsScanner.h>
 | 
					
						
							|  |  |  | #include <cplusplus/CppRewriter.h>
 | 
					
						
							|  |  |  | #include <cplusplus/ExpressionUnderCursor.h>
 | 
					
						
							|  |  |  | #include <cplusplus/MatchingText.h>
 | 
					
						
							|  |  |  | #include <cplusplus/Overview.h>
 | 
					
						
							|  |  |  | #include <cplusplus/ResolveExpression.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-05 08:22:48 +01:00
										 |  |  | #include <QDirIterator>
 | 
					
						
							| 
									
										
										
										
											2012-02-15 10:42:41 +01:00
										 |  |  | #include <QLatin1String>
 | 
					
						
							|  |  |  | #include <QTextCursor>
 | 
					
						
							|  |  |  | #include <QTextDocument>
 | 
					
						
							|  |  |  | #include <QIcon>
 | 
					
						
							| 
									
										
										
										
											2010-05-12 14:52:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | using namespace CPlusPlus; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | using namespace CppEditor; | 
					
						
							|  |  |  | using namespace CppTools; | 
					
						
							| 
									
										
										
										
											2012-03-26 15:18:01 +02:00
										 |  |  | using namespace CppTools::Internal; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | using namespace TextEditor; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | namespace CppTools { | 
					
						
							|  |  |  | namespace Internal { | 
					
						
							| 
									
										
										
										
											2009-10-08 15:32:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | struct CompleteFunctionDeclaration | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     explicit CompleteFunctionDeclaration(Function *f = 0) | 
					
						
							|  |  |  |         : function(f) | 
					
						
							|  |  |  |     {} | 
					
						
							| 
									
										
										
										
											2009-07-23 16:46:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     Function *function; | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2009-07-23 16:46:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | // ---------------------
 | 
					
						
							|  |  |  | // CppAssistProposalItem
 | 
					
						
							|  |  |  | // ---------------------
 | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  | class CppAssistProposalItem : public AssistProposalItem | 
					
						
							| 
									
										
										
										
											2011-02-21 14:02:00 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | public: | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     CppAssistProposalItem() : | 
					
						
							| 
									
										
										
										
											2011-05-26 12:10:08 +02:00
										 |  |  |         m_isOverloaded(false) {} | 
					
						
							| 
									
										
										
										
											2009-04-02 10:19:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:32:42 +02:00
										 |  |  |     bool prematurelyApplies(const QChar &c) const override; | 
					
						
							|  |  |  |     void applyContextualContent(TextEditorWidget *editorWidget, int basePosition) const override; | 
					
						
							| 
									
										
										
										
											2010-01-26 11:44:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     bool isOverloaded() const { return m_isOverloaded; } | 
					
						
							|  |  |  |     void markAsOverloaded() { m_isOverloaded = true; } | 
					
						
							|  |  |  |     void keepCompletionOperator(unsigned compOp) { m_completionOperator = compOp; } | 
					
						
							| 
									
										
										
										
											2011-05-26 12:10:08 +02:00
										 |  |  |     void keepTypeOfExpression(const QSharedPointer<TypeOfExpression> &typeOfExp) | 
					
						
							|  |  |  |     { m_typeOfExpression = typeOfExp; } | 
					
						
							| 
									
										
										
										
											2010-01-26 11:44:45 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | private: | 
					
						
							|  |  |  |     bool m_isOverloaded; | 
					
						
							|  |  |  |     mutable QChar m_typedChar; | 
					
						
							| 
									
										
										
										
											2013-02-18 18:47:54 +01:00
										 |  |  |     unsigned m_completionOperator; | 
					
						
							| 
									
										
										
										
											2011-05-26 12:10:08 +02:00
										 |  |  |     QSharedPointer<TypeOfExpression> m_typeOfExpression; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2010-07-14 12:37:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | } // Internal
 | 
					
						
							|  |  |  | } // CppTools
 | 
					
						
							| 
									
										
										
										
											2010-07-14 12:37:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | Q_DECLARE_METATYPE(CppTools::Internal::CompleteFunctionDeclaration) | 
					
						
							| 
									
										
										
										
											2010-06-02 15:22:42 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 12:58:05 +01:00
										 |  |  | bool CppAssistProposalModel::isSortable(const QString &prefix) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_completionOperator != T_EOF_SYMBOL) | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return !prefix.isEmpty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  | AssistProposalItem *CppAssistProposalModel::proposalItem(int index) const | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |     auto item = static_cast<AssistProposalItem *>(GenericProposalModel::proposalItem(index)); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (!item->data().canConvert<QString>()) { | 
					
						
							|  |  |  |         CppAssistProposalItem *cppItem = static_cast<CppAssistProposalItem *>(item); | 
					
						
							|  |  |  |         cppItem->keepCompletionOperator(m_completionOperator); | 
					
						
							| 
									
										
										
										
											2011-05-26 12:10:08 +02:00
										 |  |  |         cppItem->keepTypeOfExpression(m_typeOfExpression); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     } | 
					
						
							|  |  |  |     return item; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-05-19 14:09:43 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | bool CppAssistProposalItem::prematurelyApplies(const QChar &typedChar) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) { | 
					
						
							|  |  |  |         if (typedChar == QLatin1Char('(') || typedChar == QLatin1Char(',')) { | 
					
						
							|  |  |  |             m_typedChar = typedChar; | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (m_completionOperator == T_STRING_LITERAL | 
					
						
							|  |  |  |                || m_completionOperator == T_ANGLE_STRING_LITERAL) { | 
					
						
							|  |  |  |         if (typedChar == QLatin1Char('/') && text().endsWith(QLatin1Char('/'))) { | 
					
						
							|  |  |  |             m_typedChar = typedChar; | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (data().value<Symbol *>()) { | 
					
						
							|  |  |  |         if (typedChar == QLatin1Char(':') | 
					
						
							|  |  |  |                 || typedChar == QLatin1Char(';') | 
					
						
							|  |  |  |                 || typedChar == QLatin1Char('.') | 
					
						
							|  |  |  |                 || typedChar == QLatin1Char(',') | 
					
						
							|  |  |  |                 || typedChar == QLatin1Char('(')) { | 
					
						
							|  |  |  |             m_typedChar = typedChar; | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (data().canConvert<CompleteFunctionDeclaration>()) { | 
					
						
							|  |  |  |         if (typedChar == QLatin1Char('(')) { | 
					
						
							|  |  |  |             m_typedChar = typedChar; | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-26 11:37:54 +02:00
										 |  |  | static bool isDereferenced(TextEditorWidget *editorWidget, int basePosition) | 
					
						
							| 
									
										
										
										
											2011-10-05 10:46:06 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-09-03 22:45:33 +02:00
										 |  |  |     QTextCursor cursor = editorWidget->textCursor(); | 
					
						
							| 
									
										
										
										
											2011-10-05 10:46:06 +02:00
										 |  |  |     cursor.setPosition(basePosition); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-26 09:14:38 +02:00
										 |  |  |     BackwardsScanner scanner(cursor, LanguageFeatures()); | 
					
						
							| 
									
										
										
										
											2011-10-05 10:46:06 +02:00
										 |  |  |     for (int pos = scanner.startToken()-1; pos >= 0; pos--) { | 
					
						
							|  |  |  |         switch (scanner[pos].kind()) { | 
					
						
							|  |  |  |         case T_COLON_COLON: | 
					
						
							|  |  |  |         case T_IDENTIFIER: | 
					
						
							|  |  |  |             //Ignore scope specifiers
 | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         case T_AMPER: return true; | 
					
						
							|  |  |  |         default:      return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-26 11:37:54 +02:00
										 |  |  | void CppAssistProposalItem::applyContextualContent(TextEditorWidget *editorWidget, int basePosition) const | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     Symbol *symbol = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (data().isValid()) | 
					
						
							|  |  |  |         symbol = data().value<Symbol *>(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString toInsert; | 
					
						
							|  |  |  |     QString extraChars; | 
					
						
							|  |  |  |     int extraLength = 0; | 
					
						
							|  |  |  |     int cursorOffset = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool autoParenthesesEnabled = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_completionOperator == T_SIGNAL || m_completionOperator == T_SLOT) { | 
					
						
							|  |  |  |         toInsert = text(); | 
					
						
							|  |  |  |         extraChars += QLatin1Char(')'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (m_typedChar == QLatin1Char('(')) // Eat the opening parenthesis
 | 
					
						
							|  |  |  |             m_typedChar = QChar(); | 
					
						
							|  |  |  |     } else if (m_completionOperator == T_STRING_LITERAL || m_completionOperator == T_ANGLE_STRING_LITERAL) { | 
					
						
							|  |  |  |         toInsert = text(); | 
					
						
							|  |  |  |         if (!toInsert.endsWith(QLatin1Char('/'))) { | 
					
						
							|  |  |  |             extraChars += QLatin1Char((m_completionOperator == T_ANGLE_STRING_LITERAL) ? '>' : '"'); | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (m_typedChar == QLatin1Char('/')) // Eat the slash
 | 
					
						
							|  |  |  |                 m_typedChar = QChar(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         toInsert = text(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-09-19 17:59:27 +02:00
										 |  |  |         const CompletionSettings &completionSettings = TextEditorSettings::completionSettings(); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         const bool autoInsertBrackets = completionSettings.m_autoInsertBrackets; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (autoInsertBrackets && symbol && symbol->type()) { | 
					
						
							|  |  |  |             if (Function *function = symbol->type()->asFunctionType()) { | 
					
						
							|  |  |  |                 // If the member is a function, automatically place the opening parenthesis,
 | 
					
						
							|  |  |  |                 // except when it might take template parameters.
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |                 if (!function->hasReturnType() | 
					
						
							|  |  |  |                     && (function->unqualifiedName() | 
					
						
							|  |  |  |                     && !function->unqualifiedName()->isDestructorNameId())) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     // Don't insert any magic, since the user might have just wanted to select the class
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     /// ### port me
 | 
					
						
							|  |  |  | #if 0
 | 
					
						
							|  |  |  |                 } else if (function->templateParameterCount() != 0 && typedChar != QLatin1Char('(')) { | 
					
						
							|  |  |  |                     // If there are no arguments, then we need the template specification
 | 
					
						
							| 
									
										
										
											
												Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
  # skip ast (excluding paste, astpath, and canv'ast'imer)
  next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
  s = File.read(file)
  next if s.include?('qlalr')
  orig = s.dup
  s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
    res = $&
    if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
      res
    else
      res.gsub!('} else', 'else')
      res.gsub!(/\n +} *\n/m, "\n")
      res.gsub(/ *{$/, '')
    end
  }
  s.gsub!(/ *$/, '')
  File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
											
										 
											2013-01-08 03:32:53 +02:00
										 |  |  |                     if (function->argumentCount() == 0) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                         extraChars += QLatin1Char('<'); | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2014-09-03 22:45:33 +02:00
										 |  |  |                 } else if (!isDereferenced(editorWidget, basePosition) && !function->isAmbiguous()) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     // When the user typed the opening parenthesis, he'll likely also type the closing one,
 | 
					
						
							|  |  |  |                     // in which case it would be annoying if we put the cursor after the already automatically
 | 
					
						
							|  |  |  |                     // inserted closing parenthesis.
 | 
					
						
							|  |  |  |                     const bool skipClosingParenthesis = m_typedChar != QLatin1Char('('); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (completionSettings.m_spaceAfterFunctionName) | 
					
						
							|  |  |  |                         extraChars += QLatin1Char(' '); | 
					
						
							|  |  |  |                     extraChars += QLatin1Char('('); | 
					
						
							|  |  |  |                     if (m_typedChar == QLatin1Char('(')) | 
					
						
							|  |  |  |                         m_typedChar = QChar(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     // If the function doesn't return anything, automatically place the semicolon,
 | 
					
						
							|  |  |  |                     // unless we're doing a scope completion (then it might be function definition).
 | 
					
						
							| 
									
										
										
										
											2014-09-03 22:45:33 +02:00
										 |  |  |                     const QChar characterAtCursor = editorWidget->characterAt(editorWidget->position()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     bool endWithSemicolon = m_typedChar == QLatin1Char(';') | 
					
						
							|  |  |  |                             || (function->returnType()->isVoidType() && m_completionOperator != T_COLON_COLON); | 
					
						
							|  |  |  |                     const QChar semicolon = m_typedChar.isNull() ? QLatin1Char(';') : m_typedChar; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (endWithSemicolon && characterAtCursor == semicolon) { | 
					
						
							|  |  |  |                         endWithSemicolon = false; | 
					
						
							|  |  |  |                         m_typedChar = QChar(); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     // If the function takes no arguments, automatically place the closing parenthesis
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |                     if (!isOverloaded() && !function->hasArguments() && skipClosingParenthesis) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                         extraChars += QLatin1Char(')'); | 
					
						
							|  |  |  |                         if (endWithSemicolon) { | 
					
						
							|  |  |  |                             extraChars += semicolon; | 
					
						
							|  |  |  |                             m_typedChar = QChar(); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } else if (autoParenthesesEnabled) { | 
					
						
							| 
									
										
										
										
											2014-09-03 22:45:33 +02:00
										 |  |  |                         const QChar lookAhead = editorWidget->characterAt(editorWidget->position() + 1); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                         if (MatchingText::shouldInsertMatchingText(lookAhead)) { | 
					
						
							|  |  |  |                             extraChars += QLatin1Char(')'); | 
					
						
							|  |  |  |                             --cursorOffset; | 
					
						
							|  |  |  |                             if (endWithSemicolon) { | 
					
						
							|  |  |  |                                 extraChars += semicolon; | 
					
						
							|  |  |  |                                 --cursorOffset; | 
					
						
							|  |  |  |                                 m_typedChar = QChar(); | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                         // TODO: When an opening parenthesis exists, the "semicolon" should really be
 | 
					
						
							|  |  |  |                         // inserted after the matching closing parenthesis.
 | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (autoInsertBrackets && data().canConvert<CompleteFunctionDeclaration>()) { | 
					
						
							|  |  |  |             if (m_typedChar == QLatin1Char('(')) | 
					
						
							|  |  |  |                 m_typedChar = QChar(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             // everything from the closing parenthesis on are extra chars, to
 | 
					
						
							|  |  |  |             // make sure an auto-inserted ")" gets replaced by ") const" if necessary
 | 
					
						
							|  |  |  |             int closingParen = toInsert.lastIndexOf(QLatin1Char(')')); | 
					
						
							|  |  |  |             extraChars = toInsert.mid(closingParen); | 
					
						
							|  |  |  |             toInsert.truncate(closingParen); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Append an unhandled typed character, adjusting cursor offset when it had been adjusted before
 | 
					
						
							|  |  |  |     if (!m_typedChar.isNull()) { | 
					
						
							|  |  |  |         extraChars += m_typedChar; | 
					
						
							|  |  |  |         if (cursorOffset != 0) | 
					
						
							|  |  |  |             --cursorOffset; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-12 11:25:37 +02:00
										 |  |  |     // Determine the length of characters that should just be kept on the editor, but do
 | 
					
						
							|  |  |  |     // not consider content that ends as an identifier (which could be undesired).
 | 
					
						
							| 
									
										
										
										
											2014-09-30 17:45:48 +02:00
										 |  |  |     const int lineEnd = editorWidget->position(EndOfLinePosition); | 
					
						
							| 
									
										
										
										
											2014-09-03 22:45:33 +02:00
										 |  |  |     const QString inEditor = editorWidget->textAt(editorWidget->position(), lineEnd - editorWidget->position()); | 
					
						
							| 
									
										
										
										
											2012-06-26 14:51:13 +02:00
										 |  |  |     int preserveLength = 0; | 
					
						
							| 
									
										
										
										
											2012-06-12 11:25:37 +02:00
										 |  |  |     if (!inEditor.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2014-09-03 22:45:33 +02:00
										 |  |  |         preserveLength = toInsert.length() - (editorWidget->position() - basePosition); | 
					
						
							| 
									
										
										
										
											2012-06-12 11:25:37 +02:00
										 |  |  |         const int inEditorLength = inEditor.length(); | 
					
						
							| 
									
										
										
										
											2013-01-10 16:41:14 +01:00
										 |  |  |         while (preserveLength > 0) { | 
					
						
							| 
									
										
										
										
											2012-06-26 14:51:13 +02:00
										 |  |  |             if (inEditor.startsWith(toInsert.right(preserveLength)) | 
					
						
							|  |  |  |                     && (inEditorLength == preserveLength | 
					
						
							| 
									
										
										
										
											2014-05-08 09:48:27 -04:00
										 |  |  |                         || !CppTools::isValidIdentifierChar(inEditor.at(preserveLength)))) { | 
					
						
							| 
									
										
										
										
											2011-10-11 09:29:48 +08:00
										 |  |  |                 break; | 
					
						
							| 
									
										
										
										
											2012-06-26 14:51:13 +02:00
										 |  |  |             } | 
					
						
							|  |  |  |             --preserveLength; | 
					
						
							| 
									
										
										
										
											2011-10-11 09:29:48 +08:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2012-06-12 11:25:37 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     for (int i = 0; i < extraChars.length(); ++i) { | 
					
						
							|  |  |  |         const QChar a = extraChars.at(i); | 
					
						
							| 
									
										
										
										
											2014-09-03 22:45:33 +02:00
										 |  |  |         const QChar b = editorWidget->characterAt(editorWidget->position() + i + preserveLength); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (a == b) | 
					
						
							|  |  |  |             ++extraLength; | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     toInsert += extraChars; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Insert the remainder of the name
 | 
					
						
							| 
									
										
										
										
											2014-09-03 22:45:33 +02:00
										 |  |  |     const int length = editorWidget->position() - basePosition + preserveLength + extraLength; | 
					
						
							|  |  |  |     editorWidget->setCursorPosition(basePosition); | 
					
						
							|  |  |  |     editorWidget->replace(length, toInsert); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (cursorOffset) | 
					
						
							| 
									
										
										
										
											2014-09-03 22:45:33 +02:00
										 |  |  |         editorWidget->setCursorPosition(editorWidget->position() + cursorOffset); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // --------------------
 | 
					
						
							|  |  |  | // CppFunctionHintModel
 | 
					
						
							|  |  |  | // --------------------
 | 
					
						
							| 
									
										
										
										
											2014-08-27 11:57:32 +02:00
										 |  |  | class CppFunctionHintModel : public IFunctionHintProposalModel | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2011-05-26 12:10:08 +02:00
										 |  |  |     CppFunctionHintModel(QList<Function *> functionSymbols, | 
					
						
							|  |  |  |                          const QSharedPointer<TypeOfExpression> &typeOfExp) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         : m_functionSymbols(functionSymbols) | 
					
						
							|  |  |  |         , m_currentArg(-1) | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |         , m_typeOfExpression(typeOfExp) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:32:42 +02:00
										 |  |  |     void reset() override {} | 
					
						
							|  |  |  |     int size() const override { return m_functionSymbols.size(); } | 
					
						
							|  |  |  |     QString text(int index) const override; | 
					
						
							|  |  |  |     int activeArgument(const QString &prefix) const override; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     QList<Function *> m_functionSymbols; | 
					
						
							|  |  |  |     mutable int m_currentArg; | 
					
						
							| 
									
										
										
										
											2011-05-26 12:10:08 +02:00
										 |  |  |     QSharedPointer<TypeOfExpression> m_typeOfExpression; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | QString CppFunctionHintModel::text(int index) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     Overview overview; | 
					
						
							| 
									
										
										
										
											2012-10-10 22:09:44 +02:00
										 |  |  |     overview.showReturnTypes = true; | 
					
						
							|  |  |  |     overview.showArgumentNames = true; | 
					
						
							|  |  |  |     overview.markedArgument = m_currentArg + 1; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     Function *f = m_functionSymbols.at(index); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-10 22:09:44 +02:00
										 |  |  |     const QString prettyMethod = overview.prettyType(f->type(), f->name()); | 
					
						
							|  |  |  |     const int begin = overview.markedArgumentBegin; | 
					
						
							|  |  |  |     const int end = overview.markedArgumentEnd; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QString hintText; | 
					
						
							| 
									
										
										
										
											2014-08-28 17:33:47 +02:00
										 |  |  |     hintText += prettyMethod.left(begin).toHtmlEscaped(); | 
					
						
							| 
									
										
										
										
											2012-11-21 22:36:47 +02:00
										 |  |  |     hintText += QLatin1String("<b>"); | 
					
						
							| 
									
										
										
										
											2014-08-28 17:33:47 +02:00
										 |  |  |     hintText += prettyMethod.mid(begin, end - begin).toHtmlEscaped(); | 
					
						
							| 
									
										
										
										
											2012-11-21 22:36:47 +02:00
										 |  |  |     hintText += QLatin1String("</b>"); | 
					
						
							| 
									
										
										
										
											2014-08-28 17:33:47 +02:00
										 |  |  |     hintText += prettyMethod.mid(end).toHtmlEscaped(); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     return hintText; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int CppFunctionHintModel::activeArgument(const QString &prefix) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int argnr = 0; | 
					
						
							|  |  |  |     int parcount = 0; | 
					
						
							|  |  |  |     SimpleLexer tokenize; | 
					
						
							| 
									
										
										
										
											2014-11-06 09:35:29 +01:00
										 |  |  |     Tokens tokens = tokenize(prefix); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     for (int i = 0; i < tokens.count(); ++i) { | 
					
						
							|  |  |  |         const Token &tk = tokens.at(i); | 
					
						
							|  |  |  |         if (tk.is(T_LPAREN)) | 
					
						
							|  |  |  |             ++parcount; | 
					
						
							|  |  |  |         else if (tk.is(T_RPAREN)) | 
					
						
							|  |  |  |             --parcount; | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |         else if (!parcount && tk.is(T_COMMA)) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             ++argnr; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (parcount < 0) | 
					
						
							|  |  |  |         return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (argnr != m_currentArg) | 
					
						
							|  |  |  |         m_currentArg = argnr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return argnr; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ---------------------------
 | 
					
						
							| 
									
										
										
										
											2012-02-21 10:00:32 +01:00
										 |  |  | // InternalCompletionAssistProvider
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | // ---------------------------
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 10:00:32 +01:00
										 |  |  | IAssistProcessor *InternalCompletionAssistProvider::createProcessor() const | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  |     return new InternalCppCompletionAssistProcessor; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  | AssistInterface *InternalCompletionAssistProvider::createAssistInterface( | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |         const QString &filePath, | 
					
						
							|  |  |  |         const TextEditorWidget *textEditorWidget, | 
					
						
							|  |  |  |         const LanguageFeatures &languageFeatures, | 
					
						
							|  |  |  |         int position, | 
					
						
							|  |  |  |         AssistReason reason) const | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |     QTC_ASSERT(textEditorWidget, return 0); | 
					
						
							| 
									
										
										
										
											2014-04-10 11:13:37 -04:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |     return new CppCompletionAssistInterface(filePath, | 
					
						
							|  |  |  |                                             textEditorWidget, | 
					
						
							| 
									
										
										
										
											2015-09-01 17:34:07 +02:00
										 |  |  |                                             BuiltinEditorDocumentParser::get(filePath), | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |                                             languageFeatures, | 
					
						
							|  |  |  |                                             position, | 
					
						
							|  |  |  |                                             reason, | 
					
						
							| 
									
										
										
										
											2015-09-01 17:34:07 +02:00
										 |  |  |                                             CppModelManager::instance()->workingCopy()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // -----------------
 | 
					
						
							|  |  |  | // CppAssistProposal
 | 
					
						
							|  |  |  | // -----------------
 | 
					
						
							| 
									
										
										
										
											2014-08-27 11:57:32 +02:00
										 |  |  | class CppAssistProposal : public GenericProposal | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |     CppAssistProposal(int cursorPos, GenericProposalModel *model) | 
					
						
							| 
									
										
										
										
											2014-08-27 11:57:32 +02:00
										 |  |  |         : GenericProposal(cursorPos, model) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         , m_replaceDotForArrow(static_cast<CppAssistProposalModel *>(model)->m_replaceDotForArrow) | 
					
						
							|  |  |  |     {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-03 15:32:42 +02:00
										 |  |  |     bool isCorrective() const override { return m_replaceDotForArrow; } | 
					
						
							|  |  |  |     void makeCorrection(TextEditorWidget *editorWidget) override; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     bool m_replaceDotForArrow; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-26 11:37:54 +02:00
										 |  |  | void CppAssistProposal::makeCorrection(TextEditorWidget *editorWidget) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-09-03 22:45:33 +02:00
										 |  |  |     const int oldPosition = editorWidget->position(); | 
					
						
							|  |  |  |     editorWidget->setCursorPosition(basePosition() - 1); | 
					
						
							|  |  |  |     editorWidget->replace(1, QLatin1String("->")); | 
					
						
							|  |  |  |     editorWidget->setCursorPosition(oldPosition + 1); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     moveBasePosition(1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ConvertToCompletionItem: protected NameVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // The completion item.
 | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |     AssistProposalItem *_item; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // The current symbol.
 | 
					
						
							|  |  |  |     Symbol *_symbol; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // The pretty printer.
 | 
					
						
							|  |  |  |     Overview overview; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     ConvertToCompletionItem() | 
					
						
							|  |  |  |         : _item(0) | 
					
						
							|  |  |  |         , _symbol(0) | 
					
						
							| 
									
										
										
										
											2012-07-10 20:30:31 +04:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2012-10-10 22:09:44 +02:00
										 |  |  |         overview.showReturnTypes = true; | 
					
						
							|  |  |  |         overview.showArgumentNames = true; | 
					
						
							| 
									
										
										
										
											2012-07-10 20:30:31 +04:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |     AssistProposalItem *operator()(Symbol *symbol) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2013-04-07 17:48:16 +02:00
										 |  |  |         //using declaration can be qualified
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |         if (!symbol || !symbol->name() || (symbol->name()->isQualifiedNameId() | 
					
						
							|  |  |  |                                            && !symbol->asUsingDeclaration())) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |         AssistProposalItem *previousItem = switchCompletionItem(0); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         Symbol *previousSymbol = switchSymbol(symbol); | 
					
						
							|  |  |  |         accept(symbol->unqualifiedName()); | 
					
						
							|  |  |  |         if (_item) | 
					
						
							|  |  |  |             _item->setData(QVariant::fromValue(symbol)); | 
					
						
							|  |  |  |         (void) switchSymbol(previousSymbol); | 
					
						
							|  |  |  |         return switchCompletionItem(previousItem); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     Symbol *switchSymbol(Symbol *symbol) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Symbol *previousSymbol = _symbol; | 
					
						
							|  |  |  |         _symbol = symbol; | 
					
						
							|  |  |  |         return previousSymbol; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |     AssistProposalItem *switchCompletionItem(AssistProposalItem *item) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |         AssistProposalItem *previousItem = _item; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         _item = item; | 
					
						
							|  |  |  |         return previousItem; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |     AssistProposalItem *newCompletionItem(const Name *name) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |         AssistProposalItem *item = new CppAssistProposalItem; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         item->setText(overview.prettyName(name)); | 
					
						
							|  |  |  |         return item; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 19:23:20 +02:00
										 |  |  |     void visit(const Identifier *name) | 
					
						
							| 
									
										
										
										
											2012-07-10 20:30:31 +04:00
										 |  |  |     { | 
					
						
							|  |  |  |         _item = newCompletionItem(name); | 
					
						
							| 
									
										
										
											
												Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
  # skip ast (excluding paste, astpath, and canv'ast'imer)
  next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
  s = File.read(file)
  next if s.include?('qlalr')
  orig = s.dup
  s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
    res = $&
    if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
      res
    else
      res.gsub!('} else', 'else')
      res.gsub!(/\n +} *\n/m, "\n")
      res.gsub(/ *{$/, '')
    end
  }
  s.gsub!(/ *$/, '')
  File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
											
										 
											2013-01-08 03:32:53 +02:00
										 |  |  |         if (!_symbol->isScope() || _symbol->isFunction()) | 
					
						
							| 
									
										
										
										
											2012-07-10 20:30:31 +04:00
										 |  |  |             _item->setDetail(overview.prettyType(_symbol->type(), name)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 19:23:20 +02:00
										 |  |  |     void visit(const TemplateNameId *name) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         _item = newCompletionItem(name); | 
					
						
							| 
									
										
										
										
											2014-05-05 11:43:24 -04:00
										 |  |  |         _item->setText(QString::fromUtf8(name->identifier()->chars(), name->identifier()->size())); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 19:23:20 +02:00
										 |  |  |     void visit(const DestructorNameId *name) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     { _item = newCompletionItem(name); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 19:23:20 +02:00
										 |  |  |     void visit(const OperatorNameId *name) | 
					
						
							| 
									
										
										
										
											2012-07-10 20:30:31 +04:00
										 |  |  |     { | 
					
						
							|  |  |  |         _item = newCompletionItem(name); | 
					
						
							|  |  |  |         _item->setDetail(overview.prettyType(_symbol->type(), name)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 19:23:20 +02:00
										 |  |  |     void visit(const ConversionNameId *name) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     { _item = newCompletionItem(name); } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-17 19:23:20 +02:00
										 |  |  |     void visit(const QualifiedNameId *name) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     { _item = newCompletionItem(name->name()); } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Class *asClassOrTemplateClassType(FullySpecifiedType ty) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (Class *classTy = ty->asClassType()) | 
					
						
							|  |  |  |         return classTy; | 
					
						
							| 
									
										
										
										
											2013-07-17 00:01:45 +03:00
										 |  |  |     if (Template *templ = ty->asTemplateType()) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (Symbol *decl = templ->declaration()) | 
					
						
							|  |  |  |             return decl->asClass(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Scope *enclosingNonTemplateScope(Symbol *symbol) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (symbol) { | 
					
						
							|  |  |  |         if (Scope *scope = symbol->enclosingScope()) { | 
					
						
							|  |  |  |             if (Template *templ = scope->asTemplate()) | 
					
						
							|  |  |  |                 return templ->enclosingScope(); | 
					
						
							|  |  |  |             return scope; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Function *asFunctionOrTemplateFunctionType(FullySpecifiedType ty) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (Function *funTy = ty->asFunctionType()) | 
					
						
							|  |  |  |         return funTy; | 
					
						
							| 
									
										
										
										
											2013-07-17 00:01:45 +03:00
										 |  |  |     if (Template *templ = ty->asTemplateType()) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (Symbol *decl = templ->declaration()) | 
					
						
							|  |  |  |             return decl->asFunction(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-30 11:56:50 +02:00
										 |  |  | bool isQPrivateSignal(const Symbol *symbol) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!symbol) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     static Identifier qPrivateSignalIdentifier("QPrivateSignal", 14); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (FullySpecifiedType type = symbol->type()) { | 
					
						
							|  |  |  |         if (NamedType *namedType = type->asNamedType()) { | 
					
						
							|  |  |  |             if (const Name *name = namedType->name()) { | 
					
						
							| 
									
										
										
										
											2014-05-15 12:00:13 -04:00
										 |  |  |                 if (name->match(&qPrivateSignalIdentifier)) | 
					
						
							| 
									
										
										
										
											2013-07-30 11:56:50 +02:00
										 |  |  |                     return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  | QString createQt4SignalOrSlot(CPlusPlus::Function *function, const Overview &overview) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QString signature; | 
					
						
							|  |  |  |     signature += Overview().prettyName(function->name()); | 
					
						
							|  |  |  |     signature += QLatin1Char('('); | 
					
						
							|  |  |  |     for (unsigned i = 0, to = function->argumentCount(); i < to; ++i) { | 
					
						
							|  |  |  |         Symbol *arg = function->argumentAt(i); | 
					
						
							|  |  |  |         if (isQPrivateSignal(arg)) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         if (i != 0) | 
					
						
							|  |  |  |             signature += QLatin1Char(','); | 
					
						
							|  |  |  |         signature += overview.prettyType(arg->type()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     signature += QLatin1Char(')'); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QByteArray normalized = QMetaObject::normalizedSignature(signature.toUtf8()); | 
					
						
							|  |  |  |     return QString::fromUtf8(normalized, normalized.size()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  | QString createQt5SignalOrSlot(CPlusPlus::Function *function, const Overview &overview) | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QString text; | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |     text += overview.prettyName(function->name()); | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |     return text; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  | /*!
 | 
					
						
							|  |  |  |     \class BackwardsEater | 
					
						
							|  |  |  |     \brief Checks strings and expressions before given position. | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Similar to BackwardsScanner, but also can handle expressions. Ignores whitespace. | 
					
						
							|  |  |  | */ | 
					
						
							|  |  |  | class BackwardsEater | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     explicit BackwardsEater(const CppCompletionAssistInterface *assistInterface, int position) | 
					
						
							|  |  |  |         : m_position(position) | 
					
						
							|  |  |  |         , m_assistInterface(assistInterface) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool isPositionValid() const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return m_position >= 0; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool eatConnectOpenParenthesis() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return eatString(QLatin1String("(")) && eatString(QLatin1String("connect")); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool eatExpressionCommaAmpersand() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return eatString(QLatin1String("&")) && eatString(QLatin1String(",")) && eatExpression(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool eatConnectOpenParenthesisExpressionCommaAmpersandExpressionComma() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         return eatString(QLatin1String(",")) | 
					
						
							|  |  |  |             && eatExpression() | 
					
						
							|  |  |  |             && eatExpressionCommaAmpersand() | 
					
						
							|  |  |  |             && eatConnectOpenParenthesis(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     bool eatExpression() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!isPositionValid()) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         maybeEatWhitespace(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QTextCursor cursor(m_assistInterface->textDocument()); | 
					
						
							|  |  |  |         cursor.setPosition(m_position + 1); | 
					
						
							| 
									
										
										
										
											2015-02-26 09:14:38 +02:00
										 |  |  |         ExpressionUnderCursor expressionUnderCursor(m_assistInterface->languageFeatures()); | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |         const QString expression = expressionUnderCursor(cursor); | 
					
						
							|  |  |  |         if (expression.isEmpty()) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  |         m_position = m_position - expression.length(); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool eatString(const QString &string) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!isPositionValid()) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (string.isEmpty()) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         maybeEatWhitespace(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const int stringLength = string.length(); | 
					
						
							|  |  |  |         const int stringStart = m_position - (stringLength - 1); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (stringStart < 0) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (m_assistInterface->textAt(stringStart, stringLength) == string) { | 
					
						
							|  |  |  |             m_position = stringStart - 1; | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void maybeEatWhitespace() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         while (isPositionValid() && m_assistInterface->characterAt(m_position).isSpace()) | 
					
						
							|  |  |  |             --m_position; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     int m_position; | 
					
						
							|  |  |  |     const CppCompletionAssistInterface * const m_assistInterface; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool canCompleteConnectSignalAt2ndArgument(const CppCompletionAssistInterface *assistInterface, | 
					
						
							|  |  |  |                                            int startOfExpression) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BackwardsEater eater(assistInterface, startOfExpression); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return eater.isPositionValid() | 
					
						
							|  |  |  |         && eater.eatExpressionCommaAmpersand() | 
					
						
							|  |  |  |         && eater.eatConnectOpenParenthesis(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool canCompleteConnectSignalAt4thArgument(const CppCompletionAssistInterface *assistInterface, | 
					
						
							|  |  |  |                                            int startPosition) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BackwardsEater eater(assistInterface, startPosition); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return eater.isPositionValid() | 
					
						
							|  |  |  |         && eater.eatExpressionCommaAmpersand() | 
					
						
							|  |  |  |         && eater.eatConnectOpenParenthesisExpressionCommaAmpersandExpressionComma(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool canCompleteClassNameAt2ndOr4thConnectArgument( | 
					
						
							|  |  |  |         const CppCompletionAssistInterface *assistInterface, | 
					
						
							|  |  |  |         int startPosition) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BackwardsEater eater(assistInterface, startPosition); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!eater.isPositionValid()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return eater.eatConnectOpenParenthesis() | 
					
						
							|  |  |  |         || eater.eatConnectOpenParenthesisExpressionCommaAmpersandExpressionComma(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  | ClassOrNamespace *classOrNamespaceFromLookupItem(const LookupItem &lookupItem, | 
					
						
							|  |  |  |                                                  const LookupContext &context) | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     const Name *name = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (Symbol *d = lookupItem.declaration()) { | 
					
						
							|  |  |  |         if (Class *k = d->asClass()) | 
					
						
							|  |  |  |             name = k->name(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (!name) { | 
					
						
							|  |  |  |         FullySpecifiedType type = lookupItem.type().simplified(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (PointerType *pointerType = type->asPointerType()) | 
					
						
							|  |  |  |             type = pointerType->elementType().simplified(); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             return 0; // not a pointer or a reference to a pointer.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         NamedType *namedType = type->asNamedType(); | 
					
						
							|  |  |  |         if (!namedType) // not a class name.
 | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         name = namedType->name(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return name ? context.lookupType(name, lookupItem.scope()) : 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Class *classFromLookupItem(const LookupItem &lookupItem, const LookupContext &context) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |     ClassOrNamespace *b = classOrNamespaceFromLookupItem(lookupItem, context); | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |     if (!b) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     foreach (Symbol *s, b->symbols()) { | 
					
						
							|  |  |  |         if (Class *klass = s->asClass()) | 
					
						
							|  |  |  |             return klass; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const Name *minimalName(Symbol *symbol, Scope *targetScope, const LookupContext &context) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |     ClassOrNamespace *target = context.lookupType(targetScope); | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |     if (!target) | 
					
						
							|  |  |  |         target = context.globalNamespace(); | 
					
						
							|  |  |  |     return context.minimalName(symbol, target, context.bindings()->control().data()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | } // Anonymous
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | // ------------------------------------
 | 
					
						
							|  |  |  | // InternalCppCompletionAssistProcessor
 | 
					
						
							|  |  |  | // ------------------------------------
 | 
					
						
							|  |  |  | InternalCppCompletionAssistProcessor::InternalCppCompletionAssistProcessor() | 
					
						
							| 
									
										
										
										
											2015-01-16 10:48:09 +01:00
										 |  |  |     : m_model(new CppAssistProposalModel) | 
					
						
							| 
									
										
										
										
											2013-10-06 02:41:22 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | InternalCppCompletionAssistProcessor::~InternalCppCompletionAssistProcessor() | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | IAssistProposal * InternalCppCompletionAssistProcessor::perform(const AssistInterface *interface) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     m_interface.reset(static_cast<const CppCompletionAssistInterface *>(interface)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (interface->reason() != ExplicitlyInvoked && !accepts()) | 
					
						
							|  |  |  |         return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int index = startCompletionHelper(); | 
					
						
							|  |  |  |     if (index != -1) { | 
					
						
							|  |  |  |         if (m_hintProposal) | 
					
						
							|  |  |  |             return m_hintProposal; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return createContentProposal(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | bool InternalCppCompletionAssistProcessor::accepts() const | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     const int pos = m_interface->position(); | 
					
						
							|  |  |  |     unsigned token = T_EOF_SYMBOL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int start = startOfOperator(pos, &token, /*want function call=*/ true); | 
					
						
							|  |  |  |     if (start != pos) { | 
					
						
							|  |  |  |         if (token == T_POUND) { | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |             const int column = pos - m_interface->textDocument()->findBlock(start).position(); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             if (column != 1) | 
					
						
							|  |  |  |                 return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         // Trigger completion after three characters of a name have been typed, when not editing an existing name
 | 
					
						
							|  |  |  |         QChar characterUnderCursor = m_interface->characterAt(pos); | 
					
						
							| 
									
										
										
										
											2014-05-08 09:48:27 -04:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (!isValidIdentifierChar(characterUnderCursor)) { | 
					
						
							| 
									
										
										
										
											2010-07-15 18:22:44 +02:00
										 |  |  |             const int startOfName = findStartOfName(pos); | 
					
						
							| 
									
										
										
										
											2010-07-19 14:06:00 +02:00
										 |  |  |             if (pos - startOfName >= 3) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 const QChar firstCharacter = m_interface->characterAt(startOfName); | 
					
						
							| 
									
										
										
										
											2014-05-08 09:48:27 -04:00
										 |  |  |                 if (isValidFirstIdentifierChar(firstCharacter)) { | 
					
						
							| 
									
										
										
										
											2010-07-15 18:22:44 +02:00
										 |  |  |                     // Finally check that we're not inside a comment or string (code copied from startOfOperator)
 | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |                     QTextCursor tc(m_interface->textDocument()); | 
					
						
							| 
									
										
										
										
											2010-07-15 18:22:44 +02:00
										 |  |  |                     tc.setPosition(pos); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     SimpleLexer tokenize; | 
					
						
							| 
									
										
										
										
											2015-02-26 08:42:05 +02:00
										 |  |  |                     tokenize.setLanguageFeatures(m_interface->languageFeatures()); | 
					
						
							| 
									
										
										
										
											2010-07-15 18:22:44 +02:00
										 |  |  |                     tokenize.setSkipComments(false); | 
					
						
							| 
									
										
										
										
											2013-10-06 02:41:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-06 09:35:29 +01:00
										 |  |  |                     const Tokens &tokens = tokenize(tc.block().text(), BackwardsScanner::previousBlockState(tc.block())); | 
					
						
							| 
									
										
										
										
											2010-07-15 18:22:44 +02:00
										 |  |  |                     const int tokenIdx = SimpleLexer::tokenBefore(tokens, qMax(0, tc.positionInBlock() - 1)); | 
					
						
							|  |  |  |                     const Token tk = (tokenIdx == -1) ? Token() : tokens.at(tokenIdx); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-18 14:08:19 +02:00
										 |  |  |                     if (!tk.isComment() && !tk.isLiteral()) { | 
					
						
							| 
									
										
										
										
											2010-07-15 18:22:44 +02:00
										 |  |  |                         return true; | 
					
						
							| 
									
										
										
										
											2011-05-18 14:08:19 +02:00
										 |  |  |                     } else if (tk.isLiteral() | 
					
						
							|  |  |  |                                && tokens.size() == 3 | 
					
						
							|  |  |  |                                && tokens.at(0).kind() == T_POUND | 
					
						
							|  |  |  |                                && tokens.at(1).kind() == T_IDENTIFIER) { | 
					
						
							|  |  |  |                         const QString &line = tc.block().text(); | 
					
						
							|  |  |  |                         const Token &idToken = tokens.at(1); | 
					
						
							|  |  |  |                         const QStringRef &identifier = | 
					
						
							| 
									
										
										
										
											2013-12-12 21:37:46 +01:00
										 |  |  |                                 line.midRef(idToken.utf16charsBegin(), | 
					
						
							|  |  |  |                                             idToken.utf16charsEnd() - idToken.utf16charsBegin()); | 
					
						
							| 
									
										
										
										
											2011-05-18 14:08:19 +02:00
										 |  |  |                         if (identifier == QLatin1String("include") | 
					
						
							|  |  |  |                                 || identifier == QLatin1String("include_next") | 
					
						
							| 
									
										
										
										
											2015-02-26 08:42:05 +02:00
										 |  |  |                                 || (m_interface->languageFeatures().objCEnabled && identifier == QLatin1String("import"))) { | 
					
						
							| 
									
										
										
										
											2011-05-18 14:08:19 +02:00
										 |  |  |                             return true; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2010-07-15 18:22:44 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-07-14 12:37:49 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | IAssistProposal *InternalCppCompletionAssistProcessor::createContentProposal() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     // Duplicates are kept only if they are snippets.
 | 
					
						
							|  |  |  |     QSet<QString> processed; | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |     QList<AssistProposalItem *>::iterator it = m_completions.begin(); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     while (it != m_completions.end()) { | 
					
						
							|  |  |  |         CppAssistProposalItem *item = static_cast<CppAssistProposalItem *>(*it); | 
					
						
							|  |  |  |         if (!processed.contains(item->text()) || item->data().canConvert<QString>()) { | 
					
						
							|  |  |  |             ++it; | 
					
						
							|  |  |  |             if (!item->data().canConvert<QString>()) { | 
					
						
							|  |  |  |                 processed.insert(item->text()); | 
					
						
							|  |  |  |                 if (!item->isOverloaded()) { | 
					
						
							|  |  |  |                     if (Symbol *symbol = qvariant_cast<Symbol *>(item->data())) { | 
					
						
							|  |  |  |                         if (Function *funTy = symbol->type()->asFunctionType()) { | 
					
						
							|  |  |  |                             if (funTy->hasArguments()) | 
					
						
							|  |  |  |                                 item->markAsOverloaded(); | 
					
						
							| 
									
										
										
										
											2010-12-14 11:50:49 +01:00
										 |  |  |                         } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2010-12-14 11:50:49 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2011-09-07 14:02:31 +02:00
										 |  |  |             delete *it; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             it = m_completions.erase(it); | 
					
						
							| 
									
										
										
										
											2010-12-14 11:50:49 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-05-27 19:00:44 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-08-03 16:13:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     m_model->loadContent(m_completions); | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |     return new CppAssistProposal(m_positionForProposal, m_model.take()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-08-03 16:13:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | IAssistProposal *InternalCppCompletionAssistProcessor::createHintProposal( | 
					
						
							| 
									
										
										
										
											2015-02-04 17:01:07 +02:00
										 |  |  |     QList<Function *> functionSymbols) const | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     IFunctionHintProposalModel *model = | 
					
						
							|  |  |  |             new CppFunctionHintModel(functionSymbols, m_model->m_typeOfExpression); | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |     IAssistProposal *proposal = new FunctionHintProposal(m_positionForProposal, model); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     return proposal; | 
					
						
							| 
									
										
										
										
											2010-05-26 14:25:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | int InternalCppCompletionAssistProcessor::startOfOperator(int pos, | 
					
						
							|  |  |  |                                                           unsigned *kind, | 
					
						
							|  |  |  |                                                           bool wantFunctionCall) const | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     const QChar ch  = pos > -1 ? m_interface->characterAt(pos - 1) : QChar(); | 
					
						
							|  |  |  |     const QChar ch2 = pos >  0 ? m_interface->characterAt(pos - 2) : QChar(); | 
					
						
							|  |  |  |     const QChar ch3 = pos >  1 ? m_interface->characterAt(pos - 3) : QChar(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |     int start = pos - CppCompletionAssistProvider::activationSequenceChar(ch, ch2, ch3, kind, | 
					
						
							|  |  |  |         wantFunctionCall, /*wantQt5SignalSlots*/ true); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (start != pos) { | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |         QTextCursor tc(m_interface->textDocument()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         tc.setPosition(pos); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // Include completion: make sure the quote character is the first one on the line
 | 
					
						
							|  |  |  |         if (*kind == T_STRING_LITERAL) { | 
					
						
							|  |  |  |             QTextCursor s = tc; | 
					
						
							|  |  |  |             s.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |             QString sel = s.selectedText(); | 
					
						
							|  |  |  |             if (sel.indexOf(QLatin1Char('"')) < sel.length() - 1) { | 
					
						
							|  |  |  |                 *kind = T_EOF_SYMBOL; | 
					
						
							|  |  |  |                 start = pos; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (*kind == T_COMMA) { | 
					
						
							| 
									
										
										
										
											2015-02-26 09:14:38 +02:00
										 |  |  |             ExpressionUnderCursor expressionUnderCursor(m_interface->languageFeatures()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             if (expressionUnderCursor.startOfFunctionCall(tc) == -1) { | 
					
						
							|  |  |  |                 *kind = T_EOF_SYMBOL; | 
					
						
							|  |  |  |                 start = pos; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         SimpleLexer tokenize; | 
					
						
							| 
									
										
										
										
											2015-02-26 08:42:05 +02:00
										 |  |  |         tokenize.setLanguageFeatures(m_interface->languageFeatures()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         tokenize.setSkipComments(false); | 
					
						
							| 
									
										
										
										
											2014-11-06 09:35:29 +01:00
										 |  |  |         const Tokens &tokens = tokenize(tc.block().text(), BackwardsScanner::previousBlockState(tc.block())); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         const int tokenIdx = SimpleLexer::tokenBefore(tokens, qMax(0, tc.positionInBlock() - 1)); // get the token at the left of the cursor
 | 
					
						
							|  |  |  |         const Token tk = (tokenIdx == -1) ? Token() : tokens.at(tokenIdx); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |         if (*kind == T_AMPER && tokenIdx > 0) { | 
					
						
							|  |  |  |             const Token &previousToken = tokens.at(tokenIdx - 1); | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |             if (previousToken.kind() == T_COMMA) | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |                 start = pos - (tk.utf16charOffset - previousToken.utf16charOffset) - 1; | 
					
						
							|  |  |  |         } else if (*kind == T_DOXY_COMMENT && !(tk.is(T_DOXY_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             *kind = T_EOF_SYMBOL; | 
					
						
							|  |  |  |             start = pos; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // Don't complete in comments or strings, but still check for include completion
 | 
					
						
							| 
									
										
										
										
											2015-04-23 12:01:54 +02:00
										 |  |  |         else if (tk.is(T_COMMENT) || tk.is(T_CPP_COMMENT) | 
					
						
							|  |  |  |                  || tk.is(T_CPP_DOXY_COMMENT) || tk.is(T_DOXY_COMMENT) | 
					
						
							|  |  |  |                  || (tk.isLiteral() && (*kind != T_STRING_LITERAL | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                                      && *kind != T_ANGLE_STRING_LITERAL | 
					
						
							| 
									
										
										
										
											2012-10-04 13:13:12 +02:00
										 |  |  |                                      && *kind != T_SLASH | 
					
						
							|  |  |  |                                      && *kind != T_DOT))) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             *kind = T_EOF_SYMBOL; | 
					
						
							|  |  |  |             start = pos; | 
					
						
							|  |  |  |         // Include completion: can be triggered by slash, but only in a string
 | 
					
						
							| 
									
										
										
										
											2013-07-17 00:01:45 +03:00
										 |  |  |         } else if (*kind == T_SLASH && (tk.isNot(T_STRING_LITERAL) && tk.isNot(T_ANGLE_STRING_LITERAL))) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             *kind = T_EOF_SYMBOL; | 
					
						
							|  |  |  |             start = pos; | 
					
						
							| 
									
										
										
										
											2013-07-17 00:01:45 +03:00
										 |  |  |         } else if (*kind == T_LPAREN) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             if (tokenIdx > 0) { | 
					
						
							|  |  |  |                 const Token &previousToken = tokens.at(tokenIdx - 1); // look at the token at the left of T_LPAREN
 | 
					
						
							|  |  |  |                 switch (previousToken.kind()) { | 
					
						
							|  |  |  |                 case T_IDENTIFIER: | 
					
						
							|  |  |  |                 case T_GREATER: | 
					
						
							|  |  |  |                 case T_SIGNAL: | 
					
						
							|  |  |  |                 case T_SLOT: | 
					
						
							|  |  |  |                     break; // good
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 default: | 
					
						
							|  |  |  |                     // that's a bad token :)
 | 
					
						
							|  |  |  |                     *kind = T_EOF_SYMBOL; | 
					
						
							|  |  |  |                     start = pos; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // Check for include preprocessor directive
 | 
					
						
							| 
									
										
										
										
											2012-10-04 13:13:12 +02:00
										 |  |  |         else if (*kind == T_STRING_LITERAL || *kind == T_ANGLE_STRING_LITERAL|| *kind == T_SLASH | 
					
						
							|  |  |  |                  || (*kind == T_DOT && (tk.is(T_STRING_LITERAL) || tk.is(T_ANGLE_STRING_LITERAL)))) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             bool include = false; | 
					
						
							|  |  |  |             if (tokens.size() >= 3) { | 
					
						
							|  |  |  |                 if (tokens.at(0).is(T_POUND) && tokens.at(1).is(T_IDENTIFIER) && (tokens.at(2).is(T_STRING_LITERAL) || | 
					
						
							|  |  |  |                                                                                   tokens.at(2).is(T_ANGLE_STRING_LITERAL))) { | 
					
						
							|  |  |  |                     const Token &directiveToken = tokens.at(1); | 
					
						
							| 
									
										
										
										
											2013-12-12 21:37:46 +01:00
										 |  |  |                     QString directive = tc.block().text().mid(directiveToken.utf16charsBegin(), | 
					
						
							|  |  |  |                                                               directiveToken.utf16chars()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     if (directive == QLatin1String("include") || | 
					
						
							|  |  |  |                             directive == QLatin1String("include_next") || | 
					
						
							|  |  |  |                             directive == QLatin1String("import")) { | 
					
						
							|  |  |  |                         include = true; | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |             if (!include) { | 
					
						
							|  |  |  |                 *kind = T_EOF_SYMBOL; | 
					
						
							|  |  |  |                 start = pos; | 
					
						
							| 
									
										
										
										
											2012-10-04 13:13:12 +02:00
										 |  |  |             } else { | 
					
						
							|  |  |  |                 if (*kind == T_DOT) { | 
					
						
							|  |  |  |                     start = findStartOfName(start); | 
					
						
							|  |  |  |                     const QChar ch4  = start > -1 ? m_interface->characterAt(start - 1) : QChar(); | 
					
						
							|  |  |  |                     const QChar ch5 = start >  0 ? m_interface->characterAt(start - 2) : QChar(); | 
					
						
							|  |  |  |                     const QChar ch6 = start >  1 ? m_interface->characterAt(start - 3) : QChar(); | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |                     start = start - CppCompletionAssistProvider::activationSequenceChar( | 
					
						
							|  |  |  |                                         ch4, ch5, ch6, kind, wantFunctionCall, false); | 
					
						
							| 
									
										
										
										
											2012-10-04 13:13:12 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return start; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | int InternalCppCompletionAssistProcessor::findStartOfName(int pos) const | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     if (pos == -1) | 
					
						
							|  |  |  |         pos = m_interface->position(); | 
					
						
							|  |  |  |     QChar chr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Skip to the start of a name
 | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         chr = m_interface->characterAt(--pos); | 
					
						
							| 
									
										
										
										
											2014-05-08 09:48:27 -04:00
										 |  |  |     } while (CppTools::isValidIdentifierChar(chr)); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return pos + 1; | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | int InternalCppCompletionAssistProcessor::startCompletionHelper() | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-26 08:42:05 +02:00
										 |  |  |     if (m_interface->languageFeatures().objCEnabled) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (tryObjCCompletion()) | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int startOfName = findStartOfName(); | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |     m_positionForProposal = startOfName; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     m_model->m_completionOperator = T_EOF_SYMBOL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |     int endOfOperator = m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // Skip whitespace preceding this position
 | 
					
						
							|  |  |  |     while (m_interface->characterAt(endOfOperator - 1).isSpace()) | 
					
						
							|  |  |  |         --endOfOperator; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int endOfExpression = startOfOperator(endOfOperator, | 
					
						
							|  |  |  |                                           &m_model->m_completionOperator, | 
					
						
							|  |  |  |                                           /*want function call =*/ true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_model->m_completionOperator == T_DOXY_COMMENT) { | 
					
						
							|  |  |  |         for (int i = 1; i < T_DOXY_LAST_TAG; ++i) | 
					
						
							|  |  |  |             addCompletionItem(QString::fromLatin1(doxygenTagSpell(i)), m_icons.keywordIcon()); | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |         return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Pre-processor completion
 | 
					
						
							|  |  |  |     if (m_model->m_completionOperator == T_POUND) { | 
					
						
							|  |  |  |         completePreprocessor(); | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |         m_positionForProposal = startOfName; | 
					
						
							|  |  |  |         return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Include completion
 | 
					
						
							|  |  |  |     if (m_model->m_completionOperator == T_STRING_LITERAL | 
					
						
							|  |  |  |         || m_model->m_completionOperator == T_ANGLE_STRING_LITERAL | 
					
						
							|  |  |  |         || m_model->m_completionOperator == T_SLASH) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |         QTextCursor c(m_interface->textDocument()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         c.setPosition(endOfExpression); | 
					
						
							|  |  |  |         if (completeInclude(c)) | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             m_positionForProposal = endOfExpression + 1; | 
					
						
							|  |  |  |         return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-26 09:14:38 +02:00
										 |  |  |     ExpressionUnderCursor expressionUnderCursor(m_interface->languageFeatures()); | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |     QTextCursor tc(m_interface->textDocument()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     if (m_model->m_completionOperator == T_COMMA) { | 
					
						
							|  |  |  |         tc.setPosition(endOfExpression); | 
					
						
							|  |  |  |         const int start = expressionUnderCursor.startOfFunctionCall(tc); | 
					
						
							|  |  |  |         if (start == -1) { | 
					
						
							|  |  |  |             m_model->m_completionOperator = T_EOF_SYMBOL; | 
					
						
							|  |  |  |             return -1; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         endOfExpression = start; | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |         m_positionForProposal = start + 1; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         m_model->m_completionOperator = T_LPAREN; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString expression; | 
					
						
							|  |  |  |     int startOfExpression = m_interface->position(); | 
					
						
							|  |  |  |     tc.setPosition(endOfExpression); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_model->m_completionOperator) { | 
					
						
							|  |  |  |         expression = expressionUnderCursor(tc); | 
					
						
							|  |  |  |         startOfExpression = endOfExpression - expression.length(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |         if (m_model->m_completionOperator == T_AMPER) { | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |             // We expect 'expression' to be either "sender" or "receiver" in
 | 
					
						
							|  |  |  |             //  "connect(sender, &" or
 | 
					
						
							|  |  |  |             //  "connect(otherSender, &Foo::signal1, receiver, &"
 | 
					
						
							|  |  |  |             const int beforeExpression = startOfExpression - 1; | 
					
						
							| 
									
										
										
										
											2015-04-07 16:12:57 +02:00
										 |  |  |             if (canCompleteClassNameAt2ndOr4thConnectArgument(m_interface.data(), | 
					
						
							|  |  |  |                                                               beforeExpression)) { | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |                 m_model->m_completionOperator = CompleteQt5SignalOrSlotClassNameTrigger; | 
					
						
							| 
									
										
										
										
											2015-04-07 16:12:57 +02:00
										 |  |  |             } else { // Ensure global completion
 | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |                 startOfExpression = endOfExpression = m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2015-04-07 16:12:57 +02:00
										 |  |  |                 expression.clear(); | 
					
						
							|  |  |  |                 m_model->m_completionOperator = T_EOF_SYMBOL; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |         } else if (m_model->m_completionOperator == T_COLON_COLON) { | 
					
						
							|  |  |  |             // We expect 'expression' to be "Foo" in
 | 
					
						
							|  |  |  |             //  "connect(sender, &Foo::" or
 | 
					
						
							|  |  |  |             //  "connect(sender, &Bar::signal1, receiver, &Foo::"
 | 
					
						
							|  |  |  |             const int beforeExpression = startOfExpression - 1; | 
					
						
							|  |  |  |             if (canCompleteConnectSignalAt2ndArgument(m_interface.data(), beforeExpression)) | 
					
						
							|  |  |  |                 m_model->m_completionOperator = CompleteQt5SignalTrigger; | 
					
						
							|  |  |  |             else if (canCompleteConnectSignalAt4thArgument(m_interface.data(), beforeExpression)) | 
					
						
							|  |  |  |                 m_model->m_completionOperator = CompleteQt5SlotTrigger; | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |         } else if (m_model->m_completionOperator == T_LPAREN) { | 
					
						
							| 
									
										
										
										
											2013-07-17 00:01:45 +03:00
										 |  |  |             if (expression.endsWith(QLatin1String("SIGNAL"))) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 m_model->m_completionOperator = T_SIGNAL; | 
					
						
							| 
									
										
										
										
											2013-07-17 00:01:45 +03:00
										 |  |  |             } else if (expression.endsWith(QLatin1String("SLOT"))) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 m_model->m_completionOperator = T_SLOT; | 
					
						
							| 
									
										
										
										
											2013-07-17 00:01:45 +03:00
										 |  |  |             } else if (m_interface->position() != endOfOperator) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 // We don't want a function completion when the cursor isn't at the opening brace
 | 
					
						
							|  |  |  |                 expression.clear(); | 
					
						
							|  |  |  |                 m_model->m_completionOperator = T_EOF_SYMBOL; | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |                 m_positionForProposal = startOfName; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 startOfExpression = m_interface->position(); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } else if (expression.isEmpty()) { | 
					
						
							|  |  |  |         while (startOfExpression > 0 && m_interface->characterAt(startOfExpression).isSpace()) | 
					
						
							|  |  |  |             --startOfExpression; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int line = 0, column = 0; | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |     Convenience::convertPosition(m_interface->textDocument(), startOfExpression, &line, &column); | 
					
						
							| 
									
										
										
										
											2013-03-18 14:58:46 +01:00
										 |  |  |     const QString fileName = m_interface->fileName(); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     return startCompletionInternal(fileName, line, column, expression, endOfExpression); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | bool InternalCppCompletionAssistProcessor::tryObjCCompletion() | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     int end = m_interface->position(); | 
					
						
							|  |  |  |     while (m_interface->characterAt(end).isSpace()) | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |         ++end; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (m_interface->characterAt(end) != QLatin1Char(']')) | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |     QTextCursor tc(m_interface->textDocument()); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |     tc.setPosition(end); | 
					
						
							| 
									
										
										
										
											2015-02-26 09:14:38 +02:00
										 |  |  |     BackwardsScanner tokens(tc, m_interface->languageFeatures()); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |     if (tokens[tokens.startToken() - 1].isNot(T_RBRACKET)) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int start = tokens.startOfMatchingBrace(tokens.startToken()); | 
					
						
							|  |  |  |     if (start == tokens.startToken()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-13 18:41:15 +01:00
										 |  |  |     const int startPos = tokens[start].bytesBegin() + tokens.startPosition(); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     const QString expr = m_interface->textAt(startPos, m_interface->position() - startPos); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-18 14:58:46 +01:00
										 |  |  |     Document::Ptr thisDocument = m_interface->snapshot().document(m_interface->fileName()); | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |     if (!thisDocument) | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     m_model->m_typeOfExpression->init(thisDocument, m_interface->snapshot()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |     int line = 0, column = 0; | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |     Convenience::convertPosition(m_interface->textDocument(), m_interface->position(), &line, &column); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |     Scope *scope = thisDocument->scopeAt(line, column); | 
					
						
							|  |  |  |     if (!scope) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-12 17:35:37 +01:00
										 |  |  |     const QList<LookupItem> items = (*m_model->m_typeOfExpression)(expr.toUtf8(), scope); | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     LookupContext lookupContext(thisDocument, m_interface->snapshot()); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     foreach (const LookupItem &item, items) { | 
					
						
							|  |  |  |         FullySpecifiedType ty = item.type().simplified(); | 
					
						
							|  |  |  |         if (ty->isPointerType()) { | 
					
						
							|  |  |  |             ty = ty->asPointerType()->elementType().simplified(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (NamedType *namedTy = ty->asNamedType()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |                 ClassOrNamespace *binding = lookupContext.lookupType(namedTy->name(), item.scope()); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |                 completeObjCMsgSend(binding, false); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (ObjCClass *clazz = ty->asObjCClassType()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |                 ClassOrNamespace *binding = lookupContext.lookupType(clazz->name(), item.scope()); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |                 completeObjCMsgSend(binding, true); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_completions.isEmpty()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |     m_positionForProposal = m_interface->position(); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-14 19:36:00 +02:00
										 |  |  | namespace { | 
					
						
							|  |  |  | enum CompletionOrder { | 
					
						
							|  |  |  |     // default order is 0
 | 
					
						
							|  |  |  |     FunctionArgumentsOrder = 2, | 
					
						
							|  |  |  |     FunctionLocalsOrder = 2, // includes local types
 | 
					
						
							|  |  |  |     PublicClassMemberOrder = 1, | 
					
						
							|  |  |  |     InjectedClassNameOrder = -1, | 
					
						
							|  |  |  |     MacrosOrder = -2, | 
					
						
							|  |  |  |     KeywordsOrder = -2 | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | void InternalCppCompletionAssistProcessor::addCompletionItem(const QString &text, | 
					
						
							|  |  |  |                                                              const QIcon &icon, | 
					
						
							|  |  |  |                                                              int order, | 
					
						
							|  |  |  |                                                              const QVariant &data) | 
					
						
							| 
									
										
										
										
											2010-05-26 14:25:01 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |     AssistProposalItem *item = new CppAssistProposalItem; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     item->setText(text); | 
					
						
							|  |  |  |     item->setIcon(icon); | 
					
						
							|  |  |  |     item->setOrder(order); | 
					
						
							|  |  |  |     item->setData(data); | 
					
						
							|  |  |  |     m_completions.append(item); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 17:01:07 +02:00
										 |  |  | void InternalCppCompletionAssistProcessor::addCompletionItem(Symbol *symbol, int order) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     ConvertToCompletionItem toCompletionItem; | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |     AssistProposalItem *item = toCompletionItem(symbol); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (item) { | 
					
						
							|  |  |  |         item->setIcon(m_icons.iconForSymbol(symbol)); | 
					
						
							| 
									
										
										
										
											2012-10-14 19:36:00 +02:00
										 |  |  |         item->setOrder(order); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         m_completions.append(item); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  | void InternalCppCompletionAssistProcessor::completeObjCMsgSend(ClassOrNamespace *binding, | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  |                                                                bool staticClassAccess) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     QList<Scope*> memberScopes; | 
					
						
							|  |  |  |     foreach (Symbol *s, binding->symbols()) { | 
					
						
							|  |  |  |         if (ObjCClass *c = s->asObjCClass()) | 
					
						
							|  |  |  |             memberScopes.append(c); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     foreach (Scope *scope, memberScopes) { | 
					
						
							|  |  |  |         for (unsigned i = 0; i < scope->memberCount(); ++i) { | 
					
						
							|  |  |  |             Symbol *symbol = scope->memberAt(i); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             if (ObjCMethod *method = symbol->type()->asObjCMethodType()) { | 
					
						
							|  |  |  |                 if (method->isStatic() == staticClassAccess) { | 
					
						
							|  |  |  |                     Overview oo; | 
					
						
							|  |  |  |                     const SelectorNameId *selectorName = | 
					
						
							|  |  |  |                             method->name()->asSelectorNameId(); | 
					
						
							|  |  |  |                     QString text; | 
					
						
							|  |  |  |                     QString data; | 
					
						
							|  |  |  |                     if (selectorName->hasArguments()) { | 
					
						
							|  |  |  |                         for (unsigned i = 0; i < selectorName->nameCount(); ++i) { | 
					
						
							|  |  |  |                             if (i > 0) | 
					
						
							|  |  |  |                                 text += QLatin1Char(' '); | 
					
						
							|  |  |  |                             Symbol *arg = method->argumentAt(i); | 
					
						
							| 
									
										
										
										
											2012-11-21 22:36:47 +02:00
										 |  |  |                             text += QString::fromUtf8(selectorName->nameAt(i)->identifier()->chars()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                             text += QLatin1Char(':'); | 
					
						
							| 
									
										
										
										
											2015-02-04 17:01:07 +02:00
										 |  |  |                             text += Snippet::kVariableDelimiter; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                             text += QLatin1Char('('); | 
					
						
							| 
									
										
										
										
											2012-10-16 12:53:21 +02:00
										 |  |  |                             text += oo.prettyType(arg->type()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                             text += QLatin1Char(')'); | 
					
						
							| 
									
										
										
										
											2012-10-16 12:53:21 +02:00
										 |  |  |                             text += oo.prettyName(arg->name()); | 
					
						
							| 
									
										
										
										
											2015-02-04 17:01:07 +02:00
										 |  |  |                             text += Snippet::kVariableDelimiter; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                         } | 
					
						
							|  |  |  |                     } else { | 
					
						
							| 
									
										
										
										
											2012-11-21 22:36:47 +02:00
										 |  |  |                         text = QString::fromUtf8(selectorName->identifier()->chars()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     } | 
					
						
							|  |  |  |                     data = text; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     if (!text.isEmpty()) | 
					
						
							|  |  |  |                         addCompletionItem(text, QIcon(), 0, QVariant::fromValue(data)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-02-20 12:55:01 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-20 12:55:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | bool InternalCppCompletionAssistProcessor::completeInclude(const QTextCursor &cursor) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     QString directoryPrefix; | 
					
						
							|  |  |  |     if (m_model->m_completionOperator == T_SLASH) { | 
					
						
							|  |  |  |         QTextCursor c = cursor; | 
					
						
							|  |  |  |         c.movePosition(QTextCursor::StartOfLine, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |         QString sel = c.selectedText(); | 
					
						
							|  |  |  |         int startCharPos = sel.indexOf(QLatin1Char('"')); | 
					
						
							|  |  |  |         if (startCharPos == -1) { | 
					
						
							|  |  |  |             startCharPos = sel.indexOf(QLatin1Char('<')); | 
					
						
							|  |  |  |             m_model->m_completionOperator = T_ANGLE_STRING_LITERAL; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             m_model->m_completionOperator = T_STRING_LITERAL; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         if (startCharPos != -1) | 
					
						
							|  |  |  |             directoryPrefix = sel.mid(startCharPos + 1, sel.length() - 1); | 
					
						
							| 
									
										
										
										
											2010-05-18 17:57:49 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     // Make completion for all relevant includes
 | 
					
						
							| 
									
										
										
										
											2014-06-25 17:23:19 +02:00
										 |  |  |     ProjectPart::HeaderPaths headerPaths = m_interface->headerPaths(); | 
					
						
							|  |  |  |     const ProjectPart::HeaderPath currentFilePath(QFileInfo(m_interface->fileName()).path(), | 
					
						
							|  |  |  |                                                    ProjectPart::HeaderPath::IncludePath); | 
					
						
							|  |  |  |     if (!headerPaths.contains(currentFilePath)) | 
					
						
							|  |  |  |         headerPaths.append(currentFilePath); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 09:32:46 +01:00
										 |  |  |     Utils::MimeDatabase mdb; | 
					
						
							|  |  |  |     const QStringList suffixes = mdb.mimeTypeForName(QLatin1String("text/x-c++hdr")).suffixes(); | 
					
						
							| 
									
										
										
										
											2011-05-18 12:28:53 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-06-25 17:23:19 +02:00
										 |  |  |     foreach (const ProjectPart::HeaderPath &headerPath, headerPaths) { | 
					
						
							|  |  |  |         QString realPath = headerPath.path; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (!directoryPrefix.isEmpty()) { | 
					
						
							|  |  |  |             realPath += QLatin1Char('/'); | 
					
						
							|  |  |  |             realPath += directoryPrefix; | 
					
						
							| 
									
										
										
										
											2014-06-25 17:23:19 +02:00
										 |  |  |             if (headerPath.isFrameworkPath()) | 
					
						
							|  |  |  |                 realPath += QLatin1String(".framework/Headers"); | 
					
						
							| 
									
										
										
										
											2009-03-26 12:37:40 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-05-18 12:28:53 +02:00
										 |  |  |         completeInclude(realPath, suffixes); | 
					
						
							| 
									
										
										
										
											2009-03-26 12:37:40 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     return !m_completions.isEmpty(); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-20 12:55:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | void InternalCppCompletionAssistProcessor::completeInclude(const QString &realPath, | 
					
						
							|  |  |  |                                                            const QStringList &suffixes) | 
					
						
							| 
									
										
										
										
											2011-05-18 12:28:53 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     QDirIterator i(realPath, QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); | 
					
						
							|  |  |  |     while (i.hasNext()) { | 
					
						
							|  |  |  |         const QString fileName = i.next(); | 
					
						
							|  |  |  |         const QFileInfo fileInfo = i.fileInfo(); | 
					
						
							|  |  |  |         const QString suffix = fileInfo.suffix(); | 
					
						
							|  |  |  |         if (suffix.isEmpty() || suffixes.contains(suffix)) { | 
					
						
							|  |  |  |             QString text = fileName.mid(realPath.length() + 1); | 
					
						
							|  |  |  |             if (fileInfo.isDir()) | 
					
						
							|  |  |  |                 text += QLatin1Char('/'); | 
					
						
							|  |  |  |             addCompletionItem(text, m_icons.keywordIcon()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | void InternalCppCompletionAssistProcessor::completePreprocessor() | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-01-16 10:48:09 +01:00
										 |  |  |     foreach (const QString &preprocessorCompletion, m_preprocessorCompletions) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         addCompletionItem(preprocessorCompletion); | 
					
						
							| 
									
										
										
										
											2009-02-20 12:55:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (objcKeywordsWanted()) | 
					
						
							|  |  |  |         addCompletionItem(QLatin1String("import")); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-02-20 12:55:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | bool InternalCppCompletionAssistProcessor::objcKeywordsWanted() const | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-02-26 08:42:05 +02:00
										 |  |  |     if (!m_interface->languageFeatures().objCEnabled) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2009-02-20 12:55:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-03-18 14:58:46 +01:00
										 |  |  |     const QString fileName = m_interface->fileName(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 09:32:46 +01:00
										 |  |  |     Utils::MimeDatabase mdb; | 
					
						
							|  |  |  |     const Utils::MimeType mt = mdb.mimeTypeForFile(fileName); | 
					
						
							|  |  |  |     return mt.matchesName(QLatin1String(CppTools::Constants::OBJECTIVE_C_SOURCE_MIMETYPE)) | 
					
						
							|  |  |  |             || mt.matchesName(QLatin1String(CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE)); | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | int InternalCppCompletionAssistProcessor::startCompletionInternal(const QString &fileName, | 
					
						
							|  |  |  |                                                                   unsigned line, unsigned column, | 
					
						
							|  |  |  |                                                                   const QString &expr, | 
					
						
							|  |  |  |                                                                   int endOfExpression) | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QString expression = expr.trimmed(); | 
					
						
							| 
									
										
										
										
											2008-12-12 10:07:58 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     Document::Ptr thisDocument = m_interface->snapshot().document(fileName); | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |     if (!thisDocument) | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  |         return -1; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     m_model->m_typeOfExpression->init(thisDocument, m_interface->snapshot()); | 
					
						
							| 
									
										
										
										
											2010-05-26 12:35:20 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     Scope *scope = thisDocument->scopeAt(line, column); | 
					
						
							| 
									
										
										
										
											2012-01-23 17:44:49 +01:00
										 |  |  |     QTC_ASSERT(scope != 0, return -1); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  |     if (expression.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (m_model->m_completionOperator == T_EOF_SYMBOL || m_model->m_completionOperator == T_COLON_COLON) { | 
					
						
							| 
									
										
										
										
											2012-01-12 17:35:37 +01:00
										 |  |  |             (void) (*m_model->m_typeOfExpression)(expression.toUtf8(), scope); | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             return globalCompletion(scope) ? m_positionForProposal : -1; | 
					
						
							| 
									
										
										
										
											2010-05-26 12:35:20 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-17 00:01:45 +03:00
										 |  |  |         if (m_model->m_completionOperator == T_SIGNAL || m_model->m_completionOperator == T_SLOT) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |             // Apply signal/slot completion on 'this'
 | 
					
						
							|  |  |  |             expression = QLatin1String("this"); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-12 17:35:37 +01:00
										 |  |  |     QByteArray utf8Exp = expression.toUtf8(); | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     QList<LookupItem> results = | 
					
						
							| 
									
										
										
										
											2012-01-12 17:35:37 +01:00
										 |  |  |             (*m_model->m_typeOfExpression)(utf8Exp, scope, TypeOfExpression::Preprocess); | 
					
						
							| 
									
										
										
										
											2010-05-12 14:52:24 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  |     if (results.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (m_model->m_completionOperator == T_SIGNAL || m_model->m_completionOperator == T_SLOT) { | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |             if (!(expression.isEmpty() || expression == QLatin1String("this"))) { | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  |                 expression = QLatin1String("this"); | 
					
						
							| 
									
										
										
										
											2012-01-12 17:35:37 +01:00
										 |  |  |                 results = (*m_model->m_typeOfExpression)(utf8Exp, scope); | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-02-17 12:12:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  |             if (results.isEmpty()) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							| 
									
										
										
										
											2009-02-17 12:12:14 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         } else if (m_model->m_completionOperator == T_LPAREN) { | 
					
						
							| 
									
										
										
										
											2009-02-04 16:40:42 +01:00
										 |  |  |             // Find the expression that precedes the current name
 | 
					
						
							|  |  |  |             int index = endOfExpression; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             while (m_interface->characterAt(index - 1).isSpace()) | 
					
						
							| 
									
										
										
										
											2009-02-04 16:40:42 +01:00
										 |  |  |                 --index; | 
					
						
							|  |  |  |             index = findStartOfName(index); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |             QTextCursor tc(m_interface->textDocument()); | 
					
						
							| 
									
										
										
										
											2009-02-04 16:40:42 +01:00
										 |  |  |             tc.setPosition(index); | 
					
						
							| 
									
										
										
										
											2009-10-16 12:22:33 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-26 09:14:38 +02:00
										 |  |  |             ExpressionUnderCursor expressionUnderCursor(m_interface->languageFeatures()); | 
					
						
							| 
									
										
										
										
											2009-10-16 12:22:33 +02:00
										 |  |  |             const QString baseExpression = expressionUnderCursor(tc); | 
					
						
							| 
									
										
										
										
											2009-02-04 16:40:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // Resolve the type of this expression
 | 
					
						
							| 
									
										
										
										
											2009-11-17 14:21:46 +01:00
										 |  |  |             const QList<LookupItem> results = | 
					
						
							| 
									
										
										
										
											2012-01-12 17:35:37 +01:00
										 |  |  |                     (*m_model->m_typeOfExpression)(baseExpression.toUtf8(), scope, | 
					
						
							| 
									
										
										
										
											2009-10-16 12:22:33 +02:00
										 |  |  |                                      TypeOfExpression::Preprocess); | 
					
						
							| 
									
										
										
										
											2009-02-04 16:40:42 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             // If it's a class, add completions for the constructors
 | 
					
						
							| 
									
										
										
										
											2009-11-17 14:21:46 +01:00
										 |  |  |             foreach (const LookupItem &result, results) { | 
					
						
							|  |  |  |                 if (result.type()->isClassType()) { | 
					
						
							| 
									
										
										
										
											2010-05-17 16:27:54 +02:00
										 |  |  |                     if (completeConstructorOrFunction(results, endOfExpression, true)) | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |                         return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-04 16:40:42 +01:00
										 |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  |             return -1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |         } else if (m_model->m_completionOperator == CompleteQt5SignalOrSlotClassNameTrigger) { | 
					
						
							|  |  |  |             // Fallback to global completion if we could not lookup sender/receiver object.
 | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             return globalCompletion(scope) ? m_positionForProposal : -1; | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             return -1; // nothing to do.
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     switch (m_model->m_completionOperator) { | 
					
						
							|  |  |  |     case T_LPAREN: | 
					
						
							|  |  |  |         if (completeConstructorOrFunction(results, endOfExpression, false)) | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     case T_DOT: | 
					
						
							|  |  |  |     case T_ARROW: | 
					
						
							|  |  |  |         if (completeMember(results)) | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     case T_COLON_COLON: | 
					
						
							|  |  |  |         if (completeScope(results)) | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     case T_SIGNAL: | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |         if (completeQtMethod(results, CompleteQt4Signals)) | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     case T_SLOT: | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |         if (completeQtMethod(results, CompleteQt4Slots)) | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |     case CompleteQt5SignalOrSlotClassNameTrigger: | 
					
						
							|  |  |  |         if (completeQtMethodClassName(results, scope) || globalCompletion(scope)) | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |     case CompleteQt5SignalTrigger: | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |         // Fallback to scope completion if "X::" is a namespace and not a class.
 | 
					
						
							|  |  |  |         if (completeQtMethod(results, CompleteQt5Signals) || completeScope(results)) | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |     case CompleteQt5SlotTrigger: | 
					
						
							|  |  |  |         // Fallback to scope completion if "X::" is a namespace and not a class.
 | 
					
						
							|  |  |  |         if (completeQtMethod(results, CompleteQt5Slots) || completeScope(results)) | 
					
						
							| 
									
										
										
										
											2015-05-08 15:48:17 +02:00
										 |  |  |             return m_positionForProposal; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         break; | 
					
						
							| 
									
										
										
										
											2011-01-19 16:39:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     default: | 
					
						
							|  |  |  |         break; | 
					
						
							|  |  |  |     } // end of switch
 | 
					
						
							| 
									
										
										
										
											2011-01-19 16:39:28 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     // nothing to do.
 | 
					
						
							|  |  |  |     return -1; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  | bool InternalCppCompletionAssistProcessor::globalCompletion(Scope *currentScope) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     const LookupContext &context = m_model->m_typeOfExpression->context(); | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (m_model->m_completionOperator == T_COLON_COLON) { | 
					
						
							|  |  |  |         completeNamespace(context.globalNamespace()); | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |         return !m_completions.isEmpty(); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |     QList<ClassOrNamespace *> usingBindings; | 
					
						
							|  |  |  |     ClassOrNamespace *currentBinding = 0; | 
					
						
							| 
									
										
										
										
											2009-11-02 10:31:44 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     for (Scope *scope = currentScope; scope; scope = scope->enclosingScope()) { | 
					
						
							| 
									
										
										
										
											2013-12-15 16:35:43 +02:00
										 |  |  |         if (Block *block = scope->asBlock()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |             if (ClassOrNamespace *binding = context.lookupType(scope)) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 for (unsigned i = 0; i < scope->memberCount(); ++i) { | 
					
						
							|  |  |  |                     Symbol *member = scope->memberAt(i); | 
					
						
							| 
									
										
										
										
											2013-12-15 16:35:43 +02:00
										 |  |  |                     if (member->isEnum()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |                         if (ClassOrNamespace *b = binding->findBlock(block)) | 
					
						
							| 
									
										
										
										
											2013-12-15 16:35:43 +02:00
										 |  |  |                             completeNamespace(b); | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |                     if (!member->name()) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                         continue; | 
					
						
							| 
									
										
										
										
											2013-07-17 00:01:45 +03:00
										 |  |  |                     if (UsingNamespaceDirective *u = member->asUsingNamespaceDirective()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |                         if (ClassOrNamespace *b = binding->lookupType(u->name())) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                             usingBindings.append(b); | 
					
						
							| 
									
										
										
										
											2014-03-14 08:24:54 +01:00
										 |  |  |                     } else if (Class *c = member->asClass()) { | 
					
						
							|  |  |  |                         if (c->name()->isAnonymousNameId()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |                             if (ClassOrNamespace *b = binding->findBlock(block)) | 
					
						
							| 
									
										
										
										
											2014-03-14 08:24:54 +01:00
										 |  |  |                                 completeClass(b); | 
					
						
							|  |  |  |                         } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         } else if (scope->isFunction() || scope->isClass() || scope->isNamespace()) { | 
					
						
							|  |  |  |             currentBinding = context.lookupType(scope); | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-11-09 10:10:31 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     for (Scope *scope = currentScope; scope; scope = scope->enclosingScope()) { | 
					
						
							|  |  |  |         if (scope->isBlock()) { | 
					
						
							| 
									
										
										
										
											2013-12-22 08:15:01 +02:00
										 |  |  |             for (unsigned i = 0; i < scope->memberCount(); ++i) | 
					
						
							| 
									
										
										
										
											2012-10-14 19:36:00 +02:00
										 |  |  |                 addCompletionItem(scope->memberAt(i), FunctionLocalsOrder); | 
					
						
							| 
									
										
										
										
											2013-12-22 08:14:47 +02:00
										 |  |  |         } else if (Function *fun = scope->asFunction()) { | 
					
						
							| 
									
										
										
										
											2013-12-22 08:15:01 +02:00
										 |  |  |             for (unsigned i = 0, argc = fun->argumentCount(); i < argc; ++i) | 
					
						
							| 
									
										
										
										
											2012-10-14 19:36:00 +02:00
										 |  |  |                 addCompletionItem(fun->argumentAt(i), FunctionArgumentsOrder); | 
					
						
							| 
									
										
										
										
											2013-12-22 08:14:47 +02:00
										 |  |  |         } else if (Template *templ = scope->asTemplate()) { | 
					
						
							| 
									
										
										
										
											2013-12-22 08:15:01 +02:00
										 |  |  |             for (unsigned i = 0, argc = templ->templateParameterCount(); i < argc; ++i) | 
					
						
							| 
									
										
										
										
											2013-04-04 11:27:06 +04:00
										 |  |  |                 addCompletionItem(templ->templateParameterAt(i), FunctionArgumentsOrder); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-19 12:15:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     for (; currentBinding; currentBinding = currentBinding->parent()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |         foreach (ClassOrNamespace* u, currentBinding->usings()) | 
					
						
							| 
									
										
										
										
											2013-09-03 22:51:53 +02:00
										 |  |  |             usingBindings.append(u); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         const QList<Symbol *> symbols = currentBinding->symbols(); | 
					
						
							| 
									
										
										
										
											2009-02-12 11:41:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |         if (!symbols.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2012-10-25 07:56:01 +02:00
										 |  |  |             if (symbols.first()->isClass()) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 completeClass(currentBinding); | 
					
						
							| 
									
										
										
										
											2012-10-25 07:56:01 +02:00
										 |  |  |             else | 
					
						
							|  |  |  |                 completeNamespace(currentBinding); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-03-26 11:14:05 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |     foreach (ClassOrNamespace *b, usingBindings) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         completeNamespace(b); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     addKeywords(); | 
					
						
							| 
									
										
										
										
											2014-09-15 00:12:27 +02:00
										 |  |  |     addMacros(CppModelManager::configurationFileName(), context.snapshot()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     addMacros(context.thisDocument()->fileName(), context.snapshot()); | 
					
						
							|  |  |  |     addSnippets(); | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |     return !m_completions.isEmpty(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 17:01:07 +02:00
										 |  |  | bool InternalCppCompletionAssistProcessor::completeMember(const QList<LookupItem> &baseResults) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     const LookupContext &context = m_model->m_typeOfExpression->context(); | 
					
						
							| 
									
										
										
										
											2010-05-17 16:27:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-10-16 11:08:06 +02:00
										 |  |  |     if (baseResults.isEmpty()) | 
					
						
							| 
									
										
										
										
											2008-12-29 11:53:40 +01:00
										 |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  |     ResolveExpression resolveExpression(context); | 
					
						
							| 
									
										
										
										
											2009-10-16 11:08:06 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-05-14 11:34:45 -04:00
										 |  |  |     bool *replaceDotForArrow = 0; | 
					
						
							| 
									
										
										
										
											2015-02-26 08:42:05 +02:00
										 |  |  |     if (!m_interface->languageFeatures().objCEnabled) | 
					
						
							| 
									
										
										
										
											2014-05-14 11:34:45 -04:00
										 |  |  |         replaceDotForArrow = &m_model->m_replaceDotForArrow; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |     if (ClassOrNamespace *binding = | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             resolveExpression.baseExpression(baseResults, | 
					
						
							|  |  |  |                                              m_model->m_completionOperator, | 
					
						
							| 
									
										
										
										
											2014-05-14 11:34:45 -04:00
										 |  |  |                                              replaceDotForArrow)) { | 
					
						
							| 
									
										
										
										
											2010-05-12 14:52:24 +02:00
										 |  |  |         if (binding) | 
					
						
							| 
									
										
										
										
											2012-11-19 12:04:49 +01:00
										 |  |  |             completeClass(binding, /*static lookup = */ true); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |         return !m_completions.isEmpty(); | 
					
						
							| 
									
										
										
										
											2009-11-04 18:21:35 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 17:01:07 +02:00
										 |  |  | bool InternalCppCompletionAssistProcessor::completeScope(const QList<LookupItem> &results) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     const LookupContext &context = m_model->m_typeOfExpression->context(); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |     if (results.isEmpty()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-02-01 14:00:07 +01:00
										 |  |  |     foreach (const LookupItem &result, results) { | 
					
						
							| 
									
										
										
										
											2009-11-17 14:21:46 +01:00
										 |  |  |         FullySpecifiedType ty = result.type(); | 
					
						
							| 
									
										
										
										
											2010-05-12 12:53:16 +02:00
										 |  |  |         Scope *scope = result.scope(); | 
					
						
							| 
									
										
										
										
											2008-12-30 11:35:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         if (NamedType *namedTy = ty->asNamedType()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |             if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) { | 
					
						
							| 
									
										
										
										
											2010-05-17 16:27:54 +02:00
										 |  |  |                 completeClass(b); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         } else if (Class *classTy = ty->asClassType()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |             if (ClassOrNamespace *b = context.lookupType(classTy)) { | 
					
						
							| 
									
										
										
										
											2010-05-17 16:27:54 +02:00
										 |  |  |                 completeClass(b); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-06-03 11:03:48 +02:00
										 |  |  |             // it can be class defined inside a block
 | 
					
						
							|  |  |  |             if (classTy->enclosingScope()->isBlock()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |                 if (ClassOrNamespace *b = context.lookupType(classTy->name(), classTy->enclosingScope())) { | 
					
						
							| 
									
										
										
										
											2013-06-03 11:03:48 +02:00
										 |  |  |                     completeClass(b); | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         } else if (Namespace *nsTy = ty->asNamespaceType()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |             if (ClassOrNamespace *b = context.lookupType(nsTy)) { | 
					
						
							| 
									
										
										
										
											2010-05-17 16:27:54 +02:00
										 |  |  |                 completeNamespace(b); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2009-02-18 15:56:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-07-19 14:35:43 +02:00
										 |  |  |         } else if (Template *templ = ty->asTemplateType()) { | 
					
						
							|  |  |  |             if (!result.binding()) | 
					
						
							|  |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |             if (ClassOrNamespace *b = result.binding()->lookupType(templ->name())) { | 
					
						
							| 
									
										
										
										
											2012-07-19 14:35:43 +02:00
										 |  |  |                 completeClass(b); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2012-10-25 07:56:01 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         } else if (Enum *e = ty->asEnumType()) { | 
					
						
							| 
									
										
										
										
											2013-06-03 11:03:48 +02:00
										 |  |  |             // it can be class defined inside a block
 | 
					
						
							|  |  |  |             if (e->enclosingScope()->isBlock()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |                 if (ClassOrNamespace *b = context.lookupType(e)) { | 
					
						
							| 
									
										
										
										
											2013-06-03 11:03:48 +02:00
										 |  |  |                     Block *block = e->enclosingScope()->asBlock(); | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |                     if (ClassOrNamespace *bb = b->findBlock(block)) { | 
					
						
							| 
									
										
										
										
											2013-06-03 11:03:48 +02:00
										 |  |  |                         completeNamespace(bb); | 
					
						
							|  |  |  |                         break; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |             if (ClassOrNamespace *b = context.lookupType(e)) { | 
					
						
							| 
									
										
										
										
											2012-10-25 07:56:01 +02:00
										 |  |  |                 completeNamespace(b); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2013-06-03 11:03:48 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-18 15:56:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |     return !m_completions.isEmpty(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  | void InternalCppCompletionAssistProcessor::completeNamespace(ClassOrNamespace *b) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |     QSet<ClassOrNamespace *> bindingsVisited; | 
					
						
							|  |  |  |     QList<ClassOrNamespace *> bindingsToVisit; | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |     bindingsToVisit.append(b); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |     while (!bindingsToVisit.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |         ClassOrNamespace *binding = bindingsToVisit.takeFirst(); | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |         if (!binding || bindingsVisited.contains(binding)) | 
					
						
							| 
									
										
										
										
											2009-12-08 12:43:40 +01:00
										 |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         bindingsVisited.insert(binding); | 
					
						
							|  |  |  |         bindingsToVisit += binding->usings(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         QList<Scope *> scopesToVisit; | 
					
						
							|  |  |  |         QSet<Scope *> scopesVisited; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach (Symbol *bb, binding->symbols()) { | 
					
						
							| 
									
										
										
										
											2012-10-25 07:56:01 +02:00
										 |  |  |             if (Scope *scope = bb->asScope()) | 
					
						
							|  |  |  |                 scopesToVisit.append(scope); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-22 08:15:01 +02:00
										 |  |  |         foreach (Enum *e, binding->unscopedEnums()) | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |             scopesToVisit.append(e); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |         while (!scopesToVisit.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |             Scope *scope = scopesToVisit.takeFirst(); | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |             if (!scope || scopesVisited.contains(scope)) | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             scopesVisited.insert(scope); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-13 17:29:34 +01:00
										 |  |  |             for (Scope::iterator it = scope->memberBegin(); it != scope->memberEnd(); ++it) { | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |                 Symbol *member = *it; | 
					
						
							|  |  |  |                 addCompletionItem(member); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  | void InternalCppCompletionAssistProcessor::completeClass(ClassOrNamespace *b, bool staticLookup) | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |     QSet<ClassOrNamespace *> bindingsVisited; | 
					
						
							|  |  |  |     QList<ClassOrNamespace *> bindingsToVisit; | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |     bindingsToVisit.append(b); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |     while (!bindingsToVisit.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |         ClassOrNamespace *binding = bindingsToVisit.takeFirst(); | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |         if (!binding || bindingsVisited.contains(binding)) | 
					
						
							| 
									
										
										
										
											2009-12-08 12:43:40 +01:00
										 |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         bindingsVisited.insert(binding); | 
					
						
							|  |  |  |         bindingsToVisit += binding->usings(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         QList<Scope *> scopesToVisit; | 
					
						
							|  |  |  |         QSet<Scope *> scopesVisited; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         foreach (Symbol *bb, binding->symbols()) { | 
					
						
							|  |  |  |             if (Class *k = bb->asClass()) | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |                 scopesToVisit.append(k); | 
					
						
							| 
									
										
										
										
											2014-03-14 08:24:54 +01:00
										 |  |  |             else if (Block *b = bb->asBlock()) | 
					
						
							|  |  |  |                 scopesToVisit.append(b); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-25 07:56:01 +02:00
										 |  |  |         foreach (Enum *e, binding->unscopedEnums()) | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |             scopesToVisit.append(e); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |         while (!scopesToVisit.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |             Scope *scope = scopesToVisit.takeFirst(); | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |             if (!scope || scopesVisited.contains(scope)) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |             scopesVisited.insert(scope); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-14 19:36:00 +02:00
										 |  |  |             if (staticLookup) | 
					
						
							|  |  |  |                 addCompletionItem(scope, InjectedClassNameOrder); // add a completion item for the injected class name.
 | 
					
						
							| 
									
										
										
										
											2010-06-02 13:59:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-11-24 21:02:26 +01:00
										 |  |  |             addClassMembersToCompletion(scope, staticLookup); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | void InternalCppCompletionAssistProcessor::addClassMembersToCompletion(Scope *scope, | 
					
						
							|  |  |  |                                                                        bool staticLookup) | 
					
						
							| 
									
										
										
										
											2013-11-24 21:02:26 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (!scope) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     std::set<Class *> nestedAnonymouses; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-13 17:29:34 +01:00
										 |  |  |     for (Scope::iterator it = scope->memberBegin(); it != scope->memberEnd(); ++it) { | 
					
						
							| 
									
										
										
										
											2013-11-24 21:02:26 +01:00
										 |  |  |         Symbol *member = *it; | 
					
						
							|  |  |  |         if (member->isFriend() | 
					
						
							|  |  |  |                 || member->isQtPropertyDeclaration() | 
					
						
							|  |  |  |                 || member->isQtEnum()) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } else if (!staticLookup && (member->isTypedef() || | 
					
						
							|  |  |  |                                     member->isEnum()    || | 
					
						
							|  |  |  |                                     member->isClass())) { | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  |         } else if (member->isClass() && member->name()->isAnonymousNameId()) { | 
					
						
							|  |  |  |             nestedAnonymouses.insert(member->asClass()); | 
					
						
							|  |  |  |         } else if (member->isDeclaration()) { | 
					
						
							|  |  |  |             Class *declTypeAsClass = member->asDeclaration()->type()->asClassType(); | 
					
						
							|  |  |  |             if (declTypeAsClass && declTypeAsClass->name()->isAnonymousNameId()) | 
					
						
							|  |  |  |                 nestedAnonymouses.erase(declTypeAsClass); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2013-11-24 21:02:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         if (member->isPublic()) | 
					
						
							|  |  |  |             addCompletionItem(member, PublicClassMemberOrder); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             addCompletionItem(member); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2013-11-24 21:02:26 +01:00
										 |  |  |     std::set<Class *>::const_iterator citEnd = nestedAnonymouses.end(); | 
					
						
							|  |  |  |     for (std::set<Class *>::const_iterator cit = nestedAnonymouses.begin(); cit != citEnd; ++cit) | 
					
						
							|  |  |  |         addClassMembersToCompletion(*cit, staticLookup); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  | bool InternalCppCompletionAssistProcessor::completeQtMethod(const QList<LookupItem> &results, | 
					
						
							|  |  |  |                                                             CompleteQtMethodMode type) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     if (results.isEmpty()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     const LookupContext &context = m_model->m_typeOfExpression->context(); | 
					
						
							| 
									
										
										
										
											2010-05-17 16:27:54 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     ConvertToCompletionItem toCompletionItem; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     Overview o; | 
					
						
							| 
									
										
										
										
											2012-10-10 22:09:44 +02:00
										 |  |  |     o.showReturnTypes = false; | 
					
						
							|  |  |  |     o.showArgumentNames = false; | 
					
						
							|  |  |  |     o.showFunctionSignatures = true; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QSet<QString> signatures; | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |     foreach (const LookupItem &lookupItem, results) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |         ClassOrNamespace *b = classOrNamespaceFromLookupItem(lookupItem, context); | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |         if (!b) | 
					
						
							| 
									
										
										
										
											2010-05-05 12:06:38 +02:00
										 |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |         QList<ClassOrNamespace *>todo; | 
					
						
							|  |  |  |         QSet<ClassOrNamespace *> processed; | 
					
						
							| 
									
										
										
										
											2010-05-26 15:44:01 +02:00
										 |  |  |         QList<Scope *> scopes; | 
					
						
							|  |  |  |         todo.append(b); | 
					
						
							|  |  |  |         while (!todo.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |             ClassOrNamespace *binding = todo.takeLast(); | 
					
						
							| 
									
										
										
										
											2010-05-26 15:44:01 +02:00
										 |  |  |             if (!processed.contains(binding)) { | 
					
						
							|  |  |  |                 processed.insert(binding); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-26 15:44:01 +02:00
										 |  |  |                 foreach (Symbol *s, binding->symbols()) | 
					
						
							|  |  |  |                     if (Class *clazz = s->asClass()) | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |                         scopes.append(clazz); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-26 15:44:01 +02:00
										 |  |  |                 todo.append(binding->usings()); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-05-06 10:36:11 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |         const bool wantSignals = type == CompleteQt4Signals || type == CompleteQt5Signals; | 
					
						
							|  |  |  |         const bool wantQt5SignalOrSlot = type == CompleteQt5Signals || type == CompleteQt5Slots; | 
					
						
							| 
									
										
										
										
											2010-05-26 15:44:01 +02:00
										 |  |  |         foreach (Scope *scope, scopes) { | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |             Class *klass = scope->asClass(); | 
					
						
							|  |  |  |             if (!klass) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |             for (unsigned i = 0; i < scope->memberCount(); ++i) { | 
					
						
							|  |  |  |                 Symbol *member = scope->memberAt(i); | 
					
						
							| 
									
										
										
										
											2009-02-09 17:44:06 +01:00
										 |  |  |                 Function *fun = member->type()->asFunctionType(); | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |                 if (!fun || fun->isGenerated()) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |                 if (wantSignals && !fun->isSignal()) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |                 else if (!wantSignals && type == CompleteQt4Slots && !fun->isSlot()) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-08 14:01:18 +02:00
										 |  |  |                 unsigned count = fun->argumentCount(); | 
					
						
							|  |  |  |                 while (true) { | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |                     const QString completionText = wantQt5SignalOrSlot | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |                             ? createQt5SignalOrSlot(fun, o) | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |                             : createQt4SignalOrSlot(fun, o); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |                     if (!signatures.contains(completionText)) { | 
					
						
							| 
									
										
										
										
											2014-09-04 00:04:18 +02:00
										 |  |  |                         AssistProposalItem *ci = toCompletionItem(fun); | 
					
						
							| 
									
										
										
										
											2011-09-08 14:01:18 +02:00
										 |  |  |                         if (!ci) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                             break; | 
					
						
							| 
									
										
										
										
											2015-02-16 11:49:07 +01:00
										 |  |  |                         signatures.insert(completionText); | 
					
						
							|  |  |  |                         ci->setText(completionText); // fix the completion item.
 | 
					
						
							| 
									
										
										
										
											2015-02-20 14:47:06 +01:00
										 |  |  |                         ci->setIcon(m_icons.iconForSymbol(fun)); | 
					
						
							| 
									
										
										
										
											2015-02-20 15:03:56 +01:00
										 |  |  |                         if (wantQt5SignalOrSlot && fun->isSlot()) | 
					
						
							|  |  |  |                             ci->setOrder(1); | 
					
						
							| 
									
										
										
										
											2011-09-08 14:01:18 +02:00
										 |  |  |                         m_completions.append(ci); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2011-09-08 14:01:18 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                     if (count && fun->argumentAt(count - 1)->asArgument()->hasInitializer()) | 
					
						
							|  |  |  |                         --count; | 
					
						
							|  |  |  |                     else | 
					
						
							|  |  |  |                         break; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |     return !m_completions.isEmpty(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  | bool InternalCppCompletionAssistProcessor::completeQtMethodClassName( | 
					
						
							|  |  |  |         const QList<LookupItem> &results, Scope *cursorScope) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTC_ASSERT(cursorScope, return false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (results.isEmpty()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const LookupContext &context = m_model->m_typeOfExpression->context(); | 
					
						
							| 
									
										
										
										
											2015-02-20 14:47:06 +01:00
										 |  |  |     const QIcon classIcon = m_icons.iconForType(Icons::ClassIconType); | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |     Overview overview; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     foreach (const LookupItem &lookupItem, results) { | 
					
						
							|  |  |  |         Class *klass = classFromLookupItem(lookupItem, context); | 
					
						
							| 
									
										
										
										
											2015-05-19 09:46:10 +02:00
										 |  |  |         if (!klass) | 
					
						
							|  |  |  |             continue; | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |         const Name *name = minimalName(klass, cursorScope, context); | 
					
						
							|  |  |  |         QTC_ASSERT(name, continue); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-20 14:47:06 +01:00
										 |  |  |         addCompletionItem(overview.prettyName(name), classIcon); | 
					
						
							| 
									
										
										
										
											2015-02-17 17:47:41 +01:00
										 |  |  |         break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return !m_completions.isEmpty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | void InternalCppCompletionAssistProcessor::addKeywords() | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     int keywordLimit = T_FIRST_OBJC_AT_KEYWORD; | 
					
						
							|  |  |  |     if (objcKeywordsWanted()) | 
					
						
							|  |  |  |         keywordLimit = T_LAST_OBJC_AT_KEYWORD + 1; | 
					
						
							| 
									
										
										
										
											2010-07-19 14:06:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     // keyword completion items.
 | 
					
						
							|  |  |  |     for (int i = T_FIRST_KEYWORD; i < keywordLimit; ++i) | 
					
						
							| 
									
										
										
										
											2012-10-14 19:36:00 +02:00
										 |  |  |         addCompletionItem(QLatin1String(Token::name(i)), m_icons.keywordIcon(), KeywordsOrder); | 
					
						
							| 
									
										
										
										
											2014-06-21 14:31:06 +04:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // primitive type completion items.
 | 
					
						
							|  |  |  |     for (int i = T_FIRST_PRIMITIVE; i <= T_LAST_PRIMITIVE; ++i) | 
					
						
							|  |  |  |         addCompletionItem(QLatin1String(Token::name(i)), m_icons.keywordIcon(), KeywordsOrder); | 
					
						
							| 
									
										
										
										
											2015-04-22 12:56:02 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     // "Identifiers with special meaning"
 | 
					
						
							|  |  |  |     if (m_interface->languageFeatures().cxx11Enabled) { | 
					
						
							|  |  |  |         addCompletionItem(QLatin1String("override"), m_icons.keywordIcon(), KeywordsOrder); | 
					
						
							|  |  |  |         addCompletionItem(QLatin1String("final"), m_icons.keywordIcon(), KeywordsOrder); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  | void InternalCppCompletionAssistProcessor::addMacros(const QString &fileName, | 
					
						
							| 
									
										
										
										
											2015-02-04 17:01:07 +02:00
										 |  |  |                                                      const Snapshot &snapshot) | 
					
						
							| 
									
										
										
										
											2009-12-02 12:11:49 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-28 12:51:12 +02:00
										 |  |  |     QSet<QString> processed; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     QSet<QString> definedMacros; | 
					
						
							| 
									
										
										
										
											2009-12-02 12:11:49 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     addMacros_helper(snapshot, fileName, &processed, &definedMacros); | 
					
						
							| 
									
										
										
										
											2010-05-28 12:51:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     foreach (const QString ¯oName, definedMacros) | 
					
						
							| 
									
										
										
										
											2012-10-14 19:36:00 +02:00
										 |  |  |         addCompletionItem(macroName, m_icons.macroIcon(), MacrosOrder); | 
					
						
							| 
									
										
										
										
											2010-05-28 12:51:12 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 17:01:07 +02:00
										 |  |  | void InternalCppCompletionAssistProcessor::addMacros_helper(const Snapshot &snapshot, | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                                                     const QString &fileName, | 
					
						
							|  |  |  |                                                     QSet<QString> *processed, | 
					
						
							|  |  |  |                                                     QSet<QString> *definedMacros) | 
					
						
							| 
									
										
										
										
											2010-07-09 15:12:44 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     Document::Ptr doc = snapshot.document(fileName); | 
					
						
							| 
									
										
										
										
											2010-07-09 15:12:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |     if (!doc || processed->contains(doc->fileName())) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         return; | 
					
						
							| 
									
										
										
										
											2010-07-09 15:12:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     processed->insert(doc->fileName()); | 
					
						
							| 
									
										
										
										
											2010-07-09 15:12:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-12-22 08:15:01 +02:00
										 |  |  |     foreach (const Document::Include &i, doc->resolvedIncludes()) | 
					
						
							| 
									
										
										
										
											2013-06-06 09:35:40 +02:00
										 |  |  |         addMacros_helper(snapshot, i.resolvedFileName(), processed, definedMacros); | 
					
						
							| 
									
										
										
										
											2010-07-09 15:12:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     foreach (const Macro ¯o, doc->definedMacros()) { | 
					
						
							| 
									
										
										
										
											2014-05-09 10:04:13 -04:00
										 |  |  |         const QString macroName = macro.nameToQString(); | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |         if (!macro.isHidden()) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             definedMacros->insert(macroName); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             definedMacros->remove(macroName); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-07-09 15:12:44 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-04 17:01:07 +02:00
										 |  |  | bool InternalCppCompletionAssistProcessor::completeConstructorOrFunction(const QList<LookupItem> &results, | 
					
						
							| 
									
										
										
										
											2015-01-16 10:35:23 +01:00
										 |  |  |                                                                          int endOfExpression, | 
					
						
							|  |  |  |                                                                          bool toolTipOnly) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     const LookupContext &context = m_model->m_typeOfExpression->context(); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     QList<Function *> functions; | 
					
						
							| 
									
										
										
										
											2010-07-14 12:37:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     foreach (const LookupItem &result, results) { | 
					
						
							|  |  |  |         FullySpecifiedType exprTy = result.type().simplified(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (Class *klass = asClassOrTemplateClassType(exprTy)) { | 
					
						
							|  |  |  |             const Name *className = klass->name(); | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |             if (!className) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 continue; // nothing to do for anonymous classes.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             for (unsigned i = 0; i < klass->memberCount(); ++i) { | 
					
						
							|  |  |  |                 Symbol *member = klass->memberAt(i); | 
					
						
							|  |  |  |                 const Name *memberName = member->name(); | 
					
						
							| 
									
										
										
										
											2009-09-16 16:48:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |                 if (!memberName) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     continue; // skip anonymous member.
 | 
					
						
							| 
									
										
										
										
											2009-07-23 16:46:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 else if (memberName->isQualifiedNameId()) | 
					
						
							|  |  |  |                     continue; // skip
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:12:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 if (Function *funTy = member->type()->asFunctionType()) { | 
					
						
							| 
									
										
										
										
											2014-05-15 12:00:13 -04:00
										 |  |  |                     if (memberName->match(className)) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                         // it's a ctor.
 | 
					
						
							|  |  |  |                         functions.append(funTy); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             break; | 
					
						
							| 
									
										
										
										
											2010-07-14 12:37:49 +02:00
										 |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (functions.isEmpty()) { | 
					
						
							|  |  |  |         foreach (const LookupItem &result, results) { | 
					
						
							|  |  |  |             FullySpecifiedType ty = result.type().simplified(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             if (Function *fun = asFunctionOrTemplateFunctionType(ty)) { | 
					
						
							| 
									
										
										
										
											2010-05-10 18:30:09 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |                 if (!fun->name()) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |                 } else if (!functions.isEmpty() | 
					
						
							|  |  |  |                            && enclosingNonTemplateScope(functions.first()) | 
					
						
							|  |  |  |                                 != enclosingNonTemplateScope(fun)) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     continue; // skip fun, it's an hidden declaration.
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 bool newOverload = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 foreach (Function *f, functions) { | 
					
						
							| 
									
										
										
										
											2014-05-15 12:00:13 -04:00
										 |  |  |                     if (fun->match(f)) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                         newOverload = false; | 
					
						
							|  |  |  |                         break; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2010-12-14 14:34:57 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 if (newOverload) | 
					
						
							|  |  |  |                     functions.append(fun); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (functions.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2013-03-20 13:48:20 +01:00
										 |  |  |         const Name *functionCallOp = context.bindings()->control()->operatorNameId(OperatorNameId::FunctionCallOp); | 
					
						
							| 
									
										
										
										
											2010-07-09 15:12:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         foreach (const LookupItem &result, results) { | 
					
						
							|  |  |  |             FullySpecifiedType ty = result.type().simplified(); | 
					
						
							|  |  |  |             Scope *scope = result.scope(); | 
					
						
							| 
									
										
										
										
											2009-09-16 16:48:14 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             if (NamedType *namedTy = ty->asNamedType()) { | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |                 if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     foreach (const LookupItem &r, b->lookup(functionCallOp)) { | 
					
						
							|  |  |  |                         Symbol *overload = r.declaration(); | 
					
						
							|  |  |  |                         FullySpecifiedType overloadTy = overload->type().simplified(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
											
												Remove braces for single lines of conditions
#!/usr/bin/env ruby
Dir.glob('**/*.cpp') { |file|
  # skip ast (excluding paste, astpath, and canv'ast'imer)
  next if file =~ /ast[^eip]|keywords\.|qualifiers|preprocessor|names.cpp/i
  s = File.read(file)
  next if s.include?('qlalr')
  orig = s.dup
  s.gsub!(/\n *if [^\n]*{\n[^\n]*\n\s+}(\s+else if [^\n]* {\n[^\n]*\n\s+})*(\s+else {\n[^\n]*\n\s+})?\n/m) { |m|
    res = $&
    if res =~ /^\s*(\/\/|[A-Z_]{3,})/ # C++ comment or macro (Q_UNUSED, SDEBUG), do not touch braces
      res
    else
      res.gsub!('} else', 'else')
      res.gsub!(/\n +} *\n/m, "\n")
      res.gsub(/ *{$/, '')
    end
  }
  s.gsub!(/ *$/, '')
  File.open(file, 'wb').write(s) if s != orig
}
Change-Id: I3b30ee60df0986f66c02132c65fc38a3fbb6bbdc
Reviewed-by: hjk <qthjk@ovi.com>
											
										 
											2013-01-08 03:32:53 +02:00
										 |  |  |                         if (Function *funTy = overloadTy->asFunctionType()) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                             functions.append(funTy); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-07-24 13:48:21 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     // There are two different kinds of completion we want to provide:
 | 
					
						
							|  |  |  |     // 1. If this is a function call, we want to pop up a tooltip that shows the user
 | 
					
						
							|  |  |  |     // the possible overloads with their argument types and names.
 | 
					
						
							|  |  |  |     // 2. If this is a function definition, we want to offer autocompletion of
 | 
					
						
							|  |  |  |     // the function signature.
 | 
					
						
							| 
									
										
										
										
											2010-07-09 15:12:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     // check if function signature autocompletion is appropriate
 | 
					
						
							|  |  |  |     // Also check if the function name is a destructor name.
 | 
					
						
							|  |  |  |     bool isDestructor = false; | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |     if (!functions.isEmpty() && !toolTipOnly) { | 
					
						
							| 
									
										
										
										
											2010-07-14 12:37:49 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         // function definitions will only happen in class or namespace scope,
 | 
					
						
							|  |  |  |         // so get the current location's enclosing scope.
 | 
					
						
							| 
									
										
										
										
											2009-07-23 16:46:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         // get current line and column
 | 
					
						
							|  |  |  |         int lineSigned = 0, columnSigned = 0; | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |         Convenience::convertPosition(m_interface->textDocument(), m_interface->position(), &lineSigned, &columnSigned); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         unsigned line = lineSigned, column = columnSigned; | 
					
						
							| 
									
										
										
										
											2009-07-24 13:48:21 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         // find a scope that encloses the current location, starting from the lastVisibileSymbol
 | 
					
						
							|  |  |  |         // and moving outwards
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         Scope *sc = context.thisDocument()->scopeAt(line, column); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (sc && (sc->isClass() || sc->isNamespace())) { | 
					
						
							|  |  |  |             // It may still be a function call. If the whole line parses as a function
 | 
					
						
							|  |  |  |             // declaration, we should be certain that it isn't.
 | 
					
						
							|  |  |  |             bool autocompleteSignature = false; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |             QTextCursor tc(m_interface->textDocument()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             tc.setPosition(endOfExpression); | 
					
						
							| 
									
										
										
										
											2015-02-26 09:14:38 +02:00
										 |  |  |             BackwardsScanner bs(tc, m_interface->languageFeatures()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             const int startToken = bs.startToken(); | 
					
						
							|  |  |  |             int lineStartToken = bs.startOfLine(startToken); | 
					
						
							|  |  |  |             // make sure the required tokens are actually available
 | 
					
						
							|  |  |  |             bs.LA(startToken - lineStartToken); | 
					
						
							| 
									
										
										
										
											2012-11-21 22:36:47 +02:00
										 |  |  |             QString possibleDecl = bs.mid(lineStartToken).trimmed().append(QLatin1String("();")); | 
					
						
							| 
									
										
										
										
											2008-12-08 13:01:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             Document::Ptr doc = Document::create(QLatin1String("<completion>")); | 
					
						
							| 
									
										
										
										
											2014-05-05 11:43:24 -04:00
										 |  |  |             doc->setUtf8Source(possibleDecl.toUtf8()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             if (doc->parse(Document::ParseDeclaration)) { | 
					
						
							|  |  |  |                 doc->check(); | 
					
						
							|  |  |  |                 if (SimpleDeclarationAST *sd = doc->translationUnit()->ast()->asSimpleDeclaration()) { | 
					
						
							| 
									
										
										
										
											2014-05-19 18:31:50 +03:00
										 |  |  |                     if (sd->declarator_list && sd->declarator_list->value->postfix_declarator_list | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                         && sd->declarator_list->value->postfix_declarator_list->value->asFunctionDeclarator()) { | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                         autocompleteSignature = true; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                         CoreDeclaratorAST *coreDecl = sd->declarator_list->value->core_declarator; | 
					
						
							|  |  |  |                         if (coreDecl && coreDecl->asDeclaratorId() && coreDecl->asDeclaratorId()->name) { | 
					
						
							|  |  |  |                             NameAST *declName = coreDecl->asDeclaratorId()->name; | 
					
						
							|  |  |  |                             if (declName->asDestructorName()) { | 
					
						
							|  |  |  |                                 isDestructor = true; | 
					
						
							|  |  |  |                             } else if (QualifiedNameAST *qName = declName->asQualifiedName()) { | 
					
						
							|  |  |  |                                 if (qName->unqualified_name && qName->unqualified_name->asDestructorName()) | 
					
						
							|  |  |  |                                     isDestructor = true; | 
					
						
							|  |  |  |                             } | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             if (autocompleteSignature && !isDestructor) { | 
					
						
							| 
									
										
										
										
											2011-08-04 10:54:12 +02:00
										 |  |  |                 // set up for rewriting function types with minimally qualified names
 | 
					
						
							|  |  |  |                 // to do it correctly we'd need the declaration's context and scope, but
 | 
					
						
							|  |  |  |                 // that'd be too expensive to get here. instead, we just minimize locally
 | 
					
						
							|  |  |  |                 SubstitutionEnvironment env; | 
					
						
							|  |  |  |                 env.setContext(context); | 
					
						
							|  |  |  |                 env.switchScope(sc); | 
					
						
							| 
									
										
										
										
											2015-11-19 13:49:26 +01:00
										 |  |  |                 ClassOrNamespace *targetCoN = context.lookupType(sc); | 
					
						
							| 
									
										
										
										
											2011-08-04 10:54:12 +02:00
										 |  |  |                 if (!targetCoN) | 
					
						
							|  |  |  |                     targetCoN = context.globalNamespace(); | 
					
						
							|  |  |  |                 UseMinimalNames q(targetCoN); | 
					
						
							|  |  |  |                 env.enter(&q); | 
					
						
							| 
									
										
										
										
											2013-03-20 13:48:20 +01:00
										 |  |  |                 Control *control = context.bindings()->control().data(); | 
					
						
							| 
									
										
										
										
											2011-08-04 10:54:12 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 // set up signature autocompletion
 | 
					
						
							|  |  |  |                 foreach (Function *f, functions) { | 
					
						
							|  |  |  |                     Overview overview; | 
					
						
							| 
									
										
										
										
											2012-10-10 22:09:44 +02:00
										 |  |  |                     overview.showArgumentNames = true; | 
					
						
							|  |  |  |                     overview.showDefaultArguments = false; | 
					
						
							| 
									
										
										
										
											2009-03-26 11:14:05 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-08-04 10:54:12 +02:00
										 |  |  |                     const FullySpecifiedType localTy = rewriteType(f->type(), &env, control); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     // gets: "parameter list) cv-spec",
 | 
					
						
							| 
									
										
										
										
											2014-11-28 15:08:03 +01:00
										 |  |  |                     const QString completion = overview.prettyType(localTy).mid(1); | 
					
						
							|  |  |  |                     if (completion == QLatin1String(")")) | 
					
						
							|  |  |  |                         continue; | 
					
						
							| 
									
										
										
										
											2009-10-09 15:22:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                     addCompletionItem(completion, QIcon(), 0, | 
					
						
							|  |  |  |                                       QVariant::fromValue(CompleteFunctionDeclaration(f))); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |                 return true; | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-09 15:22:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2013-07-24 11:59:39 +02:00
										 |  |  |     if (!functions.empty() && !isDestructor) { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         m_hintProposal = createHintProposal(functions); | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-10-09 15:22:57 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2010-09-24 20:16:34 +02:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-02-18 12:59:57 -03:00
										 |  |  | 
 | 
					
						
							|  |  |  | void CppCompletionAssistInterface::getCppSpecifics() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (m_gotCppSpecifics) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     m_gotCppSpecifics = true; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-01 17:34:07 +02:00
										 |  |  |     if (m_parser) { | 
					
						
							|  |  |  |         m_parser->update(BuiltinEditorDocumentParser::InMemoryInfo(false)); | 
					
						
							|  |  |  |         m_snapshot = m_parser->snapshot(); | 
					
						
							|  |  |  |         m_headerPaths = m_parser->headerPaths(); | 
					
						
							| 
									
										
										
										
											2014-02-18 12:59:57 -03:00
										 |  |  |     } | 
					
						
							|  |  |  | } |