Author Topic: Code completion using LSP and clangd  (Read 297538 times)

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6036
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion using LSP and clangd
« Reply #240 on: November 06, 2022, 05:46:32 am »
Other issue is that it looks like the icons are not showing correctly, it looks like the transparent color is shown in black?

See the image shot below:

How are seeing those icons.
I don't remember displaying them in clangd_client.
Are you sure you're using clangd_client?

I really didn't want to use the icons. But instead use the extra column for useful data.

Hi, I'm sorry, this screen shot is from the code completion plugin, not from the clangd_client plugin.  :(
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6036
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion using LSP and clangd
« Reply #241 on: November 06, 2022, 11:30:05 am »
I have some situation that there are many information messages showing: LSP: File not yet parsed.

The step is:

1, double click on a file in the source navigation tree, and a new editor is opened.
2, mouse hover on some symbols in the editor.
3, the information massage happens.

Sometimes, I got this information messages showing many times, I think there is a logic error.

My guess the logic here is: once the editor get opened, the content will be sent to the LSP. But if the parsing is not finished, the hover event will report that the File not parsed yet. But I'm not sure sometimes, it will always popup. I have to close the project, and re-open the project to workaround this issue.

Maybe there are some options which affect this issue. My guess is the option:

Update parser when typing (on save otherwise).
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Pecan

  • Plugin developer
  • Lives here!
  • ****
  • Posts: 2808
Re: Code completion using LSP and clangd
« Reply #242 on: November 06, 2022, 07:42:32 pm »

I have one question: when I click the context menu->find reference. I see from the client log, there are also "goto declaration" and "goto definition" messages from the json RPC. Do we really need those extra 2 messages? I see find reference messages already correctly return the positions we needed.

That may be true of the current clangd you're currently using.
But in previous versions (11 & 12),  clangd was returning the wrong reference because it didn't distinguish between a declaration and a definition.
So I asked for both and chose the right one to display.

I'll revisit this some later time and make sure clangd is returning the actual request (definitions vs implementation).

Offline Pecan

  • Plugin developer
  • Lives here!
  • ****
  • Posts: 2808
Re: Code completion using LSP and clangd
« Reply #243 on: November 06, 2022, 08:04:14 pm »
I see a bug that when the source code has TAB as the indent chars, our C::B editor will report the wrong position to clangd.

It looks like clangd just recognize the TAB as a single char, but in our C::B editor, when we get the column position, a TAB may be recognized as "4 space", in this case, when the clangd_client send the request to the LSP server, it send the wrong column position.

Do you see this bug?

To fix this issue, I think we have to adjust the column position we got from the editor. Any ideas?

EDIT:

The GetColumn() function has such document:

Retrieve the column number of a position, taking tab width into account.

EDIT2

In this page, we can get a "char" based column:
get column number Issue #75 jacobslusser/ScintillaNET

This issue can be fixed by this patch:

Code
From 8acd4b5b3bfe74d36583c54c4539dda112c6b1f3 Mon Sep 17 00:00:00 2001
From: asmwarrior <a@b.com>
Date: Sat, 5 Nov 2022 18:09:48 +0800
Subject: handling the char based column, do not take account the TAB width


diff --git a/clangd_client/src/LSPclient/client.cpp b/clangd_client/src/LSPclient/client.cpp
index 1654e1d..424fd0a 100644
--- a/clangd_client/src/LSPclient/client.cpp
+++ b/clangd_client/src/LSPclient/client.cpp
@@ -2301,7 +2301,10 @@ void ProcessLanguageClient::LSP_GoToDefinition(cbEditor* pcbEd, int argCaretPosi
     //-const int startPosn = pCtrl->WordStartPosition(edCaretPosn, true);
     //-const int endPosn   = pCtrl->WordEndPosition(posn, true); //not needed
     position.line       = edLineNum;
-    position.character  = edColumn;
+
+    int linePos = pCtrl->PositionFromLine(edLineNum); // Retrieve the position at the start of a line.
+    int fauxColumn = edCaretPosn - linePos;
+    position.character  = fauxColumn;
     writeClientLog(StdString_Format("<<< GoToDefinition:\n%s,line[%d], char[%d]", docuri.c_str(), position.line, position.character) );
 
     //Tell LSP server if text has changed
@@ -2386,7 +2389,9 @@ void ProcessLanguageClient::LSP_GoToDeclaration(cbEditor* pcbEd, int argCaretPos
     DocumentUri docuri = DocumentUri(stdFileURI.c_str());
     Position position;
     position.line       = edLineNum;
-    position.character  = edColumn;
+
+    int linePos = pCtrl->PositionFromLine(edLineNum); // Retrieve the position at the start of a line.
+    int fauxColumn = edCaretPosn - linePos;
     writeClientLog(StdString_Format("<<< GoToDeclaration:\n%s,line[%d], char[%d]", docuri.c_str(), position.line, position.character) );
 
     // Tell server if text has changed
@@ -2476,7 +2481,18 @@ void ProcessLanguageClient::LSP_FindReferences(cbEditor* pEd, int argCaretPositi
     //-int startPosn = pCtrl->WordStartPosition(caretPosn, true);
     //-const int endPosn   = pCtrl->WordEndPosition(posn, true); //not needed
     position.line       = edLineNum;
-    position.character  = edColumn;
+
+    // the clangd need char based column, where a TAB equals one char
+    // but GetColumn() function just return the column which retrieves the column number of a position, taking tab width into account.
+    // so we need a hack to get a new fauxColumn
+    // get column number Issue #75 jacobslusser/ScintillaNET - https://github.com/jacobslusser/ScintillaNET/issues/75
+    // var currentPos = scintilla.CurrentPosition;
+    // var currentLine = scintilla.LineFromPosition(currentPos);
+    // var linePos = scintilla.Lines[currentLine].Position;
+    // var fauxColumn = (currentPos - linePos);
+    int linePos = pCtrl->PositionFromLine(edLineNum); // Retrieve the position at the start of a line.
+    int fauxColumn = caretPosn - linePos;
+    position.character  = fauxColumn;
     writeClientLog(StdString_Format("<<< FindReferences:\n%s,line[%d], char[%d]", docuri.c_str(), position.line, position.character) );
 
     // Report changes to server else reported line references will be wrong.


I don't understand your patch.
The fix according to the jacob slusser quote is to use GetColumn().
But your patch uses fauxColumn instead.

Jacobslusser quote:
Code
jacobslusser commented on Jul 12, 2015
TL;DR
The GetColumn method.

That's an interesting question when you think about it... We could use the CurrentPosition property to get the position of the caret within the document; use that with LineFromPosition to get the line index; get the line start position from Line.Position and then finally subtract that from the original caret position to get the "column":

var currentPos = scintilla.CurrentPosition;
var currentLine = scintilla.LineFromPosition(currentPos);
var linePos = scintilla.Lines[currentLine].Position;
var fauxColumn = (currentPos - linePos);
This wouldn't be the "column" though (hence my fauxColumn variable name). Why? Because it doesn't account for tab characters which can occupy 4, 8, or any other amount of spaces. Usually when someone says they want the "column", they want the line space as it would show on a ruler, which is not necessarily the number of characters. To get a column position--while also taking into account the tab size--use the GetColumn method:

var column = scintilla.GetColumn(scintilla.CurrentPosition);
« Last Edit: November 06, 2022, 08:17:11 pm by Pecan »

Offline Pecan

  • Plugin developer
  • Lives here!
  • ****
  • Posts: 2808
Re: Code completion using LSP and clangd
« Reply #244 on: November 06, 2022, 08:48:48 pm »
I have some situation that there are many information messages showing: LSP: File not yet parsed.

The step is:

1, double click on a file in the source navigation tree, and a new editor is opened.
2, mouse hover on some symbols in the editor.
3, the information massage happens.

Sometimes, I got this information messages showing many times, I think there is a logic error.

My guess the logic here is: once the editor get opened, the content will be sent to the LSP. But if the parsing is not finished, the hover event will report that the File not parsed yet. But I'm not sure sometimes, it will always popup. I have to close the project, and re-open the project to workaround this issue.

Maybe there are some options which affect this issue. My guess is the option:

Update parser when typing (on save otherwise).

I can't re-create the error after many tries, but I think I've experienced this.
So I'll have to insert some code to try and catch it.
I'll enter this as a ticket @clangd_client repo so it doesn't get lost.

Offline Pecan

  • Plugin developer
  • Lives here!
  • ****
  • Posts: 2808
Re: Code completion using LSP and clangd
« Reply #245 on: November 06, 2022, 09:13:59 pm »
@ollydbg
RE: #244 Tab character.

Would you provide me with an example text files with Tabs that create this situation. I'd like to debug trace through the code.
Also what is your editor setting for tabs?

Thanks

Edit:
Never mind. I finally figured it out by adding both fixes and keeping the one that works. Namey ollydbgs fix.

"var column = scintilla.GetColumn(scintilla.CurrentPosition);"
does not fix the problem. It causes the same problem when tabs are in the source line.
« Last Edit: November 07, 2022, 12:28:16 am by Pecan »

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6036
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion using LSP and clangd
« Reply #246 on: November 07, 2022, 02:09:09 am »
@ollydbg
RE: #244 Tab character.

Would you provide me with an example text files with Tabs that create this situation. I'd like to debug trace through the code.
Also what is your editor setting for tabs?

Thanks

Edit:
Never mind. I finally figured it out by adding both fixes and keeping the one that works. Namey ollydbgs fix.

"var column = scintilla.GetColumn(scintilla.CurrentPosition);"
does not fix the problem. It causes the same problem when tabs are in the source line.
It's good that you can reproduce it.
I just prepared the test code, it is very simple:

Code
int main()
{
int abc = 0;
int xyz = abc + abc;
return 0;
}

And all use "tab" as indent.

Here is the screen shot.
Find declaration shows nothing, see the information message.
Find reference shows only one line, see the list view, it should show 2 lines.

Here is the screen shot:
If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Pecan

  • Plugin developer
  • Lives here!
  • ****
  • Posts: 2808
Re: Code completion using LSP and clangd
« Reply #247 on: November 08, 2022, 07:30:09 am »
It's good that you can reproduce it.
I just prepared the test code, it is very simple:

Code
int main()
{
int abc = 0;
int xyz = abc + abc;
return 0;
}

And all use "tab" as indent.

Here is the screen shot.
Find declaration shows nothing, see the information message.
Find reference shows only one line, see the list view, it should show 2 lines.

Here is the screen shot:

@ollydbg
RE: #244 Tab character.

Tab char column determination fixed in Clangd_client rev 88.
Give it a try.
Thanks for the fix.

https://sourceforge.net/p/cb-clangd-client/code/88/

Offline Pecan

  • Plugin developer
  • Lives here!
  • ****
  • Posts: 2808
Re: Code completion using LSP and clangd
« Reply #248 on: November 08, 2022, 10:32:13 pm »
I'm trying to update clangd_client as a contrib.
On Linux after I run:
Code
cd trunk
./bootstrap
./configure
make

How do I know if it worked or not.
I don't see any make output even though it looks like it ran without errors.
Am I supposed to have .o files or something?

Edit 13:45
I see there was produced the following:
Code
pecan@Zbook17:~/proj/cbHeadM4/trunk$ find . -name ".libs"
./src/src/.libs
./src/sdk/mozilla_chardet/src/.libs
./src/sdk/wxscintilla/src/scintilla/src/.libs
./src/sdk/wxscintilla/src/scintilla/lexlib/.libs
./src/sdk/wxscintilla/src/scintilla/lexers/.libs
./src/sdk/wxscintilla/src/.libs
./src/sdk/wxscintilla/.libs
./src/sdk/scripting/sqstdlib/.libs
./src/sdk/scripting/squirrel/.libs
./src/sdk/scripting/bindings/.libs
./src/sdk/.libs
./src/build_tools/autorevision/.libs
./src/plugins/codecompletion/.libs
./src/plugins/codecompletion/parser/.libs
./src/plugins/astyle/astyle/.libs
./src/plugins/astyle/.libs
./src/plugins/scriptedwizard/.libs
./src/plugins/compilergcc/.libs
./src/plugins/compilergcc/depslib/src/.libs
./src/plugins/todo/.libs
./src/plugins/defaultmimehandler/.libs
./src/plugins/debuggergdb/.libs
./src/plugins/projectsimporter/.libs
./src/plugins/openfileslist/.libs
./src/plugins/classwizard/.libs
./src/plugins/occurrenceshighlighting/.libs
./src/plugins/abbreviations/.libs
./src/plugins/autosave/.libs
./src/base/tinyxml/.libs
./src/tools/cb_share_config/.libs
./src/tools/ConsoleRunner/.libs

But nothing for any contribs. Is this normal?
If so, how do I produce .libs for the contribs (just to see if I'm on the right track)?

« Last Edit: November 08, 2022, 10:49:00 pm by Pecan »

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 6036
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion using LSP and clangd
« Reply #249 on: November 09, 2022, 02:49:06 am »
......

@ollydbg
RE: #244 Tab character.

Tab char column determination fixed in Clangd_client rev 88.
Give it a try.
Thanks for the fix.

https://sourceforge.net/p/cb-clangd-client/code/88/

Hi, thanks for the fix, I just test the rev88, and it works quite well. I see you have extra fixes in the "rename" event handling.

When editing the "#include <" or other statement, I see an annoying messagebox, I just translate the messagebox to log:

Code
From 96e57a13033c2f67e45813ad423e2d6c077488bb Mon Sep 17 00:00:00 2001
From: asmwarrior <a@b.com>
Date: Sat, 5 Nov 2022 18:10:33 +0800
Subject: change the annoying messagebox to log


diff --git a/clangd_client/src/codecompletion/parser/LSP_symbolsparser.cpp b/clangd_client/src/codecompletion/parser/LSP_symbolsparser.cpp
index 65c2c5a..a2868de 100644
--- a/clangd_client/src/codecompletion/parser/LSP_symbolsparser.cpp
+++ b/clangd_client/src/codecompletion/parser/LSP_symbolsparser.cpp
@@ -2198,7 +2198,9 @@ Token* LSP_SymbolsParser::DoHandleClass(EClassType ct, int lineNumber, int lastL
             newToken->m_IsAnonymous = true;
             #if defined(cbDEBUG)
                 wxString msg((wxString::Format("Trying to DoParse recursion in %s():%d", __FUNCTION__, __LINE__)));
-                cbMessageBox(msg, "Assert(non fatal)");
+                CCLogger::Get()->DebugLog(msg);
+                wxString str = wxString::Format("m_Buffer = %s, next = %s", m_Buffer, next);
+                //cbMessageBox(msg, "Assert(non fatal)");
             #endif
             break; //(ph 2021/10/13)
             /// DoParse(); // recursion


BTW: I really do not know why this happens, do you want to parse a single line using the hand written parser ourselves?



If some piece of memory should be reused, turn them to variables (or const variables).
If some piece of operations should be reused, turn them to functions.
If they happened together, then turn them to classes.

Offline Pecan

  • Plugin developer
  • Lives here!
  • ****
  • Posts: 2808
Re: Code completion using LSP and clangd
« Reply #250 on: November 09, 2022, 06:36:27 pm »
...

When editing the "#include <" or other statement, I see an annoying messagebox, I just translate the messagebox to log:
Code
From 96e57a13033c2f67e45813ad423e2d6c077488bb Mon Sep 17 00:00:00 2001
From: asmwarrior <a@b.com>
Date: Sat, 5 Nov 2022 18:10:33 +0800
Subject: change the annoying messagebox to log


diff --git a/clangd_client/src/codecompletion/parser/LSP_symbolsparser.cpp b/clangd_client/src/codecompletion/parser/LSP_symbolsparser.cpp
index 65c2c5a..a2868de 100644
--- a/clangd_client/src/codecompletion/parser/LSP_symbolsparser.cpp
+++ b/clangd_client/src/codecompletion/parser/LSP_symbolsparser.cpp
@@ -2198,7 +2198,9 @@ Token* LSP_SymbolsParser::DoHandleClass(EClassType ct, int lineNumber, int lastL
             newToken->m_IsAnonymous = true;
             #if defined(cbDEBUG)
                 wxString msg((wxString::Format("Trying to DoParse recursion in %s():%d", __FUNCTION__, __LINE__)));
-                cbMessageBox(msg, "Assert(non fatal)");
+                CCLogger::Get()->DebugLog(msg);
+                wxString str = wxString::Format("m_Buffer = %s, next = %s", m_Buffer, next);
+                //cbMessageBox(msg, "Assert(non fatal)");
             #endif
             break; //(ph 2021/10/13)
             /// DoParse(); // recursion


BTW: I really do not know why this happens, do you want to parse a single line using the hand written parser ourselves?

I'll make that annoying cbMessageBox into a log msg instead.
Code
#if defined(cbDEBUG)
                // FIXME (ph#): Find out why this happens when trying to find a class ancestor.
                wxString msg((wxString::Format("Trying to DoParse recursion in %s():%d", __FUNCTION__, __LINE__)));
                //-cbMessageBox(msg, "Assert(non fatal)");
                CCLogger::Get()->DebugLog(msg);
            #endif
            break; //(ph 2021/10/13)
            /// DoParse(); // recursion

The code is trying to parse out the ancestor of a class to add to the symbols tree. Clangd has no protocol msg to achieve that, so I was trying to use the old CodeCompletion code to parse it from the source line.

Do you have any steps you can give me to re-create the situation.

Thanks
« Last Edit: November 09, 2022, 06:43:25 pm by Pecan »

Offline Pecan

  • Plugin developer
  • Lives here!
  • ****
  • Posts: 2808
Re: Code completion using LSP and clangd
« Reply #251 on: November 11, 2022, 11:48:02 pm »
If There are no objections, I'd like to commit Clangd_client as a contrib.

It runs fine on both Windows and Linux.
And I believe Andrew has it working on Mac.

Thanks


Offline gd_on

  • Lives here!
  • ****
  • Posts: 800
Re: Code completion using LSP and clangd
« Reply #252 on: November 14, 2022, 02:04:13 pm »
Cool.
I see that clangd_client plugin is now included in contrib plugins.
Three details :
  • within contrib, it's version 87 though on your svn site it's version 88;
  • CodeBlocks_wx32_64.workspace has not been updated to include the clangd_client but all other workspaces are OK;
  • the documentation-install folder is not there.

gd_on
« Last Edit: November 14, 2022, 03:46:17 pm by gd_on »
Windows 11 64 bits (23H2), svn C::B (last version or almost!), wxWidgets 3.2.5 (tests with 3.3), Msys2 Compilers 14.1.0, 64 bits (seh, posix : gcc, g++ and gfortran in C:\msys64\mingw64) or 32 bits (dwarf2, posix  in C:\msys64\mingw32).

Offline Miguel Gimenez

  • Developer
  • Lives here!
  • *****
  • Posts: 1633
Re: Code completion using LSP and clangd
« Reply #253 on: November 14, 2022, 02:30:42 pm »
Conversely, clangd_client_wx32.cbp is missing although CodeBlocks_wx32.workspace includes it (ticket #1327).
« Last Edit: November 14, 2022, 02:32:42 pm by Miguel Gimenez »

Offline Miguel Gimenez

  • Developer
  • Lives here!
  • *****
  • Posts: 1633
Re: Code completion using LSP and clangd
« Reply #254 on: November 14, 2022, 04:16:26 pm »
File clangd_client_wx31.cbp has this linker option:
Code
<Add option="-m64" />
but it is a 32-bit project.