189f6b26fSZixu Wang //===- ExtractAPI/ExtractAPIConsumer.cpp ------------------------*- C++ -*-===// 289f6b26fSZixu Wang // 389f6b26fSZixu Wang // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 489f6b26fSZixu Wang // See https://llvm.org/LICENSE.txt for license information. 589f6b26fSZixu Wang // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 689f6b26fSZixu Wang // 789f6b26fSZixu Wang //===----------------------------------------------------------------------===// 889f6b26fSZixu Wang /// 989f6b26fSZixu Wang /// \file 1089f6b26fSZixu Wang /// This file implements the ExtractAPIAction, and ASTVisitor/Consumer to 1189f6b26fSZixu Wang /// collect API information. 1289f6b26fSZixu Wang /// 1389f6b26fSZixu Wang //===----------------------------------------------------------------------===// 1489f6b26fSZixu Wang 1589f6b26fSZixu Wang #include "clang/AST/ASTConsumer.h" 1689f6b26fSZixu Wang #include "clang/AST/ASTContext.h" 1789f6b26fSZixu Wang #include "clang/AST/Decl.h" 1889f6b26fSZixu Wang #include "clang/AST/DeclCXX.h" 1989f6b26fSZixu Wang #include "clang/AST/ParentMapContext.h" 2089f6b26fSZixu Wang #include "clang/AST/RawCommentList.h" 2189f6b26fSZixu Wang #include "clang/AST/RecursiveASTVisitor.h" 2289f6b26fSZixu Wang #include "clang/Basic/TargetInfo.h" 2389f6b26fSZixu Wang #include "clang/ExtractAPI/API.h" 2489f6b26fSZixu Wang #include "clang/ExtractAPI/AvailabilityInfo.h" 2589f6b26fSZixu Wang #include "clang/ExtractAPI/DeclarationFragments.h" 2689f6b26fSZixu Wang #include "clang/ExtractAPI/FrontendActions.h" 2789f6b26fSZixu Wang #include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h" 2889f6b26fSZixu Wang #include "clang/Frontend/ASTConsumers.h" 2989f6b26fSZixu Wang #include "clang/Frontend/CompilerInstance.h" 30f833aab0SDaniel Grumberg #include "clang/Frontend/FrontendOptions.h" 31f833aab0SDaniel Grumberg #include "llvm/ADT/SmallVector.h" 32f833aab0SDaniel Grumberg #include "llvm/Support/MemoryBuffer.h" 3389f6b26fSZixu Wang #include "llvm/Support/raw_ostream.h" 3489f6b26fSZixu Wang 3589f6b26fSZixu Wang using namespace clang; 3689f6b26fSZixu Wang using namespace extractapi; 3789f6b26fSZixu Wang 3889f6b26fSZixu Wang namespace { 3989f6b26fSZixu Wang 4089f6b26fSZixu Wang /// The RecursiveASTVisitor to traverse symbol declarations and collect API 4189f6b26fSZixu Wang /// information. 4289f6b26fSZixu Wang class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> { 4389f6b26fSZixu Wang public: 44*15bf0e56SZixu Wang ExtractAPIVisitor(ASTContext &Context, Language Lang) 45*15bf0e56SZixu Wang : Context(Context), API(Context.getTargetInfo().getTriple(), Lang) {} 4689f6b26fSZixu Wang 4789f6b26fSZixu Wang const APISet &getAPI() const { return API; } 4889f6b26fSZixu Wang 4989f6b26fSZixu Wang bool VisitVarDecl(const VarDecl *Decl) { 5089f6b26fSZixu Wang // Skip function parameters. 5189f6b26fSZixu Wang if (isa<ParmVarDecl>(Decl)) 5289f6b26fSZixu Wang return true; 5389f6b26fSZixu Wang 5489f6b26fSZixu Wang // Skip non-global variables in records (struct/union/class). 5589f6b26fSZixu Wang if (Decl->getDeclContext()->isRecord()) 5689f6b26fSZixu Wang return true; 5789f6b26fSZixu Wang 5889f6b26fSZixu Wang // Skip local variables inside function or method. 5989f6b26fSZixu Wang if (!Decl->isDefinedOutsideFunctionOrMethod()) 6089f6b26fSZixu Wang return true; 6189f6b26fSZixu Wang 6289f6b26fSZixu Wang // If this is a template but not specialization or instantiation, skip. 6389f6b26fSZixu Wang if (Decl->getASTContext().getTemplateOrSpecializationInfo(Decl) && 6489f6b26fSZixu Wang Decl->getTemplateSpecializationKind() == TSK_Undeclared) 6589f6b26fSZixu Wang return true; 6689f6b26fSZixu Wang 6789f6b26fSZixu Wang // Collect symbol information. 6889f6b26fSZixu Wang StringRef Name = Decl->getName(); 6989f6b26fSZixu Wang StringRef USR = API.recordUSR(Decl); 7089f6b26fSZixu Wang PresumedLoc Loc = 7189f6b26fSZixu Wang Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 7289f6b26fSZixu Wang AvailabilityInfo Availability = getAvailability(Decl); 7389f6b26fSZixu Wang LinkageInfo Linkage = Decl->getLinkageAndVisibility(); 7489f6b26fSZixu Wang DocComment Comment; 7589f6b26fSZixu Wang if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl)) 7689f6b26fSZixu Wang Comment = RawComment->getFormattedLines(Context.getSourceManager(), 7789f6b26fSZixu Wang Context.getDiagnostics()); 7889f6b26fSZixu Wang 7989f6b26fSZixu Wang // Build declaration fragments and sub-heading for the variable. 8089f6b26fSZixu Wang DeclarationFragments Declaration = 8189f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForVar(Decl); 8289f6b26fSZixu Wang DeclarationFragments SubHeading = 8389f6b26fSZixu Wang DeclarationFragmentsBuilder::getSubHeading(Decl); 8489f6b26fSZixu Wang 8589f6b26fSZixu Wang // Add the global variable record to the API set. 8689f6b26fSZixu Wang API.addGlobalVar(Name, USR, Loc, Availability, Linkage, Comment, 8789f6b26fSZixu Wang Declaration, SubHeading); 8889f6b26fSZixu Wang return true; 8989f6b26fSZixu Wang } 9089f6b26fSZixu Wang 9189f6b26fSZixu Wang bool VisitFunctionDecl(const FunctionDecl *Decl) { 9289f6b26fSZixu Wang if (const auto *Method = dyn_cast<CXXMethodDecl>(Decl)) { 9389f6b26fSZixu Wang // Skip member function in class templates. 9489f6b26fSZixu Wang if (Method->getParent()->getDescribedClassTemplate() != nullptr) 9589f6b26fSZixu Wang return true; 9689f6b26fSZixu Wang 9789f6b26fSZixu Wang // Skip methods in records. 9889f6b26fSZixu Wang for (auto P : Context.getParents(*Method)) { 9989f6b26fSZixu Wang if (P.get<CXXRecordDecl>()) 10089f6b26fSZixu Wang return true; 10189f6b26fSZixu Wang } 10289f6b26fSZixu Wang 10389f6b26fSZixu Wang // Skip ConstructorDecl and DestructorDecl. 10489f6b26fSZixu Wang if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method)) 10589f6b26fSZixu Wang return true; 10689f6b26fSZixu Wang } 10789f6b26fSZixu Wang 10889f6b26fSZixu Wang // Skip templated functions. 10989f6b26fSZixu Wang switch (Decl->getTemplatedKind()) { 11089f6b26fSZixu Wang case FunctionDecl::TK_NonTemplate: 11189f6b26fSZixu Wang break; 11289f6b26fSZixu Wang case FunctionDecl::TK_MemberSpecialization: 11389f6b26fSZixu Wang case FunctionDecl::TK_FunctionTemplateSpecialization: 11489f6b26fSZixu Wang if (auto *TemplateInfo = Decl->getTemplateSpecializationInfo()) { 11589f6b26fSZixu Wang if (!TemplateInfo->isExplicitInstantiationOrSpecialization()) 11689f6b26fSZixu Wang return true; 11789f6b26fSZixu Wang } 11889f6b26fSZixu Wang break; 11989f6b26fSZixu Wang case FunctionDecl::TK_FunctionTemplate: 12089f6b26fSZixu Wang case FunctionDecl::TK_DependentFunctionTemplateSpecialization: 12189f6b26fSZixu Wang return true; 12289f6b26fSZixu Wang } 12389f6b26fSZixu Wang 12489f6b26fSZixu Wang // Collect symbol information. 12589f6b26fSZixu Wang StringRef Name = Decl->getName(); 12689f6b26fSZixu Wang StringRef USR = API.recordUSR(Decl); 12789f6b26fSZixu Wang PresumedLoc Loc = 12889f6b26fSZixu Wang Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 12989f6b26fSZixu Wang AvailabilityInfo Availability = getAvailability(Decl); 13089f6b26fSZixu Wang LinkageInfo Linkage = Decl->getLinkageAndVisibility(); 13189f6b26fSZixu Wang DocComment Comment; 13289f6b26fSZixu Wang if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl)) 13389f6b26fSZixu Wang Comment = RawComment->getFormattedLines(Context.getSourceManager(), 13489f6b26fSZixu Wang Context.getDiagnostics()); 13589f6b26fSZixu Wang 13689f6b26fSZixu Wang // Build declaration fragments, sub-heading, and signature of the function. 13789f6b26fSZixu Wang DeclarationFragments Declaration = 13889f6b26fSZixu Wang DeclarationFragmentsBuilder::getFragmentsForFunction(Decl); 13989f6b26fSZixu Wang DeclarationFragments SubHeading = 14089f6b26fSZixu Wang DeclarationFragmentsBuilder::getSubHeading(Decl); 14189f6b26fSZixu Wang FunctionSignature Signature = 14289f6b26fSZixu Wang DeclarationFragmentsBuilder::getFunctionSignature(Decl); 14389f6b26fSZixu Wang 14489f6b26fSZixu Wang // Add the function record to the API set. 14589f6b26fSZixu Wang API.addFunction(Name, USR, Loc, Availability, Linkage, Comment, Declaration, 14689f6b26fSZixu Wang SubHeading, Signature); 14789f6b26fSZixu Wang return true; 14889f6b26fSZixu Wang } 14989f6b26fSZixu Wang 15071b4c226SZixu Wang bool VisitEnumDecl(const EnumDecl *Decl) { 15171b4c226SZixu Wang if (!Decl->isComplete()) 15271b4c226SZixu Wang return true; 15371b4c226SZixu Wang 15471b4c226SZixu Wang // Skip forward declaration. 15571b4c226SZixu Wang if (!Decl->isThisDeclarationADefinition()) 15671b4c226SZixu Wang return true; 15771b4c226SZixu Wang 15871b4c226SZixu Wang // Collect symbol information. 15971b4c226SZixu Wang StringRef Name = Decl->getName(); 16071b4c226SZixu Wang StringRef USR = API.recordUSR(Decl); 16171b4c226SZixu Wang PresumedLoc Loc = 16271b4c226SZixu Wang Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 16371b4c226SZixu Wang AvailabilityInfo Availability = getAvailability(Decl); 16471b4c226SZixu Wang DocComment Comment; 16571b4c226SZixu Wang if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl)) 16671b4c226SZixu Wang Comment = RawComment->getFormattedLines(Context.getSourceManager(), 16771b4c226SZixu Wang Context.getDiagnostics()); 16871b4c226SZixu Wang 16971b4c226SZixu Wang // Build declaration fragments and sub-heading for the enum. 17071b4c226SZixu Wang DeclarationFragments Declaration = 17171b4c226SZixu Wang DeclarationFragmentsBuilder::getFragmentsForEnum(Decl); 17271b4c226SZixu Wang DeclarationFragments SubHeading = 17371b4c226SZixu Wang DeclarationFragmentsBuilder::getSubHeading(Decl); 17471b4c226SZixu Wang 17571b4c226SZixu Wang EnumRecord *EnumRecord = API.addEnum(Name, USR, Loc, Availability, Comment, 17671b4c226SZixu Wang Declaration, SubHeading); 17771b4c226SZixu Wang 17871b4c226SZixu Wang // Now collect information about the enumerators in this enum. 17971b4c226SZixu Wang recordEnumConstants(EnumRecord, Decl->enumerators()); 18071b4c226SZixu Wang 18171b4c226SZixu Wang return true; 18271b4c226SZixu Wang } 18371b4c226SZixu Wang 1845bb5704cSZixu Wang bool VisitRecordDecl(const RecordDecl *Decl) { 1855bb5704cSZixu Wang if (!Decl->isCompleteDefinition()) 1865bb5704cSZixu Wang return true; 1875bb5704cSZixu Wang 1885bb5704cSZixu Wang // Skip C++ structs/classes/unions 1895bb5704cSZixu Wang // TODO: support C++ records 1905bb5704cSZixu Wang if (isa<CXXRecordDecl>(Decl)) 1915bb5704cSZixu Wang return true; 1925bb5704cSZixu Wang 1935bb5704cSZixu Wang // Collect symbol information. 1945bb5704cSZixu Wang StringRef Name = Decl->getName(); 1955bb5704cSZixu Wang StringRef USR = API.recordUSR(Decl); 1965bb5704cSZixu Wang PresumedLoc Loc = 1975bb5704cSZixu Wang Context.getSourceManager().getPresumedLoc(Decl->getLocation()); 1985bb5704cSZixu Wang AvailabilityInfo Availability = getAvailability(Decl); 1995bb5704cSZixu Wang DocComment Comment; 2005bb5704cSZixu Wang if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl)) 2015bb5704cSZixu Wang Comment = RawComment->getFormattedLines(Context.getSourceManager(), 2025bb5704cSZixu Wang Context.getDiagnostics()); 2035bb5704cSZixu Wang 2045bb5704cSZixu Wang // Build declaration fragments and sub-heading for the struct. 2055bb5704cSZixu Wang DeclarationFragments Declaration = 2065bb5704cSZixu Wang DeclarationFragmentsBuilder::getFragmentsForStruct(Decl); 2075bb5704cSZixu Wang DeclarationFragments SubHeading = 2085bb5704cSZixu Wang DeclarationFragmentsBuilder::getSubHeading(Decl); 2095bb5704cSZixu Wang 2105bb5704cSZixu Wang StructRecord *StructRecord = API.addStruct( 2115bb5704cSZixu Wang Name, USR, Loc, Availability, Comment, Declaration, SubHeading); 2125bb5704cSZixu Wang 2135bb5704cSZixu Wang // Now collect information about the fields in this struct. 2145bb5704cSZixu Wang recordStructFields(StructRecord, Decl->fields()); 2155bb5704cSZixu Wang 2165bb5704cSZixu Wang return true; 2175bb5704cSZixu Wang } 2185bb5704cSZixu Wang 21989f6b26fSZixu Wang private: 22089f6b26fSZixu Wang /// Get availability information of the declaration \p D. 22189f6b26fSZixu Wang AvailabilityInfo getAvailability(const Decl *D) const { 22289f6b26fSZixu Wang StringRef PlatformName = Context.getTargetInfo().getPlatformName(); 22389f6b26fSZixu Wang 22489f6b26fSZixu Wang AvailabilityInfo Availability; 22589f6b26fSZixu Wang // Collect availability attributes from all redeclarations. 22689f6b26fSZixu Wang for (const auto *RD : D->redecls()) { 22789f6b26fSZixu Wang for (const auto *A : RD->specific_attrs<AvailabilityAttr>()) { 22889f6b26fSZixu Wang if (A->getPlatform()->getName() != PlatformName) 22989f6b26fSZixu Wang continue; 23089f6b26fSZixu Wang Availability = AvailabilityInfo(A->getIntroduced(), A->getDeprecated(), 23189f6b26fSZixu Wang A->getObsoleted(), A->getUnavailable(), 23289f6b26fSZixu Wang /* UnconditionallyDeprecated */ false, 23389f6b26fSZixu Wang /* UnconditionallyUnavailable */ false); 23489f6b26fSZixu Wang break; 23589f6b26fSZixu Wang } 23689f6b26fSZixu Wang 23789f6b26fSZixu Wang if (const auto *A = RD->getAttr<UnavailableAttr>()) 23889f6b26fSZixu Wang if (!A->isImplicit()) { 23989f6b26fSZixu Wang Availability.Unavailable = true; 24089f6b26fSZixu Wang Availability.UnconditionallyUnavailable = true; 24189f6b26fSZixu Wang } 24289f6b26fSZixu Wang 24389f6b26fSZixu Wang if (const auto *A = RD->getAttr<DeprecatedAttr>()) 24489f6b26fSZixu Wang if (!A->isImplicit()) 24589f6b26fSZixu Wang Availability.UnconditionallyDeprecated = true; 24689f6b26fSZixu Wang } 24789f6b26fSZixu Wang 24889f6b26fSZixu Wang return Availability; 24989f6b26fSZixu Wang } 25089f6b26fSZixu Wang 25171b4c226SZixu Wang /// Collect API information for the enum constants and associate with the 25271b4c226SZixu Wang /// parent enum. 25371b4c226SZixu Wang void recordEnumConstants(EnumRecord *EnumRecord, 25471b4c226SZixu Wang const EnumDecl::enumerator_range Constants) { 25571b4c226SZixu Wang for (const auto *Constant : Constants) { 25671b4c226SZixu Wang // Collect symbol information. 25771b4c226SZixu Wang StringRef Name = Constant->getName(); 25871b4c226SZixu Wang StringRef USR = API.recordUSR(Constant); 25971b4c226SZixu Wang PresumedLoc Loc = 26071b4c226SZixu Wang Context.getSourceManager().getPresumedLoc(Constant->getLocation()); 26171b4c226SZixu Wang AvailabilityInfo Availability = getAvailability(Constant); 26271b4c226SZixu Wang DocComment Comment; 26371b4c226SZixu Wang if (auto *RawComment = Context.getRawCommentForDeclNoCache(Constant)) 26471b4c226SZixu Wang Comment = RawComment->getFormattedLines(Context.getSourceManager(), 26571b4c226SZixu Wang Context.getDiagnostics()); 26671b4c226SZixu Wang 26771b4c226SZixu Wang // Build declaration fragments and sub-heading for the enum constant. 26871b4c226SZixu Wang DeclarationFragments Declaration = 26971b4c226SZixu Wang DeclarationFragmentsBuilder::getFragmentsForEnumConstant(Constant); 27071b4c226SZixu Wang DeclarationFragments SubHeading = 27171b4c226SZixu Wang DeclarationFragmentsBuilder::getSubHeading(Constant); 27271b4c226SZixu Wang 27371b4c226SZixu Wang API.addEnumConstant(EnumRecord, Name, USR, Loc, Availability, Comment, 27471b4c226SZixu Wang Declaration, SubHeading); 27571b4c226SZixu Wang } 27671b4c226SZixu Wang } 27771b4c226SZixu Wang 2785bb5704cSZixu Wang /// Collect API information for the struct fields and associate with the 2795bb5704cSZixu Wang /// parent struct. 2805bb5704cSZixu Wang void recordStructFields(StructRecord *StructRecord, 2815bb5704cSZixu Wang const RecordDecl::field_range Fields) { 2825bb5704cSZixu Wang for (const auto *Field : Fields) { 2835bb5704cSZixu Wang // Collect symbol information. 2845bb5704cSZixu Wang StringRef Name = Field->getName(); 2855bb5704cSZixu Wang StringRef USR = API.recordUSR(Field); 2865bb5704cSZixu Wang PresumedLoc Loc = 2875bb5704cSZixu Wang Context.getSourceManager().getPresumedLoc(Field->getLocation()); 2885bb5704cSZixu Wang AvailabilityInfo Availability = getAvailability(Field); 2895bb5704cSZixu Wang DocComment Comment; 2905bb5704cSZixu Wang if (auto *RawComment = Context.getRawCommentForDeclNoCache(Field)) 2915bb5704cSZixu Wang Comment = RawComment->getFormattedLines(Context.getSourceManager(), 2925bb5704cSZixu Wang Context.getDiagnostics()); 2935bb5704cSZixu Wang 2945bb5704cSZixu Wang // Build declaration fragments and sub-heading for the struct field. 2955bb5704cSZixu Wang DeclarationFragments Declaration = 2965bb5704cSZixu Wang DeclarationFragmentsBuilder::getFragmentsForField(Field); 2975bb5704cSZixu Wang DeclarationFragments SubHeading = 2985bb5704cSZixu Wang DeclarationFragmentsBuilder::getSubHeading(Field); 2995bb5704cSZixu Wang 3005bb5704cSZixu Wang API.addStructField(StructRecord, Name, USR, Loc, Availability, Comment, 3015bb5704cSZixu Wang Declaration, SubHeading); 3025bb5704cSZixu Wang } 3035bb5704cSZixu Wang } 3045bb5704cSZixu Wang 30589f6b26fSZixu Wang ASTContext &Context; 30689f6b26fSZixu Wang APISet API; 30789f6b26fSZixu Wang }; 30889f6b26fSZixu Wang 30989f6b26fSZixu Wang class ExtractAPIConsumer : public ASTConsumer { 31089f6b26fSZixu Wang public: 311*15bf0e56SZixu Wang ExtractAPIConsumer(ASTContext &Context, StringRef ProductName, Language Lang, 3125ef2ec7eSDaniel Grumberg std::unique_ptr<raw_pwrite_stream> OS) 313*15bf0e56SZixu Wang : Visitor(Context, Lang), ProductName(ProductName), OS(std::move(OS)) {} 31489f6b26fSZixu Wang 31589f6b26fSZixu Wang void HandleTranslationUnit(ASTContext &Context) override { 31689f6b26fSZixu Wang // Use ExtractAPIVisitor to traverse symbol declarations in the context. 31789f6b26fSZixu Wang Visitor.TraverseDecl(Context.getTranslationUnitDecl()); 31889f6b26fSZixu Wang 31989f6b26fSZixu Wang // Setup a SymbolGraphSerializer to write out collected API information in 32089f6b26fSZixu Wang // the Symbol Graph format. 32189f6b26fSZixu Wang // FIXME: Make the kind of APISerializer configurable. 3225ef2ec7eSDaniel Grumberg SymbolGraphSerializer SGSerializer(Visitor.getAPI(), ProductName); 32389f6b26fSZixu Wang SGSerializer.serialize(*OS); 32489f6b26fSZixu Wang } 32589f6b26fSZixu Wang 32689f6b26fSZixu Wang private: 32789f6b26fSZixu Wang ExtractAPIVisitor Visitor; 3285ef2ec7eSDaniel Grumberg std::string ProductName; 32989f6b26fSZixu Wang std::unique_ptr<raw_pwrite_stream> OS; 33089f6b26fSZixu Wang }; 33189f6b26fSZixu Wang 33289f6b26fSZixu Wang } // namespace 33389f6b26fSZixu Wang 33489f6b26fSZixu Wang std::unique_ptr<ASTConsumer> 33589f6b26fSZixu Wang ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) { 33689f6b26fSZixu Wang std::unique_ptr<raw_pwrite_stream> OS = CreateOutputFile(CI, InFile); 33789f6b26fSZixu Wang if (!OS) 33889f6b26fSZixu Wang return nullptr; 3395ef2ec7eSDaniel Grumberg return std::make_unique<ExtractAPIConsumer>( 3405ef2ec7eSDaniel Grumberg CI.getASTContext(), CI.getInvocation().getFrontendOpts().ProductName, 341*15bf0e56SZixu Wang CI.getFrontendOpts().Inputs.back().getKind().getLanguage(), 34289f6b26fSZixu Wang std::move(OS)); 34389f6b26fSZixu Wang } 34489f6b26fSZixu Wang 345f833aab0SDaniel Grumberg bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) { 346f833aab0SDaniel Grumberg auto &Inputs = CI.getFrontendOpts().Inputs; 347f833aab0SDaniel Grumberg if (Inputs.empty()) 348f833aab0SDaniel Grumberg return true; 349f833aab0SDaniel Grumberg 350f833aab0SDaniel Grumberg auto Kind = Inputs[0].getKind(); 351f833aab0SDaniel Grumberg 352f833aab0SDaniel Grumberg // Convert the header file inputs into a single input buffer. 353f833aab0SDaniel Grumberg SmallString<256> HeaderContents; 354f833aab0SDaniel Grumberg for (const FrontendInputFile &FIF : Inputs) { 355f833aab0SDaniel Grumberg if (Kind.isObjectiveC()) 356f833aab0SDaniel Grumberg HeaderContents += "#import"; 357f833aab0SDaniel Grumberg else 358f833aab0SDaniel Grumberg HeaderContents += "#include"; 359f833aab0SDaniel Grumberg HeaderContents += " \""; 360f833aab0SDaniel Grumberg HeaderContents += FIF.getFile(); 361f833aab0SDaniel Grumberg HeaderContents += "\"\n"; 362f833aab0SDaniel Grumberg } 363f833aab0SDaniel Grumberg 364f833aab0SDaniel Grumberg Buffer = llvm::MemoryBuffer::getMemBufferCopy(HeaderContents, 365f833aab0SDaniel Grumberg getInputBufferName()); 366f833aab0SDaniel Grumberg 367f833aab0SDaniel Grumberg // Set that buffer up as our "real" input in the CompilerInstance. 368f833aab0SDaniel Grumberg Inputs.clear(); 369f833aab0SDaniel Grumberg Inputs.emplace_back(Buffer->getMemBufferRef(), Kind, /*IsSystem*/ false); 370f833aab0SDaniel Grumberg 371f833aab0SDaniel Grumberg return true; 372f833aab0SDaniel Grumberg } 373f833aab0SDaniel Grumberg 37489f6b26fSZixu Wang std::unique_ptr<raw_pwrite_stream> 37589f6b26fSZixu Wang ExtractAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) { 37689f6b26fSZixu Wang std::unique_ptr<raw_pwrite_stream> OS = 37789f6b26fSZixu Wang CI.createDefaultOutputFile(/*Binary=*/false, InFile, /*Extension=*/"json", 37889f6b26fSZixu Wang /*RemoveFileOnSignal=*/false); 37989f6b26fSZixu Wang if (!OS) 38089f6b26fSZixu Wang return nullptr; 38189f6b26fSZixu Wang return OS; 38289f6b26fSZixu Wang } 383