llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-tools-extra 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 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits