ioeric updated this revision to Diff 164205.
ioeric marked an inline comment as done.
ioeric added a comment.

- Pack flags in Symbol.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D51724

Files:
  clangd/CodeComplete.cpp
  clangd/CodeComplete.h
  clangd/Protocol.cpp
  clangd/Protocol.h
  clangd/Quality.cpp
  clangd/index/Index.cpp
  clangd/index/Index.h
  clangd/index/MemIndex.cpp
  clangd/index/Serialization.cpp
  clangd/index/SymbolCollector.cpp
  clangd/index/SymbolYAML.cpp
  unittests/clangd/CodeCompleteTests.cpp
  unittests/clangd/QualityTests.cpp
  unittests/clangd/SerializationTests.cpp
  unittests/clangd/SymbolCollectorTests.cpp

Index: unittests/clangd/SymbolCollectorTests.cpp
===================================================================
--- unittests/clangd/SymbolCollectorTests.cpp
+++ unittests/clangd/SymbolCollectorTests.cpp
@@ -80,8 +80,9 @@
 }
 MATCHER_P(RefCount, R, "") { return int(arg.References) == R; }
 MATCHER_P(ForCodeCompletion, IsIndexedForCodeCompletion, "") {
-  return arg.IsIndexedForCodeCompletion == IsIndexedForCodeCompletion;
+  return arg.IsIndexedForCodeCompletion() == IsIndexedForCodeCompletion;
 }
+MATCHER(Deprecated, "") { return arg.Deprecated(); }
 MATCHER(RefRange, "") {
   const Ref &Pos = testing::get<0>(arg);
   const Range &Range = testing::get<1>(arg);
@@ -1014,6 +1015,17 @@
                                          DeclRange(Header.range("used")))));
 }
 
+TEST_F(SymbolCollectorTest, DeprecatedSymbols) {
+  const std::string Header = R"(
+    void TestClangc() __attribute__((deprecated("", "")));
+    void TestClangd();
+  )";
+  runSymbolCollector(Header, /**/ "");
+  EXPECT_THAT(Symbols, UnorderedElementsAre(
+                           AllOf(QName("TestClangc"), Deprecated()),
+                           AllOf(QName("TestClangd"), Not(Deprecated()))));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: unittests/clangd/SerializationTests.cpp
===================================================================
--- unittests/clangd/SerializationTests.cpp
+++ unittests/clangd/SerializationTests.cpp
@@ -35,7 +35,7 @@
   End:
     Line: 1
     Column: 1
-IsIndexedForCodeCompletion:    true
+Flags:    1
 Documentation:    'Foo doc'
 ReturnType:    'int'
 IncludeHeaders:
@@ -62,7 +62,7 @@
   End:
     Line: 1
     Column: 1
-IsIndexedForCodeCompletion:    false
+Flags:    2
 Signature:    '-sig'
 CompletionSnippetSuffix:    '-snippet'
 ...
@@ -82,7 +82,8 @@
   EXPECT_EQ(Sym1.Documentation, "Foo doc");
   EXPECT_EQ(Sym1.ReturnType, "int");
   EXPECT_EQ(Sym1.CanonicalDeclaration.FileURI, "file:///path/foo.h");
-  EXPECT_TRUE(Sym1.IsIndexedForCodeCompletion);
+  EXPECT_TRUE(Sym1.IsIndexedForCodeCompletion());
+  EXPECT_FALSE(Sym1.Deprecated());
   EXPECT_THAT(Sym1.IncludeHeaders,
               UnorderedElementsAre(IncludeHeaderWithRef("include1", 7u),
                                    IncludeHeaderWithRef("include2", 3u)));
@@ -94,7 +95,8 @@
   EXPECT_EQ(Sym2.Signature, "-sig");
   EXPECT_EQ(Sym2.ReturnType, "");
   EXPECT_EQ(Sym2.CanonicalDeclaration.FileURI, "file:///path/bar.h");
-  EXPECT_FALSE(Sym2.IsIndexedForCodeCompletion);
+  EXPECT_FALSE(Sym2.IsIndexedForCodeCompletion());
+  EXPECT_TRUE(Sym2.Deprecated());
 
   std::string ConcatenatedYAML;
   {
Index: unittests/clangd/QualityTests.cpp
===================================================================
--- unittests/clangd/QualityTests.cpp
+++ unittests/clangd/QualityTests.cpp
@@ -59,7 +59,7 @@
   F.References = 24; // TestTU doesn't count references, so fake it.
   Quality = {};
   Quality.merge(F);
-  EXPECT_FALSE(Quality.Deprecated); // FIXME: Include deprecated bit in index.
+  EXPECT_TRUE(Quality.Deprecated);
   EXPECT_FALSE(Quality.ReservedName);
   EXPECT_EQ(Quality.References, 24u);
   EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
Index: unittests/clangd/CodeCompleteTests.cpp
===================================================================
--- unittests/clangd/CodeCompleteTests.cpp
+++ unittests/clangd/CodeCompleteTests.cpp
@@ -77,6 +77,7 @@
   return Contains(AllOf(Named(std::move(Name)), Kind(K)));
 }
 MATCHER(IsDocumented, "") { return !arg.Documentation.empty(); }
+MATCHER(Deprecated, "") { return arg.Deprecated; }
 
 std::unique_ptr<SymbolIndex> memIndex(std::vector<Symbol> Symbols) {
   SymbolSlab::Builder Slab;
@@ -161,7 +162,7 @@
   USR += Regex("^.*$").sub(USRFormat, Sym.Name); // e.g. func -> @F@func#
   Sym.ID = SymbolID(USR);
   Sym.SymInfo.Kind = Kind;
-  Sym.IsIndexedForCodeCompletion = true;
+  Sym.Flags |= SymbolFlag::IsIndexedForCodeCompletion;
   Sym.Origin = SymbolOrigin::Static;
   return Sym;
 }
@@ -720,9 +721,9 @@
 TEST(CompletionTest, GlobalCompletionFiltering) {
 
   Symbol Class = cls("XYZ");
-  Class.IsIndexedForCodeCompletion = false;
+  Class.Flags &= ~(SymbolFlag::IsIndexedForCodeCompletion);
   Symbol Func = func("XYZ::foooo");
-  Func.IsIndexedForCodeCompletion = false;
+  Func.Flags &= ~(SymbolFlag::IsIndexedForCodeCompletion);
 
   auto Results = completions(R"(//      void f() {
       XYZ::foooo^
@@ -1355,6 +1356,7 @@
   C.Kind = CompletionItemKind::Method;
   C.Score.Total = 1.0;
   C.Origin = SymbolOrigin::AST | SymbolOrigin::Static;
+  C.Deprecated = true;
 
   CodeCompleteOptions Opts;
   Opts.IncludeIndicator.Insert = "^";
@@ -1370,6 +1372,7 @@
   EXPECT_EQ(R.documentation, "This is x().");
   EXPECT_THAT(R.additionalTextEdits, IsEmpty());
   EXPECT_EQ(R.sortText, sortText(1.0, "x"));
+  EXPECT_TRUE(R.deprecated);
 
   Opts.EnableSnippets = true;
   R = C.render(Opts);
@@ -1887,12 +1890,24 @@
   Sym.Name = "Clangd_Macro_Test";
   Sym.ID = SymbolID("c:foo.cpp@8@macro@Clangd_Macro_Test");
   Sym.SymInfo.Kind = index::SymbolKind::Macro;
-  Sym.IsIndexedForCodeCompletion = true;
+  Sym.Flags |= SymbolFlag::IsIndexedForCodeCompletion;
   EXPECT_THAT(completions("#define Clangd_Macro_Test\nClangd_Macro_T^", {Sym})
                   .Completions,
               UnorderedElementsAre(Named("Clangd_Macro_Test")));
 }
 
+TEST(CompletionTest, DeprecatedResults) {
+  std::string Body = R"cpp(
+    void TestClangd();
+    void TestClangc() __attribute__((deprecated("", "")));
+  )cpp";
+
+  EXPECT_THAT(
+      completions(Body + "int main() { TestClang^ }").Completions,
+      UnorderedElementsAre(AllOf(Named("TestClangd"), Not(Deprecated())),
+                           AllOf(Named("TestClangc"), Deprecated())));
+}
+
 } // namespace
 } // namespace clangd
 } // namespace clang
Index: clangd/index/SymbolYAML.cpp
===================================================================
--- clangd/index/SymbolYAML.cpp
+++ clangd/index/SymbolYAML.cpp
@@ -17,6 +17,7 @@
 #include "llvm/Support/Errc.h"
 #include "llvm/Support/MemoryBuffer.h"
 #include "llvm/Support/raw_ostream.h"
+#include <cstdint>
 
 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(clang::clangd::Symbol)
 LLVM_YAML_IS_SEQUENCE_VECTOR(clang::clangd::Symbol::IncludeHeaderWithReferences)
@@ -48,6 +49,19 @@
   std::string HexString;
 };
 
+struct NormalizedSymbolFlag {
+  NormalizedSymbolFlag(IO &) {}
+  NormalizedSymbolFlag(IO &, clang::clangd::SymbolFlag F) {
+    Flag = static_cast<uint8_t>(F);
+  }
+
+  clang::clangd::SymbolFlag denormalize(IO &) {
+    return static_cast<clang::clangd::SymbolFlag>(Flag);
+  }
+
+  uint8_t Flag = 0;
+};
+
 template <> struct MappingTraits<SymbolLocation::Position> {
   static void mapping(IO &IO, SymbolLocation::Position &Value) {
     IO.mapRequired("Line", Value.Line);
@@ -83,16 +97,17 @@
 template <> struct MappingTraits<Symbol> {
   static void mapping(IO &IO, Symbol &Sym) {
     MappingNormalization<NormalizedSymbolID, SymbolID> NSymbolID(IO, Sym.ID);
+    MappingNormalization<NormalizedSymbolFlag, clang::clangd::SymbolFlag>
+        NSymbolFlag(IO, Sym.Flags);
     IO.mapRequired("ID", NSymbolID->HexString);
     IO.mapRequired("Name", Sym.Name);
     IO.mapRequired("Scope", Sym.Scope);
     IO.mapRequired("SymInfo", Sym.SymInfo);
     IO.mapOptional("CanonicalDeclaration", Sym.CanonicalDeclaration,
                    SymbolLocation());
     IO.mapOptional("Definition", Sym.Definition, SymbolLocation());
     IO.mapOptional("References", Sym.References, 0u);
-    IO.mapOptional("IsIndexedForCodeCompletion", Sym.IsIndexedForCodeCompletion,
-                   false);
+    IO.mapOptional("Flags", NSymbolFlag->Flag);
     IO.mapOptional("Signature", Sym.Signature);
     IO.mapOptional("CompletionSnippetSuffix", Sym.CompletionSnippetSuffix);
     IO.mapOptional("Documentation", Sym.Documentation);
Index: clangd/index/SymbolCollector.cpp
===================================================================
--- clangd/index/SymbolCollector.cpp
+++ clangd/index/SymbolCollector.cpp
@@ -396,7 +396,7 @@
   Symbol S;
   S.ID = std::move(*ID);
   S.Name = Name->getName();
-  S.IsIndexedForCodeCompletion = true;
+  S.Flags |= SymbolFlag::IsIndexedForCodeCompletion;
   S.SymInfo = index::getSymbolInfoForMacro(*MI);
   std::string FileURI;
   if (auto DeclLoc = getTokenLocation(MI->getDefinitionLoc(), SM, Opts,
@@ -491,7 +491,8 @@
   // FIXME: this returns foo:bar: for objective-C methods, we prefer only foo:
   // for consistency with CodeCompletionString and a clean name/signature split.
 
-  S.IsIndexedForCodeCompletion = isIndexedForCodeCompletion(ND, Ctx);
+  if (isIndexedForCodeCompletion(ND, Ctx))
+    S.Flags |= SymbolFlag::IsIndexedForCodeCompletion;
   S.SymInfo = index::getSymbolInfo(&ND);
   std::string FileURI;
   if (auto DeclLoc = getTokenLocation(findNameLoc(&ND), SM, Opts,
@@ -531,6 +532,8 @@
     S.IncludeHeaders.emplace_back(Include, 1);
 
   S.Origin = Opts.Origin;
+  if (ND.getAvailability() == AR_Deprecated)
+    S.Flags |= SymbolFlag::Deprecated;
   Symbols.insert(S);
   return Symbols.find(S.ID);
 }
Index: clangd/index/Serialization.cpp
===================================================================
--- clangd/index/Serialization.cpp
+++ clangd/index/Serialization.cpp
@@ -8,6 +8,7 @@
 //===----------------------------------------------------------------------===//
 #include "Serialization.h"
 #include "../RIFF.h"
+#include "Index.h"
 #include "llvm/Support/Compression.h"
 #include "llvm/Support/Endian.h"
 #include "llvm/Support/Error.h"
@@ -200,7 +201,7 @@
     }
   }
   writeVar(Sym.References, OS);
-  OS.write(Sym.IsIndexedForCodeCompletion);
+  OS.write(static_cast<uint8_t>(Sym.Flags));
   OS.write(static_cast<uint8_t>(Sym.Origin));
   writeVar(Strings.index(Sym.Signature), OS);
   writeVar(Strings.index(Sym.CompletionSnippetSuffix), OS);
@@ -274,7 +275,7 @@
     }
   }
   Sym.References = consumeVar(Data);
-  Sym.IsIndexedForCodeCompletion = consume8(Data);
+  Sym.Flags = static_cast<SymbolFlag>(consume8(Data));
   Sym.Origin = static_cast<SymbolOrigin>(consume8(Data));
   READ_STRING(Sym.Signature);
   READ_STRING(Sym.CompletionSnippetSuffix);
Index: clangd/index/MemIndex.cpp
===================================================================
--- clangd/index/MemIndex.cpp
+++ clangd/index/MemIndex.cpp
@@ -35,7 +35,7 @@
     // Exact match against all possible scopes.
     if (!Req.Scopes.empty() && !llvm::is_contained(Req.Scopes, Sym->Scope))
       continue;
-    if (Req.RestrictForCodeCompletion && !Sym->IsIndexedForCodeCompletion)
+    if (Req.RestrictForCodeCompletion && !Sym->IsIndexedForCodeCompletion())
       continue;
 
     if (auto Score = Filter.match(Sym->Name)) {
Index: clangd/index/Index.h
===================================================================
--- clangd/index/Index.h
+++ clangd/index/Index.h
@@ -164,6 +164,29 @@
 }
 raw_ostream &operator<<(raw_ostream &, SymbolOrigin);
 
+enum class SymbolFlag : uint8_t {
+  None = 0,
+  /// Whether or not this symbol is meant to be used for the code completion.
+  /// See also isIndexedForCodeCompletion().
+  IsIndexedForCodeCompletion = 1 << 0,
+  /// Indicates if the symbol is deprecated.
+  Deprecated = 1 << 1,
+};
+inline SymbolFlag operator|(SymbolFlag A, SymbolFlag B) {
+  return static_cast<SymbolFlag>(static_cast<uint8_t>(A) |
+                                 static_cast<uint8_t>(B));
+}
+inline SymbolFlag &operator|=(SymbolFlag &A, SymbolFlag B) { return A = A | B; }
+inline SymbolFlag operator&(SymbolFlag A, SymbolFlag B) {
+  return static_cast<SymbolFlag>(static_cast<uint8_t>(A) &
+                                 static_cast<uint8_t>(B));
+}
+inline SymbolFlag &operator&=(SymbolFlag &A, SymbolFlag B) { return A = A & B; }
+inline SymbolFlag operator~(SymbolFlag F) {
+  return static_cast<SymbolFlag>(~static_cast<uint8_t>(F));
+}
+raw_ostream &operator<<(raw_ostream &, SymbolFlag);
+
 // The class presents a C++ symbol, e.g. class, function.
 //
 // WARNING: Symbols do not own much of their underlying data - typically strings
@@ -201,9 +224,6 @@
   // 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;
-  /// Whether or not this symbol is meant to be used for the code completion.
-  /// See also isIndexedForCodeCompletion().
-  bool IsIndexedForCodeCompletion = false;
   /// 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
@@ -244,7 +264,14 @@
   ///   any definition.
   llvm::SmallVector<IncludeHeaderWithReferences, 1> IncludeHeaders;
 
-  // FIXME: add extra fields for index scoring signals.
+  /// FIXME: also add deprecation message and fixit?
+  bool Deprecated() const {
+    return static_cast<bool>(Flags & SymbolFlag::Deprecated);
+  }
+  bool IsIndexedForCodeCompletion() const {
+    return static_cast<bool>(Flags & SymbolFlag::IsIndexedForCodeCompletion);
+  }
+  SymbolFlag Flags = SymbolFlag::None;
 };
 llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Symbol &S);
 
Index: clangd/index/Index.cpp
===================================================================
--- clangd/index/Index.cpp
+++ clangd/index/Index.cpp
@@ -55,6 +55,17 @@
   return OS;
 }
 
+raw_ostream &operator<<(raw_ostream &OS, SymbolFlag F) {
+  if (F == SymbolFlag::None)
+    return OS << "None";
+  std::string s;
+  if (static_cast<bool>(F & SymbolFlag::Deprecated))
+    s += "deprecated|";
+  if (static_cast<bool>(F & SymbolFlag::IsIndexedForCodeCompletion))
+    s += "completion|";
+  return OS << StringRef(s).rtrim('|');
+}
+
 raw_ostream &operator<<(raw_ostream &OS, const Symbol &S) {
   return OS << S.Scope << S.Name;
 }
Index: clangd/Quality.cpp
===================================================================
--- clangd/Quality.cpp
+++ clangd/Quality.cpp
@@ -167,9 +167,7 @@
 }
 
 void SymbolQualitySignals::merge(const CodeCompletionResult &SemaCCResult) {
-  if (SemaCCResult.Availability == CXAvailability_Deprecated)
-    Deprecated = true;
-
+  Deprecated |= (SemaCCResult.Availability == CXAvailability_Deprecated);
   Category = categorize(SemaCCResult);
 
   if (SemaCCResult.Declaration) {
@@ -180,6 +178,7 @@
 }
 
 void SymbolQualitySignals::merge(const Symbol &IndexResult) {
+  Deprecated |= IndexResult.Deprecated();
   References = std::max(IndexResult.References, References);
   Category = categorize(IndexResult.SymInfo);
   ReservedName = ReservedName || isReserved(IndexResult.Name);
Index: clangd/Protocol.h
===================================================================
--- clangd/Protocol.h
+++ clangd/Protocol.h
@@ -768,6 +768,9 @@
   /// themselves.
   std::vector<TextEdit> additionalTextEdits;
 
+  /// Indicates if this item is deprecated.
+  bool deprecated = false;
+
   // TODO(krasimir): The following optional fields defined by the language
   // server protocol are unsupported:
   //
Index: clangd/Protocol.cpp
===================================================================
--- clangd/Protocol.cpp
+++ clangd/Protocol.cpp
@@ -517,6 +517,8 @@
     Result["textEdit"] = *CI.textEdit;
   if (!CI.additionalTextEdits.empty())
     Result["additionalTextEdits"] = json::Array(CI.additionalTextEdits);
+  if (CI.deprecated)
+    Result["deprecated"] = CI.deprecated;
   return std::move(Result);
 }
 
Index: clangd/CodeComplete.h
===================================================================
--- clangd/CodeComplete.h
+++ clangd/CodeComplete.h
@@ -177,6 +177,9 @@
   };
   Scores Score;
 
+  /// Indicates if this item is deprecated.
+  bool Deprecated = false;
+
   // Serialize this to an LSP completion item. This is a lossy operation.
   CompletionItem render(const CodeCompleteOptions &) const;
 };
Index: clangd/CodeComplete.cpp
===================================================================
--- clangd/CodeComplete.cpp
+++ clangd/CodeComplete.cpp
@@ -353,6 +353,8 @@
                   return std::tie(X.range.start.line, X.range.start.character) <
                          std::tie(Y.range.start.line, Y.range.start.character);
                 });
+      Completion.Deprecated |=
+          (C.SemaResult->Availability == CXAvailability_Deprecated);
     }
     if (C.IndexResult) {
       Completion.Origin |= C.IndexResult->Origin;
@@ -362,6 +364,7 @@
         Completion.Kind = toCompletionItemKind(C.IndexResult->SymInfo.Kind);
       if (Completion.Name.empty())
         Completion.Name = C.IndexResult->Name;
+      Completion.Deprecated |= C.IndexResult->Deprecated();
     }
 
     // Turn absolute path into a literal string that can be #included.
@@ -1625,6 +1628,7 @@
   LSP.kind = Kind;
   LSP.detail = BundleSize > 1 ? llvm::formatv("[{0} overloads]", BundleSize)
                               : ReturnType;
+  LSP.deprecated = Deprecated;
   if (InsertInclude)
     LSP.detail += "\n" + InsertInclude->Header;
   LSP.documentation = Documentation;
@@ -1656,6 +1660,7 @@
                                              : InsertTextFormat::PlainText;
   if (InsertInclude && InsertInclude->Insertion)
     LSP.additionalTextEdits.push_back(*InsertInclude->Insertion);
+
   return LSP;
 }
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to