hokein updated this revision to Diff 221904.
hokein added a comment.
Fix a typo.
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D67695/new/
https://reviews.llvm.org/D67695
Files:
clang-tools-extra/clangd/SourceCode.cpp
clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
clang-tools-extra/clangd/unittests/XRefsTests.cpp
Index: clang-tools-extra/clangd/unittests/XRefsTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/XRefsTests.cpp
+++ clang-tools-extra/clangd/unittests/XRefsTests.cpp
@@ -434,6 +434,15 @@
auto x = m^akeX();
}
)cpp",
+
+ R"cpp(
+ struct X {
+ X& [[operator]]++() {}
+ };
+ void foo(X& x) {
+ +^+x;
+ }
+ )cpp",
};
for (const char *Test : Tests) {
Annotations T(Test);
Index: clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
===================================================================
--- clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
+++ clang-tools-extra/clangd/unittests/SourceCodeTests.cpp
@@ -319,14 +319,22 @@
Bar* bar;
)cpp";
// First ^ is the expected beginning, last is the search position.
- for (std::string Text : std::vector<std::string>{
+ for (const std::string &Text : std::vector<std::string>{
"int ^f^oo();", // inside identifier
"int ^foo();", // beginning of identifier
"int ^foo^();", // end of identifier
"int foo(^);", // non-identifier
"^int foo();", // beginning of file (can't back up)
"int ^f0^0();", // after a digit (lexing at N-1 is wrong)
- "int ^λλ^λ();", // UTF-8 handled properly when backing up
+ "void f(int abc) { ^abc^++; }", // range of identifier
+ "void f(int abc) { ++^abc^; }", // range of identifier
+ "void f(int abc) { ^+^+abc; }", // range of operator
+ "void f(int abc) { ^abc^ ++; }", // range of identifier
+ "void f(int abc) { abc ^++^; }", // range of range
+ "void f(int abc) { ^++^ abc; }", // range of range
+ "void f(int abc) { ++ ^abc^; }", // range of identifier
+ "void f() {^ }", // outside of identifier and operator
+ "int ^λλ^λ();", // UTF-8 handled properly when backing up
// identifier in macro arg
"MACRO(bar->^func())", // beginning of identifier
Index: clang-tools-extra/clangd/SourceCode.cpp
===================================================================
--- clang-tools-extra/clangd/SourceCode.cpp
+++ clang-tools-extra/clangd/SourceCode.cpp
@@ -237,6 +237,20 @@
return halfOpenToRange(SM, CharSourceRange::getCharRange(TokLoc, End));
}
+static bool isOverloadedOperator(const Token &Tok) {
+ switch (Tok.getKind()) {
+#define OVERLOADED_OPERATOR(Name, Spelling, Token, Unary, Binary, MemOnly) \
+ case tok::Token:
+#define OVERLOADED_OPERATOR_MULTI(Name, Spelling, Unary, Binary, MemOnly)
+#include "clang/Basic/OperatorKinds.def"
+ return true;
+
+ default:
+ break;
+ }
+ return false;
+}
+
SourceLocation getBeginningOfIdentifier(const Position &Pos,
const SourceManager &SM,
const LangOptions &LangOpts) {
@@ -247,27 +261,63 @@
return SourceLocation();
}
- // GetBeginningOfToken(pos) is almost what we want, but does the wrong thing
- // if the cursor is at the end of the identifier.
- // Instead, we lex at GetBeginningOfToken(pos - 1). The cases are:
- // 1) at the beginning of an identifier, we'll be looking at something
- // that isn't an identifier.
- // 2) at the middle or end of an identifier, we get the identifier.
- // 3) anywhere outside an identifier, we'll get some non-identifier thing.
- // We can't actually distinguish cases 1 and 3, but returning the original
- // location is correct for both!
+ // GetBeginningOfToken(InputLoc) is almost what we want, but does the wrong
+ // thing if the cursor is at the end of the token (identifier or operator).
+ // The cases are:
+ // 1) at the beginning of the token
+ // 2) at the middle of the token
+ // 3) at the end of the token
+ // 4) anywhere outside the identifier or operator
+ // To distinguish all cases, we lex both at the
+ // GetBeginningOfToken(InputLoc-1) and GetBeginningOfToken(InputLoc), for
+ // cases 1 and 4, we just return the original location.
SourceLocation InputLoc = SM.getComposedLoc(FID, *Offset);
- if (*Offset == 0) // Case 1 or 3.
+ if (*Offset == 0) // Case 1 or 4.
return InputLoc;
SourceLocation Before = SM.getComposedLoc(FID, *Offset - 1);
+ Token BeforeTok;
+ SourceLocation BeforeTokBeginning =
+ Lexer::GetBeginningOfToken(Before, SM, LangOpts);
+ if (Lexer::getRawToken(BeforeTokBeginning, BeforeTok, SM, LangOpts, false)) {
+ // Case 1 ("^foo;", "^++foo;") or Case 4.
+ return InputLoc;
+ }
- Before = Lexer::GetBeginningOfToken(Before, SM, LangOpts);
- Token Tok;
- if (Before.isValid() &&
- !Lexer::getRawToken(Before, Tok, SM, LangOpts, false) &&
- Tok.is(tok::raw_identifier))
- return Before; // Case 2.
- return InputLoc; // Case 1 or 3.
+ Token CurrentTok;
+ SourceLocation CurrentTokBeginning =
+ Lexer::GetBeginningOfToken(InputLoc, SM, LangOpts);
+ if (Lexer::getRawToken(CurrentTokBeginning, CurrentTok, SM, LangOpts,
+ false)) {
+ // Cases 3: "abc^ ++;", "++^ abc;".
+ if (BeforeTok.is(tok::raw_identifier) || isOverloadedOperator(BeforeTok))
+ return BeforeTokBeginning;
+ return InputLoc; // Case 4.
+ }
+
+ // Case 1 or 2.
+ if (CurrentTok.is(tok::raw_identifier)) {
+ // The cursor is at the beginning or middle of the identifier
+ return CurrentTokBeginning;
+ } else if (isOverloadedOperator(CurrentTok)) {
+ if (BeforeTok.is(tok::raw_identifier))
+ // For case "foo^++;", we'd return the beginning of the identifier.
+ return BeforeTokBeginning;
+ // Cases: "^++foo;", "foo+^+;"
+ return CurrentTokBeginning;
+ }
+
+ // Case 3.
+ if (BeforeTok.is(tok::raw_identifier)) {
+ // cases at the end of the identifier: "foo^;", "foo^++;"
+ return BeforeTokBeginning;
+ } else if (isOverloadedOperator(BeforeTok)) {
+ // For case "++^foo;", we'd return the beginning of the identifier.
+ if (CurrentTok.is(tok::raw_identifier))
+ return CurrentTokBeginning;
+ // Normal cases at the end of the operator: "foo++^;"
+ return BeforeTokBeginning;
+ }
+ return InputLoc; // Case 4.
}
bool isValidFileRange(const SourceManager &Mgr, SourceRange R) {
_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits