From: Manuel Klimek Date: Thu, 25 Oct 2012 08:49:11 +0000 (+0000) Subject: Adds the possibility to inject a callback that's called after each translation unit... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9fb6b27e6d584ac339363357335f8d6de3a652ac;p=clang Adds the possibility to inject a callback that's called after each translation unit is processed. This is important when one wants to deduplicate results during one run over a translation unit by pointer identity of AST nodes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@166671 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Tooling/Tooling.h b/include/clang/Tooling/Tooling.h index 5337a4fa01..a03bcb1bbb 100644 --- a/include/clang/Tooling/Tooling.h +++ b/include/clang/Tooling/Tooling.h @@ -74,6 +74,14 @@ public: template FrontendActionFactory *newFrontendActionFactory(); +/// \brief Called at the end of each source file when used with +/// \c newFrontendActionFactory. +class EndOfSourceFileCallback { +public: + virtual ~EndOfSourceFileCallback() {} + virtual void run() = 0; +}; + /// \brief Returns a new FrontendActionFactory for any type that provides an /// implementation of newASTConsumer(). /// @@ -87,7 +95,7 @@ FrontendActionFactory *newFrontendActionFactory(); /// newFrontendActionFactory(&Factory); template inline FrontendActionFactory *newFrontendActionFactory( - FactoryT *ConsumerFactory); + FactoryT *ConsumerFactory, EndOfSourceFileCallback *EndCallback = NULL); /// \brief Runs (and deletes) the tool on 'Code' with the -fsyntax-only flag. /// @@ -217,34 +225,45 @@ FrontendActionFactory *newFrontendActionFactory() { template inline FrontendActionFactory *newFrontendActionFactory( - FactoryT *ConsumerFactory) { + FactoryT *ConsumerFactory, EndOfSourceFileCallback *EndCallback) { class FrontendActionFactoryAdapter : public FrontendActionFactory { public: - explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory) - : ConsumerFactory(ConsumerFactory) {} + explicit FrontendActionFactoryAdapter(FactoryT *ConsumerFactory, + EndOfSourceFileCallback *EndCallback) + : ConsumerFactory(ConsumerFactory), EndCallback(EndCallback) {} virtual clang::FrontendAction *create() { - return new ConsumerFactoryAdaptor(ConsumerFactory); + return new ConsumerFactoryAdaptor(ConsumerFactory, EndCallback); } private: class ConsumerFactoryAdaptor : public clang::ASTFrontendAction { public: - ConsumerFactoryAdaptor(FactoryT *ConsumerFactory) - : ConsumerFactory(ConsumerFactory) {} + ConsumerFactoryAdaptor(FactoryT *ConsumerFactory, + EndOfSourceFileCallback *EndCallback) + : ConsumerFactory(ConsumerFactory), EndCallback(EndCallback) {} clang::ASTConsumer *CreateASTConsumer(clang::CompilerInstance &, llvm::StringRef) { return ConsumerFactory->newASTConsumer(); } + protected: + virtual void EndSourceFileAction() { + if (EndCallback != NULL) + EndCallback->run(); + clang::ASTFrontendAction::EndSourceFileAction(); + } + private: FactoryT *ConsumerFactory; + EndOfSourceFileCallback *EndCallback; }; FactoryT *ConsumerFactory; + EndOfSourceFileCallback *EndCallback; }; - return new FrontendActionFactoryAdapter(ConsumerFactory); + return new FrontendActionFactoryAdapter(ConsumerFactory, EndCallback); } /// \brief Returns the absolute path of \c File, by prepending it with diff --git a/unittests/Tooling/ToolingTest.cpp b/unittests/Tooling/ToolingTest.cpp index fb3af2678c..7846df3b93 100644 --- a/unittests/Tooling/ToolingTest.cpp +++ b/unittests/Tooling/ToolingTest.cpp @@ -130,5 +130,35 @@ TEST(ToolInvocation, TestMapVirtualFile) { EXPECT_TRUE(Invocation.run()); } +struct VerifyEndCallback : public EndOfSourceFileCallback { + VerifyEndCallback() : Called(0), Matched(false) {} + virtual void run() { + ++Called; + } + ASTConsumer *newASTConsumer() { + return new FindTopLevelDeclConsumer(&Matched); + } + unsigned Called; + bool Matched; +}; + +TEST(newFrontendActionFactory, InjectsEndOfSourceFileCallback) { + VerifyEndCallback EndCallback; + + FixedCompilationDatabase Compilations("/", std::vector()); + std::vector Sources; + Sources.push_back("/a.cc"); + Sources.push_back("/b.cc"); + ClangTool Tool(Compilations, Sources); + + Tool.mapVirtualFile("/a.cc", "void a() {}"); + Tool.mapVirtualFile("/b.cc", "void b() {}"); + + Tool.run(newFrontendActionFactory(&EndCallback, &EndCallback)); + + EXPECT_TRUE(EndCallback.Matched); + EXPECT_EQ(2u, EndCallback.Called); +} + } // end namespace tooling } // end namespace clang