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 
15*9fc45ca0SDaniel Grumberg #include "TypedefUnderlyingTypeResolver.h"
1689f6b26fSZixu Wang #include "clang/AST/ASTConsumer.h"
1789f6b26fSZixu Wang #include "clang/AST/ASTContext.h"
1889f6b26fSZixu Wang #include "clang/AST/Decl.h"
1989f6b26fSZixu Wang #include "clang/AST/DeclCXX.h"
2089f6b26fSZixu Wang #include "clang/AST/ParentMapContext.h"
2189f6b26fSZixu Wang #include "clang/AST/RawCommentList.h"
2289f6b26fSZixu Wang #include "clang/AST/RecursiveASTVisitor.h"
2389f6b26fSZixu Wang #include "clang/Basic/TargetInfo.h"
2489f6b26fSZixu Wang #include "clang/ExtractAPI/API.h"
2589f6b26fSZixu Wang #include "clang/ExtractAPI/AvailabilityInfo.h"
2689f6b26fSZixu Wang #include "clang/ExtractAPI/DeclarationFragments.h"
2789f6b26fSZixu Wang #include "clang/ExtractAPI/FrontendActions.h"
2889f6b26fSZixu Wang #include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h"
2989f6b26fSZixu Wang #include "clang/Frontend/ASTConsumers.h"
3089f6b26fSZixu Wang #include "clang/Frontend/CompilerInstance.h"
31f833aab0SDaniel Grumberg #include "clang/Frontend/FrontendOptions.h"
32529a0570SDaniel Grumberg #include "clang/Lex/MacroInfo.h"
33529a0570SDaniel Grumberg #include "clang/Lex/PPCallbacks.h"
34529a0570SDaniel Grumberg #include "clang/Lex/PreprocessorOptions.h"
35529a0570SDaniel Grumberg #include "llvm/ADT/STLExtras.h"
36f833aab0SDaniel Grumberg #include "llvm/ADT/SmallVector.h"
37f833aab0SDaniel Grumberg #include "llvm/Support/MemoryBuffer.h"
3889f6b26fSZixu Wang #include "llvm/Support/raw_ostream.h"
3989f6b26fSZixu Wang 
4089f6b26fSZixu Wang using namespace clang;
4189f6b26fSZixu Wang using namespace extractapi;
4289f6b26fSZixu Wang 
4389f6b26fSZixu Wang namespace {
4489f6b26fSZixu Wang 
45*9fc45ca0SDaniel Grumberg StringRef getTypedefName(const TagDecl *Decl) {
46*9fc45ca0SDaniel Grumberg   if (const auto *TypedefDecl = Decl->getTypedefNameForAnonDecl())
47*9fc45ca0SDaniel Grumberg     return TypedefDecl->getName();
48*9fc45ca0SDaniel Grumberg 
49*9fc45ca0SDaniel Grumberg   return {};
50*9fc45ca0SDaniel Grumberg }
51*9fc45ca0SDaniel Grumberg 
5289f6b26fSZixu Wang /// The RecursiveASTVisitor to traverse symbol declarations and collect API
5389f6b26fSZixu Wang /// information.
5489f6b26fSZixu Wang class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
5589f6b26fSZixu Wang public:
56a9909d23SDaniel Grumberg   ExtractAPIVisitor(ASTContext &Context, APISet &API)
57a9909d23SDaniel Grumberg       : Context(Context), API(API) {}
5889f6b26fSZixu Wang 
5989f6b26fSZixu Wang   const APISet &getAPI() const { return API; }
6089f6b26fSZixu Wang 
6189f6b26fSZixu Wang   bool VisitVarDecl(const VarDecl *Decl) {
6289f6b26fSZixu Wang     // Skip function parameters.
6389f6b26fSZixu Wang     if (isa<ParmVarDecl>(Decl))
6489f6b26fSZixu Wang       return true;
6589f6b26fSZixu Wang 
6689f6b26fSZixu Wang     // Skip non-global variables in records (struct/union/class).
6789f6b26fSZixu Wang     if (Decl->getDeclContext()->isRecord())
6889f6b26fSZixu Wang       return true;
6989f6b26fSZixu Wang 
7089f6b26fSZixu Wang     // Skip local variables inside function or method.
7189f6b26fSZixu Wang     if (!Decl->isDefinedOutsideFunctionOrMethod())
7289f6b26fSZixu Wang       return true;
7389f6b26fSZixu Wang 
7489f6b26fSZixu Wang     // If this is a template but not specialization or instantiation, skip.
7589f6b26fSZixu Wang     if (Decl->getASTContext().getTemplateOrSpecializationInfo(Decl) &&
7689f6b26fSZixu Wang         Decl->getTemplateSpecializationKind() == TSK_Undeclared)
7789f6b26fSZixu Wang       return true;
7889f6b26fSZixu Wang 
7989f6b26fSZixu Wang     // Collect symbol information.
8089f6b26fSZixu Wang     StringRef Name = Decl->getName();
8189f6b26fSZixu Wang     StringRef USR = API.recordUSR(Decl);
8289f6b26fSZixu Wang     PresumedLoc Loc =
8389f6b26fSZixu Wang         Context.getSourceManager().getPresumedLoc(Decl->getLocation());
8489f6b26fSZixu Wang     AvailabilityInfo Availability = getAvailability(Decl);
8589f6b26fSZixu Wang     LinkageInfo Linkage = Decl->getLinkageAndVisibility();
8689f6b26fSZixu Wang     DocComment Comment;
8789f6b26fSZixu Wang     if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
8889f6b26fSZixu Wang       Comment = RawComment->getFormattedLines(Context.getSourceManager(),
8989f6b26fSZixu Wang                                               Context.getDiagnostics());
9089f6b26fSZixu Wang 
9189f6b26fSZixu Wang     // Build declaration fragments and sub-heading for the variable.
9289f6b26fSZixu Wang     DeclarationFragments Declaration =
9389f6b26fSZixu Wang         DeclarationFragmentsBuilder::getFragmentsForVar(Decl);
9489f6b26fSZixu Wang     DeclarationFragments SubHeading =
9589f6b26fSZixu Wang         DeclarationFragmentsBuilder::getSubHeading(Decl);
9689f6b26fSZixu Wang 
9789f6b26fSZixu Wang     // Add the global variable record to the API set.
9889f6b26fSZixu Wang     API.addGlobalVar(Name, USR, Loc, Availability, Linkage, Comment,
9989f6b26fSZixu Wang                      Declaration, SubHeading);
10089f6b26fSZixu Wang     return true;
10189f6b26fSZixu Wang   }
10289f6b26fSZixu Wang 
10389f6b26fSZixu Wang   bool VisitFunctionDecl(const FunctionDecl *Decl) {
10489f6b26fSZixu Wang     if (const auto *Method = dyn_cast<CXXMethodDecl>(Decl)) {
10589f6b26fSZixu Wang       // Skip member function in class templates.
10689f6b26fSZixu Wang       if (Method->getParent()->getDescribedClassTemplate() != nullptr)
10789f6b26fSZixu Wang         return true;
10889f6b26fSZixu Wang 
10989f6b26fSZixu Wang       // Skip methods in records.
11089f6b26fSZixu Wang       for (auto P : Context.getParents(*Method)) {
11189f6b26fSZixu Wang         if (P.get<CXXRecordDecl>())
11289f6b26fSZixu Wang           return true;
11389f6b26fSZixu Wang       }
11489f6b26fSZixu Wang 
11589f6b26fSZixu Wang       // Skip ConstructorDecl and DestructorDecl.
11689f6b26fSZixu Wang       if (isa<CXXConstructorDecl>(Method) || isa<CXXDestructorDecl>(Method))
11789f6b26fSZixu Wang         return true;
11889f6b26fSZixu Wang     }
11989f6b26fSZixu Wang 
12089f6b26fSZixu Wang     // Skip templated functions.
12189f6b26fSZixu Wang     switch (Decl->getTemplatedKind()) {
12289f6b26fSZixu Wang     case FunctionDecl::TK_NonTemplate:
12389f6b26fSZixu Wang       break;
12489f6b26fSZixu Wang     case FunctionDecl::TK_MemberSpecialization:
12589f6b26fSZixu Wang     case FunctionDecl::TK_FunctionTemplateSpecialization:
12689f6b26fSZixu Wang       if (auto *TemplateInfo = Decl->getTemplateSpecializationInfo()) {
12789f6b26fSZixu Wang         if (!TemplateInfo->isExplicitInstantiationOrSpecialization())
12889f6b26fSZixu Wang           return true;
12989f6b26fSZixu Wang       }
13089f6b26fSZixu Wang       break;
13189f6b26fSZixu Wang     case FunctionDecl::TK_FunctionTemplate:
13289f6b26fSZixu Wang     case FunctionDecl::TK_DependentFunctionTemplateSpecialization:
13389f6b26fSZixu Wang       return true;
13489f6b26fSZixu Wang     }
13589f6b26fSZixu Wang 
13689f6b26fSZixu Wang     // Collect symbol information.
13789f6b26fSZixu Wang     StringRef Name = Decl->getName();
13889f6b26fSZixu Wang     StringRef USR = API.recordUSR(Decl);
13989f6b26fSZixu Wang     PresumedLoc Loc =
14089f6b26fSZixu Wang         Context.getSourceManager().getPresumedLoc(Decl->getLocation());
14189f6b26fSZixu Wang     AvailabilityInfo Availability = getAvailability(Decl);
14289f6b26fSZixu Wang     LinkageInfo Linkage = Decl->getLinkageAndVisibility();
14389f6b26fSZixu Wang     DocComment Comment;
14489f6b26fSZixu Wang     if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
14589f6b26fSZixu Wang       Comment = RawComment->getFormattedLines(Context.getSourceManager(),
14689f6b26fSZixu Wang                                               Context.getDiagnostics());
14789f6b26fSZixu Wang 
14889f6b26fSZixu Wang     // Build declaration fragments, sub-heading, and signature of the function.
14989f6b26fSZixu Wang     DeclarationFragments Declaration =
15089f6b26fSZixu Wang         DeclarationFragmentsBuilder::getFragmentsForFunction(Decl);
15189f6b26fSZixu Wang     DeclarationFragments SubHeading =
15289f6b26fSZixu Wang         DeclarationFragmentsBuilder::getSubHeading(Decl);
15389f6b26fSZixu Wang     FunctionSignature Signature =
15489f6b26fSZixu Wang         DeclarationFragmentsBuilder::getFunctionSignature(Decl);
15589f6b26fSZixu Wang 
15689f6b26fSZixu Wang     // Add the function record to the API set.
15789f6b26fSZixu Wang     API.addFunction(Name, USR, Loc, Availability, Linkage, Comment, Declaration,
15889f6b26fSZixu Wang                     SubHeading, Signature);
15989f6b26fSZixu Wang     return true;
16089f6b26fSZixu Wang   }
16189f6b26fSZixu Wang 
16271b4c226SZixu Wang   bool VisitEnumDecl(const EnumDecl *Decl) {
16371b4c226SZixu Wang     if (!Decl->isComplete())
16471b4c226SZixu Wang       return true;
16571b4c226SZixu Wang 
16671b4c226SZixu Wang     // Skip forward declaration.
16771b4c226SZixu Wang     if (!Decl->isThisDeclarationADefinition())
16871b4c226SZixu Wang       return true;
16971b4c226SZixu Wang 
17071b4c226SZixu Wang     // Collect symbol information.
17171b4c226SZixu Wang     StringRef Name = Decl->getName();
172*9fc45ca0SDaniel Grumberg     if (Name.empty())
173*9fc45ca0SDaniel Grumberg       Name = getTypedefName(Decl);
17471b4c226SZixu Wang     StringRef USR = API.recordUSR(Decl);
17571b4c226SZixu Wang     PresumedLoc Loc =
17671b4c226SZixu Wang         Context.getSourceManager().getPresumedLoc(Decl->getLocation());
17771b4c226SZixu Wang     AvailabilityInfo Availability = getAvailability(Decl);
17871b4c226SZixu Wang     DocComment Comment;
17971b4c226SZixu Wang     if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
18071b4c226SZixu Wang       Comment = RawComment->getFormattedLines(Context.getSourceManager(),
18171b4c226SZixu Wang                                               Context.getDiagnostics());
18271b4c226SZixu Wang 
18371b4c226SZixu Wang     // Build declaration fragments and sub-heading for the enum.
18471b4c226SZixu Wang     DeclarationFragments Declaration =
18571b4c226SZixu Wang         DeclarationFragmentsBuilder::getFragmentsForEnum(Decl);
18671b4c226SZixu Wang     DeclarationFragments SubHeading =
18771b4c226SZixu Wang         DeclarationFragmentsBuilder::getSubHeading(Decl);
18871b4c226SZixu Wang 
18971b4c226SZixu Wang     EnumRecord *EnumRecord = API.addEnum(Name, USR, Loc, Availability, Comment,
19071b4c226SZixu Wang                                          Declaration, SubHeading);
19171b4c226SZixu Wang 
19271b4c226SZixu Wang     // Now collect information about the enumerators in this enum.
19371b4c226SZixu Wang     recordEnumConstants(EnumRecord, Decl->enumerators());
19471b4c226SZixu Wang 
19571b4c226SZixu Wang     return true;
19671b4c226SZixu Wang   }
19771b4c226SZixu Wang 
1985bb5704cSZixu Wang   bool VisitRecordDecl(const RecordDecl *Decl) {
1995bb5704cSZixu Wang     if (!Decl->isCompleteDefinition())
2005bb5704cSZixu Wang       return true;
2015bb5704cSZixu Wang 
2025bb5704cSZixu Wang     // Skip C++ structs/classes/unions
2035bb5704cSZixu Wang     // TODO: support C++ records
2045bb5704cSZixu Wang     if (isa<CXXRecordDecl>(Decl))
2055bb5704cSZixu Wang       return true;
2065bb5704cSZixu Wang 
2075bb5704cSZixu Wang     // Collect symbol information.
2085bb5704cSZixu Wang     StringRef Name = Decl->getName();
209*9fc45ca0SDaniel Grumberg     if (Name.empty())
210*9fc45ca0SDaniel Grumberg       Name = getTypedefName(Decl);
2115bb5704cSZixu Wang     StringRef USR = API.recordUSR(Decl);
2125bb5704cSZixu Wang     PresumedLoc Loc =
2135bb5704cSZixu Wang         Context.getSourceManager().getPresumedLoc(Decl->getLocation());
2145bb5704cSZixu Wang     AvailabilityInfo Availability = getAvailability(Decl);
2155bb5704cSZixu Wang     DocComment Comment;
2165bb5704cSZixu Wang     if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
2175bb5704cSZixu Wang       Comment = RawComment->getFormattedLines(Context.getSourceManager(),
2185bb5704cSZixu Wang                                               Context.getDiagnostics());
2195bb5704cSZixu Wang 
2205bb5704cSZixu Wang     // Build declaration fragments and sub-heading for the struct.
2215bb5704cSZixu Wang     DeclarationFragments Declaration =
2225bb5704cSZixu Wang         DeclarationFragmentsBuilder::getFragmentsForStruct(Decl);
2235bb5704cSZixu Wang     DeclarationFragments SubHeading =
2245bb5704cSZixu Wang         DeclarationFragmentsBuilder::getSubHeading(Decl);
2255bb5704cSZixu Wang 
2265bb5704cSZixu Wang     StructRecord *StructRecord = API.addStruct(
2275bb5704cSZixu Wang         Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
2285bb5704cSZixu Wang 
2295bb5704cSZixu Wang     // Now collect information about the fields in this struct.
2305bb5704cSZixu Wang     recordStructFields(StructRecord, Decl->fields());
2315bb5704cSZixu Wang 
2325bb5704cSZixu Wang     return true;
2335bb5704cSZixu Wang   }
2345bb5704cSZixu Wang 
2359b36e126SZixu Wang   bool VisitObjCInterfaceDecl(const ObjCInterfaceDecl *Decl) {
2369b36e126SZixu Wang     // Skip forward declaration for classes (@class)
2379b36e126SZixu Wang     if (!Decl->isThisDeclarationADefinition())
2389b36e126SZixu Wang       return true;
2399b36e126SZixu Wang 
2409b36e126SZixu Wang     // Collect symbol information.
2419b36e126SZixu Wang     StringRef Name = Decl->getName();
2429b36e126SZixu Wang     StringRef USR = API.recordUSR(Decl);
2439b36e126SZixu Wang     PresumedLoc Loc =
2449b36e126SZixu Wang         Context.getSourceManager().getPresumedLoc(Decl->getLocation());
2459b36e126SZixu Wang     AvailabilityInfo Availability = getAvailability(Decl);
2469b36e126SZixu Wang     LinkageInfo Linkage = Decl->getLinkageAndVisibility();
2479b36e126SZixu Wang     DocComment Comment;
2489b36e126SZixu Wang     if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
2499b36e126SZixu Wang       Comment = RawComment->getFormattedLines(Context.getSourceManager(),
2509b36e126SZixu Wang                                               Context.getDiagnostics());
2519b36e126SZixu Wang 
2529b36e126SZixu Wang     // Build declaration fragments and sub-heading for the interface.
2539b36e126SZixu Wang     DeclarationFragments Declaration =
2549b36e126SZixu Wang         DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Decl);
2559b36e126SZixu Wang     DeclarationFragments SubHeading =
2569b36e126SZixu Wang         DeclarationFragmentsBuilder::getSubHeading(Decl);
2579b36e126SZixu Wang 
2589b36e126SZixu Wang     // Collect super class information.
2599b36e126SZixu Wang     SymbolReference SuperClass;
2609b36e126SZixu Wang     if (const auto *SuperClassDecl = Decl->getSuperClass()) {
2619b36e126SZixu Wang       SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString();
2629b36e126SZixu Wang       SuperClass.USR = API.recordUSR(SuperClassDecl);
2639b36e126SZixu Wang     }
2649b36e126SZixu Wang 
2659b36e126SZixu Wang     ObjCInterfaceRecord *ObjCInterfaceRecord =
2669b36e126SZixu Wang         API.addObjCInterface(Name, USR, Loc, Availability, Linkage, Comment,
2679b36e126SZixu Wang                              Declaration, SubHeading, SuperClass);
2689b36e126SZixu Wang 
2699b36e126SZixu Wang     // Record all methods (selectors). This doesn't include automatically
2709b36e126SZixu Wang     // synthesized property methods.
2719b36e126SZixu Wang     recordObjCMethods(ObjCInterfaceRecord, Decl->methods());
2729b36e126SZixu Wang     recordObjCProperties(ObjCInterfaceRecord, Decl->properties());
2739b36e126SZixu Wang     recordObjCInstanceVariables(ObjCInterfaceRecord, Decl->ivars());
2749b36e126SZixu Wang     recordObjCProtocols(ObjCInterfaceRecord, Decl->protocols());
2759b36e126SZixu Wang 
2769b36e126SZixu Wang     return true;
2779b36e126SZixu Wang   }
2789b36e126SZixu Wang 
279d1d34bafSZixu Wang   bool VisitObjCProtocolDecl(const ObjCProtocolDecl *Decl) {
280d1d34bafSZixu Wang     // Skip forward declaration for protocols (@protocol).
281d1d34bafSZixu Wang     if (!Decl->isThisDeclarationADefinition())
282d1d34bafSZixu Wang       return true;
283d1d34bafSZixu Wang 
284d1d34bafSZixu Wang     // Collect symbol information.
285d1d34bafSZixu Wang     StringRef Name = Decl->getName();
286d1d34bafSZixu Wang     StringRef USR = API.recordUSR(Decl);
287d1d34bafSZixu Wang     PresumedLoc Loc =
288d1d34bafSZixu Wang         Context.getSourceManager().getPresumedLoc(Decl->getLocation());
289d1d34bafSZixu Wang     AvailabilityInfo Availability = getAvailability(Decl);
290d1d34bafSZixu Wang     DocComment Comment;
291d1d34bafSZixu Wang     if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
292d1d34bafSZixu Wang       Comment = RawComment->getFormattedLines(Context.getSourceManager(),
293d1d34bafSZixu Wang                                               Context.getDiagnostics());
294d1d34bafSZixu Wang 
295d1d34bafSZixu Wang     // Build declaration fragments and sub-heading for the protocol.
296d1d34bafSZixu Wang     DeclarationFragments Declaration =
297d1d34bafSZixu Wang         DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(Decl);
298d1d34bafSZixu Wang     DeclarationFragments SubHeading =
299d1d34bafSZixu Wang         DeclarationFragmentsBuilder::getSubHeading(Decl);
300d1d34bafSZixu Wang 
301d1d34bafSZixu Wang     ObjCProtocolRecord *ObjCProtocolRecord = API.addObjCProtocol(
302d1d34bafSZixu Wang         Name, USR, Loc, Availability, Comment, Declaration, SubHeading);
303d1d34bafSZixu Wang 
304d1d34bafSZixu Wang     recordObjCMethods(ObjCProtocolRecord, Decl->methods());
305d1d34bafSZixu Wang     recordObjCProperties(ObjCProtocolRecord, Decl->properties());
306d1d34bafSZixu Wang     recordObjCProtocols(ObjCProtocolRecord, Decl->protocols());
307d1d34bafSZixu Wang 
308d1d34bafSZixu Wang     return true;
309d1d34bafSZixu Wang   }
310d1d34bafSZixu Wang 
311*9fc45ca0SDaniel Grumberg   bool VisitTypedefNameDecl(const TypedefNameDecl *Decl) {
312*9fc45ca0SDaniel Grumberg     // Skip ObjC Type Parameter for now.
313*9fc45ca0SDaniel Grumberg     if (isa<ObjCTypeParamDecl>(Decl))
314*9fc45ca0SDaniel Grumberg       return true;
315*9fc45ca0SDaniel Grumberg 
316*9fc45ca0SDaniel Grumberg     if (!Decl->isDefinedOutsideFunctionOrMethod())
317*9fc45ca0SDaniel Grumberg       return true;
318*9fc45ca0SDaniel Grumberg 
319*9fc45ca0SDaniel Grumberg     PresumedLoc Loc =
320*9fc45ca0SDaniel Grumberg         Context.getSourceManager().getPresumedLoc(Decl->getLocation());
321*9fc45ca0SDaniel Grumberg     StringRef Name = Decl->getName();
322*9fc45ca0SDaniel Grumberg     AvailabilityInfo Availability = getAvailability(Decl);
323*9fc45ca0SDaniel Grumberg     StringRef USR = API.recordUSR(Decl);
324*9fc45ca0SDaniel Grumberg     DocComment Comment;
325*9fc45ca0SDaniel Grumberg     if (auto *RawComment = Context.getRawCommentForDeclNoCache(Decl))
326*9fc45ca0SDaniel Grumberg       Comment = RawComment->getFormattedLines(Context.getSourceManager(),
327*9fc45ca0SDaniel Grumberg                                               Context.getDiagnostics());
328*9fc45ca0SDaniel Grumberg 
329*9fc45ca0SDaniel Grumberg     QualType Type = Decl->getUnderlyingType();
330*9fc45ca0SDaniel Grumberg     SymbolReference SymRef =
331*9fc45ca0SDaniel Grumberg         TypedefUnderlyingTypeResolver(Context).getSymbolReferenceForType(Type,
332*9fc45ca0SDaniel Grumberg                                                                          API);
333*9fc45ca0SDaniel Grumberg 
334*9fc45ca0SDaniel Grumberg     API.addTypedef(Name, USR, Loc, Availability, Comment,
335*9fc45ca0SDaniel Grumberg                    DeclarationFragmentsBuilder::getFragmentsForTypedef(Decl),
336*9fc45ca0SDaniel Grumberg                    DeclarationFragmentsBuilder::getSubHeading(Decl), SymRef);
337*9fc45ca0SDaniel Grumberg 
338*9fc45ca0SDaniel Grumberg     return true;
339*9fc45ca0SDaniel Grumberg   }
340*9fc45ca0SDaniel Grumberg 
34189f6b26fSZixu Wang private:
34289f6b26fSZixu Wang   /// Get availability information of the declaration \p D.
34389f6b26fSZixu Wang   AvailabilityInfo getAvailability(const Decl *D) const {
34489f6b26fSZixu Wang     StringRef PlatformName = Context.getTargetInfo().getPlatformName();
34589f6b26fSZixu Wang 
34689f6b26fSZixu Wang     AvailabilityInfo Availability;
34789f6b26fSZixu Wang     // Collect availability attributes from all redeclarations.
34889f6b26fSZixu Wang     for (const auto *RD : D->redecls()) {
34989f6b26fSZixu Wang       for (const auto *A : RD->specific_attrs<AvailabilityAttr>()) {
35089f6b26fSZixu Wang         if (A->getPlatform()->getName() != PlatformName)
35189f6b26fSZixu Wang           continue;
35289f6b26fSZixu Wang         Availability = AvailabilityInfo(A->getIntroduced(), A->getDeprecated(),
35389f6b26fSZixu Wang                                         A->getObsoleted(), A->getUnavailable(),
35489f6b26fSZixu Wang                                         /* UnconditionallyDeprecated */ false,
35589f6b26fSZixu Wang                                         /* UnconditionallyUnavailable */ false);
35689f6b26fSZixu Wang         break;
35789f6b26fSZixu Wang       }
35889f6b26fSZixu Wang 
35989f6b26fSZixu Wang       if (const auto *A = RD->getAttr<UnavailableAttr>())
36089f6b26fSZixu Wang         if (!A->isImplicit()) {
36189f6b26fSZixu Wang           Availability.Unavailable = true;
36289f6b26fSZixu Wang           Availability.UnconditionallyUnavailable = true;
36389f6b26fSZixu Wang         }
36489f6b26fSZixu Wang 
36589f6b26fSZixu Wang       if (const auto *A = RD->getAttr<DeprecatedAttr>())
36689f6b26fSZixu Wang         if (!A->isImplicit())
36789f6b26fSZixu Wang           Availability.UnconditionallyDeprecated = true;
36889f6b26fSZixu Wang     }
36989f6b26fSZixu Wang 
37089f6b26fSZixu Wang     return Availability;
37189f6b26fSZixu Wang   }
37289f6b26fSZixu Wang 
37371b4c226SZixu Wang   /// Collect API information for the enum constants and associate with the
37471b4c226SZixu Wang   /// parent enum.
37571b4c226SZixu Wang   void recordEnumConstants(EnumRecord *EnumRecord,
37671b4c226SZixu Wang                            const EnumDecl::enumerator_range Constants) {
37771b4c226SZixu Wang     for (const auto *Constant : Constants) {
37871b4c226SZixu Wang       // Collect symbol information.
37971b4c226SZixu Wang       StringRef Name = Constant->getName();
38071b4c226SZixu Wang       StringRef USR = API.recordUSR(Constant);
38171b4c226SZixu Wang       PresumedLoc Loc =
38271b4c226SZixu Wang           Context.getSourceManager().getPresumedLoc(Constant->getLocation());
38371b4c226SZixu Wang       AvailabilityInfo Availability = getAvailability(Constant);
38471b4c226SZixu Wang       DocComment Comment;
38571b4c226SZixu Wang       if (auto *RawComment = Context.getRawCommentForDeclNoCache(Constant))
38671b4c226SZixu Wang         Comment = RawComment->getFormattedLines(Context.getSourceManager(),
38771b4c226SZixu Wang                                                 Context.getDiagnostics());
38871b4c226SZixu Wang 
38971b4c226SZixu Wang       // Build declaration fragments and sub-heading for the enum constant.
39071b4c226SZixu Wang       DeclarationFragments Declaration =
39171b4c226SZixu Wang           DeclarationFragmentsBuilder::getFragmentsForEnumConstant(Constant);
39271b4c226SZixu Wang       DeclarationFragments SubHeading =
39371b4c226SZixu Wang           DeclarationFragmentsBuilder::getSubHeading(Constant);
39471b4c226SZixu Wang 
39571b4c226SZixu Wang       API.addEnumConstant(EnumRecord, Name, USR, Loc, Availability, Comment,
39671b4c226SZixu Wang                           Declaration, SubHeading);
39771b4c226SZixu Wang     }
39871b4c226SZixu Wang   }
39971b4c226SZixu Wang 
4005bb5704cSZixu Wang   /// Collect API information for the struct fields and associate with the
4015bb5704cSZixu Wang   /// parent struct.
4025bb5704cSZixu Wang   void recordStructFields(StructRecord *StructRecord,
4035bb5704cSZixu Wang                           const RecordDecl::field_range Fields) {
4045bb5704cSZixu Wang     for (const auto *Field : Fields) {
4055bb5704cSZixu Wang       // Collect symbol information.
4065bb5704cSZixu Wang       StringRef Name = Field->getName();
4075bb5704cSZixu Wang       StringRef USR = API.recordUSR(Field);
4085bb5704cSZixu Wang       PresumedLoc Loc =
4095bb5704cSZixu Wang           Context.getSourceManager().getPresumedLoc(Field->getLocation());
4105bb5704cSZixu Wang       AvailabilityInfo Availability = getAvailability(Field);
4115bb5704cSZixu Wang       DocComment Comment;
4125bb5704cSZixu Wang       if (auto *RawComment = Context.getRawCommentForDeclNoCache(Field))
4135bb5704cSZixu Wang         Comment = RawComment->getFormattedLines(Context.getSourceManager(),
4145bb5704cSZixu Wang                                                 Context.getDiagnostics());
4155bb5704cSZixu Wang 
4165bb5704cSZixu Wang       // Build declaration fragments and sub-heading for the struct field.
4175bb5704cSZixu Wang       DeclarationFragments Declaration =
4185bb5704cSZixu Wang           DeclarationFragmentsBuilder::getFragmentsForField(Field);
4195bb5704cSZixu Wang       DeclarationFragments SubHeading =
4205bb5704cSZixu Wang           DeclarationFragmentsBuilder::getSubHeading(Field);
4215bb5704cSZixu Wang 
4225bb5704cSZixu Wang       API.addStructField(StructRecord, Name, USR, Loc, Availability, Comment,
4235bb5704cSZixu Wang                          Declaration, SubHeading);
4245bb5704cSZixu Wang     }
4255bb5704cSZixu Wang   }
4265bb5704cSZixu Wang 
4279b36e126SZixu Wang   /// Collect API information for the Objective-C methods and associate with the
4289b36e126SZixu Wang   /// parent container.
4299b36e126SZixu Wang   void recordObjCMethods(ObjCContainerRecord *Container,
4309b36e126SZixu Wang                          const ObjCContainerDecl::method_range Methods) {
4319b36e126SZixu Wang     for (const auto *Method : Methods) {
4329b36e126SZixu Wang       // Don't record selectors for properties.
4339b36e126SZixu Wang       if (Method->isPropertyAccessor())
4349b36e126SZixu Wang         continue;
4359b36e126SZixu Wang 
4369b36e126SZixu Wang       StringRef Name = API.copyString(Method->getSelector().getAsString());
4379b36e126SZixu Wang       StringRef USR = API.recordUSR(Method);
4389b36e126SZixu Wang       PresumedLoc Loc =
4399b36e126SZixu Wang           Context.getSourceManager().getPresumedLoc(Method->getLocation());
4409b36e126SZixu Wang       AvailabilityInfo Availability = getAvailability(Method);
4419b36e126SZixu Wang       DocComment Comment;
4429b36e126SZixu Wang       if (auto *RawComment = Context.getRawCommentForDeclNoCache(Method))
4439b36e126SZixu Wang         Comment = RawComment->getFormattedLines(Context.getSourceManager(),
4449b36e126SZixu Wang                                                 Context.getDiagnostics());
4459b36e126SZixu Wang 
4469b36e126SZixu Wang       // Build declaration fragments, sub-heading, and signature for the method.
4479b36e126SZixu Wang       DeclarationFragments Declaration =
4489b36e126SZixu Wang           DeclarationFragmentsBuilder::getFragmentsForObjCMethod(Method);
4499b36e126SZixu Wang       DeclarationFragments SubHeading =
4509b36e126SZixu Wang           DeclarationFragmentsBuilder::getSubHeading(Method);
4519b36e126SZixu Wang       FunctionSignature Signature =
4529b36e126SZixu Wang           DeclarationFragmentsBuilder::getFunctionSignature(Method);
4539b36e126SZixu Wang 
4549b36e126SZixu Wang       API.addObjCMethod(Container, Name, USR, Loc, Availability, Comment,
4559b36e126SZixu Wang                         Declaration, SubHeading, Signature,
4569b36e126SZixu Wang                         Method->isInstanceMethod());
4579b36e126SZixu Wang     }
4589b36e126SZixu Wang   }
4599b36e126SZixu Wang 
4609b36e126SZixu Wang   void recordObjCProperties(ObjCContainerRecord *Container,
4619b36e126SZixu Wang                             const ObjCContainerDecl::prop_range Properties) {
4629b36e126SZixu Wang     for (const auto *Property : Properties) {
4639b36e126SZixu Wang       StringRef Name = Property->getName();
4649b36e126SZixu Wang       StringRef USR = API.recordUSR(Property);
4659b36e126SZixu Wang       PresumedLoc Loc =
4669b36e126SZixu Wang           Context.getSourceManager().getPresumedLoc(Property->getLocation());
4679b36e126SZixu Wang       AvailabilityInfo Availability = getAvailability(Property);
4689b36e126SZixu Wang       DocComment Comment;
4699b36e126SZixu Wang       if (auto *RawComment = Context.getRawCommentForDeclNoCache(Property))
4709b36e126SZixu Wang         Comment = RawComment->getFormattedLines(Context.getSourceManager(),
4719b36e126SZixu Wang                                                 Context.getDiagnostics());
4729b36e126SZixu Wang 
4739b36e126SZixu Wang       // Build declaration fragments and sub-heading for the property.
4749b36e126SZixu Wang       DeclarationFragments Declaration =
4759b36e126SZixu Wang           DeclarationFragmentsBuilder::getFragmentsForObjCProperty(Property);
4769b36e126SZixu Wang       DeclarationFragments SubHeading =
4779b36e126SZixu Wang           DeclarationFragmentsBuilder::getSubHeading(Property);
4789b36e126SZixu Wang 
4799b36e126SZixu Wang       StringRef GetterName =
4809b36e126SZixu Wang           API.copyString(Property->getGetterName().getAsString());
4819b36e126SZixu Wang       StringRef SetterName =
4829b36e126SZixu Wang           API.copyString(Property->getSetterName().getAsString());
4839b36e126SZixu Wang 
4849b36e126SZixu Wang       // Get the attributes for property.
4859b36e126SZixu Wang       unsigned Attributes = ObjCPropertyRecord::NoAttr;
4869b36e126SZixu Wang       if (Property->getPropertyAttributes() &
4879b36e126SZixu Wang           ObjCPropertyAttribute::kind_readonly)
4889b36e126SZixu Wang         Attributes |= ObjCPropertyRecord::ReadOnly;
4899b36e126SZixu Wang       if (Property->getPropertyAttributes() & ObjCPropertyAttribute::kind_class)
4909b36e126SZixu Wang         Attributes |= ObjCPropertyRecord::Class;
4919b36e126SZixu Wang 
4929b36e126SZixu Wang       API.addObjCProperty(
4939b36e126SZixu Wang           Container, Name, USR, Loc, Availability, Comment, Declaration,
4949b36e126SZixu Wang           SubHeading,
4959b36e126SZixu Wang           static_cast<ObjCPropertyRecord::AttributeKind>(Attributes),
4969b36e126SZixu Wang           GetterName, SetterName, Property->isOptional());
4979b36e126SZixu Wang     }
4989b36e126SZixu Wang   }
4999b36e126SZixu Wang 
5009b36e126SZixu Wang   void recordObjCInstanceVariables(
5019b36e126SZixu Wang       ObjCContainerRecord *Container,
5029b36e126SZixu Wang       const llvm::iterator_range<
5039b36e126SZixu Wang           DeclContext::specific_decl_iterator<ObjCIvarDecl>>
5049b36e126SZixu Wang           Ivars) {
5059b36e126SZixu Wang     for (const auto *Ivar : Ivars) {
5069b36e126SZixu Wang       StringRef Name = Ivar->getName();
5079b36e126SZixu Wang       StringRef USR = API.recordUSR(Ivar);
5089b36e126SZixu Wang       PresumedLoc Loc =
5099b36e126SZixu Wang           Context.getSourceManager().getPresumedLoc(Ivar->getLocation());
5109b36e126SZixu Wang       AvailabilityInfo Availability = getAvailability(Ivar);
5119b36e126SZixu Wang       DocComment Comment;
5129b36e126SZixu Wang       if (auto *RawComment = Context.getRawCommentForDeclNoCache(Ivar))
5139b36e126SZixu Wang         Comment = RawComment->getFormattedLines(Context.getSourceManager(),
5149b36e126SZixu Wang                                                 Context.getDiagnostics());
5159b36e126SZixu Wang 
5169b36e126SZixu Wang       // Build declaration fragments and sub-heading for the instance variable.
5179b36e126SZixu Wang       DeclarationFragments Declaration =
5189b36e126SZixu Wang           DeclarationFragmentsBuilder::getFragmentsForField(Ivar);
5199b36e126SZixu Wang       DeclarationFragments SubHeading =
5209b36e126SZixu Wang           DeclarationFragmentsBuilder::getSubHeading(Ivar);
5219b36e126SZixu Wang 
5229b36e126SZixu Wang       ObjCInstanceVariableRecord::AccessControl Access =
5239b36e126SZixu Wang           Ivar->getCanonicalAccessControl();
5249b36e126SZixu Wang 
5259b36e126SZixu Wang       API.addObjCInstanceVariable(Container, Name, USR, Loc, Availability,
5269b36e126SZixu Wang                                   Comment, Declaration, SubHeading, Access);
5279b36e126SZixu Wang     }
5289b36e126SZixu Wang   }
5299b36e126SZixu Wang 
5309b36e126SZixu Wang   void recordObjCProtocols(ObjCContainerRecord *Container,
5319b36e126SZixu Wang                            ObjCInterfaceDecl::protocol_range Protocols) {
5329b36e126SZixu Wang     for (const auto *Protocol : Protocols)
5339b36e126SZixu Wang       Container->Protocols.emplace_back(Protocol->getName(),
5349b36e126SZixu Wang                                         API.recordUSR(Protocol));
5359b36e126SZixu Wang   }
5369b36e126SZixu Wang 
53789f6b26fSZixu Wang   ASTContext &Context;
538a9909d23SDaniel Grumberg   APISet &API;
53989f6b26fSZixu Wang };
54089f6b26fSZixu Wang 
54189f6b26fSZixu Wang class ExtractAPIConsumer : public ASTConsumer {
54289f6b26fSZixu Wang public:
543a9909d23SDaniel Grumberg   ExtractAPIConsumer(ASTContext &Context, APISet &API)
544a9909d23SDaniel Grumberg       : Visitor(Context, API) {}
54589f6b26fSZixu Wang 
54689f6b26fSZixu Wang   void HandleTranslationUnit(ASTContext &Context) override {
54789f6b26fSZixu Wang     // Use ExtractAPIVisitor to traverse symbol declarations in the context.
54889f6b26fSZixu Wang     Visitor.TraverseDecl(Context.getTranslationUnitDecl());
54989f6b26fSZixu Wang   }
55089f6b26fSZixu Wang 
55189f6b26fSZixu Wang private:
55289f6b26fSZixu Wang   ExtractAPIVisitor Visitor;
55389f6b26fSZixu Wang };
55489f6b26fSZixu Wang 
555529a0570SDaniel Grumberg class MacroCallback : public PPCallbacks {
556529a0570SDaniel Grumberg public:
557529a0570SDaniel Grumberg   MacroCallback(const SourceManager &SM, APISet &API) : SM(SM), API(API) {}
558529a0570SDaniel Grumberg 
559529a0570SDaniel Grumberg   void MacroDefined(const Token &MacroNameToken,
560529a0570SDaniel Grumberg                     const MacroDirective *MD) override {
561529a0570SDaniel Grumberg     auto *MacroInfo = MD->getMacroInfo();
562529a0570SDaniel Grumberg 
563529a0570SDaniel Grumberg     if (MacroInfo->isBuiltinMacro())
564529a0570SDaniel Grumberg       return;
565529a0570SDaniel Grumberg 
566529a0570SDaniel Grumberg     auto SourceLoc = MacroNameToken.getLocation();
567529a0570SDaniel Grumberg     if (SM.isWrittenInBuiltinFile(SourceLoc) ||
568529a0570SDaniel Grumberg         SM.isWrittenInCommandLineFile(SourceLoc))
569529a0570SDaniel Grumberg       return;
570529a0570SDaniel Grumberg 
571529a0570SDaniel Grumberg     PendingMacros.emplace_back(MacroNameToken, MD);
572529a0570SDaniel Grumberg   }
573529a0570SDaniel Grumberg 
574529a0570SDaniel Grumberg   // If a macro gets undefined at some point during preprocessing of the inputs
575529a0570SDaniel Grumberg   // it means that it isn't an exposed API and we should therefore not add a
576529a0570SDaniel Grumberg   // macro definition for it.
577529a0570SDaniel Grumberg   void MacroUndefined(const Token &MacroNameToken, const MacroDefinition &MD,
578529a0570SDaniel Grumberg                       const MacroDirective *Undef) override {
5798b63622bSDaniel Grumberg     // If this macro wasn't previously defined we don't need to do anything
5808b63622bSDaniel Grumberg     // here.
5818b63622bSDaniel Grumberg     if (!Undef)
5828b63622bSDaniel Grumberg       return;
5838b63622bSDaniel Grumberg 
584529a0570SDaniel Grumberg     llvm::erase_if(PendingMacros, [&MD](const PendingMacro &PM) {
585529a0570SDaniel Grumberg       return MD.getMacroInfo()->getDefinitionLoc() ==
586529a0570SDaniel Grumberg              PM.MD->getMacroInfo()->getDefinitionLoc();
587529a0570SDaniel Grumberg     });
588529a0570SDaniel Grumberg   }
589529a0570SDaniel Grumberg 
590529a0570SDaniel Grumberg   void EndOfMainFile() override {
591529a0570SDaniel Grumberg     for (auto &PM : PendingMacros) {
592529a0570SDaniel Grumberg       // `isUsedForHeaderGuard` is only set when the preprocessor leaves the
593529a0570SDaniel Grumberg       // file so check for it here.
594529a0570SDaniel Grumberg       if (PM.MD->getMacroInfo()->isUsedForHeaderGuard())
595529a0570SDaniel Grumberg         continue;
596529a0570SDaniel Grumberg 
597529a0570SDaniel Grumberg       StringRef Name = PM.MacroNameToken.getIdentifierInfo()->getName();
598529a0570SDaniel Grumberg       PresumedLoc Loc = SM.getPresumedLoc(PM.MacroNameToken.getLocation());
599529a0570SDaniel Grumberg       StringRef USR =
600529a0570SDaniel Grumberg           API.recordUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM);
601529a0570SDaniel Grumberg 
602529a0570SDaniel Grumberg       API.addMacroDefinition(
603529a0570SDaniel Grumberg           Name, USR, Loc,
604529a0570SDaniel Grumberg           DeclarationFragmentsBuilder::getFragmentsForMacro(Name, PM.MD),
605529a0570SDaniel Grumberg           DeclarationFragmentsBuilder::getSubHeadingForMacro(Name));
606529a0570SDaniel Grumberg     }
607529a0570SDaniel Grumberg 
608529a0570SDaniel Grumberg     PendingMacros.clear();
609529a0570SDaniel Grumberg   }
610529a0570SDaniel Grumberg 
611529a0570SDaniel Grumberg private:
612529a0570SDaniel Grumberg   struct PendingMacro {
613529a0570SDaniel Grumberg     Token MacroNameToken;
614529a0570SDaniel Grumberg     const MacroDirective *MD;
615529a0570SDaniel Grumberg 
616529a0570SDaniel Grumberg     PendingMacro(const Token &MacroNameToken, const MacroDirective *MD)
617529a0570SDaniel Grumberg         : MacroNameToken(MacroNameToken), MD(MD) {}
618529a0570SDaniel Grumberg   };
619529a0570SDaniel Grumberg 
620529a0570SDaniel Grumberg   const SourceManager &SM;
621529a0570SDaniel Grumberg   APISet &API;
622529a0570SDaniel Grumberg   llvm::SmallVector<PendingMacro> PendingMacros;
623529a0570SDaniel Grumberg };
624529a0570SDaniel Grumberg 
62589f6b26fSZixu Wang } // namespace
62689f6b26fSZixu Wang 
62789f6b26fSZixu Wang std::unique_ptr<ASTConsumer>
62889f6b26fSZixu Wang ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
629a9909d23SDaniel Grumberg   OS = CreateOutputFile(CI, InFile);
63089f6b26fSZixu Wang   if (!OS)
63189f6b26fSZixu Wang     return nullptr;
632a9909d23SDaniel Grumberg 
633a9909d23SDaniel Grumberg   ProductName = CI.getFrontendOpts().ProductName;
634a9909d23SDaniel Grumberg 
635a9909d23SDaniel Grumberg   // Now that we have enough information about the language options and the
636a9909d23SDaniel Grumberg   // target triple, let's create the APISet before anyone uses it.
637a9909d23SDaniel Grumberg   API = std::make_unique<APISet>(
638a9909d23SDaniel Grumberg       CI.getTarget().getTriple(),
639a9909d23SDaniel Grumberg       CI.getFrontendOpts().Inputs.back().getKind().getLanguage());
640a9909d23SDaniel Grumberg 
641529a0570SDaniel Grumberg   // Register preprocessor callbacks that will add macro definitions to API.
642529a0570SDaniel Grumberg   CI.getPreprocessor().addPPCallbacks(
643529a0570SDaniel Grumberg       std::make_unique<MacroCallback>(CI.getSourceManager(), *API));
644529a0570SDaniel Grumberg 
645a9909d23SDaniel Grumberg   return std::make_unique<ExtractAPIConsumer>(CI.getASTContext(), *API);
64689f6b26fSZixu Wang }
64789f6b26fSZixu Wang 
648f833aab0SDaniel Grumberg bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) {
649f833aab0SDaniel Grumberg   auto &Inputs = CI.getFrontendOpts().Inputs;
650f833aab0SDaniel Grumberg   if (Inputs.empty())
651f833aab0SDaniel Grumberg     return true;
652f833aab0SDaniel Grumberg 
653f833aab0SDaniel Grumberg   auto Kind = Inputs[0].getKind();
654f833aab0SDaniel Grumberg 
655f833aab0SDaniel Grumberg   // Convert the header file inputs into a single input buffer.
656f833aab0SDaniel Grumberg   SmallString<256> HeaderContents;
657f833aab0SDaniel Grumberg   for (const FrontendInputFile &FIF : Inputs) {
658f833aab0SDaniel Grumberg     if (Kind.isObjectiveC())
659f833aab0SDaniel Grumberg       HeaderContents += "#import";
660f833aab0SDaniel Grumberg     else
661f833aab0SDaniel Grumberg       HeaderContents += "#include";
662f833aab0SDaniel Grumberg     HeaderContents += " \"";
663f833aab0SDaniel Grumberg     HeaderContents += FIF.getFile();
664f833aab0SDaniel Grumberg     HeaderContents += "\"\n";
665f833aab0SDaniel Grumberg   }
666f833aab0SDaniel Grumberg 
667985eaa1aSDaniel Grumberg   Buffer = llvm::MemoryBuffer::getMemBufferCopy(HeaderContents,
668f833aab0SDaniel Grumberg                                                 getInputBufferName());
669f833aab0SDaniel Grumberg 
670f833aab0SDaniel Grumberg   // Set that buffer up as our "real" input in the CompilerInstance.
671f833aab0SDaniel Grumberg   Inputs.clear();
672f833aab0SDaniel Grumberg   Inputs.emplace_back(Buffer->getMemBufferRef(), Kind, /*IsSystem*/ false);
673f833aab0SDaniel Grumberg 
674f833aab0SDaniel Grumberg   return true;
675f833aab0SDaniel Grumberg }
676f833aab0SDaniel Grumberg 
677a9909d23SDaniel Grumberg void ExtractAPIAction::EndSourceFileAction() {
678a9909d23SDaniel Grumberg   if (!OS)
679a9909d23SDaniel Grumberg     return;
680a9909d23SDaniel Grumberg 
681a9909d23SDaniel Grumberg   // Setup a SymbolGraphSerializer to write out collected API information in
682a9909d23SDaniel Grumberg   // the Symbol Graph format.
683a9909d23SDaniel Grumberg   // FIXME: Make the kind of APISerializer configurable.
684a9909d23SDaniel Grumberg   SymbolGraphSerializer SGSerializer(*API, ProductName);
685a9909d23SDaniel Grumberg   SGSerializer.serialize(*OS);
686a9909d23SDaniel Grumberg   OS->flush();
687a9909d23SDaniel Grumberg }
688a9909d23SDaniel Grumberg 
68989f6b26fSZixu Wang std::unique_ptr<raw_pwrite_stream>
69089f6b26fSZixu Wang ExtractAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) {
69189f6b26fSZixu Wang   std::unique_ptr<raw_pwrite_stream> OS =
69289f6b26fSZixu Wang       CI.createDefaultOutputFile(/*Binary=*/false, InFile, /*Extension=*/"json",
69389f6b26fSZixu Wang                                  /*RemoveFileOnSignal=*/false);
69489f6b26fSZixu Wang   if (!OS)
69589f6b26fSZixu Wang     return nullptr;
69689f6b26fSZixu Wang   return OS;
69789f6b26fSZixu Wang }
698