[clang-tools-extra] r355088 - Moved Symbol into its own header and implementation file

Dmitri Gribenko via cfe-commits cfe-commits at lists.llvm.org
Thu Feb 28 05:23:04 PST 2019


Author: gribozavr
Date: Thu Feb 28 05:23:03 2019
New Revision: 355088

URL: http://llvm.org/viewvc/llvm-project?rev=355088&view=rev
Log:
Moved Symbol into its own header and implementation file

Reviewers: ioeric

Subscribers: mgorny, jkorous, arphaman, kadircet, jdoerfert, cfe-commits

Tags: #clang

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

Added:
    clang-tools-extra/trunk/clangd/index/Symbol.cpp
    clang-tools-extra/trunk/clangd/index/Symbol.h
Modified:
    clang-tools-extra/trunk/clangd/CMakeLists.txt
    clang-tools-extra/trunk/clangd/CodeComplete.cpp
    clang-tools-extra/trunk/clangd/CodeComplete.h
    clang-tools-extra/trunk/clangd/Headers.h
    clang-tools-extra/trunk/clangd/IncludeFixer.cpp
    clang-tools-extra/trunk/clangd/IncludeFixer.h
    clang-tools-extra/trunk/clangd/index/Background.cpp
    clang-tools-extra/trunk/clangd/index/FileIndex.h
    clang-tools-extra/trunk/clangd/index/Index.cpp
    clang-tools-extra/trunk/clangd/index/Index.h
    clang-tools-extra/trunk/clangd/index/Merge.cpp
    clang-tools-extra/trunk/clangd/index/Serialization.h

Modified: clang-tools-extra/trunk/clangd/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CMakeLists.txt?rev=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/clangd/CMakeLists.txt Thu Feb 28 05:23:03 2019
@@ -63,6 +63,7 @@ add_clang_library(clangDaemon
   index/MemIndex.cpp
   index/Merge.cpp
   index/Serialization.cpp
+  index/Symbol.cpp
   index/SymbolCollector.cpp
   index/SymbolID.cpp
   index/SymbolLocation.cpp

Modified: clang-tools-extra/trunk/clangd/CodeComplete.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.cpp?rev=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CodeComplete.cpp (original)
+++ clang-tools-extra/trunk/clangd/CodeComplete.cpp Thu Feb 28 05:23:03 2019
@@ -34,6 +34,7 @@
 #include "Trace.h"
 #include "URI.h"
 #include "index/Index.h"
+#include "index/Symbol.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/Basic/LangOptions.h"

Modified: clang-tools-extra/trunk/clangd/CodeComplete.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/CodeComplete.h?rev=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/CodeComplete.h (original)
+++ clang-tools-extra/trunk/clangd/CodeComplete.h Thu Feb 28 05:23:03 2019
@@ -21,6 +21,7 @@
 #include "Path.h"
 #include "Protocol.h"
 #include "index/Index.h"
+#include "index/Symbol.h"
 #include "index/SymbolOrigin.h"
 #include "clang/Frontend/PrecompiledPreamble.h"
 #include "clang/Sema/CodeCompleteConsumer.h"

Modified: clang-tools-extra/trunk/clangd/Headers.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/Headers.h?rev=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/Headers.h (original)
+++ clang-tools-extra/trunk/clangd/Headers.h Thu Feb 28 05:23:03 2019
@@ -12,7 +12,7 @@
 #include "Path.h"
 #include "Protocol.h"
 #include "SourceCode.h"
-#include "index/Index.h"
+#include "index/Symbol.h"
 #include "clang/Format/Format.h"
 #include "clang/Lex/HeaderSearch.h"
 #include "clang/Lex/PPCallbacks.h"

Modified: clang-tools-extra/trunk/clangd/IncludeFixer.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/IncludeFixer.cpp?rev=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/IncludeFixer.cpp (original)
+++ clang-tools-extra/trunk/clangd/IncludeFixer.cpp Thu Feb 28 05:23:03 2019
@@ -13,6 +13,7 @@
 #include "SourceCode.h"
 #include "Trace.h"
 #include "index/Index.h"
+#include "index/Symbol.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclBase.h"
 #include "clang/AST/NestedNameSpecifier.h"

Modified: clang-tools-extra/trunk/clangd/IncludeFixer.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/IncludeFixer.h?rev=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/IncludeFixer.h (original)
+++ clang-tools-extra/trunk/clangd/IncludeFixer.h Thu Feb 28 05:23:03 2019
@@ -12,6 +12,7 @@
 #include "Diagnostics.h"
 #include "Headers.h"
 #include "index/Index.h"
+#include "index/Symbol.h"
 #include "clang/AST/Type.h"
 #include "clang/Basic/Diagnostic.h"
 #include "clang/Basic/SourceLocation.h"

Modified: clang-tools-extra/trunk/clangd/index/Background.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Background.cpp?rev=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Background.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/Background.cpp Thu Feb 28 05:23:03 2019
@@ -11,6 +11,7 @@
 #include "Compiler.h"
 #include "Logger.h"
 #include "SourceCode.h"
+#include "Symbol.h"
 #include "Threading.h"
 #include "Trace.h"
 #include "URI.h"

Modified: clang-tools-extra/trunk/clangd/index/FileIndex.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/FileIndex.h?rev=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/FileIndex.h (original)
+++ clang-tools-extra/trunk/clangd/index/FileIndex.h Thu Feb 28 05:23:03 2019
@@ -20,6 +20,7 @@
 #include "MemIndex.h"
 #include "Merge.h"
 #include "index/CanonicalIncludes.h"
+#include "index/Symbol.h"
 #include "clang/Lex/Preprocessor.h"
 #include <memory>
 

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=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Index.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/Index.cpp Thu Feb 28 05:23:03 2019
@@ -16,67 +16,6 @@
 namespace clang {
 namespace clangd {
 
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Symbol::SymbolFlag F) {
-  if (F == Symbol::None)
-    return OS << "None";
-  std::string S;
-  if (F & Symbol::Deprecated)
-    S += "deprecated|";
-  if (F & Symbol::IndexedForCodeCompletion)
-    S += "completion|";
-  return OS << llvm::StringRef(S).rtrim('|');
-}
-
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) {
-  return OS << S.Scope << S.Name;
-}
-
-float quality(const Symbol &S) {
-  // This avoids a sharp gradient for tail symbols, and also neatly avoids the
-  // question of whether 0 references means a bad symbol or missing data.
-  if (S.References < 3)
-    return 1;
-  return std::log(S.References);
-}
-
-SymbolSlab::const_iterator SymbolSlab::find(const SymbolID &ID) const {
-  auto It = std::lower_bound(
-      Symbols.begin(), Symbols.end(), ID,
-      [](const Symbol &S, const SymbolID &I) { return S.ID < I; });
-  if (It != Symbols.end() && It->ID == ID)
-    return It;
-  return Symbols.end();
-}
-
-// Copy the underlying data of the symbol into the owned arena.
-static void own(Symbol &S, llvm::UniqueStringSaver &Strings) {
-  visitStrings(S, [&](llvm::StringRef &V) { V = Strings.save(V); });
-}
-
-void SymbolSlab::Builder::insert(const Symbol &S) {
-  auto R = SymbolIndex.try_emplace(S.ID, Symbols.size());
-  if (R.second) {
-    Symbols.push_back(S);
-    own(Symbols.back(), UniqueStrings);
-  } else {
-    auto &Copy = Symbols[R.first->second] = S;
-    own(Copy, UniqueStrings);
-  }
-}
-
-SymbolSlab SymbolSlab::Builder::build() && {
-  Symbols = {Symbols.begin(), Symbols.end()}; // Force shrink-to-fit.
-  // Sort symbols so the slab can binary search over them.
-  llvm::sort(Symbols,
-             [](const Symbol &L, const Symbol &R) { return L.ID < R.ID; });
-  // We may have unused strings from overwritten symbols. Build a new arena.
-  llvm::BumpPtrAllocator NewArena;
-  llvm::UniqueStringSaver Strings(NewArena);
-  for (auto &S : Symbols)
-    own(S, Strings);
-  return SymbolSlab(std::move(NewArena), std::move(Symbols));
-}
-
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, RefKind K) {
   if (K == RefKind::Unknown)
     return OS << "Unknown";

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=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Index.h (original)
+++ clang-tools-extra/trunk/clangd/index/Index.h Thu Feb 28 05:23:03 2019
@@ -10,9 +10,9 @@
 #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_INDEX_H
 
 #include "ExpectedTypes.h"
+#include "Symbol.h"
 #include "SymbolID.h"
 #include "SymbolLocation.h"
-#include "SymbolOrigin.h"
 #include "clang/Index/IndexSymbol.h"
 #include "clang/Lex/Lexer.h"
 #include "llvm/ADT/DenseMap.h"
@@ -22,7 +22,6 @@
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/JSON.h"
-#include "llvm/Support/StringSaver.h"
 #include <array>
 #include <limits>
 #include <mutex>
@@ -32,207 +31,6 @@
 namespace clang {
 namespace clangd {
 
-// The class presents a C++ symbol, e.g. class, function.
-//
-// WARNING: Symbols do not own much of their underlying data - typically strings
-// are owned by a SymbolSlab. They should be treated as non-owning references.
-// Copies are shallow.
-// When adding new unowned data fields to Symbol, remember to update:
-//   - SymbolSlab::Builder in Index.cpp, to copy them to the slab's storage.
-//   - mergeSymbol in Merge.cpp, to properly combine two Symbols.
-//
-// A fully documented symbol can be split as:
-// size_type std::map<k, t>::count(const K& key) const
-// | Return  |     Scope     |Name|    Signature     |
-// We split up these components to allow display flexibility later.
-struct Symbol {
-  // The ID of the symbol.
-  SymbolID ID;
-  // The symbol information, like symbol kind.
-  index::SymbolInfo SymInfo;
-  // The unqualified name of the symbol, e.g. "bar" (for ns::bar).
-  llvm::StringRef Name;
-  // The containing namespace. e.g. "" (global), "ns::" (top-level namespace).
-  llvm::StringRef Scope;
-  // The location of the symbol's definition, if one was found.
-  // This just covers the symbol name (e.g. without class/function body).
-  SymbolLocation Definition;
-  // The location of the preferred declaration of the symbol.
-  // This just covers the symbol name.
-  // This may be the same as Definition.
-  //
-  // A C++ symbol may have multiple declarations, and we pick one to prefer.
-  //   * For classes, the canonical declaration should be the definition.
-  //   * For non-inline functions, the canonical declaration typically appears
-  //     in the ".h" file corresponding to the definition.
-  SymbolLocation CanonicalDeclaration;
-  // The number of translation units that reference this symbol from their main
-  // file. This number is only meaningful if aggregated in an index.
-  unsigned References = 0;
-  /// Where this symbol came from. Usually an index provides a constant value.
-  SymbolOrigin Origin = SymbolOrigin::Unknown;
-  /// A brief description of the symbol that can be appended in the completion
-  /// candidate list. For example, "(X x, Y y) const" is a function signature.
-  /// Only set when the symbol is indexed for completion.
-  llvm::StringRef Signature;
-  /// What to insert when completing this symbol, after the symbol name.
-  /// This is in LSP snippet syntax (e.g. "({$0})" for a no-args function).
-  /// (When snippets are disabled, the symbol name alone is used).
-  /// Only set when the symbol is indexed for completion.
-  llvm::StringRef CompletionSnippetSuffix;
-  /// Documentation including comment for the symbol declaration.
-  llvm::StringRef Documentation;
-  /// Type when this symbol is used in an expression. (Short display form).
-  /// e.g. return type of a function, or type of a variable.
-  /// Only set when the symbol is indexed for completion.
-  llvm::StringRef ReturnType;
-
-  /// Raw representation of the OpaqueType of the symbol, used for scoring
-  /// purposes.
-  /// Only set when the symbol is indexed for completion.
-  llvm::StringRef Type;
-
-  struct IncludeHeaderWithReferences {
-    IncludeHeaderWithReferences() = default;
-
-    IncludeHeaderWithReferences(llvm::StringRef IncludeHeader,
-                                unsigned References)
-        : IncludeHeader(IncludeHeader), References(References) {}
-
-    /// This can be either a URI of the header to be #include'd
-    /// for this symbol, or a literal header quoted with <> or "" that is
-    /// suitable to be included directly. When it is a URI, the exact #include
-    /// path needs to be calculated according to the URI scheme.
-    ///
-    /// Note that the include header is a canonical include for the symbol and
-    /// can be different from FileURI in the CanonicalDeclaration.
-    llvm::StringRef IncludeHeader = "";
-    /// The number of translation units that reference this symbol and include
-    /// this header. This number is only meaningful if aggregated in an index.
-    unsigned References = 0;
-  };
-  /// One Symbol can potentially be incuded via different headers.
-  ///   - If we haven't seen a definition, this covers all declarations.
-  ///   - If we have seen a definition, this covers declarations visible from
-  ///   any definition.
-  /// Only set when the symbol is indexed for completion.
-  llvm::SmallVector<IncludeHeaderWithReferences, 1> IncludeHeaders;
-
-  enum SymbolFlag : uint8_t {
-    None = 0,
-    /// Whether or not this symbol is meant to be used for the code completion.
-    /// See also isIndexedForCodeCompletion().
-    /// Note that we don't store completion information (signature, snippet,
-    /// type, inclues) if the symbol is not indexed for code completion.
-    IndexedForCodeCompletion = 1 << 0,
-    /// Indicates if the symbol is deprecated.
-    Deprecated = 1 << 1,
-    // Symbol is an implementation detail.
-    ImplementationDetail = 1 << 2,
-    // Symbol is visible to other files (not e.g. a static helper function).
-    VisibleOutsideFile = 1 << 3,
-  };
-
-  SymbolFlag Flags = SymbolFlag::None;
-  /// FIXME: also add deprecation message and fixit?
-};
-inline Symbol::SymbolFlag  operator|(Symbol::SymbolFlag A, Symbol::SymbolFlag  B) {
-  return static_cast<Symbol::SymbolFlag>(static_cast<uint8_t>(A) |
-                                         static_cast<uint8_t>(B));
-}
-inline Symbol::SymbolFlag &operator|=(Symbol::SymbolFlag &A, Symbol::SymbolFlag B) {
-  return A = A | B;
-}
-llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S);
-raw_ostream &operator<<(raw_ostream &, Symbol::SymbolFlag);
-
-// Invokes Callback with each StringRef& contained in the Symbol.
-// Useful for deduplicating backing strings.
-template <typename Callback> void visitStrings(Symbol &S, const Callback &CB) {
-  CB(S.Name);
-  CB(S.Scope);
-  CB(S.Signature);
-  CB(S.CompletionSnippetSuffix);
-  CB(S.Documentation);
-  CB(S.ReturnType);
-  CB(S.Type);
-  auto RawCharPointerCB = [&CB](const char *&P) {
-    llvm::StringRef S(P);
-    CB(S);
-    assert(!S.data()[S.size()] && "Visited StringRef must be null-terminated");
-    P = S.data();
-  };
-  RawCharPointerCB(S.CanonicalDeclaration.FileURI);
-  RawCharPointerCB(S.Definition.FileURI);
-
-  for (auto &Include : S.IncludeHeaders)
-    CB(Include.IncludeHeader);
-}
-
-// Computes query-independent quality score for a Symbol.
-// This currently falls in the range [1, ln(#indexed documents)].
-// FIXME: this should probably be split into symbol -> signals
-//        and signals -> score, so it can be reused for Sema completions.
-float quality(const Symbol &S);
-
-// An immutable symbol container that stores a set of symbols.
-// The container will maintain the lifetime of the symbols.
-class SymbolSlab {
-public:
-  using const_iterator = std::vector<Symbol>::const_iterator;
-  using iterator = const_iterator;
-  using value_type = Symbol;
-
-  SymbolSlab() = default;
-
-  const_iterator begin() const { return Symbols.begin(); }
-  const_iterator end() const { return Symbols.end(); }
-  const_iterator find(const SymbolID &SymID) const;
-
-  size_t size() const { return Symbols.size(); }
-  bool empty() const { return Symbols.empty(); }
-  // Estimates the total memory usage.
-  size_t bytes() const {
-    return sizeof(*this) + Arena.getTotalMemory() +
-           Symbols.capacity() * sizeof(Symbol);
-  }
-
-  // SymbolSlab::Builder is a mutable container that can 'freeze' to SymbolSlab.
-  // The frozen SymbolSlab will use less memory.
-  class Builder {
-  public:
-    Builder() : UniqueStrings(Arena) {}
-
-    // Adds a symbol, overwriting any existing one with the same ID.
-    // This is a deep copy: underlying strings will be owned by the slab.
-    void insert(const Symbol &S);
-
-    // Returns the symbol with an ID, if it exists. Valid until next insert().
-    const Symbol *find(const SymbolID &ID) {
-      auto I = SymbolIndex.find(ID);
-      return I == SymbolIndex.end() ? nullptr : &Symbols[I->second];
-    }
-
-    // Consumes the builder to finalize the slab.
-    SymbolSlab build() &&;
-
-  private:
-    llvm::BumpPtrAllocator Arena;
-    // Intern table for strings. Contents are on the arena.
-    llvm::UniqueStringSaver UniqueStrings;
-    std::vector<Symbol> Symbols;
-    // Values are indices into Symbols vector.
-    llvm::DenseMap<SymbolID, size_t> SymbolIndex;
-  };
-
-private:
-  SymbolSlab(llvm::BumpPtrAllocator Arena, std::vector<Symbol> Symbols)
-      : Arena(std::move(Arena)), Symbols(std::move(Symbols)) {}
-
-  llvm::BumpPtrAllocator Arena; // Owns Symbol data that the Symbols do not.
-  std::vector<Symbol> Symbols;  // Sorted by SymbolID to allow lookup.
-};
-
 // Describes the kind of a cross-reference.
 //
 // This is a bitfield which can be combined from different kinds.

Modified: clang-tools-extra/trunk/clangd/index/Merge.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Merge.cpp?rev=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Merge.cpp (original)
+++ clang-tools-extra/trunk/clangd/index/Merge.cpp Thu Feb 28 05:23:03 2019
@@ -9,6 +9,7 @@
 #include "Merge.h"
 #include "Logger.h"
 #include "Trace.h"
+#include "index/Symbol.h"
 #include "index/SymbolLocation.h"
 #include "index/SymbolOrigin.h"
 #include "llvm/ADT/STLExtras.h"

Modified: clang-tools-extra/trunk/clangd/index/Serialization.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Serialization.h?rev=355088&r1=355087&r2=355088&view=diff
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Serialization.h (original)
+++ clang-tools-extra/trunk/clangd/index/Serialization.h Thu Feb 28 05:23:03 2019
@@ -26,6 +26,7 @@
 
 #include "Headers.h"
 #include "Index.h"
+#include "index/Symbol.h"
 #include "llvm/Support/Error.h"
 
 namespace clang {

Added: clang-tools-extra/trunk/clangd/index/Symbol.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Symbol.cpp?rev=355088&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Symbol.cpp (added)
+++ clang-tools-extra/trunk/clangd/index/Symbol.cpp Thu Feb 28 05:23:03 2019
@@ -0,0 +1,76 @@
+//===--- Symbol.cpp ----------------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "Symbol.h"
+
+namespace clang {
+namespace clangd {
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Symbol::SymbolFlag F) {
+  if (F == Symbol::None)
+    return OS << "None";
+  std::string S;
+  if (F & Symbol::Deprecated)
+    S += "deprecated|";
+  if (F & Symbol::IndexedForCodeCompletion)
+    S += "completion|";
+  return OS << llvm::StringRef(S).rtrim('|');
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S) {
+  return OS << S.Scope << S.Name;
+}
+
+float quality(const Symbol &S) {
+  // This avoids a sharp gradient for tail symbols, and also neatly avoids the
+  // question of whether 0 references means a bad symbol or missing data.
+  if (S.References < 3)
+    return 1;
+  return std::log(S.References);
+}
+
+SymbolSlab::const_iterator SymbolSlab::find(const SymbolID &ID) const {
+  auto It = std::lower_bound(
+      Symbols.begin(), Symbols.end(), ID,
+      [](const Symbol &S, const SymbolID &I) { return S.ID < I; });
+  if (It != Symbols.end() && It->ID == ID)
+    return It;
+  return Symbols.end();
+}
+
+// Copy the underlying data of the symbol into the owned arena.
+static void own(Symbol &S, llvm::UniqueStringSaver &Strings) {
+  visitStrings(S, [&](llvm::StringRef &V) { V = Strings.save(V); });
+}
+
+void SymbolSlab::Builder::insert(const Symbol &S) {
+  auto R = SymbolIndex.try_emplace(S.ID, Symbols.size());
+  if (R.second) {
+    Symbols.push_back(S);
+    own(Symbols.back(), UniqueStrings);
+  } else {
+    auto &Copy = Symbols[R.first->second] = S;
+    own(Copy, UniqueStrings);
+  }
+}
+
+SymbolSlab SymbolSlab::Builder::build() && {
+  Symbols = {Symbols.begin(), Symbols.end()}; // Force shrink-to-fit.
+  // Sort symbols so the slab can binary search over them.
+  llvm::sort(Symbols,
+             [](const Symbol &L, const Symbol &R) { return L.ID < R.ID; });
+  // We may have unused strings from overwritten symbols. Build a new arena.
+  llvm::BumpPtrAllocator NewArena;
+  llvm::UniqueStringSaver Strings(NewArena);
+  for (auto &S : Symbols)
+    own(S, Strings);
+  return SymbolSlab(std::move(NewArena), std::move(Symbols));
+}
+
+} // namespace clangd
+} // namespace clang

Added: clang-tools-extra/trunk/clangd/index/Symbol.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/clangd/index/Symbol.h?rev=355088&view=auto
==============================================================================
--- clang-tools-extra/trunk/clangd/index/Symbol.h (added)
+++ clang-tools-extra/trunk/clangd/index/Symbol.h Thu Feb 28 05:23:03 2019
@@ -0,0 +1,231 @@
+//===--- Symbol.h ------------------------------------------------*- C++-*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_H
+
+#include "SymbolID.h"
+#include "SymbolLocation.h"
+#include "SymbolOrigin.h"
+#include "clang/Index/IndexSymbol.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/StringSaver.h"
+
+namespace clang {
+namespace clangd {
+
+/// The class presents a C++ symbol, e.g. class, function.
+///
+/// WARNING: Symbols do not own much of their underlying data - typically
+/// strings are owned by a SymbolSlab. They should be treated as non-owning
+/// references. Copies are shallow.
+///
+/// When adding new unowned data fields to Symbol, remember to update:
+///   - SymbolSlab::Builder in Index.cpp, to copy them to the slab's storage.
+///   - mergeSymbol in Merge.cpp, to properly combine two Symbols.
+///
+/// A fully documented symbol can be split as:
+/// size_type std::map<k, t>::count(const K& key) const
+/// | Return  |     Scope     |Name|    Signature     |
+/// We split up these components to allow display flexibility later.
+struct Symbol {
+  /// The ID of the symbol.
+  SymbolID ID;
+  /// The symbol information, like symbol kind.
+  index::SymbolInfo SymInfo;
+  /// The unqualified name of the symbol, e.g. "bar" (for ns::bar).
+  llvm::StringRef Name;
+  /// The containing namespace. e.g. "" (global), "ns::" (top-level namespace).
+  llvm::StringRef Scope;
+  /// The location of the symbol's definition, if one was found.
+  /// This just covers the symbol name (e.g. without class/function body).
+  SymbolLocation Definition;
+  /// The location of the preferred declaration of the symbol.
+  /// This just covers the symbol name.
+  /// This may be the same as Definition.
+  ///
+  /// A C++ symbol may have multiple declarations, and we pick one to prefer.
+  ///   * For classes, the canonical declaration should be the definition.
+  ///   * For non-inline functions, the canonical declaration typically appears
+  ///     in the ".h" file corresponding to the definition.
+  SymbolLocation CanonicalDeclaration;
+  /// The number of translation units that reference this symbol from their main
+  /// file. This number is only meaningful if aggregated in an index.
+  unsigned References = 0;
+  /// Where this symbol came from. Usually an index provides a constant value.
+  SymbolOrigin Origin = SymbolOrigin::Unknown;
+  /// A brief description of the symbol that can be appended in the completion
+  /// candidate list. For example, "(X x, Y y) const" is a function signature.
+  /// Only set when the symbol is indexed for completion.
+  llvm::StringRef Signature;
+  /// What to insert when completing this symbol, after the symbol name.
+  /// This is in LSP snippet syntax (e.g. "({$0})" for a no-args function).
+  /// (When snippets are disabled, the symbol name alone is used).
+  /// Only set when the symbol is indexed for completion.
+  llvm::StringRef CompletionSnippetSuffix;
+  /// Documentation including comment for the symbol declaration.
+  llvm::StringRef Documentation;
+  /// Type when this symbol is used in an expression. (Short display form).
+  /// e.g. return type of a function, or type of a variable.
+  /// Only set when the symbol is indexed for completion.
+  llvm::StringRef ReturnType;
+
+  /// Raw representation of the OpaqueType of the symbol, used for scoring
+  /// purposes.
+  /// Only set when the symbol is indexed for completion.
+  llvm::StringRef Type;
+
+  struct IncludeHeaderWithReferences {
+    IncludeHeaderWithReferences() = default;
+
+    IncludeHeaderWithReferences(llvm::StringRef IncludeHeader,
+                                unsigned References)
+        : IncludeHeader(IncludeHeader), References(References) {}
+
+    /// This can be either a URI of the header to be #include'd
+    /// for this symbol, or a literal header quoted with <> or "" that is
+    /// suitable to be included directly. When it is a URI, the exact #include
+    /// path needs to be calculated according to the URI scheme.
+    ///
+    /// Note that the include header is a canonical include for the symbol and
+    /// can be different from FileURI in the CanonicalDeclaration.
+    llvm::StringRef IncludeHeader = "";
+    /// The number of translation units that reference this symbol and include
+    /// this header. This number is only meaningful if aggregated in an index.
+    unsigned References = 0;
+  };
+  /// One Symbol can potentially be incuded via different headers.
+  ///   - If we haven't seen a definition, this covers all declarations.
+  ///   - If we have seen a definition, this covers declarations visible from
+  ///   any definition.
+  /// Only set when the symbol is indexed for completion.
+  llvm::SmallVector<IncludeHeaderWithReferences, 1> IncludeHeaders;
+
+  enum SymbolFlag : uint8_t {
+    None = 0,
+    /// Whether or not this symbol is meant to be used for the code completion.
+    /// See also isIndexedForCodeCompletion().
+    /// Note that we don't store completion information (signature, snippet,
+    /// type, inclues) if the symbol is not indexed for code completion.
+    IndexedForCodeCompletion = 1 << 0,
+    /// Indicates if the symbol is deprecated.
+    Deprecated = 1 << 1,
+    /// Symbol is an implementation detail.
+    ImplementationDetail = 1 << 2,
+    /// Symbol is visible to other files (not e.g. a static helper function).
+    VisibleOutsideFile = 1 << 3,
+  };
+
+  SymbolFlag Flags = SymbolFlag::None;
+  /// FIXME: also add deprecation message and fixit?
+};
+
+inline Symbol::SymbolFlag operator|(Symbol::SymbolFlag A,
+                                    Symbol::SymbolFlag B) {
+  return static_cast<Symbol::SymbolFlag>(static_cast<uint8_t>(A) |
+                                         static_cast<uint8_t>(B));
+}
+inline Symbol::SymbolFlag &operator|=(Symbol::SymbolFlag &A,
+                                      Symbol::SymbolFlag B) {
+  return A = A | B;
+}
+
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S);
+llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, Symbol::SymbolFlag);
+
+/// Invokes Callback with each StringRef& contained in the Symbol.
+/// Useful for deduplicating backing strings.
+template <typename Callback> void visitStrings(Symbol &S, const Callback &CB) {
+  CB(S.Name);
+  CB(S.Scope);
+  CB(S.Signature);
+  CB(S.CompletionSnippetSuffix);
+  CB(S.Documentation);
+  CB(S.ReturnType);
+  CB(S.Type);
+  auto RawCharPointerCB = [&CB](const char *&P) {
+    llvm::StringRef S(P);
+    CB(S);
+    assert(!S.data()[S.size()] && "Visited StringRef must be null-terminated");
+    P = S.data();
+  };
+  RawCharPointerCB(S.CanonicalDeclaration.FileURI);
+  RawCharPointerCB(S.Definition.FileURI);
+
+  for (auto &Include : S.IncludeHeaders)
+    CB(Include.IncludeHeader);
+}
+
+/// Computes query-independent quality score for a Symbol.
+/// This currently falls in the range [1, ln(#indexed documents)].
+/// FIXME: this should probably be split into symbol -> signals
+///        and signals -> score, so it can be reused for Sema completions.
+float quality(const Symbol &S);
+
+/// An immutable symbol container that stores a set of symbols.
+/// The container will maintain the lifetime of the symbols.
+class SymbolSlab {
+public:
+  using const_iterator = std::vector<Symbol>::const_iterator;
+  using iterator = const_iterator;
+  using value_type = Symbol;
+
+  SymbolSlab() = default;
+
+  const_iterator begin() const { return Symbols.begin(); }
+  const_iterator end() const { return Symbols.end(); }
+  const_iterator find(const SymbolID &SymID) const;
+
+  size_t size() const { return Symbols.size(); }
+  bool empty() const { return Symbols.empty(); }
+  // Estimates the total memory usage.
+  size_t bytes() const {
+    return sizeof(*this) + Arena.getTotalMemory() +
+           Symbols.capacity() * sizeof(Symbol);
+  }
+
+  /// SymbolSlab::Builder is a mutable container that can 'freeze' to
+  /// SymbolSlab. The frozen SymbolSlab will use less memory.
+  class Builder {
+  public:
+    Builder() : UniqueStrings(Arena) {}
+
+    /// Adds a symbol, overwriting any existing one with the same ID.
+    /// This is a deep copy: underlying strings will be owned by the slab.
+    void insert(const Symbol &S);
+
+    /// Returns the symbol with an ID, if it exists. Valid until next insert().
+    const Symbol *find(const SymbolID &ID) {
+      auto I = SymbolIndex.find(ID);
+      return I == SymbolIndex.end() ? nullptr : &Symbols[I->second];
+    }
+
+    /// Consumes the builder to finalize the slab.
+    SymbolSlab build() &&;
+
+  private:
+    llvm::BumpPtrAllocator Arena;
+    /// Intern table for strings. Contents are on the arena.
+    llvm::UniqueStringSaver UniqueStrings;
+    std::vector<Symbol> Symbols;
+    /// Values are indices into Symbols vector.
+    llvm::DenseMap<SymbolID, size_t> SymbolIndex;
+  };
+
+private:
+  SymbolSlab(llvm::BumpPtrAllocator Arena, std::vector<Symbol> Symbols)
+      : Arena(std::move(Arena)), Symbols(std::move(Symbols)) {}
+
+  llvm::BumpPtrAllocator Arena; // Owns Symbol data that the Symbols do not.
+  std::vector<Symbol> Symbols;  // Sorted by SymbolID to allow lookup.
+};
+
+} // namespace clangd
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_SYMBOL_H




More information about the cfe-commits mailing list