[clang-tools-extra] r320694 - [clangd] Construct SymbolSlab from YAML format.

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Thu Dec 14 04:17:14 PST 2017


Author: hokein
Date: Thu Dec 14 04:17:14 2017
New Revision: 320694

URL: http://llvm.org/viewvc/llvm-project?rev=320694&view=rev
Log:
[clangd] Construct SymbolSlab from YAML format.

Summary: This will be used together with D40548 for the global index source (experimental).

Reviewers: sammccall

Reviewed By: sammccall

Subscribers: klimek, mgorny, ilya-biryukov, cfe-commits, ioeric

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

Added:
    clang-tools-extra/trunk/clangd/index/SymbolYAML.cpp
    clang-tools-extra/trunk/clangd/index/SymbolYAML.h
Modified:
    clang-tools-extra/trunk/clangd/CMakeLists.txt
    clang-tools-extra/trunk/clangd/index/Index.cpp
    clang-tools-extra/trunk/clangd/index/Index.h
    clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp

Modified: clang-tools-extra/trunk/clangd/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CMakeLists.txt?rev=320694&r1=320693&r2=320694&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clangd/CMakeLists.txt Thu Dec 14 04:17:14 2017
@@ -22,6 +22,7 @@ add_clang_library(clangDaemon
   index/MemIndex.cpp
   index/Index.cpp
   index/SymbolCollector.cpp
+  index/SymbolYAML.cpp
 
   LINK_LIBS
   clangAST

Modified: clang-tools-extra/trunk/clangd/index/Index.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Index.cpp?rev=320694&r1=320693&r2=320694&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Index.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/Index.cpp Thu Dec 14 04:17:14 2017
@@ -10,18 +10,24 @@
 #include "Index.h"
 
 #include "llvm/Support/SHA1.h"
+#include "llvm/ADT/StringExtras.h"
 
 namespace clang {
 namespace clangd {
 
-namespace {
-ArrayRef<uint8_t> toArrayRef(StringRef S) {
-  return {reinterpret_cast<const uint8_t *>(S.data()), S.size()};
+SymbolID::SymbolID(llvm::StringRef USR)
+    : HashValue(llvm::SHA1::hash(arrayRefFromStringRef(USR))) {}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolID &ID) {
+  OS << toHex(llvm::toStringRef(ID.HashValue));
+  return OS;
 }
-} // namespace
 
-SymbolID::SymbolID(llvm::StringRef USR)
-    : HashValue(llvm::SHA1::hash(toArrayRef(USR))) {}
+void operator>>(llvm::StringRef Str, SymbolID &ID) {
+  std::string HexString = fromHex(Str);
+  assert(HexString.size() == 20);
+  std::copy(HexString.begin(), HexString.end(), ID.HashValue.begin());
+}
 
 SymbolSlab::const_iterator SymbolSlab::begin() const { return Symbols.begin(); }
 

Modified: clang-tools-extra/trunk/clangd/index/Index.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Index.h?rev=320694&r1=320693&r2=320694&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Index.h (original)
+++ clang-tools-extra/trunk/clangd/index/Index.h Thu Dec 14 04:17:14 2017
@@ -54,10 +54,22 @@ private:
   friend llvm::hash_code hash_value(const SymbolID &ID) {
     return hash_value(ArrayRef<uint8_t>(ID.HashValue));
   }
+  friend llvm::raw_ostream &operator<<(llvm::raw_ostream &OS,
+                                       const SymbolID &ID);
+  friend void operator>>(llvm::StringRef Str, SymbolID &ID);
 
   std::array<uint8_t, 20> HashValue;
 };
 
+// Write SymbolID into the given stream. SymbolID is encoded as a 40-bytes
+// hex string.
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const SymbolID &ID);
+
+// Construct SymbolID from a hex string.
+// The HexStr is required to be a 40-bytes hex string, which is encoded from the
+// "<<" operator.
+void operator>>(llvm::StringRef HexStr, SymbolID &ID);
+
 // The class presents a C++ symbol, e.g. class, function.
 //
 // FIXME: instead of having own copy fields for each symbol, we can share

Added: clang-tools-extra/trunk/clangd/index/SymbolYAML.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/SymbolYAML.cpp?rev=320694&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/index/SymbolYAML.cpp (added)
+++ clang-tools-extra/trunk/clangd/index/SymbolYAML.cpp Thu Dec 14 04:17:14 2017
@@ -0,0 +1,148 @@
+//===--- SymbolYAML.cpp ------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolYAML.h"
+
+#include "Index.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Errc.h"
+
+LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(clang::clangd::Symbol)
+
+namespace llvm {
+namespace yaml {
+
+using clang::clangd::Symbol;
+using clang::clangd::SymbolID;
+using clang::clangd::SymbolLocation;
+using clang::index::SymbolInfo;
+using clang::index::SymbolLanguage;
+using clang::index::SymbolKind;
+
+// Helper to (de)serialize the SymbolID. We serialize it as a hex string.
+struct NormalizedSymbolID {
+  NormalizedSymbolID(IO &) {}
+  NormalizedSymbolID(IO &, const SymbolID& ID) {
+    llvm::raw_string_ostream OS(HexString);
+    OS << ID;
+  }
+
+  SymbolID denormalize(IO&) {
+    SymbolID ID;
+    HexString >> ID;
+    return ID;
+  }
+
+  std::string HexString;
+};
+
+template <> struct MappingTraits<SymbolLocation> {
+  static void mapping(IO &IO, SymbolLocation &Value) {
+    IO.mapRequired("StartOffset", Value.StartOffset);
+    IO.mapRequired("EndOffset", Value.EndOffset);
+    IO.mapRequired("FilePath", Value.FilePath);
+  }
+};
+
+template <> struct MappingTraits<SymbolInfo> {
+  static void mapping(IO &io, SymbolInfo &SymInfo) {
+    // FIXME: expose other fields?
+    io.mapRequired("Kind", SymInfo.Kind);
+    io.mapRequired("Lang", SymInfo.Lang);
+  }
+};
+
+template<> struct MappingTraits<Symbol> {
+  static void mapping(IO &IO, Symbol &Sym) {
+    MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(
+        IO, Sym.ID);
+    IO.mapRequired("ID", NSymbolID->HexString);
+    IO.mapRequired("QualifiedName", Sym.QualifiedName);
+    IO.mapRequired("SymInfo", Sym.SymInfo);
+    IO.mapRequired("CanonicalDeclaration", Sym.CanonicalDeclaration);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<SymbolLanguage> {
+  static void enumeration(IO &IO, SymbolLanguage &Value) {
+    IO.enumCase(Value, "C", SymbolLanguage::C);
+    IO.enumCase(Value, "Cpp", SymbolLanguage::CXX);
+    IO.enumCase(Value, "ObjC", SymbolLanguage::ObjC);
+    IO.enumCase(Value, "Swift", SymbolLanguage::Swift);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<SymbolKind> {
+  static void enumeration(IO &IO, SymbolKind &Value) {
+#define DEFINE_ENUM(name) IO.enumCase(Value, #name, SymbolKind::name)
+
+    DEFINE_ENUM(Unknown);
+    DEFINE_ENUM(Function);
+    DEFINE_ENUM(Module);
+    DEFINE_ENUM(Namespace);
+    DEFINE_ENUM(NamespaceAlias);
+    DEFINE_ENUM(Macro);
+    DEFINE_ENUM(Enum);
+    DEFINE_ENUM(Struct);
+    DEFINE_ENUM(Class);
+    DEFINE_ENUM(Protocol);
+    DEFINE_ENUM(Extension);
+    DEFINE_ENUM(Union);
+    DEFINE_ENUM(TypeAlias);
+    DEFINE_ENUM(Function);
+    DEFINE_ENUM(Variable);
+    DEFINE_ENUM(Field);
+    DEFINE_ENUM(EnumConstant);
+    DEFINE_ENUM(InstanceMethod);
+    DEFINE_ENUM(ClassMethod);
+    DEFINE_ENUM(StaticMethod);
+    DEFINE_ENUM(InstanceProperty);
+    DEFINE_ENUM(ClassProperty);
+    DEFINE_ENUM(StaticProperty);
+    DEFINE_ENUM(Constructor);
+    DEFINE_ENUM(Destructor);
+    DEFINE_ENUM(ConversionFunction);
+    DEFINE_ENUM(Parameter);
+    DEFINE_ENUM(Using);
+
+#undef DEFINE_ENUM
+  }
+};
+
+} // namespace yaml
+} // namespace llvm
+
+namespace clang {
+namespace clangd {
+
+SymbolSlab SymbolFromYAML(llvm::StringRef YAMLContent) {
+  std::vector<Symbol> S;
+  llvm::yaml::Input Yin(YAMLContent);
+  Yin >> S;
+  SymbolSlab Syms;
+  for (auto& Sym : S)
+    Syms.insert(std::move(Sym));
+  return Syms;
+}
+
+std::string SymbolToYAML(const SymbolSlab& Symbols) {
+  std::string Str;
+  llvm::raw_string_ostream OS(Str);
+  llvm::yaml::Output Yout(OS);
+  for (auto &Pair : Symbols) {
+    Symbol MutableSymbol = Pair.second;
+    Yout<< MutableSymbol;
+  }
+  return OS.str();
+}
+
+} // namespace clangd
+} // namespace clang

Added: clang-tools-extra/trunk/clangd/index/SymbolYAML.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/SymbolYAML.h?rev=320694&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/index/SymbolYAML.h (added)
+++ clang-tools-extra/trunk/clangd/index/SymbolYAML.h Thu Dec 14 04:17:14 2017
@@ -0,0 +1,37 @@
+//===--- SymbolYAML.h --------------------------------------------*- C++-*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// SymbolYAML provides facilities to convert Symbol to YAML, and vice versa.
+// The YAML format of Symbol is designed for simplicity and experiment, but
+// isn't a suitable/efficient store.
+//
+// This is for **experimental** only. Don't use it in the production code.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_FROM_YAML_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_FROM_YAML_H
+
+#include "Index.h"
+#include "llvm/Support/Error.h"
+
+namespace clang {
+namespace clangd {
+
+// Read symbols from a YAML-format string.
+SymbolSlab SymbolFromYAML(llvm::StringRef YAMLContent);
+
+// Convert symbols to a YAML-format string.
+// The YAML result is safe to concatenate if you have multiple symbol slabs.
+std::string SymbolToYAML(const SymbolSlab& Symbols);
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_FROM_YAML_H

Modified: clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp?rev=320694&r1=320693&r2=320694&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp (original)
+++ clang-tools-extra/trunk/unittests/clangd/SymbolCollectorTests.cpp Thu Dec 14 04:17:14 2017
@@ -8,6 +8,8 @@
 //===----------------------------------------------------------------------===//
 
 #include "index/SymbolCollector.h"
+#include "index/SymbolYAML.h"
+#include "clang/Index/IndexingAction.h"
 #include "clang/Basic/FileManager.h"
 #include "clang/Basic/FileSystemOptions.h"
 #include "clang/Basic/VirtualFileSystem.h"
@@ -105,6 +107,49 @@ TEST_F(SymbolCollectorTest, CollectSymbo
                                             QName("f1"), QName("f2")));
 }
 
+TEST_F(SymbolCollectorTest, YAMLConversions) {
+  const std::string YAML1 = R"(
+---
+ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF856
+QualifiedName:   'clang::Foo1'
+SymInfo:
+  Kind:            Function
+  Lang:            Cpp
+CanonicalDeclaration:
+  StartOffset:     0
+  EndOffset:       1
+  FilePath:        /path/foo.h
+...
+)";
+  const std::string YAML2 = R"(
+---
+ID: 057557CEBF6E6B2DD437FBF60CC58F352D1DF858
+QualifiedName:   'clang::Foo2'
+SymInfo:
+  Kind:            Function
+  Lang:            Cpp
+CanonicalDeclaration:
+  StartOffset:     10
+  EndOffset:       12
+  FilePath:        /path/foo.h
+...
+)";
+
+  auto Symbols1 = SymbolFromYAML(YAML1);
+  EXPECT_THAT(Symbols1,
+              UnorderedElementsAre(QName("clang::Foo1")));
+  auto Symbols2 = SymbolFromYAML(YAML2);
+  EXPECT_THAT(Symbols2,
+              UnorderedElementsAre(QName("clang::Foo2")));
+
+  std::string ConcatenatedYAML =
+      SymbolToYAML(Symbols1) + SymbolToYAML(Symbols2);
+  auto ConcatenatedSymbols = SymbolFromYAML(ConcatenatedYAML);
+  EXPECT_THAT(ConcatenatedSymbols,
+              UnorderedElementsAre(QName("clang::Foo1"),
+                                   QName("clang::Foo2")));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang




More information about the cfe-commits mailing list