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

Offline killerbot

  • Administrator
  • Lives here!
  • *****
  • Posts: 5338
Re: Code completion using LSP and clangd
« Reply #105 on: March 23, 2022, 05:29:58 pm »
and what does it do with :
using TypeA = TypeB;

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5519
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion using LSP and clangd
« Reply #106 on: March 25, 2022, 03:18:16 am »
and what does it do with :
using TypeA = TypeB;

The same issue as the typedef.

Here is a simple test:

The cbp only contains main.cpp
Code
#include "TypeA.h"

int main()
{
    TypeA a;

    return 0;
}

And here are the TypeA.h

Code
#include "TypeB.h"


// typedef TypeB TypeA;


using TypeA = TypeB;

Here is TypeB.h

Code
class TypeB
{
public:
    int abc;

};

For testing, you can put the TypeA.h and TypeB.h in the same folder as main.cpp.

No, I can see that find declaration only goes from a file in cbp file to external file(a file not belong to cbp), such as main.cpp -> TypeA.h.

But find declaration will NOT go from an external file to an external file, so it failed from TypeA.h ->TypeB.h.

This is really an annoying issue. (BTW: our old code completion plugin works OK on this issue  :) )

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: 5519
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion using LSP and clangd
« Reply #107 on: March 25, 2022, 04:04:29 am »
Code
// ----------------------------------------------------------------------------
void CodeCompletion::OnGotoDeclaration(wxCommandEvent& event)
// ----------------------------------------------------------------------------
{
    ProjectManager* pPrjMgr = Manager::Get()->GetProjectManager();
    cbProject* pActiveProject = pPrjMgr->GetActiveProject();
    if (not GetLSPclient(pActiveProject)) return;

    EditorManager* pEdMgr  = Manager::Get()->GetEditorManager();
    cbEditor*      pActiveEditor = pEdMgr->GetBuiltinActiveEditor();
    if (!pActiveEditor)
        return;

    TRACE(_T("OnGotoDeclaration"));

    const int pos      = pActiveEditor->GetControl()->GetCurrentPos();
    const int startPos = pActiveEditor->GetControl()->WordStartPosition(pos, true);
    const int endPos   = pActiveEditor->GetControl()->WordEndPosition(pos, true);

    wxString targetText;
    targetText << pActiveEditor->GetControl()->GetTextRange(startPos, endPos);
    if (targetText.IsEmpty())
        return;

    // prepare a boolean filter for declaration/implementation
    bool isDecl = event.GetId() == idGotoDeclaration    || event.GetId() == idMenuGotoDeclaration;
    bool isImpl = event.GetId() == idGotoImplementation || event.GetId() == idMenuGotoImplementation;
   // ----------------------------------------------------------------------------
   // LSP Goto Declaration/definition                //(ph 2020/10/12)
   // ----------------------------------------------------------------------------
    bool usingLSP_client = true;
    if (usingLSP_client)
    {
        // Assure editors file belongs to the active project (else it's not parsed yet).
        ProjectFile* pProjectFile = pActiveEditor->GetProjectFile();
        cbProject* pEdProject = pProjectFile ? pProjectFile->GetParentProject() : nullptr;
        wxString filename = pActiveEditor->GetFilename();
        if ( (not pEdProject)
             //?or (not (pEdProject == pActiveProject)) //(ph 2022/02/15)
             //?or (not pActiveProject->GetFileByFilename(filename,false))  //(ph 2022/02/15)
                or (not GetLSPclient(pEdProject))
            )
        {
            //? InfoWindow::Display("LSP " + wxString(__FUNCTION__), "Editor's file is not contained in the active project.", 6000); //(ph 2022/02/15)
            wxString msg = _("The editor's file does not have an associated ");
            if (not pEdProject)
                msg << _("project.") << _("\nPerhaps add the file to a project ?");
            else if (not GetLSPclient(pEdProject))
                msg << "clangd_client." << _("\nPerhaps the project needs to be reparsed ?");
            cbMessageBox(msg, "LSP " + wxString(__FUNCTION__));
            return;
        }


If I looked at the comment "// Assure editors file belongs to the active project (else it's not parsed yet)."

I think it is not correct, I'm not sure clangd has some feature to query if a file is parsed or not, any one know the research direction?  :) Because I can only find some information about clangd in this page: What is clangd?, I'm not sure where is the official document of clangd, maybe I need to read the document about LSP?

EDIT:
Maybe, the LSP document is here:
language-server-protocol/protocol-2-x.md at main microsoft/language-server-protocol
« Last Edit: March 25, 2022, 04:13:01 am by ollydbg »
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: 2394
Re: Code completion using LSP and clangd
« Reply #108 on: March 25, 2022, 05:44:33 am »

If I looked at the comment "// Assure editors file belongs to the active project (else it's not parsed yet)."

I think it is not correct, I'm not sure clangd has some feature to query if a file is parsed or not, any one know the research direction?-server-protocol[/url]

I apologize for not responding. But I'm in the middle of the US tax season. I'll respond as soon as I can get my head out  of the tax instructions.

This is not a clangd problem.
It's a "this  programmer failed to implement sending non-project files to clangd" problem.
« Last Edit: March 25, 2022, 05:52:14 am by Pecan »

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5519
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion using LSP and clangd
« Reply #109 on: March 25, 2022, 06:41:51 am »

If I looked at the comment "// Assure editors file belongs to the active project (else it's not parsed yet)."

I think it is not correct, I'm not sure clangd has some feature to query if a file is parsed or not, any one know the research direction?-server-protocol[/url]

I apologize for not responding. But I'm in the middle of the US tax season. I'll respond as soon as I can get my head out  of the tax instructions.

This is not a clangd problem.
It's a "this  programmer failed to implement sending non-project files to clangd" problem.

Hi, Pecan, thanks for the reply.

Maybe, we can have a mechanism that if a non-project file is opened in the editor, we can dynamically add(send) it to the clangd's database, and once the editor is closed, its content(the file) can be dynamically removed from the clangd's database.

This is only a guess.

Because, for my previous example, if I put the "TypeA.h", "TypeB.h" in the cbp file, then I see the find declaration works correctly in either header files.  :)


EDIT:
This issue maybe is related to this github issue:
Support non-self-contained files  Issue #45  clangd/clangd
« Last Edit: March 25, 2022, 06:45:39 am by ollydbg »
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: 2394
Re: Code completion using LSP and clangd
« Reply #110 on: April 25, 2022, 08:59:46 pm »
The current rev 50 of clangd_client adds support to load and parse non-project files (some project must be active), allow macros in clangd installation path and fixes assorted crash and logic errors.

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5519
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion using LSP and clangd
« Reply #111 on: April 25, 2022, 11:55:41 pm »
The current rev 50 of clangd_client adds support to load and parse non-project files (some project must be active), allow macros in clangd installation path and fixes assorted crash and logic errors.

Thanks, great work!

But I got build errors, see below build logs:

Code
-------------- Build: Clangd_Client-wx31_64 in Clangd_Client-wx31_64 (compiler: GNU GCC Compiler)---------------

[ 33.3%] Running target pre-build steps
[ 66.7%] cmd /c @echo TARGET_OUTPUT_DIR: devel31_64\
TARGET_OUTPUT_DIR: devel31_64\
[100.0%] cmd /c @echo TARGET_OUTPUT_FILENAME: clangd_client.dll
TARGET_OUTPUT_FILENAME: clangd_client.dll
cmd /c @ECHO TARGET_DEVEL_DIR: D:\code\cb\cb_sf_git\cccrash2019
TARGET_DEVEL_DIR: D:\code\cb\cb_sf_git\cccrash2019
[  3.4%] g++.exe -Wall -std=gnu++17 -m64 -g -g -pipe -mthreads -fmessage-length=0 -fexceptions -DHAVE_W32API_H -DBUILDING_PLUGIN -D__WXMSW__ -DWXUSINGDLL -DcbDEBUG -DNOPCH -DwxUSE_UNICODE -D_WIN64 -DCC_NO_COLLAPSE_ITEM -DLOGGING -DDONT_SHOW_SERVER_CONSOLE -ID:\code\cb\cb_sf_git\cccrash2019\src\include -ID:\code\cb\cb_sf_git\cccrash2019\src\sdk\wxscintilla\include\ -ID:\code\cb\cb_sf_git\cccrash2019\src\include\tinyxml\ -ID:\code\cb\clangd_plugin\trunk\clangd_client\src -Isrc -Isrc\LSPclient\include -Isrc\winprocess -Isrc\winprocess\asyncprocess -Isrc\winprocess\misc -IF:\code\wxWidgets-3.1.6\include -IF:\code\wxWidgets-3.1.6\lib\gcc_dll\mswu -Isdk\wxscintilla\include -Iinclude\tinyxml -Isrc\LSPclient -c D:\code\cb\clangd_plugin\trunk\clangd_client\src\codecompletion\codecompletion.cpp -o .obj\clangd_client\src\codecompletion\codecompletion.o
D:\code\cb\clangd_plugin\trunk\clangd_client\src\codecompletion\codecompletion.cpp: In member function 'ProcessLanguageClient* CodeCompletion::CreateNewLanguageServiceProcess(cbProject*)':
D:\code\cb\clangd_plugin\trunk\clangd_client\src\codecompletion\codecompletion.cpp:2995:25: error: 'class ProcessLanguageClient' has no member named 'SetParser'
 2995 |             pLSPclient->SetParser( static_cast<Parser*>(pParser));
      |                         ^~~~~~~~~
D:\code\cb\clangd_plugin\trunk\clangd_client\src\codecompletion\codecompletion.cpp: In member function 'void CodeCompletion::DoParseOpenedProjectAndActiveEditor(wxTimerEvent&)':
D:\code\cb\clangd_plugin\trunk\clangd_client\src\codecompletion\codecompletion.cpp:4747:23: error: 'class ProcessLanguageClient' has no member named 'SetParser'
 4747 |         pProxyClient->SetParser((Parser*)pProxyParser);
      |                       ^~~~~~~~~
Process terminated with status 1 (0 minute(s), 13 second(s))
2 error(s), 0 warning(s) (0 minute(s), 13 second(s))


The code snippet is around codecompletion.cpp line 2979, see below:

Code
        if (pParser)
        {
            pParser->SetLSP_Client(pLSPclient);

            // Create ProxyProject move to OnAppDoneStartup() //(ph 2022/04/16)
////            // Create a ProxyProject to use for non-project files (if not already existent )
////            GetParseManager()->SetProxyProject(pcbProject);
////            // Set the ProxyProject to share this clangd client.
////            cbProject* pProxyProject = GetParseManager()->GetProxyProject();
////            if (pProxyProject)
////            {
////                m_LSP_Clients[GetParseManager()->GetProxyProject()] = pLSPclient;
////                ParserBase* pProxyParser = GetParseManager()->GetParserByProject(pProxyProject);
////                pProxyParser->SetLSP_Client(pLSPclient);
////            }

            pLSPclient->SetParser( static_cast<Parser*>(pParser));
        }

        pLSPclient->LSP_Initialize(pcbProject);
    }
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 BlueHazzard

  • Developer
  • Lives here!
  • *****
  • Posts: 3175
Re: Code completion using LSP and clangd
« Reply #112 on: April 26, 2022, 12:07:36 am »
With this rev i get the following compiler errors:
Code
cb_clang\clangd_client\src\codecompletion\parser\parser.cpp|1405|error: 'class ProcessLanguageClient' has no member named 'GetClientsCBProject'; did you mean 'GetClientObject'?|
cb_clang\clangd_client\src\codecompletion\codecompletion.cpp|2995|error: 'class ProcessLanguageClient' has no member named 'SetParser'|
cb_clang\clangd_client\src\codecompletion\codecompletion.cpp|4747|error: 'class ProcessLanguageClient' has no member named 'SetParser'|

[edit:] ollydbg was faster....

Offline Pecan

  • Plugin developer
  • Lives here!
  • ****
  • Posts: 2394
Re: Code completion using LSP and clangd
« Reply #113 on: April 26, 2022, 04:29:52 am »
I have no idea why Tortoise svn hates me so much.

Rev 52 should now have the correct files.
I downloaded and compiled it ok.

Thanks guys !!

Offline ollydbg

  • Developer
  • Lives here!
  • *****
  • Posts: 5519
  • OpenCV and Robotics
    • Chinese OpenCV forum moderator
Re: Code completion using LSP and clangd
« Reply #114 on: April 26, 2022, 11:59:08 am »
I have no idea why Tortoise svn hates me so much.

Rev 52 should now have the correct files.
I downloaded and compiled it ok.

Thanks guys !!

Hi, Pecan, thanks for the fix.

In rev 52, why do you add a clangd_client.zip file to the repo?

BTW: I don't use TortoiseSVN, instead, I use TortoiseGit, and the git-svn bridge works OK in TortoiseGit.

EDIT:

CC_ProxyProject.cbp, what does this cbp file used for?
« Last Edit: April 26, 2022, 12:01:05 pm by ollydbg »
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: 2394
Re: Code completion using LSP and clangd
« Reply #115 on: April 26, 2022, 05:08:29 pm »
Quote from: ollydbg
In rev 52, why do you add a clangd_client.zip file to the repo?
...snip...
CC_ProxyProject.cbp, what does this cbp file used for?

That zip file got there out of frustration with Tortoise svn.
I gave up and just updated with everything from my local trunk.
I'll delete it for the next update. Thanks for the heads-up.

Re: CC_ProxyProject.cbp.
 
It's a hidden cbProject used to contain files that are not associated with a project. To send a file to clangd, we need info containing it's location and compile commands.
It's used to avoid making any changes to user workspaces and  projects.

A file (not belonging to a project but needing to be parsed) is added to this "~ProxyProject~" and then sent through the code that prepares the info that clangd needs.

For Example, To solve the problem described by https://forums.codeblocks.org/index.php/topic,24357.msg169687.html#msg169687
"TypeA.h" and "TypeB.h" must be scanned by clangd in order to ask for its symbols to use in a GoToDecl/Impl request (or any other request to clangd).
Since the files don't belong to a project, they're just added to a hidden project and sent off to clangd via the usual process.

CB requires a filename in order to create a project.
We can't even issue a "pointer = new cbProject()" without a filename.

So the clangd_client code puts an empty project in the users' appdata/codeblocks folder and loads it, clones it, closes it, then hides the clone.
Loading and closing it via ProjectManager is necessary to keep from screwing up the order of plugin notifications.

This one-and-only hidden ~ProxyProject~ is created at OnAppStartupDone() and removed at CB clangd_client shutdown. It's the equivalent of the old CodeCompletion hidden temp parser.

Thanks for testing !
« Last Edit: April 28, 2022, 10:06:01 pm by Pecan »