113 lines
2.3 KiB
Go
113 lines
2.3 KiB
Go
package parser
|
|
|
|
import (
|
|
"strconv"
|
|
)
|
|
|
|
type ReferencesOffset struct {
|
|
Id Id
|
|
Len int32
|
|
}
|
|
|
|
type References struct {
|
|
Items *cache
|
|
Offsets *cache
|
|
CurrentOffsetId Id
|
|
}
|
|
|
|
type SerializedReference struct {
|
|
Path string `json:"path"`
|
|
}
|
|
|
|
func NewReferences(config Config) (*References, error) {
|
|
tempPath := config.TempPath
|
|
|
|
items, err := newCache(tempPath, "references", Item{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
offsets, err := newCache(tempPath, "references-offsets", ReferencesOffset{})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &References{
|
|
Items: items,
|
|
Offsets: offsets,
|
|
CurrentOffsetId: 0,
|
|
}, nil
|
|
}
|
|
|
|
// Store is responsible for keeping track of references that will be used when
|
|
// serializing in `For`.
|
|
//
|
|
// The references are stored in a file to cache them. It is like
|
|
// `map[Id][]Item` (where `Id` is `refId`) but relies on caching the array and
|
|
// its offset in files for storage to reduce RAM usage. The items can be
|
|
// fetched by calling `getItems`.
|
|
func (r *References) Store(refId Id, references []Item) error {
|
|
size := len(references)
|
|
|
|
if size == 0 {
|
|
return nil
|
|
}
|
|
|
|
items := append(r.getItems(refId), references...)
|
|
err := r.Items.SetEntry(r.CurrentOffsetId, items)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
size = len(items)
|
|
r.Offsets.SetEntry(refId, ReferencesOffset{Id: r.CurrentOffsetId, Len: int32(size)})
|
|
r.CurrentOffsetId += Id(size)
|
|
|
|
return nil
|
|
}
|
|
|
|
func (r *References) For(docs map[Id]string, refId Id) []SerializedReference {
|
|
references := r.getItems(refId)
|
|
if references == nil {
|
|
return nil
|
|
}
|
|
|
|
var serializedReferences []SerializedReference
|
|
|
|
for _, reference := range references {
|
|
serializedReference := SerializedReference{
|
|
Path: docs[reference.DocId] + "#L" + strconv.Itoa(int(reference.Line)),
|
|
}
|
|
|
|
serializedReferences = append(serializedReferences, serializedReference)
|
|
}
|
|
|
|
return serializedReferences
|
|
}
|
|
|
|
func (r *References) Close() error {
|
|
for _, err := range []error{
|
|
r.Items.Close(),
|
|
r.Offsets.Close(),
|
|
} {
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (r *References) getItems(refId Id) []Item {
|
|
var offset ReferencesOffset
|
|
if err := r.Offsets.Entry(refId, &offset); err != nil || offset.Len == 0 {
|
|
return nil
|
|
}
|
|
|
|
items := make([]Item, offset.Len)
|
|
if err := r.Items.Entry(offset.Id, &items); err != nil {
|
|
return nil
|
|
}
|
|
|
|
return items
|
|
}
|