163 lines
2.9 KiB
Go
163 lines
2.9 KiB
Go
|
package parser
|
||
|
|
||
|
import (
|
||
|
"encoding/json"
|
||
|
"io/ioutil"
|
||
|
"os"
|
||
|
)
|
||
|
|
||
|
type Offset struct {
|
||
|
At int32
|
||
|
Len int32
|
||
|
}
|
||
|
|
||
|
type Hovers struct {
|
||
|
File *os.File
|
||
|
Offsets *cache
|
||
|
CurrentOffset int
|
||
|
}
|
||
|
|
||
|
type RawResult struct {
|
||
|
Contents []json.RawMessage `json:"contents"`
|
||
|
}
|
||
|
|
||
|
type RawData struct {
|
||
|
Id Id `json:"id"`
|
||
|
Result RawResult `json:"result"`
|
||
|
}
|
||
|
|
||
|
type HoverRef struct {
|
||
|
ResultSetId Id `json:"outV"`
|
||
|
HoverId Id `json:"inV"`
|
||
|
}
|
||
|
|
||
|
type ResultSetRef struct {
|
||
|
ResultSetId Id `json:"outV"`
|
||
|
RefId Id `json:"inV"`
|
||
|
}
|
||
|
|
||
|
func NewHovers(config Config) (*Hovers, error) {
|
||
|
tempPath := config.TempPath
|
||
|
|
||
|
file, err := ioutil.TempFile(tempPath, "hovers")
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
if err := os.Remove(file.Name()); err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
offsets, err := newCache(tempPath, "hovers-indexes", Offset{})
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &Hovers{
|
||
|
File: file,
|
||
|
Offsets: offsets,
|
||
|
CurrentOffset: 0,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (h *Hovers) Read(label string, line []byte) error {
|
||
|
switch label {
|
||
|
case "hoverResult":
|
||
|
if err := h.addData(line); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
case "textDocument/hover":
|
||
|
if err := h.addHoverRef(line); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
case "textDocument/references":
|
||
|
if err := h.addResultSetRef(line); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (h *Hovers) For(refId Id) json.RawMessage {
|
||
|
var offset Offset
|
||
|
if err := h.Offsets.Entry(refId, &offset); err != nil || offset.Len == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
hover := make([]byte, offset.Len)
|
||
|
_, err := h.File.ReadAt(hover, int64(offset.At))
|
||
|
if err != nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return json.RawMessage(hover)
|
||
|
}
|
||
|
|
||
|
func (h *Hovers) Close() error {
|
||
|
return combineErrors(
|
||
|
h.File.Close(),
|
||
|
h.Offsets.Close(),
|
||
|
)
|
||
|
}
|
||
|
|
||
|
func (h *Hovers) addData(line []byte) error {
|
||
|
var rawData RawData
|
||
|
if err := json.Unmarshal(line, &rawData); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
codeHovers := []*codeHover{}
|
||
|
for _, rawContent := range rawData.Result.Contents {
|
||
|
c, err := newCodeHover(rawContent)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
codeHovers = append(codeHovers, c)
|
||
|
}
|
||
|
|
||
|
codeHoversData, err := json.Marshal(codeHovers)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
n, err := h.File.Write(codeHoversData)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
offset := Offset{At: int32(h.CurrentOffset), Len: int32(n)}
|
||
|
h.CurrentOffset += n
|
||
|
|
||
|
return h.Offsets.SetEntry(rawData.Id, &offset)
|
||
|
}
|
||
|
|
||
|
func (h *Hovers) addHoverRef(line []byte) error {
|
||
|
var hoverRef HoverRef
|
||
|
if err := json.Unmarshal(line, &hoverRef); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
var offset Offset
|
||
|
if err := h.Offsets.Entry(hoverRef.HoverId, &offset); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
return h.Offsets.SetEntry(hoverRef.ResultSetId, &offset)
|
||
|
}
|
||
|
|
||
|
func (h *Hovers) addResultSetRef(line []byte) error {
|
||
|
var ref ResultSetRef
|
||
|
if err := json.Unmarshal(line, &ref); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
var offset Offset
|
||
|
if err := h.Offsets.Entry(ref.ResultSetId, &offset); err != nil {
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
return h.Offsets.SetEntry(ref.RefId, &offset)
|
||
|
}
|