LSP icon indicating copy to clipboard operation
LSP copied to clipboard

[clangd] Auto complete feature is not so accurate for C/C++ struct type

Open oneWayOut opened this issue 1 year ago • 5 comments

Description

  1. There are some extra unwanted completions (which are snippets) for a struct variable as below: bug1

  2. Dot operator after a structure pointer would not transform to arrow (->) operator automatically as in VS Code, and the completions are all unwanted snippets too. bug2

Expected behavior

  1. No snippets show up if typing dot operator after a structure variable;
  2. Dot operator after a structure pointer can be transformed to arrow (->) operator automatically.

Environment

  • OS: [Windows 7]
  • Sublime Text version: [4180]
  • LSP version: [4070-2.2.0]
  • Language servers used: [clangd]
  • The code in this example is as below:
typedef struct {
	int    a;
	short  b;
	char   c;
}TEST_STRUCT;

int main()
{
	TEST_STRUCT   test1;
	TEST_STRUCT * pTest = &test1;
	test1.
	//pTest.
	return 0;
}

oneWayOut avatar Sep 24 '24 16:09 oneWayOut

  • No snippets show up if typing dot operator after a structure variable;

It looks like these snippets come from Sublime's builtin C++ package: https://github.com/sublimehq/Packages/tree/master/C%2B%2B/Snippets

There are a few different options to disable them:

  1. LSP setting https://github.com/sublimelsp/LSP/blob/9b6ecb6056b82269594dd4bc49ac337be5dd476b/LSP.sublime-settings#L150-L151

  2. ST setting "ignored_snippets"

Note that LSP does also obey the following settings which would apply for snippets provided by a language server:

  1. ST setting "auto_complete_include_snippets"

  2. ST setting "auto_complete_include_snippets_when_typing"


  • Dot operator after a structure pointer can be transformed to arrow (->) operator automatically.

This should be possible if the CompletionItem provides a textEdit. You could check the payload from the LSP log panel to see if this is the case or not. In general the completions should work the same as in VSCode. But again, the "s" snippet completions from your second screenshot are most likely from Sublime Text built-in, so it obviously wouldn't work for those.

jwortmann avatar Sep 24 '24 22:09 jwortmann

Thanks for your prompt reply.

  1. Setting "inhibit_snippet_completions" to true works for the first question.
  2. I still don't know how to fix the operator problem following your instruction. In the LSP log panel, I found that CompletionItem didn't provides a textEdit when a dot is after the struct pointer. It does provide a textEdit when an arrow operator is after the struct pointer. Could you please give more tips? @jwortmann

oneWayOut avatar Sep 25 '24 00:09 oneWayOut

Dot operator after a structure pointer can be transformed to arrow (->) operator automatically.

Where do you get this expectation from? Do other editors(that implement the LSP spec) do that?

The editor will insert/edit text based on what the language server tells it to, if the language server sends a text edit in which a -> replaces a dot then the editor will do that. This means that the language server doesn't do what you expect it to do, and we can know that if you see the LSP Logs (from the command palette type LSP: Log Panel) and copy/paste the response for the textDocument/completion request. That will answer your second expectation.

predragnikolic avatar Sep 25 '24 08:09 predragnikolic

Where do you get this expectation from? Do other editors(that implement the LSP spec) do that?

Yes, I used VSCode with clangd extension, the dot to arrow feature is implemented already, which is quite convenient. There is also a link "[clangd][vscode] Enable dot-to-arrow fixes in clangd completion." about this feature.

This means that the language server doesn't do what you expect it to do,

I copy and paste the Lsp logs after I type dot after the struct pointer as below. though I don't fully understand it.

:: [23:34:10.705] <<< clangd (11) (duration: 10ms): []
clangd: I[23:34:20.887] <-- textDocument/didChange
:: [23:34:20.886]  -> clangd textDocument/didChange: {'textDocument': {'uri': 'file:///E:/MyTest/Test.cpp', 'version': 23}, 'contentChanges': [{'range': {'start': {'line': 12, 'character': 6}, 'end': {'line': 12, 'character': 6}}, 'rangeLength': 0, 'text': '.'}]}
clangd: I[23:34:20.887] <-- textDocument/completion(12)
clangd: I[23:34:20.905] <-- textDocument/documentLink(13)
clangd: I[23:34:20.905] Failed to find compilation database for E:\MyTest\Test.cpp
clangd: I[23:34:20.906] ASTWorker building file E:\MyTest\Test.cpp version 23 with command clangd fallback
clangd: [E:\MyTest]
clangd: "C:\\Program Files\\LLVM\\bin\\clang" "-resource-dir=C:\\Program Files\\LLVM\\lib\\clang\\18" -- "E:\\MyTest\\Test.cpp"
:: [23:34:20.887] --> clangd textDocument/completion (12): {'textDocument': {'uri': 'file:///E:/MyTest/Test.cpp'}, 'position': {'line': 12, 'character': 7}}
:: [23:34:20.905] --> clangd textDocument/documentLink (13): {'textDocument': {'uri': 'file:///E:/MyTest/Test.cpp'}}
clangd: I[23:34:20.956] Code complete: 0 results from Sema, 0 from Index, 0 matched, 0 from identifiers, 0 returned.
clangd: I[23:34:20.956] --> reply:textDocument/completion(12) 69 ms
clangd: I[23:34:20.982] --> textDocument/publishDiagnostics
clangd: I[23:34:20.982] --> reply:textDocument/documentLink(13) 76 ms
:: [23:34:20.974] <<< clangd (12) (duration: 86ms): {'isIncomplete': False, 'items': []}
clangd: I[23:34:21.010] <-- textDocument/codeAction(14)
clangd: I[23:34:21.010] --> reply:textDocument/codeAction(14) 0 ms
:: [23:34:20.996] <-  clangd textDocument/publishDiagnostics: {'diagnostics': [{'code': 'expected_unqualified_id', 'message': 'Expected unqualified-id', 'range': {'end': {'character': 7, 'line': 13}, 'start': {'character': 1, 'line': 13}}, 'relatedInformation': [], 'severity': 1, 'source': 'clang'}], 'uri': 'file:///E:/MyTest/Test.cpp', 'version': 23}
:: [23:34:21.009] --> clangd textDocument/codeAction (14): {'textDocument': {'uri': 'file:///E:/MyTest/Test.cpp'}, 'range': {'start': {'line': 12, 'character': 7}, 'end': {'line': 12, 'character': 7}}, 'context': {'diagnostics': [], 'triggerKind': 2}}
:: [23:34:21.012] <<< clangd (13) (duration: 106ms): []
:: [23:34:21.028] <<< clangd (14) (duration: 18ms): []
:: [23:34:21.135] --> clangd textDocument/documentHighlight (15): {'textDocument': {'uri': 'file:///E:/MyTest/Test.cpp'}, 'position': {'line': 12, 'character': 7}}
clangd: I[23:34:21.135] <-- textDocument/documentHighlight(15)
clangd: I[23:34:21.135] --> reply:textDocument/documentHighlight(15) 0 ms
:: [23:34:21.135] <<< clangd (15) (duration: 0ms): []

I think the problem is that clangd didn't give the right code complete items as it did in VSCode like below. After I select one of the complete items, the dot will convert to arrow automatically in VSCode. VSCodeEg

oneWayOut avatar Sep 25 '24 16:09 oneWayOut

Whether those completions are provided depends on client announcing support for clangd's custom textDocument.completion.editsNearCursor capability.

Per previously referenced change, for VSCode they combine it with some custom completions handler to workaround VSCode filtering issue but for us I think it would work just fine without anything like that. The only problem is that currently we don't support extending arbitrary capabilities but only adding ones in capabilities.experimental object. I've raised https://github.com/clangd/vscode-clangd/issues/714 to nudge them into following the spec here which would make it easy for us to support this feature.

rchl avatar Nov 02 '24 13:11 rchl

The remaining issue is related to a clangd feature that I'm enabling in https://github.com/sublimelsp/LSP-clangd/pull/46.

Otherwise this seems resolved.

rchl avatar Nov 09 '25 14:11 rchl