11package lifecycle
22
33import (
4+ "encoding/json"
45 "testing"
56
67 "bennypowers.dev/asimonim/lsp/internal/uriutil"
@@ -110,6 +111,8 @@ func TestInitialize(t *testing.T) {
110111 diagOpts , ok := caps .DiagnosticProvider .(protocol.DiagnosticOptions )
111112 require .True (t , ok )
112113 assert .True (t , diagOpts .WorkspaceDiagnostics )
114+ require .NotNil (t , diagOpts .Identifier , "Identifier must be set to avoid Neovim null userdata crash" )
115+ assert .Equal (t , "asimonim" , * diagOpts .Identifier )
113116
114117 // Verify completion provider options
115118 assert .NotNil (t , caps .CompletionProvider .ResolveProvider )
@@ -122,6 +125,30 @@ func TestInitialize(t *testing.T) {
122125 assert .True (t , * codeActionProvider .ResolveProvider )
123126 })
124127
128+ t .Run ("diagnostic identifier serializes as string not null" , func (t * testing.T ) {
129+ ctx := testutil .NewMockServerContext ()
130+ glspCtx := & glsp.Context {}
131+ req := types .NewRequestContext (ctx , glspCtx )
132+ ctx .SetClientDiagnosticCapability (true )
133+
134+ params := & protocol.InitializeParams {
135+ Capabilities : protocol.ClientCapabilities {
136+ TextDocument : & protocol.TextDocumentClientCapabilities {},
137+ },
138+ }
139+
140+ result , err := Initialize (req , params )
141+ require .NoError (t , err )
142+
143+ initResult := result .(protocol.InitializeResult )
144+ data , err := json .Marshal (initResult .Capabilities )
145+ require .NoError (t , err )
146+
147+ // Neovim crashes when identifier is null (Lua userdata vs string)
148+ assert .NotContains (t , string (data ), `"identifier":null` )
149+ assert .Contains (t , string (data ), `"identifier":"asimonim"` )
150+ })
151+
125152 t .Run ("handles client info" , func (t * testing.T ) {
126153 ctx := testutil .NewMockServerContext ()
127154 glspCtx := & glsp.Context {}
0 commit comments