llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang-tools-extra Author: SR_team (sr-tream) <details> <summary>Changes</summary> It's a rebased PR #<!-- -->80592 without pseudo-parser usage. Extract directive branches information from DirectiveTree, fold branches that don't end with eof. Fixes https://github.com/clangd/clangd/issues/1661 --- Full diff: https://github.com/llvm/llvm-project/pull/121449.diff 3 Files Affected: - (modified) clang-tools-extra/clangd/SemanticSelection.cpp (+18) - (modified) clang-tools-extra/clangd/support/DirectiveTree.cpp (+54) - (modified) clang-tools-extra/clangd/support/DirectiveTree.h (+3) ``````````diff diff --git a/clang-tools-extra/clangd/SemanticSelection.cpp b/clang-tools-extra/clangd/SemanticSelection.cpp index dd7116e619e6d0..57e7ff8b97c658 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 Token &T) { return offsetToPosition(Code, EndOffset(T)); }; + + // Preprocessor directives + auto PPRanges = 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/clangd/support/DirectiveTree.cpp b/clang-tools-extra/clangd/support/DirectiveTree.cpp index 7ea08add7a107e..2a4448902df539 100644 --- a/clang-tools-extra/clangd/support/DirectiveTree.cpp +++ b/clang-tools-extra/clangd/support/DirectiveTree.cpp @@ -356,5 +356,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 clangd } // namespace clang diff --git a/clang-tools-extra/clangd/support/DirectiveTree.h b/clang-tools-extra/clangd/support/DirectiveTree.h index 34f5a888863f26..1a377f5e0640ca 100644 --- a/clang-tools-extra/clangd/support/DirectiveTree.h +++ b/clang-tools-extra/clangd/support/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 clangd } // namespace clang `````````` </details> https://github.com/llvm/llvm-project/pull/121449 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits