189f6b26fSZixu Wang //===- ExtractAPI/API.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 APIRecord and derived record structs,
1189f6b26fSZixu Wang /// and the APISet class.
1289f6b26fSZixu Wang ///
1389f6b26fSZixu Wang //===----------------------------------------------------------------------===//
1489f6b26fSZixu Wang 
1589f6b26fSZixu Wang #include "clang/ExtractAPI/API.h"
1689f6b26fSZixu Wang #include "clang/AST/CommentCommandTraits.h"
1789f6b26fSZixu Wang #include "clang/AST/CommentLexer.h"
1889f6b26fSZixu Wang #include "clang/AST/RawCommentList.h"
1989f6b26fSZixu Wang #include "clang/Index/USRGeneration.h"
2089f6b26fSZixu Wang #include "llvm/Support/Allocator.h"
2189f6b26fSZixu Wang 
2289f6b26fSZixu Wang using namespace clang::extractapi;
2389f6b26fSZixu Wang using namespace llvm;
2489f6b26fSZixu Wang 
2589f6b26fSZixu Wang GlobalRecord *APISet::addGlobal(GVKind Kind, StringRef Name, StringRef USR,
2689f6b26fSZixu Wang                                 PresumedLoc Loc,
2789f6b26fSZixu Wang                                 const AvailabilityInfo &Availability,
2889f6b26fSZixu Wang                                 LinkageInfo Linkage, const DocComment &Comment,
2989f6b26fSZixu Wang                                 DeclarationFragments Fragments,
3089f6b26fSZixu Wang                                 DeclarationFragments SubHeading,
3189f6b26fSZixu Wang                                 FunctionSignature Signature) {
3289f6b26fSZixu Wang   auto Result = Globals.insert({Name, nullptr});
3389f6b26fSZixu Wang   if (Result.second) {
3489f6b26fSZixu Wang     // Create the record if it does not already exist.
3589f6b26fSZixu Wang     auto Record = APIRecordUniquePtr<GlobalRecord>(new (Allocator) GlobalRecord{
3689f6b26fSZixu Wang         Kind, Name, USR, Loc, Availability, Linkage, Comment, Fragments,
3789f6b26fSZixu Wang         SubHeading, Signature});
3889f6b26fSZixu Wang     Result.first->second = std::move(Record);
3989f6b26fSZixu Wang   }
4089f6b26fSZixu Wang   return Result.first->second.get();
4189f6b26fSZixu Wang }
4289f6b26fSZixu Wang 
4389f6b26fSZixu Wang GlobalRecord *
4489f6b26fSZixu Wang APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
4589f6b26fSZixu Wang                      const AvailabilityInfo &Availability, LinkageInfo Linkage,
4689f6b26fSZixu Wang                      const DocComment &Comment, DeclarationFragments Fragments,
4789f6b26fSZixu Wang                      DeclarationFragments SubHeading) {
4889f6b26fSZixu Wang   return addGlobal(GVKind::Variable, Name, USR, Loc, Availability, Linkage,
4989f6b26fSZixu Wang                    Comment, Fragments, SubHeading, {});
5089f6b26fSZixu Wang }
5189f6b26fSZixu Wang 
5289f6b26fSZixu Wang GlobalRecord *
5389f6b26fSZixu Wang APISet::addFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
5489f6b26fSZixu Wang                     const AvailabilityInfo &Availability, LinkageInfo Linkage,
5589f6b26fSZixu Wang                     const DocComment &Comment, DeclarationFragments Fragments,
5689f6b26fSZixu Wang                     DeclarationFragments SubHeading,
5789f6b26fSZixu Wang                     FunctionSignature Signature) {
5889f6b26fSZixu Wang   return addGlobal(GVKind::Function, Name, USR, Loc, Availability, Linkage,
5989f6b26fSZixu Wang                    Comment, Fragments, SubHeading, Signature);
6089f6b26fSZixu Wang }
6189f6b26fSZixu Wang 
62*71b4c226SZixu Wang EnumConstantRecord *APISet::addEnumConstant(
63*71b4c226SZixu Wang     EnumRecord *Enum, StringRef Name, StringRef USR, PresumedLoc Loc,
64*71b4c226SZixu Wang     const AvailabilityInfo &Availability, const DocComment &Comment,
65*71b4c226SZixu Wang     DeclarationFragments Declaration, DeclarationFragments SubHeading) {
66*71b4c226SZixu Wang   auto Record =
67*71b4c226SZixu Wang       APIRecordUniquePtr<EnumConstantRecord>(new (Allocator) EnumConstantRecord{
68*71b4c226SZixu Wang           Name, USR, Loc, Availability, Comment, Declaration, SubHeading});
69*71b4c226SZixu Wang   return Enum->Constants.emplace_back(std::move(Record)).get();
70*71b4c226SZixu Wang }
71*71b4c226SZixu Wang 
72*71b4c226SZixu Wang EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
73*71b4c226SZixu Wang                             const AvailabilityInfo &Availability,
74*71b4c226SZixu Wang                             const DocComment &Comment,
75*71b4c226SZixu Wang                             DeclarationFragments Declaration,
76*71b4c226SZixu Wang                             DeclarationFragments SubHeading) {
77*71b4c226SZixu Wang   auto Result = Enums.insert({Name, nullptr});
78*71b4c226SZixu Wang   if (Result.second) {
79*71b4c226SZixu Wang     // Create the record if it does not already exist.
80*71b4c226SZixu Wang     auto Record = APIRecordUniquePtr<EnumRecord>(new (Allocator) EnumRecord{
81*71b4c226SZixu Wang         Name, USR, Loc, Availability, Comment, Declaration, SubHeading});
82*71b4c226SZixu Wang     Result.first->second = std::move(Record);
83*71b4c226SZixu Wang   }
84*71b4c226SZixu Wang   return Result.first->second.get();
85*71b4c226SZixu Wang }
86*71b4c226SZixu Wang 
8789f6b26fSZixu Wang StringRef APISet::recordUSR(const Decl *D) {
8889f6b26fSZixu Wang   SmallString<128> USR;
8989f6b26fSZixu Wang   index::generateUSRForDecl(D, USR);
9089f6b26fSZixu Wang   return copyString(USR);
9189f6b26fSZixu Wang }
9289f6b26fSZixu Wang 
9389f6b26fSZixu Wang StringRef APISet::copyString(StringRef String) {
9489f6b26fSZixu Wang   if (String.empty())
9589f6b26fSZixu Wang     return {};
9689f6b26fSZixu Wang 
9789f6b26fSZixu Wang   // No need to allocate memory and copy if the string has already been stored.
9889f6b26fSZixu Wang   if (Allocator.identifyObject(String.data()))
9989f6b26fSZixu Wang     return String;
10089f6b26fSZixu Wang 
10189f6b26fSZixu Wang   void *Ptr = Allocator.Allocate(String.size(), 1);
10289f6b26fSZixu Wang   memcpy(Ptr, String.data(), String.size());
10389f6b26fSZixu Wang   return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
10489f6b26fSZixu Wang }
10589f6b26fSZixu Wang 
10689f6b26fSZixu Wang APIRecord::~APIRecord() {}
10789f6b26fSZixu Wang 
10889f6b26fSZixu Wang void GlobalRecord::anchor() {}
109