Index: clangd/CMakeLists.txt =================================================================== --- clangd/CMakeLists.txt +++ clangd/CMakeLists.txt @@ -21,6 +21,7 @@ Trace.cpp index/Index.cpp index/SymbolCollector.cpp + index/SymbolFromYAML.cpp LINK_LIBS clangAST Index: clangd/index/Index.h =================================================================== --- clangd/index/Index.h +++ clangd/index/Index.h @@ -14,6 +14,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/Hashing.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/YAMLTraits.h" #include #include @@ -53,6 +54,7 @@ friend llvm::hash_code hash_value(const SymbolID &ID) { return hash_value(ArrayRef(ID.HashValue)); } + friend struct llvm::yaml::MappingTraits; std::array HashValue; }; Index: clangd/index/SymbolFromYAML.h =================================================================== --- /dev/null +++ clangd/index/SymbolFromYAML.h @@ -0,0 +1,28 @@ +//===--- SymbolFromYAML.h ----------------------------------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#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. +std::string SymbolToYAML(const SymbolSlab& Symbols); + +} // namespace clangd +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_FROM_YAML_H Index: clangd/index/SymbolFromYAML.cpp =================================================================== --- /dev/null +++ clangd/index/SymbolFromYAML.cpp @@ -0,0 +1,154 @@ +//===--- SymbolFromYAML.cpp --------------------------------------*- C++-*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "SymbolFromYAML.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; + +// Helpers to (de)serialize the SymbolID underlying data as std::array is not +// supported in YAML I/O. +struct NPArray { + NPArray(IO &) {} + NPArray(IO &, std::array HashValue) { + Value = {HashValue.begin(), HashValue.end()}; + } + std::array denormalize(IO &) { + assert(Value.size() == 20); + std::array Result; + std::copy(Value.begin(), Value.end(), Result.begin()); + return Result; + } + + std::vector Value; +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, SymbolID &ID) { + MappingNormalization> NPArry( + IO, ID.HashValue); + IO.mapOptional("Value", NPArry->Value); + } +}; + +template <> struct MappingTraits { + 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 { + static void mapping(IO &io, SymbolInfo &SymInfo) { + // FIXME: expose other fields? + io.mapRequired("Kind", SymInfo.Kind); + io.mapRequired("Lang", SymInfo.Lang); + } +}; + +template<> struct MappingTraits { + static void mapping(IO &IO, Symbol &Sym) { + IO.mapRequired("ID", Sym.ID); + IO.mapRequired("QualifiedName", Sym.QualifiedName); + IO.mapRequired("SymInfo", Sym.SymInfo); + IO.mapRequired("CanonicalDeclaration", Sym.CanonicalDeclaration); + } +}; + +template <> struct ScalarEnumerationTraits { + 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 { + 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 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 Index: unittests/clangd/SymbolCollectorTests.cpp =================================================================== --- unittests/clangd/SymbolCollectorTests.cpp +++ unittests/clangd/SymbolCollectorTests.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "index/SymbolCollector.h" +#include "index/SymbolFromYAML.h" #include "clang/Index/IndexingAction.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/FileSystemOptions.h" @@ -103,6 +104,12 @@ runSymbolCollector(Header, Main); EXPECT_THAT(Symbols, UnorderedElementsAre(QName("Foo"), QName("Foo::f"), QName("f1"), QName("f2"))); + + std::string YAMLContent = SymbolToYAML(Symbols); + auto SymbolsReadFromYAML = SymbolFromYAML(YAMLContent); + EXPECT_THAT(SymbolsReadFromYAML, + UnorderedElementsAre(QName("Foo"), QName("Foo::f"), QName("f1"), + QName("f2"))); } } // namespace