Skip to content

Commit 8aef81d

Browse files
authored
Remove null fields form LSP response (microsoft#15329)
* Remove null fields form LSP response * Addressing comments * Add unicode for 2.7 and address comments * Cleanup comments * Simplify how we check for unicode availability * Address comments and add support for dicts * Using filter instead of list comprehension
1 parent 28e0350 commit 8aef81d

1 file changed

Lines changed: 81 additions & 0 deletions

File tree

pythonFiles/runJediLanguageServer.py

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,87 @@
55
EXTENSION_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
66
sys.path.append(os.path.join(EXTENSION_ROOT, "pythonFiles", "lib", "python"))
77

8+
import pygls.protocol
9+
10+
try:
11+
unicode
12+
except Exception:
13+
unicode = str
14+
15+
16+
def is_json_basic_type(obj):
17+
"""Checks if the object is an int, float, bool, or str."""
18+
if isinstance(obj, (int, float, bool, str)):
19+
return True
20+
return sys.version_info < (3,) and isinstance(obj, unicode)
21+
22+
23+
def handle_null_fields(obj, obj_field_name=None):
24+
"""Removes fields with a 'None' value.
25+
26+
The LS Client in VS Code expects optional fields that are not needed
27+
to be omitted. Unfortunately, pygls uses 'null' in these instances.
28+
"""
29+
# This is a temporary workaround to address the following issues:
30+
# https://github.com/microsoft/vscode-languageserver-node/issues/740#issuecomment-773967897
31+
# https://github.com/pappasam/jedi-language-server/issues/60
32+
# https://github.com/openlawlibrary/pygls/issues/145
33+
# https://github.com/microsoft/vscode-languageserver-node/issues/740
34+
if is_json_basic_type(obj):
35+
return
36+
elif isinstance(obj, list):
37+
for o in obj:
38+
handle_null_fields(o, obj_field_name)
39+
return
40+
elif isinstance(obj, dict):
41+
for k, v in obj.items():
42+
handle_null_fields(v, k)
43+
44+
important_attribute = lambda x: not x.startswith("_") and not callable(
45+
getattr(obj, x)
46+
)
47+
48+
for attr in filter(important_attribute, dir(obj)):
49+
member = getattr(obj, attr)
50+
if member is None:
51+
# This is a special condition to handle VersionedTextDocumentIdentifier object.
52+
# See issues:
53+
# https://github.com/pappasam/jedi-language-server/issues/61
54+
# https://github.com/openlawlibrary/pygls/issues/146
55+
#
56+
# The version field should either use `0` or the value received from `client`.
57+
# Seems like using `null` or removing this causes VS Code to ignore
58+
# code actions.
59+
if (
60+
attr == "version"
61+
and obj_field_name == "textDocument"
62+
and "uri" in dir(obj)
63+
):
64+
setattr(obj, "version", 0)
65+
else:
66+
delattr(obj, attr)
67+
68+
elif is_json_basic_type(member):
69+
continue
70+
71+
else:
72+
handle_null_fields(member, attr)
73+
74+
75+
def patched_without_none_fields(resp):
76+
"""Monkeypatch for `JsonRPCResponseMessage.without_none_fields` to remove `None` results."""
77+
if resp.error is None:
78+
del resp.error
79+
if hasattr(resp, "result"):
80+
handle_null_fields(resp.result)
81+
else:
82+
del resp.result
83+
return resp
84+
85+
86+
pygls.protocol.JsonRPCResponseMessage.without_none_fields = patched_without_none_fields
87+
88+
889
from jedi_language_server.cli import cli
990

1091
sys.exit(cli())

0 commit comments

Comments
 (0)