145 lines
2.5 KiB
Go
145 lines
2.5 KiB
Go
|
package parser
|
||
|
|
||
|
import (
|
||
|
"archive/zip"
|
||
|
"bufio"
|
||
|
"encoding/json"
|
||
|
"io"
|
||
|
"strings"
|
||
|
)
|
||
|
|
||
|
const maxScanTokenSize = 1024 * 1024
|
||
|
|
||
|
type Line struct {
|
||
|
Type string `json:"label"`
|
||
|
}
|
||
|
|
||
|
type Docs struct {
|
||
|
Root string
|
||
|
Entries map[Id]string
|
||
|
DocRanges map[Id][]Id
|
||
|
Ranges *Ranges
|
||
|
}
|
||
|
|
||
|
type Document struct {
|
||
|
Id Id `json:"id"`
|
||
|
Uri string `json:"uri"`
|
||
|
}
|
||
|
|
||
|
type DocumentRange struct {
|
||
|
OutV Id `json:"outV"`
|
||
|
RangeIds []Id `json:"inVs"`
|
||
|
}
|
||
|
|
||
|
type Metadata struct {
|
||
|
Root string `json:"projectRoot"`
|
||
|
}
|
||
|
|
||
|
func NewDocs(config Config) (*Docs, error) {
|
||
|
ranges, err := NewRanges(config)
|
||
|
if err != nil {
|
||
|
return nil, err
|
||
|
}
|
||
|
|
||
|
return &Docs{
|
||
|
Root: "file:///",
|
||
|
Entries: make(map[Id]string),
|
||
|
DocRanges: make(map[Id][]Id),
|
||
|
Ranges: ranges,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (d *Docs) Parse(r io.Reader) error {
|
||
|
scanner := bufio.NewScanner(r)
|
||
|
buf := make([]byte, 0, bufio.MaxScanTokenSize)
|
||
|
scanner.Buffer(buf, maxScanTokenSize)
|
||
|
|
||
|
for scanner.Scan() {
|
||
|
if err := d.process(scanner.Bytes()); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return scanner.Err()
|
||
|
}
|
||
|
|
||
|
func (d *Docs) process(line []byte) error {
|
||
|
l := Line{}
|
||
|
if err := json.Unmarshal(line, &l); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
switch l.Type {
|
||
|
case "metaData":
|
||
|
if err := d.addMetadata(line); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
case "document":
|
||
|
if err := d.addDocument(line); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
case "contains":
|
||
|
if err := d.addDocRanges(line); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
default:
|
||
|
return d.Ranges.Read(l.Type, line)
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (d *Docs) Close() error {
|
||
|
return d.Ranges.Close()
|
||
|
}
|
||
|
|
||
|
func (d *Docs) SerializeEntries(w *zip.Writer) error {
|
||
|
for id, path := range d.Entries {
|
||
|
filePath := Lsif + "/" + path + ".json"
|
||
|
|
||
|
f, err := w.Create(filePath)
|
||
|
if err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
if err := d.Ranges.Serialize(f, d.DocRanges[id], d.Entries); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (d *Docs) addMetadata(line []byte) error {
|
||
|
var metadata Metadata
|
||
|
if err := json.Unmarshal(line, &metadata); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
d.Root = strings.TrimSpace(metadata.Root) + "/"
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (d *Docs) addDocument(line []byte) error {
|
||
|
var doc Document
|
||
|
if err := json.Unmarshal(line, &doc); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
d.Entries[doc.Id] = strings.TrimPrefix(doc.Uri, d.Root)
|
||
|
|
||
|
return nil
|
||
|
}
|
||
|
|
||
|
func (d *Docs) addDocRanges(line []byte) error {
|
||
|
var docRange DocumentRange
|
||
|
if err := json.Unmarshal(line, &docRange); err != nil {
|
||
|
return err
|
||
|
}
|
||
|
|
||
|
d.DocRanges[docRange.OutV] = append(d.DocRanges[docRange.OutV], docRange.RangeIds...)
|
||
|
|
||
|
return nil
|
||
|
}
|