[DFAJumpThreading] Remove incoming StartBlock from all phis when unfolding select...
[llvm-project.git] / clang / tools / libclang / CXExtractAPI.cpp
blob9128e891538a807a6ed0a7ff1326206d0c271713
1 //===- CXExtractAPI.cpp - libclang APIs for manipulating CXAPISet ---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file defines all libclang APIs related to manipulation CXAPISet
11 //===----------------------------------------------------------------------===//
13 #include "CXCursor.h"
14 #include "CXString.h"
15 #include "CXTranslationUnit.h"
16 #include "clang-c/CXErrorCode.h"
17 #include "clang-c/Documentation.h"
18 #include "clang-c/Index.h"
19 #include "clang-c/Platform.h"
20 #include "clang/AST/Decl.h"
21 #include "clang/AST/DeclObjC.h"
22 #include "clang/Basic/TargetInfo.h"
23 #include "clang/ExtractAPI/API.h"
24 #include "clang/ExtractAPI/ExtractAPIVisitor.h"
25 #include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h"
26 #include "clang/Frontend/ASTUnit.h"
27 #include "clang/Frontend/FrontendOptions.h"
28 #include "clang/Index/USRGeneration.h"
29 #include "llvm/ADT/SmallString.h"
30 #include "llvm/Support/CBindingWrapping.h"
31 #include "llvm/Support/Casting.h"
32 #include "llvm/Support/JSON.h"
33 #include "llvm/Support/raw_ostream.h"
35 using namespace clang;
36 using namespace clang::extractapi;
38 namespace {
39 struct LibClangExtractAPIVisitor
40 : ExtractAPIVisitor<LibClangExtractAPIVisitor> {
41 using Base = ExtractAPIVisitor<LibClangExtractAPIVisitor>;
43 LibClangExtractAPIVisitor(ASTContext &Context, APISet &API)
44 : ExtractAPIVisitor<LibClangExtractAPIVisitor>(Context, API) {}
46 const RawComment *fetchRawCommentForDecl(const Decl *D) const {
47 return Context.getRawCommentForAnyRedecl(D);
50 // We need to visit implementations as well to ensure that when a user clicks
51 // on a method defined only within the implementation that we can still
52 // provide a symbol graph for it.
53 bool VisitObjCImplementationDecl(const ObjCImplementationDecl *Decl) {
54 if (!shouldDeclBeIncluded(Decl))
55 return true;
57 const ObjCInterfaceDecl *Interface = Decl->getClassInterface();
58 StringRef Name = Interface->getName();
59 StringRef USR = API.recordUSR(Decl);
60 PresumedLoc Loc =
61 Context.getSourceManager().getPresumedLoc(Decl->getLocation());
62 LinkageInfo Linkage = Decl->getLinkageAndVisibility();
63 DocComment Comment;
64 if (auto *RawComment = fetchRawCommentForDecl(Interface))
65 Comment = RawComment->getFormattedLines(Context.getSourceManager(),
66 Context.getDiagnostics());
68 // Build declaration fragments and sub-heading by generating them for the
69 // interface.
70 DeclarationFragments Declaration =
71 DeclarationFragmentsBuilder::getFragmentsForObjCInterface(Interface);
72 DeclarationFragments SubHeading =
73 DeclarationFragmentsBuilder::getSubHeading(Decl);
75 // Collect super class information.
76 SymbolReference SuperClass;
77 if (const auto *SuperClassDecl = Decl->getSuperClass()) {
78 SuperClass.Name = SuperClassDecl->getObjCRuntimeNameAsString();
79 SuperClass.USR = API.recordUSR(SuperClassDecl);
82 ObjCInterfaceRecord *ObjCInterfaceRecord = API.addObjCInterface(
83 Name, USR, Loc, AvailabilitySet(Decl), Linkage, Comment, Declaration,
84 SubHeading, SuperClass, isInSystemHeader(Decl));
86 // Record all methods (selectors). This doesn't include automatically
87 // synthesized property methods.
88 recordObjCMethods(ObjCInterfaceRecord, Decl->methods());
89 recordObjCProperties(ObjCInterfaceRecord, Decl->properties());
90 recordObjCInstanceVariables(ObjCInterfaceRecord, Decl->ivars());
92 return true;
95 } // namespace
97 DEFINE_SIMPLE_CONVERSION_FUNCTIONS(APISet, CXAPISet)
99 static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
100 Decl *D);
102 template <typename DeclTy>
103 static bool WalkupParentContext(DeclContext *Parent,
104 LibClangExtractAPIVisitor &Visitor) {
105 if (auto *D = dyn_cast<DeclTy>(Parent)) {
106 WalkupFromMostDerivedType(Visitor, D);
107 return true;
109 return false;
112 static void WalkupFromMostDerivedType(LibClangExtractAPIVisitor &Visitor,
113 Decl *D) {
114 switch (D->getKind()) {
115 #define ABSTRACT_DECL(DECL)
116 #define DECL(CLASS, BASE) \
117 case Decl::CLASS: \
118 Visitor.WalkUpFrom##CLASS##Decl(static_cast<CLASS##Decl *>(D)); \
119 break;
120 #include "clang/AST/DeclNodes.inc"
123 for (auto *Parent = D->getDeclContext(); Parent != nullptr;
124 Parent = Parent->getParent()) {
125 if (WalkupParentContext<ObjCContainerDecl>(Parent, Visitor))
126 return;
127 if (WalkupParentContext<TagDecl>(Parent, Visitor))
128 return;
132 static CXString GenerateCXStringFromSymbolGraphData(llvm::json::Object Obj) {
133 llvm::SmallString<0> BackingString;
134 llvm::raw_svector_ostream OS(BackingString);
135 OS << Value(std::move(Obj));
136 return cxstring::createDup(BackingString.str());
139 enum CXErrorCode clang_createAPISet(CXTranslationUnit tu, CXAPISet *out_api) {
140 if (cxtu::isNotUsableTU(tu) || !out_api)
141 return CXError_InvalidArguments;
143 ASTUnit *Unit = cxtu::getASTUnit(tu);
145 auto &Ctx = Unit->getASTContext();
146 auto Lang = Unit->getInputKind().getLanguage();
147 APISet *API = new APISet(Ctx.getTargetInfo().getTriple(), Lang,
148 Unit->getMainFileName().str());
149 LibClangExtractAPIVisitor Visitor(Ctx, *API);
151 for (auto It = Unit->top_level_begin(); It != Unit->top_level_end(); ++It) {
152 Visitor.TraverseDecl(*It);
155 *out_api = wrap(API);
156 return CXError_Success;
159 void clang_disposeAPISet(CXAPISet api) { delete unwrap(api); }
161 CXString clang_getSymbolGraphForUSR(const char *usr, CXAPISet api) {
162 auto *API = unwrap(api);
164 if (auto SGF = SymbolGraphSerializer::serializeSingleSymbolSGF(usr, *API))
165 return GenerateCXStringFromSymbolGraphData(std::move(*SGF));
167 return cxstring::createNull();
170 CXString clang_getSymbolGraphForCursor(CXCursor cursor) {
171 cursor = clang_getCursorReferenced(cursor);
172 CXCursorKind Kind = clang_getCursorKind(cursor);
173 if (!clang_isDeclaration(Kind))
174 return cxstring::createNull();
176 const Decl *D = cxcursor::getCursorDecl(cursor);
178 if (!D)
179 return cxstring::createNull();
181 CXTranslationUnit TU = cxcursor::getCursorTU(cursor);
182 if (!TU)
183 return cxstring::createNull();
185 ASTUnit *Unit = cxtu::getASTUnit(TU);
187 auto &Ctx = Unit->getASTContext();
189 auto Lang = Unit->getInputKind().getLanguage();
190 APISet API(Ctx.getTargetInfo().getTriple(), Lang,
191 Unit->getMainFileName().str());
192 LibClangExtractAPIVisitor Visitor(Ctx, API);
194 const Decl *CanonicalDecl = D->getCanonicalDecl();
195 CanonicalDecl = CanonicalDecl ? CanonicalDecl : D;
197 SmallString<128> USR;
198 if (index::generateUSRForDecl(CanonicalDecl, USR))
199 return cxstring::createNull();
201 WalkupFromMostDerivedType(Visitor, const_cast<Decl *>(CanonicalDecl));
202 auto *Record = API.findRecordForUSR(USR);
204 if (!Record)
205 return cxstring::createNull();
207 for (const auto &Fragment : Record->Declaration.getFragments()) {
208 if (Fragment.Declaration)
209 WalkupFromMostDerivedType(Visitor,
210 const_cast<Decl *>(Fragment.Declaration));
213 if (auto SGF = SymbolGraphSerializer::serializeSingleSymbolSGF(USR, API))
214 return GenerateCXStringFromSymbolGraphData(std::move(*SGF));
216 return cxstring::createNull();