/* This file is part of KDevelop Copyright 2006 Hamish Rodda Copyright 2007-2009 David Nolden This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "testhelper.h" #include "parsesession.h" #include "parser.h" #include "rpp/preprocessor.h" #include "rpp/pp-engine.h" #include "declarationbuilder.h" #include "usebuilder.h" #include #include #include #include #include #include #include #include using namespace KDevelop; using namespace Cpp; void Cpp::release( TopDUContext* top ) { //KDevelop::EditorIntegrator::releaseTopRange(top->textRangePtr()); TopDUContextPointer tp(top); DUChain::self()->removeDocumentChain(static_cast(top)); Q_ASSERT(!tp); } //BEGIN LockedTopDUContext LockedTopDUContext::LockedTopDUContext( TopDUContext* top ) : m_top( top ) { } LockedTopDUContext::operator KDevelop::TopDUContext*() const { return m_top; } TopDUContext* LockedTopDUContext::operator->() const { return m_top; } LockedTopDUContext& LockedTopDUContext::operator=( TopDUContext * ctx ) { m_top = ctx; return *this; } LockedTopDUContext::~LockedTopDUContext() { DUChainWriteLocker lock; release( m_top ); } //BEGIN TestHelper void TestHelper::initShell() { AutoTestShell::init(QStringList() << "kdevcppsupport"); TestCore* core = new TestCore(); core->initialize(KDevelop::Core::NoUi); EnvironmentManager::init(); DUChain::self()->disablePersistentStorage(); KDevelop::CodeRepresentation::setDiskChangesForbidden(true); } TopDUContext* TestHelper::parse(const QByteArray& unit, DumpAreas dump, TopDUContext* update, bool keepAst) { m_modifications.clear(); m_ctlflowGraph.clear(); if (dump) kDebug(9007) << "==== Beginning new test case...:" << endl << unit; //If the AST flag is set, then the parse session needs to be owned by a shared pointer ParseSession::Ptr session(new ParseSession()); rpp::Preprocessor preprocessor; rpp::pp pp(&preprocessor); session->setContentsAndGenerateLocationTable(pp.processFile("anonymous", unit)); Parser parser(&control); TranslationUnitAST* ast = parser.parse(session.data()); ast->session = session.data(); if (dump & DumpAST) { kDebug(9007) << "===== AST:"; cppDumper.dump(ast, session.data()); } static int testNumber = 0; IndexedString url(QString("/internal/%1").arg(testNumber++)); DeclarationBuilder definitionBuilder(session.data()); Cpp::EnvironmentFilePointer file( new Cpp::EnvironmentFile( url, 0 ) ); //HACK Should actually use DUChain::updateContextForUrl kDebug() << "update->features & TopDUContext::AST: " << (update ? update->features() & TopDUContext::AST : 0); if(keepAst) { definitionBuilder.setMapAst(true); if (update) { DUChainWriteLocker lock(DUChain::lock()); update->setAst( IAstContainer::Ptr( session.data() ) ); } } TopDUContext* top = definitionBuilder.buildDeclarations(file, ast, 0, ReferencedTopDUContext(update)); if(update) { Q_ASSERT(top == update); } if (top && keepAst) { DUChainWriteLocker lock(DUChain::lock()); top->setAst( IAstContainer::Ptr( session.data() ) ); } UseBuilder useBuilder(session.data()); useBuilder.setMapAst(keepAst); useBuilder.buildUses(ast); UseDecoratorVisitor visit(session.data(), &m_modifications); visit.run(ast); ControlFlowGraphBuilder flowvisitor(ReferencedTopDUContext(top), session.data(), &m_ctlflowGraph); flowvisitor.run(ast); if (dump & DumpDUChain) { kDebug(9007) << "===== DUChain:"; DUChainWriteLocker lock(DUChain::lock()); dumpDUContext(top); } if (dump) kDebug(9007) << "===== Finished test case."; return top; } namespace Cpp { void dump(const TemplateDeclaration::InstantiationsHash& instantiations) { TemplateDeclaration::InstantiationsHash::const_iterator it = instantiations.constBegin(); while(it != instantiations.constEnd()) { qDebug() << it.key().information().toString(); ++it; } } QByteArray readCodeFile(const QString& file) { QFile f(QFileInfo(__FILE__).absolutePath() + QLatin1String("/data/") + file); qDebug() << f.fileName(); if (!f.open(QIODevice::ReadOnly)) { kWarning() << "Could not open test file" << file; return QByteArray(); } return f.readAll(); } }