Skip to content

Commit f2a1456

Browse files
authored
Allow IndexVisitor to return errors (#315)
1 parent 1077d0d commit f2a1456

File tree

4 files changed

+50
-23
lines changed

4 files changed

+50
-23
lines changed

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ Rust SCIP bindings:
99
the latest release v3.7.2.
1010
(https://github.com/sourcegraph/scip/pull/313)
1111

12+
Go bindings:
13+
14+
- BREAKING CHANGE: IndexVisitor now accepts a context object and returns an error.
15+
When an error is returned, the visitor short-circuits.
16+
1217
## v0.5.2
1318

1419
SCIP schema:

bindings/go/scip/memtest/low_mem_test.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package memtest
22

33
import (
4+
"context"
45
"fmt"
56
"io"
67
"os"
@@ -52,12 +53,15 @@ func TestLowMemoryParsing(t *testing.T) {
5253
debug.SetMemoryLimit(textSize * maxDocsInMemory)
5354

5455
curDoc := &scip.Document{}
55-
indexVisitor := scip.IndexVisitor{VisitDocument: func(d *scip.Document) {
56-
curDoc = d
57-
}}
56+
indexVisitor := scip.IndexVisitor{
57+
VisitDocument: func(_ context.Context, d *scip.Document) error {
58+
curDoc = d
59+
return nil
60+
},
61+
}
5862

5963
// No OOM
60-
err = indexVisitor.ParseStreaming(tmpFile)
64+
err = indexVisitor.ParseStreaming(context.Background(), tmpFile)
6165
_ = curDoc
6266
require.NoError(t, err)
6367
}

bindings/go/scip/parse.go

+14-7
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package scip
22

33
import (
4+
"context"
45
"io"
56

67
"github.com/cockroachdb/errors"
@@ -13,9 +14,9 @@ import (
1314
// implementations, so adding new functions here for new fields in
1415
// the SCIP schema would break clients. Individual functions may be nil.
1516
type IndexVisitor struct {
16-
VisitMetadata func(*Metadata)
17-
VisitDocument func(*Document)
18-
VisitExternalSymbol func(*SymbolInformation)
17+
VisitMetadata func(ctx context.Context, m *Metadata) error
18+
VisitDocument func(ctx context.Context, d *Document) error
19+
VisitExternalSymbol func(ctx context.Context, si *SymbolInformation) error
1920
}
2021

2122
// See https://protobuf.dev/programming-guides/encoding/#varints
@@ -24,7 +25,7 @@ const maxVarintBytes = 10
2425
// ParseStreaming processes an index by incrementally reading input from the io.Reader.
2526
//
2627
// Parsing takes place at Document granularity for ease of use.
27-
func (pi *IndexVisitor) ParseStreaming(r io.Reader) error {
28+
func (pi *IndexVisitor) ParseStreaming(ctx context.Context, r io.Reader) error {
2829
// The tag is encoded as a varint with value: (field_number << 3) | wire_type
2930
// Varints < 128 fit in 1 byte, which means 4 bits are available for field
3031
// numbers. The Index type has less than 15 fields, so the tag will fit in 1 byte.
@@ -84,23 +85,29 @@ func (pi *IndexVisitor) ParseStreaming(r io.Reader) error {
8485
if err := proto.Unmarshal(dataBuf, &m); err != nil {
8586
return errors.Wrapf(err, "failed to read %s", indexFieldName(fieldNumber))
8687
}
87-
pi.VisitMetadata(&m)
88+
if err := pi.VisitMetadata(ctx, &m); err != nil {
89+
return err
90+
}
8891
}
8992
} else if fieldNumber == documentsFieldNumber {
9093
if pi.VisitDocument != nil {
9194
d := Document{}
9295
if err := proto.Unmarshal(dataBuf, &d); err != nil {
9396
return errors.Wrapf(err, "failed to read %s", indexFieldName(fieldNumber))
9497
}
95-
pi.VisitDocument(&d)
98+
if err := pi.VisitDocument(ctx, &d); err != nil {
99+
return err
100+
}
96101
}
97102
} else if fieldNumber == externalSymbolsFieldNumber {
98103
if pi.VisitExternalSymbol != nil {
99104
s := SymbolInformation{}
100105
if err := proto.Unmarshal(dataBuf, &s); err != nil {
101106
return errors.Wrapf(err, "failed to read %s", indexFieldName(fieldNumber))
102107
}
103-
pi.VisitExternalSymbol(&s)
108+
if err := pi.VisitExternalSymbol(ctx, &s); err != nil {
109+
return err
110+
}
104111
}
105112
} else {
106113
return errors.Newf(

bindings/go/scip/parse_test.go

+23-12
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package scip
33
import (
44
"bytes"
55
"compress/gzip"
6+
"context"
67
"io"
78
"os"
89
"regexp"
@@ -60,15 +61,18 @@ func TestDocumentsOnly(t *testing.T) {
6061

6162
parsedIndex := Index{}
6263

63-
indexVisitor := IndexVisitor{VisitDocument: func(document *Document) {
64-
parsedIndex.Documents = append(parsedIndex.Documents, document)
65-
}}
64+
indexVisitor := IndexVisitor{
65+
VisitDocument: func(_ context.Context, document *Document) error {
66+
parsedIndex.Documents = append(parsedIndex.Documents, document)
67+
return nil
68+
},
69+
}
6670

6771
indexBytes, err := proto.Marshal(&index)
6872
require.NoError(t, err)
6973
bytesReader := bytes.NewReader(indexBytes)
7074

71-
if err := indexVisitor.ParseStreaming(bytesReader); err != nil {
75+
if err := indexVisitor.ParseStreaming(context.Background(), bytesReader); err != nil {
7276
t.Fatalf("got error parsing index %v", err)
7377
}
7478

@@ -102,15 +106,22 @@ func checkRoundtrip(t *testing.T, index *Index) {
102106
func parseStreaming(t *testing.T, reader io.Reader) *Index {
103107
parsedIndex := Index{}
104108

105-
indexVisitor := IndexVisitor{func(metadata *Metadata) {
106-
parsedIndex.Metadata = metadata
107-
}, func(document *Document) {
108-
parsedIndex.Documents = append(parsedIndex.Documents, document)
109-
}, func(extSym *SymbolInformation) {
110-
parsedIndex.ExternalSymbols = append(parsedIndex.ExternalSymbols, extSym)
111-
}}
109+
indexVisitor := IndexVisitor{
110+
VisitMetadata: func(_ context.Context, metadata *Metadata) error {
111+
parsedIndex.Metadata = metadata
112+
return nil
113+
},
114+
VisitDocument: func(_ context.Context, document *Document) error {
115+
parsedIndex.Documents = append(parsedIndex.Documents, document)
116+
return nil
117+
},
118+
VisitExternalSymbol: func(_ context.Context, extSym *SymbolInformation) error {
119+
parsedIndex.ExternalSymbols = append(parsedIndex.ExternalSymbols, extSym)
120+
return nil
121+
},
122+
}
112123

113-
if err := indexVisitor.ParseStreaming(reader); err != nil {
124+
if err := indexVisitor.ParseStreaming(context.Background(), reader); err != nil {
114125
t.Fatalf("got error parsing index %v", err)
115126
}
116127
return &parsedIndex

0 commit comments

Comments
 (0)