Documents

Track open documents, apply LSP edits, and convert UTF-16 positions safely.

Use document.Store

type Handler struct {
    documents *document.Store
}

func NewHandler() *Handler {
    return &Handler{documents: document.NewStore()}
}

Forward Sync Notifications

func (h *Handler) DidOpen(ctx context.Context, params *lsp.DidOpenTextDocumentParams) error {
    _, err := h.documents.Open(params)
    return err
}

func (h *Handler) DidChange(ctx context.Context, params *lsp.DidChangeTextDocumentParams) error {
    _, err := h.documents.Change(params)
    return err
}

func (h *Handler) DidClose(ctx context.Context, params *lsp.DidCloseTextDocumentParams) error {
    h.documents.Close(params)
    return nil
}

Read Text

text, ok := h.documents.Text(params.TextDocument.URI)
if !ok {
    return nil
}

Positions and Offsets

LSP positions use UTF-16 code units. Go strings use byte offsets. Use OffsetAt and PositionAt at the boundary between LSP and your parser.

doc, ok := h.documents.Get(uri)
if !ok {
    return nil
}

offset, err := doc.OffsetAt(params.Position)
position, err := doc.PositionAt(offset)
This matters for emoji and other characters represented as UTF-16 surrogate pairs. Do not treat LSP character values as Go byte offsets.