This is the second part for introducing include hierarchy into index
files produced by clangd. You can see the base patch that introduces structures
and discusses the future of the patches in D54817
Details
Diff Detail
- Repository
- rL LLVM
Event Timeline
clangd/index/IndexAction.cpp | ||
---|---|---|
23 ↗ | (On Diff #175664) | Could we add an assertion that the final graph does not contain uninitialized nodes? |
28 ↗ | (On Diff #175664) | Maybe expand a bit on what a node is? I.e. mention file digests, URIs, etc. |
33 ↗ | (On Diff #175664) | s/enteries/entries |
44 ↗ | (On Diff #175664) | Is there a way to check the node has already been populated? Can we do this and avoid recomputing the hashes for the same file/assert they're the same in assertion mode? |
45 ↗ | (On Diff #175664) | What happens if we can't compute a digest for a file? Are we left with an uninitialized memory? |
63 ↗ | (On Diff #175664) | Maybe convert both URIs before adding anything to IG? |
72 ↗ | (On Diff #175664) | Maybe move the if block into the function body? To make sure we're be producing compiler errors on changes to the base function signature regardless of the compile configuration |
109 ↗ | (On Diff #175664) | NIT: maybe remove != nullptr? the callback is a function, not a pointer, so nullptr might be a bit confusing |
133 ↗ | (On Diff #175664) | NIT: maybe remove != nullptr? |
unittests/clangd/IndexActionTests.cpp | ||
79 ↗ | (On Diff #175664) | Why 3 headers on each level? 1 or 2, would probably read a but simpler. |
104 ↗ | (On Diff #175664) | Directly looking at the graph to capture the include structure might be more straightforward, e.g. EXPECT_THAT(graph, UnorderedElementsAre(Pair(Main, IncludersAre("level1", ....))) This won't work on StringMap, but converting to std::map<string, node> should be simple. Other invariants can be tested separately (e.g. values of IsTU) |
126 ↗ | (On Diff #175664) | Could we also test a few corner cases?
|
- Address comments.
clangd/index/IndexAction.cpp | ||
---|---|---|
45 ↗ | (On Diff #175664) | Yes, we'll be left with some random digest in the node. But I believe it is as good as any sentinel value, this field is used for consistency checks. Absence of digest implies we will always(well almost always) have an inconsistent(~stale) version of the file in the current structure and will re-trigger indexing action next time. Therefore, having this digest initialized to some sentinel or random gibberish has the same probability of colliding with the actual hash. So I believe it is OK to leave it like that. |
109 ↗ | (On Diff #175664) | yeah but this was the convention in the file, is it ok if I change the other usages as well? |
unittests/clangd/IndexActionTests.cpp | ||
126 ↗ | (On Diff #175664) | I've added a self-include test with header guards, I don't think it is possible to do that without a guard. Wouldn't it cause an infinite loop? I end up getting abort with: |
clangd/index/IndexAction.cpp | ||
---|---|---|
45 ↗ | (On Diff #175664) | Reading those values is undefined behavior, which is not the same as reading a random digest. |
109 ↗ | (On Diff #175664) | Keeping it for consistency LG. Not sure changing the whole file is worth the trouble |
unittests/clangd/IndexActionTests.cpp | ||
126 ↗ | (On Diff #175664) | Yeah, we'll need some cut-off, in might be in a form that's different from the include guard to test this. #ifndef FOO #define FOO "main.cpp" #else #define FOO "header.h" #endif #include FOO Granted, the test-case is obscure, but there's so much C++ code out there, that someone will eventually run clangd on the code doing something like this. To be clear, I don't think testing anything other than clangd does not crash on this is useful, not saying we should think too much about those cases :-) |
clangd/index/IndexAction.cpp | ||
---|---|---|
12 ↗ | (On Diff #175684) | NIT: maybe call it toURI? |
23 ↗ | (On Diff #175684) | I think this comment would also be useful on the IncludeGraph definition itself, most of the readers won't see the code building the graph |
34 ↗ | (On Diff #175684) | NIT: maybe add a note mentioning why we have to do this separately from InclusionDirective? |
152 ↗ | (On Diff #175684) | NIT: maybe add a comment that we are checking for the absence of the uninitialized values here? |
unittests/clangd/IndexActionTests.cpp | ||
28 ↗ | (On Diff #175684) | Maybe inline this? This looks simple enough. |
32 ↗ | (On Diff #175684) | Why not simply return arg.IsTU? |
38 ↗ | (On Diff #175684) | Why not return arg.Digest == Digest? |
88 ↗ | (On Diff #175684) | Maybe return all outputs in runIndexingAction in a dedicated struct? Unless this has also been copied from some other test, in which case you could argue it's consistent with how we did things before. |
124 ↗ | (On Diff #175684) | NIT: Maybe use StringRef? i.e. for (StringRef Path : ...) |
149 ↗ | (On Diff #175684) | Maybe directly store map<string, IncludeGraphNode> to avoid the flattenning code in every test? |
162 ↗ | (On Diff #175684) | Maybe move to the common code? Repeating these in every test does not seem ideal, it's a common invariant. |
unittests/clangd/IndexActionTests.cpp | ||
---|---|---|
28 ↗ | (On Diff #175684) | yeah but repeating all of that over and over again looks really ugly. |
clangd/index/IndexAction.cpp | ||
---|---|---|
31 ↗ | (On Diff #175831) | No need to duplicate the comments here, one can always look at the struct definition. |
36 ↗ | (On Diff #175831) | No need to mention IO, something like the following should convey the same message: we cannot populate the fields in InclusionDirective because it does not have access to the contents of the target file |
unittests/clangd/IndexActionTests.cpp | ||
52 ↗ | (On Diff #175831) | NIT: add a comment that uninitialized nodes will have an empty URI? |
109 ↗ | (On Diff #175831) | Do we ever use anything but the include graph? |
128 ↗ | (On Diff #175831) | Could we move these checks into the body of runIndexingAction to avoid repeating them in every test? |
28 ↗ | (On Diff #175684) | Maybe call it toUri to make it even shorther then? |
clangd/Headers.h | ||
---|---|---|
64 ↗ | (On Diff #175878) | And multi-edges too, right? Even though they're not useful. |
unittests/clangd/IndexActionTests.cpp | ||
168 ↗ | (On Diff #175878) | Maybe have two variables instead? Would format better and HeaderPath is arguably more readable than Header.first |
211 ↗ | (On Diff #175878) | Is there a way to make this format nicer? |
225 ↗ | (On Diff #175878) | Why not auto Nodes = toMap(*runIndexingAction(MainFilePath).Sources)? |
unittests/clangd/IndexActionTests.cpp | ||
---|---|---|
168 ↗ | (On Diff #175878) | Is it that important? |
225 ↗ | (On Diff #175878) | because toMap doesn't modify the contents of the nodes(to make sure we don't change behaviour during the process), and all the strings are still referring to the keys of the graph. Therefore the graph needs to be kept alive. |
unittests/clangd/IndexActionTests.cpp | ||
---|---|---|
168 ↗ | (On Diff #175878) | I think it is of minor importance. Creating a pair that is deconstructed at every use site anyway hurts readability. I would also expect the raw strings to format better and not have a very long indent if we put them into separate variables. |
225 ↗ | (On Diff #175878) | I missed this. It makes sense, thanks for clarifying. It's ok to have the boilerplate then. |
Thank, LGTM. A few NITs.
clangd/index/IndexAction.h | ||
---|---|---|
31 ↗ | (On Diff #176065) | We have only two call sites, maybe leave out the default arg and specify null explicitly where needed? |
unittests/clangd/IndexActionTests.cpp | ||
52 ↗ | (On Diff #176065) | Maybe also check the size of IndexFile.Sources is the same as Paths? To make sure we didn't miss any |