-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
pyright-lsp may enter a strange state reporting library not found when there are sub-project inside a folder #4994
Comments
I don't know anything about vim, so I'm trying to diagnose this based on the provided logs. Based on the symptoms, I suspect that the delta changes to the document are not being properly applied to the in-memory contents, so pyright is analyzing a corrupted source file. Here's why I think this is the case. The starting text in the document "./projects/example.py" is: import os
from sac.datasets import Data
os
Data Here's the RPC message sent to the language server: {
jsonrpc = "2.0",
method = "textDocument/didChange",
params = {
contentChanges = { {
range = {
["end"] = {
character = 4,
line = 4
},
start = {
character = 0,
line = 1
}
},
rangeLength = 38,
text = "\nfrom sac.datasets import Data\n\nos\nData\n"
}, {
range = {
["end"] = {
character = 0,
line = 7
},
start = {
character = 0,
line = 6
}
},
rangeLength = 1,
text = ""
} },
textDocument = {
uri = "file:///Users/yichaozhou/Sources/reproduce-bug/projects/example.py",
version = 5
}
}
} This message looks fine to me. The first change should replace the contents of line 1 through line 4 (where line numbers are zero-based) with the string "\nfrom sac.datasets import Data\n\nos\nData\n". The second change should simply strip the final LF from the file. After these deltas are applied, the resulting source file should be as follows (with the final LF stripped). import os
from sac.datasets import Data
os
Data From the screen shot, I can see that pyright is reporting the from sac.datasets import Data
os
Data Note that the first line has been stripped out when it should still be present. If my theory is correct, the next question is why the internal state of the file contents have been corrupted when applying these deltas. When applying deltas, pyright relies on the Perhaps someone from the pylance team could look at this further and let me know if you have any other theories or debugging suggestions. @debonte, @rchiodo, @heejaechang |
Hi Eric, Thank you for the analysis! I'd like to mention that project nesting (the existence of |
I wonder if the presence of two files with overlapping names is related? Could you try renaming the outer file something like It looks from the screen shot that you're on a Mac? I ask because MacOS file systems are case insensitive. I'm not sure that matters here, but it's a useful clue. |
@erictraut No, the same filename is not related to the bug. I just renamed Yes, I am on a Mac. I also tested other Python language servers: jedi and python-language-server. They are fine. |
I have a hypothesis that when I performed step 3-4, pyright or pylance changed the "project root" from |
so, from the log, what I am seeing is that There are 2 workspaces
one is added when server is created
the other is added when
using this info, I have setup the repro env with the given zip file and ran
that is different than what you have in the log.
the first weird thing is (it could be just how it log things), contentChanges used The end impact looks like the whole content we have is replaced with my gut feeling is |
For used According to my hypothesis, even if everything is exactly the same, the following msg
cannot trigger the bug, since it is just adding an You can see the line number of the error is wrong. |
Attach the new log. Note that although this is long, one of response is around 5000 lines. |
this is not adding |
Yes, this might be the case if everything works correctly in the vscode for you. But I am trying to provide a reason to explain the bug I saw:
I don't think this is a problem that neovim is generating a problematic |
@zhou13 can you point me in the log where this happens
we do not change |
Also, once the files are open in the editor, we're working from in-memory contents. We don't go back to the file system unless/until the file has been closed in the editor. So the theory about applying the delta to the wrong file doesn't sound right to me. @zhou13, are you able to rebuild pyright from source? If so, I could show you where you can add a bit of additional logging code that would help diagnose the problem. |
Yes, I can rebuild pyright from source. |
Please check out the latest sources for pyright. Then go to the source file this._console.log(`Updating file contents for ${this._filePath}`);
this._console.log('Old file contents:');
this._console.log(this._clientDocument.getText());
this._clientDocument = TextDocument.update(this._clientDocument, contents, version);
this._console.log('New file contents:');
this._console.log(this._clientDocument.getText()); Rebuild pyright and repro the bug. Let's see what clues these logs give us. |
Actually, I found a way to reliably reproduce this bug without neovim by just replaying stdio. I can successfully reproduce it on both linux and mac. To do that, you first need a unix-like machine and unzip the file to The file structure should looks like this:
Simply run
to replay the problem. Note that Here is the example putout:
|
@zhou13, thanks for the repro. I figured out the underlying cause. Now we need to determine how to fix it. The problem is that the source file is part of two different workspaces, but it is opened in the first workspace before the language server is made aware of the second workspace. We have two separate language server instances — one for each of the two workspaces, but only the first one has received the "open file" command along with the initial contents of the file. When we apply the delta change to both instances, the first one works fine, but the second one applies the delta to an empty file. |
@heejaechang, this is related to the conversation we had recently about sharing file contents across workspaces in the case where a file is associated with more than one workspace. Our discussion was focussed on memory and CPU, but it's now clear that there's a correctness issue as well. Perhaps we should maintain a map of open files and their contents within the languageServerBase and simply send the updated contents to each of the service instances. That way, the text would be shared between them. |
tagging @rchiodo
I believe Rich has fixed the issue in this PR - 68a8e98#diff-8a9e7373556006db29659ed8820a21073840a944192d2b49977c032276f1f979R1283 so we should already do that. there might be a bug in |
I don't think Rich's change addresses this problem. That logic is able to send "open file" and "document changed" events to all relevant workspaces, but if the workspace list changes and a new workspace is added between an "open file" and a "document changed" event, it doesn't synthesize an "open file" event for the new workspace. |
ah. I miss understood. yes. the file is already opened when new workspace is added. This can't happen with
ya, when we get |
…responsible for applying any delta changes and updating the contents for each of the workspaces associated with that file. This allows source code contents to be shared between workspaces, which reduces memory usage. It also eliminates a correctness issue that can occur if new workspaces are added after files are open. It addresses #4994.
I have a proposed fix ready for review in this PR. |
…responsible for applying any delta changes and updating the contents for each of the workspaces associated with that file. This allows source code contents to be shared between workspaces, which reduces memory usage. It also eliminates a correctness issue that can occur if new workspaces are added after files are open. It addresses #4994.
PR is merged. This will be addressed in the next release. |
This is addressed in pyright 1.1.306, which I just published. |
Describe the bug
Let's say we have a project structure like this:
I attached the example files in Archive.zip
With certain operation, pyright-lsp may enter a strange state reporting system library like os not found.
To Reproduce
The following sequence has 100% chance to trigger the bug on my Mac:
nvim projects/example.py example.py
:bnext
or:BufferPrev
bprev
or:BufferPrev
os
not found.Expected behavior
pyright-lsp should not enter a strange state reporting
os
not found.Screenshots or Code
VS Code extension or command-line
I am using vim-lsp with pyright. I attached the lsp log for analysis, which contains all the communication in a json-like format:
lsp.log
I am not sure whether it is possible to write a reproducible script by communicating with pyright-lsp in command-line tools. I will be happy to do that if there is a pointer.
Additional context
projects/requirements.txt
, then this bug is not reproducible.textDocument/didChange
The text was updated successfully, but these errors were encountered: