Commit da0ba499 authored by Nick Thomas's avatar Nick Thomas

Fix some missing Close() calls and unnecessary allocations

parent d1601586
...@@ -2,7 +2,9 @@ package parser ...@@ -2,7 +2,9 @@ package parser
import ( import (
"archive/zip" "archive/zip"
"bufio"
"encoding/json" "encoding/json"
"io"
"strings" "strings"
) )
...@@ -45,7 +47,19 @@ func NewDocs(config Config) (*Docs, error) { ...@@ -45,7 +47,19 @@ func NewDocs(config Config) (*Docs, error) {
}, nil }, nil
} }
func (d *Docs) Read(line []byte) error { func (d *Docs) Parse(r io.Reader) error {
scanner := bufio.NewScanner(r)
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{} l := Line{}
if err := json.Unmarshal(line, &l); err != nil { if err := json.Unmarshal(line, &l); err != nil {
return err return err
......
package parser package parser
import ( import (
"bytes"
"fmt" "fmt"
"testing" "testing"
...@@ -8,34 +9,34 @@ import ( ...@@ -8,34 +9,34 @@ import (
) )
func createLine(id, label, uri string) []byte { func createLine(id, label, uri string) []byte {
return []byte(fmt.Sprintf(`{"id":"%s","label":"%s","uri":"%s"}`, id, label, uri)) return []byte(fmt.Sprintf(`{"id":"%s","label":"%s","uri":"%s"}`+"\n", id, label, uri))
} }
func TestRead(t *testing.T) { func TestParse(t *testing.T) {
d, err := NewDocs(Config{}) d, err := NewDocs(Config{})
require.NoError(t, err) require.NoError(t, err)
defer d.Close() defer d.Close()
metadataLine := []byte(`{"id":"1","label":"metaData","projectRoot":"file:///Users/nested"}`) data := []byte(`{"id":"1","label":"metaData","projectRoot":"file:///Users/nested"}` + "\n")
data = append(data, createLine("2", "document", "file:///Users/nested/file.rb")...)
data = append(data, createLine("3", "document", "file:///Users/nested/folder/file.rb")...)
data = append(data, createLine("4", "document", "file:///Users/wrong/file.rb")...)
require.NoError(t, d.Read(metadataLine)) require.NoError(t, d.Parse(bytes.NewReader(data)))
require.NoError(t, d.Read(createLine("2", "document", "file:///Users/nested/file.rb")))
require.NoError(t, d.Read(createLine("3", "document", "file:///Users/nested/folder/file.rb")))
require.NoError(t, d.Read(createLine("4", "document", "file:///Users/wrong/file.rb")))
require.Equal(t, d.Entries[2], "file.rb") require.Equal(t, d.Entries[2], "file.rb")
require.Equal(t, d.Entries[3], "folder/file.rb") require.Equal(t, d.Entries[3], "folder/file.rb")
require.Equal(t, d.Entries[4], "file:///Users/wrong/file.rb") require.Equal(t, d.Entries[4], "file:///Users/wrong/file.rb")
} }
func TestReadContainsLine(t *testing.T) { func TestParseContainsLine(t *testing.T) {
d, err := NewDocs(Config{}) d, err := NewDocs(Config{})
require.NoError(t, err) require.NoError(t, err)
defer d.Close() defer d.Close()
line := []byte(`{"id":"5","label":"contains","outV":"1", "inVs": ["2", "3"]}`) line := []byte(`{"id":"5","label":"contains","outV":"1", "inVs": ["2", "3"]}` + "\n")
require.NoError(t, d.Read(line)) require.NoError(t, d.Parse(bytes.NewReader(line)))
require.Equal(t, []Id{2, 3}, d.DocRanges[1]) require.Equal(t, []Id{2, 3}, d.DocRanges[1])
} }
...@@ -2,7 +2,6 @@ package parser ...@@ -2,7 +2,6 @@ package parser
import ( import (
"archive/zip" "archive/zip"
"bufio"
"errors" "errors"
"fmt" "fmt"
"io" "io"
...@@ -30,21 +29,41 @@ func NewParser(r io.Reader, config Config) (io.ReadCloser, error) { ...@@ -30,21 +29,41 @@ func NewParser(r io.Reader, config Config) (io.ReadCloser, error) {
return nil, err return nil, err
} }
zr, err := openZipReader(r, config.TempPath) // ZIP files need to be seekable. Don't hold it all in RAM, use a tempfile
tempFile, err := ioutil.TempFile(config.TempPath, Lsif)
if err != nil { if err != nil {
return nil, err return nil, err
} }
reader := bufio.NewReader(zr)
for { defer tempFile.Close()
line, err := reader.ReadBytes('\n')
if err != nil {
break
}
if err := docs.Read(line); err != nil { if err := os.Remove(tempFile.Name()); err != nil {
return nil, err return nil, err
} }
size, err := io.Copy(tempFile, r)
if err != nil {
return nil, err
}
zr, err := zip.NewReader(tempFile, size)
if err != nil {
return nil, err
}
if len(zr.File) == 0 {
return nil, errors.New("empty zip file")
}
file, err := zr.File[0].Open()
if err != nil {
return nil, err
}
defer file.Close()
if err := docs.Parse(file); err != nil {
return nil, err
} }
pr, pw := io.Pipe() pr, pw := io.Pipe()
...@@ -53,7 +72,7 @@ func NewParser(r io.Reader, config Config) (io.ReadCloser, error) { ...@@ -53,7 +72,7 @@ func NewParser(r io.Reader, config Config) (io.ReadCloser, error) {
pr: pr, pr: pr,
} }
go parser.parse(pw) go parser.transform(pw)
return parser, nil return parser, nil
} }
...@@ -68,7 +87,7 @@ func (p *Parser) Close() error { ...@@ -68,7 +87,7 @@ func (p *Parser) Close() error {
return p.Docs.Close() return p.Docs.Close()
} }
func (p *Parser) parse(pw *io.PipeWriter) { func (p *Parser) transform(pw *io.PipeWriter) {
zw := zip.NewWriter(pw) zw := zip.NewWriter(pw)
if err := p.Docs.SerializeEntries(zw); err != nil { if err := p.Docs.SerializeEntries(zw); err != nil {
...@@ -84,34 +103,3 @@ func (p *Parser) parse(pw *io.PipeWriter) { ...@@ -84,34 +103,3 @@ func (p *Parser) parse(pw *io.PipeWriter) {
pw.Close() pw.Close()
} }
func openZipReader(reader io.Reader, tempDir string) (io.Reader, error) {
tempFile, err := ioutil.TempFile(tempDir, Lsif)
if err != nil {
return nil, err
}
if err := os.Remove(tempFile.Name()); err != nil {
return nil, err
}
size, err := io.Copy(tempFile, reader)
if err != nil {
return nil, err
}
if _, err := tempFile.Seek(0, io.SeekStart); err != nil {
return nil, err
}
zr, err := zip.NewReader(tempFile, size)
if err != nil {
return nil, err
}
if len(zr.File) == 0 {
return nil, errors.New("empty zip file")
}
return zr.File[0].Open()
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment