[PATCH] D116218: [clangd] Fix selection on multi-dimensional array.
Haojian Wu via Phabricator via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 4 02:21:40 PST 2022
hokein updated this revision to Diff 397233.
hokein added a comment.
refine the patch based on D116536 <https://reviews.llvm.org/D116536>, and one more test.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D116218/new/
https://reviews.llvm.org/D116218
Files:
clang-tools-extra/clangd/Selection.cpp
clang-tools-extra/clangd/unittests/SelectionTests.cpp
Index: clang-tools-extra/clangd/unittests/SelectionTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/SelectionTests.cpp
+++ clang-tools-extra/clangd/unittests/SelectionTests.cpp
@@ -318,6 +318,14 @@
{"[[st^ruct {int x;}]] y;", "CXXRecordDecl"},
{"[[struct {int x;} ^y]];", "VarDecl"},
{"struct {[[int ^x]];} y;", "FieldDecl"},
+
+ // Tricky case: nested ArrayTypeLocs have the same token range.
+ {"const int x = 1, y = 2; int array[^[[x]]][10][y];", "DeclRefExpr"},
+ {"const int x = 1, y = 2; int array[x][10][^[[y]]];", "DeclRefExpr"},
+ {"const int x = 1, y = 2; int array[x][^[[10]]][y];", "IntegerLiteral"},
+ {"const int x = 1, y = 2; [[i^nt]] array[x][10][y];", "BuiltinTypeLoc"},
+ {"void func(int x) { int v_array[^[[x]]][10]; }", "DeclRefExpr"},
+
// FIXME: the AST has no location info for qualifiers.
{"const [[a^uto]] x = 42;", "AutoTypeLoc"},
{"[[co^nst auto x = 42]];", "VarDecl"},
Index: clang-tools-extra/clangd/Selection.cpp
===================================================================
--- clang-tools-extra/clangd/Selection.cpp
+++ clang-tools-extra/clangd/Selection.cpp
@@ -58,6 +58,7 @@
SelectionUsedRecovery.record(0, LanguageLabel); // unused.
}
+// Return the range covering a node and all its children.
SourceRange getSourceRange(const DynTypedNode &N) {
// MemberExprs to implicitly access anonymous fields should not claim any
// tokens for themselves. Given:
@@ -702,7 +703,7 @@
void pop() {
Node &N = *Stack.top();
dlog("{1}pop: {0}", printNodeToString(N.ASTNode, PrintPolicy), indent(-1));
- claimRange(getSourceRange(N.ASTNode), N.Selected);
+ claimTokensFor(N.ASTNode, N.Selected);
if (N.Selected == NoTokens)
N.Selected = SelectionTree::Unselected;
if (N.Selected || !N.Children.empty()) {
@@ -744,6 +745,28 @@
return SourceRange();
}
+ // Claim tokens for N, after processing its children.
+ // By default this claims all unclaimed tokens in getSourceRange().
+ // We override this if we want to claim fewer tokens (e.g. there are gaps).
+ void claimTokensFor(const DynTypedNode &N, SelectionTree::Selection &Result) {
+ if (const auto *TL = N.get<TypeLoc>()) {
+ // e.g. EltType Foo[OuterSize][InnerSize];
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ArrayTypeLoc (Outer)
+ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |-ArrayTypeLoc (Inner)
+ // ~~~~~~~ | |-RecordType
+ // ~~~~~~~~~ | `-Expr (InnerSize)
+ // ~~~~~~~~~ `-Expr (OuterSize)
+ // Inner ATL must not claim its whole SourceRange, or it clobbers Outer.
+ if (TL->getAs<ArrayTypeLoc>()) {
+ claimRange(TL->getLocalSourceRange(), Result);
+ return;
+ }
+ // FIXME: maybe LocalSourceRange is a better default for TypeLocs.
+ // It doesn't seem to be usable for FunctionTypeLocs.
+ }
+ claimRange(getSourceRange(N), Result);
+ }
+
// Perform hit-testing of a complete Node against the selection.
// This runs for every node in the AST, and must be fast in common cases.
// This is usually called from pop(), so we can take children into account.
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D116218.397233.patch
Type: text/x-patch
Size: 3324 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20220104/717eec81/attachment.bin>
More information about the cfe-commits
mailing list