[clang-tools-extra] 774acdf - [clangd] Add metrics for selection tree and recovery expressions.

Haojian Wu via cfe-commits cfe-commits at lists.llvm.org
Tue May 12 07:28:16 PDT 2020


Author: Haojian Wu
Date: 2020-05-12T16:14:48+02:00
New Revision: 774acdfb8c46de9b4f8a92d80bbbd96e4d467682

URL: https://github.com/llvm/llvm-project/commit/774acdfb8c46de9b4f8a92d80bbbd96e4d467682
DIFF: https://github.com/llvm/llvm-project/commit/774acdfb8c46de9b4f8a92d80bbbd96e4d467682.diff

LOG: [clangd] Add metrics for selection tree and recovery expressions.

Reviewers: sammccall

Subscribers: ilya-biryukov, MaskRay, jkorous, arphaman, kadircet, usaxena95, cfe-commits

Tags: #clang

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

Added: 
    

Modified: 
    clang-tools-extra/clangd/Selection.cpp
    clang-tools-extra/clangd/unittests/SelectionTests.cpp

Removed: 
    


################################################################################
diff  --git a/clang-tools-extra/clangd/Selection.cpp b/clang-tools-extra/clangd/Selection.cpp
index 7d52714ad3fa..df7e82ccb2d3 100644
--- a/clang-tools-extra/clangd/Selection.cpp
+++ b/clang-tools-extra/clangd/Selection.cpp
@@ -9,6 +9,7 @@
 #include "Selection.h"
 #include "SourceCode.h"
 #include "support/Logger.h"
+#include "support/Trace.h"
 #include "clang/AST/ASTTypeTraits.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
@@ -35,6 +36,21 @@ namespace {
 using Node = SelectionTree::Node;
 using ast_type_traits::DynTypedNode;
 
+// Measure the fraction of selections that were enabled by recovery AST.
+void recordMetrics(const SelectionTree &S) {
+  static constexpr trace::Metric SelectionUsedRecovery(
+      "selection_recovery", trace::Metric::Distribution);
+  const auto *Common = S.commonAncestor();
+  for (const auto *N = Common; N; N = N->Parent) {
+    if (N->ASTNode.get<RecoveryExpr>()) {
+      SelectionUsedRecovery.record(1); // used recovery ast.
+      return;
+    }
+  }
+  if (Common)
+    SelectionUsedRecovery.record(0); // unused.
+}
+
 // An IntervalSet maintains a set of disjoint subranges of an array.
 //
 // Initially, it contains the entire array.
@@ -774,6 +790,7 @@ SelectionTree::SelectionTree(ASTContext &AST, const syntax::TokenBuffer &Tokens,
            .printToString(SM));
   Nodes = SelectionVisitor::collect(AST, Tokens, PrintPolicy, Begin, End, FID);
   Root = Nodes.empty() ? nullptr : &Nodes.front();
+  recordMetrics(*this);
   dlog("Built selection tree\n{0}", *this);
 }
 

diff  --git a/clang-tools-extra/clangd/unittests/SelectionTests.cpp b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
index e1c873a22b13..6f8c10e966a8 100644
--- a/clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ b/clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -9,6 +9,7 @@
 #include "Selection.h"
 #include "SourceCode.h"
 #include "TestTU.h"
+#include "support/TestTracer.h"
 #include "clang/AST/Decl.h"
 #include "llvm/Support/Casting.h"
 #include "gmock/gmock.h"
@@ -390,6 +391,7 @@ TEST(SelectionTest, CommonAncestor) {
       )cpp", "DeclRefExpr"} // DeclRefExpr to the "operator->" method.
   };
   for (const Case &C : Cases) {
+    trace::TestTracer Tracer;
     Annotations Test(C.Code);
 
     TestTU TU;
@@ -407,6 +409,7 @@ TEST(SelectionTest, CommonAncestor) {
     if (Test.ranges().empty()) {
       // If no [[range]] is marked in the example, there should be no selection.
       EXPECT_FALSE(T.commonAncestor()) << C.Code << "\n" << T;
+      EXPECT_THAT(Tracer.takeMetric("selection_recovery"), testing::IsEmpty());
     } else {
       // If there is an expected selection, common ancestor should exist
       // with the appropriate node type.
@@ -422,6 +425,8 @@ TEST(SelectionTest, CommonAncestor) {
       // and no nodes outside it are selected.
       EXPECT_TRUE(verifyCommonAncestor(T.root(), T.commonAncestor(), C.Code))
           << C.Code;
+      EXPECT_THAT(Tracer.takeMetric("selection_recovery"),
+                  testing::ElementsAreArray({0}));
     }
   }
 }
@@ -436,6 +441,20 @@ TEST(SelectionTest, InjectedClassName) {
   EXPECT_FALSE(D->isInjectedClassName());
 }
 
+TEST(SelectionTree, Metrics) {
+  const char *Code = R"cpp(
+    // error-ok: testing behavior on recovery expression
+    int foo();
+    int foo(int, int);
+    int x = fo^o(42);
+  )cpp";
+  auto AST = TestTU::withCode(Annotations(Code).code()).build();
+  trace::TestTracer Tracer;
+  auto T = makeSelectionTree(Code, AST);
+  EXPECT_THAT(Tracer.takeMetric("selection_recovery"),
+              testing::ElementsAreArray({1}));
+}
+
 // FIXME: Doesn't select the binary operator node in
 //          #define FOO(X) X + 1
 //          int a, b = [[FOO(a)]];


        


More information about the cfe-commits mailing list