1package parser 2 3import ( 4 "encoding/json" 5 "io/ioutil" 6 "os" 7) 8 9type Offset struct { 10 At int32 11 Len int32 12} 13 14type Hovers struct { 15 File *os.File 16 Offsets *cache 17 CurrentOffset int 18} 19 20type RawResult struct { 21 Contents json.RawMessage `json:"contents"` 22} 23 24type RawData struct { 25 Id Id `json:"id"` 26 Result RawResult `json:"result"` 27} 28 29type HoverRef struct { 30 ResultSetId Id `json:"outV"` 31 HoverId Id `json:"inV"` 32} 33 34type ResultSetRef struct { 35 ResultSetId Id `json:"outV"` 36 RefId Id `json:"inV"` 37} 38 39func NewHovers(config Config) (*Hovers, error) { 40 tempPath := config.TempPath 41 42 file, err := ioutil.TempFile(tempPath, "hovers") 43 if err != nil { 44 return nil, err 45 } 46 47 if err := os.Remove(file.Name()); err != nil { 48 return nil, err 49 } 50 51 offsets, err := newCache(tempPath, "hovers-indexes", Offset{}) 52 if err != nil { 53 return nil, err 54 } 55 56 return &Hovers{ 57 File: file, 58 Offsets: offsets, 59 CurrentOffset: 0, 60 }, nil 61} 62 63func (h *Hovers) Read(label string, line []byte) error { 64 switch label { 65 case "hoverResult": 66 if err := h.addData(line); err != nil { 67 return err 68 } 69 case "textDocument/hover": 70 if err := h.addHoverRef(line); err != nil { 71 return err 72 } 73 case "textDocument/references": 74 if err := h.addResultSetRef(line); err != nil { 75 return err 76 } 77 } 78 79 return nil 80} 81 82func (h *Hovers) For(refId Id) json.RawMessage { 83 var offset Offset 84 if err := h.Offsets.Entry(refId, &offset); err != nil || offset.Len == 0 { 85 return nil 86 } 87 88 hover := make([]byte, offset.Len) 89 _, err := h.File.ReadAt(hover, int64(offset.At)) 90 if err != nil { 91 return nil 92 } 93 94 return json.RawMessage(hover) 95} 96 97func (h *Hovers) Close() error { 98 return combineErrors( 99 h.File.Close(), 100 h.Offsets.Close(), 101 ) 102} 103 104func (h *Hovers) addData(line []byte) error { 105 var rawData RawData 106 if err := json.Unmarshal(line, &rawData); err != nil { 107 return err 108 } 109 110 codeHovers, err := newCodeHovers(rawData.Result.Contents) 111 if err != nil { 112 return err 113 } 114 115 codeHoversData, err := json.Marshal(codeHovers) 116 if err != nil { 117 return err 118 } 119 120 n, err := h.File.Write(codeHoversData) 121 if err != nil { 122 return err 123 } 124 125 offset := Offset{At: int32(h.CurrentOffset), Len: int32(n)} 126 h.CurrentOffset += n 127 128 return h.Offsets.SetEntry(rawData.Id, &offset) 129} 130 131func (h *Hovers) addHoverRef(line []byte) error { 132 var hoverRef HoverRef 133 if err := json.Unmarshal(line, &hoverRef); err != nil { 134 return err 135 } 136 137 var offset Offset 138 if err := h.Offsets.Entry(hoverRef.HoverId, &offset); err != nil { 139 return err 140 } 141 142 return h.Offsets.SetEntry(hoverRef.ResultSetId, &offset) 143} 144 145func (h *Hovers) addResultSetRef(line []byte) error { 146 var ref ResultSetRef 147 if err := json.Unmarshal(line, &ref); err != nil { 148 return err 149 } 150 151 var offset Offset 152 if err := h.Offsets.Entry(ref.ResultSetId, &offset); err != nil { 153 return nil 154 } 155 156 return h.Offsets.SetEntry(ref.RefId, &offset) 157} 158