[PATCH] D53312: [clangd] Support limiting down traversals from sources in FileDistance.

Sam McCall via Phabricator via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 16 01:44:12 PDT 2018


sammccall added a comment.

The slightly weird down-traversals semantics are indeed slightly weird. I'm happy to move forward with this approach though if we document it.

I did think of one alternative:

- instead of `unsigned Source::MaxDownTraversals`, have `bool Source::AllowDownTraversals` (obviously less flexible)
- instead of `(min-cost, max-down-traversals)` in the cache, store `(first=min-cost, second=min-cost-allowing-downtraversals)`.

When populating tree based on sources, set both cache values if down-traversals are allowed, otherwise just the first.
When propagating scores from parent to child, only read from the second cache value, and write to both.
When looking up a result from the cache, use the first cached value.

I don't think there's a lot of practical difference for our use case, the advantage would be the semantics are easier to reason about. WDYT?



================
Comment at: clangd/FileDistance.cpp:84
+        Node.Cost = S.getValue().Cost + I * Opts.UpCost;
+        if (SourceParams::MaxTraversals - S.getValue().MaxDownTraversals >= I)
+          Node.MaxDownTraversals = S.getValue().MaxDownTraversals + I;
----------------
I don't understand this if condition


================
Comment at: clangd/FileDistance.cpp:90
+          // reachable with a higher cost but large down traversal limit.
+          if (Node.Cost < R.first->second.Cost) {
+            R.first->second = std::move(Node);
----------------
For consistency, tiebreak with down traversals: `|| Node.Cost == R.first->second.Cost && Node.MaxDownTraversals > R.first->second.MaxDownTraversals` (note the opposite sign)

But probably clearer to write this by defining `CacheNode::operator<`


================
Comment at: clangd/FileDistance.cpp:107
   while (!Next.empty()) {
-    auto ParentCost = Cache.lookup(Next.front());
-    for (auto Child : DownEdges.lookup(Next.front())) {
-      auto &ChildCost =
-          Cache.try_emplace(Child, Unreachable).first->getSecond();
-      if (ParentCost + Opts.DownCost < ChildCost)
-        ChildCost = ParentCost + Opts.DownCost;
-      Next.push(Child);
+    const auto &Parent = Cache[Next.front()];
+    if (Parent.MaxDownTraversals > 0) {
----------------
This fills in the cache if it wasn't set - it's probably harmless but not quite as clear. Does lookup not work here?


================
Comment at: clangd/FileDistance.h:65
+  // Limits the number of upwards/downwards traversals allowed from this source.
+  static constexpr unsigned MaxTraversals =
+      std::numeric_limits<unsigned>::max();
----------------
nit: "unlimited" might be a clearer name here.


================
Comment at: clangd/FileDistance.h:68
+  unsigned MaxUpTraversals = MaxTraversals;
+  unsigned MaxDownTraversals = MaxTraversals;
 };
----------------
We should document the slightly weird semantics.


================
Comment at: unittests/clangd/FileDistanceTests.cpp:124
+  // These are actually reacahble from "/a" with high cost. But we don't support
+  // such case.
+  EXPECT_EQ(D.distance("/a/b"), FileDistance::Unreachable);
----------------
, because /a itself is reached more cheaply via the root.


Repository:
  rCTE Clang Tools Extra

https://reviews.llvm.org/D53312





More information about the cfe-commits mailing list