Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 0 additions & 78 deletions clang-tools-extra/clangd/SemanticSelection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,72 +42,6 @@ void addIfDistinct(const Range &R, std::vector<Range> &Result) {
}
}

std::optional<FoldingRange> toFoldingRange(SourceRange SR,
const SourceManager &SM) {
const auto Begin = SM.getDecomposedLoc(SR.getBegin()),
End = SM.getDecomposedLoc(SR.getEnd());
// Do not produce folding ranges if either range ends is not within the main
// file. Macros have their own FileID so this also checks if locations are not
// within the macros.
if ((Begin.first != SM.getMainFileID()) || (End.first != SM.getMainFileID()))
return std::nullopt;
FoldingRange Range;
Range.startCharacter = SM.getColumnNumber(Begin.first, Begin.second) - 1;
Range.startLine = SM.getLineNumber(Begin.first, Begin.second) - 1;
Range.endCharacter = SM.getColumnNumber(End.first, End.second) - 1;
Range.endLine = SM.getLineNumber(End.first, End.second) - 1;
return Range;
}

std::optional<FoldingRange>
extractFoldingRange(const syntax::Node *Node,
const syntax::TokenBufferTokenManager &TM) {
if (const auto *Stmt = dyn_cast<syntax::CompoundStatement>(Node)) {
const auto *LBrace = cast_or_null<syntax::Leaf>(
Stmt->findChild(syntax::NodeRole::OpenParen));
// FIXME(kirillbobyrev): This should find the last child. Compound
// statements have only one pair of braces so this is valid but for other
// node kinds it might not be correct.
const auto *RBrace = cast_or_null<syntax::Leaf>(
Stmt->findChild(syntax::NodeRole::CloseParen));
if (!LBrace || !RBrace)
return std::nullopt;
// Fold the entire range within braces, including whitespace.
const SourceLocation LBraceLocInfo =
TM.getToken(LBrace->getTokenKey())->endLocation(),
RBraceLocInfo =
TM.getToken(RBrace->getTokenKey())->location();
auto Range = toFoldingRange(SourceRange(LBraceLocInfo, RBraceLocInfo),
TM.sourceManager());
// Do not generate folding range for compound statements without any
// nodes and newlines.
if (Range && Range->startLine != Range->endLine)
return Range;
}
return std::nullopt;
}

// Traverse the tree and collect folding ranges along the way.
std::vector<FoldingRange>
collectFoldingRanges(const syntax::Node *Root,
const syntax::TokenBufferTokenManager &TM) {
std::queue<const syntax::Node *> Nodes;
Nodes.push(Root);
std::vector<FoldingRange> Result;
while (!Nodes.empty()) {
const syntax::Node *Node = Nodes.front();
Nodes.pop();
const auto Range = extractFoldingRange(Node, TM);
if (Range)
Result.push_back(*Range);
if (const auto *T = dyn_cast<syntax::Tree>(Node))
for (const auto *NextNode = T->getFirstChild(); NextNode;
NextNode = NextNode->getNextSibling())
Nodes.push(NextNode);
}
return Result;
}

} // namespace

llvm::Expected<SelectionRange> getSemanticRanges(ParsedAST &AST, Position Pos) {
Expand Down Expand Up @@ -230,18 +164,6 @@ class PragmaRegionFinder {
}
};

// FIXME(kirillbobyrev): Collect comments, PP conditional regions, includes and
// other code regions (e.g. public/private/protected sections of classes,
// control flow statement bodies).
// Related issue: https://github.com/clangd/clangd/issues/310
llvm::Expected<std::vector<FoldingRange>> getFoldingRanges(ParsedAST &AST) {
syntax::Arena A;
syntax::TokenBufferTokenManager TM(AST.getTokens(), AST.getLangOpts(),
AST.getSourceManager());
const auto *SyntaxTree = syntax::buildSyntaxTree(A, TM, AST.getASTContext());
return collectFoldingRanges(SyntaxTree, TM);
}

// FIXME( usaxena95): Collect includes and other code regions (e.g.
// public/private/protected sections of classes, control flow statement bodies).
// Related issue: https://github.com/clangd/clangd/issues/310
Expand Down
4 changes: 0 additions & 4 deletions clang-tools-extra/clangd/SemanticSelection.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,6 @@ namespace clangd {
/// If pos is not in any interesting range, return [Pos, Pos).
llvm::Expected<SelectionRange> getSemanticRanges(ParsedAST &AST, Position Pos);

/// Returns a list of ranges whose contents might be collapsible in an editor.
/// This should include large scopes, preprocessor blocks etc.
llvm::Expected<std::vector<FoldingRange>> getFoldingRanges(ParsedAST &AST);

/// Returns a list of ranges whose contents might be collapsible in an editor.
/// This version uses the pseudoparser which does not require the AST.
llvm::Expected<std::vector<FoldingRange>>
Expand Down
70 changes: 0 additions & 70 deletions clang-tools-extra/clangd/unittests/SemanticSelectionTests.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -196,76 +196,6 @@ TEST(SemanticSelection, RunViaClangdServer) {
ElementsAre(SourceAnnotations.range("empty")));
}

TEST(FoldingRanges, ASTAll) {
const char *Tests[] = {
R"cpp(
#define FOO int foo() {\
int Variable = 42; \
return 0; \
}

// Do not generate folding range for braces within macro expansion.
FOO

// Do not generate folding range within macro arguments.
#define FUNCTOR(functor) functor
void func() {[[
FUNCTOR([](){});
]]}

// Do not generate folding range with a brace coming from macro.
#define LBRACE {
void bar() LBRACE
int X = 42;
}
)cpp",
R"cpp(
void func() {[[
int Variable = 100;

if (Variable > 5) {[[
Variable += 42;
]]} else if (Variable++)
++Variable;
else {[[
Variable--;
]]}

// Do not generate FoldingRange for empty CompoundStmts.
for (;;) {}

// If there are newlines between {}, we should generate one.
for (;;) {[[

]]}
]]}
)cpp",
R"cpp(
class Foo {
public:
Foo() {[[
int X = 1;
]]}

private:
int getBar() {[[
return 42;
]]}

// Braces are located at the same line: no folding range here.
void getFooBar() { }
};
)cpp",
};
for (const char *Test : Tests) {
auto T = Annotations(Test);
auto AST = TestTU::withCode(T.code()).build();
EXPECT_THAT(gatherFoldingRanges(llvm::cantFail(getFoldingRanges(AST))),
UnorderedElementsAreArray(T.ranges()))
<< Test;
}
}

TEST(FoldingRanges, PseudoParserWithoutLineFoldings) {
const char *Tests[] = {
R"cpp(
Expand Down