[clang-tools-extra] [clangd] Correctly identify the next token after the completion point (PR #69153)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Oct 16 01:04:25 PDT 2023
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clangd
Author: Nathan Ridge (HighCommander4)
<details>
<summary>Changes</summary>
The code was previously using Lexer::findNextToken() which does not handle being passed the completion point as input.
Fixes https://github.com/clangd/clangd/issues/1785
---
Full diff: https://github.com/llvm/llvm-project/pull/69153.diff
2 Files Affected:
- (modified) clang-tools-extra/clangd/CodeComplete.cpp (+41-1)
- (modified) clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp (+23)
``````````diff
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 70c4d7e65b76db3..fba93d8e50fc973 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -1491,6 +1491,46 @@ FuzzyFindRequest speculativeFuzzyFindRequestForCompletion(
return CachedReq;
}
+// This function is similar to Lexer::findNextToken(), but assumes
+// that the input SourceLocation is the completion point (which is
+// a case findNextToken() does not handle).
+std::optional<Token>
+findTokenAfterCompletionPoint(SourceLocation CompletionPoint,
+ const SourceManager &SM,
+ const LangOptions &LangOpts) {
+ SourceLocation Loc = CompletionPoint;
+ if (Loc.isMacroID()) {
+ if (!Lexer::isAtEndOfMacroExpansion(Loc, SM, LangOpts, &Loc))
+ return std::nullopt;
+ }
+
+ // Advance to the next SourceLocation after the completion point.
+ // Lexer::findNextToken() would call MeasureTokenLength() here,
+ // which does not handle the completion point (and can't, because
+ // the Lexer instance it constructs internally doesn't have a
+ // Preprocessor and so doesn't know about the completion point).
+ Loc = Loc.getLocWithOffset(1);
+
+ // Break down the source location.
+ std::pair<FileID, unsigned> LocInfo = SM.getDecomposedLoc(Loc);
+
+ // Try to load the file buffer.
+ bool InvalidTemp = false;
+ StringRef File = SM.getBufferData(LocInfo.first, &InvalidTemp);
+ if (InvalidTemp)
+ return std::nullopt;
+
+ const char *TokenBegin = File.data() + LocInfo.second;
+
+ // Lex from the start of the given location.
+ Lexer TheLexer(SM.getLocForStartOfFile(LocInfo.first), LangOpts, File.begin(),
+ TokenBegin, File.end());
+ // Find the token.
+ Token Tok;
+ TheLexer.LexFromRawLexer(Tok);
+ return Tok;
+}
+
// Runs Sema-based (AST) and Index-based completion, returns merged results.
//
// There are a few tricky considerations:
@@ -1589,7 +1629,7 @@ class CodeCompleteFlow {
auto Style = getFormatStyleForFile(SemaCCInput.FileName,
SemaCCInput.ParseInput.Contents,
*SemaCCInput.ParseInput.TFS);
- const auto NextToken = Lexer::findNextToken(
+ const auto NextToken = findTokenAfterCompletionPoint(
Recorder->CCSema->getPreprocessor().getCodeCompletionLoc(),
Recorder->CCSema->getSourceManager(), Recorder->CCSema->LangOpts);
if (NextToken)
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 671c0b7da97c6cf..883aa85f5438acb 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -3854,6 +3854,29 @@ TEST(CompletionTest, FunctionArgsExist) {
kind(CompletionItemKind::Function))));
}
+TEST(CompletionTest, FunctionArgsExist_Issue1785) {
+ // This is a scenario where the implementation of our check for
+ // "is there a function argument list right after the cursor"
+ // gave a bogus result.
+ clangd::CodeCompleteOptions Opts;
+ Opts.EnableSnippets = true;
+ // The whitespace in this testcase is important!
+ std::string Code = R"cpp(
+void waldo(int);
+
+int main()
+{
+ wal^
+
+
+ // ( )
+}
+ )cpp";
+ EXPECT_THAT(
+ completions(Code, {}, Opts).Completions,
+ Contains(AllOf(labeled("waldo(int)"), snippetSuffix("(${1:int})"))));
+}
+
TEST(CompletionTest, NoCrashDueToMacroOrdering) {
EXPECT_THAT(completions(R"cpp(
#define ECHO(X) X
``````````
</details>
https://github.com/llvm/llvm-project/pull/69153
More information about the cfe-commits
mailing list