| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | /****************************************************************************
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2012-10-02 09:12:39 +02:00
										 |  |  | ** Copyright (C) 2012 Digia Plc and/or its subsidiary(-ies). | 
					
						
							|  |  |  | ** Contact: http://www.qt-project.org/legal
 | 
					
						
							| 
									
										
										
										
											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 | 
					
						
							|  |  |  | ** a written agreement between you and Digia.  For licensing terms and | 
					
						
							|  |  |  | ** conditions see http://qt.digia.com/licensing.  For further information
 | 
					
						
							|  |  |  | ** use the contact form at http://qt.digia.com/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 | 
					
						
							|  |  |  | ** General Public License version 2.1 as published by the Free Software | 
					
						
							|  |  |  | ** Foundation and appearing in the file LICENSE.LGPL included in the | 
					
						
							|  |  |  | ** packaging of this file.  Please review the following information to | 
					
						
							|  |  |  | ** ensure the GNU Lesser General Public License version 2.1 requirements | 
					
						
							|  |  |  | ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
 | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** In addition, as a special exception, Digia gives you certain additional | 
					
						
							|  |  |  | ** rights.  These rights are described in the Digia Qt 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include "cppmodelmanager.h"
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | #include "cppcompletionassist.h"
 | 
					
						
							| 
									
										
										
										
											2009-02-20 12:55:01 +01:00
										 |  |  | #include "cppdoxygen.h"
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | #include "cppmodelmanager.h"
 | 
					
						
							| 
									
										
										
										
											2009-10-09 15:22:57 +02:00
										 |  |  | #include "cpptoolsconstants.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <Control.h>
 | 
					
						
							|  |  |  | #include <AST.h>
 | 
					
						
							|  |  |  | #include <ASTVisitor.h>
 | 
					
						
							|  |  |  | #include <CoreTypes.h>
 | 
					
						
							|  |  |  | #include <Literals.h>
 | 
					
						
							|  |  |  | #include <Names.h>
 | 
					
						
							|  |  |  | #include <NameVisitor.h>
 | 
					
						
							|  |  |  | #include <Symbols.h>
 | 
					
						
							|  |  |  | #include <SymbolVisitor.h>
 | 
					
						
							|  |  |  | #include <Scope.h>
 | 
					
						
							|  |  |  | #include <TranslationUnit.h>
 | 
					
						
							| 
									
										
										
										
											2011-08-04 10:54:12 +02:00
										 |  |  | #include <CppRewriter.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-09 15:25:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <cplusplus/ResolveExpression.h>
 | 
					
						
							| 
									
										
										
										
											2009-09-22 16:52:27 +02:00
										 |  |  | #include <cplusplus/MatchingText.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <cplusplus/Overview.h>
 | 
					
						
							|  |  |  | #include <cplusplus/ExpressionUnderCursor.h>
 | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | #include <cplusplus/BackwardsScanner.h>
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  | #include <cplusplus/LookupContext.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  | #include <coreplugin/idocument.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | #include <coreplugin/icore.h>
 | 
					
						
							| 
									
										
										
										
											2009-10-09 15:22:57 +02:00
										 |  |  | #include <coreplugin/mimedatabase.h>
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | #include <cppeditor/cppeditorconstants.h>
 | 
					
						
							|  |  |  | #include <texteditor/codeassist/basicproposalitem.h>
 | 
					
						
							|  |  |  | #include <texteditor/codeassist/basicproposalitemlistmodel.h>
 | 
					
						
							|  |  |  | #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>
 | 
					
						
							| 
									
										
										
										
											2012-01-23 17:44:49 +01:00
										 |  |  | #include <utils/qtcassert.h>
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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
										 |  |  | // ----------------------
 | 
					
						
							|  |  |  | // CppAssistProposalModel
 | 
					
						
							|  |  |  | // ----------------------
 | 
					
						
							|  |  |  | class CppAssistProposalModel : public TextEditor::BasicProposalItemListModel | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     CppAssistProposalModel() | 
					
						
							|  |  |  |         : TextEditor::BasicProposalItemListModel() | 
					
						
							|  |  |  |         , m_completionOperator(T_EOF_SYMBOL) | 
					
						
							|  |  |  |         , m_replaceDotForArrow(false) | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |         , m_typeOfExpression(new TypeOfExpression) | 
					
						
							| 
									
										
										
										
											2012-10-08 13:23:21 +02:00
										 |  |  |     { | 
					
						
							|  |  |  |         m_typeOfExpression->setExpandTemplates(true); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-20 12:55:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-10 12:58:05 +01:00
										 |  |  |     virtual bool isSortable(const QString &prefix) const; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     virtual IAssistProposalItem *proposalItem(int index) const; | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     unsigned m_completionOperator; | 
					
						
							|  |  |  |     bool m_replaceDotForArrow; | 
					
						
							| 
									
										
										
										
											2011-05-26 12:10:08 +02:00
										 |  |  |     QSharedPointer<TypeOfExpression> m_typeOfExpression; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | }; | 
					
						
							| 
									
										
										
										
											2011-02-21 14:02:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | // ---------------------
 | 
					
						
							|  |  |  | // CppAssistProposalItem
 | 
					
						
							|  |  |  | // ---------------------
 | 
					
						
							|  |  |  | class CppAssistProposalItem : public TextEditor::BasicProposalItem | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     virtual bool prematurelyApplies(const QChar &c) const; | 
					
						
							|  |  |  |     virtual void applyContextualContent(TextEditor::BaseTextEditor *editor, | 
					
						
							|  |  |  |                                         int basePosition) const; | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  |     unsigned m_completionOperator; | 
					
						
							|  |  |  |     mutable QChar m_typedChar; | 
					
						
							| 
									
										
										
										
											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(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | IAssistProposalItem *CppAssistProposalModel::proposalItem(int index) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     BasicProposalItem *item = | 
					
						
							|  |  |  |         static_cast<BasicProposalItem *>(BasicProposalItemListModel::proposalItem(index)); | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-10-05 10:46:06 +02:00
										 |  |  | static bool isDereferenced(TextEditor::BaseTextEditor *editor, int basePosition) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QTextCursor cursor = editor->editorWidget()->textCursor(); | 
					
						
							|  |  |  |     cursor.setPosition(basePosition); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BackwardsScanner scanner(cursor); | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppAssistProposalItem::applyContextualContent(TextEditor::BaseTextEditor *editor, | 
					
						
							|  |  |  |                                                     int basePosition) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     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(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const CompletionSettings &completionSettings = | 
					
						
							|  |  |  |                 TextEditorSettings::instance()->completionSettings(); | 
					
						
							|  |  |  |         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.
 | 
					
						
							|  |  |  |                 if (! function->hasReturnType() && (function->unqualifiedName() && !function->unqualifiedName()->isDestructorNameId())) { | 
					
						
							|  |  |  |                     // 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
 | 
					
						
							|  |  |  |                     if (function->argumentCount() == 0) { | 
					
						
							|  |  |  |                         extraChars += QLatin1Char('<'); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2011-10-05 10:46:06 +02:00
										 |  |  |                 } else if (!isDereferenced(editor, 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).
 | 
					
						
							|  |  |  |                     const QChar characterAtCursor = editor->characterAt(editor->position()); | 
					
						
							|  |  |  |                     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
 | 
					
						
							|  |  |  |                     if (!isOverloaded() && ! function->hasArguments() && skipClosingParenthesis) { | 
					
						
							|  |  |  |                         extraChars += QLatin1Char(')'); | 
					
						
							|  |  |  |                         if (endWithSemicolon) { | 
					
						
							|  |  |  |                             extraChars += semicolon; | 
					
						
							|  |  |  |                             m_typedChar = QChar(); | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } else if (autoParenthesesEnabled) { | 
					
						
							|  |  |  |                         const QChar lookAhead = editor->characterAt(editor->position() + 1); | 
					
						
							|  |  |  |                         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).
 | 
					
						
							|  |  |  |     const int lineEnd = editor->position(TextEditor::ITextEditor::EndOfLine); | 
					
						
							|  |  |  |     const QString inEditor = editor->textAt(editor->position(), lineEnd - editor->position()); | 
					
						
							| 
									
										
										
										
											2012-06-26 14:51:13 +02:00
										 |  |  |     int preserveLength = 0; | 
					
						
							| 
									
										
										
										
											2012-06-12 11:25:37 +02:00
										 |  |  |     if (!inEditor.isEmpty()) { | 
					
						
							| 
									
										
										
										
											2012-06-26 14:51:13 +02:00
										 |  |  |         preserveLength = toInsert.length() - (editor->position() - basePosition); | 
					
						
							| 
									
										
										
										
											2012-06-12 11:25:37 +02:00
										 |  |  |         const int inEditorLength = inEditor.length(); | 
					
						
							| 
									
										
										
										
											2012-06-26 14:51:13 +02:00
										 |  |  |         while (preserveLength) { | 
					
						
							|  |  |  |             if (inEditor.startsWith(toInsert.right(preserveLength)) | 
					
						
							|  |  |  |                     && (inEditorLength == preserveLength | 
					
						
							|  |  |  |                         || (!inEditor.at(preserveLength).isLetterOrNumber() | 
					
						
							|  |  |  |                             && inEditor.at(preserveLength) != QLatin1Char('_')))) { | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							| 
									
										
										
										
											2012-06-26 14:51:13 +02:00
										 |  |  |         const QChar b = editor->characterAt(editor->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
 | 
					
						
							| 
									
										
										
										
											2012-06-26 14:51:13 +02:00
										 |  |  |     const int length = editor->position() - basePosition + preserveLength + extraLength; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     editor->setCursorPosition(basePosition); | 
					
						
							|  |  |  |     editor->replace(length, toInsert); | 
					
						
							|  |  |  |     if (cursorOffset) | 
					
						
							|  |  |  |         editor->setCursorPosition(editor->position() + cursorOffset); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // --------------------
 | 
					
						
							|  |  |  | // CppFunctionHintModel
 | 
					
						
							|  |  |  | // --------------------
 | 
					
						
							|  |  |  | class CppFunctionHintModel : public TextEditor::IFunctionHintProposalModel | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 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
										 |  |  |     {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void reset() {} | 
					
						
							|  |  |  |     virtual int size() const { return m_functionSymbols.size(); } | 
					
						
							|  |  |  |     virtual QString text(int index) const; | 
					
						
							|  |  |  |     virtual int activeArgument(const QString &prefix) const; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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; | 
					
						
							|  |  |  |     overview.setShowReturnTypes(true); | 
					
						
							|  |  |  |     overview.setShowArgumentNames(true); | 
					
						
							|  |  |  |     overview.setMarkedArgument(m_currentArg + 1); | 
					
						
							|  |  |  |     Function *f = m_functionSymbols.at(index); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QString prettyMethod = overview(f->type(), f->name()); | 
					
						
							|  |  |  |     const int begin = overview.markedArgumentBegin(); | 
					
						
							|  |  |  |     const int end = overview.markedArgumentEnd(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString hintText; | 
					
						
							|  |  |  |     hintText += Qt::escape(prettyMethod.left(begin)); | 
					
						
							|  |  |  |     hintText += "<b>"; | 
					
						
							|  |  |  |     hintText += Qt::escape(prettyMethod.mid(begin, end - begin)); | 
					
						
							|  |  |  |     hintText += "</b>"; | 
					
						
							|  |  |  |     hintText += Qt::escape(prettyMethod.mid(end)); | 
					
						
							|  |  |  |     return hintText; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int CppFunctionHintModel::activeArgument(const QString &prefix) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     int argnr = 0; | 
					
						
							|  |  |  |     int parcount = 0; | 
					
						
							|  |  |  |     SimpleLexer tokenize; | 
					
						
							|  |  |  |     QList<Token> tokens = tokenize(prefix); | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  |         else if (! parcount && tk.is(T_COMMA)) | 
					
						
							|  |  |  |             ++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
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-21 10:00:32 +01:00
										 |  |  |     return new CppCompletionAssistProcessor; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 10:00:32 +01:00
										 |  |  | namespace { | 
					
						
							|  |  |  | class CppCompletionSupportInternal: public CppCompletionSupport | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-21 10:00:32 +01:00
										 |  |  | public: | 
					
						
							|  |  |  |     CppCompletionSupportInternal(TextEditor::ITextEditor *editor) | 
					
						
							|  |  |  |         : CppCompletionSupport(editor) | 
					
						
							|  |  |  |     {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual ~CppCompletionSupportInternal() | 
					
						
							|  |  |  |     {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual TextEditor::IAssistInterface *createAssistInterface(ProjectExplorer::Project *project, | 
					
						
							|  |  |  |                                                                 QTextDocument *document, | 
					
						
							|  |  |  |                                                                 int position, | 
					
						
							|  |  |  |                                                                 TextEditor::AssistReason reason) const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         CppModelManagerInterface *modelManager = CppModelManagerInterface::instance(); | 
					
						
							|  |  |  |         QStringList includePaths; | 
					
						
							|  |  |  |         QStringList frameworkPaths; | 
					
						
							|  |  |  |         if (project) { | 
					
						
							|  |  |  |             includePaths = modelManager->projectInfo(project).includePaths(); | 
					
						
							|  |  |  |             frameworkPaths = modelManager->projectInfo(project).frameworkPaths(); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         return new CppTools::Internal::CppCompletionAssistInterface( | 
					
						
							|  |  |  |                     document, | 
					
						
							|  |  |  |                     position, | 
					
						
							|  |  |  |                     editor()->document(), | 
					
						
							|  |  |  |                     reason, | 
					
						
							|  |  |  |                     modelManager->snapshot(), | 
					
						
							|  |  |  |                     includePaths, | 
					
						
							|  |  |  |                     frameworkPaths); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 10:00:32 +01:00
										 |  |  | CppCompletionSupport *InternalCompletionAssistProvider::completionSupport(ITextEditor *editor) | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-02-21 10:00:32 +01:00
										 |  |  |     return new CppCompletionSupportInternal(editor); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // -----------------
 | 
					
						
							|  |  |  | // CppAssistProposal
 | 
					
						
							|  |  |  | // -----------------
 | 
					
						
							|  |  |  | class CppAssistProposal : public TextEditor::GenericProposal | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     CppAssistProposal(int cursorPos, TextEditor::IGenericProposalModel *model) | 
					
						
							|  |  |  |         : TextEditor::GenericProposal(cursorPos, model) | 
					
						
							|  |  |  |         , m_replaceDotForArrow(static_cast<CppAssistProposalModel *>(model)->m_replaceDotForArrow) | 
					
						
							|  |  |  |     {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool isCorrective() const { return m_replaceDotForArrow; } | 
					
						
							|  |  |  |     virtual void makeCorrection(BaseTextEditor *editor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     bool m_replaceDotForArrow; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CppAssistProposal::makeCorrection(BaseTextEditor *editor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     editor->setCursorPosition(basePosition() - 1); | 
					
						
							|  |  |  |     editor->replace(1, QLatin1String("->")); | 
					
						
							|  |  |  |     moveBasePosition(1); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ConvertToCompletionItem: protected NameVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     // The completion item.
 | 
					
						
							|  |  |  |     BasicProposalItem *_item; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // The current symbol.
 | 
					
						
							|  |  |  |     Symbol *_symbol; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // The pretty printer.
 | 
					
						
							|  |  |  |     Overview overview; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     ConvertToCompletionItem() | 
					
						
							|  |  |  |         : _item(0) | 
					
						
							|  |  |  |         , _symbol(0) | 
					
						
							| 
									
										
										
										
											2012-07-10 20:30:31 +04:00
										 |  |  |     { | 
					
						
							|  |  |  |         overview.setShowReturnTypes(true); | 
					
						
							|  |  |  |         overview.setShowArgumentNames(true); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     BasicProposalItem *operator()(Symbol *symbol) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (! symbol || ! symbol->name() || symbol->name()->isQualifiedNameId()) | 
					
						
							|  |  |  |             return 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         BasicProposalItem *previousItem = switchCompletionItem(0); | 
					
						
							|  |  |  |         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; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BasicProposalItem *switchCompletionItem(BasicProposalItem *item) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         BasicProposalItem *previousItem = _item; | 
					
						
							|  |  |  |         _item = item; | 
					
						
							|  |  |  |         return previousItem; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     BasicProposalItem *newCompletionItem(const Name *name) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         BasicProposalItem *item = new CppAssistProposalItem; | 
					
						
							|  |  |  |         item->setText(overview.prettyName(name)); | 
					
						
							|  |  |  |         return item; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(const Identifier *name) | 
					
						
							| 
									
										
										
										
											2012-07-10 20:30:31 +04:00
										 |  |  |     { | 
					
						
							|  |  |  |         _item = newCompletionItem(name); | 
					
						
							|  |  |  |         if (!_symbol->isScope() || _symbol->isFunction()) { | 
					
						
							|  |  |  |             _item->setDetail(overview.prettyType(_symbol->type(), name)); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(const TemplateNameId *name) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         _item = newCompletionItem(name); | 
					
						
							|  |  |  |         _item->setText(QLatin1String(name->identifier()->chars())); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(const DestructorNameId *name) | 
					
						
							|  |  |  |     { _item = newCompletionItem(name); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual 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
										 |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(const ConversionNameId *name) | 
					
						
							|  |  |  |     { _item = newCompletionItem(name); } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual void visit(const QualifiedNameId *name) | 
					
						
							|  |  |  |     { _item = newCompletionItem(name->name()); } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | Class *asClassOrTemplateClassType(FullySpecifiedType ty) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (Class *classTy = ty->asClassType()) | 
					
						
							|  |  |  |         return classTy; | 
					
						
							|  |  |  |     else if (Template *templ = ty->asTemplateType()) { | 
					
						
							|  |  |  |         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; | 
					
						
							|  |  |  |     else if (Template *templ = ty->asTemplateType()) { | 
					
						
							|  |  |  |         if (Symbol *decl = templ->declaration()) | 
					
						
							|  |  |  |             return decl->asFunction(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // Anonymous
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // ----------------------------
 | 
					
						
							|  |  |  | // CppCompletionAssistProcessor
 | 
					
						
							|  |  |  | // ----------------------------
 | 
					
						
							|  |  |  | CppCompletionAssistProcessor::CppCompletionAssistProcessor() | 
					
						
							|  |  |  |     : m_startPosition(-1) | 
					
						
							|  |  |  |     , m_objcEnabled(true) | 
					
						
							|  |  |  |     , m_snippetCollector(CppEditor::Constants::CPP_SNIPPETS_GROUP_ID, | 
					
						
							|  |  |  |                          QIcon(QLatin1String(":/texteditor/images/snippet.png"))) | 
					
						
							|  |  |  |     , preprocessorCompletions(QStringList() | 
					
						
							|  |  |  |           << QLatin1String("define") | 
					
						
							|  |  |  |           << QLatin1String("error") | 
					
						
							|  |  |  |           << QLatin1String("include") | 
					
						
							|  |  |  |           << QLatin1String("line") | 
					
						
							|  |  |  |           << QLatin1String("pragma") | 
					
						
							|  |  |  |           << QLatin1String("undef") | 
					
						
							|  |  |  |           << QLatin1String("if") | 
					
						
							|  |  |  |           << QLatin1String("ifdef") | 
					
						
							|  |  |  |           << QLatin1String("ifndef") | 
					
						
							|  |  |  |           << QLatin1String("elif") | 
					
						
							|  |  |  |           << QLatin1String("else") | 
					
						
							|  |  |  |           << QLatin1String("endif")) | 
					
						
							|  |  |  |     , m_model(new CppAssistProposalModel) | 
					
						
							|  |  |  |     , m_hintProposal(0) | 
					
						
							|  |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CppCompletionAssistProcessor::~CppCompletionAssistProcessor() | 
					
						
							|  |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IAssistProposal * CppCompletionAssistProcessor::perform(const IAssistInterface *interface) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CppCompletionAssistProcessor::accepts() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     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); | 
					
						
							| 
									
										
										
										
											2011-05-26 11:29:25 +02:00
										 |  |  |         if (!characterUnderCursor.isLetterOrNumber() && characterUnderCursor != QLatin1Char('_')) { | 
					
						
							| 
									
										
										
										
											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); | 
					
						
							| 
									
										
										
										
											2010-07-15 18:22:44 +02:00
										 |  |  |                 if (firstCharacter.isLetter() || firstCharacter == QLatin1Char('_')) { | 
					
						
							|  |  |  |                     // 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; | 
					
						
							|  |  |  |                     tokenize.setQtMocRunEnabled(true); | 
					
						
							|  |  |  |                     tokenize.setObjCEnabled(true); | 
					
						
							|  |  |  |                     tokenize.setSkipComments(false); | 
					
						
							|  |  |  |                     const QList<Token> &tokens = tokenize(tc.block().text(), BackwardsScanner::previousBlockState(tc.block())); | 
					
						
							|  |  |  |                     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 = | 
					
						
							|  |  |  |                                 line.midRef(idToken.begin(), idToken.end() - idToken.begin()); | 
					
						
							|  |  |  |                         if (identifier == QLatin1String("include") | 
					
						
							|  |  |  |                                 || identifier == QLatin1String("include_next") | 
					
						
							|  |  |  |                                 || (m_objcEnabled && identifier == QLatin1String("import"))) { | 
					
						
							|  |  |  |                             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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | IAssistProposal *CppCompletionAssistProcessor::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; | 
					
						
							|  |  |  |     QList<BasicProposalItem *>::iterator it = m_completions.begin(); | 
					
						
							|  |  |  |     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); | 
					
						
							|  |  |  |     return new CppAssistProposal(m_startPosition, m_model.take()); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-08-03 16:13:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | IAssistProposal *CppCompletionAssistProcessor::createHintProposal( | 
					
						
							|  |  |  |     QList<CPlusPlus::Function *> functionSymbols) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-05-19 18:02:09 +02:00
										 |  |  |     IFunctionHintProposalModel *model = | 
					
						
							|  |  |  |             new CppFunctionHintModel(functionSymbols, m_model->m_typeOfExpression); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     IAssistProposal *proposal = new FunctionHintProposal(m_startPosition, model); | 
					
						
							|  |  |  |     return proposal; | 
					
						
							| 
									
										
										
										
											2010-05-26 14:25:01 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | int CppCompletionAssistProcessor::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(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-21 10:00:32 +01:00
										 |  |  |     int start = pos - CppCompletionAssistProvider::activationSequenceChar(ch, ch2, ch3, kind, wantFunctionCall); | 
					
						
							| 
									
										
										
										
											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) { | 
					
						
							|  |  |  |             ExpressionUnderCursor expressionUnderCursor; | 
					
						
							|  |  |  |             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; | 
					
						
							|  |  |  |         tokenize.setQtMocRunEnabled(true); | 
					
						
							|  |  |  |         tokenize.setObjCEnabled(true); | 
					
						
							|  |  |  |         tokenize.setSkipComments(false); | 
					
						
							|  |  |  |         const QList<Token> &tokens = tokenize(tc.block().text(), BackwardsScanner::previousBlockState(tc.block())); | 
					
						
							|  |  |  |         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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (*kind == T_DOXY_COMMENT && !(tk.is(T_DOXY_COMMENT) || tk.is(T_CPP_DOXY_COMMENT))) { | 
					
						
							|  |  |  |             *kind = T_EOF_SYMBOL; | 
					
						
							|  |  |  |             start = pos; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         // Don't complete in comments or strings, but still check for include completion
 | 
					
						
							|  |  |  |         else if (tk.is(T_COMMENT) || tk.is(T_CPP_COMMENT) || | 
					
						
							|  |  |  |                  (tk.isLiteral() && (*kind != T_STRING_LITERAL | 
					
						
							|  |  |  |                                      && *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
 | 
					
						
							|  |  |  |         else if (*kind == T_SLASH && (tk.isNot(T_STRING_LITERAL) && tk.isNot(T_ANGLE_STRING_LITERAL))) { | 
					
						
							|  |  |  |             *kind = T_EOF_SYMBOL; | 
					
						
							|  |  |  |             start = pos; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |         else if (*kind == T_LPAREN) { | 
					
						
							|  |  |  |             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); | 
					
						
							|  |  |  |                     QString directive = tc.block().text().mid(directiveToken.begin(), | 
					
						
							|  |  |  |                                                               directiveToken.length()); | 
					
						
							|  |  |  |                     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(); | 
					
						
							|  |  |  |                     start = start - CppCompletionAssistProvider::activationSequenceChar(ch4, ch5, ch6, kind, wantFunctionCall); | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | int CppCompletionAssistProcessor::findStartOfName(int pos) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (pos == -1) | 
					
						
							|  |  |  |         pos = m_interface->position(); | 
					
						
							|  |  |  |     QChar chr; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Skip to the start of a name
 | 
					
						
							|  |  |  |     do { | 
					
						
							|  |  |  |         chr = m_interface->characterAt(--pos); | 
					
						
							|  |  |  |     } while (chr.isLetterOrNumber() || chr == QLatin1Char('_')); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return pos + 1; | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | int CppCompletionAssistProcessor::startCompletionHelper() | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (m_objcEnabled) { | 
					
						
							|  |  |  |         if (tryObjCCompletion()) | 
					
						
							|  |  |  |             return m_startPosition; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int startOfName = findStartOfName(); | 
					
						
							|  |  |  |     m_startPosition = startOfName; | 
					
						
							|  |  |  |     m_model->m_completionOperator = T_EOF_SYMBOL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int endOfOperator = m_startPosition; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |     const Core::IDocument *document = m_interface->document(); | 
					
						
							|  |  |  |     QString fileName = document->fileName(); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     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()); | 
					
						
							|  |  |  |         return m_startPosition; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // Pre-processor completion
 | 
					
						
							|  |  |  |     if (m_model->m_completionOperator == T_POUND) { | 
					
						
							|  |  |  |         completePreprocessor(); | 
					
						
							|  |  |  |         m_startPosition = startOfName; | 
					
						
							|  |  |  |         return m_startPosition; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     // 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)) | 
					
						
							| 
									
										
										
										
											2012-10-04 13:13:12 +02:00
										 |  |  |             m_startPosition = endOfExpression + 1; | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         return m_startPosition; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ExpressionUnderCursor expressionUnderCursor; | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  |         m_startPosition = start + 1; | 
					
						
							|  |  |  |         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(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (m_model->m_completionOperator == T_LPAREN) { | 
					
						
							|  |  |  |             if (expression.endsWith(QLatin1String("SIGNAL"))) | 
					
						
							|  |  |  |                 m_model->m_completionOperator = T_SIGNAL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             else if (expression.endsWith(QLatin1String("SLOT"))) | 
					
						
							|  |  |  |                 m_model->m_completionOperator = T_SLOT; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             else if (m_interface->position() != endOfOperator) { | 
					
						
							|  |  |  |                 // 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; | 
					
						
							|  |  |  |                 m_startPosition = startOfName; | 
					
						
							|  |  |  |                 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); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     return startCompletionInternal(fileName, line, column, expression, endOfExpression); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | bool CppCompletionAssistProcessor::tryObjCCompletion() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     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); | 
					
						
							|  |  |  |     BackwardsScanner tokens(tc); | 
					
						
							|  |  |  |     if (tokens[tokens.startToken() - 1].isNot(T_RBRACKET)) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int start = tokens.startOfMatchingBrace(tokens.startToken()); | 
					
						
							|  |  |  |     if (start == tokens.startToken()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const int startPos = tokens[start].begin() + 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |     Document::Ptr thisDocument = m_interface->snapshot().document(m_interface->document()->fileName()); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |     if (! thisDocument) | 
					
						
							|  |  |  |         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()) { | 
					
						
							|  |  |  |                 ClassOrNamespace *binding = lookupContext.lookupType(namedTy->name(), item.scope()); | 
					
						
							|  |  |  |                 completeObjCMsgSend(binding, false); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             if (ObjCClass *clazz = ty->asObjCClassType()) { | 
					
						
							|  |  |  |                 ClassOrNamespace *binding = lookupContext.lookupType(clazz->name(), item.scope()); | 
					
						
							|  |  |  |                 completeObjCMsgSend(binding, true); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (m_completions.isEmpty()) | 
					
						
							|  |  |  |         return false; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     m_startPosition = m_interface->position(); | 
					
						
							| 
									
										
										
										
											2010-06-18 12:34:32 +02:00
										 |  |  |     return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppCompletionAssistProcessor::addCompletionItem(const QString &text, | 
					
						
							|  |  |  |                                                      const QIcon &icon, | 
					
						
							|  |  |  |                                                      int order, | 
					
						
							|  |  |  |                                                      const QVariant &data) | 
					
						
							| 
									
										
										
										
											2010-05-26 14:25:01 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     BasicProposalItem *item = new CppAssistProposalItem; | 
					
						
							|  |  |  |     item->setText(text); | 
					
						
							|  |  |  |     item->setIcon(icon); | 
					
						
							|  |  |  |     item->setOrder(order); | 
					
						
							|  |  |  |     item->setData(data); | 
					
						
							|  |  |  |     m_completions.append(item); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppCompletionAssistProcessor::addCompletionItem(CPlusPlus::Symbol *symbol) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     ConvertToCompletionItem toCompletionItem; | 
					
						
							|  |  |  |     BasicProposalItem *item = toCompletionItem(symbol); | 
					
						
							|  |  |  |     if (item) { | 
					
						
							|  |  |  |         item->setIcon(m_icons.iconForSymbol(symbol)); | 
					
						
							|  |  |  |         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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppCompletionAssistProcessor::completeObjCMsgSend(CPlusPlus::ClassOrNamespace *binding, | 
					
						
							|  |  |  |                                                        bool staticClassAccess) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     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); | 
					
						
							|  |  |  |                             text += selectorName->nameAt(i)->identifier()->chars(); | 
					
						
							|  |  |  |                             text += QLatin1Char(':'); | 
					
						
							|  |  |  |                             text += TextEditor::Snippet::kVariableDelimiter; | 
					
						
							|  |  |  |                             text += QLatin1Char('('); | 
					
						
							|  |  |  |                             text += oo(arg->type()); | 
					
						
							|  |  |  |                             text += QLatin1Char(')'); | 
					
						
							|  |  |  |                             text += oo(arg->name()); | 
					
						
							|  |  |  |                             text += TextEditor::Snippet::kVariableDelimiter; | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     } else { | 
					
						
							|  |  |  |                         text = selectorName->identifier()->chars(); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | bool CppCompletionAssistProcessor::completeInclude(const QTextCursor &cursor) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     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
 | 
					
						
							|  |  |  |     QStringList includePaths = m_interface->includePaths(); | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |     const QString ¤tFilePath = QFileInfo(m_interface->document()->fileName()).path(); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (!includePaths.contains(currentFilePath)) | 
					
						
							|  |  |  |         includePaths.append(currentFilePath); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-18 12:28:53 +02:00
										 |  |  |     const Core::MimeType mimeType = | 
					
						
							| 
									
										
										
										
											2012-01-24 15:36:40 +01:00
										 |  |  |             Core::ICore::mimeDatabase()->findByType(QLatin1String("text/x-c++hdr")); | 
					
						
							| 
									
										
										
										
											2011-05-18 12:28:53 +02:00
										 |  |  |     const QStringList suffixes = mimeType.suffixes(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     foreach (const QString &includePath, includePaths) { | 
					
						
							|  |  |  |         QString realPath = includePath; | 
					
						
							|  |  |  |         if (!directoryPrefix.isEmpty()) { | 
					
						
							|  |  |  |             realPath += QLatin1Char('/'); | 
					
						
							|  |  |  |             realPath += directoryPrefix; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2011-05-18 12:28:53 +02:00
										 |  |  |         completeInclude(realPath, suffixes); | 
					
						
							| 
									
										
										
										
											2009-07-23 16:46:30 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     foreach (const QString &frameworkPath, m_interface->frameworkPaths()) { | 
					
						
							|  |  |  |         QString realPath = frameworkPath; | 
					
						
							|  |  |  |         if (!directoryPrefix.isEmpty()) { | 
					
						
							|  |  |  |             realPath += QLatin1Char('/'); | 
					
						
							|  |  |  |             realPath += directoryPrefix; | 
					
						
							|  |  |  |             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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-05-18 12:28:53 +02:00
										 |  |  | void CppCompletionAssistProcessor::completeInclude(const QString &realPath, | 
					
						
							|  |  |  |                                                    const QStringList &suffixes) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     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()); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppCompletionAssistProcessor::completePreprocessor() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     foreach (const QString &preprocessorCompletion, preprocessorCompletions) | 
					
						
							|  |  |  |         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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | bool CppCompletionAssistProcessor::objcKeywordsWanted() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     if (!m_objcEnabled) | 
					
						
							|  |  |  |         return false; | 
					
						
							| 
									
										
										
										
											2009-02-20 12:55:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-02-14 16:43:51 +01:00
										 |  |  |     const Core::IDocument *document = m_interface->document(); | 
					
						
							|  |  |  |     QString fileName = document->fileName(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-01-24 15:36:40 +01:00
										 |  |  |     const Core::MimeDatabase *mdb = Core::ICore::mimeDatabase(); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     return mdb->findByFile(fileName).type() == CppTools::Constants::OBJECTIVE_CPP_SOURCE_MIMETYPE; | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | int CppCompletionAssistProcessor::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); | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  |     if (! thisDocument) | 
					
						
							|  |  |  |         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); | 
					
						
							| 
									
										
										
										
											2010-05-26 12:35:20 +02:00
										 |  |  |             globalCompletion(scope); | 
					
						
							|  |  |  |             if (m_completions.isEmpty()) | 
					
						
							|  |  |  |                 return -1; | 
					
						
							|  |  |  |             return m_startPosition; | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         else 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) { | 
					
						
							| 
									
										
										
										
											2010-01-11 13:47:15 +01:00
										 |  |  |             if (! (expression.isEmpty() || expression == QLatin1String("this"))) { | 
					
						
							|  |  |  |                 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-06-29 17:47:59 +02:00
										 |  |  |             ExpressionUnderCursor expressionUnderCursor; | 
					
						
							| 
									
										
										
										
											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)) | 
					
						
							| 
									
										
										
										
											2009-02-04 16:40:42 +01:00
										 |  |  |                         return m_startPosition; | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         } else { | 
					
						
							|  |  |  |             // nothing to do.
 | 
					
						
							|  |  |  |             return -1; | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											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)) | 
					
						
							|  |  |  |             return m_startPosition; | 
					
						
							|  |  |  |         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)) | 
					
						
							|  |  |  |             return m_startPosition; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     case T_COLON_COLON: | 
					
						
							|  |  |  |         if (completeScope(results)) | 
					
						
							|  |  |  |             return m_startPosition; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     case T_SIGNAL: | 
					
						
							|  |  |  |         if (completeSignal(results)) | 
					
						
							|  |  |  |             return m_startPosition; | 
					
						
							|  |  |  |         break; | 
					
						
							| 
									
										
										
										
											2009-10-19 14:14:28 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     case T_SLOT: | 
					
						
							|  |  |  |         if (completeSlot(results)) | 
					
						
							|  |  |  |             return m_startPosition; | 
					
						
							|  |  |  |         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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppCompletionAssistProcessor::globalCompletion(CPlusPlus::Scope *currentScope) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											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()); | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     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()) { | 
					
						
							|  |  |  |         if (scope->isBlock()) { | 
					
						
							|  |  |  |             if (ClassOrNamespace *binding = context.lookupType(scope)) { | 
					
						
							|  |  |  |                 for (unsigned i = 0; i < scope->memberCount(); ++i) { | 
					
						
							|  |  |  |                     Symbol *member = scope->memberAt(i); | 
					
						
							|  |  |  |                     if (! member->name()) | 
					
						
							|  |  |  |                         continue; | 
					
						
							|  |  |  |                     else if (UsingNamespaceDirective *u = member->asUsingNamespaceDirective()) { | 
					
						
							|  |  |  |                         if (ClassOrNamespace *b = binding->lookupType(u->name())) | 
					
						
							|  |  |  |                             usingBindings.append(b); | 
					
						
							|  |  |  |                     } | 
					
						
							| 
									
										
										
										
											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()) { | 
					
						
							|  |  |  |             for (unsigned i = 0; i < scope->memberCount(); ++i) { | 
					
						
							|  |  |  |                 addCompletionItem(scope->memberAt(i)); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } else if (scope->isFunction()) { | 
					
						
							|  |  |  |             Function *fun = scope->asFunction(); | 
					
						
							|  |  |  |             for (unsigned i = 0; i < fun->argumentCount(); ++i) { | 
					
						
							|  |  |  |                 addCompletionItem(fun->argumentAt(i)); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } else { | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-05-19 12:15:30 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     for (; currentBinding; currentBinding = currentBinding->parent()) { | 
					
						
							|  |  |  |         const QList<Symbol *> symbols = currentBinding->symbols(); | 
					
						
							| 
									
										
										
										
											2009-02-12 11:41:52 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |         if (! symbols.isEmpty()) { | 
					
						
							|  |  |  |             if (symbols.first()->isNamespace()) | 
					
						
							|  |  |  |                 completeNamespace(currentBinding); | 
					
						
							|  |  |  |             else | 
					
						
							|  |  |  |                 completeClass(currentBinding); | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-03-26 11:14:05 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     foreach (ClassOrNamespace *b, usingBindings) | 
					
						
							|  |  |  |         completeNamespace(b); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     addKeywords(); | 
					
						
							|  |  |  |     addMacros(QLatin1String("<configuration>"), context.snapshot()); | 
					
						
							|  |  |  |     addMacros(context.thisDocument()->fileName(), context.snapshot()); | 
					
						
							|  |  |  |     addSnippets(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | bool CppCompletionAssistProcessor::completeMember(const QList<CPlusPlus::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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (ClassOrNamespace *binding = | 
					
						
							|  |  |  |             resolveExpression.baseExpression(baseResults, | 
					
						
							|  |  |  |                                              m_model->m_completionOperator, | 
					
						
							|  |  |  |                                              &m_model->m_replaceDotForArrow)) { | 
					
						
							| 
									
										
										
										
											2010-05-12 14:52:24 +02:00
										 |  |  |         if (binding) | 
					
						
							| 
									
										
										
										
											2010-05-17 16:27:54 +02:00
										 |  |  |             completeClass(binding, /*static lookup = */ false); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-12 14:52:24 +02:00
										 |  |  |         return ! m_completions.isEmpty(); | 
					
						
							| 
									
										
										
										
											2009-11-04 18:21:35 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | bool CppCompletionAssistProcessor::completeScope(const QList<CPlusPlus::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()) { | 
					
						
							| 
									
										
										
										
											2010-05-14 13:44:54 +02: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()) { | 
					
						
							| 
									
										
										
										
											2010-05-14 13:44:54 +02: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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         } else if (Namespace *nsTy = ty->asNamespaceType()) { | 
					
						
							| 
									
										
										
										
											2010-05-14 13:44:54 +02: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; | 
					
						
							|  |  |  |             if (ClassOrNamespace *b = result.binding()->lookupType(templ->name())) { | 
					
						
							|  |  |  |                 completeClass(b); | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-02-18 15:56:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |     return ! m_completions.isEmpty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppCompletionAssistProcessor::completeNamespace(CPlusPlus::ClassOrNamespace *b) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |     QSet<ClassOrNamespace *> bindingsVisited; | 
					
						
							|  |  |  |     QList<ClassOrNamespace *> bindingsToVisit; | 
					
						
							|  |  |  |     bindingsToVisit.append(b); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |     while (! bindingsToVisit.isEmpty()) { | 
					
						
							|  |  |  |         ClassOrNamespace *binding = bindingsToVisit.takeFirst(); | 
					
						
							|  |  |  |         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()) { | 
					
						
							|  |  |  |             if (Namespace *ns = bb->asNamespace()) | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |                 scopesToVisit.append(ns); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach (Enum *e, binding->enums()) { | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |             scopesToVisit.append(e); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         while (! scopesToVisit.isEmpty()) { | 
					
						
							|  |  |  |             Scope *scope = scopesToVisit.takeFirst(); | 
					
						
							|  |  |  |             if (! scope || scopesVisited.contains(scope)) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             scopesVisited.insert(scope); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |             for (Scope::iterator it = scope->firstMember(); it != scope->lastMember(); ++it) { | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |                 Symbol *member = *it; | 
					
						
							|  |  |  |                 addCompletionItem(member); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppCompletionAssistProcessor::completeClass(CPlusPlus::ClassOrNamespace *b, bool staticLookup) | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     QSet<ClassOrNamespace *> bindingsVisited; | 
					
						
							|  |  |  |     QList<ClassOrNamespace *> bindingsToVisit; | 
					
						
							|  |  |  |     bindingsToVisit.append(b); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     while (! bindingsToVisit.isEmpty()) { | 
					
						
							|  |  |  |         ClassOrNamespace *binding = bindingsToVisit.takeFirst(); | 
					
						
							|  |  |  |         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); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         foreach (Enum *e, binding->enums()) | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |             scopesToVisit.append(e); | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         while (! scopesToVisit.isEmpty()) { | 
					
						
							|  |  |  |             Scope *scope = scopesToVisit.takeFirst(); | 
					
						
							|  |  |  |             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); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |             addCompletionItem(scope); // add a completion item for the injected class name.
 | 
					
						
							| 
									
										
										
										
											2010-06-02 13:59:01 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |             for (Scope::iterator it = scope->firstMember(); it != scope->lastMember(); ++it) { | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |                 Symbol *member = *it; | 
					
						
							| 
									
										
										
										
											2011-01-07 09:22:54 +01:00
										 |  |  |                 if (member->isFriend() | 
					
						
							|  |  |  |                         || member->isQtPropertyDeclaration() | 
					
						
							|  |  |  |                         || member->isQtEnum()) { | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2011-01-07 09:22:54 +01:00
										 |  |  |                 } else if (! staticLookup && (member->isTypedef() || | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |                                             member->isEnum()    || | 
					
						
							| 
									
										
										
										
											2011-01-07 09:22:54 +01:00
										 |  |  |                                             member->isClass())) { | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  |                     continue; | 
					
						
							| 
									
										
										
										
											2011-01-07 09:22:54 +01:00
										 |  |  |                 } | 
					
						
							| 
									
										
										
										
											2010-05-05 10:59:46 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 addCompletionItem(member); | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | bool CppCompletionAssistProcessor::completeQtMethod(const QList<CPlusPlus::LookupItem> &results, bool wantSignals) | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							|  |  |  |     o.setShowReturnTypes(false); | 
					
						
							|  |  |  |     o.setShowArgumentNames(false); | 
					
						
							|  |  |  |     o.setShowFunctionSignatures(true); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QSet<QString> signatures; | 
					
						
							| 
									
										
										
										
											2009-11-17 14:21:46 +01:00
										 |  |  |     foreach (const LookupItem &p, results) { | 
					
						
							|  |  |  |         FullySpecifiedType ty = p.type().simplified(); | 
					
						
							| 
									
										
										
										
											2009-09-30 11:24:00 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         if (PointerType *ptrTy = ty->asPointerType()) | 
					
						
							| 
									
										
										
										
											2009-10-05 11:38:54 +02:00
										 |  |  |             ty = ptrTy->elementType().simplified(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |         else | 
					
						
							|  |  |  |             continue; // not a pointer or a reference to a pointer.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         NamedType *namedTy = ty->asNamedType(); | 
					
						
							|  |  |  |         if (! namedTy) // not a class name.
 | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-17 16:27:54 +02:00
										 |  |  |         ClassOrNamespace *b = context.lookupType(namedTy->name(), p.scope()); | 
					
						
							| 
									
										
										
										
											2010-05-05 12:06:38 +02:00
										 |  |  |         if (! b) | 
					
						
							|  |  |  |             continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-26 15:44:01 +02:00
										 |  |  |         QList<ClassOrNamespace *>todo; | 
					
						
							|  |  |  |         QSet<ClassOrNamespace *> processed; | 
					
						
							|  |  |  |         QList<Scope *> scopes; | 
					
						
							|  |  |  |         todo.append(b); | 
					
						
							|  |  |  |         while (!todo.isEmpty()) { | 
					
						
							|  |  |  |             ClassOrNamespace *binding = todo.takeLast(); | 
					
						
							|  |  |  |             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
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-05-26 15:44:01 +02:00
										 |  |  |         foreach (Scope *scope, scopes) { | 
					
						
							| 
									
										
										
										
											2010-08-11 12:26:02 +02:00
										 |  |  |             if (! scope->isClass()) | 
					
						
							| 
									
										
										
										
											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(); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                 if (! fun) | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 if (wantSignals && ! fun->isSignal()) | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 else if (! wantSignals && ! fun->isSlot()) | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-08 14:01:18 +02:00
										 |  |  |                 unsigned count = fun->argumentCount(); | 
					
						
							|  |  |  |                 while (true) { | 
					
						
							|  |  |  |                     QString signature; | 
					
						
							|  |  |  |                     signature += Overview().prettyName(fun->name()); | 
					
						
							|  |  |  |                     signature += QLatin1Char('('); | 
					
						
							|  |  |  |                     for (unsigned i = 0; i < count; ++i) { | 
					
						
							|  |  |  |                         Symbol *arg = fun->argumentAt(i); | 
					
						
							|  |  |  |                         if (i != 0) | 
					
						
							|  |  |  |                             signature += QLatin1Char(','); | 
					
						
							|  |  |  |                         signature += o.prettyType(arg->type()); | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                     signature += QLatin1Char(')'); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-08 14:01:18 +02:00
										 |  |  |                     const QByteArray normalized = | 
					
						
							|  |  |  |                             QMetaObject::normalizedSignature(signature.toLatin1()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-08 14:01:18 +02:00
										 |  |  |                     signature = QString::fromLatin1(normalized, normalized.size()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-09-08 14:01:18 +02:00
										 |  |  |                     if (! signatures.contains(signature)) { | 
					
						
							|  |  |  |                         BasicProposalItem *ci = toCompletionItem(fun); | 
					
						
							|  |  |  |                         if (!ci) | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  |                             break; | 
					
						
							| 
									
										
										
										
											2011-09-08 14:01:18 +02:00
										 |  |  |                         signatures.insert(signature); | 
					
						
							|  |  |  |                         ci->setText(signature); // fix the completion item.
 | 
					
						
							|  |  |  |                         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
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     return ! m_completions.isEmpty(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppCompletionAssistProcessor::addSnippets() | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     m_completions.append(m_snippetCollector.collect()); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2010-05-26 12:35:20 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppCompletionAssistProcessor::addKeywords() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     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) | 
					
						
							|  |  |  |         addCompletionItem(QLatin1String(Token::name(i)), m_icons.keywordIcon()); | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppCompletionAssistProcessor::addMacros(const QString &fileName, const CPlusPlus::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) | 
					
						
							|  |  |  |         addCompletionItem(macroName, m_icons.macroIcon()); | 
					
						
							| 
									
										
										
										
											2010-05-28 12:51:12 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | void CppCompletionAssistProcessor::addMacros_helper(const CPlusPlus::Snapshot &snapshot, | 
					
						
							|  |  |  |                                                     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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (! doc || processed->contains(doc->fileName())) | 
					
						
							|  |  |  |         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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     foreach (const Document::Include &i, doc->includes()) { | 
					
						
							|  |  |  |         addMacros_helper(snapshot, i.fileName(), processed, definedMacros); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-07-09 15:12:44 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     foreach (const Macro ¯o, doc->definedMacros()) { | 
					
						
							|  |  |  |         const QString macroName = QString::fromUtf8(macro.name().constData(), macro.name().length()); | 
					
						
							|  |  |  |         if (! macro.isHidden()) | 
					
						
							|  |  |  |             definedMacros->insert(macroName); | 
					
						
							|  |  |  |         else | 
					
						
							|  |  |  |             definedMacros->remove(macroName); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-07-09 15:12:44 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  | bool CppCompletionAssistProcessor::completeConstructorOrFunction(const QList<CPlusPlus::LookupItem> &results, | 
					
						
							|  |  |  |                                                                  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(); | 
					
						
							|  |  |  |             if (! className) | 
					
						
							|  |  |  |                 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 if (! memberName) | 
					
						
							|  |  |  |                     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()) { | 
					
						
							|  |  |  |                     if (memberName->isEqualTo(className)) { | 
					
						
							|  |  |  |                         // 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 if (! fun->name()) | 
					
						
							|  |  |  |                     continue; | 
					
						
							|  |  |  |                 else if (! functions.isEmpty() && enclosingNonTemplateScope(functions.first()) != enclosingNonTemplateScope(fun)) | 
					
						
							|  |  |  |                     continue; // skip fun, it's an hidden declaration.
 | 
					
						
							| 
									
										
										
										
											2008-12-02 12:01:29 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 bool newOverload = true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 foreach (Function *f, functions) { | 
					
						
							|  |  |  |                     if (fun->isEqualTo(f)) { | 
					
						
							|  |  |  |                         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()) { | 
					
						
							|  |  |  |         const Name *functionCallOp = context.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()) { | 
					
						
							|  |  |  |                 if (ClassOrNamespace *b = context.lookupType(namedTy->name(), scope)) { | 
					
						
							|  |  |  |                     foreach (const LookupItem &r, b->lookup(functionCallOp)) { | 
					
						
							|  |  |  |                         Symbol *overload = r.declaration(); | 
					
						
							|  |  |  |                         FullySpecifiedType overloadTy = overload->type().simplified(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                         if (Function *funTy = overloadTy->asFunctionType()) { | 
					
						
							|  |  |  |                             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; | 
					
						
							|  |  |  |     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); | 
					
						
							|  |  |  |             BackwardsScanner bs(tc); | 
					
						
							|  |  |  |             const int startToken = bs.startToken(); | 
					
						
							|  |  |  |             int lineStartToken = bs.startOfLine(startToken); | 
					
						
							|  |  |  |             // make sure the required tokens are actually available
 | 
					
						
							|  |  |  |             bs.LA(startToken - lineStartToken); | 
					
						
							|  |  |  |             QString possibleDecl = bs.mid(lineStartToken).trimmed().append("();"); | 
					
						
							| 
									
										
										
										
											2008-12-08 13:01:54 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             Document::Ptr doc = Document::create(QLatin1String("<completion>")); | 
					
						
							| 
									
										
										
										
											2012-01-12 17:53:56 +01:00
										 |  |  |             doc->setUtf8Source(possibleDecl.toLatin1()); | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |             if (doc->parse(Document::ParseDeclaration)) { | 
					
						
							|  |  |  |                 doc->check(); | 
					
						
							|  |  |  |                 if (SimpleDeclarationAST *sd = doc->translationUnit()->ast()->asSimpleDeclaration()) { | 
					
						
							|  |  |  |                     if (sd->declarator_list && | 
					
						
							|  |  |  |                         sd->declarator_list && sd->declarator_list->value->postfix_declarator_list | 
					
						
							|  |  |  |                         && 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); | 
					
						
							|  |  |  |                 ClassOrNamespace *targetCoN = context.lookupType(sc); | 
					
						
							|  |  |  |                 if (!targetCoN) | 
					
						
							|  |  |  |                     targetCoN = context.globalNamespace(); | 
					
						
							|  |  |  |                 UseMinimalNames q(targetCoN); | 
					
						
							|  |  |  |                 env.enter(&q); | 
					
						
							|  |  |  |                 Control *control = context.control().data(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |                 // set up signature autocompletion
 | 
					
						
							|  |  |  |                 foreach (Function *f, functions) { | 
					
						
							|  |  |  |                     Overview overview; | 
					
						
							|  |  |  |                     overview.setShowArgumentNames(true); | 
					
						
							|  |  |  |                     overview.setShowDefaultArguments(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",
 | 
					
						
							| 
									
										
										
										
											2011-08-04 10:54:12 +02:00
										 |  |  |                     QString completion = overview(localTy).mid(1); | 
					
						
							| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2011-04-15 16:19:23 +02:00
										 |  |  |     if (! functions.empty() && !isDestructor) { | 
					
						
							|  |  |  |         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
										 |  |  | } |