ClangCodeModel: Fix overly simplistic check

... when doing function call completion with clangd.
We did not take default arguments into account. E.g. the following
declaration:
    void func(int i, int j = int());
was mis-detected as taking no arguments, causing to the cursor to be at
the wrong location afterwards.

Change-Id: I522921721b0cb347ed593c43ed285ca6d02ccfee
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2021-11-23 18:02:41 +01:00
parent a95a77bcfc
commit 153dd2fe0b

View File

@@ -2938,10 +2938,12 @@ void ClangdCompletionItem::apply(TextDocumentManipulatorInterface &manipulator,
if (!edit) if (!edit)
return; return;
const int labelOpenParenOffset = item.label().indexOf('(');
const int labelClosingParenOffset = item.label().indexOf(')');
const auto kind = static_cast<CompletionItemKind::Kind>( const auto kind = static_cast<CompletionItemKind::Kind>(
item.kind().value_or(CompletionItemKind::Text)); item.kind().value_or(CompletionItemKind::Text));
const bool isMacroCall = kind == CompletionItemKind::Text && item.label().contains('(') const bool isMacroCall = kind == CompletionItemKind::Text && labelOpenParenOffset != -1
&& item.label().contains(')'); // Heuristic && labelClosingParenOffset > labelOpenParenOffset; // Heuristic
const bool isFunctionLike = kind == CompletionItemKind::Function const bool isFunctionLike = kind == CompletionItemKind::Function
|| kind == CompletionItemKind::Method || kind == CompletionItemKind::Constructor || kind == CompletionItemKind::Method || kind == CompletionItemKind::Constructor
|| isMacroCall; || isMacroCall;
@@ -2951,10 +2953,12 @@ void ClangdCompletionItem::apply(TextDocumentManipulatorInterface &manipulator,
// Some preparation for our magic involving (non-)insertion of parentheses and // Some preparation for our magic involving (non-)insertion of parentheses and
// cursor placement. // cursor placement.
if (isFunctionLike && !rawInsertText.contains('(')) { if (isFunctionLike && !rawInsertText.contains('(')) {
if (item.label().contains("()")) // function takes no arguments if (labelOpenParenOffset != -1) {
rawInsertText += "()"; if (labelClosingParenOffset == labelOpenParenOffset + 1) // function takes no arguments
else if (item.label().contains('(')) // function takes arguments rawInsertText += "()";
rawInsertText += "( )"; else // function takes arguments
rawInsertText += "( )";
}
} }
const int firstParenOffset = rawInsertText.indexOf('('); const int firstParenOffset = rawInsertText.indexOf('(');