annotate clang-tools-extra/clangd/SemanticSelection.cpp @ 252:1f2b6ac9f198 llvm-original

LLVM16-1
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Fri, 18 Aug 2023 09:04:13 +0900
parents c4bab56944e8
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
150
anatofuz
parents:
diff changeset
1 //===--- SemanticSelection.cpp -----------------------------------*- C++-*-===//
anatofuz
parents:
diff changeset
2 //
anatofuz
parents:
diff changeset
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
anatofuz
parents:
diff changeset
4 // See https://llvm.org/LICENSE.txt for license information.
anatofuz
parents:
diff changeset
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
anatofuz
parents:
diff changeset
6 //
anatofuz
parents:
diff changeset
7 //===----------------------------------------------------------------------===//
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
8
150
anatofuz
parents:
diff changeset
9 #include "SemanticSelection.h"
anatofuz
parents:
diff changeset
10 #include "ParsedAST.h"
anatofuz
parents:
diff changeset
11 #include "Protocol.h"
anatofuz
parents:
diff changeset
12 #include "Selection.h"
anatofuz
parents:
diff changeset
13 #include "SourceCode.h"
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
14 #include "clang-pseudo/Bracket.h"
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
15 #include "clang-pseudo/DirectiveTree.h"
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
16 #include "clang-pseudo/Token.h"
150
anatofuz
parents:
diff changeset
17 #include "clang/AST/DeclBase.h"
anatofuz
parents:
diff changeset
18 #include "clang/Basic/SourceLocation.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
19 #include "clang/Basic/SourceManager.h"
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
20 #include "clang/Tooling/Syntax/BuildTree.h"
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
21 #include "clang/Tooling/Syntax/Nodes.h"
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
22 #include "clang/Tooling/Syntax/TokenBufferTokenManager.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
23 #include "clang/Tooling/Syntax/Tree.h"
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
24 #include "llvm/ADT/ArrayRef.h"
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
25 #include "llvm/ADT/StringRef.h"
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
26 #include "llvm/Support/Casting.h"
150
anatofuz
parents:
diff changeset
27 #include "llvm/Support/Error.h"
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
28 #include <optional>
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
29 #include <queue>
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
30 #include <vector>
150
anatofuz
parents:
diff changeset
31
anatofuz
parents:
diff changeset
32 namespace clang {
anatofuz
parents:
diff changeset
33 namespace clangd {
anatofuz
parents:
diff changeset
34 namespace {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
35
150
anatofuz
parents:
diff changeset
36 // Adds Range \p R to the Result if it is distinct from the last added Range.
anatofuz
parents:
diff changeset
37 // Assumes that only consecutive ranges can coincide.
anatofuz
parents:
diff changeset
38 void addIfDistinct(const Range &R, std::vector<Range> &Result) {
anatofuz
parents:
diff changeset
39 if (Result.empty() || Result.back() != R) {
anatofuz
parents:
diff changeset
40 Result.push_back(R);
anatofuz
parents:
diff changeset
41 }
anatofuz
parents:
diff changeset
42 }
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
43
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
44 std::optional<FoldingRange> toFoldingRange(SourceRange SR,
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
45 const SourceManager &SM) {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
46 const auto Begin = SM.getDecomposedLoc(SR.getBegin()),
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
47 End = SM.getDecomposedLoc(SR.getEnd());
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
48 // Do not produce folding ranges if either range ends is not within the main
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
49 // file. Macros have their own FileID so this also checks if locations are not
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
50 // within the macros.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
51 if ((Begin.first != SM.getMainFileID()) || (End.first != SM.getMainFileID()))
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
52 return std::nullopt;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
53 FoldingRange Range;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
54 Range.startCharacter = SM.getColumnNumber(Begin.first, Begin.second) - 1;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
55 Range.startLine = SM.getLineNumber(Begin.first, Begin.second) - 1;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
56 Range.endCharacter = SM.getColumnNumber(End.first, End.second) - 1;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
57 Range.endLine = SM.getLineNumber(End.first, End.second) - 1;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
58 return Range;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
59 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
60
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
61 std::optional<FoldingRange>
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
62 extractFoldingRange(const syntax::Node *Node,
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
63 const syntax::TokenBufferTokenManager &TM) {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
64 if (const auto *Stmt = dyn_cast<syntax::CompoundStatement>(Node)) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
65 const auto *LBrace = cast_or_null<syntax::Leaf>(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
66 Stmt->findChild(syntax::NodeRole::OpenParen));
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
67 // FIXME(kirillbobyrev): This should find the last child. Compound
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
68 // statements have only one pair of braces so this is valid but for other
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
69 // node kinds it might not be correct.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
70 const auto *RBrace = cast_or_null<syntax::Leaf>(
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
71 Stmt->findChild(syntax::NodeRole::CloseParen));
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
72 if (!LBrace || !RBrace)
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
73 return std::nullopt;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
74 // Fold the entire range within braces, including whitespace.
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
75 const SourceLocation LBraceLocInfo =
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
76 TM.getToken(LBrace->getTokenKey())->endLocation(),
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
77 RBraceLocInfo =
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
78 TM.getToken(RBrace->getTokenKey())->location();
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
79 auto Range = toFoldingRange(SourceRange(LBraceLocInfo, RBraceLocInfo),
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
80 TM.sourceManager());
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
81 // Do not generate folding range for compound statements without any
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
82 // nodes and newlines.
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
83 if (Range && Range->startLine != Range->endLine)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
84 return Range;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
85 }
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
86 return std::nullopt;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
87 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
88
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
89 // Traverse the tree and collect folding ranges along the way.
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
90 std::vector<FoldingRange>
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
91 collectFoldingRanges(const syntax::Node *Root,
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
92 const syntax::TokenBufferTokenManager &TM) {
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
93 std::queue<const syntax::Node *> Nodes;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
94 Nodes.push(Root);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
95 std::vector<FoldingRange> Result;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
96 while (!Nodes.empty()) {
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
97 const syntax::Node *Node = Nodes.front();
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
98 Nodes.pop();
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
99 const auto Range = extractFoldingRange(Node, TM);
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
100 if (Range)
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
101 Result.push_back(*Range);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
102 if (const auto *T = dyn_cast<syntax::Tree>(Node))
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
103 for (const auto *NextNode = T->getFirstChild(); NextNode;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
104 NextNode = NextNode->getNextSibling())
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
105 Nodes.push(NextNode);
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
106 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
107 return Result;
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
108 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
109
150
anatofuz
parents:
diff changeset
110 } // namespace
anatofuz
parents:
diff changeset
111
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
112 llvm::Expected<SelectionRange> getSemanticRanges(ParsedAST &AST, Position Pos) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
113 std::vector<Range> Ranges;
150
anatofuz
parents:
diff changeset
114 const auto &SM = AST.getSourceManager();
anatofuz
parents:
diff changeset
115 const auto &LangOpts = AST.getLangOpts();
anatofuz
parents:
diff changeset
116
anatofuz
parents:
diff changeset
117 auto FID = SM.getMainFileID();
anatofuz
parents:
diff changeset
118 auto Offset = positionToOffset(SM.getBufferData(FID), Pos);
anatofuz
parents:
diff changeset
119 if (!Offset) {
anatofuz
parents:
diff changeset
120 return Offset.takeError();
anatofuz
parents:
diff changeset
121 }
anatofuz
parents:
diff changeset
122
anatofuz
parents:
diff changeset
123 // Get node under the cursor.
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
124 SelectionTree ST = SelectionTree::createRight(
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
125 AST.getASTContext(), AST.getTokens(), *Offset, *Offset);
150
anatofuz
parents:
diff changeset
126 for (const auto *Node = ST.commonAncestor(); Node != nullptr;
anatofuz
parents:
diff changeset
127 Node = Node->Parent) {
anatofuz
parents:
diff changeset
128 if (const Decl *D = Node->ASTNode.get<Decl>()) {
anatofuz
parents:
diff changeset
129 if (llvm::isa<TranslationUnitDecl>(D)) {
anatofuz
parents:
diff changeset
130 break;
anatofuz
parents:
diff changeset
131 }
anatofuz
parents:
diff changeset
132 }
anatofuz
parents:
diff changeset
133
anatofuz
parents:
diff changeset
134 auto SR = toHalfOpenFileRange(SM, LangOpts, Node->ASTNode.getSourceRange());
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
135 if (!SR || SM.getFileID(SR->getBegin()) != SM.getMainFileID()) {
150
anatofuz
parents:
diff changeset
136 continue;
anatofuz
parents:
diff changeset
137 }
anatofuz
parents:
diff changeset
138 Range R;
anatofuz
parents:
diff changeset
139 R.start = sourceLocToPosition(SM, SR->getBegin());
anatofuz
parents:
diff changeset
140 R.end = sourceLocToPosition(SM, SR->getEnd());
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
141 addIfDistinct(R, Ranges);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
142 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
143
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
144 if (Ranges.empty()) {
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
145 // LSP provides no way to signal "the point is not within a semantic range".
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
146 // Return an empty range at the point.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
147 SelectionRange Empty;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
148 Empty.range.start = Empty.range.end = Pos;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
149 return std::move(Empty);
150
anatofuz
parents:
diff changeset
150 }
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
151
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
152 // Convert to the LSP linked-list representation.
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
153 SelectionRange Head;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
154 Head.range = std::move(Ranges.front());
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
155 SelectionRange *Tail = &Head;
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
156 for (auto &Range :
252
1f2b6ac9f198 LLVM16-1
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 236
diff changeset
157 llvm::MutableArrayRef(Ranges.data(), Ranges.size()).drop_front()) {
173
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
158 Tail->parent = std::make_unique<SelectionRange>();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
159 Tail = Tail->parent.get();
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
160 Tail->range = std::move(Range);
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
161 }
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
162
0572611fdcc8 reorgnization done
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 150
diff changeset
163 return std::move(Head);
150
anatofuz
parents:
diff changeset
164 }
anatofuz
parents:
diff changeset
165
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
166 // FIXME(kirillbobyrev): Collect comments, PP conditional regions, includes and
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
167 // other code regions (e.g. public/private/protected sections of classes,
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
168 // control flow statement bodies).
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
169 // Related issue: https://github.com/clangd/clangd/issues/310
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
170 llvm::Expected<std::vector<FoldingRange>> getFoldingRanges(ParsedAST &AST) {
236
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
171 syntax::Arena A;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
172 syntax::TokenBufferTokenManager TM(AST.getTokens(), AST.getLangOpts(),
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
173 AST.getSourceManager());
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
174 const auto *SyntaxTree = syntax::buildSyntaxTree(A, TM, AST.getASTContext());
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
175 return collectFoldingRanges(SyntaxTree, TM);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
176 }
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
177
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
178 // FIXME( usaxena95): Collect PP conditional regions, includes and other code
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
179 // regions (e.g. public/private/protected sections of classes, control flow
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
180 // statement bodies).
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
181 // Related issue: https://github.com/clangd/clangd/issues/310
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
182 llvm::Expected<std::vector<FoldingRange>>
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
183 getFoldingRanges(const std::string &Code, bool LineFoldingOnly) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
184 auto OrigStream = pseudo::lex(Code, clang::pseudo::genericLangOpts());
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
185
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
186 auto DirectiveStructure = pseudo::DirectiveTree::parse(OrigStream);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
187 pseudo::chooseConditionalBranches(DirectiveStructure, OrigStream);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
188
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
189 // FIXME: Provide ranges in the disabled-PP regions as well.
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
190 auto Preprocessed = DirectiveStructure.stripDirectives(OrigStream);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
191
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
192 auto ParseableStream = cook(Preprocessed, clang::pseudo::genericLangOpts());
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
193 pseudo::pairBrackets(ParseableStream);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
194
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
195 std::vector<FoldingRange> Result;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
196 auto AddFoldingRange = [&](Position Start, Position End,
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
197 llvm::StringLiteral Kind) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
198 if (Start.line >= End.line)
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
199 return;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
200 FoldingRange FR;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
201 FR.startLine = Start.line;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
202 FR.startCharacter = Start.character;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
203 FR.endLine = End.line;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
204 FR.endCharacter = End.character;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
205 FR.kind = Kind.str();
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
206 Result.push_back(FR);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
207 };
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
208 auto OriginalToken = [&](const pseudo::Token &T) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
209 return OrigStream.tokens()[T.OriginalIndex];
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
210 };
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
211 auto StartOffset = [&](const pseudo::Token &T) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
212 return OriginalToken(T).text().data() - Code.data();
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
213 };
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
214 auto StartPosition = [&](const pseudo::Token &T) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
215 return offsetToPosition(Code, StartOffset(T));
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
216 };
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
217 auto EndOffset = [&](const pseudo::Token &T) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
218 return StartOffset(T) + OriginalToken(T).Length;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
219 };
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
220 auto EndPosition = [&](const pseudo::Token &T) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
221 return offsetToPosition(Code, EndOffset(T));
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
222 };
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
223 auto Tokens = ParseableStream.tokens();
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
224 // Brackets.
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
225 for (const auto &Tok : Tokens) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
226 if (auto *Paired = Tok.pair()) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
227 // Process only token at the start of the range. Avoid ranges on a single
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
228 // line.
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
229 if (Tok.Line < Paired->Line) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
230 Position Start = offsetToPosition(Code, 1 + StartOffset(Tok));
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
231 Position End = StartPosition(*Paired);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
232 if (LineFoldingOnly)
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
233 End.line--;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
234 AddFoldingRange(Start, End, FoldingRange::REGION_KIND);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
235 }
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
236 }
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
237 }
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
238 auto IsBlockComment = [&](const pseudo::Token &T) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
239 assert(T.Kind == tok::comment);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
240 return OriginalToken(T).Length >= 2 &&
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
241 Code.substr(StartOffset(T), 2) == "/*";
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
242 };
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
243 // Multi-line comments.
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
244 for (auto *T = Tokens.begin(); T != Tokens.end();) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
245 if (T->Kind != tok::comment) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
246 T++;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
247 continue;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
248 }
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
249 pseudo::Token *FirstComment = T;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
250 // Show starting sentinals (// and /*) of the comment.
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
251 Position Start = offsetToPosition(Code, 2 + StartOffset(*FirstComment));
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
252 pseudo::Token *LastComment = T;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
253 Position End = EndPosition(*T);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
254 while (T != Tokens.end() && T->Kind == tok::comment &&
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
255 StartPosition(*T).line <= End.line + 1) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
256 End = EndPosition(*T);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
257 LastComment = T;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
258 T++;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
259 }
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
260 if (IsBlockComment(*FirstComment)) {
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
261 if (LineFoldingOnly)
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
262 // Show last line of a block comment.
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
263 End.line--;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
264 if (IsBlockComment(*LastComment))
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
265 // Show ending sentinal "*/" of the block comment.
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
266 End.character -= 2;
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
267 }
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
268 AddFoldingRange(Start, End, FoldingRange::COMMENT_KIND);
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
269 }
c4bab56944e8 LLVM 16
kono
parents: 221
diff changeset
270 return Result;
221
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
271 }
79ff65ed7e25 LLVM12 Original
Shinji KONO <kono@ie.u-ryukyu.ac.jp>
parents: 173
diff changeset
272
150
anatofuz
parents:
diff changeset
273 } // namespace clangd
anatofuz
parents:
diff changeset
274 } // namespace clang