r311199 - [clang-diff] Move the JSON export function to clang-diff

Johannes Altmanninger via cfe-commits cfe-commits at lists.llvm.org
Fri Aug 18 14:26:13 PDT 2017


Author: krobelus
Date: Fri Aug 18 14:26:13 2017
New Revision: 311199

URL: http://llvm.org/viewvc/llvm-project?rev=311199&view=rev
Log:
[clang-diff] Move the JSON export function to clang-diff

Reviewers: arphaman

Subscribers: klimek

Differential Revision: https://reviews.llvm.org/D36178

Added:
    cfe/trunk/test/Tooling/clang-diff-json.cpp
Modified:
    cfe/trunk/include/clang/Tooling/ASTDiff/ASTDiff.h
    cfe/trunk/lib/Tooling/ASTDiff/ASTDiff.cpp
    cfe/trunk/test/lit.cfg
    cfe/trunk/test/lit.site.cfg.in
    cfe/trunk/tools/clang-diff/ClangDiff.cpp

Modified: cfe/trunk/include/clang/Tooling/ASTDiff/ASTDiff.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/Tooling/ASTDiff/ASTDiff.h?rev=311199&r1=311198&r2=311199&view=diff
==============================================================================
--- cfe/trunk/include/clang/Tooling/ASTDiff/ASTDiff.h (original)
+++ cfe/trunk/include/clang/Tooling/ASTDiff/ASTDiff.h Fri Aug 18 14:26:13 2017
@@ -57,8 +57,8 @@ struct Node {
   ast_type_traits::DynTypedNode ASTNode;
   SmallVector<NodeId, 4> Children;
 
-  ast_type_traits::ASTNodeKind getType() const { return ASTNode.getNodeKind(); }
-  const StringRef getTypeLabel() const { return getType().asStringRef(); }
+  ast_type_traits::ASTNodeKind getType() const;
+  StringRef getTypeLabel() const;
   bool isLeaf() const { return Children.empty(); }
 };
 
@@ -96,15 +96,20 @@ public:
   SyntaxTree(SyntaxTree &&Other) = default;
   ~SyntaxTree();
 
+  const ASTContext &getASTContext() const;
+  StringRef getFilename() const;
+
   const Node &getNode(NodeId Id) const;
+  NodeId getRootId() const;
+
+  // Returns the starting and ending offset of the node in its source file.
+  std::pair<unsigned, unsigned> getSourceRangeOffsets(const Node &N) const;
 
   /// Serialize the node attributes to a string representation. This should
   /// uniquely distinguish nodes of the same kind. Note that this function just
   /// returns a representation of the node value, not considering descendants.
   std::string getNodeValue(const DynTypedNode &DTN) const;
 
-  void printAsJson(raw_ostream &OS);
-
   class Impl;
   std::unique_ptr<Impl> TreeImpl;
 };

Modified: cfe/trunk/lib/Tooling/ASTDiff/ASTDiff.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/Tooling/ASTDiff/ASTDiff.cpp?rev=311199&r1=311198&r2=311199&view=diff
==============================================================================
--- cfe/trunk/lib/Tooling/ASTDiff/ASTDiff.cpp (original)
+++ cfe/trunk/lib/Tooling/ASTDiff/ASTDiff.cpp Fri Aug 18 14:26:13 2017
@@ -176,9 +176,6 @@ public:
   void printTree(NodeId Root) const;
   void printTree(raw_ostream &OS, NodeId Root) const;
 
-  void printAsJsonImpl(raw_ostream &OS) const;
-  void printNodeAsJson(raw_ostream &OS, NodeId Id) const;
-
 private:
   /// Nodes in preorder.
   std::vector<Node> Nodes;
@@ -438,28 +435,6 @@ void SyntaxTree::Impl::printNode(raw_ost
   OS << "(" << PostorderIds[Id] << ")";
 }
 
-void SyntaxTree::Impl::printNodeAsJson(raw_ostream &OS, NodeId Id) const {
-  auto N = getNode(Id);
-  OS << R"({"type":")" << N.getTypeLabel() << R"(")";
-  if (getNodeValue(Id) != "")
-    OS << R"(,"value":")" << getNodeValue(Id) << R"(")";
-  OS << R"(,"children":[)";
-  if (N.Children.size() > 0) {
-    printNodeAsJson(OS, N.Children[0]);
-    for (size_t I = 1, E = N.Children.size(); I < E; ++I) {
-      OS << ",";
-      printNodeAsJson(OS, N.Children[I]);
-    }
-  }
-  OS << "]}";
-}
-
-void SyntaxTree::Impl::printAsJsonImpl(raw_ostream &OS) const {
-  OS << R"({"root":)";
-  printNodeAsJson(OS, getRootId());
-  OS << "}\n";
-}
-
 /// Identifies a node in a subtree by its postorder offset, starting at 1.
 struct SNodeId {
   int Id = 0;
@@ -674,6 +649,12 @@ private:
   }
 };
 
+ast_type_traits::ASTNodeKind Node::getType() const {
+  return ASTNode.getNodeKind();
+}
+
+StringRef Node::getTypeLabel() const { return getType().asStringRef(); }
+
 namespace {
 // Compares nodes by their depth.
 struct HeightLess {
@@ -999,7 +980,28 @@ void ASTDiff::printMatch(raw_ostream &OS
 
 SyntaxTree::~SyntaxTree() = default;
 
-void SyntaxTree::printAsJson(raw_ostream &OS) { TreeImpl->printAsJsonImpl(OS); }
+const ASTContext &SyntaxTree::getASTContext() const { return TreeImpl->AST; }
+
+const Node &SyntaxTree::getNode(NodeId Id) const {
+  return TreeImpl->getNode(Id);
+}
+
+NodeId SyntaxTree::getRootId() const { return TreeImpl->getRootId(); }
+
+std::pair<unsigned, unsigned> SyntaxTree::getSourceRangeOffsets(const Node &N) const {
+  const SourceManager &SrcMgr = TreeImpl->AST.getSourceManager();
+  SourceRange Range = N.ASTNode.getSourceRange();
+  SourceLocation BeginLoc = Range.getBegin();
+  SourceLocation EndLoc = Lexer::getLocForEndOfToken(
+      Range.getEnd(), /*Offset=*/0, SrcMgr, TreeImpl->AST.getLangOpts());
+  if (auto *ThisExpr = N.ASTNode.get<CXXThisExpr>()) {
+    if (ThisExpr->isImplicit())
+      EndLoc = BeginLoc;
+  }
+  unsigned Begin = SrcMgr.getFileOffset(SrcMgr.getExpansionLoc(BeginLoc));
+  unsigned End = SrcMgr.getFileOffset(SrcMgr.getExpansionLoc(EndLoc));
+  return {Begin, End};
+}
 
 std::string SyntaxTree::getNodeValue(const DynTypedNode &DTN) const {
   return TreeImpl->getNodeValue(DTN);

Added: cfe/trunk/test/Tooling/clang-diff-json.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Tooling/clang-diff-json.cpp?rev=311199&view=auto
==============================================================================
--- cfe/trunk/test/Tooling/clang-diff-json.cpp (added)
+++ cfe/trunk/test/Tooling/clang-diff-json.cpp Fri Aug 18 14:26:13 2017
@@ -0,0 +1,27 @@
+// RUN: clang-diff -ast-dump %s -- \
+// RUN: | %python -c 'import json, sys; json.dump(json.loads(sys.stdin.read()), sys.stdout, sort_keys=True, indent=2)' \
+// RUN: | FileCheck %s
+
+// CHECK: "begin": 294,
+// CHECK: "type": "CXXRecordDecl",
+// CHECK: "type": "FieldDecl",
+// CHECK: "end": 314,
+class A {
+  int x;
+};
+
+// CHECK: "children": [
+// CHECK-NEXT: {
+// CHECK-NEXT: "begin":
+// CHECK-NEXT: "children": []
+// CHECK-NEXT: "end":
+// CHECK-NEXT: "id":
+// CHECK-NEXT: "type": "CharacterLiteral"
+// CHECK-NEXT: }
+// CHECK: ]
+// CHECK: "type": "VarDecl",
+char nl = '\n';
+
+// CHECK: "value": "abc \n\t\u0000\u001f\u0123 \ub370\ubc15"
+char s[] = "abc \n\t\0\x1f\u0123 데박";
+

Modified: cfe/trunk/test/lit.cfg
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/lit.cfg?rev=311199&r1=311198&r2=311199&view=diff
==============================================================================
--- cfe/trunk/test/lit.cfg (original)
+++ cfe/trunk/test/lit.cfg Fri Aug 18 14:26:13 2017
@@ -276,6 +276,7 @@ config.substitutions.append( ('%test_deb
 config.substitutions.append( ('%itanium_abi_triple', makeItaniumABITriple(config.target_triple)) )
 config.substitutions.append( ('%ms_abi_triple', makeMSABITriple(config.target_triple)) )
 config.substitutions.append( ('%resource_dir', getClangBuiltinIncludeDir(config.clang)) )
+config.substitutions.append( ('%python', config.python_executable) )
 
 # The host triple might not be set, at least if we're compiling clang from
 # an already installed llvm.

Modified: cfe/trunk/test/lit.site.cfg.in
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/lit.site.cfg.in?rev=311199&r1=311198&r2=311199&view=diff
==============================================================================
--- cfe/trunk/test/lit.site.cfg.in (original)
+++ cfe/trunk/test/lit.site.cfg.in Fri Aug 18 14:26:13 2017
@@ -25,6 +25,7 @@ config.enable_shared = @ENABLE_SHARED@
 config.enable_backtrace = @ENABLE_BACKTRACES@
 config.host_arch = "@HOST_ARCH@"
 config.enable_abi_breaking_checks = "@LLVM_ENABLE_ABI_BREAKING_CHECKS@"
+config.python_executable = "@PYTHON_EXECUTABLE@"
 
 # Support substitution of the tools and libs dirs with user parameters. This is
 # used when we can't determine the tool dir at configuration time.

Modified: cfe/trunk/tools/clang-diff/ClangDiff.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/clang-diff/ClangDiff.cpp?rev=311199&r1=311198&r2=311199&view=diff
==============================================================================
--- cfe/trunk/tools/clang-diff/ClangDiff.cpp (original)
+++ cfe/trunk/tools/clang-diff/ClangDiff.cpp Fri Aug 18 14:26:13 2017
@@ -94,6 +94,65 @@ getAST(const std::unique_ptr<Compilation
   return std::move(ASTs[0]);
 }
 
+static char hexdigit(int N) { return N &= 0xf, N + (N < 10 ? '0' : 'a' - 10); }
+
+static void printJsonString(raw_ostream &OS, const StringRef Str) {
+  for (char C : Str) {
+    switch (C) {
+    case '"':
+      OS << R"(\")";
+      break;
+    case '\\':
+      OS << R"(\\)";
+      break;
+    case '\n':
+      OS << R"(\n)";
+      break;
+    case '\t':
+      OS << R"(\t)";
+      break;
+    default:
+      if ('\x00' <= C && C <= '\x1f') {
+        OS << R"(\u00)" << hexdigit(C >> 4) << hexdigit(C);
+      } else {
+        OS << C;
+      }
+    }
+  }
+}
+
+static void printNodeAttributes(raw_ostream &OS, diff::SyntaxTree &Tree,
+                                diff::NodeId Id) {
+  const diff::Node &N = Tree.getNode(Id);
+  OS << R"("id":)" << int(Id);
+  OS << R"(,"type":")" << N.getTypeLabel() << '"';
+  auto Offsets = Tree.getSourceRangeOffsets(N);
+  OS << R"(,"begin":)" << Offsets.first;
+  OS << R"(,"end":)" << Offsets.second;
+  std::string Value = Tree.getNodeValue(N.ASTNode);
+  if (!Value.empty()) {
+    OS << R"(,"value":")";
+    printJsonString(OS, Value);
+    OS << '"';
+  }
+}
+
+static void printNodeAsJson(raw_ostream &OS, diff::SyntaxTree &Tree,
+                            diff::NodeId Id) {
+  const diff::Node &N = Tree.getNode(Id);
+  OS << "{";
+  printNodeAttributes(OS, Tree, Id);
+  OS << R"(,"children":[)";
+  if (N.Children.size() > 0) {
+    printNodeAsJson(OS, Tree, N.Children[0]);
+    for (size_t I = 1, E = N.Children.size(); I < E; ++I) {
+      OS << ",";
+      printNodeAsJson(OS, Tree, N.Children[I]);
+    }
+  }
+  OS << "]}";
+}
+
 int main(int argc, const char **argv) {
   std::string ErrorMessage;
   std::unique_ptr<CompilationDatabase> CommonCompilations =
@@ -117,7 +176,11 @@ int main(int argc, const char **argv) {
     if (!AST)
       return 1;
     diff::SyntaxTree Tree(AST->getASTContext());
-    Tree.printAsJson(llvm::outs());
+    llvm::outs() << R"({"filename":")";
+    printJsonString(llvm::outs(), SourcePath);
+    llvm::outs() << R"(","root":)";
+    printNodeAsJson(llvm::outs(), Tree, Tree.getRootId());
+    llvm::outs() << "}\n";
     return 0;
   }
 




More information about the cfe-commits mailing list