[clang-tools-extra] [clangd] Implement simple folding of preprocessor branches (PR #80592)
via cfe-commits
cfe-commits at lists.llvm.org
Sun Feb 4 01:00:42 PST 2024
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangd
Author: Ruihua Dong (144026)
<details>
<summary>Changes</summary>
Extract directive branches information from DirectiveTree, fold branches that don't end with eof.
Fixes https://github.com/clangd/clangd/issues/1661
Examples:
Folded:
<img width="400" alt="image" src="https://github.com/llvm/llvm-project/assets/44112701/c5b7ab39-7371-47f8-9d0d-29f11dbc9a1f">
Unfolded:
<img width="400" alt="image" src="https://github.com/llvm/llvm-project/assets/44112701/6bfcb325-26b1-4435-9e3d-f2deed8136ef">
Folded (unpaired conditionals):
<img width="400" alt="image" src="https://github.com/llvm/llvm-project/assets/44112701/fdddfcf8-866f-4ab7-b8a7-6848f9bee0de">
Unfolded (unpaired conditionals):
<img width="400" alt="image" src="https://github.com/llvm/llvm-project/assets/44112701/090a9f31-69d7-41de-ba45-54f86196da9f">
---
Full diff: https://github.com/llvm/llvm-project/pull/80592.diff
3 Files Affected:
- (modified) clang-tools-extra/clangd/SemanticSelection.cpp (+18)
- (modified) clang-tools-extra/pseudo/include/clang-pseudo/DirectiveTree.h (+3)
- (modified) clang-tools-extra/pseudo/lib/DirectiveTree.cpp (+54)
``````````diff
diff --git a/clang-tools-extra/clangd/SemanticSelection.cpp b/clang-tools-extra/clangd/SemanticSelection.cpp
index 3d687173b2be9..d2aefb51fd49a 100644
--- a/clang-tools-extra/clangd/SemanticSelection.cpp
+++ b/clang-tools-extra/clangd/SemanticSelection.cpp
@@ -220,6 +220,24 @@ getFoldingRanges(const std::string &Code, bool LineFoldingOnly) {
auto EndPosition = [&](const pseudo::Token &T) {
return offsetToPosition(Code, EndOffset(T));
};
+
+ // Preprocessor directives
+ auto PPRanges = pseudo::pairDirectiveRanges(DirectiveStructure, OrigStream);
+ for (const auto &R : PPRanges) {
+ auto BTok = OrigStream.tokens()[R.Begin];
+ auto ETok = OrigStream.tokens()[R.End];
+ if (ETok.Kind == tok::eof)
+ continue;
+ if (BTok.Line >= ETok.Line)
+ continue;
+
+ Position Start = EndPosition(BTok);
+ Position End = StartPosition(ETok);
+ if (LineFoldingOnly)
+ End.line--;
+ AddFoldingRange(Start, End, FoldingRange::REGION_KIND);
+ }
+
auto Tokens = ParseableStream.tokens();
// Brackets.
for (const auto &Tok : Tokens) {
diff --git a/clang-tools-extra/pseudo/include/clang-pseudo/DirectiveTree.h b/clang-tools-extra/pseudo/include/clang-pseudo/DirectiveTree.h
index 2b6cb63297915..2e5f007f94a76 100644
--- a/clang-tools-extra/pseudo/include/clang-pseudo/DirectiveTree.h
+++ b/clang-tools-extra/pseudo/include/clang-pseudo/DirectiveTree.h
@@ -124,6 +124,9 @@ llvm::raw_ostream &operator<<(llvm::raw_ostream &,
/// The choices are stored in Conditional::Taken nodes.
void chooseConditionalBranches(DirectiveTree &, const TokenStream &Code);
+std::vector<Token::Range> pairDirectiveRanges(const DirectiveTree &Tree,
+ const TokenStream &Code);
+
} // namespace pseudo
} // namespace clang
diff --git a/clang-tools-extra/pseudo/lib/DirectiveTree.cpp b/clang-tools-extra/pseudo/lib/DirectiveTree.cpp
index 9e853e46edc23..4882f01890654 100644
--- a/clang-tools-extra/pseudo/lib/DirectiveTree.cpp
+++ b/clang-tools-extra/pseudo/lib/DirectiveTree.cpp
@@ -353,5 +353,59 @@ TokenStream DirectiveTree::stripDirectives(const TokenStream &In) const {
return Out;
}
+namespace {
+class RangePairer {
+ std::vector<Token::Range> &Ranges;
+
+public:
+ RangePairer(std::vector<Token::Range> &Ranges) : Ranges(Ranges) {}
+
+ void walk(const DirectiveTree &T) {
+ for (const auto &C : T.Chunks)
+ std::visit(*this, C);
+ }
+
+ void operator()(const DirectiveTree::Code &C) {}
+
+ void operator()(const DirectiveTree::Directive &) {}
+
+ void operator()(const DirectiveTree::Conditional &C) {
+ Token::Range Range;
+ Token::Index Last;
+ auto First = true;
+ for (const auto &B : C.Branches) {
+ if (First) {
+ First = false;
+ } else {
+ Range = {Last, B.first.Tokens.Begin};
+ Ranges.push_back(Range);
+ }
+ Last = B.first.Tokens.Begin;
+ }
+ Range = {Last, C.End.Tokens.Begin};
+ Ranges.push_back(Range);
+
+ for (const auto &B : C.Branches)
+ walk(B.second);
+ }
+};
+} // namespace
+
+std::vector<Token::Range> pairDirectiveRanges(const DirectiveTree &Tree,
+ const TokenStream &Code) {
+ std::vector<Token::Range> Ranges;
+ RangePairer(Ranges).walk(Tree);
+
+ // Transform paired ranges to start with last token in its logical line
+ for (auto &R : Ranges) {
+ const Token *Tok = &Code.tokens()[R.Begin + 1];
+ while (Tok->Kind != tok::eof && !Tok->flag(LexFlags::StartsPPLine))
+ ++Tok;
+ Tok = Tok - 1;
+ R.Begin = Tok->OriginalIndex;
+ }
+ return std::move(Ranges);
+}
+
} // namespace pseudo
} // namespace clang
``````````
</details>
https://github.com/llvm/llvm-project/pull/80592
More information about the cfe-commits
mailing list