| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <QCoreApplication>
 | 
					
						
							|  |  |  | #include <QStringList>
 | 
					
						
							|  |  |  | #include <QTextDocument>
 | 
					
						
							|  |  |  | #include <QTextCursor>
 | 
					
						
							|  |  |  | #include <QTextBlock>
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  | #include <QDir>
 | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | #include <QDebug>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <Control.h>
 | 
					
						
							|  |  |  | #include <Parser.h>
 | 
					
						
							|  |  |  | #include <AST.h>
 | 
					
						
							|  |  |  | #include <ASTVisitor.h>
 | 
					
						
							|  |  |  | #include <Symbols.h>
 | 
					
						
							|  |  |  | #include <CoreTypes.h>
 | 
					
						
							|  |  |  | #include <Literals.h>
 | 
					
						
							|  |  |  | #include <CppDocument.h>
 | 
					
						
							|  |  |  | #include <Overview.h>
 | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  | #include <Names.h>
 | 
					
						
							|  |  |  | #include <Scope.h>
 | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include <iostream>
 | 
					
						
							|  |  |  | #include <cstdlib>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace CPlusPlus; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 10:32:36 +01:00
										 |  |  | static const char copyrightHeader[] = | 
					
						
							|  |  |  | "/**************************************************************************\n" | 
					
						
							|  |  |  | "**\n" | 
					
						
							|  |  |  | "** This file is part of Qt Creator\n" | 
					
						
							|  |  |  | "**\n" | 
					
						
							|  |  |  | "** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).\n" | 
					
						
							|  |  |  | "**\n" | 
					
						
							|  |  |  | "** Contact: Nokia Corporation (qt-info@nokia.com)\n" | 
					
						
							|  |  |  | "**\n" | 
					
						
							|  |  |  | "** Commercial Usage\n" | 
					
						
							|  |  |  | "**\n" | 
					
						
							|  |  |  | "** Licensees holding valid Qt Commercial licenses may use this file in\n" | 
					
						
							|  |  |  | "** accordance with the Qt Commercial License Agreement provided with the\n" | 
					
						
							|  |  |  | "** Software or, alternatively, in accordance with the terms contained in\n" | 
					
						
							|  |  |  | "** a written agreement between you and Nokia.\n" | 
					
						
							|  |  |  | "**\n" | 
					
						
							|  |  |  | "** GNU Lesser General Public License Usage\n" | 
					
						
							|  |  |  | "**\n" | 
					
						
							|  |  |  | "** Alternatively, this file may be used under the terms of the GNU Lesser\n" | 
					
						
							|  |  |  | "** General Public License version 2.1 as published by the Free Software\n" | 
					
						
							|  |  |  | "** Foundation and appearing in the file LICENSE.LGPL included in the\n" | 
					
						
							|  |  |  | "** packaging of this file.  Please review the following information to\n" | 
					
						
							|  |  |  | "** ensure the GNU Lesser General Public License version 2.1 requirements\n" | 
					
						
							|  |  |  | "** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.\n" | 
					
						
							|  |  |  | "**\n" | 
					
						
							|  |  |  | "** If you are unsure which license is appropriate for your use, please\n" | 
					
						
							|  |  |  | "** contact the sales department at http://qt.nokia.com/contact.\n" | 
					
						
							|  |  |  | "**\n" | 
					
						
							|  |  |  | "**************************************************************************/\n" | 
					
						
							|  |  |  | ; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-16 13:38:37 +01:00
										 |  |  | class ASTNodes | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     ASTNodes(): base(0) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ClassSpecifierAST *base; // points to "class AST"
 | 
					
						
							|  |  |  |     QList<ClassSpecifierAST *> deriveds; // n where n extends AST
 | 
					
						
							|  |  |  |     QList<QTextCursor> endOfPublicClassSpecifiers; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static ASTNodes astNodes; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static QTextCursor createCursor(TranslationUnit *unit, AST *ast, QTextDocument *document) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     unsigned startLine, startColumn, endLine, endColumn; | 
					
						
							|  |  |  |     unit->getTokenStartPosition(ast->firstToken(), &startLine, &startColumn); | 
					
						
							|  |  |  |     unit->getTokenEndPosition(ast->lastToken() - 1, &endLine, &endColumn); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextCursor tc(document); | 
					
						
							|  |  |  |     tc.setPosition(document->findBlockByNumber(startLine - 1).position()); | 
					
						
							|  |  |  |     tc.setPosition(document->findBlockByNumber(endLine - 1).position() + endColumn - 1, | 
					
						
							|  |  |  |                    QTextCursor::KeepAnchor); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     int charsToSkip = 0; | 
					
						
							|  |  |  |     forever { | 
					
						
							|  |  |  |         QChar ch = document->characterAt(tc.position() + charsToSkip); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (! ch.isSpace()) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         ++charsToSkip; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (ch == QChar::ParagraphSeparator) | 
					
						
							|  |  |  |             break; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     tc.setPosition(tc.position() + charsToSkip, QTextCursor::KeepAnchor); | 
					
						
							|  |  |  |     return tc; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FindASTNodes: protected ASTVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     FindASTNodes(Document::Ptr doc, QTextDocument *document) | 
					
						
							|  |  |  |         : ASTVisitor(doc->control()), document(document) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     ASTNodes operator()(AST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         accept(ast); | 
					
						
							|  |  |  |         return _nodes; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     virtual bool visit(ClassSpecifierAST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Class *klass = ast->symbol; | 
					
						
							|  |  |  |         Q_ASSERT(klass != 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         const QString className = oo(klass->name()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (className.endsWith("AST")) { | 
					
						
							|  |  |  |             if (className == QLatin1String("AST")) | 
					
						
							|  |  |  |                 _nodes.base = ast; | 
					
						
							|  |  |  |             else { | 
					
						
							|  |  |  |                 _nodes.deriveds.append(ast); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 AccessDeclarationAST *accessDeclaration = 0; | 
					
						
							|  |  |  |                 for (DeclarationListAST *it = ast->member_specifier_list; it; it = it->next) { | 
					
						
							|  |  |  |                     if (AccessDeclarationAST *decl = it->value->asAccessDeclaration()) { | 
					
						
							|  |  |  |                         if (tokenKind(decl->access_specifier_token) == T_PUBLIC) | 
					
						
							|  |  |  |                             accessDeclaration = decl; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (! accessDeclaration) | 
					
						
							|  |  |  |                     qDebug() << "no access declaration for class:" << className; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 Q_ASSERT(accessDeclaration != 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 QTextCursor tc = createCursor(translationUnit(), accessDeclaration, document); | 
					
						
							|  |  |  |                 tc.setPosition(tc.position()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 _nodes.endOfPublicClassSpecifiers.append(tc); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     QTextDocument *document; | 
					
						
							|  |  |  |     ASTNodes _nodes; | 
					
						
							|  |  |  |     Overview oo; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  | class Accept0CG: protected ASTVisitor | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |     QDir _cplusplusDir; | 
					
						
							|  |  |  |     QTextStream *out; | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |     Accept0CG(const QDir &cplusplusDir, Control *control) | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |         : ASTVisitor(control), _cplusplusDir(cplusplusDir), out(0) | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |     { } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |     void operator()(AST *ast) | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |         QFileInfo fileInfo(_cplusplusDir, QLatin1String("ASTVisit.cpp")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QFile file(fileInfo.absoluteFilePath()); | 
					
						
							|  |  |  |         if (! file.open(QFile::WriteOnly)) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QTextStream output(&file); | 
					
						
							|  |  |  |         out = &output; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *out << copyrightHeader << | 
					
						
							|  |  |  |             "\n" | 
					
						
							|  |  |  |             "#include \"AST.h\"\n" | 
					
						
							|  |  |  |             "#include \"ASTVisitor.h\"\n" | 
					
						
							|  |  |  |             "\n" | 
					
						
							|  |  |  |             "using namespace CPlusPlus;\n" << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |         accept(ast); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |     using ASTVisitor::visit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QMap<QByteArray, ClassSpecifierAST *> classMap; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QByteArray id_cast(NameAST *name) | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |         if (! name) | 
					
						
							|  |  |  |             return QByteArray(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Identifier *id = identifier(name->asSimpleName()->identifier_token); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return QByteArray::fromRawData(id->chars(), id->size()); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |     void visitMembers(Class *klass) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         // *out << "        // visit " << className.constData() << endl;
 | 
					
						
							|  |  |  |         for (unsigned i = 0; i < klass->memberCount(); ++i) { | 
					
						
							|  |  |  |             Symbol *member = klass->memberAt(i); | 
					
						
							|  |  |  |             if (! member->name()) | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             Identifier *id = member->name()->identifier(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (! id) | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |                 continue; | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             const QByteArray memberName = QByteArray::fromRawData(id->chars(), id->size()); | 
					
						
							|  |  |  |             if (member->type().isUnsigned() && memberName.endsWith("_token")) { | 
					
						
							|  |  |  |                 // nothing to do. The member is a token.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             } else if (PointerType *ptrTy = member->type()->asPointerType()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { | 
					
						
							|  |  |  |                     QByteArray typeName = namedTy->name()->identifier()->chars(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                     if (typeName.endsWith("AST") && memberName != "next") { | 
					
						
							|  |  |  |                         *out << "        accept(" << memberName.constData() << ", visitor);" << endl; | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (unsigned i = 0; i < klass->baseClassCount(); ++i) { | 
					
						
							|  |  |  |             const QByteArray baseClassName = klass->baseClassAt(i)->identifier()->chars(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (ClassSpecifierAST *baseClassSpec = classMap.value(baseClassName, 0)) { | 
					
						
							|  |  |  |                 visitMembers(baseClassSpec->symbol); | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool checkMethod(Symbol *accept0Method) const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Declaration *decl = accept0Method->asDeclaration(); | 
					
						
							|  |  |  |         if (! decl) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Function *funTy = decl->type()->asFunctionType(); | 
					
						
							|  |  |  |         if (! funTy) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         else if (funTy->isPureVirtual()) | 
					
						
							|  |  |  |             return false; | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |     virtual bool visit(ClassSpecifierAST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Class *klass = ast->symbol; | 
					
						
							|  |  |  |         const QByteArray className = id_cast(ast->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Identifier *visit_id = control()->findOrInsertIdentifier("accept0"); | 
					
						
							|  |  |  |         Symbol *accept0Method = klass->members()->lookat(visit_id); | 
					
						
							|  |  |  |         for (; accept0Method; accept0Method = accept0Method->next()) { | 
					
						
							|  |  |  |             if (accept0Method->identifier() != visit_id) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (checkMethod(accept0Method)) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (! accept0Method) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         classMap.insert(className, ast); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *out | 
					
						
							|  |  |  |                 << "void " << className.constData() << "::accept0(ASTVisitor *visitor)" << endl | 
					
						
							|  |  |  |                 << "{" << endl | 
					
						
							|  |  |  |                 << "    if (visitor->visit(this)) {" << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         visitMembers(klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *out | 
					
						
							|  |  |  |                 << "    }" << endl | 
					
						
							|  |  |  |                 << "    visitor->endVisit(this);" << endl | 
					
						
							|  |  |  |                 << "}" << endl | 
					
						
							|  |  |  |                 << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  | class Match0CG: protected ASTVisitor | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  | { | 
					
						
							|  |  |  |     QDir _cplusplusDir; | 
					
						
							|  |  |  |     QTextStream *out; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |     Match0CG(const QDir &cplusplusDir, Control *control) | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |         : ASTVisitor(control), _cplusplusDir(cplusplusDir), out(0) | 
					
						
							|  |  |  |     { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void operator()(AST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |         QFileInfo fileInfo(_cplusplusDir, QLatin1String("ASTMatch0.cpp")); | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         QFile file(fileInfo.absoluteFilePath()); | 
					
						
							|  |  |  |         if (! file.open(QFile::WriteOnly)) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QTextStream output(&file); | 
					
						
							|  |  |  |         out = &output; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-10 10:32:36 +01:00
										 |  |  |         *out << copyrightHeader << | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |             "\n" | 
					
						
							|  |  |  |             "#include \"AST.h\"\n" | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |             "#include \"ASTMatcher.h\"\n" | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |             "\n" | 
					
						
							|  |  |  |             "using namespace CPlusPlus;\n" << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         accept(ast); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     using ASTVisitor::visit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QMap<QByteArray, ClassSpecifierAST *> classMap; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QByteArray id_cast(NameAST *name) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (! name) | 
					
						
							|  |  |  |             return QByteArray(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Identifier *id = identifier(name->asSimpleName()->identifier_token); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return QByteArray::fromRawData(id->chars(), id->size()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void visitMembers(Class *klass) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |         Overview oo; | 
					
						
							|  |  |  |         const QString className = oo(klass->name()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |         *out << "    if (" << className << " *_other = pattern->as" << className.left(className.length() - 3) << "())" << endl; | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |         *out << "        return matcher->match(this, _other);" << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *out << endl; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool checkMethod(Symbol *accept0Method) const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Declaration *decl = accept0Method->asDeclaration(); | 
					
						
							|  |  |  |         if (! decl) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Function *funTy = decl->type()->asFunctionType(); | 
					
						
							|  |  |  |         if (! funTy) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         else if (funTy->isPureVirtual()) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(ClassSpecifierAST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Class *klass = ast->symbol; | 
					
						
							|  |  |  |         const QByteArray className = id_cast(ast->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Identifier *match0_id = control()->findOrInsertIdentifier("match0"); | 
					
						
							|  |  |  |         Symbol *accept0Method = klass->members()->lookat(match0_id); | 
					
						
							|  |  |  |         for (; accept0Method; accept0Method = accept0Method->next()) { | 
					
						
							|  |  |  |             if (accept0Method->identifier() != match0_id) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (checkMethod(accept0Method)) | 
					
						
							|  |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (! accept0Method) | 
					
						
							|  |  |  |             return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         classMap.insert(className, ast); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *out | 
					
						
							|  |  |  |                 << "bool " << className.constData() << "::match0(AST *pattern, ASTMatcher *matcher)" << endl | 
					
						
							|  |  |  |                 << "{" << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         visitMembers(klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *out | 
					
						
							|  |  |  |                 << "    return false;" << endl | 
					
						
							|  |  |  |                 << "}" << endl | 
					
						
							|  |  |  |                 << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class MatcherCPPCG: protected ASTVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QDir _cplusplusDir; | 
					
						
							|  |  |  |     QTextStream *out; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     MatcherCPPCG(const QDir &cplusplusDir, Control *control) | 
					
						
							|  |  |  |         : ASTVisitor(control), _cplusplusDir(cplusplusDir), out(0) | 
					
						
							|  |  |  |     { } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void operator()(AST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         QFileInfo fileInfo(_cplusplusDir, QLatin1String("ASTMatcher.cpp")); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QFile file(fileInfo.absoluteFilePath()); | 
					
						
							|  |  |  |         if (! file.open(QFile::WriteOnly)) | 
					
						
							|  |  |  |             return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         QTextStream output(&file); | 
					
						
							|  |  |  |         out = &output; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 11:43:52 +01:00
										 |  |  |         *out << copyrightHeader << endl | 
					
						
							|  |  |  |                 << "#include \"AST.h\"" << endl | 
					
						
							|  |  |  |                 << "#include \"ASTMatcher.h\"" << endl | 
					
						
							|  |  |  |                 << "#include \"TranslationUnit.h\"" << endl | 
					
						
							|  |  |  |                 << endl | 
					
						
							|  |  |  |                 << "using namespace CPlusPlus;" << endl | 
					
						
							|  |  |  |                 << endl | 
					
						
							| 
									
										
										
										
											2009-11-16 13:38:37 +01:00
										 |  |  |                 << "ASTMatcher::ASTMatcher(TranslationUnit *translationUnit)" | 
					
						
							|  |  |  |                 << "    : _translationUnit(translationUnit)" << endl | 
					
						
							| 
									
										
										
										
											2009-11-13 11:43:52 +01:00
										 |  |  |                 << "{ }" << endl | 
					
						
							|  |  |  |                 << endl | 
					
						
							|  |  |  |                 << "ASTMatcher::~ASTMatcher()" << endl | 
					
						
							|  |  |  |                 << "{ }" << endl | 
					
						
							|  |  |  |                 << endl | 
					
						
							|  |  |  |                 << "TranslationUnit *ASTMatcher::translationUnit() const" << endl | 
					
						
							| 
									
										
										
										
											2009-11-16 13:38:37 +01:00
										 |  |  |                 << "{ return _translationUnit; }" << endl | 
					
						
							| 
									
										
										
										
											2009-11-13 11:43:52 +01:00
										 |  |  |                 << endl; | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         accept(ast); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     using ASTVisitor::visit; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QMap<QByteArray, ClassSpecifierAST *> classMap; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QByteArray id_cast(NameAST *name) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         if (! name) | 
					
						
							|  |  |  |             return QByteArray(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Identifier *id = identifier(name->asSimpleName()->identifier_token); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return QByteArray::fromRawData(id->chars(), id->size()); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     void visitMembers(Class *klass) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |         for (unsigned i = 0; i < klass->memberCount(); ++i) { | 
					
						
							|  |  |  |             Symbol *member = klass->memberAt(i); | 
					
						
							|  |  |  |             if (! member->name()) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             Identifier *id = member->name()->identifier(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (! id) | 
					
						
							|  |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             const QByteArray memberName = QByteArray::fromRawData(id->chars(), id->size()); | 
					
						
							|  |  |  |             if (member->type().isUnsigned() && memberName.endsWith("_token")) { | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-16 13:38:37 +01:00
										 |  |  |                 *out | 
					
						
							|  |  |  |                         << "    pattern->" << memberName << " = node->" << memberName << ";" << endl | 
					
						
							|  |  |  |                         << endl; | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             } else if (PointerType *ptrTy = member->type()->asPointerType()) { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (NamedType *namedTy = ptrTy->elementType()->asNamedType()) { | 
					
						
							|  |  |  |                     QByteArray typeName = namedTy->name()->identifier()->chars(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |                     if (typeName.endsWith("AST")) { | 
					
						
							| 
									
										
										
										
											2009-11-16 13:38:37 +01:00
										 |  |  |                         *out | 
					
						
							|  |  |  |                                 << "    if (! pattern->" << memberName << ")" << endl | 
					
						
							|  |  |  |                                 << "        pattern->" << memberName << " = node->" << memberName << ";" << endl | 
					
						
							|  |  |  |                                 << "    else if (! AST::match(node->" << memberName << ", pattern->" << memberName << ", this))" << endl | 
					
						
							|  |  |  |                                 << "        return false;" << endl | 
					
						
							|  |  |  |                                 << endl; | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         for (unsigned i = 0; i < klass->baseClassCount(); ++i) { | 
					
						
							|  |  |  |             const QByteArray baseClassName = klass->baseClassAt(i)->identifier()->chars(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             if (ClassSpecifierAST *baseClassSpec = classMap.value(baseClassName, 0)) { | 
					
						
							|  |  |  |                 visitMembers(baseClassSpec->symbol); | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     bool checkMethod(Symbol *accept0Method) const | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Declaration *decl = accept0Method->asDeclaration(); | 
					
						
							|  |  |  |         if (! decl) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         Function *funTy = decl->type()->asFunctionType(); | 
					
						
							|  |  |  |         if (! funTy) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         else if (funTy->isPureVirtual()) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     virtual bool visit(ClassSpecifierAST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Class *klass = ast->symbol; | 
					
						
							|  |  |  |         const QByteArray className = id_cast(ast->name); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |         Identifier *match0_id = control()->findOrInsertIdentifier("match0"); | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |         Symbol *match0Method = klass->members()->lookat(match0_id); | 
					
						
							|  |  |  |         for (; match0Method; match0Method = match0Method->next()) { | 
					
						
							|  |  |  |             if (match0Method->identifier() != match0_id) | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |                 continue; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |             if (checkMethod(match0Method)) | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |                 break; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |         if (! match0Method) | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |             return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         classMap.insert(className, ast); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *out | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |                 << "bool ASTMatcher::match(" << className.constData() << " *node, " << className.constData() << " *pattern)" << endl | 
					
						
							| 
									
										
										
										
											2009-11-16 13:38:37 +01:00
										 |  |  |                 << "{" << endl | 
					
						
							|  |  |  |                 << "    (void) node;" << endl | 
					
						
							|  |  |  |                 << "    (void) pattern;" << endl | 
					
						
							|  |  |  |                 << endl; | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         visitMembers(klass); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         *out | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |                 << "    return true;" << endl | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |                 << "}" << endl | 
					
						
							|  |  |  |                 << endl; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | class RemoveCastMethods: protected ASTVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     RemoveCastMethods(Document::Ptr doc, QTextDocument *document) | 
					
						
							|  |  |  |         : ASTVisitor(doc->control()), document(document) {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<QTextCursor> operator()(AST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         _cursors.clear(); | 
					
						
							|  |  |  |         accept(ast); | 
					
						
							|  |  |  |         return _cursors; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     virtual bool visit(FunctionDefinitionAST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         Function *fun = ast->symbol; | 
					
						
							|  |  |  |         const QString functionName = oo(fun->name()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (functionName.length() > 3 && functionName.startsWith(QLatin1String("as")) | 
					
						
							|  |  |  |             && functionName.at(2).isUpper()) { | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:42:55 +01:00
										 |  |  |             QTextCursor tc = createCursor(translationUnit(), ast, document); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |             //qDebug() << qPrintable(tc.selectedText());
 | 
					
						
							|  |  |  |             _cursors.append(tc); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     QTextDocument *document; | 
					
						
							|  |  |  |     QList<QTextCursor> _cursors; | 
					
						
							|  |  |  |     Overview oo; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-16 13:38:37 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:42:55 +01:00
										 |  |  | QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir) | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2009-11-09 15:42:55 +01:00
										 |  |  |     QStringList astDerivedClasses; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     QFileInfo fileAST_h(cplusplusDir, QLatin1String("AST.h")); | 
					
						
							|  |  |  |     Q_ASSERT(fileAST_h.exists()); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     const QString fileName = fileAST_h.absoluteFilePath(); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     QFile file(fileName); | 
					
						
							|  |  |  |     if (! file.open(QFile::ReadOnly)) | 
					
						
							| 
									
										
										
										
											2009-11-09 15:42:55 +01:00
										 |  |  |         return astDerivedClasses; | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     const QString source = QTextStream(&file).readAll(); | 
					
						
							|  |  |  |     file.close(); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     QTextDocument document; | 
					
						
							|  |  |  |     document.setPlainText(source); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     Document::Ptr doc = Document::create(fileName); | 
					
						
							|  |  |  |     const QByteArray preprocessedCode = snapshot.preprocessedCode(source, fileName); | 
					
						
							|  |  |  |     doc->setSource(preprocessedCode); | 
					
						
							|  |  |  |     doc->check(); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     FindASTNodes process(doc, &document); | 
					
						
							| 
									
										
										
										
											2009-11-16 13:38:37 +01:00
										 |  |  |     astNodes = process(doc->translationUnit()->ast()); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     RemoveCastMethods removeCastMethods(doc, &document); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     QList<QTextCursor> baseCastMethodCursors = removeCastMethods(astNodes.base); | 
					
						
							|  |  |  |     QMap<ClassSpecifierAST *, QList<QTextCursor> > cursors; | 
					
						
							|  |  |  |     QMap<ClassSpecifierAST *, QString> replacementCastMethods; | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     Overview oo; | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     QStringList castMethods; | 
					
						
							|  |  |  |     foreach (ClassSpecifierAST *classAST, astNodes.deriveds) { | 
					
						
							|  |  |  |         cursors[classAST] = removeCastMethods(classAST); | 
					
						
							|  |  |  |         const QString className = oo(classAST->symbol->name()); | 
					
						
							|  |  |  |         const QString methodName = QLatin1String("as") + className.mid(0, className.length() - 3); | 
					
						
							|  |  |  |         replacementCastMethods[classAST] = QString("    virtual %1 *%2() { return this; }\n").arg(className, methodName); | 
					
						
							|  |  |  |         castMethods.append(QString("    virtual %1 *%2() { return 0; }\n").arg(className, methodName)); | 
					
						
							| 
									
										
										
										
											2009-11-09 15:42:55 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |         astDerivedClasses.append(className); | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     if (! baseCastMethodCursors.isEmpty()) { | 
					
						
							|  |  |  |         castMethods.sort(); | 
					
						
							|  |  |  |         for (int i = 0; i < baseCastMethodCursors.length(); ++i) { | 
					
						
							|  |  |  |             baseCastMethodCursors[i].removeSelectedText(); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |         baseCastMethodCursors.first().insertText(castMethods.join(QLatin1String(""))); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int classIndex = 0; classIndex < astNodes.deriveds.size(); ++classIndex) { | 
					
						
							|  |  |  |         ClassSpecifierAST *classAST = astNodes.deriveds.at(classIndex); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |         // remove the cast methods.
 | 
					
						
							|  |  |  |         QList<QTextCursor> c = cursors.value(classAST); | 
					
						
							|  |  |  |         for (int i = 0; i < c.length(); ++i) { | 
					
						
							|  |  |  |             c[i].removeSelectedText(); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |         astNodes.endOfPublicClassSpecifiers[classIndex].insertText(replacementCastMethods.value(classAST)); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     if (file.open(QFile::WriteOnly)) { | 
					
						
							|  |  |  |         QTextStream out(&file); | 
					
						
							|  |  |  |         out << document.toPlainText(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-09 15:42:55 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |     Accept0CG cg(cplusplusDir, doc->control()); | 
					
						
							| 
									
										
										
										
											2009-11-09 16:28:01 +01:00
										 |  |  |     cg(doc->translationUnit()->ast()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |     Match0CG cg2(cplusplusDir, doc->control()); | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |     cg2(doc->translationUnit()->ast()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-13 11:35:19 +01:00
										 |  |  |     MatcherCPPCG cg3(cplusplusDir, doc->control()); | 
					
						
							|  |  |  |     cg3(doc->translationUnit()->ast()); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:42:55 +01:00
										 |  |  |     return astDerivedClasses; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class FindASTForwards: protected ASTVisitor | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | public: | 
					
						
							|  |  |  |     FindASTForwards(Document::Ptr doc, QTextDocument *document) | 
					
						
							|  |  |  |         : ASTVisitor(doc->control()), document(document) | 
					
						
							|  |  |  |     {} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QList<QTextCursor> operator()(AST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         accept(ast); | 
					
						
							|  |  |  |         return _cursors; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | protected: | 
					
						
							|  |  |  |     bool visit(SimpleDeclarationAST *ast) | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2009-11-12 17:35:48 +01:00
										 |  |  |         if (! ast->decl_specifier_list) | 
					
						
							|  |  |  |             return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (ElaboratedTypeSpecifierAST *e = ast->decl_specifier_list->value->asElaboratedTypeSpecifier()) { | 
					
						
							|  |  |  |             if (tokenKind(e->classkey_token) == T_CLASS && !ast->declarator_list) { | 
					
						
							| 
									
										
										
										
											2009-11-09 15:42:55 +01:00
										 |  |  |                 QString className = oo(e->name->name); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 if (className.length() > 3 && className.endsWith(QLatin1String("AST"))) { | 
					
						
							|  |  |  |                     QTextCursor tc = createCursor(translationUnit(), ast, document); | 
					
						
							|  |  |  |                     _cursors.append(tc); | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | private: | 
					
						
							|  |  |  |     QTextDocument *document; | 
					
						
							|  |  |  |     QList<QTextCursor> _cursors; | 
					
						
							|  |  |  |     Overview oo; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void generateASTFwd_h(const Snapshot &snapshot, const QDir &cplusplusDir, const QStringList &astDerivedClasses) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QFileInfo fileASTFwd_h(cplusplusDir, QLatin1String("ASTfwd.h")); | 
					
						
							|  |  |  |     Q_ASSERT(fileASTFwd_h.exists()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QString fileName = fileASTFwd_h.absoluteFilePath(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QFile file(fileName); | 
					
						
							|  |  |  |     if (! file.open(QFile::ReadOnly)) | 
					
						
							|  |  |  |         return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     const QString source = QTextStream(&file).readAll(); | 
					
						
							|  |  |  |     file.close(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QTextDocument document; | 
					
						
							|  |  |  |     document.setPlainText(source); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     Document::Ptr doc = Document::create(fileName); | 
					
						
							|  |  |  |     const QByteArray preprocessedCode = snapshot.preprocessedCode(source, fileName); | 
					
						
							|  |  |  |     doc->setSource(preprocessedCode); | 
					
						
							|  |  |  |     doc->check(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     FindASTForwards process(doc, &document); | 
					
						
							|  |  |  |     QList<QTextCursor> cursors = process(doc->translationUnit()->ast()); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     for (int i = 0; i < cursors.length(); ++i) | 
					
						
							|  |  |  |         cursors[i].removeSelectedText(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     QString replacement; | 
					
						
							|  |  |  |     foreach (const QString &astDerivedClass, astDerivedClasses) { | 
					
						
							|  |  |  |         replacement += QString(QLatin1String("class %1;\n")).arg(astDerivedClass); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     cursors.first().insertText(replacement); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     if (file.open(QFile::WriteOnly)) { | 
					
						
							|  |  |  |         QTextStream out(&file); | 
					
						
							|  |  |  |         out << document.toPlainText(); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  | int main(int argc, char *argv[]) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |     QCoreApplication app(argc, argv); | 
					
						
							|  |  |  |     QStringList files = app.arguments(); | 
					
						
							|  |  |  |     files.removeFirst(); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  |     if (files.isEmpty()) { | 
					
						
							|  |  |  |         std::cerr << "Usage: cplusplus [path to C++ front-end]" << std::endl; | 
					
						
							|  |  |  |         return EXIT_FAILURE; | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  |     } | 
					
						
							| 
									
										
										
										
											2009-11-09 15:10:03 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  |     QDir cplusplusDir(files.first()); | 
					
						
							|  |  |  |     Snapshot snapshot; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-11-09 15:42:55 +01:00
										 |  |  |     QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir); | 
					
						
							|  |  |  |     astDerivedClasses.sort(); | 
					
						
							|  |  |  |     generateASTFwd_h(snapshot, cplusplusDir, astDerivedClasses); | 
					
						
							| 
									
										
										
										
											2009-11-09 12:50:00 +01:00
										 |  |  | } |