usaxena95 created this revision.
usaxena95 added a reviewer: sammccall.
Herald added subscribers: cfe-commits, kadircet, arphaman, jkorous, MaskRay, 
ilya-biryukov.
Herald added a project: clang.

This patch adds an instrumentation mode for clangd (enabled by
corresponding option in cc_opts).
If this mode is enabled then user can specify callbacks to run on the
final code completion result.

Moreover the CodeCompletion::Score will contain the detailed Quality and
Relevance signals used to compute the score when this mode is enabled.
These are required because we do not any place in which the final
candidates (scored and sorted) are available along with the above
signals. The signals are temporary structures in `addCandidate`.

The callback is needed as it gives access to many data structures that
are internal to CodeCompleteFlow and are available once Sema has run. Eg:
ScopeDistnace and FileDistance.

If this mode is disabled (as in default) then Score would just contain 2
shared pointers (null). Thus cost(memory/time) increase for the default
mode would be fairly cheap and insignificant.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D75603

Files:
  clang-tools-extra/clangd/CodeComplete.cpp
  clang-tools-extra/clangd/CodeComplete.h
  clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp

Index: clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -29,6 +29,7 @@
 #include "gmock/gmock.h"
 #include "gtest/gtest.h"
 #include <condition_variable>
+#include <functional>
 #include <mutex>
 
 namespace clang {
@@ -1041,6 +1042,31 @@
   EXPECT_THAT(Completions, Contains(Named("TT")));
 }
 
+TEST(CompletionTest, EnableInstrumentationMode) {
+  CodeCompleteResult CapturedResult;
+  std::function<void(const CodeCompleteResult &)> ResultRecorder =
+      [&CapturedResult](const CodeCompleteResult &Result) -> void {
+    CapturedResult = Result;
+  };
+  CodeCompleteOptions cc_opts;
+  cc_opts.EnableInstrumentationMode = true;
+  cc_opts.RecordCCResults = &ResultRecorder;
+
+  auto Results =
+      completions("int xyz; int a = xy^", /*IndexSymbols=*/{}, cc_opts);
+  EXPECT_EQ(Results.Completions.size(), CapturedResult.Completions.size());
+  ASSERT_GT(CapturedResult.Completions.size(), 0);
+  EXPECT_TRUE(CapturedResult.Completions.front().Score.QualitySignals);
+  EXPECT_TRUE(CapturedResult.Completions.front().Score.RelevanceSignals);
+}
+
+TEST(CompletionTest, DisableInstrumentationModeByDefault) {
+  auto Results = completions("int xyz; int a = xy^");
+  ASSERT_GT(Results.Completions.size(), 0);
+  EXPECT_FALSE(Results.Completions.front().Score.QualitySignals);
+  EXPECT_FALSE(Results.Completions.front().Score.RelevanceSignals);
+}
+
 SignatureHelp signatures(llvm::StringRef Text, Position Point,
                          std::vector<Symbol> IndexSymbols = {}) {
   std::unique_ptr<SymbolIndex> Index;
Index: clang-tools-extra/clangd/CodeComplete.h
===================================================================
--- clang-tools-extra/clangd/CodeComplete.h
+++ clang-tools-extra/clangd/CodeComplete.h
@@ -19,6 +19,7 @@
 #include "Logger.h"
 #include "Path.h"
 #include "Protocol.h"
+#include "Quality.h"
 #include "index/Index.h"
 #include "index/Symbol.h"
 #include "index/SymbolOrigin.h"
@@ -29,12 +30,15 @@
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/Error.h"
+#include <functional>
 #include <future>
+#include <memory>
 
 namespace clang {
 class NamedDecl;
 namespace clangd {
 struct PreambleData;
+struct CodeCompleteResult;
 
 struct CodeCompleteOptions {
   /// Returns options that can be passed to clang's completion engine.
@@ -129,6 +133,13 @@
     /// Always use text-based completion.
     NeverParse,
   } RunParser = ParseIfReady;
+
+  /// Enables special instrumentation mode that allows capturing various
+  /// internal structures used by clangd during code completion. Eg: Symbol
+  /// quality and relevance signals of all the candidates in the output.
+  /// Ideally this must be disabled when being used by ClangdLSPServer.
+  bool EnableInstrumentationMode = false;
+  std::function<void(const CodeCompleteResult&)>* RecordCCResults;
 };
 
 // Semi-structured representation of a code-complete suggestion for our C++ API.
@@ -202,6 +213,10 @@
     // Relevance describes how well this candidate matched the query.
     // e.g. symbols from nearby files have higher relevance.
     float Relevance = 0.f;
+
+    // Signals captured when instrumentation is enabled during code completion.
+    std::shared_ptr<SymbolQualitySignals> QualitySignals;
+    std::shared_ptr<SymbolRelevanceSignals> RelevanceSignals;
   };
   Scores Score;
 
Index: clang-tools-extra/clangd/CodeComplete.cpp
===================================================================
--- clang-tools-extra/clangd/CodeComplete.cpp
+++ clang-tools-extra/clangd/CodeComplete.cpp
@@ -65,7 +65,9 @@
 #include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/ScopedPrinter.h"
 #include <algorithm>
+#include <iostream>
 #include <iterator>
+#include <memory>
 
 // We log detailed candidate here if you run with -debug-only=codecomplete.
 #define DEBUG_TYPE "CodeComplete"
@@ -1458,6 +1460,10 @@
     // Merge Sema and Index results, score them, and pick the winners.
     auto Top =
         mergeResults(Recorder->Results, IndexResults, /*Identifiers*/ {});
+
+    if (Opts.EnableInstrumentationMode)
+      (*Opts.RecordCCResults)(toCodeCompleteResult(Top));
+
     return toCodeCompleteResult(Top);
   }
 
@@ -1660,6 +1666,12 @@
                                ? Scores.Total / Relevance.NameMatch
                                : Scores.Quality;
 
+    if (Opts.EnableInstrumentationMode) {
+      Scores.QualitySignals = std::make_shared<SymbolQualitySignals>(Quality);
+      Scores.RelevanceSignals =
+          std::make_shared<SymbolRelevanceSignals>(Relevance);
+    }
+
     dlog("CodeComplete: {0} ({1}) = {2}\n{3}{4}\n", First.Name,
          llvm::to_string(Origin), Scores.Total, llvm::to_string(Quality),
          llvm::to_string(Relevance));
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to