func decorationToReference(norm *xrefs.Normalizer, d *srvpb.FileDecorations_Decoration) *xpb.DecorationsReply_Reference { return &xpb.DecorationsReply_Reference{ SourceTicket: d.Anchor.Ticket, TargetTicket: d.TargetTicket, Kind: d.Kind, AnchorStart: norm.ByteOffset(d.Anchor.StartOffset), AnchorEnd: norm.ByteOffset(d.Anchor.EndOffset), } }
func normalizeSpan(norm *xrefs.Normalizer, startOffset, endOffset int32) (start, end *xpb.Location_Point, err error) { start = norm.ByteOffset(startOffset) end = norm.ByteOffset(endOffset) if start.ByteOffset != startOffset { err = fmt.Errorf("inconsistent start location; expected: %d; found; %d", startOffset, start.ByteOffset) } else if end.ByteOffset != endOffset { err = fmt.Errorf("inconsistent end location; expected: %d; found; %d", endOffset, end.ByteOffset) } return }
func expandAnchor(anchor *srvpb.RawAnchor, file *srvpb.File, norm *xrefs.Normalizer, kind string) (*srvpb.ExpandedAnchor, error) { sp := norm.ByteOffset(anchor.StartOffset) ep := norm.ByteOffset(anchor.EndOffset) txt, err := getText(sp, ep, file) if err != nil { return nil, fmt.Errorf("error getting anchor text: %v", err) } ssp := norm.ByteOffset(anchor.SnippetStart) sep := norm.ByteOffset(anchor.SnippetEnd) snippet, err := getText(ssp, sep, file) if err != nil { return nil, fmt.Errorf("error getting text for snippet: %v", err) } // fallback to a line-based snippet if the indexer did not provide its own snippet offsets if snippet == "" { ssp = &xpb.Location_Point{ ByteOffset: sp.ByteOffset - sp.ColumnOffset, LineNumber: sp.LineNumber, } nextLine := norm.Point(&xpb.Location_Point{LineNumber: sp.LineNumber + 1}) sep = &xpb.Location_Point{ ByteOffset: nextLine.ByteOffset - 1, LineNumber: sp.LineNumber, ColumnOffset: sp.ColumnOffset + (nextLine.ByteOffset - sp.ByteOffset - 1), } snippet, err = getText(ssp, sep, file) if err != nil { return nil, fmt.Errorf("error getting text for line snippet: %v", err) } } return &srvpb.ExpandedAnchor{ Ticket: anchor.Ticket, Kind: kind, Parent: file.Ticket, Text: txt, Span: &cpb.Span{ Start: p2p(sp), End: p2p(ep), }, Snippet: snippet, SnippetSpan: &cpb.Span{ Start: p2p(ssp), End: p2p(sep), }, }, nil }
// ExpandAnchor returns the ExpandedAnchor equivalent of the given RawAnchor // where file (and its associated Normalizer) must be the anchor's parent file. func ExpandAnchor(anchor *srvpb.RawAnchor, file *srvpb.File, norm *xrefs.Normalizer, kind string) (*srvpb.ExpandedAnchor, error) { if err := checkSpan(len(file.Text), anchor.StartOffset, anchor.EndOffset); err != nil { return nil, fmt.Errorf("invalid text offsets: %v", err) } sp := norm.ByteOffset(anchor.StartOffset) ep := norm.ByteOffset(anchor.EndOffset) txt, err := getText(sp, ep, file) if err != nil { return nil, fmt.Errorf("error getting anchor text: %v", err) } var snippet string var ssp, sep *xpb.Location_Point if anchor.SnippetStart != 0 || anchor.SnippetEnd != 0 { if err := checkSpan(len(file.Text), anchor.SnippetStart, anchor.SnippetEnd); err != nil { return nil, fmt.Errorf("invalid snippet offsets: %v", err) } ssp = norm.ByteOffset(anchor.SnippetStart) sep = norm.ByteOffset(anchor.SnippetEnd) snippet, err = getText(ssp, sep, file) if err != nil { return nil, fmt.Errorf("error getting text for snippet: %v", err) } } else { // fallback to a line-based snippet if the indexer did not provide its own snippet offsets ssp = &xpb.Location_Point{ ByteOffset: sp.ByteOffset - sp.ColumnOffset, LineNumber: sp.LineNumber, } nextLine := norm.Point(&xpb.Location_Point{LineNumber: sp.LineNumber + 1}) if nextLine.ByteOffset <= ssp.ByteOffset { // double-check ssp != EOF return nil, errors.New("anchor past EOF") } sep = &xpb.Location_Point{ ByteOffset: nextLine.ByteOffset - 1, LineNumber: sp.LineNumber, ColumnOffset: sp.ColumnOffset + (nextLine.ByteOffset - sp.ByteOffset - 1), } snippet, err = getText(ssp, sep, file) if err != nil { return nil, fmt.Errorf("error getting text for line snippet: %v", err) } } return &srvpb.ExpandedAnchor{ Ticket: anchor.Ticket, Kind: kind, Parent: file.Ticket, Text: txt, Span: &cpb.Span{ Start: p2p(sp), End: p2p(ep), }, Snippet: snippet, SnippetSpan: &cpb.Span{ Start: p2p(ssp), End: p2p(sep), }, }, nil }