-
Notifications
You must be signed in to change notification settings - Fork 206
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[LSP] Add support for providing definitions from the SymbolTable #1530
[LSP] Add support for providing definitions from the SymbolTable #1530
Conversation
cd94b3d
to
8546e27
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some first comments.
84bcca0
to
339bbb1
Compare
Codecov ReportBase: 93.00% // Head: 92.94% // Decreases project coverage by
📣 This organization is not using Codecov’s GitHub App Integration. We recommend you install it so Codecov can continue to function properly for your repositories. Learn more Additional details and impacted files@@ Coverage Diff @@
## master #1530 +/- ##
==========================================
- Coverage 93.00% 92.94% -0.07%
==========================================
Files 348 350 +2
Lines 24760 25030 +270
==========================================
+ Hits 23028 23263 +235
- Misses 1732 1767 +35
Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. ☔ View full report at Codecov. |
f6a2016
to
69439b1
Compare
9f544ba
to
bd48c7d
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some comments, mostly with focus on some style. It might look like a lot, but it is mostly minor.
- Avoiding global complex destructing objects (e.g. use
absl::string_view
instead ofstd::string
for global constant strings) - In general prefer
absl::string_view
tostd::string
if possible in particular for parameters but often in return values as well. This avoids unnecessary allocations and also provides a better way to trace where a particular string originates from. - Prefer
insert()
andfind()
tooperator[]
in maps. The latter does a lot more (e.g. creates a temporary object) that we usually not want (It is ok in containers such as vectors that only really return a reference to a particular pre-determined object; but map-like containers do more than we want).
An independent style-guide that we often use as reference is; it might not cover the above parts specifically, but in general it is worth-while reading
https://google.github.io/styleguide/cppguide.html
bd48c7d
to
9c3f2a6
Compare
3827733
to
d9bdf2a
Compare
What is the status here ? If you have finished a comment, is ok to You said that you'd like to put everything comprising the language server into an object. Are you working on that in a separate change ? It would be nice to get this in before this, as it then might simplify the integration here. |
I am currently working on utilizing the FileList object to obtain the list of include files and incdirs using the I have added initial lookup for the file with file list (currently I called it I am currently testing the solution and once I get everything to work I will push the update. I will also work today on wrapping the language server logic into an object - I will create a separate PR for it. |
1c4bb75
to
42dd666
Compare
Ready for another review, or are you still working on the comments ? |
42dd666
to
ffd76df
Compare
ffd76df
to
916c28f
Compare
I changed the way symbol is searched in the SymbolTable - now the symbol is searched for in the reference components' tree, which is created during table building and resolving. It takes scope into consideration. I also added measuring |
…or textDocument/definition requests Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
if (change_listener_) change_listener_(uri, *tracker); | ||
for (const auto &change_listener : change_listeners_) { | ||
change_listener(uri, *tracker); | ||
} | ||
} else { | ||
Remove(uri); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On called back with this callback, you store references to the text structure stored in tracker data.
But if the file gets removed, there is no change listener that informs about a URI being removed (the Remove(uri)
below does not call any listeners)...
Which means in case the URI is deleted (someone closes the buffer in the editor) you'll store a dangeling reference to a removed text buffer in VerilogLanguageServer::UpdateEditedFileInProject()
-> SymbolTableHandler::UpdateFileContent()
.
I suggest to have the change listener to take a pointer, which can inform about a nullptr
buffer (i.e. inform about a removed URI), which you then can also use to properly clean up references.
Also, longer term it is probably better to have BufferTracker
own the ParsedVerilogSourceFile
which we then pass to VerilogProject::UpdateFileContents()
. Right now, due to the chain of change listeners, the ownership is quite murky and will result in issues.
The problem with the for (const auto &file_in_project : filelist.file_paths) {
const std::string canoncialized = std::filesystem::path(file_in_project).lexically_normal().string();
//... and use canonicalized instead of file_in_project below |
For your testing: have a file where going to definition opens another file. Then close the other file (which internally should remove it, but if the remove listener from above is not there will point dangeling data). |
The reacting to remove also would need to take into account that now we have to read the file from the filesystem again. |
Robustness testing: if there is one file in the filelist that has issues resolving symbols in the symbol table, no symbol can be resolved, even though other symbols might still be there, in particular in the file. But in that case, the symbol resolving bails out with This is important, because of course if you have 5000 files in the file-list (typical scale project), there will be one or more that have some issues parsing or producing symbols. That should not prevent us from the rest of the 'go to definition' working. |
…for filelist file Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
…erilogProject When "initialize" request does not send rootUri or rootPath, let's use either the current directory as project root or the first directory up in hierarchy that has filelist file Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
…from filelist Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
…he file in Language Server Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
…osed/unopened files Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
With my VSCode that does not set the root path and URI the new logic that derives things from the file-list is kicking in (i really like that btw. I think that is a good fallback). It does seem that it got confused in my testcase and attempts to resolve files relative to the filelist, not the filelist's directory - probably due to the dot in the filelist directory ? (/foo/bar/./verible.fileliist). Maybe some round of
|
…terals Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
…r can be nullptr in modification callback Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
…importing Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
…irectory Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
Maybe to reduce the impact of 'there is a single issue somewhere in building the symbol table and therefore we can't resolve any symbols'-issue there could be a quick fix for now: always build the symbol table for a single file, the current one, and try to resolve a symbol there (I suspect that is very common). (which also will help performance: in my case, building the symbol table for a single file takes a few 100 microseconds, while building for the whole project takes about 40 seconds). Longer term we then can refine things of course: ignore issues in some files but at least build partial symbol table, incremental update etc. |
…te errors in symbol table Since there can be files that have errors in them, it is not a good idea to stop go-to definition request due to errors in the symbol table. This commit removes errors and halting of textDocument/definition request on Build and Resolve errors. Instead, it prints warnings and allow functions to continue Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
…or textDocument/definition requests Signed-off-by: Grzegorz Latosinski <glatosinski@antmicro.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
contents = std::make_unique<VerilogSourceFile>(projectpath, path, ""); | ||
auto fileptr = files_.find(projectpath); | ||
if (fileptr == files_.end()) { | ||
files_.insert(std::make_pair(projectpath, std::move(contents))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For later: Probably files_.emplace()
might be easier here.
return true; | ||
} | ||
|
||
const SymbolTableNode *ScanReferenceComponents( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For future consideration: if scanning takes a while, maybe we need to build an index in the symbol table.
This PR is Work in Progress.
It adds support for creating a SymbolTable in the Language Server and utilizing it for finding definitions.
The current status is:
textDocument/initialize
requesttextDocument/definition
and current state of the buffers from LS clienttextDocument/definition
supportverible.filelist
file, parsed by verilog::FileList from verilog_filelistverible.filelist
fileSymbolTableHandler
VerilogLanguageServer
regardingSymbolTableHandler
supportCurrently, the workspace directory provided by the editor is used as VerilogProject root (however, emacs uses git repository root directory as the workspace directory, if available).