1145449b1SDimitry Andric //===- ExtractAPI/API.cpp ---------------------------------------*- C++ -*-===//
2145449b1SDimitry Andric //
3145449b1SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4145449b1SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5145449b1SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6145449b1SDimitry Andric //
7145449b1SDimitry Andric //===----------------------------------------------------------------------===//
8145449b1SDimitry Andric ///
9145449b1SDimitry Andric /// \file
10145449b1SDimitry Andric /// This file implements the APIRecord and derived record structs,
11145449b1SDimitry Andric /// and the APISet class.
12145449b1SDimitry Andric ///
13145449b1SDimitry Andric //===----------------------------------------------------------------------===//
14145449b1SDimitry Andric
15145449b1SDimitry Andric #include "clang/ExtractAPI/API.h"
16145449b1SDimitry Andric #include "clang/AST/RawCommentList.h"
17145449b1SDimitry Andric #include "clang/Index/USRGeneration.h"
18145449b1SDimitry Andric #include "llvm/ADT/StringRef.h"
19ac9a064cSDimitry Andric #include "llvm/Support/ErrorHandling.h"
20145449b1SDimitry Andric #include <memory>
21145449b1SDimitry Andric
22145449b1SDimitry Andric using namespace clang::extractapi;
23145449b1SDimitry Andric using namespace llvm;
24145449b1SDimitry Andric
SymbolReference(const APIRecord * R)25ac9a064cSDimitry Andric SymbolReference::SymbolReference(const APIRecord *R)
26ac9a064cSDimitry Andric : Name(R->Name), USR(R->USR), Record(R) {}
27145449b1SDimitry Andric
castFromRecordContext(const RecordContext * Ctx)28ac9a064cSDimitry Andric APIRecord *APIRecord::castFromRecordContext(const RecordContext *Ctx) {
29ac9a064cSDimitry Andric switch (Ctx->getKind()) {
30ac9a064cSDimitry Andric #define RECORD_CONTEXT(CLASS, KIND) \
31ac9a064cSDimitry Andric case KIND: \
32ac9a064cSDimitry Andric return static_cast<CLASS *>(const_cast<RecordContext *>(Ctx));
33ac9a064cSDimitry Andric #include "clang/ExtractAPI/APIRecords.inc"
34ac9a064cSDimitry Andric default:
35ac9a064cSDimitry Andric return nullptr;
36ac9a064cSDimitry Andric // llvm_unreachable("RecordContext derived class isn't propertly
37ac9a064cSDimitry Andric // implemented");
38ac9a064cSDimitry Andric }
39145449b1SDimitry Andric }
40145449b1SDimitry Andric
castToRecordContext(const APIRecord * Record)41ac9a064cSDimitry Andric RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) {
42ac9a064cSDimitry Andric if (!Record)
43ac9a064cSDimitry Andric return nullptr;
44ac9a064cSDimitry Andric switch (Record->getKind()) {
45ac9a064cSDimitry Andric #define RECORD_CONTEXT(CLASS, KIND) \
46ac9a064cSDimitry Andric case KIND: \
47ac9a064cSDimitry Andric return static_cast<CLASS *>(const_cast<APIRecord *>(Record));
48ac9a064cSDimitry Andric #include "clang/ExtractAPI/APIRecords.inc"
49ac9a064cSDimitry Andric default:
50ac9a064cSDimitry Andric return nullptr;
51ac9a064cSDimitry Andric // llvm_unreachable("RecordContext derived class isn't propertly
52ac9a064cSDimitry Andric // implemented");
53ac9a064cSDimitry Andric }
54b1c73532SDimitry Andric }
55b1c73532SDimitry Andric
IsWellFormed() const56ac9a064cSDimitry Andric bool RecordContext::IsWellFormed() const {
57ac9a064cSDimitry Andric // Check that First and Last are both null or both non-null.
58ac9a064cSDimitry Andric return (First == nullptr) == (Last == nullptr);
59145449b1SDimitry Andric }
60145449b1SDimitry Andric
stealRecordChain(RecordContext & Other)61ac9a064cSDimitry Andric void RecordContext::stealRecordChain(RecordContext &Other) {
62ac9a064cSDimitry Andric assert(IsWellFormed());
63ac9a064cSDimitry Andric // If we don't have an empty chain append Other's chain into ours.
64ac9a064cSDimitry Andric if (First)
65ac9a064cSDimitry Andric Last->NextInContext = Other.First;
66e3b55780SDimitry Andric else
67ac9a064cSDimitry Andric First = Other.First;
68e3b55780SDimitry Andric
69ac9a064cSDimitry Andric Last = Other.Last;
70ac9a064cSDimitry Andric
71ac9a064cSDimitry Andric // Delete Other's chain to ensure we don't accidentally traverse it.
72ac9a064cSDimitry Andric Other.First = nullptr;
73ac9a064cSDimitry Andric Other.Last = nullptr;
74145449b1SDimitry Andric }
75145449b1SDimitry Andric
addToRecordChain(APIRecord * Record) const76ac9a064cSDimitry Andric void RecordContext::addToRecordChain(APIRecord *Record) const {
77ac9a064cSDimitry Andric assert(IsWellFormed());
78ac9a064cSDimitry Andric if (!First) {
79ac9a064cSDimitry Andric First = Record;
80ac9a064cSDimitry Andric Last = Record;
81ac9a064cSDimitry Andric return;
82145449b1SDimitry Andric }
83145449b1SDimitry Andric
84ac9a064cSDimitry Andric Last->NextInContext = Record;
85ac9a064cSDimitry Andric Last = Record;
86e3b55780SDimitry Andric }
87e3b55780SDimitry Andric
findRecordForUSR(StringRef USR) const88e3b55780SDimitry Andric APIRecord *APISet::findRecordForUSR(StringRef USR) const {
89e3b55780SDimitry Andric if (USR.empty())
90e3b55780SDimitry Andric return nullptr;
91e3b55780SDimitry Andric
92ac9a064cSDimitry Andric auto FindIt = USRBasedLookupTable.find(USR);
93ac9a064cSDimitry Andric if (FindIt != USRBasedLookupTable.end())
94ac9a064cSDimitry Andric return FindIt->getSecond().get();
95145449b1SDimitry Andric
96ac9a064cSDimitry Andric return nullptr;
97145449b1SDimitry Andric }
98145449b1SDimitry Andric
copyString(StringRef String)99145449b1SDimitry Andric StringRef APISet::copyString(StringRef String) {
100145449b1SDimitry Andric if (String.empty())
101145449b1SDimitry Andric return {};
102145449b1SDimitry Andric
103145449b1SDimitry Andric // No need to allocate memory and copy if the string has already been stored.
104ac9a064cSDimitry Andric if (Allocator.identifyObject(String.data()))
105145449b1SDimitry Andric return String;
106145449b1SDimitry Andric
107ac9a064cSDimitry Andric void *Ptr = Allocator.Allocate(String.size(), 1);
108145449b1SDimitry Andric memcpy(Ptr, String.data(), String.size());
109145449b1SDimitry Andric return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
110145449b1SDimitry Andric }
111145449b1SDimitry Andric
createSymbolReference(StringRef Name,StringRef USR,StringRef Source)112ac9a064cSDimitry Andric SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR,
113ac9a064cSDimitry Andric StringRef Source) {
114ac9a064cSDimitry Andric return SymbolReference(copyString(Name), copyString(USR), copyString(Source));
115ac9a064cSDimitry Andric }
116ac9a064cSDimitry Andric
~APIRecord()117145449b1SDimitry Andric APIRecord::~APIRecord() {}
~TagRecord()118ac9a064cSDimitry Andric TagRecord::~TagRecord() {}
~RecordRecord()119ac9a064cSDimitry Andric RecordRecord::~RecordRecord() {}
~RecordFieldRecord()120ac9a064cSDimitry Andric RecordFieldRecord::~RecordFieldRecord() {}
~ObjCContainerRecord()121145449b1SDimitry Andric ObjCContainerRecord::~ObjCContainerRecord() {}
~ObjCMethodRecord()122e3b55780SDimitry Andric ObjCMethodRecord::~ObjCMethodRecord() {}
~ObjCPropertyRecord()123e3b55780SDimitry Andric ObjCPropertyRecord::~ObjCPropertyRecord() {}
~CXXMethodRecord()124b1c73532SDimitry Andric CXXMethodRecord::~CXXMethodRecord() {}
125145449b1SDimitry Andric
anchor()126145449b1SDimitry Andric void GlobalFunctionRecord::anchor() {}
anchor()127145449b1SDimitry Andric void GlobalVariableRecord::anchor() {}
anchor()128145449b1SDimitry Andric void EnumConstantRecord::anchor() {}
anchor()129145449b1SDimitry Andric void EnumRecord::anchor() {}
anchor()130ac9a064cSDimitry Andric void StructFieldRecord::anchor() {}
anchor()131ac9a064cSDimitry Andric void StructRecord::anchor() {}
anchor()132ac9a064cSDimitry Andric void UnionFieldRecord::anchor() {}
anchor()133ac9a064cSDimitry Andric void UnionRecord::anchor() {}
anchor()134b1c73532SDimitry Andric void CXXFieldRecord::anchor() {}
anchor()135b1c73532SDimitry Andric void CXXClassRecord::anchor() {}
anchor()136b1c73532SDimitry Andric void CXXConstructorRecord::anchor() {}
anchor()137b1c73532SDimitry Andric void CXXDestructorRecord::anchor() {}
anchor()138b1c73532SDimitry Andric void CXXInstanceMethodRecord::anchor() {}
anchor()139b1c73532SDimitry Andric void CXXStaticMethodRecord::anchor() {}
anchor()140e3b55780SDimitry Andric void ObjCInstancePropertyRecord::anchor() {}
anchor()141e3b55780SDimitry Andric void ObjCClassPropertyRecord::anchor() {}
anchor()142145449b1SDimitry Andric void ObjCInstanceVariableRecord::anchor() {}
anchor()143e3b55780SDimitry Andric void ObjCInstanceMethodRecord::anchor() {}
anchor()144e3b55780SDimitry Andric void ObjCClassMethodRecord::anchor() {}
anchor()145145449b1SDimitry Andric void ObjCCategoryRecord::anchor() {}
anchor()146145449b1SDimitry Andric void ObjCInterfaceRecord::anchor() {}
anchor()147145449b1SDimitry Andric void ObjCProtocolRecord::anchor() {}
anchor()148145449b1SDimitry Andric void MacroDefinitionRecord::anchor() {}
anchor()149145449b1SDimitry Andric void TypedefRecord::anchor() {}
150