-
Notifications
You must be signed in to change notification settings - Fork 26
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(tools/spxls): implement initial LSP features
- Add WASM adapter for spxls. - Implement spxlc (JavaScript client for spxls). - Add `MapFS` implementation for file system operations. - Implement `textDocument/formatting` LSP capability. - Fix multiple `var` blocks handling in spx source code. (Fixes #752) - Fix declaration order requirements (vars -> funcs -> others). (Fixes #591) - Set up basic project layout. Updates #1059 Signed-off-by: Aofei Sheng <[email protected]>
- Loading branch information
Showing
15 changed files
with
1,815 additions
and
27 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,116 @@ | ||
import { Files, NewSpxls, NotificationMessage, RequestMessage, ResponseMessage, Spxls } from '.' | ||
|
||
/** | ||
* Client wrapper for the spxls. | ||
*/ | ||
export class Spxlc { | ||
private ls: Spxls | ||
private nextRequestId: number = 1 | ||
private pendingRequests = new Map<number, { | ||
resolve: (response: any) => void | ||
reject: (error: any) => void | ||
}>() | ||
private notificationHandlers = new Map<string, (params: any) => void>() | ||
|
||
/** | ||
* Creates a new client instance. | ||
* @param filesProvider Function that provides access to workspace files. | ||
*/ | ||
constructor(filesProvider: () => Files) { | ||
const ls = NewSpxls(filesProvider, this.handleMessage.bind(this)) | ||
if (ls instanceof Error) throw ls | ||
this.ls = ls | ||
} | ||
|
||
/** | ||
* Handles messages from the language server. | ||
* @param message Message from the server. | ||
* @throws Error if the message type is unknown. | ||
*/ | ||
private handleMessage(message: ResponseMessage | NotificationMessage): void { | ||
if ('id' in message) return this.handleResponseMessage(message) | ||
if ('method' in message) return this.handleNotificationMessage(message) | ||
throw new Error('unknown message type') | ||
} | ||
|
||
/** | ||
* Handles response messages from the language server. | ||
* @param message Response message from the server. | ||
* @throws Error if no pending request is found for the message ID. | ||
*/ | ||
private handleResponseMessage(message: ResponseMessage): void { | ||
const pending = this.pendingRequests.get(message.id) | ||
if (pending == null) throw new Error(`no pending request found for id: ${message.id}`) | ||
this.pendingRequests.delete(message.id) | ||
|
||
if ('error' in message) pending.reject(message.error) | ||
else pending.resolve(message.result) | ||
} | ||
|
||
/** | ||
* Handles notification messages from the language server. | ||
* @param message Notification message from the server. | ||
* @throws Error if no handler is found for the notification method. | ||
*/ | ||
private handleNotificationMessage(message: NotificationMessage): void { | ||
const handler = this.notificationHandlers.get(message.method) | ||
if (handler == null) throw new Error(`no notification handler found for method: ${message.method}`) | ||
|
||
handler(message.params) | ||
} | ||
|
||
/** | ||
* Sends a request to the language server and waits for response. | ||
* @param method LSP method name. | ||
* @param params Method parameters. | ||
* @returns Promise that resolves with the response. | ||
*/ | ||
request<T>(method: string, params?: any): Promise<T> { | ||
return new Promise((resolve, reject) => { | ||
const id = this.nextRequestId++ | ||
|
||
const message: RequestMessage = { | ||
jsonrpc: '2.0', | ||
id, | ||
method, | ||
params | ||
} | ||
const err = this.ls.handleMessage(message) | ||
if (err != null) reject(err) | ||
|
||
this.pendingRequests.set(id, { resolve, reject }) | ||
}) | ||
} | ||
|
||
/** | ||
* Sends a notification to the language server (no response expected). | ||
* @param method LSP method name. | ||
* @param params Method parameters. | ||
*/ | ||
notify(method: string, params?: any): void { | ||
const message: NotificationMessage = { | ||
jsonrpc: '2.0', | ||
method, | ||
params | ||
} | ||
const err = this.ls.handleMessage(message) | ||
if (err != null) throw err | ||
} | ||
|
||
/** | ||
* Registers a handler for server notifications. | ||
* @param method LSP method name. | ||
* @param handler Function to handle the notification. | ||
*/ | ||
onNotification(method: string, handler: (params: any) => void): void { | ||
this.notificationHandlers.set(method, handler) | ||
} | ||
|
||
/** | ||
* Cleans up client resources. | ||
*/ | ||
dispose(): void { | ||
this.pendingRequests.clear() | ||
this.notificationHandlers.clear() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
module github.com/goplus/builder/tools/spxls | ||
|
||
go 1.21.0 | ||
|
||
require ( | ||
github.com/goplus/gop v1.2.6 | ||
github.com/stretchr/testify v1.9.0 | ||
) | ||
|
||
require ( | ||
github.com/davecgh/go-spew v1.1.1 // indirect | ||
github.com/goplus/gogen v1.15.2 // indirect | ||
github.com/pmezard/go-difflib v1.0.0 // indirect | ||
github.com/qiniu/x v1.13.10 // indirect | ||
gopkg.in/yaml.v3 v3.0.1 // indirect | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= | ||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= | ||
github.com/goplus/gogen v1.15.2 h1:Q6XaSx/Zi5tWnjfAziYsQI6Jv6MgODRpFtOYqNkiiqM= | ||
github.com/goplus/gogen v1.15.2/go.mod h1:92qEzVgv7y8JEFICWG9GvYI5IzfEkxYdsA1DbmnTkqk= | ||
github.com/goplus/gop v1.2.6 h1:kog3c5Js+8EopqmI4+CwueXsqibnBwYVt5q5N7juRVY= | ||
github.com/goplus/gop v1.2.6/go.mod h1:uREWbR1MrFaviZ4Mbx4ZCcAYDoqzO0iv1Qo6Np0Xx4E= | ||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= | ||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= | ||
github.com/qiniu/x v1.13.10 h1:J4Z3XugYzAq85SlyAfqlKVrbf05glMbAOh+QncsDQpE= | ||
github.com/qiniu/x v1.13.10/go.mod h1:INZ2TSWSJVWO/RuELQROERcslBwVgFG7MkTfEdaQz9E= | ||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= | ||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
Oops, something went wrong.