CXExtractAPI.cpp 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  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
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "CXCursor.h"
  13. #include "CXString.h"
  14. #include "CXTranslationUnit.h"
  15. #include "clang-c/CXErrorCode.h"
  16. #include "clang-c/Documentation.h"
  17. #include "clang-c/Index.h"
  18. #include "clang-c/Platform.h"
  19. #include "clang/AST/Decl.h"
  20. #include "clang/Basic/TargetInfo.h"
  21. #include "clang/ExtractAPI/API.h"
  22. #include "clang/ExtractAPI/ExtractAPIVisitor.h"
  23. #include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h"
  24. #include "clang/Frontend/ASTUnit.h"
  25. #include "clang/Frontend/FrontendOptions.h"
  26. #include "clang/Index/USRGeneration.h"
  27. #include "llvm/ADT/SmallString.h"
  28. #include "llvm/Support/CBindingWrapping.h"
  29. #include "llvm/Support/Casting.h"
  30. #include "llvm/Support/JSON.h"
  31. #include "llvm/Support/raw_ostream.h"
  32. using namespace clang;
  33. using namespace clang::extractapi;
  34. DEFINE_SIMPLE_CONVERSION_FUNCTIONS(APISet, CXAPISet)
  35. static void WalkupFromMostDerivedType(ExtractAPIVisitor &Visitor, Decl *D);
  36. template <typename DeclTy>
  37. static bool WalkupParentContext(DeclContext *Parent,
  38. ExtractAPIVisitor &Visitor) {
  39. if (auto *D = dyn_cast<DeclTy>(Parent)) {
  40. WalkupFromMostDerivedType(Visitor, D);
  41. return true;
  42. }
  43. return false;
  44. }
  45. static void WalkupFromMostDerivedType(ExtractAPIVisitor &Visitor, Decl *D) {
  46. switch (D->getKind()) {
  47. #define ABSTRACT_DECL(DECL)
  48. #define DECL(CLASS, BASE) \
  49. case Decl::CLASS: \
  50. Visitor.WalkUpFrom##CLASS##Decl(static_cast<CLASS##Decl *>(D)); \
  51. break;
  52. #include "clang/AST/DeclNodes.inc"
  53. }
  54. for (auto *Parent = D->getDeclContext(); Parent != nullptr;
  55. Parent = Parent->getParent()) {
  56. if (WalkupParentContext<ObjCContainerDecl>(Parent, Visitor))
  57. return;
  58. if (WalkupParentContext<TagDecl>(Parent, Visitor))
  59. return;
  60. }
  61. }
  62. static CXString GenerateCXStringFromSymbolGraphData(llvm::json::Object Obj) {
  63. llvm::SmallString<0> BackingString;
  64. llvm::raw_svector_ostream OS(BackingString);
  65. OS << Value(std::move(Obj));
  66. return cxstring::createDup(BackingString.str());
  67. }
  68. enum CXErrorCode clang_createAPISet(CXTranslationUnit tu, CXAPISet *out_api) {
  69. if (cxtu::isNotUsableTU(tu) || !out_api)
  70. return CXError_InvalidArguments;
  71. ASTUnit *Unit = cxtu::getASTUnit(tu);
  72. auto &Ctx = Unit->getASTContext();
  73. auto Lang = Unit->getInputKind().getLanguage();
  74. APISet *API = new APISet(Ctx.getTargetInfo().getTriple(), Lang,
  75. Unit->getMainFileName().str());
  76. ExtractAPIVisitor Visitor(
  77. Ctx, [](SourceLocation Loc) { return true; }, *API);
  78. for (auto It = Unit->top_level_begin(); It != Unit->top_level_end(); ++It) {
  79. Visitor.TraverseDecl(*It);
  80. }
  81. *out_api = wrap(API);
  82. return CXError_Success;
  83. }
  84. void clang_disposeAPISet(CXAPISet api) { delete unwrap(api); }
  85. CXString clang_getSymbolGraphForUSR(const char *usr, CXAPISet api) {
  86. auto *API = unwrap(api);
  87. if (auto SGF = SymbolGraphSerializer::serializeSingleSymbolSGF(usr, *API))
  88. return GenerateCXStringFromSymbolGraphData(std::move(*SGF));
  89. return cxstring::createNull();
  90. }
  91. CXString clang_getSymbolGraphForCursor(CXCursor cursor) {
  92. CXCursorKind Kind = clang_getCursorKind(cursor);
  93. if (clang_isDeclaration(Kind)) {
  94. const Decl *D = cxcursor::getCursorDecl(cursor);
  95. if (!D)
  96. return cxstring::createNull();
  97. CXTranslationUnit TU = cxcursor::getCursorTU(cursor);
  98. if (!TU)
  99. return cxstring::createNull();
  100. ASTUnit *Unit = cxtu::getASTUnit(TU);
  101. auto &Ctx = Unit->getASTContext();
  102. auto Lang = Unit->getInputKind().getLanguage();
  103. APISet API(Ctx.getTargetInfo().getTriple(), Lang,
  104. Unit->getMainFileName().str());
  105. ExtractAPIVisitor Visitor(
  106. Ctx, [](SourceLocation Loc) { return true; }, API);
  107. SmallString<128> USR;
  108. if (index::generateUSRForDecl(D, USR))
  109. return cxstring::createNull();
  110. WalkupFromMostDerivedType(Visitor, const_cast<Decl *>(D));
  111. auto *Record = API.findRecordForUSR(USR);
  112. if (!Record)
  113. return cxstring::createNull();
  114. for (const auto &Fragment : Record->Declaration.getFragments()) {
  115. if (Fragment.Declaration)
  116. WalkupFromMostDerivedType(Visitor,
  117. const_cast<Decl *>(Fragment.Declaration));
  118. }
  119. if (auto SGF = SymbolGraphSerializer::serializeSingleSymbolSGF(USR, API))
  120. return GenerateCXStringFromSymbolGraphData(std::move(*SGF));
  121. }
  122. return cxstring::createNull();
  123. }