diff --git a/src/shared/cplusplus/ASTfwd.h b/src/shared/cplusplus/ASTfwd.h index e0a5c59d9a6..8703e512e15 100644 --- a/src/shared/cplusplus/ASTfwd.h +++ b/src/shared/cplusplus/ASTfwd.h @@ -100,11 +100,12 @@ class ExpressionAST; class ExpressionListAST; class ExpressionOrDeclarationStatementAST; class ExpressionStatementAST; -class ForeachStatementAST; class ForStatementAST; +class ForeachStatementAST; class FunctionDeclaratorAST; class FunctionDefinitionAST; class GotoStatementAST; +class IdentifierListAST; class IfStatementAST; class LabeledStatementAST; class LinkageBodyAST; @@ -120,10 +121,42 @@ class NestedExpressionAST; class NestedNameSpecifierAST; class NewArrayDeclaratorAST; class NewExpressionAST; -class NewPlacementAST; class NewInitializerAST; +class NewPlacementAST; class NewTypeIdAST; class NumericLiteralAST; +class ObjCClassDeclarationAST; +class ObjCClassForwardDeclarationAST; +class ObjCDynamicPropertiesDeclarationAST; +class ObjCEncodeExpressionAST; +class ObjCFastEnumerationAST; +class ObjCInstanceVariablesDeclarationAST; +class ObjCMessageArgumentAST; +class ObjCMessageArgumentDeclarationAST; +class ObjCMessageArgumentDeclarationListAST; +class ObjCMessageArgumentListAST; +class ObjCMessageExpressionAST; +class ObjCMethodDeclarationAST; +class ObjCMethodPrototypeAST; +class ObjCPropertyAttributeAST; +class ObjCPropertyAttributeListAST; +class ObjCPropertyDeclarationAST; +class ObjCProtocolDeclarationAST; +class ObjCProtocolExpressionAST; +class ObjCProtocolForwardDeclarationAST; +class ObjCProtocolRefsAST; +class ObjCSelectorAST; +class ObjCSelectorArgumentAST; +class ObjCSelectorArgumentListAST; +class ObjCSelectorExpressionAST; +class ObjCSelectorWithArgumentsAST; +class ObjCSelectorWithoutArgumentsAST; +class ObjCSynchronizedStatementAST; +class ObjCSynthesizedPropertiesDeclarationAST; +class ObjCSynthesizedPropertyAST; +class ObjCSynthesizedPropertyListAST; +class ObjCTypeNameAST; +class ObjCVisibilityDeclarationAST; class OperatorAST; class OperatorFunctionIdAST; class ParameterDeclarationAST; @@ -135,6 +168,7 @@ class PostfixAST; class PostfixDeclaratorAST; class PostfixExpressionAST; class PtrOperatorAST; +class QtMethodAST; class QualifiedNameAST; class ReferenceAST; class ReturnStatementAST; @@ -165,42 +199,6 @@ class UnaryExpressionAST; class UsingAST; class UsingDirectiveAST; class WhileStatementAST; -class QtMethodAST; - -// ObjC++ -class IdentifierListAST; -class ObjCClassForwardDeclarationAST; -class ObjCClassDeclarationAST; -class ObjCProtocolForwardDeclarationAST; -class ObjCProtocolDeclarationAST; -class ObjCProtocolRefsAST; -class ObjCMessageExpressionAST; -class ObjCMessageArgumentListAST; -class ObjCMessageArgumentAST; -class ObjCProtocolExpressionAST; -class ObjCTypeNameAST; -class ObjCEncodeExpressionAST; -class ObjCSelectorAST; -class ObjCSelectorWithoutArgumentsAST; -class ObjCSelectorArgumentAST; -class ObjCSelectorArgumentListAST; -class ObjCSelectorWithArgumentsAST; -class ObjCSelectorExpressionAST; -class ObjCInstanceVariablesDeclarationAST; -class ObjCVisibilityDeclarationAST; -class ObjCPropertyDeclarationAST; -class ObjCPropertyAttributeListAST; -class ObjCPropertyAttributeAST; -class ObjCMethodPrototypeAST; -class ObjCMethodDeclarationAST; -class ObjCMessageArgumentDeclarationListAST; -class ObjCMessageArgumentDeclarationAST; -class ObjCSynthesizedPropertyAST; -class ObjCSynthesizedPropertyListAST; -class ObjCSynthesizedPropertiesDeclarationAST; -class ObjCDynamicPropertiesDeclarationAST; -class ObjCFastEnumerationAST; -class ObjCSynchronizedStatementAST; } // end of namespace CPlusPlus diff --git a/src/tools/cplusplus/Main.cpp b/src/tools/cplusplus/Main.cpp index 434b060ef35..a60d3c661e8 100644 --- a/src/tools/cplusplus/Main.cpp +++ b/src/tools/cplusplus/Main.cpp @@ -22,6 +22,34 @@ using namespace CPlusPlus; +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 ASTNodes { public: @@ -73,25 +101,8 @@ protected: Q_ASSERT(accessDeclaration != 0); - unsigned endLine, endColumn; - getTokenEndPosition(accessDeclaration->lastToken() - 1, &endLine, &endColumn); - - QTextCursor tc(document); - tc.setPosition(document->findBlockByNumber(endLine - 1).position() + endColumn - 1); - - 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 tc = createCursor(translationUnit(), accessDeclaration, document); + tc.setPosition(tc.position()); _nodes.endOfPublicClassSpecifiers.append(tc); } @@ -127,29 +138,8 @@ protected: if (functionName.length() > 3 && functionName.startsWith(QLatin1String("as")) && functionName.at(2).isUpper()) { - unsigned startLine, startColumn, endLine, endColumn; - getTokenStartPosition(ast->firstToken(), &startLine, &startColumn); - 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); + QTextCursor tc = createCursor(translationUnit(), ast, document); //qDebug() << qPrintable(tc.selectedText()); _cursors.append(tc); @@ -164,8 +154,10 @@ private: Overview oo; }; -void generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir) +QStringList generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir) { + QStringList astDerivedClasses; + QFileInfo fileAST_h(cplusplusDir, QLatin1String("AST.h")); Q_ASSERT(fileAST_h.exists()); @@ -173,7 +165,7 @@ void generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir) QFile file(fileName); if (! file.open(QFile::ReadOnly)) - return; + return astDerivedClasses; const QString source = QTextStream(&file).readAll(); file.close(); @@ -204,6 +196,8 @@ void generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir) 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)); + + astDerivedClasses.append(className); } if (! baseCastMethodCursors.isEmpty()) { @@ -231,6 +225,85 @@ void generateAST_H(const Snapshot &snapshot, const QDir &cplusplusDir) QTextStream out(&file); out << document.toPlainText(); } + + return astDerivedClasses; +} + +class FindASTForwards: protected ASTVisitor +{ +public: + FindASTForwards(Document::Ptr doc, QTextDocument *document) + : ASTVisitor(doc->control()), document(document) + {} + + QList operator()(AST *ast) + { + accept(ast); + return _cursors; + } + +protected: + bool visit(SimpleDeclarationAST *ast) + { + if (ElaboratedTypeSpecifierAST *e = ast->decl_specifier_seq->asElaboratedTypeSpecifier()) { + if (tokenKind(e->classkey_token) == T_CLASS && !ast->declarators) { + 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 _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 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(); + } } int main(int argc, char *argv[]) @@ -247,5 +320,7 @@ int main(int argc, char *argv[]) QDir cplusplusDir(files.first()); Snapshot snapshot; - generateAST_H(snapshot, cplusplusDir); + QStringList astDerivedClasses = generateAST_H(snapshot, cplusplusDir); + astDerivedClasses.sort(); + generateASTFwd_h(snapshot, cplusplusDir, astDerivedClasses); }