aronsky updated this revision to Diff 302558.
aronsky retitled this revision from "Include attribute details when dumping AST 
in JSON" to "Include more attribute details when dumping AST in JSON".
aronsky edited the summary of this revision.
aronsky added a comment.

Updated the relevant unit-test: it now passes, and also verifies the changes.


CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D90221/new/

https://reviews.llvm.org/D90221

Files:
  clang/include/clang/AST/CMakeLists.txt
  clang/include/clang/AST/JSONNodeDumper.h
  clang/lib/AST/JSONNodeDumper.cpp
  clang/test/AST/ast-dump-stmt-json.cpp
  clang/utils/TableGen/ClangAttrEmitter.cpp
  clang/utils/TableGen/TableGen.cpp
  clang/utils/TableGen/TableGenBackends.h

Index: clang/utils/TableGen/TableGenBackends.h
===================================================================
--- clang/utils/TableGen/TableGenBackends.h
+++ clang/utils/TableGen/TableGenBackends.h
@@ -59,6 +59,8 @@
                                   llvm::raw_ostream &OS);
 void EmitClangAttrTextNodeDump(llvm::RecordKeeper &Records,
                                llvm::raw_ostream &OS);
+void EmitClangAttrJSONNodeDump(llvm::RecordKeeper &Records,
+                               llvm::raw_ostream &OS);
 void EmitClangAttrNodeTraverse(llvm::RecordKeeper &Records,
                                llvm::raw_ostream &OS);
 
Index: clang/utils/TableGen/TableGen.cpp
===================================================================
--- clang/utils/TableGen/TableGen.cpp
+++ clang/utils/TableGen/TableGen.cpp
@@ -41,6 +41,7 @@
   GenClangAttrParsedAttrImpl,
   GenClangAttrParsedAttrKinds,
   GenClangAttrTextNodeDump,
+  GenClangAttrJSONNodeDump,
   GenClangAttrNodeTraverse,
   GenClangBasicReader,
   GenClangBasicWriter,
@@ -138,6 +139,8 @@
                    "Generate a clang parsed attribute kinds"),
         clEnumValN(GenClangAttrTextNodeDump, "gen-clang-attr-text-node-dump",
                    "Generate clang attribute text node dumper"),
+        clEnumValN(GenClangAttrJSONNodeDump, "gen-clang-attr-json-node-dump",
+                   "Generate clang attribute JSON node dumper"),
         clEnumValN(GenClangAttrNodeTraverse, "gen-clang-attr-node-traverse",
                    "Generate clang attribute traverser"),
         clEnumValN(GenClangDiagsDefs, "gen-clang-diags-defs",
@@ -295,6 +298,9 @@
   case GenClangAttrTextNodeDump:
     EmitClangAttrTextNodeDump(Records, OS);
     break;
+  case GenClangAttrJSONNodeDump:
+    EmitClangAttrJSONNodeDump(Records, OS);
+    break;
   case GenClangAttrNodeTraverse:
     EmitClangAttrNodeTraverse(Records, OS);
     break;
Index: clang/utils/TableGen/ClangAttrEmitter.cpp
===================================================================
--- clang/utils/TableGen/ClangAttrEmitter.cpp
+++ clang/utils/TableGen/ClangAttrEmitter.cpp
@@ -24,6 +24,7 @@
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/iterator_range.h"
 #include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/JSON.h"
 #include "llvm/Support/raw_ostream.h"
 #include "llvm/TableGen/Error.h"
 #include "llvm/TableGen/Record.h"
@@ -3895,7 +3896,7 @@
      << "}\n";
 }
 
-// Emits the code to dump an attribute.
+// Emits the code to dump an attribute as text.
 void EmitClangAttrTextNodeDump(RecordKeeper &Records, raw_ostream &OS) {
   emitSourceFileHeader("Attribute text node dumper", OS);
 
@@ -3932,6 +3933,58 @@
   }
 }
 
+// Emits the code to dump an attribute as JSON.
+void EmitClangAttrJSONNodeDump(RecordKeeper &Records, raw_ostream &OS) {
+  emitSourceFileHeader("Attribute text node dumper", OS);
+
+  std::vector<Record *> Attrs = Records.getAllDerivedDefinitions("Attr"), Args;
+  for (const auto *Attr : Attrs) {
+    const Record &R = *Attr;
+    if (!R.getValueAsBit("ASTNode"))
+      continue;
+
+    OS << "  void Visit" << R.getName() << "Attr(const " << R.getName()
+       << "Attr *A) {\n";
+
+    // If the attribute has a semantically-meaningful name (which is determined
+    // by whether there is a Spelling enumeration for it), then write out the
+    // spelling used for the attribute.
+
+    std::string FunctionContent;
+    llvm::raw_string_ostream SS(FunctionContent);
+
+    Args = R.getValueAsListOfDefs("Args");
+
+    if (!Args.empty())
+      OS << "    const auto *SA = cast<" << R.getName()
+         << "Attr>(A); (void)SA;\n"
+         << "    llvm::json::Array Args;\n";
+
+    std::vector<FlattenedSpelling> Spellings = GetFlattenedSpellings(R);
+    if (Spellings.size() > 1 && !SpellingNamesAreCommon(Spellings))
+      OS << "    JOS.attribute(\"spelling\", A->getSpelling());\n";
+
+    for (const auto *Arg : Args) {
+      std::string ArgContent;
+      llvm::raw_string_ostream SS(ArgContent);
+
+      createArgument(*Arg, R.getName())->writeDump(SS);
+
+      if (SS.tell())
+        OS << "    {\n"
+           << "        std::string Str;\n"
+           << "        llvm::raw_string_ostream OS(Str);\n"
+           << SS.str() << "        Args.push_back(OS.str());\n"
+           << "    }\n";
+    }
+
+    if (!Args.empty())
+      OS << "    JOS.attribute(\"args\", std::move(Args));\n";
+
+    OS << "}\n";
+  }
+}
+
 void EmitClangAttrNodeTraverse(RecordKeeper &Records, raw_ostream &OS) {
   emitSourceFileHeader("Attribute text node traverser", OS);
 
Index: clang/test/AST/ast-dump-stmt-json.cpp
===================================================================
--- clang/test/AST/ast-dump-stmt-json.cpp
+++ clang/test/AST/ast-dump-stmt-json.cpp
@@ -1461,6 +1461,9 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " Default"
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   },
 // CHECK-NEXT:   {
 // CHECK-NEXT:    "id": "0x{{.*}}",
@@ -1479,6 +1482,10 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " 1",
+// CHECK-NEXT:     ""
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   }
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
@@ -1531,6 +1538,9 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " Default"
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   },
 // CHECK-NEXT:   {
 // CHECK-NEXT:    "id": "0x{{.*}}",
@@ -1549,6 +1559,10 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " 1",
+// CHECK-NEXT:     ""
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   },
 // CHECK-NEXT:   {
 // CHECK-NEXT:    "id": "0x{{.*}}",
@@ -1558,6 +1572,9 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " 2"
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   }
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
@@ -1598,6 +1615,9 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " Default"
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   },
 // CHECK-NEXT:   {
 // CHECK-NEXT:    "id": "0x{{.*}}",
@@ -1616,6 +1636,10 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " 1"
+// CHECK-NEXT:     ""
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   }
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
@@ -1668,6 +1692,9 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " Default"
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   },
 // CHECK-NEXT:   {
 // CHECK-NEXT:    "id": "0x{{.*}}",
@@ -1686,6 +1713,10 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " 1"
+// CHECK-NEXT:     ""
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   },
 // CHECK-NEXT:   {
 // CHECK-NEXT:    "id": "0x{{.*}}",
@@ -1695,6 +1726,9 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " 2"
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   }
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
@@ -1735,6 +1769,9 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " Default"
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   }
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
@@ -1787,6 +1824,9 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " Default"
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   }
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
@@ -1827,6 +1867,9 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " Default"
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   }
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
@@ -1879,6 +1922,9 @@
 // CHECK-NEXT:     "end": {}
 // CHECK-NEXT:    },
 // CHECK-NEXT:    "implicit": true
+// CHECK-NEXT:    "args": [
+// CHECK-NEXT:     " Default"
+// CHECK-NEXT:    ]
 // CHECK-NEXT:   }
 // CHECK-NEXT:  ]
 // CHECK-NEXT: }
Index: clang/lib/AST/JSONNodeDumper.cpp
===================================================================
--- clang/lib/AST/JSONNodeDumper.cpp
+++ clang/lib/AST/JSONNodeDumper.cpp
@@ -306,6 +306,12 @@
     JOS.attribute("type", createQualType(VD->getType()));
 }
 
+void JSONNodeDumper::dumpBareDeclRef(const Decl *D) { writeBareDeclRef(D); }
+
+void JSONNodeDumper::dumpType(QualType QT) {
+  JOS.attribute("type", createQualType(QT));
+}
+
 llvm::json::Object JSONNodeDumper::createBareDeclRef(const Decl *D) {
   llvm::json::Object Ret{{"id", createPointerRepresentation(D)}};
   if (!D)
Index: clang/include/clang/AST/JSONNodeDumper.h
===================================================================
--- clang/include/clang/AST/JSONNodeDumper.h
+++ clang/include/clang/AST/JSONNodeDumper.h
@@ -161,6 +161,8 @@
   llvm::json::Object createQualType(QualType QT, bool Desugar = true);
   llvm::json::Object createBareDeclRef(const Decl *D);
   void writeBareDeclRef(const Decl *D);
+  void dumpBareDeclRef(const Decl *D);
+  void dumpType(QualType QT);
   llvm::json::Object createCXXRecordDefinitionData(const CXXRecordDecl *RD);
   llvm::json::Object createCXXBaseSpecifier(const CXXBaseSpecifier &BS);
   std::string createAccessSpecifier(AccessSpecifier AS);
@@ -206,6 +208,9 @@
   void Visit(const GenericSelectionExpr::ConstAssociation &A);
   void Visit(const APValue &Value, QualType Ty);
 
+// Implements Visit methods for Attrs.
+#include "clang/AST/AttrJSONNodeDump.inc"
+
   void VisitTypedefType(const TypedefType *TT);
   void VisitFunctionType(const FunctionType *T);
   void VisitFunctionProtoType(const FunctionProtoType *T);
Index: clang/include/clang/AST/CMakeLists.txt
===================================================================
--- clang/include/clang/AST/CMakeLists.txt
+++ clang/include/clang/AST/CMakeLists.txt
@@ -10,6 +10,10 @@
   SOURCE ../Basic/Attr.td
   TARGET ClangAttrTextDump)
 
+clang_tablegen(AttrJSONNodeDump.inc -gen-clang-attr-json-node-dump
+  SOURCE ../Basic/Attr.td
+  TARGET ClangAttrJSONDump)
+
 clang_tablegen(AttrNodeTraverse.inc -gen-clang-attr-node-traverse
   SOURCE ../Basic/Attr.td
   TARGET ClangAttrTraverse)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to