[PATCH] D49546: [clangd] Implement query iterators for Dex symbol index
Sam McCall via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Jul 24 07:04:39 PDT 2018
sammccall added a comment.
This looks really nice.
Iterator implementations can be simplified a bit I think.
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:50
+ OS << Documents[Index];
+ if (Index + 1 != Documents.size())
+ OS << ", ";
----------------
(uber-nit: slightly clearer to add the separator first, then you only have to compare against zero.
Or this idiom:
```const char* Sep = "";
for (DocID D : Documents) {
OS << Sep << D;
Sep = ", ";
}
```
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:59
+ PostingListRef Documents;
+ DocID Index;
+};
----------------
nit: the code might be slightly more concise (particularly advanceTo) if the current element is represented by a PostingListRef::Iterator rather than an index, up to you.
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:59
+ PostingListRef Documents;
+ DocID Index;
+};
----------------
sammccall wrote:
> nit: the code might be slightly more concise (particularly advanceTo) if the current element is represented by a PostingListRef::Iterator rather than an index, up to you.
(DocID is the wrong type for an index)
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:65
+public:
+ AndIterator(std::vector<std::unique_ptr<Iterator>> &&AllChildren)
+ : Children(std::move(AllChildren)), ReachedEnd(false) {
----------------
nit: just take children by value without &&
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:69
+ DocID ID = 0;
+ for (auto &Child : Children) {
+ // Check whether any child iterator points to the end. In this case,
----------------
nit: const auto &
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:74
+ ReachedEnd = true;
+ break;
+ }
----------------
just return so you don't need the if at the end?
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:88
+ // FIXME(kbobyrev): Properly document this one.
+ void advance() override {
+ assert(!reachedEnd() && "AndIterator can't call advance() at the end.");
----------------
It would be nice if the functions in this class could share some logic.
what about:
```
for (auto& C : children)
C->advance();
sync();
```
where `sync` is
```
// restores class invariants: ReachedEnd set, or all children in sync
void sync() {
DocID Max = 0;
for (auto &C : Children) {
if (C->reachedEnd()) {
ReachedEnd = true;
return;
}
Max = std::max(C->peek(), Max);
}
for (auto &C : Children) {
C->advanceTo(Max);
if (C->reachedEnd()) {
ReachedEnd = true;
return;
}
}
}
```
the trick is then the constructor is just `sync();`, `advanceTo` is just "advance all children and sync", etc.
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:155
+// FIXME(kbobyrev): Document this one properly.
+// FIXME(kbobyrev): Currently, the implementation is inefficient because peek()
+// and reachedEnd() are computed in O(Children.size()). This can be fixed by
----------------
I think this is `FIXME: would a min-heap be faster?` :-)
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:181
+ const auto HighestID = peek();
+ DocID ChildrenToAdvance = 0;
+ while ((ChildrenToAdvance++ < Children.size()) && !reachedEnd() &&
----------------
I can't follow this one - why is the outer loop needed?
(It looks like you're using DocID as integer again, but I can't tell why the variable is needed at all)
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:184
+ (peek() == HighestID)) {
+ for (auto &Child : Children) {
+ if (!Child->reachedEnd() && Child->peek() == HighestID) {
----------------
nit: you can drop the extra braces here and in advanceTo (at least, you use that style above)
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:204
+ "OrIterator must have at least one child to peek().");
+ bool FoundFirstValid = false;
+ DocID Result = 0;
----------------
why not just initialize Result to `std::numeric_limits<DocID>::max()`, and skip the valid checking?
You know by assertion that you'll find something better.
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.cpp:235
+ std::vector<DocID> Result;
+ while (!It.reachedEnd()) {
+ Result.push_back(It.peek());
----------------
`for (; !It.reachedEnd(); It.advance())`
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.h:50
+
+ static std::vector<DocID> consume(Iterator &It);
+
----------------
this doesn't really make sense as static as it operates on an Iterator.
Either a free function or non-static member seems fine
================
Comment at: clang-tools-extra/clangd/index/dex/Iterator.h:65
+ static std::unique_ptr<Iterator>
+ createAnd(std::vector<std::unique_ptr<Iterator>> Children);
+
----------------
nit nit: move above the template overload so you can document the readable one.
https://reviews.llvm.org/D49546
More information about the cfe-commits
mailing list