[clang-doc] add namespaces to JSON generator (#143209)
Emit namespaces to JSON. Also adds tests for namespaces and non-member constructs.
This commit is contained in:
@@ -440,6 +440,39 @@ static void serializeInfo(const RecordInfo &I, json::Object &Obj,
|
||||
serializeCommonChildren(I.Children, Obj, RepositoryUrl);
|
||||
}
|
||||
|
||||
static void serializeInfo(const NamespaceInfo &I, json::Object &Obj,
|
||||
std::optional<StringRef> RepositoryUrl) {
|
||||
serializeCommonAttributes(I, Obj, RepositoryUrl);
|
||||
|
||||
if (!I.Children.Namespaces.empty()) {
|
||||
json::Value NamespacesArray = Array();
|
||||
auto &NamespacesArrayRef = *NamespacesArray.getAsArray();
|
||||
NamespacesArrayRef.reserve(I.Children.Namespaces.size());
|
||||
for (auto &Namespace : I.Children.Namespaces) {
|
||||
json::Value NamespaceVal = Object();
|
||||
auto &NamespaceObj = *NamespaceVal.getAsObject();
|
||||
serializeReference(Namespace, NamespaceObj);
|
||||
NamespacesArrayRef.push_back(NamespaceVal);
|
||||
}
|
||||
Obj["Namespaces"] = NamespacesArray;
|
||||
}
|
||||
|
||||
if (!I.Children.Functions.empty()) {
|
||||
json::Value FunctionsArray = Array();
|
||||
auto &FunctionsArrayRef = *FunctionsArray.getAsArray();
|
||||
FunctionsArrayRef.reserve(I.Children.Functions.size());
|
||||
for (const auto &Function : I.Children.Functions) {
|
||||
json::Value FunctionVal = Object();
|
||||
auto &FunctionObj = *FunctionVal.getAsObject();
|
||||
serializeInfo(Function, FunctionObj, RepositoryUrl);
|
||||
FunctionsArrayRef.push_back(FunctionVal);
|
||||
}
|
||||
Obj["Functions"] = FunctionsArray;
|
||||
}
|
||||
|
||||
serializeCommonChildren(I.Children, Obj, RepositoryUrl);
|
||||
}
|
||||
|
||||
Error JSONGenerator::generateDocs(
|
||||
StringRef RootDir, llvm::StringMap<std::unique_ptr<doc::Info>> Infos,
|
||||
const ClangDocContext &CDCtx) {
|
||||
@@ -482,6 +515,7 @@ Error JSONGenerator::generateDocForInfo(Info *I, raw_ostream &OS,
|
||||
|
||||
switch (I->IT) {
|
||||
case InfoType::IT_namespace:
|
||||
serializeInfo(*static_cast<NamespaceInfo *>(I), Obj, CDCtx.RepositoryUrl);
|
||||
break;
|
||||
case InfoType::IT_record:
|
||||
serializeInfo(*static_cast<RecordInfo *>(I), Obj, CDCtx.RepositoryUrl);
|
||||
|
||||
@@ -742,6 +742,7 @@ static void populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
|
||||
I.ReturnType = getTypeInfoForType(D->getReturnType(), LO);
|
||||
I.Prototype = getFunctionPrototype(D);
|
||||
parseParameters(I, D);
|
||||
I.IsStatic = D->isStatic();
|
||||
|
||||
populateTemplateParameters(I.Template, D);
|
||||
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// RUN: rm -rf %t && mkdir -p %t
|
||||
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
|
||||
// RUN: FileCheck %s < %t/GlobalNamespace/index.json
|
||||
|
||||
static void myFunction() {}
|
||||
|
||||
void noExceptFunction() noexcept {}
|
||||
|
||||
inline void inlineFunction() {}
|
||||
|
||||
extern void externFunction() {}
|
||||
|
||||
constexpr void constexprFunction() {}
|
||||
|
||||
// CHECK: "Functions": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK: "IsStatic": true,
|
||||
// COM: FIXME: Emit ExceptionSpecificationType
|
||||
// CHECK-NOT: "ExceptionSpecifcation" : "noexcept",
|
||||
// COM: FIXME: Emit inline
|
||||
// CHECK-NOT: "IsInline": true,
|
||||
// COM: FIXME: Emit extern
|
||||
// CHECK-NOT: "IsExtern": true,
|
||||
// COM: FIXME: Emit constexpr
|
||||
// CHECK-NOT: "IsConstexpr": true,
|
||||
107
clang-tools-extra/test/clang-doc/json/namespace.cpp
Normal file
107
clang-tools-extra/test/clang-doc/json/namespace.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
// RUN: rm -rf %t && mkdir -p %t
|
||||
// RUN: clang-doc --output=%t --format=json --executor=standalone %s
|
||||
// RUN: FileCheck %s < %t/GlobalNamespace/index.json
|
||||
|
||||
class MyClass {};
|
||||
|
||||
void myFunction(int Param);
|
||||
|
||||
namespace NestedNamespace {
|
||||
} // namespace NestedNamespace
|
||||
|
||||
// FIXME: Global variables are not mapped or serialized.
|
||||
static int Global;
|
||||
|
||||
enum Color {
|
||||
RED,
|
||||
GREEN,
|
||||
BLUE = 5
|
||||
};
|
||||
|
||||
typedef int MyTypedef;
|
||||
|
||||
// CHECK: {
|
||||
// CHECK-NEXT: "Enums": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "Location": {
|
||||
// CHECK-NEXT: "Filename": "{{.*}}namespace.cpp",
|
||||
// CHECK-NEXT: "LineNumber": 15
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "Members": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "Name": "RED",
|
||||
// CHECK-NEXT: "Value": "0"
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "Name": "GREEN",
|
||||
// CHECK-NEXT: "Value": "1"
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "Name": "BLUE",
|
||||
// CHECK-NEXT: "ValueExpr": "5"
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "Name": "Color",
|
||||
// CHECK-NEXT: "Scoped": false,
|
||||
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "Functions": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "IsStatic": false,
|
||||
// CHECK-NEXT: "Name": "myFunction",
|
||||
// CHECK-NEXT: "Params": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "Name": "Param",
|
||||
// CHECK-NEXT: "Type": "int"
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "ReturnType": {
|
||||
// CHECK-NEXT: "IsBuiltIn": false,
|
||||
// CHECK-NEXT: "IsTemplate": false,
|
||||
// CHECK-NEXT: "Name": "void",
|
||||
// CHECK-NEXT: "QualName": "void",
|
||||
// CHECK-NEXT: "USR": "0000000000000000000000000000000000000000"
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "Name": "",
|
||||
// CHECK-NEXT: "Namespaces": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "Name": "NestedNamespace",
|
||||
// CHECK-NEXT: "Path": "",
|
||||
// CHECK-NEXT: "QualName": "NestedNamespace",
|
||||
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "Records": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "Name": "MyClass",
|
||||
// CHECK-NEXT: "Path": "GlobalNamespace",
|
||||
// CHECK-NEXT: "QualName": "MyClass",
|
||||
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}"
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "Typedefs": [
|
||||
// CHECK-NEXT: {
|
||||
// CHECK-NEXT: "IsUsing": false,
|
||||
// CHECK-NEXT: "Location": {
|
||||
// CHECK-NEXT: "Filename": "{{.*}}namespace.cpp",
|
||||
// CHECK-NEXT: "LineNumber": 21
|
||||
// CHECK-NEXT: },
|
||||
// CHECK-NEXT: "Name": "MyTypedef",
|
||||
// CHECK-NEXT: "TypeDeclaration": "",
|
||||
// CHECK-NEXT: "USR": "{{[0-9A-F]*}}",
|
||||
// CHECK-NEXT: "Underlying": {
|
||||
// CHECK-NEXT: "IsBuiltIn": false,
|
||||
// CHECK-NEXT: "IsTemplate": false,
|
||||
// CHECK-NEXT: "Name": "int",
|
||||
// CHECK-NEXT: "QualName": "int",
|
||||
// CHECK-NEXT: "USR": "0000000000000000000000000000000000000000"
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: }
|
||||
// CHECK-NEXT: ],
|
||||
// CHECK-NEXT: "USR": "0000000000000000000000000000000000000000"
|
||||
// CHECK-NOT: "Variables": [
|
||||
// CHECK-NEXT: }
|
||||
@@ -171,5 +171,77 @@ TEST(JSONGeneratorTest, emitRecordJSON) {
|
||||
})raw";
|
||||
EXPECT_EQ(Expected, Actual.str());
|
||||
}
|
||||
|
||||
TEST(JSONGeneratorTest, emitNamespaceJSON) {
|
||||
NamespaceInfo I;
|
||||
I.Name = "Namespace";
|
||||
I.Path = "path/to/A";
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.Children.Namespaces.emplace_back(
|
||||
EmptySID, "ChildNamespace", InfoType::IT_namespace,
|
||||
"path::to::A::Namespace::ChildNamespace", "path/to/A/Namespace");
|
||||
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
|
||||
"path::to::A::Namespace::ChildStruct",
|
||||
"path/to/A/Namespace");
|
||||
I.Children.Functions.emplace_back();
|
||||
I.Children.Functions.back().Name = "OneFunction";
|
||||
I.Children.Functions.back().Access = AccessSpecifier::AS_none;
|
||||
I.Children.Enums.emplace_back();
|
||||
I.Children.Enums.back().Name = "OneEnum";
|
||||
|
||||
auto G = getJSONGenerator();
|
||||
assert(G);
|
||||
std::string Buffer;
|
||||
llvm::raw_string_ostream Actual(Buffer);
|
||||
auto Err = G->generateDocForInfo(&I, Actual, ClangDocContext());
|
||||
assert(!Err);
|
||||
std::string Expected = R"raw({
|
||||
"Enums": [
|
||||
{
|
||||
"Name": "OneEnum",
|
||||
"Scoped": false,
|
||||
"USR": "0000000000000000000000000000000000000000"
|
||||
}
|
||||
],
|
||||
"Functions": [
|
||||
{
|
||||
"IsStatic": false,
|
||||
"Name": "OneFunction",
|
||||
"ReturnType": {
|
||||
"IsBuiltIn": false,
|
||||
"IsTemplate": false,
|
||||
"Name": "",
|
||||
"QualName": "",
|
||||
"USR": "0000000000000000000000000000000000000000"
|
||||
},
|
||||
"USR": "0000000000000000000000000000000000000000"
|
||||
}
|
||||
],
|
||||
"Name": "Namespace",
|
||||
"Namespace": [
|
||||
"A"
|
||||
],
|
||||
"Namespaces": [
|
||||
{
|
||||
"Name": "ChildNamespace",
|
||||
"Path": "path/to/A/Namespace",
|
||||
"QualName": "path::to::A::Namespace::ChildNamespace",
|
||||
"USR": "0000000000000000000000000000000000000000"
|
||||
}
|
||||
],
|
||||
"Path": "path/to/A",
|
||||
"Records": [
|
||||
{
|
||||
"Name": "ChildStruct",
|
||||
"Path": "path/to/A/Namespace",
|
||||
"QualName": "path::to::A::Namespace::ChildStruct",
|
||||
"USR": "0000000000000000000000000000000000000000"
|
||||
}
|
||||
],
|
||||
"USR": "0000000000000000000000000000000000000000"
|
||||
})raw";
|
||||
EXPECT_EQ(Expected, Actual.str());
|
||||
}
|
||||
} // namespace doc
|
||||
} // namespace clang
|
||||
|
||||
Reference in New Issue
Block a user