index

package
v0.36.3 Latest Latest
Warning

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

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

Documentation

Overview

Package index provides structures to index spec nodes and a source tree.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func MarkDiagnostics

func MarkDiagnostics(spans map[int][]theme.Span, marks []DiagMark) map[int][]theme.Span

MarkDiagnostics overlays diagnostic marks onto lexical spans.

It returns a new map and leaves the input untouched. The lexical spans are rebuilt only when the buffer changes, while the marks change on every rescan.

A diagnostic wins over the token it lands on. The scanner's opinion is why the pane is open, so it takes the run rather than tinting around it.

Nil spans stay nil: a file with no lexical runs is one we do not tokenize (not Go). Inventing runs for it would colour text that nobody classified.

Types

type DiagMark

type DiagMark struct {
	Line, Col int
	Kind      theme.SyntaxKind
}

DiagMark is one diagnostic located in the DISPLAYED text.

A 0-based line and a 1-based rune column, already translated out of the file coordinates the scanner reports in.

Kind is the severity class to paint.

type HighlightIndex

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

HighlightIndex maps each rendered line to the lexical runs on it.

It costs nothing to produce: the lexer already classifies every token while the pointer index is being built, and until now that classification was thrown away.

Re-parsing the same bytes with a separate highlighting library would be both a second pass and a dependency, for information already in hand.

Spans record only where a run STARTS.

The renderer takes each run to the next span's column, which is what lets it slice RAW text at known boundaries and apply styling last — the only ordering in which a truncated line cannot cut through an escape sequence.

func BuildGoHighlight

func BuildGoHighlight(src []byte) *HighlightIndex

BuildGoHighlight classifies Go source into the same per-line lexical runs the spec pane uses, so both panes share one renderer and one palette.

The classifier is the standard library's own scanner: it is the definition of how Go tokenizes, it costs no dependency, and it is deliberately error TOLERANT — a buffer the user is halfway through editing still yields a usable token stream instead of nothing.

Scan errors are therefore discarded rather than reported; a highlighter that gives up on a syntactically incomplete file is a highlighter that goes blank exactly when you are typing.

Comments get three classes rather than one, because in a spec generator a comment is not uniformly commentary:

  • a `swagger:` line is the annotation that declares the thing, and reads as a spec key — the input that produced the pane next to it;
  • a leading `<keyword>:` inside an annotated block is grammar, and reads as a keyword, so `// required: true` looks the way `"required": true` does on the spec side;
  • everything else is prose, and is dimmed.

func (*HighlightIndex) All

func (x *HighlightIndex) All() map[int][]theme.Span

All returns the whole per-line map, for a renderer that wants to install it once rather than query per line.

Nil for a nil index.

func (*HighlightIndex) Len

func (x *HighlightIndex) Len() int

Len reports how many lines carry spans (0 for a nil index).

func (*HighlightIndex) Spans

func (x *HighlightIndex) Spans(line int) []theme.Span

Spans returns the runs on a 0-based rendered line, ordered by column, or nil when the line has none.

type Indexes

type Indexes struct {
	Spec      *SpecIndex
	Refs      *RefIndex
	Highlight *HighlightIndex
}

Indexes are the per-render products of a single lexer walk over the rendered spec.

It tells where each node is, where each $ref points, and what every token is.

They are grouped because they share the walk — adding a fourth should not mean a fourth traversal of the same bytes.

func BuildJSONIndex

func BuildJSONIndex(b []byte) Indexes

BuildJSONIndex builds the per-render indexes from indented JSON bytes in ONE lexer pass.

The lexer reports, per token, its JSON pointer (RFC 6901 escaping handled for us) and its 1-based source line.

The first token to report a pointer is the line that member is declared on; later repeats (its value, its closing delimiter) are the same node seen again. Reads the bytes the pane renders, so the ordered keys of spec.Swagger's MarshalJSON are preserved.

func BuildYAMLIndex

func BuildYAMLIndex(b []byte) Indexes

BuildYAMLIndex is BuildJSONIndex over the YAML render.

The YAML lexer emits the same logical token stream with the same RFC 6901 pointer escaping, so the indexes built from either render are interchangeable — only the lines differ.

type RefIndex

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

RefIndex records every $ref in a rendered spec, keyed by what it points at.

This is the "find references" half: a decl is anchored to its own field, never to the type it references, so answering "where is this definition used?" means resolving $refs at RENDER time.

That makes the index per-render, exactly like SpecIndex — and it is built in the same lexer pass, so it costs no extra walk.

Scope, deliberately: this is a SITE index, not a JSON-Schema resolver. It records where each $ref token sits and what string it holds. It does not follow ref-to-ref chains, does not reason about $refs nested in allOf, and does not apply the "sibling keywords are ignored" rule — $ref quirks stay documented but are not chased here.

func (*RefIndex) Len

func (x *RefIndex) Len() int

Len reports how many $ref sites the index holds (0 for a nil index), including non-local ones.

func (*RefIndex) LocalRefLines

func (x *RefIndex) LocalRefLines() []int

LocalRefLines returns the 0-based rendered lines holding a FOLLOWABLE $ref, i.e. one pointing inside this document.

Backs the spec pane's gutter: an external ref is not marked, because Enter cannot take you there.

func (*RefIndex) RefAt

func (x *RefIndex) RefAt(line int) (RefSite, bool)

RefAt returns the $ref rendered on the given 0-based line, if any.

Backs go-to-definition: the user puts the cursor on a $ref and follows it.

func (*RefIndex) RefsNear

func (x *RefIndex) RefsNear(ptr string) (string, []RefSite)

RefsNear returns the sites referencing ptr — or, when nothing references ptr itself, the sites referencing its nearest referenced ANCESTOR, along with the pointer that actually matched.

The segment-trim walk mirrors SourceIndex.PositionFor, and for the same reason: the user's cursor is rarely on the definition line itself.

Asking for the references of `/definitions/User/properties/name` should find the uses of `User`, not report nothing.

func (*RefIndex) RefsToPointer

func (x *RefIndex) RefsToPointer(ptr string) []RefSite

RefsToPointer returns every site referencing the node at ptr, ordered by rendered line.

ptr is a plain JSON pointer as the SpecIndex reports it (e.g. "/definitions/User"). The leading "#" of the $ref is not included: generated specs only produce $ref's as fragments rooted in the same document.

type RefSite

type RefSite struct {
	Pointer string // the node HOLDING the $ref (the /$ref segment trimmed)
	Line    int    // 0-based rendered line of the $ref
	Target  RefTarget
}

RefSite is one place in the rendered spec where a $ref appears.

type RefTarget

type RefTarget struct {
	Raw     string // exactly as written in the document
	Pointer string // the RFC 6901 pointer for a local ref; "" otherwise
	Local   bool   // whether the ref points inside this document
}

RefTarget is a parsed $ref value.

Local refs point inside the document being rendered and can therefore be followed with the SpecIndex. Anything else (a sibling file, a URL, a bare filename) is recorded honestly but is not resolvable here. The TUI renders one spec, it is not a $ref resolver.

func ParseRefTarget

func ParseRefTarget(raw string) RefTarget

ParseRefTarget parses a raw $ref value.

A local ref is a bare fragment ("#/definitions/User"). The fragment is percent-DECODED, because go-openapi/spec marshals refs through net/url and will escape a definition name containing e.g. a space — while the SpecIndex keys on the document's own key text, which is not escaped. Decoding here is what makes the two sides comparable.

A malformed escape falls back to the verbatim fragment rather than dropping the ref.

type SourceIndex

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

SourceIndex is the caller-owned source-side half of the cross-ref linker. It maps RFC 6901 JSON pointers that codescan emits via OnProvenance to the Go source position that produced them, and back. codescan anchors only code-detail nodes, so this is NOT a bijection: a finer pointer resolves to its nearest anchored ancestor (PositionFor), and a source line resolves to its nearest enclosing anchor (PointerAt).

func BuildSourceIndex

func BuildSourceIndex(provs []scanner.Provenance) *SourceIndex

BuildSourceIndex builds the index from the provenance records collected during a scan (one OnProvenance call each).

Later records win on a duplicate pointer (upsert / last-wins), matching codescan's build, where a node may be rewritten.

func (*SourceIndex) AnchorLines

func (x *SourceIndex) AnchorLines(file string) map[int]bool

AnchorLines returns the 1-based source lines in file that carry an anchor, i.e. the lines that produced a spec node.

Backs the source viewer's gutter.

func (*SourceIndex) AnchoredPointers

func (x *SourceIndex) AnchoredPointers() []string

AnchoredPointers returns every pointer that has an anchor of its OWN (not one inherited from an ancestor).

Backs the spec pane's gutter: the caller maps each to its rendered line, marking the nodes whose source position is exact.

func (*SourceIndex) FirstAnchor

func (x *SourceIndex) FirstAnchor(file string) (string, bool)

FirstAnchor returns the pointer of the earliest (lowest-line) anchor recorded in file, or ok=false when the file produced no spec node.

Backs the tree's "locate this file in the spec" jump.

func (*SourceIndex) Len

func (x *SourceIndex) Len() int

Len reports how many anchored pointers the index holds (0 for a nil index).

func (*SourceIndex) PointerAt

func (x *SourceIndex) PointerAt(file string, line int) (string, bool)

PointerAt returns the pointer of the nearest anchor at or above (file, line).

The spec node enclosing that source line. line is 1-based (token.Position.Line). The bool is false when the file holds no anchors or line precedes the first.

func (*SourceIndex) PositionFor

func (x *SourceIndex) PositionFor(ptr string) (token.Position, bool)

PositionFor returns the source position anchored to ptr, or — when ptr itself is a finer node with no anchor of its own — the position of its nearest anchored ancestor.

The walk trims one pointer segment at a time (a zero-alloc suffix shrink), so /definitions/User/properties/x/items resolves to /definitions/User/properties/x, then /definitions/User, … until a hit.

type SpecIndex

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

SpecIndex maps between rendered-spec lines and the RFC 6901 JSON pointer of the spec node shown on each line.

It is the spec-side half of the cross-ref linker: line ↔ pointer, built fresh from the exact bytes the spec pane displays. Lines are 0-based (matching the viewport's strings.Split addressing); the same structure also anchors spec remarks.

func NewSpecIndex

func NewSpecIndex(line2ptr map[int]string, ptr2line map[string]int) *SpecIndex

NewSpecIndex finalizes the maps into a SpecIndex with sorted line keys.

func (*SpecIndex) Len

func (x *SpecIndex) Len() int

Len reports how many pointers the index holds (0 for a nil index).

func (*SpecIndex) LineForPointer

func (x *SpecIndex) LineForPointer(ptr string) (int, bool)

LineForPointer returns the 0-based line where pointer is rendered.

func (*SpecIndex) PointerAt

func (x *SpecIndex) PointerAt(line int) (string, bool)

PointerAt returns the JSON pointer of the node at line, or the nearest member line above it when line itself carries no pointer (e.g. a closing brace).

The bool is false only for an empty index or a line above the first member.

Jump to

Keyboard shortcuts

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