Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 22 additions & 47 deletions LSP.sc
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ LSPConnection {
classvar readyMsg = "***LSP READY***";
classvar <handlerThread;

var <>inPort, <>outPort;
var socket;
var <>transport;
var messageLengthExpected, messageBuffer;
var requestId=0;
var outstandingRequests;
Expand Down Expand Up @@ -43,9 +42,7 @@ LSPConnection {
});

if (settings[\enabled].asBoolean) {
{
connection = LSPConnection().start;
}.defer(0.0001)
connection = LSPConnection().start;
};

Log('LanguageServer.quark').level = \error;
Expand All @@ -67,13 +64,15 @@ LSPConnection {

init {
|settings|
inPort = settings[\inPort];
outPort = settings[\outPort];
var inPort = settings[\inPort];
var outPort = settings[\outPort];
outstandingRequests = ();
workspaceFolders = List();

Log('LanguageServer.quark').level = settings[\logLevel].asSymbol;

this.transport = LSPUDPTransport(inPort, outPort);

this.addDependant({
|server, message, value|
if (message == \clientOptions) {
Expand All @@ -87,29 +86,16 @@ LSPConnection {
}

start {
// @TODO: What do we do before start / after stop? Errors?
Log('LanguageServer.quark').info("Starting language server, inPort: % outPort:%", inPort, outPort);

3.do {
try {
socket = socket ?? { NetAddr("127.0.0.1", outPort) };
thisProcess.openUDPPort(inPort, \raw);
} {
Log('LanguageServer.quark').warning("Opening LSP port failed. Probably this is because an old scsynth process is holding onto the port. Killing old servers and trying again...");
Server.killAll();
0.5.wait();
};
};

thisProcess.addRawRecvFunc({
|msg, time, replyAddr, recvPort|
this.prOnReceived(time, replyAddr, msg);
});

// @TODO Is this the only "default" provider we want?
this.addProvider(InitializeProvider(this, {}));
Routine({
this.transport.start(this);

// @TODO Is this the only "default" provider we want?
this.addProvider(InitializeProvider(this, {}));

readyMsg.postln;
}).play(AppClock);
Comment on lines +89 to +96
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a preferred approach here? This is blocking as I understand, which could be a problem.


readyMsg.postln;
^this;
}

stop {
Expand Down Expand Up @@ -140,6 +126,11 @@ LSPConnection {
}
}

onReceived {
|message|
this.prOnReceived(message);
}

request {
|methodName, params|
providers[methodName] !? {
Expand All @@ -151,10 +142,7 @@ LSPConnection {
}

prOnReceived {
|time, replyAddr, message|

Log('LanguageServer.quark').info("Message received: %, %, %", time, replyAddr, message);

|message|
this.prParseMessage(message) !? this.prHandleMessage(_)
}

Expand Down Expand Up @@ -347,24 +335,11 @@ LSPConnection {

prSendMessage {
|dict|
var maxSize = 6000;
var offset = 0;
var packetSize;
var message = this.prEncodeMessage(dict);
var messageSize = message.size;

Log('LanguageServer.quark').info("Responding with: %", message);

if (message.size < maxSize) {
socket.sendRaw(message);
} {
while { offset < messageSize } {
packetSize = min(messageSize, maxSize);
socket.sendRaw(message[offset..(offset + packetSize - 1)]);
offset = offset + packetSize;
}
}

this.transport.send(message);
}
}

Expand Down
98 changes: 98 additions & 0 deletions LSPTransport.sc
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
LSPTransport {
start {
|lspConnection|
this.subclassResponsibility(thisMethod);
}

stop { this.subclassResponsibility(thisMethod); }

send {
|message|
this.subclassResponsibility(thisMethod);
}
}

LSPUDPTransport : LSPTransport {
var <inPort, <outPort;
var <socket;
var <rawRecvFunc;

*new {
|inPort, outPort|
^super.newCopyArgs(inPort, outPort)
}

start {
|lspConnection|

var numAttempts = 3;

// @TODO: What do we do before start / after stop? Errors?
Log('LanguageServer.quark').info("Starting language server, inPort: % outPort:%", inPort, outPort);

numAttempts.do {
|attempt|

try {
socket = socket ?? { NetAddr("127.0.0.1", outPort) };
thisProcess.openUDPPort(inPort, \raw);

rawRecvFunc = {
|msg, time, replyAddr, recvPort|
Log('LanguageServer.quark').info("Message received: %, %, %", time, replyAddr, msg);
lspConnection.onReceived(msg);
};

thisProcess.addRawRecvFunc(rawRecvFunc);
Log('LanguageServer.quark').info("Successfully opened UDP port % on attempt %", inPort, attempt + 1);
^this;
} {
|error|
if (attempt < (numAttempts - 1)) {
Log('LanguageServer.quark').warning("LSP attempt % failed. Killing servers and retrying...", attempt + 1);
Server.killAll();
0.5.wait();
} {
Log('LanguageServer.quark').warning("FATAL: LSP failed after % attempts. Last error: %", numAttempts, error.what);
}
}
};
}

stop {
rawRecvFunc !? {
thisProcess.removeRawRecvFunc(rawRecvFunc);
rawRecvFunc = nil;
};
socket = nil;
}

send {
|message|
var maxSize = 6000;
var offset = 0;
var packetSize;
var messageSize = message.size;

if (socket.isNil) {
Log('LanguageServer.quark').error("Cannot send message: socket not initialized");
^this;
};

try {
if (messageSize < maxSize) {
socket.sendRaw(message);
} {
while { offset < messageSize } {
packetSize = min(messageSize, maxSize);
socket.sendRaw(message[offset..(offset + packetSize - 1)]);
offset = offset + packetSize;
}
}
} {
|error|
Log('LanguageServer.quark').error("Failed to send message: %", error.what);
}

}
}