microsoft / monitors4codegen

Code and Data artifact for NeurIPS 2023 paper - "Monitor-Guided Decoding of Code LMs with Static Analysis of Repository Context". `multispy` is a lsp client library in Python intended to be used to build applications around language servers.
https://www.microsoft.com/en-us/research/publication/guiding-language-models-of-code-with-global-context-using-monitors/
MIT License
189 stars 25 forks source link

Allow easy usage of external Language Servers in `multilspy` #24

Open Moosems opened 2 months ago

Moosems commented 2 months ago

If I want to use ruff server as a user and know the command to use and the specific initialization parameters/runtime dependencies it might require, it doesn't seem like it would be too difficult to allow the user to use their own Language Servers if they would be allowed to.

LakshyAAAgrawal commented 2 months ago

Dear @Moosems,

Thanks a lot for the great suggestion. Do you have a specific interface in mind that would benefit your usecase? Once we have discussed that, it could be implemented and merged quickly.

adlternative commented 2 months ago

If multilspy could be extracted, that would be great. I am looking forward to it :)

Moosems commented 2 months ago

@LakshyAAAgrawal I would imagine it looking something looking something like this:

from monitors4codegen.multilspy import LanguageServer
from monitors4codegen.multilspy.multilspy_config import MultilspyConfig, DefaultInitParams, JavaLang # Python, Rust, and other languages come with language servers
from monitors4codegen.multilspy.multilspy_logger import MultilspyLogger

from time import sleep
...
java_config = MultilspyConfig(language="Java", language_server=JavaLang, init_params=DefaultInitParams)
java_logger = MultilspyLogger()
java_lsp = LanguageServer(java_config, "/abs/path/to/project/root/", logger) # Make the logger default to None and not require it but still allow it (and highly recommend it)
# The server start should probably be automatic as well
java_lsp.open_file("relative/path/to/code_file.java") # Tell the langserver a file has been opened and theoretically allow the flexibility of code snippets
result = java_lsp.request( # use a standard request method that takes a command and pattern matches instead of using a bunch of boilerplate functions
    "Definitions", # We can also add a set of string constants to give a form of spell checking
    "relative/path/to/code_file.java", # Filename of location where request is being made (now the Language Server will use the current state of the file as we describe it)
    # This also means I don't have to save the file on every change
    163, # line number of symbol for which request is being made
    4 # column number of symbol for which request is being made
)
result2 = lsp.request(
    "Completions",
    ...
)
java_lsp.try_kill()
sleep(0.5)
java_lsp.check_kill()
...
custom_py_config = MultilspyConfig(language="Python", language_server=["ruff", "server", "--preview"], init_params=DefaultInitParams) # We can allow a custom server
py_logger = MultilspyLogger()
ruff_langserver = LanguageServer(custom_py_config, "some/random/path", py_logger) # Again, make logging optional
ruff_langserver.try_kill()
sleep(0.5) # Sometimes it takes a moment for the langserver to die but forcing asyncio is also not a great option (I like how it's completely optional in it's current state)
ruff_langserver.check_kill()

I would also highly recommend putting the package on pypi as it simplifies imports for most projects and makes it more approachable for many. Some good docs on the necessary arguments for any given command in this new system would also be great. I would be more than willing to give a hand at trying to write docs if that makes this any more appealing :D

My hope is for there to be a LSP system as flexible and powerful as possible while still allowing it to be easy to use and provide easy defaults when the user doesn't need much customization all in Python.

Moosems commented 2 months ago

A force_kill option should also be provided if the server starts to freak out and stops responding but should be a last resort