11import EventEmitter from "node:events" ;
2+ import * as path from "node:path" ;
23import * as vscode from "vscode" ;
34import {
45LanguageClient ,
@@ -10,7 +11,7 @@ import {
1011} from "vscode-languageclient/node" ;
1112
1213import { globals } from "../extension" ;
13- import { createLogger , get_configuration } from "../utils" ;
14+ import { createLogger , get_configuration , get_project_dir } from "../utils" ;
1415import { MessageIO } from "./MessageIO" ;
1516
1617const log = createLogger ( "lsp.client" , { output : "Godot LSP" } ) ;
@@ -19,6 +20,7 @@ export enum ClientStatus {
1920PENDING = 0 ,
2021DISCONNECTED = 1 ,
2122CONNECTED = 2 ,
23+ REJECTED = 3 ,
2224}
2325
2426export enum TargetLSP {
@@ -29,7 +31,7 @@ export enum TargetLSP {
2931export type Target = {
3032host : string ;
3133port : number ;
32- type : TargetLSP ;
34+ type : TargetLSP ;
3335} ;
3436
3537type HoverResult = {
@@ -55,6 +57,13 @@ type HoverResponseMesssage = {
5557result : HoverResult ;
5658} ;
5759
60+ type ChangeWorkspaceNotification = {
61+ method : string ;
62+ params : {
63+ path : string ;
64+ } ;
65+ } ;
66+
5867export default class GDScriptLanguageClient extends LanguageClient {
5968public io : MessageIO = new MessageIO ( ) ;
6069
@@ -63,6 +72,8 @@ export default class GDScriptLanguageClient extends LanguageClient {
6372public port = - 1 ;
6473public lastPortTried = - 1 ;
6574public sentMessages = new Map ( ) ;
75+ private initMessage : RequestMessage ;
76+ private rejected = false ;
6677
6778events = new EventEmitter ( ) ;
6879
@@ -85,9 +96,6 @@ export default class GDScriptLanguageClient extends LanguageClient {
8596{ scheme : "file" , language : "gdscript" } ,
8697{ scheme : "untitled" , language : "gdscript" } ,
8798] ,
88- synchronize : {
89- fileEvents : vscode . workspace . createFileSystemWatcher ( "**/*.gd" ) ,
90- } ,
9199} ;
92100
93101super ( "GDScriptLanguageClient" , serverOptions , clientOptions ) ;
@@ -100,6 +108,7 @@ export default class GDScriptLanguageClient extends LanguageClient {
100108}
101109
102110connect ( target : TargetLSP = TargetLSP . EDITOR ) {
111+ this . rejected = false ;
103112this . target = target ;
104113this . status = ClientStatus . PENDING ;
105114
@@ -122,15 +131,38 @@ export default class GDScriptLanguageClient extends LanguageClient {
122131this . io . connect ( host , port ) ;
123132}
124133
134+ async send_request ( method : string , params ) {
135+ try {
136+ return this . sendRequest ( method , params ) ;
137+ } catch {
138+ log . warn ( "sending request failed!" ) ;
139+ }
140+ }
141+
125142private request_filter ( message : RequestMessage ) {
143+ if ( this . rejected ) {
144+ if ( message . method === "shutdown" ) {
145+ return message ;
146+ }
147+ return false ;
148+ }
126149this . sentMessages . set ( message . id , message ) ;
127150
151+ if ( ! this . initMessage && message . method === "initialize" ) {
152+ this . initMessage = message ;
153+ }
128154// discard outgoing messages that we know aren't supported
129- if ( message . method === "didChangeWatchedFiles" ) {
130- return ;
155+ // if (message.method === "textDocument/didSave") {
156+ // return false;
157+ // }
158+ // if (message.method === "textDocument/willSaveWaitUntil") {
159+ // return false;
160+ // }
161+ if ( message . method === "workspace/didChangeWatchedFiles" ) {
162+ return false ;
131163}
132164if ( message . method === "workspace/symbol" ) {
133- return ;
165+ return false ;
134166}
135167
136168return message ;
@@ -165,9 +197,19 @@ export default class GDScriptLanguageClient extends LanguageClient {
165197return message ;
166198}
167199
200+ private async check_workspace ( message : ChangeWorkspaceNotification ) {
201+ const server_path = path . normalize ( message . params . path ) ;
202+ const client_path = path . normalize ( await get_project_dir ( ) ) ;
203+ if ( server_path !== client_path ) {
204+ log . warn ( "Connected LSP is a different workspace" ) ;
205+ this . io . socket . resetAndDestroy ( ) ;
206+ this . rejected = true ;
207+ }
208+ }
209+
168210private notification_filter ( message : NotificationMessage ) {
169211if ( message . method === "gdscript_client/changeWorkspace" ) {
170- //
212+ this . check_workspace ( message as ChangeWorkspaceNotification ) ;
171213}
172214if ( message . method === "gdscript/capabilities" ) {
173215globals . docsProvider . register_capabilities ( message ) ;
@@ -194,9 +236,8 @@ export default class GDScriptLanguageClient extends LanguageClient {
194236textDocument : { uri : uri . toString ( ) } ,
195237position : { line : position . line , character : position . character } ,
196238} ;
197- const response : HoverResult = await this . sendRequest ( "textDocument/hover" , params ) ;
198-
199- return this . parse_hover_result ( response ) ;
239+ const response = await this . send_request ( "textDocument/hover" , params ) ;
240+ return this . parse_hover_result ( response as HoverResult ) ;
200241}
201242
202243private parse_hover_result ( message : HoverResult ) {
@@ -233,9 +274,17 @@ export default class GDScriptLanguageClient extends LanguageClient {
233274
234275const host = get_configuration ( "lsp.serverHost" ) ;
235276log . info ( `connected to LSP at ${ host } :${ this . lastPortTried } ` ) ;
277+
278+ if ( this . initMessage ) {
279+ this . send_request ( this . initMessage . method , this . initMessage . params ) ;
280+ }
236281}
237282
238283private on_disconnected ( ) {
284+ if ( this . rejected ) {
285+ this . status = ClientStatus . REJECTED ;
286+ return ;
287+ }
239288if ( this . target === TargetLSP . EDITOR ) {
240289const host = get_configuration ( "lsp.serverHost" ) ;
241290let port = get_configuration ( "lsp.serverPort" ) ;
0 commit comments