Did personalizxed formatting; example cleanup; added some client commands

This commit is contained in:
itdominator 2023-11-11 23:38:53 -06:00
parent fc6e645261
commit 248771d57e
5 changed files with 350 additions and 247 deletions

View File

@ -1,8 +1,12 @@
#from __future__ import absolute_import
__all__ = [] __all__ = []
from pylspclient.json_rpc_endpoint import JsonRpcEndpoint # Python imports
from pylspclient.lsp_client import LspClient
from pylspclient.lsp_endpoint import LspEndpoint # Lib imports
from pylspclient import lsp_structs
# Application imports
from .json_rpc_endpoint import JsonRpcEndpoint
from .lsp_client import LspClient
from .lsp_endpoint import LspEndpoint
from . import lsp_structs

View File

@ -1,17 +1,25 @@
# Python imports
from __future__ import print_function from __future__ import print_function
import json import json
import re import re
from pylspclient import lsp_structs
import threading import threading
JSON_RPC_REQ_FORMAT = "Content-Length: {json_string_len}\r\n\r\n{json_string}" # Lib imports
LEN_HEADER = "Content-Length: "
TYPE_HEADER = "Content-Type: "
# Application imports
from . import lsp_structs
JSON_RPC_REQ_FORMAT = "Content-Length: {json_string_len}\r\n\r\n{json_string}"
LEN_HEADER = "Content-Length: "
TYPE_HEADER = "Content-Type: "
# TODO: add content-type # TODO: add content-type
class MyEncoder(json.JSONEncoder): class MyEncoder(json.JSONEncoder):
""" """
Encodes an object in JSON Encodes an object in JSON
@ -26,10 +34,10 @@ class JsonRpcEndpoint(object):
protocol. More information can be found: https://www.jsonrpc.org/ protocol. More information can be found: https://www.jsonrpc.org/
''' '''
def __init__(self, stdin, stdout): def __init__(self, stdin, stdout):
self.stdin = stdin self.stdin = stdin
self.stdout = stdout self.stdout = stdout
self.read_lock = threading.Lock() self.read_lock = threading.Lock()
self.write_lock = threading.Lock() self.write_lock = threading.Lock()
@staticmethod @staticmethod
def __add_header(json_string): def __add_header(json_string):
@ -39,7 +47,7 @@ class JsonRpcEndpoint(object):
:param str json_string: The string :param str json_string: The string
:return: the string with the header :return: the string with the header
''' '''
return JSON_RPC_REQ_FORMAT.format(json_string_len=len(json_string), json_string=json_string) return JSON_RPC_REQ_FORMAT.format(json_string_len = len(json_string), json_string = json_string)
def send_request(self, message): def send_request(self, message):
@ -48,7 +56,7 @@ class JsonRpcEndpoint(object):
:param dict message: The message to send. :param dict message: The message to send.
''' '''
json_string = json.dumps(message, cls=MyEncoder) json_string = json.dumps(message, cls = MyEncoder)
jsonrpc_req = self.__add_header(json_string) jsonrpc_req = self.__add_header(json_string)
with self.write_lock: with self.write_lock:
self.stdin.write(jsonrpc_req.encode()) self.stdin.write(jsonrpc_req.encode())
@ -64,18 +72,16 @@ class JsonRpcEndpoint(object):
with self.read_lock: with self.read_lock:
message_size = None message_size = None
while True: while True:
#read header
line = self.stdout.readline() line = self.stdout.readline()
if not line: if not line:
# server quit
return None return None
line = line.decode("utf-8") line = line.decode("utf-8")
if not line.endswith("\r\n"): if not line.endswith("\r\n"):
raise lsp_structs.ResponseError(lsp_structs.ErrorCodes.ParseError, "Bad header: missing newline") raise lsp_structs.ResponseError(lsp_structs.ErrorCodes.ParseError, "Bad header: missing newline")
#remove the "\r\n"
line = line[:-2] line = line[:-2] #remove the "\r\n"
if line == "": if line == "":
# done with the headers
break break
elif line.startswith(LEN_HEADER): elif line.startswith(LEN_HEADER):
line = line[len(LEN_HEADER):] line = line[len(LEN_HEADER):]
@ -83,12 +89,12 @@ class JsonRpcEndpoint(object):
raise lsp_structs.ResponseError(lsp_structs.ErrorCodes.ParseError, "Bad header: size is not int") raise lsp_structs.ResponseError(lsp_structs.ErrorCodes.ParseError, "Bad header: size is not int")
message_size = int(line) message_size = int(line)
elif line.startswith(TYPE_HEADER): elif line.startswith(TYPE_HEADER):
# nothing todo with type for now. ...
pass
else: else:
raise lsp_structs.ResponseError(lsp_structs.ErrorCodes.ParseError, "Bad header: unkown header") raise lsp_structs.ResponseError(lsp_structs.ErrorCodes.ParseError, "Bad header: unkown header")
if not message_size: if not message_size:
raise lsp_structs.ResponseError(lsp_structs.ErrorCodes.ParseError, "Bad header: missing size") raise lsp_structs.ResponseError(lsp_structs.ErrorCodes.ParseError, "Bad header: missing size")
jsonrpc_res = self.stdout.read(message_size).decode("utf-8") jsonrpc_res = self.stdout.read(message_size).decode("utf-8")
return json.loads(jsonrpc_res) return json.loads(jsonrpc_res)

View File

@ -1,4 +1,11 @@
from pylspclient import lsp_structs # Python imports
# Lib imports
# Application imports
from . import lsp_structs
class LspClient(object): class LspClient(object):
def __init__(self, lsp_endpoint): def __init__(self, lsp_endpoint):
@ -7,20 +14,20 @@ class LspClient(object):
:param lsp_endpoint: TODO :param lsp_endpoint: TODO
""" """
self.lsp_endpoint = lsp_endpoint
self.lsp_endpoint = lsp_endpoint
def initialize(self, processId, rootPath, rootUri, initializationOptions, capabilities, trace, workspaceFolders): def initialize(self, processId, rootPath, rootUri, initializationOptions, capabilities, trace, workspaceFolders):
""" """
The initialize request is sent as the first request from the client to the server. If the server receives a request or notification The initialize request is sent as the first request from the client to the server. If the server receives a request or notification
before the initialize request it should act as follows: before the initialize request it should act as follows:
1. For a request the response should be an error with code: -32002. The message can be picked by the server. 1. For a request the response should be an error with code: -32002. The message can be picked by the server.
2. Notifications should be dropped, except for the exit notification. This will allow the exit of a server without an initialize request. 2. Notifications should be dropped, except for the exit notification. This will allow the exit of a server without an initialize request.
Until the server has responded to the initialize request with an InitializeResult, the client must not send any additional requests or Until the server has responded to the initialize request with an InitializeResult, the client must not send any additional requests or
notifications to the server. In addition the server is not allowed to send any requests or notifications to the client until it has responded notifications to the server. In addition the server is not allowed to send any requests or notifications to the client until it has responded
with an InitializeResult, with the exception that during the initialize request the server is allowed to send the notifications window/showMessage, with an InitializeResult, with the exception that during the initialize request the server is allowed to send the notifications window/showMessage,
window/logMessage and telemetry/event as well as the window/showMessageRequest request to the client. window/logMessage and telemetry/event as well as the window/showMessageRequest request to the client.
The initialize request may only be sent once. The initialize request may only be sent once.
@ -36,9 +43,17 @@ class LspClient(object):
:param list workspaceFolders: The workspace folders configured in the client when the server starts. This property is only available if the client supports workspace folders. :param list workspaceFolders: The workspace folders configured in the client when the server starts. This property is only available if the client supports workspace folders.
It can be `null` if the client supports workspace folders but none are configured. It can be `null` if the client supports workspace folders but none are configured.
""" """
self.lsp_endpoint.start()
return self.lsp_endpoint.call_method("initialize", processId=processId, rootPath=rootPath, rootUri=rootUri, initializationOptions=initializationOptions, capabilities=capabilities, trace=trace, workspaceFolders=workspaceFolders)
self.lsp_endpoint.start()
return self.lsp_endpoint.call_method("initialize",
processId = processId,
rootPath = rootPath,
rootUri = rootUri,
initializationOptions = initializationOptions,
capabilities = capabilities,
trace = trace,
workspaceFolders = workspaceFolders
)
def initialized(self): def initialized(self):
""" """
@ -46,150 +61,197 @@ class LspClient(object):
but before the client is sending any other request or notification to the server. The server can use the initialized notification but before the client is sending any other request or notification to the server. The server can use the initialized notification
for example to dynamically register capabilities. The initialized notification may only be sent once. for example to dynamically register capabilities. The initialized notification may only be sent once.
""" """
self.lsp_endpoint.send_notification("initialized")
self.lsp_endpoint.send_notification("initialized")
def shutdown(self): def shutdown(self):
""" """
The initialized notification is sent from the client to the server after the client received the result of the initialize request
but before the client is sending any other request or notification to the server. The server can use the initialized notification
for example to dynamically register capabilities. The initialized notification may only be sent once.
""" """
self.lsp_endpoint.stop()
return self.lsp_endpoint.call_method("shutdown") return self.lsp_endpoint.call_method("shutdown")
def exit(self): def exit(self):
""" """
The initialized notification is sent from the client to the server after the client received the result of the initialize request
but before the client is sending any other request or notification to the server. The server can use the initialized notification
for example to dynamically register capabilities. The initialized notification may only be sent once.
""" """
self.lsp_endpoint.send_notification("exit") self.lsp_endpoint.send_notification("exit")
self.lsp_endpoint.stop()
def didOpen(self, textDocument): def didOpen(self, textDocument):
""" """
The document open notification is sent from the client to the server to signal newly opened text documents. The document's truth is The document open notification is sent from the client to the server to signal newly opened text documents. The document's truth is
now managed by the client and the server must not try to read the document's truth using the document's uri. Open in this sense now managed by the client and the server must not try to read the document's truth using the document's uri. Open in this sense
means it is managed by the client. It doesn't necessarily mean that its content is presented in an editor. An open notification must means it is managed by the client. It doesn't necessarily mean that its content is presented in an editor. An open notification must
not be sent more than once without a corresponding close notification send before. This means open and close notification must be not be sent more than once without a corresponding close notification send before. This means open and close notification must be
balanced and the max open count for a particular textDocument is one. Note that a server's ability to fulfill requests is independent balanced and the max open count for a particular textDocument is one. Note that a server's ability to fulfill requests is independent
of whether a text document is open or closed. of whether a text document is open or closed.
The DidOpenTextDocumentParams contain the language id the document is associated with. If the language Id of a document changes, the The DidOpenTextDocumentParams contain the language id the document is associated with. If the language Id of a document changes, the
client needs to send a textDocument/didClose to the server followed by a textDocument/didOpen with the new language id if the server client needs to send a textDocument/didClose to the server followed by a textDocument/didOpen with the new language id if the server
handles the new language id as well. handles the new language id as well.
:param TextDocumentItem textDocument: The document that was opened. :param TextDocumentItem textDocument: The document that was opened.
""" """
return self.lsp_endpoint.send_notification("textDocument/didOpen", textDocument=textDocument)
return self.lsp_endpoint.send_notification("textDocument/didOpen", textDocument = textDocument)
def didSave(self, textDocument):
"""
:param TextDocumentIdentifier textDocument: The document that was saved.
"""
return self.lsp_endpoint.send_notification("textDocument/didSave", textDocument = textDocument)
def didClose(self, textDocument):
"""
:param TextDocumentIdentifier textDocument: The document that was closed.
"""
return self.lsp_endpoint.send_notification("textDocument/didClose", textDocument = textDocument)
def didChange(self, textDocument, contentChanges): def didChange(self, textDocument, contentChanges):
""" """
The document change notification is sent from the client to the server to signal changes to a text document. The document change notification is sent from the client to the server to signal changes to a text document.
In 2.0 the shape of the params has changed to include proper version numbers and language ids. In 2.0 the shape of the params has changed to include proper version numbers and language ids.
:param VersionedTextDocumentIdentifier textDocument: The initial trace setting. If omitted trace is disabled ('off'). :param VersionedTextDocumentIdentifier textDocument: The initial trace setting. If omitted trace is disabled ('off').
:param TextDocumentContentChangeEvent[] contentChanges: The actual content changes. The content changes describe single state changes :param TextDocumentContentChangeEvent[] contentChanges: The actual content changes. The content changes describe single state changes
to the document. So if there are two content changes c1 and c2 for a document in state S then c1 move the document to the document. So if there are two content changes c1 and c2 for a document in state S then c1 move the document
to S' and c2 to S''. to S' and c2 to S''.
""" """
return self.lsp_endpoint.send_notification("textDocument/didChange", textDocument=textDocument, contentChanges=contentChanges)
return self.lsp_endpoint.send_notification("textDocument/didChange", textDocument = textDocument, contentChanges = contentChanges)
def documentSymbol(self, textDocument): def documentSymbol(self, textDocument):
""" """
The document symbol request is sent from the client to the server to return a flat list of all symbols found in a given text document. The document symbol request is sent from the client to the server to
Neither the symbol's location range nor the symbol's container name should be used to infer a hierarchy. return a flat list of all symbols found in a given text document.
Neither the symbol's location range nor the symbol's container name
should be used to infer a hierarchy.
:param TextDocumentItem textDocument: The text document. :param TextDocumentItem textDocument: The text document.
""" """
result_dict = self.lsp_endpoint.call_method("textDocument/documentSymbol", textDocument=textDocument) result_dict = self.lsp_endpoint.call_method( "textDocument/documentSymbol", textDocument=textDocument )
if not result_dict: return []
return [lsp_structs.SymbolInformation(**sym) for sym in result_dict] return [lsp_structs.SymbolInformation(**sym) for sym in result_dict]
def declaration(self, textDocument, position):
def definition(self, textDocument, position):
""" """
The goto definition request is sent from the client to the server to resolve the definition location of a symbol at a given text document position. The go to declaration request is sent from the client to the server to
resolve the declaration location of a symbol at a given text document
position.
The result type LocationLink[] got introduce with version 3.14.0 and
depends in the corresponding client capability
`clientCapabilities.textDocument.declaration.linkSupport`.
:param TextDocumentItem textDocument: The text document. :param TextDocumentItem textDocument: The text document.
:param Position position: The position inside the text document. :param Position position: The position inside the text document.
""" """
result_dict = self.lsp_endpoint.call_method("textDocument/definition", textDocument=textDocument, position=position)
return [lsp_structs.Location(**l) for l in result_dict]
result_dict = self.lsp_endpoint.call_method("textDocument/declaration",
textDocument = textDocument,
position = position
)
if not result_dict: return []
if "uri" in result_dict:
return lsp_structs.Location(**result_dict)
return [lsp_structs.Location(**loc) if "uri" in loc else lsp_structs.LinkLocation(**loc) for loc in result_dict]
def definition(self, textDocument, position):
"""
The goto definition request is sent from the client to the server to
resolve the definition location of a symbol at a given text document
position.
:param TextDocumentItem textDocument: The text document.
:param Position position: The position inside the text document.
"""
result_dict = self.lsp_endpoint.call_method("textDocument/definition",
textDocument = textDocument,
position = position
)
if not result_dict: return []
return [lsp_structs.Location(**loc) for loc in result_dict]
def typeDefinition(self, textDocument, position): def typeDefinition(self, textDocument, position):
""" """
The goto type definition request is sent from the client to the server to resolve the type definition location of a symbol at a given text document position. The goto type definition request is sent from the client to the server
to resolve the type definition location of a symbol at a given text
document position.
:param TextDocumentItem textDocument: The text document. :param TextDocumentItem textDocument: The text document.
:param Position position: The position inside the text document. :param Position position: The position inside the text document.
""" """
result_dict = self.lsp_endpoint.call_method("textDocument/definition", textDocument=textDocument, position=position)
return [lsp_structs.Location(**l) for l in result_dict]
result_dict = self.lsp_endpoint.call_method("textDocument/typeDefinition",
textDocument = textDocument,
position = position
)
if not result_dict: return []
return [lsp_structs.Location(**loc) for loc in result_dict]
def signatureHelp(self, textDocument, position): def signatureHelp(self, textDocument, position):
""" """
The signature help request is sent from the client to the server to request signature information at a given cursor position. The signature help request is sent from the client to the server to
request signature information at a given cursor position.
:param TextDocumentItem textDocument: The text document. :param TextDocumentItem textDocument: The text document.
:param Position position: The position inside the text document. :param Position position: The position inside the text document.
""" """
result_dict = self.lsp_endpoint.call_method("textDocument/signatureHelp", textDocument=textDocument, position=position)
return lsp_structs.SignatureHelp(**result_dict)
result_dict = self.lsp_endpoint.call_method( "textDocument/signatureHelp",
textDocument = textDocument,
position = position
)
if not result_dict: return []
return lsp_structs.SignatureHelp(**result_dict)
def completion(self, textDocument, position, context): def completion(self, textDocument, position, context):
""" """
The signature help request is sent from the client to the server to request signature information at a given cursor position. The signature help request is sent from the client to the server to
request signature information at a given cursor position.
:param TextDocumentItem textDocument: The text document. :param TextDocumentItem textDocument: The text document.
:param Position position: The position inside the text document. :param Position position: The position inside the text document.
:param CompletionContext context: The completion context. This is only available if the client specifies :param CompletionContext context: The completion context. This is only
to send this using `ClientCapabilities.textDocument.completion.contextSupport === true` available if the client specifies
""" to send this using `ClientCapabilities.textDocument.completion.contextSupport === true`
result_dict = self.lsp_endpoint.call_method("textDocument/completion", textDocument=textDocument, position=position, context=context) """
if "isIncomplete" in result_dict:
return lsp_structs.CompletionList(**result_dict)
return [lsp_structs.CompletionItem(**l) for l in result_dict]
def declaration(self, textDocument, position):
"""
The go to declaration request is sent from the client to the server to resolve the declaration location of a
symbol at a given text document position.
The result type LocationLink[] got introduce with version 3.14.0 and depends in the corresponding client result_dict = self.lsp_endpoint.call_method("textDocument/completion",
capability `clientCapabilities.textDocument.declaration.linkSupport`. textDocument = textDocument,
position = position,
context = context
)
if not result_dict: return []
:param TextDocumentItem textDocument: The text document. if "isIncomplete" in result_dict:
:param Position position: The position inside the text document. return lsp_structs.CompletionList(**result_dict)
"""
result_dict = self.lsp_endpoint.call_method("textDocument/declaration", textDocument=textDocument, position=position)
if "uri" in result_dict:
return lsp_structs.Location(**result_dict)
return [lsp_structs.Location(**l) if "uri" in l else lsp_structs.LinkLocation(**l) for l in result_dict] return [lsp_structs.CompletionItem(**loc) for loc in result_dict]
def definition(self, textDocument, position): def references(self, textDocument, position):
""" """
The go to definition request is sent from the client to the server to resolve the declaration location of a The references request is sent from the client to the server to resolve
symbol at a given text document position. project-wide references for the symbol denoted by the given text
document position.
The result type LocationLink[] got introduce with version 3.14.0 and depends in the corresponding client :param TextDocumentItem textDocument: The text document.
capability `clientCapabilities.textDocument.declaration.linkSupport`. :param Position position: The position inside the text document.
"""
:param TextDocumentItem textDocument: The text document. result_dict = self.lsp_endpoint.call_method("textDocument/references",
:param Position position: The position inside the text document. textDocument = textDocument,
""" position = position)
result_dict = self.lsp_endpoint.call_method("textDocument/definition", textDocument=textDocument, position=position)
if "uri" in result_dict:
return lsp_structs.Location(**result_dict)
return [lsp_structs.Location(**l) if "uri" in l else lsp_structs.LinkLocation(**l) for l in result_dict] if not result_dict: return []
return [lsp_structs.Location(**loc) for loc in result_dict]

View File

@ -1,20 +1,27 @@
# Python imports
from __future__ import print_function from __future__ import print_function
import threading import threading
import collections import collections
from pylspclient import lsp_structs
# Lib imports
# Application imports
from . import lsp_structs
class LspEndpoint(threading.Thread): class LspEndpoint(threading.Thread):
def __init__(self, json_rpc_endpoint, method_callbacks={}, notify_callbacks={}, timeout=2): def __init__(self, json_rpc_endpoint, method_callbacks={}, notify_callbacks={}, timeout=2):
threading.Thread.__init__(self) threading.Thread.__init__(self)
self.json_rpc_endpoint = json_rpc_endpoint self.json_rpc_endpoint = json_rpc_endpoint
self.notify_callbacks = notify_callbacks self.notify_callbacks = notify_callbacks
self.method_callbacks = method_callbacks self.method_callbacks = method_callbacks
self.event_dict = {} self.event_dict = {}
self.response_dict = {} self.response_dict = {}
self.next_id = 0 self.next_id = 0
self._timeout = timeout self._timeout = timeout
self.shutdown_flag = False self.shutdown_flag = False
def handle_result(self, rpc_id, result, error): def handle_result(self, rpc_id, result, error):
@ -34,25 +41,23 @@ class LspEndpoint(threading.Thread):
try: try:
jsonrpc_message = self.json_rpc_endpoint.recv_response() jsonrpc_message = self.json_rpc_endpoint.recv_response()
if jsonrpc_message is None: if jsonrpc_message is None:
print("server quit") print("Server Quit...")
break break
method = jsonrpc_message.get("method") method = jsonrpc_message.get("method")
result = jsonrpc_message.get("result") result = jsonrpc_message.get("result")
error = jsonrpc_message.get("error") error = jsonrpc_message.get("error")
rpc_id = jsonrpc_message.get("id") rpc_id = jsonrpc_message.get("id")
params = jsonrpc_message.get("params") params = jsonrpc_message.get("params")
if method: if method:
if rpc_id: if rpc_id:
# a call for method
if method not in self.method_callbacks: if method not in self.method_callbacks:
raise lsp_structs.ResponseError(lsp_structs.ErrorCodes.MethodNotFound, "Method not found: {method}".format(method=method)) raise lsp_structs.ResponseError(lsp_structs.ErrorCodes.MethodNotFound, "Method not found: {method}".format(method=method))
result = self.method_callbacks[method](params) result = self.method_callbacks[method](params)
self.send_response(rpc_id, result, None) self.send_response(rpc_id, result, None)
else: else:
# a call for notify
if method not in self.notify_callbacks: if method not in self.notify_callbacks:
# Have nothing to do with this.
print("Notify method not found: {method}.".format(method=method)) print("Notify method not found: {method}.".format(method=method))
else: else:
self.notify_callbacks[method](params) self.notify_callbacks[method](params)
@ -63,13 +68,13 @@ class LspEndpoint(threading.Thread):
def send_response(self, id, result, error): def send_response(self, id, result, error):
message_dict = {} message_dict = {}
message_dict["jsonrpc"] = "2.0" message_dict["jsonrpc"] = "2.0"
message_dict["id"] = id message_dict["id"] = id
if result: if result:
message_dict["result"] = result message_dict["result"] = result
if error: if error:
message_dict["error"] = error message_dict["error"] = error
self.json_rpc_endpoint.send_request(message_dict) self.json_rpc_endpoint.send_request(message_dict)
@ -77,9 +82,9 @@ class LspEndpoint(threading.Thread):
message_dict = {} message_dict = {}
message_dict["jsonrpc"] = "2.0" message_dict["jsonrpc"] = "2.0"
if id is not None: if id is not None:
message_dict["id"] = id message_dict["id"] = id
message_dict["method"] = method_name message_dict["method"] = method_name
message_dict["params"] = params message_dict["params"] = params
self.json_rpc_endpoint.send_request(message_dict) self.json_rpc_endpoint.send_request(message_dict)
@ -101,9 +106,11 @@ class LspEndpoint(threading.Thread):
self.event_dict.pop(current_id) self.event_dict.pop(current_id)
result, error = self.response_dict.pop(current_id) result, error = self.response_dict.pop(current_id)
if error: if error:
raise lsp_structs.ResponseError(error.get("code"), error.get("message"), error.get("data")) raise lsp_structs.ResponseError(error.get("code"),
error.get("message"),
error.get("data"))
return result return result
def send_notification(self, method_name, **kwargs): def send_notification(self, method_name, **kwargs):
self.send_message(method_name, kwargs) self.send_message(method_name, kwargs)

View File

@ -1,17 +1,22 @@
# Python imports
import enum import enum
# Lib imports
# Application imports
def to_type(o, new_type): def to_type(o, new_type):
''' '''
Helper funciton that receives an object or a dict and convert it to a new given type. Helper funciton that receives an object or a dict and convert it to a new
given type.
:param object|dict o: The object to convert :param object|dict o: The object to convert
:param Type new_type: The type to convert to. :param Type new_type: The type to convert to.
''' '''
if new_type == type(o):
return o return o if new_type == type(o) else new_type(**o)
else:
return new_type(**o)
class Position(object): class Position(object):
@ -20,9 +25,10 @@ class Position(object):
Constructs a new Position instance. Constructs a new Position instance.
:param int line: Line position in a document (zero-based). :param int line: Line position in a document (zero-based).
:param int character: Character offset on a line in a document (zero-based). :param int character: Character offset on a line in a document
(zero-based).
""" """
self.line = line self.line = line
self.character = character self.character = character
@ -35,13 +41,14 @@ class Range(object):
:param Position end: The range's end position. :param Position end: The range's end position.
""" """
self.start = to_type(start, Position) self.start = to_type(start, Position)
self.end = to_type(end, Position) self.end = to_type(end, Position)
class Location(object): class Location(object):
""" """
Represents a location inside a resource, such as a line inside a text file. Represents a location inside a resource, such as a line inside a text file.
""" """
def __init__(self, uri, range): def __init__(self, uri, range):
""" """
Constructs a new Location instance. Constructs a new Location instance.
@ -49,7 +56,7 @@ class Location(object):
:param str uri: Resource file. :param str uri: Resource file.
:param Range range: The range inside the file :param Range range: The range inside the file
""" """
self.uri = uri self.uri = uri
self.range = to_type(range, Range) self.range = to_type(range, Range)
@ -57,6 +64,7 @@ class LocationLink(object):
""" """
Represents a link between a source and a target location. Represents a link between a source and a target location.
""" """
def __init__(self, originSelectionRange, targetUri, targetRange, targetSelectionRange): def __init__(self, originSelectionRange, targetUri, targetRange, targetSelectionRange):
""" """
Constructs a new LocationLink instance. Constructs a new LocationLink instance.
@ -64,18 +72,18 @@ class LocationLink(object):
:param Range originSelectionRange: Span of the origin of this link. :param Range originSelectionRange: Span of the origin of this link.
Used as the underlined span for mouse interaction. Defaults to the word range at the mouse position. Used as the underlined span for mouse interaction. Defaults to the word range at the mouse position.
:param str targetUri: The target resource identifier of this link. :param str targetUri: The target resource identifier of this link.
:param Range targetRange: The full target range of this link. If the target for example is a symbol then target :param Range targetRange: The full target range of this link. If the target for example is a symbol then target
range is the range enclosing this symbol not including leading/trailing whitespace but everything else range is the range enclosing this symbol not including leading/trailing whitespace but everything else
like comments. This information is typically used to highlight the range in the editor. like comments. This information is typically used to highlight the range in the editor.
:param Range targetSelectionRange: The range that should be selected and revealed when this link is being followed, :param Range targetSelectionRange: The range that should be selected and revealed when this link is being followed,
e.g the name of a function. Must be contained by the the `targetRange`. See also `DocumentSymbol#range` e.g the name of a function. Must be contained by the the `targetRange`. See also `DocumentSymbol#range`
""" """
self.originSelectionRange = to_type(originSelectionRange, Range) self.originSelectionRange = to_type(originSelectionRange, Range)
self.targetUri = targetUri self.targetUri = targetUri
self.targetRange = to_type(targetRange, Range) self.targetRange = to_type(targetRange, Range)
self.targetSelectionRange = to_type(targetSelectionRange, Range) self.targetSelectionRange = to_type(targetSelectionRange, Range)
class Diagnostic(object): class Diagnostic(object):
def __init__(self, range, severity, code, source, message, relatedInformation): def __init__(self, range, severity, code, source, message, relatedInformation):
""" """
@ -87,14 +95,14 @@ class Diagnostic(object):
:param str source: A human-readable string describing the source of this :param str source: A human-readable string describing the source of this
diagnostic, e.g. 'typescript' or 'super lint'. diagnostic, e.g. 'typescript' or 'super lint'.
:param str message: The diagnostic's message. :param str message: The diagnostic's message.
:param list relatedInformation: An array of related diagnostic information, e.g. when symbol-names within :param list relatedInformation: An array of related diagnostic information, e.g. when symbol-names within
a scope collide all definitions can be marked via this property. a scope collide all definitions can be marked via this property.
""" """
self.range = range self.range = range
self.severity = severity self.severity = severity
self.code = code self.code = code
self.source = source self.source = source
self.message = message self.message = message
self.relatedInformation = relatedInformation self.relatedInformation = relatedInformation
@ -113,9 +121,9 @@ class DiagnosticRelatedInformation(object):
:param str message: The message of this related diagnostic information. :param str message: The message of this related diagnostic information.
""" """
self.location = location self.location = location
self.message = message self.message = message
class Command(object): class Command(object):
def __init__(self, title, command, arguments): def __init__(self, title, command, arguments):
""" """
@ -124,8 +132,8 @@ class Command(object):
:param str command: The identifier of the actual command handler. :param str command: The identifier of the actual command handler.
:param list argusments: Arguments that the command handler should be invoked with. :param list argusments: Arguments that the command handler should be invoked with.
""" """
self.title = title self.title = title
self.command = command self.command = command
self.arguments = arguments self.arguments = arguments
@ -136,27 +144,27 @@ class TextDocumentItem(object):
def __init__(self, uri, languageId, version, text): def __init__(self, uri, languageId, version, text):
""" """
Constructs a new Diagnostic instance. Constructs a new Diagnostic instance.
:param DocumentUri uri: Title of the command, like `save`. :param DocumentUri uri: Title of the command, like `save`.
:param str languageId: The identifier of the actual command handler. :param str languageId: The identifier of the actual command handler.
:param int version: Arguments that the command handler should be invoked with. :param int version: Arguments that the command handler should be invoked with.
:param str text: Arguments that the command handler should be invoked with. :param str text: Arguments that the command handler should be invoked with.
""" """
self.uri = uri self.uri = uri
self.languageId = languageId self.languageId = languageId
self.version = version self.version = version
self.text = text self.text = text
class TextDocumentIdentifier(object): class TextDocumentIdentifier(object):
""" """
Text documents are identified using a URI. On the protocol level, URIs are passed as strings. Text documents are identified using a URI. On the protocol level, URIs are passed as strings.
""" """
def __init__(self, uri): def __init__(self, uri):
""" """
Constructs a new TextDocumentIdentifier instance. Constructs a new TextDocumentIdentifier instance.
:param DocumentUri uri: The text document's URI. :param DocumentUri uri: The text document's URI.
""" """
self.uri = uri self.uri = uri
@ -168,13 +176,13 @@ class VersionedTextDocumentIdentifier(TextDocumentIdentifier):
def __init__(self, uri, version): def __init__(self, uri, version):
""" """
Constructs a new TextDocumentIdentifier instance. Constructs a new TextDocumentIdentifier instance.
:param DocumentUri uri: The text document's URI. :param DocumentUri uri: The text document's URI.
:param int version: The version number of this document. If a versioned :param int version: The version number of this document. If a versioned
text document identifier is sent from the server to the client and text document identifier is sent from the server to the client and
the file is not open in the editor (the server has not received an the file is not open in the editor (the server has not received an
open notification before) the server can send `null` to indicate open notification before) the server can send `null` to indicate
that the version is known and the content on disk is the truth (as that the version is known and the content on disk is the truth (as
speced with document content ownership). speced with document content ownership).
The version number of a document will increase after each change, including The version number of a document will increase after each change, including
undo/redo. The number doesn't need to be consecutive. undo/redo. The number doesn't need to be consecutive.
@ -196,9 +204,9 @@ class TextDocumentContentChangeEvent(object):
:param int rangeLength: The length of the range that got replaced. :param int rangeLength: The length of the range that got replaced.
:param str text: The new text of the range/document. :param str text: The new text of the range/document.
""" """
self.range = range self.range = range
self.rangeLength = rangeLength self.rangeLength = rangeLength
self.text = text self.text = text
class TextDocumentPositionParams(object): class TextDocumentPositionParams(object):
@ -208,64 +216,64 @@ class TextDocumentPositionParams(object):
def __init__(self, textDocument, position): def __init__(self, textDocument, position):
""" """
Constructs a new TextDocumentPositionParams instance. Constructs a new TextDocumentPositionParams instance.
:param TextDocumentIdentifier textDocument: The text document. :param TextDocumentIdentifier textDocument: The text document.
:param Position position: The position inside the text document. :param Position position: The position inside the text document.
""" """
self.textDocument = textDocument self.textDocument = textDocument
self.position = position self.position = position
class LANGUAGE_IDENTIFIER(object): class LANGUAGE_IDENTIFIER(object):
BAT="bat" BAT = "bat"
BIBTEX="bibtex" BIBTEX = "bibtex"
CLOJURE="clojure" CLOJURE = "clojure"
COFFESCRIPT="coffeescript" COFFESCRIPT = "coffeescript"
C="c" C = "c"
CPP="cpp" CPP = "cpp"
CSHARP="csharp" CSHARP = "csharp"
CSS="css" CSS = "css"
DIFF="diff" DIFF = "diff"
DOCKERFILE="dockerfile" DOCKERFILE = "dockerfile"
FSHARP="fsharp" FSHARP = "fsharp"
GIT_COMMIT="git-commit" GIT_COMMIT = "git-commit"
GIT_REBASE="git-rebase" GIT_REBASE = "git-rebase"
GO="go" GO = "go"
GROOVY="groovy" GROOVY = "groovy"
HANDLEBARS="handlebars" HANDLEBARS = "handlebars"
HTML="html" HTML = "html"
INI="ini" INI = "ini"
JAVA="java" JAVA = "java"
JAVASCRIPT="javascript" JAVASCRIPT = "javascript"
JSON="json" JSON = "json"
LATEX="latex" LATEX = "latex"
LESS="less" LESS = "less"
LUA="lua" LUA = "lua"
MAKEFILE="makefile" MAKEFILE = "makefile"
MARKDOWN="markdown" MARKDOWN = "markdown"
OBJECTIVE_C="objective-c" OBJECTIVE_C = "objective-c"
OBJECTIVE_CPP="objective-cpp" OBJECTIVE_CPP = "objective-cpp"
Perl="perl" Perl = "perl"
PHP="php" PHP = "php"
POWERSHELL="powershell" POWERSHELL = "powershell"
PUG="jade" PUG = "jade"
PYTHON="python" PYTHON = "python"
R="r" R = "r"
RAZOR="razor" RAZOR = "razor"
RUBY="ruby" RUBY = "ruby"
RUST="rust" RUST = "rust"
SASS="sass" SASS = "sass"
SCSS="scss" SCSS = "scss"
ShaderLab="shaderlab" ShaderLab = "shaderlab"
SHELL_SCRIPT="shellscript" SHELL_SCRIPT = "shellscript"
SQL="sql" SQL = "sql"
SWIFT="swift" SWIFT = "swift"
TYPE_SCRIPT="typescript" TYPE_SCRIPT = "typescript"
TEX="tex" TEX = "tex"
VB="vb" VB = "vb"
XML="xml" XML = "xml"
XSL="xsl" XSL = "xsl"
YAML="yaml" YAML = "yaml"
class SymbolKind(enum.Enum): class SymbolKind(enum.Enum):
@ -301,7 +309,7 @@ class SymbolInformation(object):
""" """
Represents information about programming constructs like variables, classes, interfaces etc. Represents information about programming constructs like variables, classes, interfaces etc.
""" """
def __init__(self, name, kind, location, containerName=None, deprecated=False): def __init__(self, name, kind, location, containerName = None, deprecated = False):
""" """
Constructs a new SymbolInformation instance. Constructs a new SymbolInformation instance.
@ -322,10 +330,10 @@ class SymbolInformation(object):
symbols. symbols.
:param bool deprecated: Indicates if this symbol is deprecated. :param bool deprecated: Indicates if this symbol is deprecated.
""" """
self.name = name self.name = name
self.kind = SymbolKind(kind) self.kind = SymbolKind(kind)
self.deprecated = deprecated self.deprecated = deprecated
self.location = to_type(location, Location) self.location = to_type(location, Location)
self.containerName = containerName self.containerName = containerName
@ -334,14 +342,14 @@ class ParameterInformation(object):
Represents a parameter of a callable-signature. A parameter can Represents a parameter of a callable-signature. A parameter can
have a label and a doc-comment. have a label and a doc-comment.
""" """
def __init__(self, label, documentation=""): def __init__(self, label, documentation = ""):
""" """
Constructs a new ParameterInformation instance. Constructs a new ParameterInformation instance.
:param str label: The label of this parameter. Will be shown in the UI. :param str label: The label of this parameter. Will be shown in the UI.
:param str documentation: The human-readable doc-comment of this parameter. Will be shown in the UI but can be omitted. :param str documentation: The human-readable doc-comment of this parameter. Will be shown in the UI but can be omitted.
""" """
self.label = label self.label = label
self.documentation = documentation self.documentation = documentation
@ -351,7 +359,7 @@ class SignatureInformation(object):
can have a label, like a function-name, a doc-comment, and can have a label, like a function-name, a doc-comment, and
a set of parameters. a set of parameters.
""" """
def __init__(self, label, documentation="", parameters=[]): def __init__(self, label, documentation = "", parameters = []):
""" """
Constructs a new SignatureInformation instance. Constructs a new SignatureInformation instance.
@ -359,9 +367,9 @@ class SignatureInformation(object):
:param str documentation: The human-readable doc-comment of this signature. Will be shown in the UI but can be omitted. :param str documentation: The human-readable doc-comment of this signature. Will be shown in the UI but can be omitted.
:param ParameterInformation[] parameters: The parameters of this signature. :param ParameterInformation[] parameters: The parameters of this signature.
""" """
self.label = label self.label = label
self.documentation = documentation self.documentation = documentation
self.parameters = [to_type(parameter, ParameterInformation) for parameter in parameters] self.parameters = [to_type(parameter, ParameterInformation) for parameter in parameters]
class SignatureHelp(object): class SignatureHelp(object):
@ -370,7 +378,7 @@ class SignatureHelp(object):
callable. There can be multiple signature but only one callable. There can be multiple signature but only one
active and only one active parameter. active and only one active parameter.
""" """
def __init__(self, signatures, activeSignature=0, activeParameter=0): def __init__(self, signatures, activeSignature = 0, activeParameter = 0):
""" """
Constructs a new SignatureHelp instance. Constructs a new SignatureHelp instance.
@ -378,7 +386,7 @@ class SignatureHelp(object):
:param int activeSignature: :param int activeSignature:
:param int activeParameter: :param int activeParameter:
""" """
self.signatures = [to_type(signature, SignatureInformation) for signature in signatures] self.signatures = [to_type(signature, SignatureInformation) for signature in signatures]
self.activeSignature = activeSignature self.activeSignature = activeSignature
self.activeParameter = activeParameter self.activeParameter = activeParameter
@ -393,7 +401,7 @@ class CompletionContext(object):
""" """
Contains additional information about the context in which a completion request is triggered. Contains additional information about the context in which a completion request is triggered.
""" """
def __init__(self, triggerKind, triggerCharacter=None): def __init__(self, triggerKind, triggerCharacter = None):
""" """
Constructs a new CompletionContext instance. Constructs a new CompletionContext instance.
@ -412,31 +420,47 @@ class TextEdit(object):
""" """
def __init__(self, range, newText): def __init__(self, range, newText):
""" """
:param Range range: The range of the text document to be manipulated. To insert :param Range range: The range of the text document to be manipulated. To insert
text into a document create a range where start === end. text into a document create a range where start === end.
:param str newText: The string to be inserted. For delete operations use an empty string. :param str newText: The string to be inserted. For delete operations use an empty string.
""" """
self.range = range self.range = range
self.newText = newText self.newText = newText
class InsertTextFormat(object): class InsertTextFormat(object):
PlainText = 1 PlainText = 1
Snippet = 2 Snippet = 2
class CompletionItem(object): class CompletionItem(object):
""" """
""" """
def __init__(self, label, kind=None, detail=None, documentation=None, deprecated=None, presented=None, sortText=None, filterText=None, insertText=None, insertTextFormat=None, textEdit=None, additionalTextEdits=None, commitCharacters=None, command=None, data=None, score=0.0): def __init__(self, label, \
""" kind = None, \
detail = None, \
documentation = None, \
deprecated = None, \
preselect = None, \
sortText = None, \
filterText = None, \
insertText = None, \
insertTextFormat = None, \
textEdit = None, \
additionalTextEdits = None, \
commitCharacters = None, \
command = None, \
data = None, \
score = 0.0
):
"""
:param str label: The label of this completion item. By default also the text that is inserted when selecting :param str label: The label of this completion item. By default also the text that is inserted when selecting
this completion. this completion.
:param int kind: The kind of this completion item. Based of the kind an icon is chosen by the editor. :param int kind: The kind of this completion item. Based of the kind an icon is chosen by the editor.
:param str detail: A human-readable string with additional information about this item, like type or symbol information. :param str detail: A human-readable string with additional information about this item, like type or symbol information.
:param tr ocumentation: A human-readable string that represents a doc-comment. :param tr ocumentation: A human-readable string that represents a doc-comment.
:param bool deprecated: Indicates if this item is deprecated. :param bool deprecated: Indicates if this item is deprecated.
:param bool presented: Select this item when showing. Note: that only one completion item can be selected and that the :param bool preselect: Select this item when showing. Note: that only one completion item can be selected and that the
tool / client decides which item that is. The rule is that the first item of those that match best is selected. tool / client decides which item that is. The rule is that the first item of those that match best is selected.
:param str sortText: A string that should be used when comparing this item with other items. When `falsy` the label is used. :param str sortText: A string that should be used when comparing this item with other items. When `falsy` the label is used.
:param str filterText: A string that should be used when filtering a set of completion items. When `falsy` the label is used. :param str filterText: A string that should be used when filtering a set of completion items. When `falsy` the label is used.
@ -450,7 +474,7 @@ class CompletionItem(object):
:param TextEdit textEdit: An edit which is applied to a document when selecting this completion. When an edit is provided the value of `insertText` is ignored. :param TextEdit textEdit: An edit which is applied to a document when selecting this completion. When an edit is provided the value of `insertText` is ignored.
Note:* The range of the edit must be a single line range and it must contain the position at which completion Note:* The range of the edit must be a single line range and it must contain the position at which completion
has been requested. has been requested.
:param TextEdit additionalTextEdits: An optional array of additional text edits that are applied when selecting this completion. :param TextEdit additionalTextEdits: An optional array of additional text edits that are applied when selecting this completion.
Edits must not overlap (including the same insert position) with the main edit nor with themselves. Edits must not overlap (including the same insert position) with the main edit nor with themselves.
Additional text edits should be used to change text unrelated to the current cursor position Additional text edits should be used to change text unrelated to the current cursor position
(for example adding an import statement at the top of the file if the completion item will (for example adding an import statement at the top of the file if the completion item will
@ -468,7 +492,7 @@ class CompletionItem(object):
self.detail = detail self.detail = detail
self.documentation = documentation self.documentation = documentation
self.deprecated = deprecated self.deprecated = deprecated
self.presented = presented self.preselect = preselect
self.sortText = sortText self.sortText = sortText
self.filterText = filterText self.filterText = filterText
self.insertText = insertText self.insertText = insertText
@ -511,12 +535,12 @@ class CompletionItemKind(enum.Enum):
class CompletionList(object): class CompletionList(object):
""" """
Represents a collection of [completion items](#CompletionItem) to be presented in the editor. Represents a collection of [completion items](#CompletionItem) to be preselect in the editor.
""" """
def __init__(self, isIncomplete, items): def __init__(self, isIncomplete, items):
""" """
Constructs a new CompletionContext instance. Constructs a new CompletionContext instance.
:param bool isIncomplete: This list it not complete. Further typing should result in recomputing this list. :param bool isIncomplete: This list it not complete. Further typing should result in recomputing this list.
:param CompletionItem items: The completion items. :param CompletionItem items: The completion items.
""" """
@ -544,4 +568,4 @@ class ResponseError(Exception):
self.code = code self.code = code
self.message = message self.message = message
if data: if data:
self.data = data self.data = data