This is not an actual patch, this is an RFC + TDD plan for future RAV
implementation. Hopefully, the implementation would gradually make all of the
tests from this snippet pass.
Details
- Reviewers
sammccall
Diff Detail
- Repository
- rG LLVM Github Monorepo
Unit Tests
Event Timeline
A few different types of feedback mixed up here :-)
Some nitpicks about behavior: these are probably worth discussing.
Places where the coverage is incomplete: obviously until we get closer to implementation, how complete this is is up to you.
Looking at examples mostly reinforced to me that foldability should have some threshold for what's inside as well as rules about grammatically what's foldable. I just can't see editors doing a good job of discarding uninteresting ranges - they're going to consider that our job.
If "only things spanning newlines" is too strict, we could consider maybe other complexity heuristics.
At least for the AST-based folds, I'd like some formalism like:
- we build a tree of potentially-foldable regions based on the AST
- starting at the bottom, we decide whether each potentially-foldable region is actually folded
- any region containing a non-folded newline is folded
- any bracket-delimited region containing a non-folded comma or semicolon token is folded
Regarding implementation and RAV: we talked about the possibility of using syntax trees, is that still on the table?
clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp | ||
---|---|---|
237 | nit: the subexpression tests are mixed in with the if cases | |
246 | confused about [[++I]] - why is this foldable but not I > 42 etc - is this because of the containing parens? FWIW, Personally, I'd want the whole if condition to be foldable (maybe only if it spans lines), and only paren subexpressions, arg lists etc that span lines to be foldable. It's hard to imagine a UX that could expose folding small parens in a way that's not annoying. (e.g. shows lots of extra UI elements, or prevents folding the outer expression) | |
277 | this is a really nice model, but I worry that having multiple folding ranges starting at the same point within a line is going to be a UX nightmare. (Note that other control flow statements can look like for loops too these days, with initializer statements) | |
329 | missing lambdas, blocks, objc methods. | |
342 | linkage specs probably belong here too | |
414 | why is the template argument list not foldable here? (it is for the class example above) | |
552 | I think clang-format messed some of these up for you | |
578 | I think consistent with how you handle braces and comments, the range should end just before the #endif | |
580 | I don't think you want the condition as part of the same of the same fold as the content, it might be important What about #if [[some_condition]][[ body ]]#elif [[some_condition]][[ body ]]#else[[ body ]]#endif Rendering (partially folded) as: | |
583 | here I'd expect folding before # so you can see it's a directive when folded | |
605 | I think YAGNI here - not sure how this could help, and it's an obscure feature to start with | |
613 | Similarly. | |
628 | would be lovely to cover objc @interface/@implementation too... | |
656 | You're missing the case where there's stuff in the implicit initial section, and then another accessor section. It's an interesting one because if you allow the implicit section to be folded, and also the whole class to be folded, then you have two folds triggered at the same location. (Currently there's only one [[[[ in this file, which i've flagged) | |
718 | nit: these are "member initializer lists", not to be confused with "initializer lists" which are the braced things (and should also be covered, I guess!) |
clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp | ||
---|---|---|
329 |
Parallel-universe lambdas https://clang.llvm.org/doxygen/classclang_1_1BlockDecl.html#details (Commonly used in the apple world I think, though it's not actually an extension to objc but rather c)
You have to go through the different ways to write functions here, I was just suggesting making sure they are definitions so you can test their body ranges too... |
just some random comments from my side.
At least for the AST-based folds, I'd like some formalism like:
+1. I think we need some general rules (mental model) to guide us how the folding works.
Some editors (e.g. VSCode) have their builtin folding-range, it is worth to investigate how the built folding-range interacts with one provided by the language server.
From my experience, VSCode's built folding-range kind of works though this is not perfect, would be nice to have some concrete examples see the improvements, we may want to prioritize those during the implementation.
clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp | ||
---|---|---|
261 | this example seems vague, it is folded because
or both? | |
284 | nit: for completeness, add a for-range case. | |
326 | not sure about this case. if we decide to support this (btw, the test on L242 should be adjusted too), would be nice to support the following usages. // forward decls [[class A; class B; class C;]] // using decls; [[using ns::A; using ns::B; using ns::C;]] | |
556 | this [[ seems mismatched, if I read the code correctly. btw, this example contains too many brackets, considering split into simpler ones. | |
598 | another option: we could just fold the whole preamble region, it seems easier, and provides a visible to see preamble range :), the downside is that any comments/macros will be folded together. | |
601 | These macros are quite simple, I'm not sure this is useful to fold them. I'd just not fold it, but if the macro body is complicated (multi-lines), it is worth folding it. | |
679 | looks like we're missing case of inheritance, e.g. a class inherits multiple classes class B : public A, private C {}; |
nit: the subexpression tests are mixed in with the if cases