[clangd] Boost keyword completions.

Summary: These have few signals other than being keywords, so the boost is high.

Reviewers: ilya-biryukov

Subscribers: ioeric, MaskRay, jkorous, cfe-commits

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

git-svn-id: https://llvm.org/svn/llvm-project/clang-tools-extra/trunk@334711 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/clangd/Quality.cpp b/clangd/Quality.cpp
index e42fca4..fb67c3a 100644
--- a/clangd/Quality.cpp
+++ b/clangd/Quality.cpp
@@ -59,6 +59,29 @@
   return Switch().Visit(&ND);
 }
 
+static SymbolQualitySignals::SymbolCategory categorize(const CodeCompletionResult &R) {
+  if (R.Declaration)
+    return categorize(*R.Declaration);
+  if (R.Kind == CodeCompletionResult::RK_Macro)
+    return SymbolQualitySignals::Macro;
+  // Everything else is a keyword or a pattern. Patterns are mostly keywords
+  // too, except a few which we recognize by cursor kind.
+  switch (R.CursorKind) {
+    case CXCursor_CXXMethod:
+      return SymbolQualitySignals::Function;
+    case CXCursor_ModuleImportDecl:
+      return SymbolQualitySignals::Namespace;
+    case CXCursor_MacroDefinition:
+      return SymbolQualitySignals::Macro;
+    case CXCursor_TypeRef:
+      return SymbolQualitySignals::Type;
+    case CXCursor_MemberRef:
+      return SymbolQualitySignals::Variable;
+    default:
+      return SymbolQualitySignals::Keyword;
+  }
+}
+
 static SymbolQualitySignals::SymbolCategory
 categorize(const index::SymbolInfo &D) {
   switch (D.Kind) {
@@ -103,10 +126,7 @@
   if (SemaCCResult.Availability == CXAvailability_Deprecated)
     Deprecated = true;
 
-  if (SemaCCResult.Declaration)
-    Category = categorize(*SemaCCResult.Declaration);
-  else if (SemaCCResult.Kind == CodeCompletionResult::RK_Macro)
-    Category = Macro;
+  Category = categorize(SemaCCResult);
 
   if (SemaCCResult.Declaration) {
     if (auto *ID = SemaCCResult.Declaration->getIdentifier())
@@ -135,6 +155,9 @@
     Score *= 0.1f;
 
   switch (Category) {
+    case Keyword:  // Usually relevant, but misses most signals.
+      Score *= 10;
+      break;
     case Type:
     case Function:
     case Variable:
diff --git a/clangd/Quality.h b/clangd/Quality.h
index ca1f1bf..0e0b6df 100644
--- a/clangd/Quality.h
+++ b/clangd/Quality.h
@@ -50,12 +50,13 @@
   unsigned References = 0;
 
   enum SymbolCategory {
+    Unknown = 0,
     Variable,
     Macro,
     Type,
     Function,
     Namespace,
-    Unknown,
+    Keyword,
   } Category = Unknown;
 
   void merge(const CodeCompletionResult &SemaCCResult);
diff --git a/unittests/clangd/QualityTests.cpp b/unittests/clangd/QualityTests.cpp
index 097fd32..7238bf6 100644
--- a/unittests/clangd/QualityTests.cpp
+++ b/unittests/clangd/QualityTests.cpp
@@ -58,6 +58,10 @@
   EXPECT_FALSE(Quality.ReservedName);
   EXPECT_EQ(Quality.References, SymbolQualitySignals().References);
   EXPECT_EQ(Quality.Category, SymbolQualitySignals::Function);
+
+  Quality = {};
+  Quality.merge(CodeCompletionResult("if"));
+  EXPECT_EQ(Quality.Category, SymbolQualitySignals::Keyword);
 }
 
 TEST(QualityTests, SymbolRelevanceSignalExtraction) {
@@ -125,10 +129,12 @@
   EXPECT_GT(WithReferences.evaluate(), Default.evaluate());
   EXPECT_GT(ManyReferences.evaluate(), WithReferences.evaluate());
 
-  SymbolQualitySignals Variable, Macro;
+  SymbolQualitySignals Keyword, Variable, Macro;
+  Keyword.Category = SymbolQualitySignals::Keyword;
   Variable.Category = SymbolQualitySignals::Variable;
   Macro.Category = SymbolQualitySignals::Macro;
   EXPECT_GT(Variable.evaluate(), Default.evaluate());
+  EXPECT_GT(Keyword.evaluate(), Variable.evaluate());
   EXPECT_LT(Macro.evaluate(), Default.evaluate());
 }