Skip to content
代码片段 群组 项目
references.go 2.3 KB
更新 更旧
Patrick Bajao's avatar
Patrick Bajao 已提交
package parser

import (
	"strconv"
)

Patrick Bajao's avatar
Patrick Bajao 已提交
type ReferencesOffset struct {
	Id  Id
	Len int32
}

Patrick Bajao's avatar
Patrick Bajao 已提交
type References struct {
	Items           *cache
	Offsets         *cache
	CurrentOffsetId Id
Patrick Bajao's avatar
Patrick Bajao 已提交
}

type SerializedReference struct {
	Path string `json:"path"`
}

Patrick Bajao's avatar
Patrick Bajao 已提交
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
	}

Patrick Bajao's avatar
Patrick Bajao 已提交
	return &References{
		Items:           items,
		Offsets:         offsets,
		CurrentOffsetId: 0,
Patrick Bajao's avatar
Patrick Bajao 已提交
	}, nil
Patrick Bajao's avatar
Patrick Bajao 已提交
// 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 {
Patrick Bajao's avatar
Patrick Bajao 已提交
		return nil
	}

	items := append(r.getItems(refId), references...)
	err := r.Items.SetEntry(r.CurrentOffsetId, items)
Patrick Bajao's avatar
Patrick Bajao 已提交
	if err != nil {
		return err
Patrick Bajao's avatar
Patrick Bajao 已提交
	}
Patrick Bajao's avatar
Patrick Bajao 已提交
	r.Offsets.SetEntry(refId, ReferencesOffset{Id: r.CurrentOffsetId, Len: int32(size)})
	r.CurrentOffsetId += Id(size)

	return nil
Patrick Bajao's avatar
Patrick Bajao 已提交
}

func (r *References) For(docs map[Id]string, refId Id) []SerializedReference {
Patrick Bajao's avatar
Patrick Bajao 已提交
	references := r.getItems(refId)
	if references == nil {
Patrick Bajao's avatar
Patrick Bajao 已提交
		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
}
Patrick Bajao's avatar
Patrick Bajao 已提交

func (r *References) Close() error {
	return combineErrors(
		r.Items.Close(),
		r.Offsets.Close(),
	)
}

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
}