starlsp

package module
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 16, 2026 License: Apache-2.0 Imports: 22 Imported by: 0

README

starlsp

A language server for Starlark, written in pure Go. No cgo, no C toolchain, no build tags — go install and it works.

go install github.com/M31-Labs/starlsp/cmd/starlsp@latest

Starlark has no single dialect. Bazel, Buck, Tilt, and Starkite each add their own builtins, their own meaning for load(), and their own rules about what a well-formed file even is. starlsp knows the language specification; a dialect supplies the rest through one small interface. Bazel and Tilt ship in the box.

starlsp --dialect bazel      # BUILD, BUILD.bazel, WORKSPACE, MODULE.bazel, .bzl
starlsp --dialect tilt       # Tiltfile
starlsp                      # auto-detects from the working directory

It is quiet on real code

The measurement that matters for a language server is how often it is wrong about working code. Against 461 files from bazelbuild/rules_go, bazelbuild/bazel-skylib, and tilt-dev/tilt:

Corpus Files Errors, spec host Errors, dialect host
Bazel .bzl / BUILD / WORKSPACE 426 1,275 0
Tiltfiles 35 195 0

Zero. Not "few" — every file that Bazel and Tilt accept, starlsp accepts.

Two things that number depends on, both of which are easy to get wrong:

  • Tilt permits top-level if and for. Bazel does not. A server that hard-codes the specification reports a syntax error on real Tiltfiles. Dialects carry syntax.FileOptions, so the parser and resolver enforce the variant the host actually runs.
  • The builtin sets were checked against real code, not just documentation. Every name those three repositories reference is present.

Robustness is measured the same way: 21,740 positional requests — hover, completion, signature help, definition, highlight — driven at a stride across 60 real files, with no crash. Plus out-of-range positions, negative lines, and requests for documents that were never opened.

The protocol is verified against Microsoft's own LSP client libraries (vscode-languageserver-protocol), the layers VS Code's LanguageClient is built on — not a hand-written harness that might agree with the server about what the protocol means. 18 end-to-end exchanges, run in CI.

Built to survive a working day

A language server runs for hours inside an editor, and the failures that matter there are not wrong answers:

  • A panic cannot kill the session. Every handler is recovered; the client gets an error response and the server carries on. Hosts are written by other people, so a host that panics is tested for explicitly.
  • Slow work does not block typing. Read-only requests run concurrently under a bounded pool; only the notifications whose order is their meaning — didOpen, didChange, didClose — are serialised.
  • Cancellation is honoured. $/cancelRequest stops work nobody is waiting for, including a workspace scan mid-walk.
  • The outline does not vanish while you type. Typing the dot in x = foo. degenerates the whole parse into one error node — exactly when you are asking for completion — so navigation falls back to the last tree that had structure. Highlighting deliberately does not, because stale token ranges colour the wrong characters.
  • The analysis cache is per document. A single-entry cache is worse than none once two files are open, since every switch evicts the other.

Tested against adversarial input — nul bytes, invalid UTF-8, a 100,000-character line, 500-deep nesting, unterminated strings, CRLF, a BOM — and under -race with two dozen goroutines hammering the same documents.

Also a linter

The server without the protocol. Same parser, same resolver, same host — so a file clean in CI is clean in the editor, and neither can drift from the other.

$ starlsp --dialect tilt --check Tiltfile
$ echo $?
0

$ starlsp --dialect starlark --check Tiltfile
Tiltfile:5:1: error: if statement not within a function
Tiltfile:6:3: error: undefined: k8s_yaml
$ echo $?
1

Embeddable too — Server.Diagnose(uri, text) and Server.DiagnoseFile(path) need no client and no transport.

Why another one

tilt-dev/starlark-lsp came first and proved the idea. It is worth reading, and this project owes it. The reasons it did not become the foundation are specific and checkable:

tilt-dev/starlark-lsp starlsp
Parser binding smacker/go-tree-sitter — cgo, pinned to a 2022 commit gotreesitter — pure Go
Cross-compilation needs a C toolchain per target GOOS=… go build
Document sync full document per edit incremental
Builtin names Python stub files, maintained by hand introspected from starlark.Universe
Type methods stub files introspected from the runtime values
Dialect extension stub files a typed Host interface
Dialect rules fixed syntax.FileOptions per host
Last code commit July 2024 —

Capabilities, counted from what each advertises at initialize:

tilt-dev starlsp
Diagnostics · completion · hover · signature help · definition · document symbols ● ●
References · document highlight · rename (+prepare) · workspace symbols ○ ●
Folding · selection ranges · document links · semantic tokens ○ ●

Six become fourteen. The new ones hang off a reference index the resolver does not keep: go.starlark.net/resolve establishes which identifiers bind to which variable, then discards the back-references. Rebuilding that is what makes rename exact — a local x in one function is not the same variable as a local x in another, and matching by text merges them.

Two parsers, one opinion

gotreesitter answers structural questions on every keystroke. It tolerates a half-typed buffer, which is exactly when an editor is most useful — outline, folding, semantic tokens, and the caret context completion needs.

go.starlark.net answers every question about correctness, because it is the same parser and resolver a Starlark host runs. Diagnostics, binding, and scope come from there and nowhere else.

A language server that reimplements Starlark's scope rules eventually disagrees with the runtime, and the disagreement is always the server's fault. Here it cannot happen: the core never gets a vote on whether a file is correct, only on what shape it currently has.

Extending it for a dialect

Two methods are required. Everything else is an optional interface, found by type assertion, so a host implements only what it has.

type myDialect struct{}

func (myDialect) Name() string { return "mydialect" }

func (myDialect) Globals() []starlsp.Symbol {
	return []starlsp.Symbol{{
		Name:      "greet",
		Kind:      starlsp.KindFunction,
		Signature: "greet(name)",
		Returns:   "None",
		Doc:       "Print a greeting.",
	}}
}

func main() {
	srv, _ := starlsp.New(starlsp.Options{
		Host: starlsp.Hosts(starlsp.NewVanilla(), myDialect{}),
	})
	log.Fatal(srv.Run())
}

That alone gives greet completion, hover with its signature, signature help with its parameter, the right semantic-token colour, and — because the resolver is told the name exists — no false "undefined" diagnostic.

Optional interface Adds
MemberProvider completion after a dot
TypeResolver what p is, after p = fs.path(...)
LoadResolver go to definition across load()
Linter diagnostics belonging to the dialect
Documenter prose and signatures held elsewhere
DialectOptions syntax.FileOptions — top-level control flow, while, set

Hosts(a, b, …) composes them; later hosts win a name collision.

Real example: Starkite implements six of these in ~1,200 lines and gets the whole server.

Prefer introspection over tables

The vanilla host reads its globals from starlark.Universe and its methods from calling AttrNames on a zero String, List, Dict, Set, and Bytes. A go.starlark.net release that adds a method gains completion for it with no change here. Starkite reads its surface from a live module registry the same way.

The Bazel and Tilt hosts cannot do this — neither is a Go library — so they carry curated tables, and say so. A table tracking a moving API rots; that is a cost those two dialects pay and the others do not.

Checking a build

$ starlsp --dialect bazel --probe
starlsp 0.3.0

host           starlark+bazel
parser         starlark (gotreesitter, pure Go)
globals        125
hooks          members, types

namespaces  12  apple_common attr cc_common config config_common coverage_common
                java_common json native platform_common proto testing
types       30  CcInfo DefaultInfo JavaInfo OutputGroupInfo ProtoInfo PyInfo …
functions   65  Label aspect bazel_dep depset exec_group glob module provider
                rule select struct transition …

members
  attr             13
  native            9
  string           35

Editors

Neovim
vim.filetype.add({
  extension = { star = "starlark", bzl = "starlark" },
  filename = { BUILD = "starlark", ["BUILD.bazel"] = "starlark", Tiltfile = "starlark" },
})

vim.lsp.config.starlsp = {
  cmd = { "starlsp" },
  filetypes = { "starlark" },
  root_markers = { "WORKSPACE", "MODULE.bazel", "Tiltfile", ".git" },
}
vim.lsp.enable("starlsp")
Helix
[language-server.starlsp]
command = "starlsp"

[[language]]
name = "starlark"
scope = "source.star"
file-types = ["star", "bzl", "sky", { glob = "BUILD" }, { glob = "BUILD.bazel" }, { glob = "Tiltfile" }]
comment-token = "#"
indent = { tab-width = 4, unit = "    " }
language-servers = ["starlsp"]
Zed
{ "lsp": { "starlsp": { "binary": { "path": "starlsp" } } } }
VS Code

An extension lives in editors/vscode. Until it is on the Marketplace, build and install it:

cd editors/vscode
npm install && npm run package
code --install-extension starlsp-*.vsix

It contributes the starlark language for .star, .bzl, .sky, BUILD, BUILD.bazel, WORKSPACE, MODULE.bazel, and Tiltfile, and starts the server for them. Settings:

Setting Default
starlsp.serverPath starlsp path to the binary
starlsp.dialect auto starlark, bazel, tilt, or auto
starlsp.trace.server off log the traffic

STARLSP_PATH overrides serverPath, which is convenient when working on the server itself.

Smaller binaries

The parser library carries more than 200 grammars. Embed only the one this needs:

go build -tags 'grammar_subset,grammar_subset_starlark' ./cmd/starlsp

31.6 MB → 12.9 MB, no behaviour change. CI runs the test suite under both.

Status

v0.3.0. The Host interface is settled enough to build against; it may still change before 1.0. Dialect hosts for Buck, Isopod, Copybara, or anything else are very welcome — they are a table and two methods.

License

Apache 2.0.

Documentation

Overview

Package starlsp implements a Language Server Protocol server for Starlark.

The server splits work between two parsers, because they answer different questions. gotreesitter answers structural questions on every keystroke: it tolerates a half-typed buffer, which is exactly when an editor is most useful. go.starlark.net answers every question about correctness, because it is the same parser and resolver a Starlark host actually runs — so a diagnostic shown in an editor is one the host would report.

The core knows the Starlark specification and nothing else. A dialect — Bazel, Buck, Tilt, Starkite — supplies its builtins, its load() semantics, and its own lints through the Host interface. See host.go.

Everything here is pure Go. There is no cgo, and therefore no C toolchain and no cross-compilation cliff when embedding the server in another program.

This file carries the wire protocol: JSON-RPC 2.0 over Content-Length framed stdio, plus the LSP structures the server exchanges. The types are hand-written rather than taken from a protocol library, so embedding this server adds one dependency for parsing and none for the protocol.

Index

Constants

View Source
const Version = "0.3.0"

Version is reported to the client at initialize.

Variables

This section is empty.

Functions

func SpecFileOptions added in v0.2.0

func SpecFileOptions() *syntax.FileOptions

SpecFileOptions is the Starlark specification's own dialect: no top-level control flow, no while, no set, no global reassignment.

Types

type CompletionItem

type CompletionItem struct {
	Label         string             `json:"label"`
	Kind          CompletionItemKind `json:"kind,omitempty"`
	Detail        string             `json:"detail,omitempty"`
	Documentation *MarkupContent     `json:"documentation,omitempty"`
	InsertText    string             `json:"insertText,omitempty"`
	SortText      string             `json:"sortText,omitempty"`
}

type CompletionItemKind

type CompletionItemKind int

type Diagnostic

type Diagnostic struct {
	Range    Range              `json:"range"`
	Severity DiagnosticSeverity `json:"severity,omitempty"`
	Source   string             `json:"source,omitempty"`
	Message  string             `json:"message"`
}

type DiagnosticSeverity

type DiagnosticSeverity int
const (
	SeverityError       DiagnosticSeverity = 1
	SeverityWarning     DiagnosticSeverity = 2
	SeverityInformation DiagnosticSeverity = 3
	SeverityHint        DiagnosticSeverity = 4
)

Severities a host may set on a Diagnostic it returns.

type DialectOptions added in v0.2.0

type DialectOptions interface {
	FileOptions() *syntax.FileOptions
}

A DialectOptions host controls the language variant the parser and resolver enforce.

Starlark is not one language here either. go.starlark.net gates several behaviours behind syntax.FileOptions, and real dialects differ on them: Tilt permits if and for at the top level, Bazel does not; some hosts enable the set builtin, most do not. Getting this wrong produces a syntax error on a file that its own runtime accepts, which is the worst failure a language server has.

A host that does not implement this gets the specification defaults.

type Document

type Document struct {
	// contains filtered or unexported fields
}

Document holds one open buffer, its line index, and its parse tree.

The tree is produced by gotreesitter and is always available, even when the buffer does not parse as valid Starlark. That is the whole reason the structural half of this server uses tree-sitter: a language server is most useful exactly when the buffer is half-typed.

func (*Document) OffsetOf added in v0.1.1

func (d *Document) OffsetOf(p Position) int

OffsetOf converts an LSP position into a byte offset.

func (*Document) Path added in v0.1.1

func (d *Document) Path() string

Path is the document's filesystem path, empty when the buffer is not on disk.

func (*Document) PositionOf added in v0.1.1

func (d *Document) PositionOf(offset int) Position

PositionOf converts a byte offset into an LSP position.

func (*Document) SpanRange added in v0.1.1

func (d *Document) SpanRange(n syntax.Node) Range

SpanRange converts a Starlark syntax node's span into an LSP range, so a host can report a diagnostic against a node it found in the AST.

func (*Document) Text added in v0.1.1

func (d *Document) Text() []byte

Text returns the buffer's current bytes. The slice must not be modified.

func (*Document) URI added in v0.1.1

func (d *Document) URI() string

URI is the document's client-supplied identifier.

func (*Document) Version added in v0.1.1

func (d *Document) Version() int

Version is the client's version counter for this buffer.

type DocumentHighlight

type DocumentHighlight struct {
	Range Range                 `json:"range"`
	Kind  DocumentHighlightKind `json:"kind,omitempty"`
}

type DocumentHighlightKind

type DocumentHighlightKind int

DocumentHighlightKind distinguishes a read from a write at a location.

type DocumentLink struct {
	Range   Range  `json:"range"`
	Target  string `json:"target,omitempty"`
	Tooltip string `json:"tooltip,omitempty"`
}

type DocumentSymbol

type DocumentSymbol struct {
	Name           string           `json:"name"`
	Detail         string           `json:"detail,omitempty"`
	Kind           SymbolKind       `json:"kind"`
	Range          Range            `json:"range"`
	SelectionRange Range            `json:"selectionRange"`
	Children       []DocumentSymbol `json:"children,omitempty"`
}

type Documenter

type Documenter interface {
	Document(owner, name string) (Symbol, bool)
}

A Documenter supplies prose and signatures the server cannot introspect.

A Starlark builtin carries neither its parameter names nor its description, so a host that has documentation elsewhere — reference files, stub files, Go doc comments — surfaces it here. Symbols returned from Globals and Members may carry their own documentation instead; this hook exists for hosts whose documentation is not attached to the values.

type FoldingRange

type FoldingRange struct {
	StartLine int    `json:"startLine"`
	EndLine   int    `json:"endLine"`
	Kind      string `json:"kind,omitempty"`
}

type Host

type Host interface {
	// Name identifies the dialect in server logs and in the initialize
	// response, for example "bazel" or "starkite".
	Name() string

	// Globals returns the names the host predeclares, beyond the universe the
	// Starlark specification defines. The server treats these as defined, so
	// they are also what stops the resolver reporting them as undefined names.
	Globals() []Symbol
}

A Host teaches the server about one Starlark dialect.

Starlark has no single dialect. Bazel, Buck, Tilt, and Starkite each add their own builtins, their own meaning for load(), and their own rules about what a well-formed file looks like. The core of this server knows the language specification and nothing else; a Host supplies the rest.

Only Name and Globals are required. Everything else is an optional interface, checked with a type assertion, so a host that merely adds a few builtins implements two methods rather than six.

The vanilla host in this package implements Host alone, and is what the standalone binary uses when no dialect is configured.

func Hosts

func Hosts(hosts ...Host) Host

Hosts composes several hosts into one.

Names from later hosts take precedence on collision, which lets a dialect layer over a base without either knowing about the other. Optional interfaces are honoured for every member: a composite answers a member query from the first host that has an answer.

type Kind

type Kind int

Kind classifies a name for the editor.

const (
	KindUnknown Kind = iota
	KindFunction
	KindMethod
	KindNamespace // a module or package: fs, http
	KindType      // a constructible type: Path, Response
	KindProperty  // an attribute read without a call
	KindVariable
	KindConstant
	KindKeyword
	KindParameter
)

The kinds a host can produce. They map onto LSP completion item kinds and onto semantic token types.

type Linter

type Linter interface {
	Lint(doc *Document, file *syntax.File) []Diagnostic
}

A Linter reports diagnostics that belong to the dialect rather than to the language, such as an entry-point convention or a permission rule.

The server calls it after its own analysis. File is nil when the buffer does not parse, so a linter that needs an AST must check for that and return nothing rather than guess at a broken buffer.

type LoadRequest

type LoadRequest struct {
	// Target is the literal text inside the load() call, without quotes.
	Target string

	// From is the filesystem path of the file containing the load(), or empty
	// when the buffer is not on disk.
	From string
}

LoadRequest describes one load() target to resolve.

type LoadResolver

type LoadResolver interface {
	ResolveLoad(req LoadRequest) (path string, ok bool)
}

A LoadResolver maps a load() target to a file.

This is the most dialect-specific hook in the interface. Bazel takes a label, Tilt takes a path, and Starkite takes either a path or a "namespace/name" identity pinned by a lockfile. The core never guesses; without this hook a load() target is highlighted but not navigable.

type Location

type Location struct {
	URI   string `json:"uri"`
	Range Range  `json:"range"`
}

type MarkupContent

type MarkupContent struct {
	Kind  string `json:"kind"`  // "markdown" or "plaintext"
	Value string `json:"value"` //
}

type MemberProvider

type MemberProvider interface {
	Members(owner string) []Symbol
}

A MemberProvider supplies the names reachable through a dot.

owner is either a namespace the host predeclared — "fs" — or a type name that a TypeResolver produced — "fs.path". A host that has no member structure does not implement this, and the server offers nothing after a dot rather than guessing.

type Options

type Options struct {
	// Host supplies the dialect. Defaults to NewVanilla, which is Starlark as
	// the specification defines it.
	Host Host

	// In and Out are the client transport. Both default to stdio.
	In  io.Reader
	Out io.Writer

	// Log receives server-side messages. It must never be Out, because
	// anything written there corrupts the protocol stream.
	Log io.Writer
}

Options configures a server.

type ParameterInformation

type ParameterInformation struct {
	Label string `json:"label"`
}

type Position

type Position struct {
	Line      int `json:"line"`
	Character int `json:"character"`
}

Position is a zero-based line and UTF-16 code-unit offset. The UTF-16 column is the protocol default and is what editors send.

type Range

type Range struct {
	Start Position `json:"start"`
	End   Position `json:"end"`
}

Range is a half-open span between two positions.

type SelectionRange

type SelectionRange struct {
	Range  Range           `json:"range"`
	Parent *SelectionRange `json:"parent,omitempty"`
}

SelectionRange is one step of expand-selection, linked to its parent.

type Server

type Server struct {
	// contains filtered or unexported fields
}

Server is a Starlark language server.

It is usable two ways. Run drives it over a transport, which is what the standalone binary does. A host application can also embed it and supply its own Host, which is the reason the type and its Options are exported.

func New

func New(opts Options) (*Server, error)

New builds a server. It touches no transport until Run is called.

func (*Server) Diagnose added in v0.2.0

func (s *Server) Diagnose(uri, text string) []Diagnostic

Diagnose analyses one document and returns its diagnostics, with no client and no transport.

It is the whole server minus the protocol: the same parse, the same resolver, the same host lints an editor would see. That makes it usable as a linter — in CI, in a pre-commit hook, or in a program that embeds this package — without pretending to be an editor.

uri may be a file:// URI or a plain path. It is used for error messages and for any host hook that resolves relative to the file.

func (*Server) DiagnoseFile added in v0.2.0

func (s *Server) DiagnoseFile(path string) ([]Diagnostic, error)

DiagnoseFile reads a file from disk and analyses it.

func (*Server) Probe

func (s *Server) Probe() string

Probe renders what this server would offer, without a client.

It exists so a host's surface can be inspected directly. Anyone debugging a missing completion can see exactly which names and owners the configured host exposes, rather than inferring it from an editor.

func (*Server) Run

func (s *Server) Run() error

Run serves the client until the stream closes or the client exits.

Notifications that mutate a document are handled inline, in arrival order, because their order is their meaning: a didChange that overtook its didOpen would corrupt the buffer. Everything else is read-only and runs concurrently.

type SignatureInformation

type SignatureInformation struct {
	Label         string                 `json:"label"`
	Documentation *MarkupContent         `json:"documentation,omitempty"`
	Parameters    []ParameterInformation `json:"parameters,omitempty"`
}

type Symbol

type Symbol struct {
	// Name is the identifier as written in source: "read_text".
	Name string

	// Owner is the namespace or type that holds it, empty for a global.
	Owner string

	// Kind classifies it for completion and highlighting.
	Kind Kind

	// Signature is the full call form when known: "fs.path(p)". The server
	// parses parameters out of it for signature help, so the parentheses
	// matter.
	Signature string

	// Returns is the result type, shown beside the name in completion.
	Returns string

	// Doc is markdown prose shown on hover.
	Doc string

	// Deprecated marks a name the editor should strike through.
	Deprecated bool

	// SortText overrides completion ordering. Leave empty for the default,
	// which sorts host globals after file-local names.
	SortText string

	// Detail overrides the right-hand text in the completion list. Leave empty
	// to let the server compose it from Signature and Returns.
	Detail string
}

A Symbol is one completable, hoverable name.

A host builds these from whatever it actually knows. Only Name is required; everything else improves what the editor shows and none of it is guessed by the server.

func (Symbol) Params

func (s Symbol) Params() []string

Params splits the parameter list out of Signature. It returns nil when the symbol has no signature or is not a call.

func (Symbol) Qualified

func (s Symbol) Qualified() string

Qualified renders the dotted path of a symbol.

type SymbolInformation

type SymbolInformation struct {
	Name          string     `json:"name"`
	Kind          SymbolKind `json:"kind"`
	Location      Location   `json:"location"`
	ContainerName string     `json:"containerName,omitempty"`
}

SymbolInformation is the flat symbol shape workspace/symbol returns.

type SymbolKind

type SymbolKind int

type TextDocumentIdentifier

type TextDocumentIdentifier struct {
	URI string `json:"uri"`
}

type TextDocumentItem

type TextDocumentItem struct {
	URI        string `json:"uri"`
	LanguageID string `json:"languageId"`
	Version    int    `json:"version"`
	Text       string `json:"text"`
}

type TextEdit

type TextEdit struct {
	Range   Range  `json:"range"`
	NewText string `json:"newText"`
}

TextEdit is one replacement within a document.

type TypeRequest

type TypeRequest struct {
	// Expr is the receiver expression, for example "fs.path(\"/etc/hosts\")".
	Expr string

	// Document is the buffer the expression appears in, so a host can consult
	// the file's own bindings.
	Document *Document

	// Resolve re-enters the server's inference for a sub-expression. A host
	// uses it to walk a chain without reimplementing the walk.
	Resolve func(expr string) (owner string, ok bool)
}

TypeRequest describes one type-inference question.

type TypeResolver

type TypeResolver interface {
	ResolveType(req TypeRequest) (owner string, ok bool)
}

A TypeResolver maps an expression to the owner whose members it exposes.

The server calls it with the receiver text left of the caret's dot, already trimmed: "fs", "fs.path(\"/etc\")", or a bare identifier the server has resolved to its binding expression. Returning false means the server offers no completion, which is deliberately better than offering the wrong list.

type Vanilla

type Vanilla struct {
	// contains filtered or unexported fields
}

Vanilla is the Host for Starlark as the specification defines it, with no dialect extensions.

Its name set is introspected rather than written down. The globals come from starlark.Universe, and the methods on strings, lists, dicts, sets, and bytes come from calling AttrNames on a zero value of each type. A build of go.starlark.net that adds a method therefore gains completion for it with no change here.

The documentation below is written by hand, because a Starlark builtin carries neither its parameter names nor its description. That is acceptable for exactly one reason: the Starlark specification is frozen. A hand-written table tracking a moving API rots; a hand-written table tracking a specification does not.

func NewVanilla

func NewVanilla() *Vanilla

NewVanilla returns the specification-only host.

func (*Vanilla) Globals

func (v *Vanilla) Globals() []Symbol

func (*Vanilla) Members

func (v *Vanilla) Members(owner string) []Symbol

func (*Vanilla) Name

func (v *Vanilla) Name() string

func (*Vanilla) ResolveType

func (v *Vanilla) ResolveType(req TypeRequest) (string, bool)

ResolveType infers the type of a literal receiver, so that completion works after a string, list, dict, or set written inline.

type VersionedTextDocumentIdentifier

type VersionedTextDocumentIdentifier struct {
	URI     string `json:"uri"`
	Version int    `json:"version"`
}

type WorkspaceEdit

type WorkspaceEdit struct {
	Changes map[string][]TextEdit `json:"changes"`
}

WorkspaceEdit carries a rename's replacements, keyed by document URI.

Directories

Path Synopsis
cmd
starlsp command
Command starlsp is a language server for Starlark.
Command starlsp is a language server for Starlark.
dialects
bazel
Package bazel is the Bazel dialect of Starlark, for BUILD, BUILD.bazel, WORKSPACE, MODULE.bazel, and .bzl files.
Package bazel is the Bazel dialect of Starlark, for BUILD, BUILD.bazel, WORKSPACE, MODULE.bazel, and .bzl files.
tilt
Package tilt is the Tilt dialect of Starlark, for Tiltfiles.
Package tilt is the Tilt dialect of Starlark, for Tiltfiles.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL