| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | /**************************************************************************
 | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** This file is part of Qt Creator | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-01-11 16:28:15 +01:00
										 |  |  | ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** Contact: Nokia Corporation (info@qt.nokia.com) | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | ** | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** GNU Lesser General Public License Usage | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** 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.
 | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** In addition, as a special exception, Nokia gives you certain additional | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** rights. These rights are described in the Nokia Qt LGPL Exception | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2011-04-13 08:42:33 +02:00
										 |  |  | ** Other Usage | 
					
						
							|  |  |  | ** | 
					
						
							|  |  |  | ** Alternatively, this file may be used in accordance with the terms and | 
					
						
							|  |  |  | ** conditions contained in a signed written agreement between you and Nokia. | 
					
						
							|  |  |  | ** | 
					
						
							| 
									
										
										
										
											2010-12-17 16:01:08 +01:00
										 |  |  | ** If you have questions regarding the use of this file, please contact | 
					
						
							| 
									
										
										
										
											2011-05-06 15:05:37 +02:00
										 |  |  | ** Nokia at info@qt.nokia.com. | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | ** | 
					
						
							|  |  |  | **************************************************************************/ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-30 14:00:43 +02:00
										 |  |  | #include "cpptoolsplugin.h"
 | 
					
						
							| 
									
										
										
										
											2010-09-30 12:09:38 +02:00
										 |  |  | #include "cpprefactoringchanges.h"
 | 
					
						
							| 
									
										
										
										
											2010-09-30 14:00:43 +02:00
										 |  |  | #include "insertionpointlocator.h"
 | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <AST.h>
 | 
					
						
							|  |  |  | #include <ASTVisitor.h>
 | 
					
						
							|  |  |  | #include <TranslationUnit.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-06 14:01:59 +02:00
										 |  |  | #include <coreplugin/icore.h>
 | 
					
						
							|  |  |  | #include <coreplugin/mimedatabase.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | using namespace CPlusPlus; | 
					
						
							| 
									
										
										
										
											2010-09-30 12:09:38 +02:00
										 |  |  | using namespace CppTools; | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static QString generate(InsertionPointLocator::AccessSpec xsSpec) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     switch (xsSpec) { | 
					
						
							|  |  |  |     default: | 
					
						
							|  |  |  |     case InsertionPointLocator::Public: | 
					
						
							|  |  |  |         return QLatin1String("public:\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case InsertionPointLocator::Protected: | 
					
						
							|  |  |  |         return QLatin1String("protected:\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case InsertionPointLocator::Private: | 
					
						
							|  |  |  |         return QLatin1String("private:\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case InsertionPointLocator::PublicSlot: | 
					
						
							|  |  |  |         return QLatin1String("public slots:\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case InsertionPointLocator::ProtectedSlot: | 
					
						
							|  |  |  |         return QLatin1String("protected slots:\n"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     case InsertionPointLocator::PrivateSlot: | 
					
						
							| 
									
										
										
										
											2010-07-27 17:02:12 +02:00
										 |  |  |         return QLatin1String("private slots:\n"); | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     case InsertionPointLocator::Signals: | 
					
						
							|  |  |  |         return QLatin1String("signals:\n"); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  | static int ordering(InsertionPointLocator::AccessSpec xsSpec) | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |     static QList<InsertionPointLocator::AccessSpec> order = QList<InsertionPointLocator::AccessSpec>() | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |             << InsertionPointLocator::Public | 
					
						
							|  |  |  |             << InsertionPointLocator::PublicSlot | 
					
						
							|  |  |  |             << InsertionPointLocator::Signals | 
					
						
							|  |  |  |             << InsertionPointLocator::Protected | 
					
						
							|  |  |  |             << InsertionPointLocator::ProtectedSlot | 
					
						
							|  |  |  |             << InsertionPointLocator::PrivateSlot | 
					
						
							|  |  |  |             << InsertionPointLocator::Private | 
					
						
							|  |  |  |             ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |     return order.indexOf(xsSpec); | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | struct AccessRange | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned start; | 
					
						
							|  |  |  |     unsigned end; | 
					
						
							|  |  |  |     InsertionPointLocator::AccessSpec xsSpec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     AccessRange() | 
					
						
							|  |  |  |         : start(0) | 
					
						
							|  |  |  |         , end(0) | 
					
						
							|  |  |  |         , xsSpec(InsertionPointLocator::Invalid) | 
					
						
							|  |  |  |     {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     AccessRange(unsigned start, unsigned end, InsertionPointLocator::AccessSpec xsSpec) | 
					
						
							|  |  |  |         : start(start) | 
					
						
							|  |  |  |         , end(end) | 
					
						
							|  |  |  |         , xsSpec(xsSpec) | 
					
						
							|  |  |  |     {} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FindInClass: public ASTVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     FindInClass(const Document::Ptr &doc, const Class *clazz, InsertionPointLocator::AccessSpec xsSpec) | 
					
						
							|  |  |  |         : ASTVisitor(doc->translationUnit()) | 
					
						
							|  |  |  |         , _doc(doc) | 
					
						
							|  |  |  |         , _clazz(clazz) | 
					
						
							|  |  |  |         , _xsSpec(xsSpec) | 
					
						
							|  |  |  |     {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     InsertionLocation operator()() | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         _result = InsertionLocation(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         AST *ast = translationUnit()->ast(); | 
					
						
							|  |  |  |         accept(ast); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return _result; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     using ASTVisitor::visit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool visit(ClassSpecifierAST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (!ast->lbrace_token || !ast->rbrace_token) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  |         if (!ast->symbol || !ast->symbol->isEqualTo(_clazz)) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QList<AccessRange> ranges = collectAccessRanges( | 
					
						
							|  |  |  |                     ast->member_specifier_list, | 
					
						
							|  |  |  |                     tokenKind(ast->classkey_token) == T_CLASS ? InsertionPointLocator::Private : InsertionPointLocator::Public, | 
					
						
							|  |  |  |                     ast->lbrace_token, | 
					
						
							|  |  |  |                     ast->rbrace_token); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |         unsigned beforeToken = 0; | 
					
						
							|  |  |  |         bool needsPrefix = false; | 
					
						
							|  |  |  |         bool needsSuffix = false; | 
					
						
							|  |  |  |         findMatch(ranges, _xsSpec, beforeToken, needsPrefix, needsSuffix); | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         unsigned line = 0, column = 0; | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |         getTokenStartPosition(beforeToken, &line, &column); | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |         QString prefix; | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |         if (needsPrefix) | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |             prefix = generate(_xsSpec); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |         QString suffix; | 
					
						
							|  |  |  |         if (needsSuffix) | 
					
						
							|  |  |  |             suffix = QLatin1Char('\n'); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-30 12:09:38 +02:00
										 |  |  |         _result = InsertionLocation(_doc->fileName(), prefix, suffix, | 
					
						
							|  |  |  |                                     line, column); | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |         return false; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |     static void findMatch(const QList<AccessRange> &ranges, | 
					
						
							|  |  |  |                           InsertionPointLocator::AccessSpec xsSpec, | 
					
						
							|  |  |  |                           unsigned &beforeToken, | 
					
						
							|  |  |  |                           bool &needsPrefix, | 
					
						
							|  |  |  |                           bool &needsSuffix) | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |         Q_ASSERT(!ranges.isEmpty()); | 
					
						
							|  |  |  |         const int lastIndex = ranges.size() - 1; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |         // try an exact match, and ignore the first (default) access spec:
 | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |         for (int i = lastIndex; i > 0; --i) { | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |             const AccessRange &range = ranges.at(i); | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |             if (range.xsSpec == xsSpec) { | 
					
						
							|  |  |  |                 beforeToken = range.end; | 
					
						
							|  |  |  |                 needsPrefix = false; | 
					
						
							|  |  |  |                 needsSuffix = (i != lastIndex); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |         // try to find a fitting access spec to insert XXX:
 | 
					
						
							|  |  |  |         for (int i = lastIndex; i > 0; --i) { | 
					
						
							|  |  |  |             const AccessRange ¤t = ranges.at(i); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (ordering(xsSpec) > ordering(current.xsSpec)) { | 
					
						
							|  |  |  |                 beforeToken = current.end; | 
					
						
							|  |  |  |                 needsPrefix = true; | 
					
						
							|  |  |  |                 needsSuffix = (i != lastIndex); | 
					
						
							|  |  |  |                 return; | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         // otherwise:
 | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |         beforeToken = ranges.first().end; | 
					
						
							|  |  |  |         needsPrefix = true; | 
					
						
							|  |  |  |         needsSuffix = (ranges.size() != 1); | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<AccessRange> collectAccessRanges(DeclarationListAST *decls, | 
					
						
							|  |  |  |                                            InsertionPointLocator::AccessSpec initialXs, | 
					
						
							|  |  |  |                                            int firstRangeStart, | 
					
						
							|  |  |  |                                            int lastRangeEnd) const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QList<AccessRange> ranges; | 
					
						
							|  |  |  |         ranges.append(AccessRange(firstRangeStart, lastRangeEnd, initialXs)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (DeclarationListAST *iter = decls; iter; iter = iter->next) { | 
					
						
							|  |  |  |             DeclarationAST *decl = iter->value; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (AccessDeclarationAST *xsDecl = decl->asAccessDeclaration()) { | 
					
						
							|  |  |  |                 const unsigned token = xsDecl->access_specifier_token; | 
					
						
							|  |  |  |                 int newXsSpec = initialXs; | 
					
						
							| 
									
										
										
										
											2010-09-27 18:01:04 +02:00
										 |  |  |                 bool isSlot = xsDecl->slots_token | 
					
						
							|  |  |  |                         && tokenKind(xsDecl->slots_token) == T_Q_SLOTS; | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 switch (tokenKind(token)) { | 
					
						
							|  |  |  |                 case T_PUBLIC: | 
					
						
							| 
									
										
										
										
											2010-09-27 18:01:04 +02:00
										 |  |  |                     newXsSpec = isSlot ? InsertionPointLocator::PublicSlot | 
					
						
							|  |  |  |                                        : InsertionPointLocator::Public; | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |                     break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 case T_PROTECTED: | 
					
						
							| 
									
										
										
										
											2010-09-27 18:01:04 +02:00
										 |  |  |                     newXsSpec = isSlot ? InsertionPointLocator::ProtectedSlot | 
					
						
							|  |  |  |                                        : InsertionPointLocator::Protected; | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |                     break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 case T_PRIVATE: | 
					
						
							| 
									
										
										
										
											2010-09-27 18:01:04 +02:00
										 |  |  |                     newXsSpec = isSlot ? InsertionPointLocator::PrivateSlot | 
					
						
							|  |  |  |                                        : InsertionPointLocator::Private; | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |                     break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 case T_Q_SIGNALS: | 
					
						
							|  |  |  |                     newXsSpec = InsertionPointLocator::Signals; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 case T_Q_SLOTS: { | 
					
						
							|  |  |  |                     newXsSpec = ranges.last().xsSpec | InsertionPointLocator::SlotBit; | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 default: | 
					
						
							|  |  |  |                     break; | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (newXsSpec != ranges.last().xsSpec) { | 
					
						
							|  |  |  |                     ranges.last().end = token; | 
					
						
							|  |  |  |                     ranges.append(AccessRange(token, lastRangeEnd, (InsertionPointLocator::AccessSpec) newXsSpec)); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ranges.last().end = lastRangeEnd; | 
					
						
							|  |  |  |         return ranges; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     Document::Ptr _doc; | 
					
						
							|  |  |  |     const Class *_clazz; | 
					
						
							|  |  |  |     InsertionPointLocator::AccessSpec _xsSpec; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     InsertionLocation _result; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // end of anonymous namespace
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | InsertionLocation::InsertionLocation() | 
					
						
							|  |  |  |     : m_line(0) | 
					
						
							|  |  |  |     , m_column(0) | 
					
						
							|  |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-30 12:09:38 +02:00
										 |  |  | InsertionLocation::InsertionLocation(const QString &fileName, | 
					
						
							|  |  |  |                                      const QString &prefix, | 
					
						
							|  |  |  |                                      const QString &suffix, | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |                                      unsigned line, unsigned column) | 
					
						
							| 
									
										
										
										
											2010-09-30 12:09:38 +02:00
										 |  |  |     : m_fileName(fileName) | 
					
						
							|  |  |  |     , m_prefix(prefix) | 
					
						
							| 
									
										
										
										
											2010-07-28 12:09:50 +02:00
										 |  |  |     , m_suffix(suffix) | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  |     , m_line(line) | 
					
						
							|  |  |  |     , m_column(column) | 
					
						
							|  |  |  | {} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-30 12:09:38 +02:00
										 |  |  | InsertionPointLocator::InsertionPointLocator(CppRefactoringChanges *refactoringChanges) | 
					
						
							|  |  |  |     : m_refactoringChanges(refactoringChanges) | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-27 18:01:04 +02:00
										 |  |  | InsertionLocation InsertionPointLocator::methodDeclarationInClass( | 
					
						
							|  |  |  |     const QString &fileName, | 
					
						
							|  |  |  |     const Class *clazz, | 
					
						
							|  |  |  |     AccessSpec xsSpec) const | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2010-09-30 12:09:38 +02:00
										 |  |  |     const Document::Ptr doc = m_refactoringChanges->file(fileName).cppDocument(); | 
					
						
							| 
									
										
										
										
											2010-09-27 18:01:04 +02:00
										 |  |  |     if (doc) { | 
					
						
							|  |  |  |         FindInClass find(doc, clazz, xsSpec); | 
					
						
							|  |  |  |         return find(); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |         return InsertionLocation(); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-06 14:01:59 +02:00
										 |  |  | static bool isSourceFile(const QString &fileName) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     const Core::MimeDatabase *mimeDb = Core::ICore::instance()->mimeDatabase(); | 
					
						
							|  |  |  |     Core::MimeType cSourceTy = mimeDb->findByType(QLatin1String("text/x-csrc")); | 
					
						
							|  |  |  |     Core::MimeType cppSourceTy = mimeDb->findByType(QLatin1String("text/x-c++src")); | 
					
						
							|  |  |  |     Core::MimeType mSourceTy = mimeDb->findByType(QLatin1String("text/x-objcsrc")); | 
					
						
							|  |  |  |     QStringList suffixes = cSourceTy.suffixes(); | 
					
						
							|  |  |  |     suffixes += cppSourceTy.suffixes(); | 
					
						
							|  |  |  |     suffixes += mSourceTy.suffixes(); | 
					
						
							|  |  |  |     QFileInfo fileInfo(fileName); | 
					
						
							|  |  |  |     return suffixes.contains(fileInfo.suffix()); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-27 18:05:24 +02:00
										 |  |  | /// Currently, we return the end of fileName.cpp
 | 
					
						
							| 
									
										
										
										
											2010-10-06 15:49:59 +02:00
										 |  |  | /// \todo take the definitions of the surrounding declarations into account
 | 
					
						
							| 
									
										
										
										
											2010-09-27 18:01:04 +02:00
										 |  |  | QList<InsertionLocation> InsertionPointLocator::methodDefinition( | 
					
						
							| 
									
										
										
										
											2010-09-30 12:09:38 +02:00
										 |  |  |     Declaration *declaration) const | 
					
						
							| 
									
										
										
										
											2010-09-27 18:01:04 +02:00
										 |  |  | { | 
					
						
							|  |  |  |     QList<InsertionLocation> result; | 
					
						
							| 
									
										
										
										
											2010-09-30 12:09:38 +02:00
										 |  |  |     if (!declaration) | 
					
						
							|  |  |  |         return result; | 
					
						
							| 
									
										
										
										
											2010-09-27 18:01:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-06 14:01:59 +02:00
										 |  |  |     const QString declFileName = QString::fromUtf8(declaration->fileName(), | 
					
						
							|  |  |  |                                                    declaration->fileNameLength()); | 
					
						
							|  |  |  |     QString target = declFileName; | 
					
						
							|  |  |  |     if (!isSourceFile(declFileName)) { | 
					
						
							| 
									
										
										
										
											2011-07-06 17:34:45 +02:00
										 |  |  |         QString candidate = Internal::CppToolsPlugin::correspondingHeaderOrSource(declFileName); | 
					
						
							| 
									
										
										
										
											2010-10-07 15:22:32 +02:00
										 |  |  |         if (!candidate.isEmpty()) | 
					
						
							|  |  |  |             target = candidate; | 
					
						
							| 
									
										
										
										
											2010-10-06 14:01:59 +02:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2010-09-27 18:01:04 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-30 12:09:38 +02:00
										 |  |  |     Document::Ptr doc = m_refactoringChanges->file(target).cppDocument(); | 
					
						
							|  |  |  |     if (doc.isNull()) | 
					
						
							|  |  |  |         return result; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-10-06 15:49:59 +02:00
										 |  |  |     Snapshot simplified = m_refactoringChanges->snapshot().simplified(doc); | 
					
						
							|  |  |  |     if (Symbol *s = simplified.findMatchingDefinition(declaration)) { | 
					
						
							|  |  |  |         if (Function *f = s->asFunction()) { | 
					
						
							|  |  |  |             if (f->isConst() == declaration->type().isConst() | 
					
						
							|  |  |  |                     && f->isVolatile() == declaration->type().isVolatile()) | 
					
						
							|  |  |  |                 return result; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-09-30 12:09:38 +02:00
										 |  |  |     TranslationUnit *xUnit = doc->translationUnit(); | 
					
						
							|  |  |  |     unsigned tokenCount = xUnit->tokenCount(); | 
					
						
							|  |  |  |     if (tokenCount < 2) // no tokens available
 | 
					
						
							|  |  |  |         return result; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     unsigned line = 0, column = 0; | 
					
						
							|  |  |  |     xUnit->getTokenEndPosition(xUnit->tokenCount() - 2, &line, &column); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QLatin1String prefix("\n\n"); | 
					
						
							|  |  |  |     result.append(InsertionLocation(target, prefix, QString(), line, column)); | 
					
						
							| 
									
										
										
										
											2010-09-27 18:01:04 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  |     return result; | 
					
						
							| 
									
										
										
										
											2010-07-27 15:29:16 +02:00
										 |  |  | } |