Skip to content
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: fix "call hierarchy" across files #26040

Merged
merged 15 commits into from
Oct 14, 2024
Merged

Conversation

DanilaFe
Copy link
Contributor

@DanilaFe DanilaFe commented Oct 4, 2024

In the following program, trying to get the call hierarchy for writeln did not work on main.

writeln("Hello, world!");

There were a few issues with this. The first issue is that the the "index" that was fed through a CallHierarchyItem to LSP and back to CLS was an index into a single file's list of instantiations. Thus, if the function was instantiated in one place, but defined in another, the index would not be valid (or worse, be incorrect). This PR changes this by changing the way typed signatures are mapped to JSON-compatible identifiers; they are instead registered with a ContextContainer object, getting a unique ID. The unique ID is then used as JSON data, and can be used to access the same TypedSignature object when the JSON is being deserialized.

This, however, was not enough. The next problem was that we currently create a new ContextContainer per file (to handle the case in which multiple files with the same name / module name exist). As a result of this, writeln that is called in module A and defined in module B will have its instantiation computed using A's context, but its AST and other information will use B's context. This is troublesome. This PR adjusts the situation by changing the file -> FileInfo mapping to be a (file, context id) -> FileInfo mapping. This way, the same file can have several contexts (e.g., if a standard library file is loaded from two distinct files, but both named A.chpl). By default (e.g., when opening a file), the (file, "None") key is used (since no particular context was requested). However, if a file A needs to show an instantiation (via file info) from file B, we create a new mapping (fileB, fileA.context.id) -> fileInfoB, which is created from the same context. This ensures that there is a file information object for file B with the same context as that of file A.

When a call hierarchy item is constructed, it now specifies what context was used to create it. Thus, if other CallHierarchyItems point to other files, these other files are opened with the same context. To communicate the context over JSON, I employ the same approach as I did with typed signatures (register a context object with unique ID, use the ID to marshal the context to and from JSON).

To fix the case of writeln in particular, I had to relax an assertion from the _owned/_shared_ resolution PR #25617. This led to some simplified code in any case, which is great. I believe @arezaii is fine with this change. This was separately merged in #26078.

A bug that I'm surprised we didn't find prior to this, which is fixed in this PR, is that vector unmarshalling for Python interop allocates a vector of the Python list's size, then pushes additional elements instead of setting the already-allocated locations. This ended up e.g., pushing an empty string for each "real" string a user passed in a list. This led to some odd interactions with Dyno's module searching (an empty string as an input file led to "." being added to the module search path, which we do not want).

Reviewed by @jabraham17 -- thanks!

Testing

  • LSP tests
  • new call hierarchy tests
  • dyno tests

@DanilaFe DanilaFe marked this pull request as ready for review October 4, 2024 22:31
Copy link
Member

@jabraham17 jabraham17 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks good, just a few nits

frontend/lib/resolution/Resolver.cpp Outdated Show resolved Hide resolved
@@ -1128,19 +1164,34 @@ def get_file_info(
creating one if it doesn't exist. If do_update is set to True,
then the FileInfo's index is rebuilt even if it has already been
computed. This is useful if the underlying file has changed.

Most of the tiem, we will create a new context for a given URI. When
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, typo

):
self.show_message(
"Call hierarchy item contains missing or invalid additional data",
MessageType.Error,
)
return None
uid, idx = item.data
uid, idx, ctx = item.data
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, rename idx to inst_id

Signed-off-by: Danila Fedorin <[email protected]>
Signed-off-by: Danila Fedorin <[email protected]>
No Jade, did not hit CI warning this time :)

Signed-off-by: Danila Fedorin <[email protected]>
Signed-off-by: Danila Fedorin <[email protected]>
Signed-off-by: Danila Fedorin <[email protected]>
Signed-off-by: Danila Fedorin <[email protected]>
Signed-off-by: Danila Fedorin <[email protected]>
@@ -0,0 +1,215 @@
"""
Tests basic functionality, including autocompletion, go-to-definition, hover,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit, wrong file comment

@DanilaFe DanilaFe merged commit 55f5489 into chapel-lang:main Oct 14, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants