mirror of
https://github.com/apple/sourcekit-lsp.git
synced 2026-03-02 18:23:24 +01:00
Simplify the Python files used to write BSP servers for SourceKit-LSP tests
This commit is contained in:
129
Sources/SKTestSupport/INPUTS/AbstractBuildServer.py
Normal file
129
Sources/SKTestSupport/INPUTS/AbstractBuildServer.py
Normal file
@@ -0,0 +1,129 @@
|
||||
import json
|
||||
import sys
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class RequestError(Exception):
|
||||
"""
|
||||
An error that can be thrown from a request handling function in `AbstractBuildServer` to return an error response to
|
||||
SourceKit-LSP.
|
||||
"""
|
||||
|
||||
code: int
|
||||
message: str
|
||||
|
||||
def __init__(self, code: int, message: str):
|
||||
self.code = code
|
||||
self.message = message
|
||||
|
||||
|
||||
class AbstractBuildServer:
|
||||
"""
|
||||
An abstract class to implement a BSP server in Python for SourceKit-LSP testing purposes.
|
||||
"""
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Run the build server. This should be called from the top-level code of the build server's Python file.
|
||||
"""
|
||||
while True:
|
||||
line = sys.stdin.readline()
|
||||
if len(line) == 0:
|
||||
break
|
||||
|
||||
assert line.startswith("Content-Length:")
|
||||
length = int(line[len("Content-Length:") :])
|
||||
sys.stdin.readline()
|
||||
message = json.loads(sys.stdin.read(length))
|
||||
|
||||
try:
|
||||
result = self.handle_message(message)
|
||||
if result:
|
||||
response_message: dict[str, object] = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": result,
|
||||
}
|
||||
self.send_raw_message(response_message)
|
||||
except RequestError as e:
|
||||
error_response_message: dict[str, object] = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"error": {
|
||||
"code": e.code,
|
||||
"message": e.message,
|
||||
},
|
||||
}
|
||||
self.send_raw_message(error_response_message)
|
||||
|
||||
def handle_message(self, message: dict[str, object]) -> Optional[dict[str, object]]:
|
||||
"""
|
||||
Dispatch handling of the given method, received from SourceKit-LSP to the message handling function.
|
||||
"""
|
||||
method: str = str(message["method"])
|
||||
params: dict[str, object] = message["params"] # type: ignore
|
||||
if method == "build/exit":
|
||||
return self.exit(params)
|
||||
elif method == "build/initialize":
|
||||
return self.initialize(params)
|
||||
elif method == "build/initialized":
|
||||
return self.initialized(params)
|
||||
elif method == "build/shutdown":
|
||||
return self.shutdown(params)
|
||||
elif method == "textDocument/registerForChanges":
|
||||
return self.register_for_changes(params)
|
||||
|
||||
# ignore other notifications
|
||||
if "id" in message:
|
||||
raise RequestError(code=-32601, message=f"Method not found: {method}")
|
||||
|
||||
def send_raw_message(self, message: dict[str, object]):
|
||||
"""
|
||||
Send a raw message to SourceKit-LSP. The message needs to have all JSON-RPC wrapper fields.
|
||||
|
||||
Subclasses should not call this directly
|
||||
"""
|
||||
message_str = json.dumps(message)
|
||||
sys.stdout.buffer.write(
|
||||
f"Content-Length: {len(message_str)}\r\n\r\n{message_str}".encode("utf-8")
|
||||
)
|
||||
sys.stdout.flush()
|
||||
|
||||
def send_notification(self, method: str, params: dict[str, object]):
|
||||
"""
|
||||
Send a notification with the given method and parameters to SourceKit-LSP.
|
||||
"""
|
||||
message: dict[str, object] = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": method,
|
||||
"params": params,
|
||||
}
|
||||
self.send_raw_message(message)
|
||||
|
||||
# Message handling functions.
|
||||
# Subclasses should override these to provide functionality.
|
||||
|
||||
def exit(self, notification: dict[str, object]) -> None:
|
||||
pass
|
||||
|
||||
def initialize(self, request: dict[str, object]) -> dict[str, object]:
|
||||
return {
|
||||
"displayName": "test server",
|
||||
"version": "0.1",
|
||||
"bspVersion": "2.0",
|
||||
"rootUri": "blah",
|
||||
"capabilities": {"languageIds": ["a", "b"]},
|
||||
"data": {
|
||||
"indexDatabasePath": "some/index/db/path",
|
||||
"indexStorePath": "some/index/store/path",
|
||||
},
|
||||
}
|
||||
|
||||
def initialized(self, notification: dict[str, object]) -> None:
|
||||
pass
|
||||
|
||||
def register_for_changes(self, notification: dict[str, object]):
|
||||
pass
|
||||
|
||||
def shutdown(self, notification: dict[str, object]) -> None:
|
||||
pass
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "client name",
|
||||
"version": "10",
|
||||
"bspVersion": "2.0",
|
||||
"languages": ["a", "b"],
|
||||
"argv": ["server.py"]
|
||||
}
|
||||
@@ -1,75 +0,0 @@
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
while True:
|
||||
line = sys.stdin.readline()
|
||||
if len(line) == 0:
|
||||
break
|
||||
|
||||
assert line.startswith('Content-Length:')
|
||||
length = int(line[len('Content-Length:'):])
|
||||
sys.stdin.readline()
|
||||
message = json.loads(sys.stdin.read(length))
|
||||
|
||||
response = None
|
||||
if message["method"] == "build/initialize":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": {
|
||||
"displayName": "test server",
|
||||
"version": "0.1",
|
||||
"bspVersion": "2.0",
|
||||
"rootUri": "blah",
|
||||
"capabilities": {"languageIds": ["a", "b"]},
|
||||
"data": {
|
||||
"indexStorePath": "some/index/store/path"
|
||||
}
|
||||
}
|
||||
}
|
||||
elif message["method"] == "build/initialized":
|
||||
continue
|
||||
elif message["method"] == "build/shutdown":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": None
|
||||
}
|
||||
elif message["method"] == "build/exit":
|
||||
break
|
||||
elif message["method"] == "buildTarget/outputPaths":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": {
|
||||
"items": [
|
||||
{
|
||||
"target": {"uri": "build://target/a"},
|
||||
"outputPaths": [
|
||||
"file:///path/to/a/file",
|
||||
"file:///path/to/a/file2"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
# ignore other notifications
|
||||
elif "id" in message:
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"error": {
|
||||
"code": 123,
|
||||
"message": "unhandled method {}".format(message["method"]),
|
||||
}
|
||||
}
|
||||
|
||||
if response:
|
||||
responseStr = json.dumps(response)
|
||||
try:
|
||||
sys.stdout.buffer.write(f"Content-Length: {len(responseStr)}\r\n\r\n{responseStr}".encode('utf-8'))
|
||||
sys.stdout.flush()
|
||||
except IOError:
|
||||
# stdout closed, time to quit
|
||||
break
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "client name",
|
||||
"version": "10",
|
||||
"bspVersion": "2.0",
|
||||
"languages": ["a", "b"],
|
||||
"argv": ["server.py"]
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
while True:
|
||||
line = sys.stdin.readline()
|
||||
if len(line) == 0:
|
||||
break
|
||||
|
||||
assert line.startswith('Content-Length:')
|
||||
length = int(line[len('Content-Length:'):])
|
||||
sys.stdin.readline()
|
||||
message = json.loads(sys.stdin.read(length))
|
||||
|
||||
response = None
|
||||
if message["method"] == "build/initialize":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": {
|
||||
"displayName": "test server",
|
||||
"version": "0.1",
|
||||
"bspVersion": "2.0",
|
||||
"rootUri": "blah",
|
||||
"capabilities": {"languageIds": ["a", "b"]},
|
||||
"data": {
|
||||
"indexStorePath": "some/index/store/path"
|
||||
}
|
||||
}
|
||||
}
|
||||
elif message["method"] == "build/initialized":
|
||||
continue
|
||||
elif message["method"] == "build/shutdown":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": None
|
||||
}
|
||||
elif message["method"] == "build/exit":
|
||||
break
|
||||
elif message["method"] == "buildTarget/sources":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": {
|
||||
"items": [
|
||||
{
|
||||
"target": {"uri": "build://target/a"},
|
||||
"sources": [
|
||||
{
|
||||
"uri": "file:///path/to/a/file",
|
||||
"kind": 1,
|
||||
"generated": False
|
||||
},
|
||||
{
|
||||
"uri": "file:///path/to/a/folder/",
|
||||
"kind": 2,
|
||||
"generated": False
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": {"uri": "build://target/b"},
|
||||
"sources": [
|
||||
{
|
||||
"uri": "file:///path/to/b/file",
|
||||
"kind": 1,
|
||||
"generated": False
|
||||
},
|
||||
{
|
||||
"uri": "file:///path/to/b/folder/",
|
||||
"kind": 2,
|
||||
"generated": False
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
# ignore other notifications
|
||||
elif "id" in message:
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"error": {
|
||||
"code": 123,
|
||||
"message": "unhandled method {}".format(message["method"]),
|
||||
}
|
||||
}
|
||||
|
||||
if response:
|
||||
responseStr = json.dumps(response)
|
||||
try:
|
||||
sys.stdout.buffer.write(f"Content-Length: {len(responseStr)}\r\n\r\n{responseStr}".encode('utf-8'))
|
||||
sys.stdout.flush()
|
||||
except IOError:
|
||||
# stdout closed, time to quit
|
||||
break
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "client name",
|
||||
"version": "10",
|
||||
"bspVersion": "2.0",
|
||||
"languages": ["a", "b"],
|
||||
"argv": ["server.py"]
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
import json
|
||||
import sys
|
||||
|
||||
|
||||
while True:
|
||||
line = sys.stdin.readline()
|
||||
if len(line) == 0:
|
||||
break
|
||||
|
||||
assert line.startswith('Content-Length:')
|
||||
length = int(line[len('Content-Length:'):])
|
||||
sys.stdin.readline()
|
||||
message = json.loads(sys.stdin.read(length))
|
||||
|
||||
response = None
|
||||
if message["method"] == "build/initialize":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": {
|
||||
"displayName": "test server",
|
||||
"version": "0.1",
|
||||
"bspVersion": "2.0",
|
||||
"rootUri": "blah",
|
||||
"capabilities": {"languageIds": ["objective-c", "swift"]},
|
||||
"data": {
|
||||
"indexStorePath": "some/index/store/path"
|
||||
}
|
||||
}
|
||||
}
|
||||
elif message["method"] == "build/initialized":
|
||||
continue
|
||||
elif message["method"] == "build/shutdown":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": None
|
||||
}
|
||||
elif message["method"] == "build/exit":
|
||||
break
|
||||
elif message["method"] == "workspace/buildTargets":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": {
|
||||
"targets": [
|
||||
{
|
||||
"id": {"uri": "target:first_target"},
|
||||
"displayName": "First Target",
|
||||
"baseDirectory": "file:///some/dir",
|
||||
"tags": ["library", "test"],
|
||||
"capabilities": {
|
||||
"canCompile": True,
|
||||
"canTest": True,
|
||||
"canRun": False
|
||||
},
|
||||
"languageIds": ["objective-c", "swift"],
|
||||
"dependencies": []
|
||||
},
|
||||
{
|
||||
"id": {"uri": "target:second_target"},
|
||||
"displayName": "Second Target",
|
||||
"baseDirectory": "file:///some/dir",
|
||||
"tags": ["library", "test"],
|
||||
"capabilities": {
|
||||
"canCompile": True,
|
||||
"canTest": False,
|
||||
"canRun": False
|
||||
},
|
||||
"languageIds": ["objective-c", "swift"],
|
||||
"dependencies": [{"uri": "target:first_target"}]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
# ignore other notifications
|
||||
elif "id" in message:
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"error": {
|
||||
"code": 123,
|
||||
"message": "unhandled method {}".format(message["method"]),
|
||||
}
|
||||
}
|
||||
|
||||
if response:
|
||||
responseStr = json.dumps(response)
|
||||
try:
|
||||
sys.stdout.buffer.write(f"Content-Length: {len(responseStr)}\r\n\r\n{responseStr}".encode('utf-8'))
|
||||
sys.stdout.flush()
|
||||
except IOError:
|
||||
# stdout closed, time to quit
|
||||
break
|
||||
@@ -1,87 +1,26 @@
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
sys.path.append(str(Path(__file__).parent.parent))
|
||||
|
||||
def send(data):
|
||||
dataStr = json.dumps(data)
|
||||
try:
|
||||
sys.stdout.buffer.write(f"Content-Length: {len(dataStr)}\r\n\r\n{dataStr}".encode('utf-8'))
|
||||
sys.stdout.flush()
|
||||
except IOError:
|
||||
# stdout closed, time to quit
|
||||
raise SystemExit(0)
|
||||
from AbstractBuildServer import AbstractBuildServer
|
||||
|
||||
|
||||
while True:
|
||||
line = sys.stdin.readline()
|
||||
if len(line) == 0:
|
||||
break
|
||||
|
||||
assert line.startswith('Content-Length:')
|
||||
length = int(line[len('Content-Length:'):])
|
||||
sys.stdin.readline()
|
||||
message = json.loads(sys.stdin.read(length))
|
||||
|
||||
response = None
|
||||
notification = None
|
||||
|
||||
if message["method"] == "build/initialize":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": {
|
||||
"displayName": "test server",
|
||||
"version": "0.1",
|
||||
"bspVersion": "2.0",
|
||||
"rootUri": "blah",
|
||||
"capabilities": {"languageIds": ["a", "b"]},
|
||||
"data": {
|
||||
"indexStorePath": "some/index/store/path"
|
||||
}
|
||||
}
|
||||
}
|
||||
elif message["method"] == "build/initialized":
|
||||
continue
|
||||
elif message["method"] == "build/shutdown":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": None
|
||||
}
|
||||
elif message["method"] == "build/exit":
|
||||
break
|
||||
elif message["method"] == "textDocument/registerForChanges":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": None
|
||||
}
|
||||
if message["params"]["action"] == "register":
|
||||
notification = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "buildTarget/didChange",
|
||||
"params": {
|
||||
class BuildServer(AbstractBuildServer):
|
||||
def register_for_changes(self, notification: dict[str, object]):
|
||||
if notification["action"] == "register":
|
||||
self.send_notification(
|
||||
"buildTarget/didChange",
|
||||
{
|
||||
"changes": [
|
||||
{
|
||||
"target": {"uri": "build://target/a"},
|
||||
"kind": 1,
|
||||
"data": {"key": "value"}
|
||||
"data": {"key": "value"},
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
# ignore other notifications
|
||||
elif "id" in message:
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"error": {
|
||||
"code": -32600,
|
||||
"message": "unhandled method {}".format(message["method"]),
|
||||
}
|
||||
}
|
||||
|
||||
if response: send(response)
|
||||
if notification: send(notification)
|
||||
BuildServer().run()
|
||||
|
||||
@@ -1,85 +1,24 @@
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
sys.path.append(str(Path(__file__).parent.parent))
|
||||
|
||||
def send(data):
|
||||
dataStr = json.dumps(data)
|
||||
try:
|
||||
sys.stdout.buffer.write(f"Content-Length: {len(dataStr)}\r\n\r\n{dataStr}".encode('utf-8'))
|
||||
sys.stdout.flush()
|
||||
except IOError:
|
||||
# stdout closed, time to quit
|
||||
raise SystemExit(0)
|
||||
from AbstractBuildServer import AbstractBuildServer
|
||||
|
||||
|
||||
while True:
|
||||
line = sys.stdin.readline()
|
||||
if len(line) == 0:
|
||||
break
|
||||
|
||||
assert line.startswith('Content-Length:')
|
||||
length = int(line[len('Content-Length:'):])
|
||||
sys.stdin.readline()
|
||||
message = json.loads(sys.stdin.read(length))
|
||||
|
||||
response = None
|
||||
notification = None
|
||||
|
||||
if message["method"] == "build/initialize":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": {
|
||||
"displayName": "test server",
|
||||
"version": "0.1",
|
||||
"bspVersion": "2.0",
|
||||
"rootUri": "blah",
|
||||
"capabilities": {"languageIds": ["a", "b"]},
|
||||
"data": {
|
||||
"indexStorePath": "some/index/store/path"
|
||||
}
|
||||
}
|
||||
}
|
||||
elif message["method"] == "build/initialized":
|
||||
continue
|
||||
elif message["method"] == "build/shutdown":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": None
|
||||
}
|
||||
elif message["method"] == "build/exit":
|
||||
break
|
||||
elif message["method"] == "textDocument/registerForChanges":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": None
|
||||
}
|
||||
if message["params"]["action"] == "register":
|
||||
notification = {
|
||||
"jsonrpc": "2.0",
|
||||
"method": "build/sourceKitOptionsChanged",
|
||||
"params": {
|
||||
"uri": message["params"]["uri"],
|
||||
class BuildServer(AbstractBuildServer):
|
||||
def register_for_changes(self, notification: dict[str, object]):
|
||||
if notification["action"] == "register":
|
||||
self.send_notification(
|
||||
"build/sourceKitOptionsChanged",
|
||||
{
|
||||
"uri": notification["uri"],
|
||||
"updatedOptions": {
|
||||
"options": ["a", "b"],
|
||||
"workingDirectory": "/some/dir"
|
||||
}
|
||||
}
|
||||
}
|
||||
"workingDirectory": "/some/dir",
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
# ignore other notifications
|
||||
elif "id" in message:
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"error": {
|
||||
"code": -32600,
|
||||
"message": "unhandled method {}".format(message["method"]),
|
||||
}
|
||||
}
|
||||
|
||||
if response: send(response)
|
||||
if notification: send(notification)
|
||||
BuildServer().run()
|
||||
|
||||
@@ -1,60 +1,13 @@
|
||||
import json
|
||||
from pathlib import Path
|
||||
import sys
|
||||
|
||||
sys.path.append(str(Path(__file__).parent.parent))
|
||||
|
||||
while True:
|
||||
line = sys.stdin.readline()
|
||||
if len(line) == 0:
|
||||
break
|
||||
from AbstractBuildServer import AbstractBuildServer
|
||||
|
||||
assert line.startswith('Content-Length:')
|
||||
length = int(line[len('Content-Length:'):])
|
||||
sys.stdin.readline()
|
||||
message = json.loads(sys.stdin.read(length))
|
||||
|
||||
response = None
|
||||
if message["method"] == "build/initialize":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": {
|
||||
"displayName": "test server",
|
||||
"version": "0.1",
|
||||
"bspVersion": "2.0",
|
||||
"rootUri": "blah",
|
||||
"capabilities": {"languageIds": ["a", "b"]},
|
||||
"data": {
|
||||
"indexDatabasePath": "some/index/db/path",
|
||||
"indexStorePath": "some/index/store/path"
|
||||
}
|
||||
}
|
||||
}
|
||||
elif message["method"] == "build/initialized":
|
||||
continue
|
||||
elif message["method"] == "build/shutdown":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": None
|
||||
}
|
||||
elif message["method"] == "build/exit":
|
||||
break
|
||||
# ignore other notifications
|
||||
elif "id" in message:
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"error": {
|
||||
"code": 123,
|
||||
"message": "unhandled method {}".format(message["method"]),
|
||||
}
|
||||
}
|
||||
class BuildServer(AbstractBuildServer):
|
||||
pass
|
||||
|
||||
if response:
|
||||
responseStr = json.dumps(response)
|
||||
try:
|
||||
sys.stdout.buffer.write(f"Content-Length: {len(responseStr)}\r\n\r\n{responseStr}".encode('utf-8'))
|
||||
sys.stdout.flush()
|
||||
except IOError:
|
||||
# stdout closed, time to quit
|
||||
break
|
||||
|
||||
BuildServer().run()
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"name": "client name",
|
||||
"version": "10",
|
||||
"bspVersion": "2.0",
|
||||
"languages": ["a", "b"],
|
||||
"argv": ["server.py"]
|
||||
}
|
||||
@@ -1,81 +0,0 @@
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
|
||||
|
||||
while True:
|
||||
line = sys.stdin.readline()
|
||||
if len(line) == 0:
|
||||
break
|
||||
|
||||
assert line.startswith('Content-Length:')
|
||||
length = int(line[len('Content-Length:'):])
|
||||
sys.stdin.readline()
|
||||
message = json.loads(sys.stdin.read(length))
|
||||
|
||||
response = None
|
||||
if message["method"] == "build/initialize":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": {
|
||||
"displayName": "test server",
|
||||
"version": "0.1",
|
||||
"bspVersion": "2.0",
|
||||
"rootUri": "blah",
|
||||
"capabilities": {"languageIds": ["a", "b"]},
|
||||
"data": {
|
||||
"indexStorePath": "some/index/store/path"
|
||||
}
|
||||
}
|
||||
}
|
||||
elif message["method"] == "build/initialized":
|
||||
continue
|
||||
elif message["method"] == "build/shutdown":
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": None
|
||||
}
|
||||
elif message["method"] == "build/exit":
|
||||
break
|
||||
elif message["method"] == "textDocument/sourceKitOptions":
|
||||
file_path = message["params"]["uri"][len("file://"):]
|
||||
if file_path.endswith(".missing"):
|
||||
# simulate error response for unhandled file
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"error": {
|
||||
"code": -32600,
|
||||
"message": "unknown file {}".format(file_path),
|
||||
}
|
||||
}
|
||||
else:
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"result": {
|
||||
"options": ["-a", "-b"],
|
||||
"workingDirectory": os.path.dirname(file_path),
|
||||
}
|
||||
}
|
||||
# ignore other notifications
|
||||
elif "id" in message:
|
||||
response = {
|
||||
"jsonrpc": "2.0",
|
||||
"id": message["id"],
|
||||
"error": {
|
||||
"code": -32600,
|
||||
"message": "unhandled method {}".format(message["method"]),
|
||||
}
|
||||
}
|
||||
|
||||
if response:
|
||||
responseStr = json.dumps(response)
|
||||
try:
|
||||
sys.stdout.buffer.write(f"Content-Length: {len(responseStr)}\r\n\r\n{responseStr}".encode('utf-8'))
|
||||
sys.stdout.flush()
|
||||
except IOError:
|
||||
# stdout closed, time to quit
|
||||
break
|
||||
Reference in New Issue
Block a user