diff --git a/clang/include/clang/ExtractAPI/FrontendActions.h b/clang/include/clang/ExtractAPI/FrontendActions.h --- a/clang/include/clang/ExtractAPI/FrontendActions.h +++ b/clang/include/clang/ExtractAPI/FrontendActions.h @@ -14,6 +14,7 @@ #ifndef LLVM_CLANG_EXTRACTAPI_FRONTEND_ACTIONS_H #define LLVM_CLANG_EXTRACTAPI_FRONTEND_ACTIONS_H +#include "clang/ExtractAPI/API.h" #include "clang/Frontend/FrontendAction.h" namespace clang { @@ -25,11 +26,19 @@ StringRef InFile) override; private: + /// A representation of the APIs this action extracts. + std::unique_ptr API; + + /// A stream to the output file of this action. + std::unique_ptr OS; + + /// The product this action is extracting API information for. + std::string ProductName; + /// The synthesized input buffer that contains all the provided input header /// files. std::unique_ptr Buffer; -public: /// Prepare to execute the action on the given CompilerInstance. /// /// This is called before executing the action on any inputs. This generates a @@ -37,8 +46,15 @@ /// list with it before actually executing the action. bool PrepareToExecuteAction(CompilerInstance &CI) override; + /// Called after executing the action on the synthesized input buffer. + /// + /// Note: Now that we have gathered all the API definitions to surface we can + /// emit them in this callback. + void EndSourceFileAction() override; + static std::unique_ptr CreateOutputFile(CompilerInstance &CI, StringRef InFile); + static StringRef getInputBufferName() { return ""; } }; diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp --- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp +++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp @@ -41,9 +41,8 @@ /// information. class ExtractAPIVisitor : public RecursiveASTVisitor { public: - explicit ExtractAPIVisitor(ASTContext &Context) - : Context(Context), - API(Context.getTargetInfo().getTriple(), Context.getLangOpts()) {} + ExtractAPIVisitor(ASTContext &Context, APISet &API) + : Context(Context), API(API) {} const APISet &getAPI() const { return API; } @@ -304,42 +303,38 @@ } ASTContext &Context; - APISet API; + APISet &API; }; class ExtractAPIConsumer : public ASTConsumer { public: - ExtractAPIConsumer(ASTContext &Context, StringRef ProductName, - std::unique_ptr OS) - : Visitor(Context), ProductName(ProductName), OS(std::move(OS)) {} + ExtractAPIConsumer(ASTContext &Context, APISet &API) + : Visitor(Context, API) {} void HandleTranslationUnit(ASTContext &Context) override { // Use ExtractAPIVisitor to traverse symbol declarations in the context. Visitor.TraverseDecl(Context.getTranslationUnitDecl()); - - // Setup a SymbolGraphSerializer to write out collected API information in - // the Symbol Graph format. - // FIXME: Make the kind of APISerializer configurable. - SymbolGraphSerializer SGSerializer(Visitor.getAPI(), ProductName); - SGSerializer.serialize(*OS); } private: ExtractAPIVisitor Visitor; - std::string ProductName; - std::unique_ptr OS; }; } // namespace std::unique_ptr ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { - std::unique_ptr OS = CreateOutputFile(CI, InFile); + OS = CreateOutputFile(CI, InFile); if (!OS) return nullptr; - return std::make_unique( - CI.getASTContext(), CI.getInvocation().getFrontendOpts().ProductName, - std::move(OS)); + + ProductName = CI.getFrontendOpts().ProductName; + + // Now that we have enough information about the language options and the + // target triple, let's create the APISet before anyone uses it. + API = std::make_unique(CI.getTarget().getTriple(), CI.getLangOpts()); + + return std::make_unique(CI.getASTContext(), *API); } bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) { @@ -371,6 +366,18 @@ return true; } +void ExtractAPIAction::EndSourceFileAction() { + if (!OS) + return; + + // Setup a SymbolGraphSerializer to write out collected API information in + // the Symbol Graph format. + // FIXME: Make the kind of APISerializer configurable. + SymbolGraphSerializer SGSerializer(*API, ProductName); + SGSerializer.serialize(*OS); + OS->flush(); +} + std::unique_ptr ExtractAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) { std::unique_ptr OS =