Compare commits

...

2 commits

Author SHA1 Message Date
dece d3e015a51a readme: set license to GPLv3 2022-12-03 16:40:05 +01:00
dece a8d44fa619 server: implement basic hover 2022-12-03 16:39:56 +01:00
2 changed files with 56 additions and 5 deletions

View file

@ -6,7 +6,21 @@ Minimal Python language server, based on [Jedi][jedi] and [pygls][pygls].
[jedi]: https://jedi.readthedocs.io/en/latest/index.html [jedi]: https://jedi.readthedocs.io/en/latest/index.html
[pygls]: https://pygls.readthedocs.io/en/latest/index.html [pygls]: https://pygls.readthedocs.io/en/latest/index.html
WIP. WIP! ⚠ 👷🚧
Supported features:
| LSP method | Description |
|---------------------------|---------------|
| `textDocument/completion` | Completions |
| `textDocument/hover` | Documentation |
Install
-------
TODO
@ -34,3 +48,7 @@ HA!
Take the string “Is this a Star Wars reference?” Language Server, compress it to Take the string “Is this a Star Wars reference?” Language Server, compress it to
`ITASWRLS` and expand it back to Italian Swirls. Italian dishes are made of few `ITASWRLS` and expand it back to Italian Swirls. Italian dishes are made of few
elements that work well together. Enough questions! elements that work well together. Enough questions!
### License
GPLv3.

View file

@ -1,10 +1,11 @@
import logging import logging
from jedi import Script from jedi import Script
from pygls.lsp.methods import COMPLETION, INITIALIZE from pygls.lsp.methods import COMPLETION, HOVER, INITIALIZE
from pygls.lsp.types import (CompletionItem, CompletionItemKind, from pygls.lsp.types import (CompletionItem, CompletionItemKind,
CompletionList, CompletionOptions, CompletionList, CompletionOptions,
CompletionParams, InsertTextFormat, Position) CompletionParams, Hover, InsertTextFormat,
Position, TextDocumentPositionParams)
from pygls.server import LanguageServer from pygls.server import LanguageServer
from pygls.workspace import Document from pygls.workspace import Document
@ -50,14 +51,16 @@ async def do_initialize(*args):
@LS.feature(COMPLETION, CompletionOptions(trigger_characters=["."])) @LS.feature(COMPLETION, CompletionOptions(trigger_characters=["."]))
async def do_completion(server: LanguageServer, params: CompletionParams): async def do_completion(
server: LanguageServer,
params: CompletionParams,
) -> CompletionList:
"""Return completion items.""" """Return completion items."""
document_uri = params.text_document.uri document_uri = params.text_document.uri
document = server.workspace.get_document(document_uri) document = server.workspace.get_document(document_uri)
script = get_jedi_script(document) script = get_jedi_script(document)
jedi_position = get_jedi_position(params.position) jedi_position = get_jedi_position(params.position)
jedi_completions = script.complete(*jedi_position) jedi_completions = script.complete(*jedi_position)
LOG.debug(f"Completions: {jedi_completions}")
completion_items = [] completion_items = []
for jedi_completion in jedi_completions: for jedi_completion in jedi_completions:
@ -78,5 +81,35 @@ async def do_completion(server: LanguageServer, params: CompletionParams):
) )
@LS.feature(HOVER)
async def do_hover(
server: LanguageServer,
params: TextDocumentPositionParams,
) -> Hover:
"""Provide "hover", which is documentation of a symbol.
Jedi provides a list of names with information, usually only one. We handle
them all and concatenate them, separated by a horizontal line. For
simplicity, the text is mostly provided untouched.
"""
document_uri = params.text_document.uri
document = server.workspace.get_document(document_uri)
script = get_jedi_script(document)
jedi_position = get_jedi_position(params.position)
jedi_help_names = script.help(*jedi_position)
help_texts = []
for jedi_name in jedi_help_names:
text = f"`{jedi_name.full_name}`"
if sigs := jedi_name.get_signatures():
text += "\n" + "\n".join(f"`{sig.to_string()}`" for sig in sigs)
if docstring := jedi_name.docstring(raw=True):
text += "\n\n" + docstring
help_texts.append(text)
hover_text = "\n\n---\n\n".join(help_texts)
return Hover(contents=hover_text) # TODO range
if __name__ == "__main__": if __name__ == "__main__":
LS.start_io() LS.start_io()