aboutsummaryrefslogtreecommitdiff
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/Driver/Driver.cpp7
-rw-r--r--clang/lib/Driver/ToolChains/Clang.cpp15
-rw-r--r--clang/lib/ExtractAPI/API.cpp544
-rw-r--r--clang/lib/ExtractAPI/DeclarationFragments.cpp71
-rw-r--r--clang/lib/ExtractAPI/ExtractAPIConsumer.cpp112
-rw-r--r--clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp943
-rw-r--r--clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp6
-rw-r--r--clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp10
8 files changed, 1143 insertions, 565 deletions
diff --git a/clang/lib/Driver/Driver.cpp b/clang/lib/Driver/Driver.cpp
index e6c1767..1a0f5f2 100644
--- a/clang/lib/Driver/Driver.cpp
+++ b/clang/lib/Driver/Driver.cpp
@@ -49,7 +49,6 @@
#include "ToolChains/WebAssembly.h"
#include "ToolChains/XCore.h"
#include "ToolChains/ZOS.h"
-#include "clang/Basic/DiagnosticDriver.h"
#include "clang/Basic/TargetID.h"
#include "clang/Basic/Version.h"
#include "clang/Config/config.h"
@@ -5890,12 +5889,6 @@ const char *Driver::GetNamedOutputPath(Compilation &C, const JobAction &JA,
&JA);
}
- if (JA.getType() == types::TY_API_INFO &&
- C.getArgs().hasArg(options::OPT_emit_extension_symbol_graphs) &&
- C.getArgs().hasArg(options::OPT_o))
- Diag(clang::diag::err_drv_unexpected_symbol_graph_output)
- << C.getArgs().getLastArgValue(options::OPT_o);
-
// DXC defaults to standard out when generating assembly. We check this after
// any DXC flags that might specify a file.
if (AtTopLevel && JA.getType() == types::TY_PP_Asm && IsDXCMode())
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp
index b7ec7e0..7fd6ad6 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -5046,26 +5046,11 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
assert(JA.getType() == types::TY_API_INFO &&
"Extract API actions must generate a API information.");
CmdArgs.push_back("-extract-api");
-
- if (Arg *PrettySGFArg = Args.getLastArg(options::OPT_emit_pretty_sgf))
- PrettySGFArg->render(Args, CmdArgs);
-
- Arg *SymbolGraphDirArg = Args.getLastArg(options::OPT_symbol_graph_dir_EQ);
-
if (Arg *ProductNameArg = Args.getLastArg(options::OPT_product_name_EQ))
ProductNameArg->render(Args, CmdArgs);
if (Arg *ExtractAPIIgnoresFileArg =
Args.getLastArg(options::OPT_extract_api_ignores_EQ))
ExtractAPIIgnoresFileArg->render(Args, CmdArgs);
- if (Arg *EmitExtensionSymbolGraphs =
- Args.getLastArg(options::OPT_emit_extension_symbol_graphs)) {
- if (!SymbolGraphDirArg)
- D.Diag(diag::err_drv_missing_symbol_graph_dir);
-
- EmitExtensionSymbolGraphs->render(Args, CmdArgs);
- }
- if (SymbolGraphDirArg)
- SymbolGraphDirArg->render(Args, CmdArgs);
} else {
assert((isa<CompileJobAction>(JA) || isa<BackendJobAction>(JA)) &&
"Invalid action for clang tool.");
diff --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp
index 5a62c5d..aa7a1e9 100644
--- a/clang/lib/ExtractAPI/API.cpp
+++ b/clang/lib/ExtractAPI/API.cpp
@@ -13,67 +13,514 @@
//===----------------------------------------------------------------------===//
#include "clang/ExtractAPI/API.h"
+#include "clang/AST/CommentCommandTraits.h"
+#include "clang/AST/CommentLexer.h"
#include "clang/AST/RawCommentList.h"
-#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"
#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/ErrorHandling.h"
#include <memory>
using namespace clang::extractapi;
using namespace llvm;
-SymbolReference::SymbolReference(const APIRecord *R)
- : Name(R->Name), USR(R->USR), Record(R) {}
+namespace {
-APIRecord *APIRecord::castFromRecordContext(const RecordContext *Ctx) {
- switch (Ctx->getKind()) {
-#define RECORD_CONTEXT(CLASS, KIND) \
- case KIND: \
- return static_cast<CLASS *>(const_cast<RecordContext *>(Ctx));
-#include "clang/ExtractAPI/APIRecords.inc"
- default:
- return nullptr;
- // llvm_unreachable("RecordContext derived class isn't propertly
- // implemented");
- }
+template <typename RecordTy, typename... CtorArgsTy>
+RecordTy *addTopLevelRecord(DenseMap<StringRef, APIRecord *> &USRLookupTable,
+ APISet::RecordMap<RecordTy> &RecordMap,
+ StringRef USR, CtorArgsTy &&...CtorArgs) {
+ auto Result = RecordMap.insert({USR, nullptr});
+
+ // Create the record if it does not already exist
+ if (Result.second)
+ Result.first->second =
+ std::make_unique<RecordTy>(USR, std::forward<CtorArgsTy>(CtorArgs)...);
+
+ auto *Record = Result.first->second.get();
+ USRLookupTable.insert({USR, Record});
+ return Record;
}
-RecordContext *APIRecord::castToRecordContext(const APIRecord *Record) {
- if (!Record)
- return nullptr;
- switch (Record->getKind()) {
-#define RECORD_CONTEXT(CLASS, KIND) \
- case KIND: \
- return static_cast<CLASS *>(const_cast<APIRecord *>(Record));
-#include "clang/ExtractAPI/APIRecords.inc"
- default:
- return nullptr;
- // llvm_unreachable("RecordContext derived class isn't propertly
- // implemented");
- }
+} // namespace
+
+NamespaceRecord *
+APISet::addNamespace(APIRecord *Parent, StringRef Name, StringRef USR,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ LinkageInfo Linkage, const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader) {
+ auto *Record = addTopLevelRecord(
+ USRBasedLookupTable, Namespaces, USR, Name, Loc, std::move(Availability),
+ Linkage, Comment, Declaration, SubHeading, IsFromSystemHeader);
+
+ if (Parent)
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Parent->USR, Parent->Name, Parent->getKind(), Parent);
+ return Record;
+}
+
+GlobalVariableRecord *
+APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Fragments,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, GlobalVariables, USR, Name, Loc,
+ std::move(Availability), Linkage, Comment, Fragments,
+ SubHeading, IsFromSystemHeader);
+}
+
+GlobalVariableTemplateRecord *APISet::addGlobalVariableTemplate(
+ StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, Template Template,
+ bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, GlobalVariableTemplates, USR,
+ Name, Loc, std::move(Availability), Linkage, Comment,
+ Declaration, SubHeading, Template,
+ IsFromSystemHeader);
+}
+
+GlobalFunctionRecord *APISet::addGlobalFunction(
+ StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Fragments,
+ DeclarationFragments SubHeading, FunctionSignature Signature,
+ bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, GlobalFunctions, USR, Name, Loc,
+ std::move(Availability), Linkage, Comment, Fragments,
+ SubHeading, Signature, IsFromSystemHeader);
+}
+
+GlobalFunctionTemplateRecord *APISet::addGlobalFunctionTemplate(
+ StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, FunctionSignature Signature,
+ Template Template, bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, GlobalFunctionTemplates, USR,
+ Name, Loc, std::move(Availability), Linkage, Comment,
+ Declaration, SubHeading, Signature, Template,
+ IsFromSystemHeader);
+}
+
+GlobalFunctionTemplateSpecializationRecord *
+APISet::addGlobalFunctionTemplateSpecialization(
+ StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, FunctionSignature Signature,
+ bool IsFromSystemHeader) {
+ return addTopLevelRecord(
+ USRBasedLookupTable, GlobalFunctionTemplateSpecializations, USR, Name,
+ Loc, std::move(Availability), Linkage, Comment, Declaration, SubHeading,
+ Signature, IsFromSystemHeader);
+}
+
+EnumConstantRecord *APISet::addEnumConstant(EnumRecord *Enum, StringRef Name,
+ StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability,
+ const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading,
+ bool IsFromSystemHeader) {
+ auto Record = std::make_unique<EnumConstantRecord>(
+ USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
+ IsFromSystemHeader);
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Enum->USR, Enum->Name, Enum->getKind(), Enum);
+ USRBasedLookupTable.insert({USR, Record.get()});
+ return Enum->Constants.emplace_back(std::move(Record)).get();
+}
+
+EnumRecord *APISet::addEnum(StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability,
+ const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading,
+ bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, Enums, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, IsFromSystemHeader);
}
-void RecordContext::addToRecordChain(APIRecord *Record) const {
- if (!First) {
- First = Record;
- Last = Record;
- return;
- }
+RecordFieldRecord *APISet::addRecordField(
+ RecordRecord *Record, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ APIRecord::RecordKind Kind, bool IsFromSystemHeader) {
+ auto RecordField = std::make_unique<RecordFieldRecord>(
+ USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
+ Kind, IsFromSystemHeader);
+ RecordField->ParentInformation = APIRecord::HierarchyInformation(
+ Record->USR, Record->Name, Record->getKind(), Record);
+ USRBasedLookupTable.insert({USR, RecordField.get()});
+ return Record->Fields.emplace_back(std::move(RecordField)).get();
+}
+
+RecordRecord *APISet::addRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability,
+ const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading,
+ APIRecord::RecordKind Kind,
+ bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, Records, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, Kind, IsFromSystemHeader);
+}
+
+StaticFieldRecord *
+APISet::addStaticField(StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, SymbolReference Context,
+ AccessControl Access, bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, StaticFields, USR, Name, Loc,
+ std::move(Availability), Linkage, Comment,
+ Declaration, SubHeading, Context, Access,
+ IsFromSystemHeader);
+}
+
+CXXFieldRecord *
+APISet::addCXXField(APIRecord *CXXClass, StringRef Name, StringRef USR,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, AccessControl Access,
+ bool IsFromSystemHeader) {
+ auto *Record = addTopLevelRecord(
+ USRBasedLookupTable, CXXFields, USR, Name, Loc, std::move(Availability),
+ Comment, Declaration, SubHeading, Access, IsFromSystemHeader);
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ CXXClass->USR, CXXClass->Name, CXXClass->getKind(), CXXClass);
+ return Record;
+}
+
+CXXFieldTemplateRecord *APISet::addCXXFieldTemplate(
+ APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ AccessControl Access, Template Template, bool IsFromSystemHeader) {
+ auto *Record =
+ addTopLevelRecord(USRBasedLookupTable, CXXFieldTemplates, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, Access, Template, IsFromSystemHeader);
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Parent->USR, Parent->Name, Parent->getKind(), Parent);
+
+ return Record;
+}
+
+CXXClassRecord *
+APISet::addCXXClass(APIRecord *Parent, StringRef Name, StringRef USR,
+ PresumedLoc Loc, AvailabilityInfo Availability,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, APIRecord::RecordKind Kind,
+ AccessControl Access, bool IsFromSystemHeader) {
+ auto *Record = addTopLevelRecord(
+ USRBasedLookupTable, CXXClasses, USR, Name, Loc, std::move(Availability),
+ Comment, Declaration, SubHeading, Kind, Access, IsFromSystemHeader);
+ if (Parent)
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Parent->USR, Parent->Name, Parent->getKind(), Parent);
+ return Record;
+}
+
+ClassTemplateRecord *APISet::addClassTemplate(
+ APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ Template Template, AccessControl Access, bool IsFromSystemHeader) {
+ auto *Record =
+ addTopLevelRecord(USRBasedLookupTable, ClassTemplates, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, Template, Access, IsFromSystemHeader);
+ if (Parent)
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Parent->USR, Parent->Name, Parent->getKind(), Parent);
+ return Record;
+}
+
+ClassTemplateSpecializationRecord *APISet::addClassTemplateSpecialization(
+ APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ AccessControl Access, bool IsFromSystemHeader) {
+ auto *Record =
+ addTopLevelRecord(USRBasedLookupTable, ClassTemplateSpecializations, USR,
+ Name, Loc, std::move(Availability), Comment,
+ Declaration, SubHeading, Access, IsFromSystemHeader);
+ if (Parent)
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Parent->USR, Parent->Name, Parent->getKind(), Parent);
+ return Record;
+}
+
+ClassTemplatePartialSpecializationRecord *
+APISet::addClassTemplatePartialSpecialization(
+ APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ Template Template, AccessControl Access, bool IsFromSystemHeader) {
+ auto *Record = addTopLevelRecord(
+ USRBasedLookupTable, ClassTemplatePartialSpecializations, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration, SubHeading, Template,
+ Access, IsFromSystemHeader);
+ if (Parent)
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Parent->USR, Parent->Name, Parent->getKind(), Parent);
+ return Record;
+}
+
+GlobalVariableTemplateSpecializationRecord *
+APISet::addGlobalVariableTemplateSpecialization(
+ StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable,
+ GlobalVariableTemplateSpecializations, USR, Name,
+ Loc, std::move(Availability), Linkage, Comment,
+ Declaration, SubHeading, IsFromSystemHeader);
+}
- Last->NextInContext = Record;
- Last = Record;
+GlobalVariableTemplatePartialSpecializationRecord *
+APISet::addGlobalVariableTemplatePartialSpecialization(
+ StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment, DeclarationFragments Declaration,
+ DeclarationFragments SubHeading, Template Template,
+ bool IsFromSystemHeader) {
+ return addTopLevelRecord(
+ USRBasedLookupTable, GlobalVariableTemplatePartialSpecializations, USR,
+ Name, Loc, std::move(Availability), Linkage, Comment, Declaration,
+ SubHeading, Template, IsFromSystemHeader);
+}
+
+ConceptRecord *APISet::addConcept(StringRef Name, StringRef USR,
+ PresumedLoc Loc,
+ AvailabilityInfo Availability,
+ const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading,
+ Template Template, bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, Concepts, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, Template, IsFromSystemHeader);
+}
+
+CXXMethodRecord *APISet::addCXXInstanceMethod(
+ APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ FunctionSignature Signature, AccessControl Access,
+ bool IsFromSystemHeader) {
+ CXXMethodRecord *Record =
+ addTopLevelRecord(USRBasedLookupTable, CXXInstanceMethods, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, Signature, Access, IsFromSystemHeader);
+
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
+ CXXClassRecord);
+ return Record;
+}
+
+CXXMethodRecord *APISet::addCXXStaticMethod(
+ APIRecord *CXXClassRecord, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ FunctionSignature Signature, AccessControl Access,
+ bool IsFromSystemHeader) {
+ CXXMethodRecord *Record =
+ addTopLevelRecord(USRBasedLookupTable, CXXStaticMethods, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, Signature, Access, IsFromSystemHeader);
+
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ CXXClassRecord->USR, CXXClassRecord->Name, CXXClassRecord->getKind(),
+ CXXClassRecord);
+ return Record;
+}
+
+CXXMethodTemplateRecord *APISet::addCXXMethodTemplate(
+ APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ FunctionSignature Signature, AccessControl Access, Template Template,
+ bool IsFromSystemHeader) {
+ auto *Record = addTopLevelRecord(USRBasedLookupTable, CXXMethodTemplates, USR,
+ Name, Loc, std::move(Availability), Comment,
+ Declaration, SubHeading, Signature, Access,
+ Template, IsFromSystemHeader);
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Parent->USR, Parent->Name, Parent->getKind(), Parent);
+
+ return Record;
+}
+
+CXXMethodTemplateSpecializationRecord *APISet::addCXXMethodTemplateSpec(
+ APIRecord *Parent, StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ FunctionSignature Signature, AccessControl Access,
+ bool IsFromSystemHeader) {
+
+ auto *Record = addTopLevelRecord(
+ USRBasedLookupTable, CXXMethodTemplateSpecializations, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration, SubHeading, Signature,
+ Access, IsFromSystemHeader);
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Parent->USR, Parent->Name, Parent->getKind(), Parent);
+
+ return Record;
+}
+
+ObjCCategoryRecord *APISet::addObjCCategory(
+ StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ SymbolReference Interface, bool IsFromSystemHeader,
+ bool IsFromExternalModule) {
+ // Create the category record.
+ auto *Record =
+ addTopLevelRecord(USRBasedLookupTable, ObjCCategories, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, Interface, IsFromSystemHeader);
+
+ Record->IsFromExternalModule = IsFromExternalModule;
+
+ auto It = ObjCInterfaces.find(Interface.USR);
+ if (It != ObjCInterfaces.end())
+ It->second->Categories.push_back(Record);
+
+ return Record;
+}
+
+ObjCInterfaceRecord *
+APISet::addObjCInterface(StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, LinkageInfo Linkage,
+ const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading,
+ SymbolReference SuperClass, bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, ObjCInterfaces, USR, Name, Loc,
+ std::move(Availability), Linkage, Comment,
+ Declaration, SubHeading, SuperClass,
+ IsFromSystemHeader);
+}
+
+ObjCMethodRecord *APISet::addObjCMethod(
+ ObjCContainerRecord *Container, StringRef Name, StringRef USR,
+ PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ FunctionSignature Signature, bool IsInstanceMethod,
+ bool IsFromSystemHeader) {
+ std::unique_ptr<ObjCMethodRecord> Record;
+ if (IsInstanceMethod)
+ Record = std::make_unique<ObjCInstanceMethodRecord>(
+ USR, Name, Loc, std::move(Availability), Comment, Declaration,
+ SubHeading, Signature, IsFromSystemHeader);
+ else
+ Record = std::make_unique<ObjCClassMethodRecord>(
+ USR, Name, Loc, std::move(Availability), Comment, Declaration,
+ SubHeading, Signature, IsFromSystemHeader);
+
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Container->USR, Container->Name, Container->getKind(), Container);
+ USRBasedLookupTable.insert({USR, Record.get()});
+ return Container->Methods.emplace_back(std::move(Record)).get();
+}
+
+ObjCPropertyRecord *APISet::addObjCProperty(
+ ObjCContainerRecord *Container, StringRef Name, StringRef USR,
+ PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ ObjCPropertyRecord::AttributeKind Attributes, StringRef GetterName,
+ StringRef SetterName, bool IsOptional, bool IsInstanceProperty,
+ bool IsFromSystemHeader) {
+ std::unique_ptr<ObjCPropertyRecord> Record;
+ if (IsInstanceProperty)
+ Record = std::make_unique<ObjCInstancePropertyRecord>(
+ USR, Name, Loc, std::move(Availability), Comment, Declaration,
+ SubHeading, Attributes, GetterName, SetterName, IsOptional,
+ IsFromSystemHeader);
+ else
+ Record = std::make_unique<ObjCClassPropertyRecord>(
+ USR, Name, Loc, std::move(Availability), Comment, Declaration,
+ SubHeading, Attributes, GetterName, SetterName, IsOptional,
+ IsFromSystemHeader);
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Container->USR, Container->Name, Container->getKind(), Container);
+ USRBasedLookupTable.insert({USR, Record.get()});
+ return Container->Properties.emplace_back(std::move(Record)).get();
+}
+
+ObjCInstanceVariableRecord *APISet::addObjCInstanceVariable(
+ ObjCContainerRecord *Container, StringRef Name, StringRef USR,
+ PresumedLoc Loc, AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration, DeclarationFragments SubHeading,
+ ObjCInstanceVariableRecord::AccessControl Access, bool IsFromSystemHeader) {
+ auto Record = std::make_unique<ObjCInstanceVariableRecord>(
+ USR, Name, Loc, std::move(Availability), Comment, Declaration, SubHeading,
+ Access, IsFromSystemHeader);
+ Record->ParentInformation = APIRecord::HierarchyInformation(
+ Container->USR, Container->Name, Container->getKind(), Container);
+ USRBasedLookupTable.insert({USR, Record.get()});
+ return Container->Ivars.emplace_back(std::move(Record)).get();
+}
+
+ObjCProtocolRecord *APISet::addObjCProtocol(StringRef Name, StringRef USR,
+ PresumedLoc Loc,
+ AvailabilityInfo Availability,
+ const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading,
+ bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, ObjCProtocols, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, IsFromSystemHeader);
+}
+
+MacroDefinitionRecord *
+APISet::addMacroDefinition(StringRef Name, StringRef USR, PresumedLoc Loc,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading,
+ bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, Macros, USR, Name, Loc,
+ Declaration, SubHeading, IsFromSystemHeader);
+}
+
+TypedefRecord *
+APISet::addTypedef(StringRef Name, StringRef USR, PresumedLoc Loc,
+ AvailabilityInfo Availability, const DocComment &Comment,
+ DeclarationFragments Declaration,
+ DeclarationFragments SubHeading,
+ SymbolReference UnderlyingType, bool IsFromSystemHeader) {
+ return addTopLevelRecord(USRBasedLookupTable, Typedefs, USR, Name, Loc,
+ std::move(Availability), Comment, Declaration,
+ SubHeading, UnderlyingType, IsFromSystemHeader);
}
APIRecord *APISet::findRecordForUSR(StringRef USR) const {
if (USR.empty())
return nullptr;
- auto FindIt = USRBasedLookupTable.find(USR);
- if (FindIt != USRBasedLookupTable.end())
- return FindIt->getSecond().get();
+ return USRBasedLookupTable.lookup(USR);
+}
+
+StringRef APISet::recordUSR(const Decl *D) {
+ SmallString<128> USR;
+ index::generateUSRForDecl(D, USR);
+ return copyString(USR);
+}
- return nullptr;
+StringRef APISet::recordUSRForMacro(StringRef Name, SourceLocation SL,
+ const SourceManager &SM) {
+ SmallString<128> USR;
+ index::generateUSRForMacro(Name, SL, SM, USR);
+ return copyString(USR);
}
StringRef APISet::copyString(StringRef String) {
@@ -81,22 +528,15 @@ StringRef APISet::copyString(StringRef String) {
return {};
// No need to allocate memory and copy if the string has already been stored.
- if (Allocator.identifyObject(String.data()))
+ if (StringAllocator.identifyObject(String.data()))
return String;
- void *Ptr = Allocator.Allocate(String.size(), 1);
+ void *Ptr = StringAllocator.Allocate(String.size(), 1);
memcpy(Ptr, String.data(), String.size());
return StringRef(reinterpret_cast<const char *>(Ptr), String.size());
}
-SymbolReference APISet::createSymbolReference(StringRef Name, StringRef USR,
- StringRef Source) {
- return SymbolReference(copyString(Name), copyString(USR), copyString(Source));
-}
-
APIRecord::~APIRecord() {}
-RecordRecord::~RecordRecord() {}
-RecordFieldRecord::~RecordFieldRecord() {}
ObjCContainerRecord::~ObjCContainerRecord() {}
ObjCMethodRecord::~ObjCMethodRecord() {}
ObjCPropertyRecord::~ObjCPropertyRecord() {}
@@ -106,10 +546,8 @@ void GlobalFunctionRecord::anchor() {}
void GlobalVariableRecord::anchor() {}
void EnumConstantRecord::anchor() {}
void EnumRecord::anchor() {}
-void StructFieldRecord::anchor() {}
-void StructRecord::anchor() {}
-void UnionFieldRecord::anchor() {}
-void UnionRecord::anchor() {}
+void RecordFieldRecord::anchor() {}
+void RecordRecord::anchor() {}
void CXXFieldRecord::anchor() {}
void CXXClassRecord::anchor() {}
void CXXConstructorRecord::anchor() {}
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
index 0a24312..22b98e0 100644
--- a/clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -57,44 +57,23 @@ void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
} // namespace
-DeclarationFragments &
-DeclarationFragments::appendUnduplicatedTextCharacter(char Character) {
+DeclarationFragments &DeclarationFragments::appendSpace() {
if (!Fragments.empty()) {
Fragment &Last = Fragments.back();
if (Last.Kind == FragmentKind::Text) {
// Merge the extra space into the last fragment if the last fragment is
// also text.
- if (Last.Spelling.back() != Character) { // avoid duplicates at end
- Last.Spelling.push_back(Character);
+ if (Last.Spelling.back() != ' ') { // avoid extra trailing spaces.
+ Last.Spelling.push_back(' ');
}
} else {
- append("", FragmentKind::Text);
- Fragments.back().Spelling.push_back(Character);
+ append(" ", FragmentKind::Text);
}
}
return *this;
}
-DeclarationFragments &DeclarationFragments::appendSpace() {
- return appendUnduplicatedTextCharacter(' ');
-}
-
-DeclarationFragments &DeclarationFragments::appendSemicolon() {
- return appendUnduplicatedTextCharacter(';');
-}
-
-DeclarationFragments &DeclarationFragments::removeTrailingSemicolon() {
- if (Fragments.empty())
- return *this;
-
- Fragment &Last = Fragments.back();
- if (Last.Kind == FragmentKind::Text && Last.Spelling.back() == ';')
- Last.Spelling.pop_back();
-
- return *this;
-}
-
StringRef DeclarationFragments::getFragmentKindString(
DeclarationFragments::FragmentKind Kind) {
switch (Kind) {
@@ -487,7 +466,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForNamespace(
if (!Decl->isAnonymousNamespace())
Fragments.appendSpace().append(
Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -529,7 +508,7 @@ DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
return Fragments
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -559,7 +538,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplate(const VarDecl *Var) {
Fragments.append(std::move(ArgumentFragment))
.appendSpace()
.append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
return Fragments;
}
@@ -719,7 +698,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Func->getExceptionSpecType()));
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForEnumConstant(
@@ -748,7 +727,7 @@ DeclarationFragmentsBuilder::getFragmentsForEnum(const EnumDecl *EnumDecl) {
getFragmentsForType(IntegerType, EnumDecl->getASTContext(), After))
.append(std::move(After));
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -764,7 +743,7 @@ DeclarationFragmentsBuilder::getFragmentsForField(const FieldDecl *Field) {
.appendSpace()
.append(Field->getName(), DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
@@ -782,7 +761,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForRecordDecl(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
@@ -797,7 +776,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXClass(
Fragments.appendSpace().append(
Record->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -827,7 +806,7 @@ DeclarationFragmentsBuilder::getFragmentsForSpecialCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
@@ -867,7 +846,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForCXXMethod(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -898,7 +877,7 @@ DeclarationFragmentsBuilder::getFragmentsForConversionFunction(
Fragments.appendSpace().append("const",
DeclarationFragments::FragmentKind::Keyword);
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -930,7 +909,7 @@ DeclarationFragmentsBuilder::getFragmentsForOverloadedOperator(
Fragments.append(DeclarationFragments::getExceptionSpecificationString(
Method->getExceptionSpecType()));
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
// Get fragments for template parameters, e.g. T in tempalte<typename T> ...
@@ -1018,7 +997,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
.appendSpace()
.append(Concept->getName().str(),
DeclarationFragments::FragmentKind::Identifier)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -1059,7 +1038,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -1081,7 +1060,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateArgsAsWritten()->arguments()))
.append(">", DeclarationFragments::FragmentKind::Text)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -1100,7 +1079,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(),
Decl->getASTContext(), std::nullopt))
.append(">", DeclarationFragments::FragmentKind::Text)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -1122,7 +1101,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
Decl->getTemplateArgs().asArray(), Decl->getASTContext(),
Decl->getTemplateArgsAsWritten()->arguments()))
.append(">", DeclarationFragments::FragmentKind::Text)
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments
@@ -1193,7 +1172,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCCategory(
Fragments.append("@interface", DeclarationFragments::FragmentKind::Keyword)
.appendSpace()
- .append(Interface->getName(),
+ .append(Category->getClassInterface()->getName(),
DeclarationFragments::FragmentKind::TypeIdentifier, InterfaceUSR,
Interface)
.append(" (", DeclarationFragments::FragmentKind::Text)
@@ -1267,7 +1246,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCMethod(
Fragments.append(getFragmentsForParam(Param));
}
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
@@ -1368,7 +1347,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
.append(Property->getName(),
DeclarationFragments::FragmentKind::Identifier)
.append(std::move(After))
- .appendSemicolon();
+ .append(";", DeclarationFragments::FragmentKind::Text);
}
DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
@@ -1412,7 +1391,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForTypedef(
.appendSpace()
.append(Decl->getName(), DeclarationFragments::FragmentKind::Identifier);
- return Fragments.appendSemicolon();
+ return Fragments.append(";", DeclarationFragments::FragmentKind::Text);
}
// Instantiate template for FunctionDecl.
diff --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
index d633585..275f49b 100644
--- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
+++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
@@ -30,7 +30,6 @@
#include "clang/Frontend/CompilerInstance.h"
#include "clang/Frontend/FrontendOptions.h"
#include "clang/Frontend/MultiplexConsumer.h"
-#include "clang/Index/USRGeneration.h"
#include "clang/InstallAPI/HeaderFile.h"
#include "clang/Lex/MacroInfo.h"
#include "clang/Lex/PPCallbacks.h"
@@ -40,7 +39,6 @@
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Error.h"
#include "llvm/Support/FileSystem.h"
@@ -329,12 +327,11 @@ public:
StringRef Name = PM.MacroNameToken.getIdentifierInfo()->getName();
PresumedLoc Loc = SM.getPresumedLoc(PM.MacroNameToken.getLocation());
- SmallString<128> USR;
- index::generateUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM,
- USR);
+ StringRef USR =
+ API.recordUSRForMacro(Name, PM.MacroNameToken.getLocation(), SM);
- API.createRecord<extractapi::MacroDefinitionRecord>(
- USR, Name, SymbolReference(), Loc,
+ API.addMacroDefinition(
+ Name, USR, Loc,
DeclarationFragmentsBuilder::getFragmentsForMacro(Name, PM.MD),
DeclarationFragmentsBuilder::getSubHeadingForMacro(Name),
SM.isInSystemHeader(PM.MacroNameToken.getLocation()));
@@ -375,57 +372,40 @@ private:
LocationFileChecker &LCF;
};
-std::unique_ptr<llvm::raw_pwrite_stream>
-createAdditionalSymbolGraphFile(CompilerInstance &CI, Twine BaseName) {
- auto OutputDirectory = CI.getFrontendOpts().SymbolGraphOutputDir;
-
- SmallString<256> FileName;
- llvm::sys::path::append(FileName, OutputDirectory,
- BaseName + ".symbols.json");
- return CI.createOutputFile(
- FileName, /*Binary*/ false, /*RemoveFileOnSignal*/ false,
- /*UseTemporary*/ true, /*CreateMissingDirectories*/ true);
-}
-
} // namespace
-void ExtractAPIActionBase::ImplEndSourceFileAction(CompilerInstance &CI) {
- SymbolGraphSerializerOption SerializationOptions;
- SerializationOptions.Compact = !CI.getFrontendOpts().EmitPrettySymbolGraphs;
- SerializationOptions.EmitSymbolLabelsForTesting =
- CI.getFrontendOpts().EmitSymbolGraphSymbolLabelsForTesting;
-
- if (CI.getFrontendOpts().EmitExtensionSymbolGraphs) {
- auto ConstructOutputFile = [&CI](Twine BaseName) {
- return createAdditionalSymbolGraphFile(CI, BaseName);
- };
-
- SymbolGraphSerializer::serializeWithExtensionGraphs(
- *OS, *API, IgnoresList, ConstructOutputFile, SerializationOptions);
- } else {
- SymbolGraphSerializer::serializeMainSymbolGraph(*OS, *API, IgnoresList,
- SerializationOptions);
- }
+void ExtractAPIActionBase::ImplEndSourceFileAction() {
+ if (!OS)
+ return;
- // Flush the stream and close the main output stream.
+ // Setup a SymbolGraphSerializer to write out collected API information in
+ // the Symbol Graph format.
+ // FIXME: Make the kind of APISerializer configurable.
+ SymbolGraphSerializer SGSerializer(*API, IgnoresList);
+ SGSerializer.serialize(*OS);
OS.reset();
}
+std::unique_ptr<raw_pwrite_stream>
+ExtractAPIAction::CreateOutputFile(CompilerInstance &CI, StringRef InFile) {
+ std::unique_ptr<raw_pwrite_stream> OS;
+ OS = CI.createDefaultOutputFile(/*Binary=*/false, InFile,
+ /*Extension=*/"json",
+ /*RemoveFileOnSignal=*/false);
+ if (!OS)
+ return nullptr;
+ return OS;
+}
+
std::unique_ptr<ASTConsumer>
ExtractAPIAction::CreateASTConsumer(CompilerInstance &CI, StringRef InFile) {
- auto ProductName = CI.getFrontendOpts().ProductName;
-
- if (CI.getFrontendOpts().SymbolGraphOutputDir.empty())
- OS = CI.createDefaultOutputFile(/*Binary*/ false, InFile,
- /*Extension*/ "symbols.json",
- /*RemoveFileOnSignal*/ false,
- /*CreateMissingDirectories*/ true);
- else
- OS = createAdditionalSymbolGraphFile(CI, ProductName);
+ OS = CreateOutputFile(CI, InFile);
if (!OS)
return nullptr;
+ auto ProductName = CI.getFrontendOpts().ProductName;
+
// Now that we have enough information about the language options and the
// target triple, let's create the APISet before anyone uses it.
API = std::make_unique<APISet>(
@@ -515,9 +495,7 @@ bool ExtractAPIAction::PrepareToExecuteAction(CompilerInstance &CI) {
return true;
}
-void ExtractAPIAction::EndSourceFileAction() {
- ImplEndSourceFileAction(getCompilerInstance());
-}
+void ExtractAPIAction::EndSourceFileAction() { ImplEndSourceFileAction(); }
std::unique_ptr<ASTConsumer>
WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,
@@ -528,9 +506,11 @@ WrappingExtractAPIAction::CreateASTConsumer(CompilerInstance &CI,
CreatedASTConsumer = true;
- ProductName = CI.getFrontendOpts().ProductName;
- auto InputFilename = llvm::sys::path::filename(InFile);
- OS = createAdditionalSymbolGraphFile(CI, InputFilename);
+ OS = CreateOutputFile(CI, InFile);
+ if (!OS)
+ return nullptr;
+
+ auto ProductName = CI.getFrontendOpts().ProductName;
// Now that we have enough information about the language options and the
// target triple, let's create the APISet before anyone uses it.
@@ -572,6 +552,32 @@ void WrappingExtractAPIAction::EndSourceFileAction() {
WrapperFrontendAction::EndSourceFileAction();
if (CreatedASTConsumer) {
- ImplEndSourceFileAction(getCompilerInstance());
+ ImplEndSourceFileAction();
}
}
+
+std::unique_ptr<raw_pwrite_stream>
+WrappingExtractAPIAction::CreateOutputFile(CompilerInstance &CI,
+ StringRef InFile) {
+ std::unique_ptr<raw_pwrite_stream> OS;
+ std::string OutputDir = CI.getFrontendOpts().SymbolGraphOutputDir;
+
+ // The symbol graphs need to be generated as a side effect of regular
+ // compilation so the output should be dumped in the directory provided with
+ // the command line option.
+ llvm::SmallString<128> OutFilePath(OutputDir);
+ auto Seperator = llvm::sys::path::get_separator();
+ auto Infilename = llvm::sys::path::filename(InFile);
+ OutFilePath.append({Seperator, Infilename});
+ llvm::sys::path::replace_extension(OutFilePath, "json");
+ // StringRef outputFilePathref = *OutFilePath;
+
+ // don't use the default output file
+ OS = CI.createOutputFile(/*OutputPath=*/OutFilePath, /*Binary=*/false,
+ /*RemoveFileOnSignal=*/true,
+ /*UseTemporary=*/true,
+ /*CreateMissingDirectories=*/true);
+ if (!OS)
+ return nullptr;
+ return OS;
+}
diff --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
index 57f966c..545860a 100644
--- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -14,17 +14,13 @@
#include "clang/ExtractAPI/Serialization/SymbolGraphSerializer.h"
#include "clang/Basic/SourceLocation.h"
#include "clang/Basic/Version.h"
-#include "clang/ExtractAPI/API.h"
#include "clang/ExtractAPI/DeclarationFragments.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/STLFunctionalExtras.h"
-#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/Casting.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/VersionTuple.h"
-#include "llvm/Support/raw_ostream.h"
-#include <iterator>
#include <optional>
#include <type_traits>
@@ -37,27 +33,26 @@ namespace {
/// Helper function to inject a JSON object \p Obj into another object \p Paren
/// at position \p Key.
-void serializeObject(Object &Paren, StringRef Key,
- std::optional<Object> &&Obj) {
+void serializeObject(Object &Paren, StringRef Key, std::optional<Object> Obj) {
if (Obj)
Paren[Key] = std::move(*Obj);
}
+/// Helper function to inject a StringRef \p String into an object \p Paren at
+/// position \p Key
+void serializeString(Object &Paren, StringRef Key,
+ std::optional<std::string> String) {
+ if (String)
+ Paren[Key] = std::move(*String);
+}
+
/// Helper function to inject a JSON array \p Array into object \p Paren at
/// position \p Key.
-void serializeArray(Object &Paren, StringRef Key,
- std::optional<Array> &&Array) {
+void serializeArray(Object &Paren, StringRef Key, std::optional<Array> Array) {
if (Array)
Paren[Key] = std::move(*Array);
}
-/// Helper function to inject a JSON array composed of the values in \p C into
-/// object \p Paren at position \p Key.
-template <typename ContainerTy>
-void serializeArray(Object &Paren, StringRef Key, ContainerTy &&C) {
- Paren[Key] = Array(C);
-}
-
/// Serialize a \c VersionTuple \p V with the Symbol Graph semantic version
/// format.
///
@@ -253,7 +248,6 @@ std::optional<Object> serializeDocComment(const DocComment &Comment) {
return std::nullopt;
Object DocComment;
-
Array LinesArray;
for (const auto &CommentLine : Comment) {
Object Line;
@@ -262,8 +256,7 @@ std::optional<Object> serializeDocComment(const DocComment &Comment) {
serializeSourceRange(CommentLine.Begin, CommentLine.End));
LinesArray.emplace_back(std::move(Line));
}
-
- serializeArray(DocComment, "lines", std::move(LinesArray));
+ serializeArray(DocComment, "lines", LinesArray);
return DocComment;
}
@@ -329,14 +322,19 @@ serializeDeclarationFragments(const DeclarationFragments &DF) {
/// - \c subHeading : An array of declaration fragments that provides tags,
/// and potentially more tokens (for example the \c +/- symbol for
/// Objective-C methods). Can be used as sub-headings for documentation.
-Object serializeNames(const APIRecord *Record) {
+Object serializeNames(const APIRecord &Record) {
Object Names;
- Names["title"] = Record->Name;
+ if (auto *CategoryRecord =
+ dyn_cast_or_null<const ObjCCategoryRecord>(&Record))
+ Names["title"] =
+ (CategoryRecord->Interface.Name + " (" + Record.Name + ")").str();
+ else
+ Names["title"] = Record.Name;
serializeArray(Names, "subHeading",
- serializeDeclarationFragments(Record->SubHeading));
+ serializeDeclarationFragments(Record.SubHeading));
DeclarationFragments NavigatorFragments;
- NavigatorFragments.append(Record->Name,
+ NavigatorFragments.append(Record.Name,
DeclarationFragments::FragmentKind::Identifier,
/*PreciseIdentifier*/ "");
serializeArray(Names, "navigator",
@@ -353,8 +351,7 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
Object Kind;
switch (RK) {
case APIRecord::RK_Unknown:
- Kind["identifier"] = AddLangPrefix("unknown");
- Kind["displayName"] = "Unknown";
+ llvm_unreachable("Records should have an explicit kind");
break;
case APIRecord::RK_Namespace:
Kind["identifier"] = AddLangPrefix("namespace");
@@ -487,6 +484,10 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
Kind["identifier"] = AddLangPrefix("class.extension");
Kind["displayName"] = "Class Extension";
break;
+ case APIRecord::RK_ObjCCategoryModule:
+ Kind["identifier"] = AddLangPrefix("module.extension");
+ Kind["displayName"] = "Module Extension";
+ break;
case APIRecord::RK_ObjCProtocol:
Kind["identifier"] = AddLangPrefix("protocol");
Kind["displayName"] = "Protocol";
@@ -499,8 +500,6 @@ Object serializeSymbolKind(APIRecord::RecordKind RK, Language Lang) {
Kind["identifier"] = AddLangPrefix("typealias");
Kind["displayName"] = "Type Alias";
break;
- default:
- llvm_unreachable("API Record with uninstantiable kind");
}
return Kind;
@@ -515,18 +514,12 @@ Object serializeSymbolKind(const APIRecord &Record, Language Lang) {
return serializeSymbolKind(Record.getKind(), Lang);
}
-/// Serialize the function signature field, as specified by the
-/// Symbol Graph format.
-///
-/// The Symbol Graph function signature property contains two arrays.
-/// - The \c returns array is the declaration fragments of the return type;
-/// - The \c parameters array contains names and declaration fragments of the
-/// parameters.
template <typename RecordTy>
-void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
+std::optional<Object>
+serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::true_type) {
const auto &FS = Record.Signature;
if (FS.empty())
- return;
+ return std::nullopt;
Object Signature;
serializeArray(Signature, "returns",
@@ -544,14 +537,63 @@ void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
if (!Parameters.empty())
Signature["parameters"] = std::move(Parameters);
- serializeObject(Paren, "functionSignature", std::move(Signature));
+ return Signature;
}
template <typename RecordTy>
-void serializeTemplateMixin(Object &Paren, const RecordTy &Record) {
+std::optional<Object>
+serializeFunctionSignatureMixinImpl(const RecordTy &Record, std::false_type) {
+ return std::nullopt;
+}
+
+/// Serialize the function signature field, as specified by the
+/// Symbol Graph format.
+///
+/// The Symbol Graph function signature property contains two arrays.
+/// - The \c returns array is the declaration fragments of the return type;
+/// - The \c parameters array contains names and declaration fragments of the
+/// parameters.
+///
+/// \returns \c std::nullopt if \p FS is empty, or an \c Object containing the
+/// formatted function signature.
+template <typename RecordTy>
+void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
+ serializeObject(Paren, "functionSignature",
+ serializeFunctionSignatureMixinImpl(
+ Record, has_function_signature<RecordTy>()));
+}
+
+template <typename RecordTy>
+std::optional<std::string> serializeAccessMixinImpl(const RecordTy &Record,
+ std::true_type) {
+ const auto &AccessControl = Record.Access;
+ std::string Access;
+ if (AccessControl.empty())
+ return std::nullopt;
+ Access = AccessControl.getAccess();
+ return Access;
+}
+
+template <typename RecordTy>
+std::optional<std::string> serializeAccessMixinImpl(const RecordTy &Record,
+ std::false_type) {
+ return std::nullopt;
+}
+
+template <typename RecordTy>
+void serializeAccessMixin(Object &Paren, const RecordTy &Record) {
+ auto accessLevel = serializeAccessMixinImpl(Record, has_access<RecordTy>());
+ if (!accessLevel.has_value())
+ accessLevel = "public";
+ serializeString(Paren, "accessLevel", accessLevel);
+}
+
+template <typename RecordTy>
+std::optional<Object> serializeTemplateMixinImpl(const RecordTy &Record,
+ std::true_type) {
const auto &Template = Record.Templ;
if (Template.empty())
- return;
+ return std::nullopt;
Object Generics;
Array GenericParameters;
@@ -577,66 +619,97 @@ void serializeTemplateMixin(Object &Paren, const RecordTy &Record) {
if (!GenericConstraints.empty())
Generics["constraints"] = std::move(GenericConstraints);
- serializeObject(Paren, "swiftGenerics", Generics);
+ return Generics;
}
-Array generateParentContexts(const SmallVectorImpl<SymbolReference> &Parents,
- Language Lang) {
- Array ParentContexts;
-
- for (const auto &Parent : Parents) {
- Object Elem;
- Elem["usr"] = Parent.USR;
- Elem["name"] = Parent.Name;
- if (Parent.Record)
- Elem["kind"] =
- serializeSymbolKind(Parent.Record->getKind(), Lang)["identifier"];
- else
- Elem["kind"] =
- serializeSymbolKind(APIRecord::RK_Unknown, Lang)["identifier"];
- ParentContexts.emplace_back(std::move(Elem));
- }
+template <typename RecordTy>
+std::optional<Object> serializeTemplateMixinImpl(const RecordTy &Record,
+ std::false_type) {
+ return std::nullopt;
+}
- return ParentContexts;
+template <typename RecordTy>
+void serializeTemplateMixin(Object &Paren, const RecordTy &Record) {
+ serializeObject(Paren, "swiftGenerics",
+ serializeTemplateMixinImpl(Record, has_template<RecordTy>()));
}
-/// Walk the records parent information in reverse to generate a hierarchy
-/// suitable for serialization.
-SmallVector<SymbolReference, 8>
-generateHierarchyFromRecord(const APIRecord *Record) {
- SmallVector<SymbolReference, 8> ReverseHierarchy;
- for (const auto *Current = Record; Current != nullptr;
- Current = Current->Parent.Record)
- ReverseHierarchy.emplace_back(Current);
-
- return SmallVector<SymbolReference, 8>(
- std::make_move_iterator(ReverseHierarchy.rbegin()),
- std::make_move_iterator(ReverseHierarchy.rend()));
-}
-
-SymbolReference getHierarchyReference(const APIRecord *Record,
- const APISet &API) {
- // If the parent is a category extended from internal module then we need to
- // pretend this belongs to the associated interface.
- if (auto *CategoryRecord = dyn_cast_or_null<ObjCCategoryRecord>(Record)) {
- return CategoryRecord->Interface;
- // FIXME: TODO generate path components correctly for categories extending
- // an external module.
+struct PathComponent {
+ StringRef USR;
+ StringRef Name;
+ APIRecord::RecordKind Kind;
+
+ PathComponent(StringRef USR, StringRef Name, APIRecord::RecordKind Kind)
+ : USR(USR), Name(Name), Kind(Kind) {}
+};
+
+template <typename RecordTy>
+bool generatePathComponents(
+ const RecordTy &Record, const APISet &API,
+ function_ref<void(const PathComponent &)> ComponentTransformer) {
+ SmallVector<PathComponent, 4> ReverseComponenents;
+ ReverseComponenents.emplace_back(Record.USR, Record.Name, Record.getKind());
+ const auto *CurrentParent = &Record.ParentInformation;
+ bool FailedToFindParent = false;
+ while (CurrentParent && !CurrentParent->empty()) {
+ PathComponent CurrentParentComponent(CurrentParent->ParentUSR,
+ CurrentParent->ParentName,
+ CurrentParent->ParentKind);
+
+ auto *ParentRecord = CurrentParent->ParentRecord;
+ // Slow path if we don't have a direct reference to the ParentRecord
+ if (!ParentRecord)
+ ParentRecord = API.findRecordForUSR(CurrentParent->ParentUSR);
+
+ // If the parent is a category extended from internal module then we need to
+ // pretend this belongs to the associated interface.
+ if (auto *CategoryRecord =
+ dyn_cast_or_null<ObjCCategoryRecord>(ParentRecord)) {
+ if (!CategoryRecord->IsFromExternalModule) {
+ ParentRecord = API.findRecordForUSR(CategoryRecord->Interface.USR);
+ CurrentParentComponent = PathComponent(CategoryRecord->Interface.USR,
+ CategoryRecord->Interface.Name,
+ APIRecord::RK_ObjCInterface);
+ }
+ }
+
+ // The parent record doesn't exist which means the symbol shouldn't be
+ // treated as part of the current product.
+ if (!ParentRecord) {
+ FailedToFindParent = true;
+ break;
+ }
+
+ ReverseComponenents.push_back(std::move(CurrentParentComponent));
+ CurrentParent = &ParentRecord->ParentInformation;
}
- return SymbolReference(Record);
-}
+ for (const auto &PC : reverse(ReverseComponenents))
+ ComponentTransformer(PC);
-} // namespace
+ return FailedToFindParent;
+}
-Object *ExtendedModule::addSymbol(Object &&Symbol) {
- Symbols.emplace_back(std::move(Symbol));
- return Symbols.back().getAsObject();
+Object serializeParentContext(const PathComponent &PC, Language Lang) {
+ Object ParentContextElem;
+ ParentContextElem["usr"] = PC.USR;
+ ParentContextElem["name"] = PC.Name;
+ ParentContextElem["kind"] = serializeSymbolKind(PC.Kind, Lang)["identifier"];
+ return ParentContextElem;
}
-void ExtendedModule::addRelationship(Object &&Relationship) {
- Relationships.emplace_back(std::move(Relationship));
+template <typename RecordTy>
+Array generateParentContexts(const RecordTy &Record, const APISet &API,
+ Language Lang) {
+ Array ParentContexts;
+ generatePathComponents(
+ Record, API, [Lang, &ParentContexts](const PathComponent &PC) {
+ ParentContexts.push_back(serializeParentContext(PC, Lang));
+ });
+
+ return ParentContexts;
}
+} // namespace
/// Defines the format version emitted by SymbolGraphSerializer.
const VersionTuple SymbolGraphSerializer::FormatVersion{0, 5, 3};
@@ -649,44 +722,84 @@ Object SymbolGraphSerializer::serializeMetadata() const {
return Metadata;
}
-Object
-SymbolGraphSerializer::serializeModuleObject(StringRef ModuleName) const {
+Object SymbolGraphSerializer::serializeModule() const {
Object Module;
- Module["name"] = ModuleName;
+ // The user is expected to always pass `--product-name=` on the command line
+ // to populate this field.
+ Module["name"] = API.ProductName;
serializeObject(Module, "platform", serializePlatform(API.getTarget()));
return Module;
}
-bool SymbolGraphSerializer::shouldSkip(const APIRecord *Record) const {
- if (!Record)
+bool SymbolGraphSerializer::shouldSkip(const APIRecord &Record) const {
+ // Skip explicitly ignored symbols.
+ if (IgnoresList.shouldIgnore(Record.Name))
return true;
// Skip unconditionally unavailable symbols
- if (Record->Availability.isUnconditionallyUnavailable())
+ if (Record.Availability.isUnconditionallyUnavailable())
return true;
// Filter out symbols prefixed with an underscored as they are understood to
// be symbols clients should not use.
- if (Record->Name.starts_with("_"))
- return true;
-
- // Skip explicitly ignored symbols.
- if (IgnoresList.shouldIgnore(Record->Name))
+ if (Record.Name.starts_with("_"))
return true;
return false;
}
-ExtendedModule &SymbolGraphSerializer::getModuleForCurrentSymbol() {
- if (!ForceEmitToMainModule && ModuleForCurrentSymbol)
- return *ModuleForCurrentSymbol;
+template <typename RecordTy>
+std::optional<Object>
+SymbolGraphSerializer::serializeAPIRecord(const RecordTy &Record) const {
+ if (shouldSkip(Record))
+ return std::nullopt;
+
+ Object Obj;
+ serializeObject(Obj, "identifier",
+ serializeIdentifier(Record, API.getLanguage()));
+ serializeObject(Obj, "kind", serializeSymbolKind(Record, API.getLanguage()));
+ serializeObject(Obj, "names", serializeNames(Record));
+ serializeObject(
+ Obj, "location",
+ serializeSourceLocation(Record.Location, /*IncludeFileURI=*/true));
+ serializeArray(Obj, "availability",
+ serializeAvailability(Record.Availability));
+ serializeObject(Obj, "docComment", serializeDocComment(Record.Comment));
+ serializeArray(Obj, "declarationFragments",
+ serializeDeclarationFragments(Record.Declaration));
+ SmallVector<StringRef, 4> PathComponentsNames;
+ // If this returns true it indicates that we couldn't find a symbol in the
+ // hierarchy.
+ if (generatePathComponents(Record, API,
+ [&PathComponentsNames](const PathComponent &PC) {
+ PathComponentsNames.push_back(PC.Name);
+ }))
+ return {};
+
+ serializeArray(Obj, "pathComponents", Array(PathComponentsNames));
- return MainModule;
+ serializeFunctionSignatureMixin(Obj, Record);
+ serializeAccessMixin(Obj, Record);
+ serializeTemplateMixin(Obj, Record);
+
+ return Obj;
}
-Array SymbolGraphSerializer::serializePathComponents(
- const APIRecord *Record) const {
- return Array(map_range(Hierarchy, [](auto Elt) { return Elt.Name; }));
+template <typename MemberTy>
+void SymbolGraphSerializer::serializeMembers(
+ const APIRecord &Record,
+ const SmallVector<std::unique_ptr<MemberTy>> &Members) {
+ // Members should not be serialized if we aren't recursing.
+ if (!ShouldRecurse)
+ return;
+ for (const auto &Member : Members) {
+ auto MemberRecord = serializeAPIRecord(*Member);
+ if (!MemberRecord)
+ continue;
+
+ Symbols.emplace_back(std::move(*MemberRecord));
+ serializeRelationship(RelationshipKind::MemberOf, *Member, Record);
+ }
}
StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
@@ -703,33 +816,6 @@ StringRef SymbolGraphSerializer::getRelationshipString(RelationshipKind Kind) {
llvm_unreachable("Unhandled relationship kind");
}
-void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
- const SymbolReference &Source,
- const SymbolReference &Target,
- ExtendedModule &Into) {
- Object Relationship;
- SmallString<64> TestRelLabel;
- if (EmitSymbolLabelsForTesting) {
- llvm::raw_svector_ostream OS(TestRelLabel);
- OS << SymbolGraphSerializer::getRelationshipString(Kind) << " $ "
- << Source.USR << " $ ";
- if (Target.USR.empty())
- OS << Target.Name;
- else
- OS << Target.USR;
- Relationship["!testRelLabel"] = TestRelLabel;
- }
- Relationship["source"] = Source.USR;
- Relationship["target"] = Target.USR;
- Relationship["targetFallback"] = Target.Name;
- Relationship["kind"] = SymbolGraphSerializer::getRelationshipString(Kind);
-
- if (ForceEmitToMainModule)
- MainModule.addRelationship(std::move(Relationship));
- else
- Into.addRelationship(std::move(Relationship));
-}
-
StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
switch (Kind) {
case ConstraintKind::Conformance:
@@ -740,324 +826,430 @@ StringRef SymbolGraphSerializer::getConstraintString(ConstraintKind Kind) {
llvm_unreachable("Unhandled constraint kind");
}
-void SymbolGraphSerializer::serializeAPIRecord(const APIRecord *Record) {
- Object Obj;
-
- // If we need symbol labels for testing emit the USR as the value and the key
- // starts with '!'' to ensure it ends up at the top of the object.
- if (EmitSymbolLabelsForTesting)
- Obj["!testLabel"] = Record->USR;
+void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
+ SymbolReference Source,
+ SymbolReference Target) {
+ Object Relationship;
+ Relationship["source"] = Source.USR;
+ Relationship["target"] = Target.USR;
+ Relationship["targetFallback"] = Target.Name;
+ Relationship["kind"] = getRelationshipString(Kind);
- serializeObject(Obj, "identifier",
- serializeIdentifier(*Record, API.getLanguage()));
- serializeObject(Obj, "kind", serializeSymbolKind(*Record, API.getLanguage()));
- serializeObject(Obj, "names", serializeNames(Record));
- serializeObject(
- Obj, "location",
- serializeSourceLocation(Record->Location, /*IncludeFileURI=*/true));
- serializeArray(Obj, "availability",
- serializeAvailability(Record->Availability));
- serializeObject(Obj, "docComment", serializeDocComment(Record->Comment));
- serializeArray(Obj, "declarationFragments",
- serializeDeclarationFragments(Record->Declaration));
+ Relationships.emplace_back(std::move(Relationship));
+}
- Obj["pathComponents"] = serializePathComponents(Record);
- Obj["accessLevel"] = Record->Access.getAccess();
+void SymbolGraphSerializer::visitNamespaceRecord(
+ const NamespaceRecord &Record) {
+ auto Namespace = serializeAPIRecord(Record);
+ if (!Namespace)
+ return;
+ Symbols.emplace_back(std::move(*Namespace));
+ if (!Record.ParentInformation.empty())
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
+}
- ExtendedModule &Module = getModuleForCurrentSymbol();
- // If the hierarchy has at least one parent and child.
- if (Hierarchy.size() >= 2)
- serializeRelationship(MemberOf, Hierarchy.back(),
- Hierarchy[Hierarchy.size() - 2], Module);
+void SymbolGraphSerializer::visitGlobalFunctionRecord(
+ const GlobalFunctionRecord &Record) {
+ auto Obj = serializeAPIRecord(Record);
+ if (!Obj)
+ return;
- CurrentSymbol = Module.addSymbol(std::move(Obj));
+ Symbols.emplace_back(std::move(*Obj));
}
-bool SymbolGraphSerializer::traverseAPIRecord(const APIRecord *Record) {
- if (!Record)
- return true;
- if (shouldSkip(Record))
- return true;
- Hierarchy.push_back(getHierarchyReference(Record, API));
- // Defer traversal mechanics to APISetVisitor base implementation
- auto RetVal = Base::traverseAPIRecord(Record);
- Hierarchy.pop_back();
- return RetVal;
+void SymbolGraphSerializer::visitGlobalVariableRecord(
+ const GlobalVariableRecord &Record) {
+ auto Obj = serializeAPIRecord(Record);
+ if (!Obj)
+ return;
+
+ Symbols.emplace_back(std::move(*Obj));
}
-bool SymbolGraphSerializer::visitAPIRecord(const APIRecord *Record) {
- serializeAPIRecord(Record);
- return true;
+void SymbolGraphSerializer::visitEnumRecord(const EnumRecord &Record) {
+ auto Enum = serializeAPIRecord(Record);
+ if (!Enum)
+ return;
+
+ Symbols.emplace_back(std::move(*Enum));
+ serializeMembers(Record, Record.Constants);
}
-bool SymbolGraphSerializer::visitGlobalFunctionRecord(
- const GlobalFunctionRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitRecordRecord(const RecordRecord &Record) {
+ auto SerializedRecord = serializeAPIRecord(Record);
+ if (!SerializedRecord)
+ return;
- serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
- return true;
+ Symbols.emplace_back(std::move(*SerializedRecord));
+ serializeMembers(Record, Record.Fields);
}
-bool SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitStaticFieldRecord(
+ const StaticFieldRecord &Record) {
+ auto StaticField = serializeAPIRecord(Record);
+ if (!StaticField)
+ return;
+ Symbols.emplace_back(std::move(*StaticField));
+ serializeRelationship(RelationshipKind::MemberOf, Record, Record.Context);
+}
- for (const auto &Base : Record->Bases)
- serializeRelationship(RelationshipKind::InheritsFrom, Record, Base,
- getModuleForCurrentSymbol());
- return true;
+void SymbolGraphSerializer::visitCXXClassRecord(const CXXClassRecord &Record) {
+ auto Class = serializeAPIRecord(Record);
+ if (!Class)
+ return;
+
+ Symbols.emplace_back(std::move(*Class));
+ for (const auto &Base : Record.Bases)
+ serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
+ if (!Record.ParentInformation.empty())
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
}
-bool SymbolGraphSerializer::visitClassTemplateRecord(
- const ClassTemplateRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitClassTemplateRecord(
+ const ClassTemplateRecord &Record) {
+ auto Class = serializeAPIRecord(Record);
+ if (!Class)
+ return;
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+ Symbols.emplace_back(std::move(*Class));
+ for (const auto &Base : Record.Bases)
+ serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
+ if (!Record.ParentInformation.empty())
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
}
-bool SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord(
- const ClassTemplatePartialSpecializationRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitClassTemplateSpecializationRecord(
+ const ClassTemplateSpecializationRecord &Record) {
+ auto Class = serializeAPIRecord(Record);
+ if (!Class)
+ return;
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+ Symbols.emplace_back(std::move(*Class));
+
+ for (const auto &Base : Record.Bases)
+ serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
+ if (!Record.ParentInformation.empty())
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
}
-bool SymbolGraphSerializer::visitCXXMethodRecord(
- const CXXMethodRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitClassTemplatePartialSpecializationRecord(
+ const ClassTemplatePartialSpecializationRecord &Record) {
+ auto Class = serializeAPIRecord(Record);
+ if (!Class)
+ return;
+
+ Symbols.emplace_back(std::move(*Class));
- serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
- return true;
+ for (const auto &Base : Record.Bases)
+ serializeRelationship(RelationshipKind::InheritsFrom, Record, Base);
+ if (!Record.ParentInformation.empty())
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
}
-bool SymbolGraphSerializer::visitCXXMethodTemplateRecord(
- const CXXMethodTemplateRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitCXXInstanceMethodRecord(
+ const CXXInstanceMethodRecord &Record) {
+ auto InstanceMethod = serializeAPIRecord(Record);
+ if (!InstanceMethod)
+ return;
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+ Symbols.emplace_back(std::move(*InstanceMethod));
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
}
-bool SymbolGraphSerializer::visitCXXFieldTemplateRecord(
- const CXXFieldTemplateRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitCXXStaticMethodRecord(
+ const CXXStaticMethodRecord &Record) {
+ auto StaticMethod = serializeAPIRecord(Record);
+ if (!StaticMethod)
+ return;
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+ Symbols.emplace_back(std::move(*StaticMethod));
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
}
-bool SymbolGraphSerializer::visitConceptRecord(const ConceptRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitMethodTemplateRecord(
+ const CXXMethodTemplateRecord &Record) {
+ if (!ShouldRecurse)
+ // Ignore child symbols
+ return;
+ auto MethodTemplate = serializeAPIRecord(Record);
+ if (!MethodTemplate)
+ return;
+ Symbols.emplace_back(std::move(*MethodTemplate));
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
+}
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+void SymbolGraphSerializer::visitMethodTemplateSpecializationRecord(
+ const CXXMethodTemplateSpecializationRecord &Record) {
+ if (!ShouldRecurse)
+ // Ignore child symbols
+ return;
+ auto MethodTemplateSpecialization = serializeAPIRecord(Record);
+ if (!MethodTemplateSpecialization)
+ return;
+ Symbols.emplace_back(std::move(*MethodTemplateSpecialization));
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
}
-bool SymbolGraphSerializer::visitGlobalVariableTemplateRecord(
- const GlobalVariableTemplateRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitCXXFieldRecord(const CXXFieldRecord &Record) {
+ if (!ShouldRecurse)
+ return;
+ auto CXXField = serializeAPIRecord(Record);
+ if (!CXXField)
+ return;
+ Symbols.emplace_back(std::move(*CXXField));
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
+}
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+void SymbolGraphSerializer::visitCXXFieldTemplateRecord(
+ const CXXFieldTemplateRecord &Record) {
+ if (!ShouldRecurse)
+ // Ignore child symbols
+ return;
+ auto CXXFieldTemplate = serializeAPIRecord(Record);
+ if (!CXXFieldTemplate)
+ return;
+ Symbols.emplace_back(std::move(*CXXFieldTemplate));
+ serializeRelationship(RelationshipKind::MemberOf, Record,
+ Record.ParentInformation.ParentRecord);
}
-bool SymbolGraphSerializer::
- visitGlobalVariableTemplatePartialSpecializationRecord(
- const GlobalVariableTemplatePartialSpecializationRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitConceptRecord(const ConceptRecord &Record) {
+ auto Concept = serializeAPIRecord(Record);
+ if (!Concept)
+ return;
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+ Symbols.emplace_back(std::move(*Concept));
}
-bool SymbolGraphSerializer::visitGlobalFunctionTemplateRecord(
- const GlobalFunctionTemplateRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitGlobalVariableTemplateRecord(
+ const GlobalVariableTemplateRecord &Record) {
+ auto GlobalVariableTemplate = serializeAPIRecord(Record);
+ if (!GlobalVariableTemplate)
+ return;
+ Symbols.emplace_back(std::move(*GlobalVariableTemplate));
+}
- serializeTemplateMixin(*CurrentSymbol, *Record);
- return true;
+void SymbolGraphSerializer::visitGlobalVariableTemplateSpecializationRecord(
+ const GlobalVariableTemplateSpecializationRecord &Record) {
+ auto GlobalVariableTemplateSpecialization = serializeAPIRecord(Record);
+ if (!GlobalVariableTemplateSpecialization)
+ return;
+ Symbols.emplace_back(std::move(*GlobalVariableTemplateSpecialization));
}
-bool SymbolGraphSerializer::visitObjCContainerRecord(
- const ObjCContainerRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::
+ visitGlobalVariableTemplatePartialSpecializationRecord(
+ const GlobalVariableTemplatePartialSpecializationRecord &Record) {
+ auto GlobalVariableTemplatePartialSpecialization = serializeAPIRecord(Record);
+ if (!GlobalVariableTemplatePartialSpecialization)
+ return;
+ Symbols.emplace_back(std::move(*GlobalVariableTemplatePartialSpecialization));
+}
- for (const auto &Protocol : Record->Protocols)
- serializeRelationship(ConformsTo, Record, Protocol,
- getModuleForCurrentSymbol());
+void SymbolGraphSerializer::visitGlobalFunctionTemplateRecord(
+ const GlobalFunctionTemplateRecord &Record) {
+ auto GlobalFunctionTemplate = serializeAPIRecord(Record);
+ if (!GlobalFunctionTemplate)
+ return;
+ Symbols.emplace_back(std::move(*GlobalFunctionTemplate));
+}
- return true;
+void SymbolGraphSerializer::visitGlobalFunctionTemplateSpecializationRecord(
+ const GlobalFunctionTemplateSpecializationRecord &Record) {
+ auto GlobalFunctionTemplateSpecialization = serializeAPIRecord(Record);
+ if (!GlobalFunctionTemplateSpecialization)
+ return;
+ Symbols.emplace_back(std::move(*GlobalFunctionTemplateSpecialization));
}
-bool SymbolGraphSerializer::visitObjCInterfaceRecord(
- const ObjCInterfaceRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitObjCContainerRecord(
+ const ObjCContainerRecord &Record) {
+ auto ObjCContainer = serializeAPIRecord(Record);
+ if (!ObjCContainer)
+ return;
- if (!Record->SuperClass.empty())
- serializeRelationship(InheritsFrom, Record, Record->SuperClass,
- getModuleForCurrentSymbol());
- return true;
+ Symbols.emplace_back(std::move(*ObjCContainer));
+
+ serializeMembers(Record, Record.Ivars);
+ serializeMembers(Record, Record.Methods);
+ serializeMembers(Record, Record.Properties);
+
+ for (const auto &Protocol : Record.Protocols)
+ // Record that Record conforms to Protocol.
+ serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
+
+ if (auto *ObjCInterface = dyn_cast<ObjCInterfaceRecord>(&Record)) {
+ if (!ObjCInterface->SuperClass.empty())
+ // If Record is an Objective-C interface record and it has a super class,
+ // record that Record is inherited from SuperClass.
+ serializeRelationship(RelationshipKind::InheritsFrom, Record,
+ ObjCInterface->SuperClass);
+
+ // Members of categories extending an interface are serialized as members of
+ // the interface.
+ for (const auto *Category : ObjCInterface->Categories) {
+ serializeMembers(Record, Category->Ivars);
+ serializeMembers(Record, Category->Methods);
+ serializeMembers(Record, Category->Properties);
+
+ // Surface the protocols of the category to the interface.
+ for (const auto &Protocol : Category->Protocols)
+ serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
+ }
+ }
}
-bool SymbolGraphSerializer::traverseObjCCategoryRecord(
- const ObjCCategoryRecord *Record) {
- auto *CurrentModule = ModuleForCurrentSymbol;
- if (Record->isExtendingExternalModule())
- ModuleForCurrentSymbol = &ExtendedModules[Record->Interface.Source];
+void SymbolGraphSerializer::visitObjCCategoryRecord(
+ const ObjCCategoryRecord &Record) {
+ if (!Record.IsFromExternalModule)
+ return;
- if (!walkUpFromObjCCategoryRecord(Record))
- return false;
+ // Check if the current Category' parent has been visited before, if so skip.
+ if (!visitedCategories.contains(Record.Interface.Name)) {
+ visitedCategories.insert(Record.Interface.Name);
+ Object Obj;
+ serializeObject(Obj, "identifier",
+ serializeIdentifier(Record, API.getLanguage()));
+ serializeObject(Obj, "kind",
+ serializeSymbolKind(APIRecord::RK_ObjCCategoryModule,
+ API.getLanguage()));
+ Obj["accessLevel"] = "public";
+ Symbols.emplace_back(std::move(Obj));
+ }
- bool RetVal = traverseRecordContext(Record);
- ModuleForCurrentSymbol = CurrentModule;
- return RetVal;
-}
+ Object Relationship;
+ Relationship["source"] = Record.USR;
+ Relationship["target"] = Record.Interface.USR;
+ Relationship["targetFallback"] = Record.Interface.Name;
+ Relationship["kind"] = getRelationshipString(RelationshipKind::ExtensionTo);
+ Relationships.emplace_back(std::move(Relationship));
-bool SymbolGraphSerializer::walkUpFromObjCCategoryRecord(
- const ObjCCategoryRecord *Record) {
- return visitObjCCategoryRecord(Record);
-}
+ auto ObjCCategory = serializeAPIRecord(Record);
+
+ if (!ObjCCategory)
+ return;
-bool SymbolGraphSerializer::visitObjCCategoryRecord(
- const ObjCCategoryRecord *Record) {
- // If we need to create a record for the category in the future do so here,
- // otherwise everything is set up to pretend that the category is in fact the
- // interface it extends.
- for (const auto &Protocol : Record->Protocols)
- serializeRelationship(ConformsTo, Record->Interface, Protocol,
- getModuleForCurrentSymbol());
+ Symbols.emplace_back(std::move(*ObjCCategory));
+ serializeMembers(Record, Record.Methods);
+ serializeMembers(Record, Record.Properties);
- return true;
+ // Surface the protocols of the category to the interface.
+ for (const auto &Protocol : Record.Protocols)
+ serializeRelationship(RelationshipKind::ConformsTo, Record, Protocol);
}
-bool SymbolGraphSerializer::visitObjCMethodRecord(
- const ObjCMethodRecord *Record) {
- if (!CurrentSymbol)
- return true;
+void SymbolGraphSerializer::visitMacroDefinitionRecord(
+ const MacroDefinitionRecord &Record) {
+ auto Macro = serializeAPIRecord(Record);
- serializeFunctionSignatureMixin(*CurrentSymbol, *Record);
- return true;
-}
+ if (!Macro)
+ return;
-bool SymbolGraphSerializer::visitObjCInstanceVariableRecord(
- const ObjCInstanceVariableRecord *Record) {
- // FIXME: serialize ivar access control here.
- return true;
+ Symbols.emplace_back(std::move(*Macro));
}
-bool SymbolGraphSerializer::walkUpFromTypedefRecord(
- const TypedefRecord *Record) {
- // Short-circuit walking up the class hierarchy and handle creating typedef
- // symbol objects manually as there are additional symbol dropping rules to
- // respect.
- return visitTypedefRecord(Record);
+void SymbolGraphSerializer::serializeSingleRecord(const APIRecord *Record) {
+ switch (Record->getKind()) {
+ case APIRecord::RK_Unknown:
+ llvm_unreachable("Records should have a known kind!");
+ case APIRecord::RK_GlobalFunction:
+ visitGlobalFunctionRecord(*cast<GlobalFunctionRecord>(Record));
+ break;
+ case APIRecord::RK_GlobalVariable:
+ visitGlobalVariableRecord(*cast<GlobalVariableRecord>(Record));
+ break;
+ case APIRecord::RK_Enum:
+ visitEnumRecord(*cast<EnumRecord>(Record));
+ break;
+ case APIRecord::RK_Struct:
+ LLVM_FALLTHROUGH;
+ case APIRecord::RK_Union:
+ visitRecordRecord(*cast<RecordRecord>(Record));
+ break;
+ case APIRecord::RK_StaticField:
+ visitStaticFieldRecord(*cast<StaticFieldRecord>(Record));
+ break;
+ case APIRecord::RK_CXXClass:
+ visitCXXClassRecord(*cast<CXXClassRecord>(Record));
+ break;
+ case APIRecord::RK_ObjCInterface:
+ visitObjCContainerRecord(*cast<ObjCInterfaceRecord>(Record));
+ break;
+ case APIRecord::RK_ObjCProtocol:
+ visitObjCContainerRecord(*cast<ObjCProtocolRecord>(Record));
+ break;
+ case APIRecord::RK_ObjCCategory:
+ visitObjCCategoryRecord(*cast<ObjCCategoryRecord>(Record));
+ break;
+ case APIRecord::RK_MacroDefinition:
+ visitMacroDefinitionRecord(*cast<MacroDefinitionRecord>(Record));
+ break;
+ case APIRecord::RK_Typedef:
+ visitTypedefRecord(*cast<TypedefRecord>(Record));
+ break;
+ default:
+ if (auto Obj = serializeAPIRecord(*Record)) {
+ Symbols.emplace_back(std::move(*Obj));
+ auto &ParentInformation = Record->ParentInformation;
+ if (!ParentInformation.empty())
+ serializeRelationship(RelationshipKind::MemberOf, *Record,
+ *ParentInformation.ParentRecord);
+ }
+ break;
+ }
}
-bool SymbolGraphSerializer::visitTypedefRecord(const TypedefRecord *Record) {
+void SymbolGraphSerializer::visitTypedefRecord(const TypedefRecord &Record) {
// Typedefs of anonymous types have their entries unified with the underlying
// type.
- bool ShouldDrop = Record->UnderlyingType.Name.empty();
+ bool ShouldDrop = Record.UnderlyingType.Name.empty();
// enums declared with `NS_OPTION` have a named enum and a named typedef, with
// the same name
- ShouldDrop |= (Record->UnderlyingType.Name == Record->Name);
+ ShouldDrop |= (Record.UnderlyingType.Name == Record.Name);
if (ShouldDrop)
- return true;
+ return;
- // Create the symbol record if the other symbol droppping rules permit it.
- serializeAPIRecord(Record);
- if (!CurrentSymbol)
- return true;
+ auto Typedef = serializeAPIRecord(Record);
+ if (!Typedef)
+ return;
- (*CurrentSymbol)["type"] = Record->UnderlyingType.USR;
+ (*Typedef)["type"] = Record.UnderlyingType.USR;
- return true;
+ Symbols.emplace_back(std::move(*Typedef));
}
-void SymbolGraphSerializer::serializeSingleRecord(const APIRecord *Record) {
- switch (Record->getKind()) {
- // dispatch to the relevant walkUpFromMethod
-#define CONCRETE_RECORD(CLASS, BASE, KIND) \
- case APIRecord::KIND: { \
- walkUpFrom##CLASS(static_cast<const CLASS *>(Record)); \
- break; \
- }
-#include "clang/ExtractAPI/APIRecords.inc"
- // otherwise fallback on the only behavior we can implement safely.
- case APIRecord::RK_Unknown:
- visitAPIRecord(Record);
- break;
- default:
- llvm_unreachable("API Record with uninstantiable kind");
- }
+Object SymbolGraphSerializer::serialize() {
+ traverseAPISet();
+ return serializeCurrentGraph();
}
-Object SymbolGraphSerializer::serializeGraph(StringRef ModuleName,
- ExtendedModule &&EM) {
+Object SymbolGraphSerializer::serializeCurrentGraph() {
Object Root;
serializeObject(Root, "metadata", serializeMetadata());
- serializeObject(Root, "module", serializeModuleObject(ModuleName));
+ serializeObject(Root, "module", serializeModule());
- Root["symbols"] = std::move(EM.Symbols);
- Root["relationships"] = std::move(EM.Relationships);
+ Root["symbols"] = std::move(Symbols);
+ Root["relationships"] = std::move(Relationships);
return Root;
}
-void SymbolGraphSerializer::serializeGraphToStream(
- raw_ostream &OS, SymbolGraphSerializerOption Options, StringRef ModuleName,
- ExtendedModule &&EM) {
- Object Root = serializeGraph(ModuleName, std::move(EM));
+void SymbolGraphSerializer::serialize(raw_ostream &os) {
+ Object root = serialize();
if (Options.Compact)
- OS << formatv("{0}", Value(std::move(Root))) << "\n";
+ os << formatv("{0}", Value(std::move(root))) << "\n";
else
- OS << formatv("{0:2}", Value(std::move(Root))) << "\n";
-}
-
-void SymbolGraphSerializer::serializeMainSymbolGraph(
- raw_ostream &OS, const APISet &API, const APIIgnoresList &IgnoresList,
- SymbolGraphSerializerOption Options) {
- SymbolGraphSerializer Serializer(API, IgnoresList,
- Options.EmitSymbolLabelsForTesting);
- Serializer.traverseAPISet();
- Serializer.serializeGraphToStream(OS, Options, API.ProductName,
- std::move(Serializer.MainModule));
- // FIXME: TODO handle extended modules here
-}
-
-void SymbolGraphSerializer::serializeWithExtensionGraphs(
- raw_ostream &MainOutput, const APISet &API,
- const APIIgnoresList &IgnoresList,
- llvm::function_ref<std::unique_ptr<llvm::raw_pwrite_stream>(Twine BaseName)>
- CreateOutputStream,
- SymbolGraphSerializerOption Options) {
- SymbolGraphSerializer Serializer(API, IgnoresList,
- Options.EmitSymbolLabelsForTesting);
- Serializer.traverseAPISet();
-
- Serializer.serializeGraphToStream(MainOutput, Options, API.ProductName,
- std::move(Serializer.MainModule));
-
- for (auto &ExtensionSGF : Serializer.ExtendedModules) {
- if (auto ExtensionOS =
- CreateOutputStream(ExtensionSGF.getKey() + "@" + API.ProductName))
- Serializer.serializeGraphToStream(*ExtensionOS, Options,
- ExtensionSGF.getKey(),
- std::move(ExtensionSGF.getValue()));
- }
+ os << formatv("{0:2}", Value(std::move(root))) << "\n";
}
std::optional<Object>
@@ -1070,20 +1262,14 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR,
Object Root;
APIIgnoresList EmptyIgnores;
SymbolGraphSerializer Serializer(API, EmptyIgnores,
- /*EmitSymbolLabelsForTesting*/ false,
- /*ForceEmitToMainModule*/ true);
-
- // Set up serializer parent chain
- Serializer.Hierarchy = generateHierarchyFromRecord(Record);
-
+ /*Options.Compact*/ {true},
+ /*ShouldRecurse*/ false);
Serializer.serializeSingleRecord(Record);
- serializeObject(Root, "symbolGraph",
- Serializer.serializeGraph(API.ProductName,
- std::move(Serializer.MainModule)));
+ serializeObject(Root, "symbolGraph", Serializer.serializeCurrentGraph());
Language Lang = API.getLanguage();
serializeArray(Root, "parentContexts",
- generateParentContexts(Serializer.Hierarchy, Lang));
+ generateParentContexts(*Record, API, Lang));
Array RelatedSymbols;
@@ -1101,15 +1287,14 @@ SymbolGraphSerializer::serializeSingleSymbolSGF(StringRef USR,
Object RelatedSymbol;
RelatedSymbol["usr"] = RelatedRecord->USR;
RelatedSymbol["declarationLanguage"] = getLanguageName(Lang);
- RelatedSymbol["accessLevel"] = RelatedRecord->Access.getAccess();
+ // TODO: once we record this properly let's serialize it right.
+ RelatedSymbol["accessLevel"] = "public";
RelatedSymbol["filePath"] = RelatedRecord->Location.getFilename();
RelatedSymbol["moduleName"] = API.ProductName;
RelatedSymbol["isSystem"] = RelatedRecord->IsFromSystemHeader;
serializeArray(RelatedSymbol, "parentContexts",
- generateParentContexts(
- generateHierarchyFromRecord(RelatedRecord), Lang));
-
+ generateParentContexts(*RelatedRecord, API, Lang));
RelatedSymbols.push_back(std::move(RelatedSymbol));
}
diff --git a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
index 41e4e0c..3a5f62c 100644
--- a/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
+++ b/clang/lib/ExtractAPI/TypedefUnderlyingTypeResolver.cpp
@@ -12,7 +12,6 @@
//===----------------------------------------------------------------------===//
#include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
-#include "clang/Basic/Module.h"
#include "clang/Index/USRGeneration.h"
using namespace clang;
@@ -51,20 +50,17 @@ TypedefUnderlyingTypeResolver::getSymbolReferenceForType(QualType Type,
SmallString<128> TypeUSR;
const NamedDecl *TypeDecl = getUnderlyingTypeDecl(Type);
const TypedefType *TypedefTy = Type->getAs<TypedefType>();
- StringRef OwningModuleName;
if (TypeDecl) {
if (!TypedefTy)
TypeName = TypeDecl->getName().str();
clang::index::generateUSRForDecl(TypeDecl, TypeUSR);
- if (auto *OwningModule = TypeDecl->getImportedOwningModule())
- OwningModuleName = OwningModule->Name;
} else {
clang::index::generateUSRForType(Type, Context, TypeUSR);
}
- return API.createSymbolReference(TypeName, TypeUSR, OwningModuleName);
+ return {API.copyString(TypeName), API.copyString(TypeUSR)};
}
std::string TypedefUnderlyingTypeResolver::getUSRForType(QualType Type) const {
diff --git a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
index f85f036..2446aee 100644
--- a/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
+++ b/clang/lib/FrontendTool/ExecuteCompilerInvocation.cpp
@@ -181,13 +181,9 @@ CreateFrontendAction(CompilerInstance &CI) {
#endif
// Wrap the base FE action in an extract api action to generate
- // symbol graph as a biproduct of compilation (enabled with
- // --emit-symbol-graph option)
- if (FEOpts.EmitSymbolGraph) {
- if (FEOpts.SymbolGraphOutputDir.empty()) {
- CI.getDiagnostics().Report(diag::warn_missing_symbol_graph_dir);
- CI.getFrontendOpts().SymbolGraphOutputDir = ".";
- }
+ // symbol graph as a biproduct of compilation ( enabled with
+ // --emit-symbol-graph option )
+ if (!FEOpts.SymbolGraphOutputDir.empty()) {
CI.getCodeGenOpts().ClearASTBeforeBackend = false;
Act = std::make_unique<WrappingExtractAPIAction>(std::move(Act));
}