From be37cd5a53c831f21185c98615ba45a01b5a0621 Mon Sep 17 00:00:00 2001 From: Henrik Hautakoski Date: Sun, 1 Mar 2026 22:57:28 +0100 Subject: [PATCH] add tests --- base_test.go | 97 +++++++++++++++++++++++++++++++ capabilities_client_test.go | 58 ++++++++++++++++++ capabilities_server_test.go | 95 ++++++++++++++++++++++++++++++ client_test.go | 26 +++++++++ completion_test.go | 26 +++++++++ diagnostics_test.go | 28 +++++++++ document_change_operation_test.go | 42 +++++++++++++ document_code_action_test.go | 30 ++++++++++ document_completion_test.go | 18 ++++++ document_definition_test.go | 18 ++++++ document_diagnostic_test.go | 26 +++++++++ document_hover_test.go | 18 ++++++ document_sync_test.go | 34 +++++++++++ document_test.go | 58 ++++++++++++++++++ lifecycle_test.go | 47 +++++++++++++++ progress_test.go | 36 ++++++++++++ rpc_test.go | 2 +- server_test.go | 18 ++++++ window_test.go | 50 ++++++++++++++++ workspace_test.go | 29 +++++++++ 20 files changed, 755 insertions(+), 1 deletion(-) create mode 100644 base_test.go create mode 100644 capabilities_client_test.go create mode 100644 capabilities_server_test.go create mode 100644 client_test.go create mode 100644 completion_test.go create mode 100644 diagnostics_test.go create mode 100644 document_change_operation_test.go create mode 100644 document_code_action_test.go create mode 100644 document_completion_test.go create mode 100644 document_definition_test.go create mode 100644 document_diagnostic_test.go create mode 100644 document_hover_test.go create mode 100644 document_sync_test.go create mode 100644 document_test.go create mode 100644 lifecycle_test.go create mode 100644 progress_test.go create mode 100644 server_test.go create mode 100644 window_test.go create mode 100644 workspace_test.go diff --git a/base_test.go b/base_test.go new file mode 100644 index 0000000..fb6f719 --- /dev/null +++ b/base_test.go @@ -0,0 +1,97 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_Base_PositionJSONRoundTrip(t *testing.T) { + original := protocol.Position{Line: 12, Character: 34} + + data, err := json.Marshal(original) + if err != nil { + t.Fatalf("marshal failed: %v", err) + } + + var decoded protocol.Position + if err := json.Unmarshal(data, &decoded); err != nil { + t.Fatalf("unmarshal failed: %v", err) + } + + if decoded.Line != original.Line || decoded.Character != original.Character { + t.Fatalf("expected %+v, got %+v", original, decoded) + } +} + +func Test_Base_LocationLinkJSONRoundTrip(t *testing.T) { + original := protocol.LocationLink{ + OriginSelectionRange: &protocol.Range{ + Start: protocol.Position{Line: 1, Character: 2}, + End: protocol.Position{Line: 1, Character: 5}, + }, + TargetURI: protocol.DocumentURI("file:///tmp/target.go"), + TargetRange: protocol.Range{ + Start: protocol.Position{Line: 10, Character: 0}, + End: protocol.Position{Line: 20, Character: 0}, + }, + TargetSelectionRange: protocol.Range{ + Start: protocol.Position{Line: 12, Character: 4}, + End: protocol.Position{Line: 12, Character: 10}, + }, + } + + data, err := json.Marshal(original) + if err != nil { + t.Fatalf("marshal failed: %v", err) + } + + var decoded protocol.LocationLink + if err := json.Unmarshal(data, &decoded); err != nil { + t.Fatalf("unmarshal failed: %v", err) + } + + if decoded.TargetURI != original.TargetURI { + t.Fatalf("expected target URI %q, got %q", original.TargetURI, decoded.TargetURI) + } + + if decoded.OriginSelectionRange == nil { + t.Fatalf("expected origin selection range to be present") + } + + if decoded.TargetRange.Start.Line != original.TargetRange.Start.Line || decoded.TargetRange.End.Line != original.TargetRange.End.Line { + t.Fatalf("expected target range %+v, got %+v", original.TargetRange, decoded.TargetRange) + } +} + +func Test_Base_ChangeAnnotationJSONRoundTrip(t *testing.T) { + needsConfirmation := true + original := protocol.ChangeAnnotation{ + Label: "Refactor imports", + NeedsConfirmation: &needsConfirmation, + Description: "Reorders and removes unused imports", + } + + data, err := json.Marshal(original) + if err != nil { + t.Fatalf("marshal failed: %v", err) + } + + var decoded protocol.ChangeAnnotation + if err := json.Unmarshal(data, &decoded); err != nil { + t.Fatalf("unmarshal failed: %v", err) + } + + if decoded.Label != original.Label { + t.Fatalf("expected label %q, got %q", original.Label, decoded.Label) + } + + if decoded.Description != original.Description { + t.Fatalf("expected description %q, got %q", original.Description, decoded.Description) + } + + if decoded.NeedsConfirmation == nil || *decoded.NeedsConfirmation != *original.NeedsConfirmation { + t.Fatalf("expected needsConfirmation=%v, got %+v", *original.NeedsConfirmation, decoded.NeedsConfirmation) + } +} diff --git a/capabilities_client_test.go b/capabilities_client_test.go new file mode 100644 index 0000000..eb82934 --- /dev/null +++ b/capabilities_client_test.go @@ -0,0 +1,58 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_CapabilitiesClient_UnmarshalValidJSON(t *testing.T) { + data := []byte(`{"window":{"showDocument":{"support":true}}}`) + + var decoded protocol.ClientCapabilities + if err := json.Unmarshal(data, &decoded); err != nil { + t.Fatalf("unmarshal failed: %v", err) + } + + if decoded.Window == nil { + t.Fatalf("expected window capabilities to be present") + } + + if decoded.Window.ShowDocument == nil { + t.Fatalf("expected showDocument capabilities to be present") + } + + if !decoded.Window.ShowDocument.Support { + t.Fatalf("expected showDocument support to be true") + } +} + +func Test_CapabilitiesClient_UnmarshalEmptyObject(t *testing.T) { + var decoded protocol.ClientCapabilities + if err := json.Unmarshal([]byte(`{}`), &decoded); err != nil { + t.Fatalf("unmarshal failed: %v", err) + } + + if decoded.Window != nil { + t.Fatalf("expected window capabilities to be nil for empty object") + } +} + +func Test_CapabilitiesClient_MarshalOmitEmptyWindow(t *testing.T) { + original := protocol.ClientCapabilities{} + + data, err := json.Marshal(original) + if err != nil { + t.Fatalf("marshal failed: %v", err) + } + + var payload map[string]any + if err := json.Unmarshal(data, &payload); err != nil { + t.Fatalf("unmarshal failed: %v", err) + } + + if _, ok := payload["window"]; ok { + t.Fatalf("expected window to be omitted, got payload: %s", string(data)) + } +} diff --git a/capabilities_server_test.go b/capabilities_server_test.go new file mode 100644 index 0000000..c345436 --- /dev/null +++ b/capabilities_server_test.go @@ -0,0 +1,95 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_CapabilitiesServer_UnmarshalValidJSON(t *testing.T) { + data := []byte(`{ + "positionEncoding": "utf-16", + "textDocumentSync": 2, + "completionProvider": { + "triggerCharacters": [".", ":"], + "resolveProvider": true, + "completionItem": { + "labelDetailsSupport": true + } + }, + "hoverProvider": true, + "definitionProvider": true, + "codeActionProvider": true, + "signatureHelpProvider": { + "triggerCharacters": ["(", ","], + "retriggerCharacters": [")"] + }, + "diagnosticProvider": { + "interFileDependencies": true, + "workspaceDiagnostics": true + } + }`) + + var decoded protocol.ServerCapabilities + if err := json.Unmarshal(data, &decoded); err != nil { + t.Fatalf("unmarshal failed: %v", err) + } + + positionEncoding := protocol.PositionEncodingKindUTF16 + if decoded.PositionEncoding == nil || *decoded.PositionEncoding != positionEncoding { + t.Fatalf("expected positionEncoding=%q, got %+v", positionEncoding, decoded.PositionEncoding) + } + + if decoded.CompletionProvider == nil { + t.Fatalf("expected completionProvider to be present") + } + + if decoded.CompletionProvider.ResolveProvider == nil || !*decoded.CompletionProvider.ResolveProvider { + t.Fatalf("expected completionProvider.resolveProvider=true") + } + + if decoded.CompletionProvider.CompletionItem == nil { + t.Fatalf("expected completionProvider.completionItem to be present") + } + + if decoded.CompletionProvider.CompletionItem.LabelDetailsSupport == nil || !*decoded.CompletionProvider.CompletionItem.LabelDetailsSupport { + t.Fatalf("expected completionProvider.completionItem.labelDetailsSupport=true") + } + + textDocumentSync, ok := decoded.TextDocumentSync.(float64) + if !ok || int(textDocumentSync) != int(protocol.TextDocumentSyncKindIncremental) { + t.Fatalf("expected textDocumentSync=%d, got %#v", protocol.TextDocumentSyncKindIncremental, decoded.TextDocumentSync) + } + + diagnosticProvider, ok := decoded.DiagnosticProvider.(map[string]any) + if !ok { + t.Fatalf("expected diagnosticProvider object, got %#v", decoded.DiagnosticProvider) + } + + if inter, ok := diagnosticProvider["interFileDependencies"].(bool); !ok || !inter { + t.Fatalf("expected diagnosticProvider.interFileDependencies=true, got %#v", diagnosticProvider["interFileDependencies"]) + } + + if ws, ok := diagnosticProvider["workspaceDiagnostics"].(bool); !ok || !ws { + t.Fatalf("expected diagnosticProvider.workspaceDiagnostics=true, got %#v", diagnosticProvider["workspaceDiagnostics"]) + } +} + +func Test_CapabilitiesServer_MarshalOmitEmptyFields(t *testing.T) { + original := protocol.ServerCapabilities{} + + data, err := json.Marshal(original) + if err != nil { + t.Fatalf("marshal failed: %v", err) + } + + var payload map[string]any + if err := json.Unmarshal(data, &payload); err != nil { + t.Fatalf("unmarshal failed: %v", err) + } + + if len(payload) != 0 { + t.Fatalf("expected empty JSON object from zero-value capabilities, got: %s", string(data)) + } +} diff --git a/client_test.go b/client_test.go new file mode 100644 index 0000000..9edab20 --- /dev/null +++ b/client_test.go @@ -0,0 +1,26 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_Client_StructsUnmarshalValidJSON(t *testing.T) { + var clientInfo protocol.ClientInfo + if err := json.Unmarshal([]byte(`{"name":"nvim","version":"0.10"}`), &clientInfo); err != nil { + t.Fatalf("unmarshal ClientInfo failed: %v", err) + } + if clientInfo.Name != "nvim" { + t.Fatalf("unexpected ClientInfo: %+v", clientInfo) + } + + var command protocol.Command + if err := json.Unmarshal([]byte(`{"title":"Fix","command":"app.fix","arguments":["a",1]}`), &command); err != nil { + t.Fatalf("unmarshal Command failed: %v", err) + } + if command.Command != "app.fix" || len(command.Arguments) != 2 { + t.Fatalf("unexpected Command: %+v", command) + } +} diff --git a/completion_test.go b/completion_test.go new file mode 100644 index 0000000..0213efa --- /dev/null +++ b/completion_test.go @@ -0,0 +1,26 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_Completion_StructsUnmarshalValidJSON(t *testing.T) { + var item protocol.CompletionItem + if err := json.Unmarshal([]byte(`{"label":"fmt.Println","kind":3,"detail":"func","documentation":"prints","insertText":"fmt.Println($1)","textEditText":"fmt.Println","commitCharacters":";"}`), &item); err != nil { + t.Fatalf("unmarshal CompletionItem failed: %v", err) + } + if item.Label != "fmt.Println" { + t.Fatalf("unexpected CompletionItem: %+v", item) + } + + var list protocol.CompletionList + if err := json.Unmarshal([]byte(`{"isIncomplete":false,"items":[{"label":"x"}]}`), &list); err != nil { + t.Fatalf("unmarshal CompletionList failed: %v", err) + } + if len(list.Items) != 1 { + t.Fatalf("unexpected CompletionList: %+v", list) + } +} diff --git a/diagnostics_test.go b/diagnostics_test.go new file mode 100644 index 0000000..389f5e2 --- /dev/null +++ b/diagnostics_test.go @@ -0,0 +1,28 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_Diagnostics_StructsUnmarshalValidJSON(t *testing.T) { + var diag protocol.Diagnostic + if err := json.Unmarshal([]byte(`{ + "range":{"start":{"line":1,"character":1},"end":{"line":1,"character":3}}, + "severity":1, + "code":"E100", + "codeDescription":{"href":"https://example.com/E100"}, + "source":"golangci-lint", + "message":"example diagnostic", + "tags":[1], + "relatedInformation":[{"location":{"uri":"file:///tmp/main.go","range":{"start":{"line":0,"character":0},"end":{"line":0,"character":1}}},"message":"related"}], + "data":{"k":"v"} + }`), &diag); err != nil { + t.Fatalf("unmarshal Diagnostic failed: %v", err) + } + if diag.Message != "example diagnostic" || diag.CodeDescription == nil { + t.Fatalf("unexpected Diagnostic: %+v", diag) + } +} diff --git a/document_change_operation_test.go b/document_change_operation_test.go new file mode 100644 index 0000000..a326bff --- /dev/null +++ b/document_change_operation_test.go @@ -0,0 +1,42 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_DocumentChangeOperation_StructsUnmarshalValidJSON(t *testing.T) { + var op protocol.ResourceOperation + if err := json.Unmarshal([]byte(`{"kind":"create","annotationId":"a1"}`), &op); err != nil { + t.Fatalf("unmarshal ResourceOperation failed: %v", err) + } + if op.Kind != "create" { + t.Fatalf("unexpected ResourceOperation: %+v", op) + } + + var create protocol.CreateFile + if err := json.Unmarshal([]byte(`{"kind":"create","uri":"file:///tmp/new.go","options":{"overwrite":true}}`), &create); err != nil { + t.Fatalf("unmarshal CreateFile failed: %v", err) + } + if create.Options == nil || !create.Options.Overwrite { + t.Fatalf("unexpected CreateFile: %+v", create) + } + + var rename protocol.RenameFile + if err := json.Unmarshal([]byte(`{"kind":"rename","oldUri":"file:///tmp/a.go","newUri":"file:///tmp/b.go","options":{"ignoreIfExists":true}}`), &rename); err != nil { + t.Fatalf("unmarshal RenameFile failed: %v", err) + } + if rename.Options == nil || !rename.Options.IgnoreIfExists { + t.Fatalf("unexpected RenameFile: %+v", rename) + } + + var del protocol.DeleteFile + if err := json.Unmarshal([]byte(`{"kind":"delete","uri":"file:///tmp/old.go","options":{"recursive":true,"ignoreIfNotExists":true}}`), &del); err != nil { + t.Fatalf("unmarshal DeleteFile failed: %v", err) + } + if del.Options == nil || !del.Options.Recursive || !del.Options.IgnoreIfNotExists { + t.Fatalf("unexpected DeleteFile: %+v", del) + } +} diff --git a/document_code_action_test.go b/document_code_action_test.go new file mode 100644 index 0000000..58094f1 --- /dev/null +++ b/document_code_action_test.go @@ -0,0 +1,30 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_DocumentCodeAction_StructsUnmarshalValidJSON(t *testing.T) { + var params protocol.CodeActionParams + if err := json.Unmarshal([]byte(`{ + "textDocument":{"uri":"file:///tmp/main.go"}, + "range":{"start":{"line":1,"character":0},"end":{"line":1,"character":4}}, + "context":{"diagnostics":[{"range":{"start":{"line":1,"character":0},"end":{"line":1,"character":4}},"message":"problem"}],"only":["quickfix"],"triggerKind":1} + }`), ¶ms); err != nil { + t.Fatalf("unmarshal CodeActionParams failed: %v", err) + } + if len(params.Context.Diagnostics) != 1 { + t.Fatalf("unexpected CodeActionParams diagnostics: %+v", params.Context.Diagnostics) + } + + var action protocol.CodeAction + if err := json.Unmarshal([]byte(`{"title":"Fix issue","kind":"quickfix","isPreferred":true,"disabled":{"reason":"not applicable"}}`), &action); err != nil { + t.Fatalf("unmarshal CodeAction failed: %v", err) + } + if action.Disabled == nil || action.Disabled.Reason != "not applicable" { + t.Fatalf("unexpected CodeAction disabled state: %+v", action.Disabled) + } +} diff --git a/document_completion_test.go b/document_completion_test.go new file mode 100644 index 0000000..6877347 --- /dev/null +++ b/document_completion_test.go @@ -0,0 +1,18 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_DocumentCompletion_ParamsUnmarshalValidJSON(t *testing.T) { + var completion protocol.CompletionParams + if err := json.Unmarshal([]byte(`{"textDocument":{"uri":"file:///tmp/main.go"},"position":{"line":1,"character":1},"context":{"triggerKind":2,"triggerCharacter":"."}}`), &completion); err != nil { + t.Fatalf("unmarshal CompletionParams failed: %v", err) + } + if completion.Context == nil || completion.Context.TriggerCharacter != "." { + t.Fatalf("unexpected CompletionParams context: %+v", completion.Context) + } +} diff --git a/document_definition_test.go b/document_definition_test.go new file mode 100644 index 0000000..754b5d7 --- /dev/null +++ b/document_definition_test.go @@ -0,0 +1,18 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_DocumentDefinition_ParamsUnmarshalValidJSON(t *testing.T) { + var def protocol.DefinitionParams + if err := json.Unmarshal([]byte(`{"textDocument":{"uri":"file:///tmp/main.go"},"position":{"line":1,"character":1}}`), &def); err != nil { + t.Fatalf("unmarshal DefinitionParams failed: %v", err) + } + if def.TextDocument.URI != "file:///tmp/main.go" { + t.Fatalf("unexpected DefinitionParams: %+v", def) + } +} diff --git a/document_diagnostic_test.go b/document_diagnostic_test.go new file mode 100644 index 0000000..e6fb2b5 --- /dev/null +++ b/document_diagnostic_test.go @@ -0,0 +1,26 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_DocumentDiagnostic_StructsUnmarshalValidJSON(t *testing.T) { + var params protocol.DocumentDiagnosticParams + if err := json.Unmarshal([]byte(`{"textDocument":{"uri":"file:///tmp/main.go"},"identifier":"go","previousResultId":"r1"}`), ¶ms); err != nil { + t.Fatalf("unmarshal DocumentDiagnosticParams failed: %v", err) + } + if params.Identifier != "go" { + t.Fatalf("unexpected DocumentDiagnosticParams: %+v", params) + } + + var report protocol.DocumentDiagnosticReport + if err := json.Unmarshal([]byte(`{"kind":"full","resultId":"r2","items":[{"range":{"start":{"line":0,"character":0},"end":{"line":0,"character":1}},"message":"m"}]}`), &report); err != nil { + t.Fatalf("unmarshal DocumentDiagnosticReport failed: %v", err) + } + if report.Full == nil || report.Full.Kind != "full" { + t.Fatalf("unexpected DocumentDiagnosticReport: %+v", report) + } +} diff --git a/document_hover_test.go b/document_hover_test.go new file mode 100644 index 0000000..b4b8576 --- /dev/null +++ b/document_hover_test.go @@ -0,0 +1,18 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_DocumentHover_ParamsUnmarshalValidJSON(t *testing.T) { + var hover protocol.HoverParams + if err := json.Unmarshal([]byte(`{"textDocument":{"uri":"file:///tmp/main.go"},"position":{"line":1,"character":1}}`), &hover); err != nil { + t.Fatalf("unmarshal HoverParams failed: %v", err) + } + if hover.TextDocument.URI == "" { + t.Fatalf("unexpected HoverParams: %+v", hover) + } +} diff --git a/document_sync_test.go b/document_sync_test.go new file mode 100644 index 0000000..abd3d99 --- /dev/null +++ b/document_sync_test.go @@ -0,0 +1,34 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_DocumentSync_StructsUnmarshalValidJSON(t *testing.T) { + var open protocol.DidOpenTextDocumentParams + if err := json.Unmarshal([]byte(`{"textDocument":{"uri":"file:///tmp/main.go","languageId":"go","version":1,"text":"package main"}}`), &open); err != nil { + t.Fatalf("unmarshal DidOpenTextDocumentParams failed: %v", err) + } + if open.TextDocument.URI == "" { + t.Fatalf("unexpected DidOpenTextDocumentParams: %+v", open) + } + + var change protocol.DidChangeTextDocumentParams + if err := json.Unmarshal([]byte(`{"textDocument":{"uri":"file:///tmp/main.go","version":2},"contentChanges":[{"range":{"start":{"line":0,"character":0},"end":{"line":0,"character":0}},"text":"x"}]}`), &change); err != nil { + t.Fatalf("unmarshal DidChangeTextDocumentParams failed: %v", err) + } + if len(change.ContentChanges) != 1 { + t.Fatalf("unexpected DidChangeTextDocumentParams: %+v", change) + } + + var save protocol.DidSaveTextDocumentParams + if err := json.Unmarshal([]byte(`{"textDocument":{"uri":"file:///tmp/main.go"},"text":"content"}`), &save); err != nil { + t.Fatalf("unmarshal DidSaveTextDocumentParams failed: %v", err) + } + if save.Text != "content" { + t.Fatalf("unexpected DidSaveTextDocumentParams: %+v", save) + } +} diff --git a/document_test.go b/document_test.go new file mode 100644 index 0000000..df20905 --- /dev/null +++ b/document_test.go @@ -0,0 +1,58 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_Document_StructsUnmarshalValidJSON(t *testing.T) { + var id protocol.TextDocumentIdentifier + if err := json.Unmarshal([]byte(`{"uri":"file:///tmp/main.go"}`), &id); err != nil { + t.Fatalf("unmarshal TextDocumentIdentifier failed: %v", err) + } + if id.URI != "file:///tmp/main.go" { + t.Fatalf("unexpected TextDocumentIdentifier: %+v", id) + } + + var versioned protocol.VersionedTextDocumentIdentifier + if err := json.Unmarshal([]byte(`{"uri":"file:///tmp/main.go","version":5}`), &versioned); err != nil { + t.Fatalf("unmarshal VersionedTextDocumentIdentifier failed: %v", err) + } + if versioned.Version != 5 { + t.Fatalf("unexpected VersionedTextDocumentIdentifier: %+v", versioned) + } + + var item protocol.TextDocumentItem + if err := json.Unmarshal([]byte(`{"uri":"file:///tmp/main.go","languageId":"go","version":5,"text":"package main"}`), &item); err != nil { + t.Fatalf("unmarshal TextDocumentItem failed: %v", err) + } + if item.LanguageID != protocol.LanguageGo { + t.Fatalf("unexpected TextDocumentItem language: %s", item.LanguageID) + } + + var pos protocol.TextDocumentPositionParams + if err := json.Unmarshal([]byte(`{"textDocument":{"uri":"file:///tmp/main.go"},"position":{"line":3,"character":1}}`), &pos); err != nil { + t.Fatalf("unmarshal TextDocumentPositionParams failed: %v", err) + } + if pos.Position.Line != 3 { + t.Fatalf("unexpected TextDocumentPositionParams: %+v", pos) + } + + var edit protocol.TextEdit + if err := json.Unmarshal([]byte(`{"range":{"start":{"line":1,"character":0},"end":{"line":1,"character":2}},"newText":"hi"}`), &edit); err != nil { + t.Fatalf("unmarshal TextEdit failed: %v", err) + } + if edit.NewText != "hi" { + t.Fatalf("unexpected TextEdit: %+v", edit) + } + + var docEdit protocol.TextDocumentEdit + if err := json.Unmarshal([]byte(`{"textDocument":{"uri":"file:///tmp/main.go","version":5},"edits":[{"range":{"start":{"line":0,"character":0},"end":{"line":0,"character":0}},"newText":"x"}]}`), &docEdit); err != nil { + t.Fatalf("unmarshal TextDocumentEdit failed: %v", err) + } + if len(docEdit.Edits) != 1 { + t.Fatalf("unexpected TextDocumentEdit edits: %+v", docEdit.Edits) + } +} diff --git a/lifecycle_test.go b/lifecycle_test.go new file mode 100644 index 0000000..1b8a5a6 --- /dev/null +++ b/lifecycle_test.go @@ -0,0 +1,47 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_Lifecycle_StructsUnmarshalValidJSON(t *testing.T) { + var initParams protocol.InitializeParams + if err := json.Unmarshal([]byte(`{ + "processId":123, + "clientInfo":{"name":"vscode","version":"1.0"}, + "locale":"en-US", + "rootPath":"/workspace", + "rootUri":"file:///workspace", + "initializationOptions":{"feature":true}, + "capabilities":{"window":{"showDocument":{"support":true}}}, + "trace":"messages", + "workspaceFolders":[{"uri":"file:///workspace","name":"workspace"}] + }`), &initParams); err != nil { + t.Fatalf("unmarshal InitializeParams failed: %v", err) + } + if initParams.ClientInfo == nil || initParams.ClientInfo.Name != "vscode" { + t.Fatalf("unexpected InitializeParams clientInfo: %+v", initParams.ClientInfo) + } + if initParams.Capabilities.Window == nil || initParams.Capabilities.Window.ShowDocument == nil || !initParams.Capabilities.Window.ShowDocument.Support { + t.Fatalf("unexpected InitializeParams capabilities: %+v", initParams.Capabilities) + } + + var initResult protocol.InitializeResult + if err := json.Unmarshal([]byte(`{"capabilities":{"hoverProvider":true},"serverInfo":{"name":"ls","version":"0.1"}}`), &initResult); err != nil { + t.Fatalf("unmarshal InitializeResult failed: %v", err) + } + if initResult.ServerInfo == nil || initResult.ServerInfo.Name != "ls" { + t.Fatalf("unexpected InitializeResult: %+v", initResult) + } + + var cancel protocol.CancelParams + if err := json.Unmarshal([]byte(`{"id":42}`), &cancel); err != nil { + t.Fatalf("unmarshal CancelParams failed: %v", err) + } + if cancel.Id.String() != "42" { + t.Fatalf("unexpected CancelParams id: %s", cancel.Id.String()) + } +} diff --git a/progress_test.go b/progress_test.go new file mode 100644 index 0000000..93440b4 --- /dev/null +++ b/progress_test.go @@ -0,0 +1,36 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_Progress_StructsUnmarshalValidJSON(t *testing.T) { + var workDone protocol.WorkDoneProgressParams + if err := json.Unmarshal([]byte(`{"workDoneToken":"wd-1"}`), &workDone); err != nil { + t.Fatalf("unmarshal WorkDoneProgressParams failed: %v", err) + } + if workDone.WorkDoneToken == nil { + t.Fatalf("expected workDoneToken to be set") + } + + var partial protocol.PartialResultParams + if err := json.Unmarshal([]byte(`{"partialResultToken":99}`), &partial); err != nil { + t.Fatalf("unmarshal PartialResultParams failed: %v", err) + } + if partial.PartialResultToken == nil { + t.Fatalf("expected partialResultToken to be set") + } + + var create protocol.WorkDoneProgressCreateParams + if err := json.Unmarshal([]byte(`{"token":"create-token"}`), &create); err != nil { + t.Fatalf("unmarshal WorkDoneProgressCreateParams failed: %v", err) + } + + var cancel protocol.WorkDoneProgressCancelParams + if err := json.Unmarshal([]byte(`{"token":7}`), &cancel); err != nil { + t.Fatalf("unmarshal WorkDoneProgressCancelParams failed: %v", err) + } +} diff --git a/rpc_test.go b/rpc_test.go index f827aef..7174813 100644 --- a/rpc_test.go +++ b/rpc_test.go @@ -6,7 +6,7 @@ import ( "github.com/laravel-ls/protocol" ) -func Test_IsLspRPCErrorCode(t *testing.T) { +func Test_Rpc_IsLspRPCErrorCode(t *testing.T) { if protocol.IsLspRPCErrorCode(5000) { t.Errorf("5000 is not a valid code, but function returned true") } diff --git a/server_test.go b/server_test.go new file mode 100644 index 0000000..bd7b636 --- /dev/null +++ b/server_test.go @@ -0,0 +1,18 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_Server_InfoUnmarshalValidJSON(t *testing.T) { + var serverInfo protocol.ServerInfo + if err := json.Unmarshal([]byte(`{"name":"my-ls","version":"0.0.1"}`), &serverInfo); err != nil { + t.Fatalf("unmarshal ServerInfo failed: %v", err) + } + if serverInfo.Name != "my-ls" { + t.Fatalf("unexpected ServerInfo: %+v", serverInfo) + } +} diff --git a/window_test.go b/window_test.go new file mode 100644 index 0000000..bbab1a5 --- /dev/null +++ b/window_test.go @@ -0,0 +1,50 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_Window_StructsUnmarshalValidJSON(t *testing.T) { + var show protocol.ShowMessageParams + if err := json.Unmarshal([]byte(`{"type":2,"message":"Heads up"}`), &show); err != nil { + t.Fatalf("unmarshal ShowMessageParams failed: %v", err) + } + if show.Type != protocol.MessageTypeWarning || show.Message != "Heads up" { + t.Fatalf("unexpected ShowMessageParams: %+v", show) + } + + var request protocol.ShowMessageRequestParams + if err := json.Unmarshal([]byte(`{"type":1,"message":"Retry?","actions":[{"title":"Retry"}]}`), &request); err != nil { + t.Fatalf("unmarshal ShowMessageRequestParams failed: %v", err) + } + if len(request.Actions) != 1 || request.Actions[0].Title != "Retry" { + t.Fatalf("unexpected ShowMessageRequestParams actions: %+v", request.Actions) + } + + var log protocol.LogMessageParams + if err := json.Unmarshal([]byte(`{"type":4,"message":"log line"}`), &log); err != nil { + t.Fatalf("unmarshal LogMessageParams failed: %v", err) + } + if log.Type != protocol.MessageTypeLog { + t.Fatalf("unexpected LogMessageParams type: %v", log.Type) + } + + var showDoc protocol.ShowDocumentParams + if err := json.Unmarshal([]byte(`{"uri":"file:///tmp/a.go","takeFocus":true,"external":false,"selection":{"start":{"line":1,"character":2},"end":{"line":1,"character":6}}}`), &showDoc); err != nil { + t.Fatalf("unmarshal ShowDocumentParams failed: %v", err) + } + if showDoc.URI != "file:///tmp/a.go" || showDoc.Selection == nil { + t.Fatalf("unexpected ShowDocumentParams: %+v", showDoc) + } + + var result protocol.ShowDocumentResult + if err := json.Unmarshal([]byte(`{"success":true}`), &result); err != nil { + t.Fatalf("unmarshal ShowDocumentResult failed: %v", err) + } + if !result.Success { + t.Fatalf("unexpected ShowDocumentResult: %+v", result) + } +} diff --git a/workspace_test.go b/workspace_test.go new file mode 100644 index 0000000..36d4289 --- /dev/null +++ b/workspace_test.go @@ -0,0 +1,29 @@ +package protocol_test + +import ( + "encoding/json" + "testing" + + "github.com/laravel-ls/protocol" +) + +func Test_Workspace_StructsUnmarshalValidJSON(t *testing.T) { + var ws protocol.WorkspaceEdit + if err := json.Unmarshal([]byte(`{ + "changes":{"file:///tmp/main.go":[{"range":{"start":{"line":0,"character":0},"end":{"line":0,"character":0}},"newText":"package main\n"}]}, + "changeAnnotations":{"a1":{"label":"Add package declaration","description":"Needed for file header","needsConfirmation":false}} + }`), &ws); err != nil { + t.Fatalf("unmarshal WorkspaceEdit failed: %v", err) + } + if len(ws.Changes) != 1 || len(ws.ChangeAnnotations) != 1 { + t.Fatalf("unexpected WorkspaceEdit: %+v", ws) + } + + var folder protocol.WorkspaceFolder + if err := json.Unmarshal([]byte(`{"uri":"file:///workspace","name":"workspace"}`), &folder); err != nil { + t.Fatalf("unmarshal WorkspaceFolder failed: %v", err) + } + if folder.Name != "workspace" { + t.Fatalf("unexpected WorkspaceFolder: %+v", folder) + } +}