Skip to content

Commit 16c15d1

Browse files
haoqixumvdan
authored andcommitted
encoding/json: fix position for jsonl
When the json decoder decoded multiple json objects from a single file, each object will be parsed separately, resulting in incorrect file location. Maintain a token.File for the entire file and correct the position according to the offset of the object in the file. Fixes #2444 Change-Id: Ib9b8bbacc0ad6aefe4fcad5b0cfafa9cfe734493 Signed-off-by: haoqixu <[email protected]> Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/1196332 TryBot-Result: CUEcueckoo <[email protected]> Unity-Result: CUE porcuepine <[email protected]> Reviewed-by: Daniel Martí <[email protected]>
1 parent 0d69846 commit 16c15d1

File tree

2 files changed

+36
-9
lines changed

2 files changed

+36
-9
lines changed

cmd/cue/cmd/testdata/script/vet_path.txtar

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,10 @@ cmp stderr expect-stderr
33
-- expect-stderr --
44
deployment.Booster.name: invalid value "Booster" (out of bound !~"^[A-Z]"):
55
./services.cue:1:29
6-
./services.jsonl:3:13
6+
./services.jsonl:7:13
77
service."Supplement\nfoo".name: invalid value "Supplement\nfoo" (out of bound !~"^[A-Z]"):
88
./services.cue:2:26
9-
./services.jsonl:3:13
9+
./services.jsonl:12:13
1010
-- services.cue --
1111
deployment: [string]: name: !~"^[A-Z]"
1212
service: [string]: name: !~"^[A-Z]"

encoding/json/json.go

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package json
1717

1818
import (
19+
"bytes"
1920
"encoding/json"
2021
"fmt"
2122
"io"
@@ -28,6 +29,7 @@ import (
2829
"cuelang.org/go/cue/literal"
2930
"cuelang.org/go/cue/parser"
3031
"cuelang.org/go/cue/token"
32+
"cuelang.org/go/internal/source"
3133
)
3234

3335
// Valid reports whether data is a valid JSON encoding.
@@ -60,7 +62,7 @@ func Extract(path string, data []byte) (ast.Expr, error) {
6062
if err != nil {
6163
return nil, err
6264
}
63-
patchExpr(expr)
65+
patchExpr(expr, nil)
6466
return expr, nil
6567
}
6668

@@ -96,10 +98,15 @@ func extract(path string, b []byte) (ast.Expr, error) {
9698
//
9799
// The runtime may be nil if Decode isn't used.
98100
func NewDecoder(r *cue.Runtime, path string, src io.Reader) *Decoder {
101+
b, err := source.ReadAll(path, src)
102+
tokFile := token.NewFile(path, 0, len(b))
103+
tokFile.SetLinesForContent(b)
99104
return &Decoder{
100-
r: r,
101-
path: path,
102-
dec: json.NewDecoder(src),
105+
r: r,
106+
path: path,
107+
dec: json.NewDecoder(bytes.NewReader(b)),
108+
tokFile: tokFile,
109+
readAllErr: err,
103110
}
104111
}
105112

@@ -108,16 +115,24 @@ type Decoder struct {
108115
r *cue.Runtime
109116
path string
110117
dec *json.Decoder
118+
119+
startOffset int
120+
tokFile *token.File
121+
readAllErr error
111122
}
112123

113124
// Extract converts the current JSON value to a CUE ast. It returns io.EOF
114125
// if the input has been exhausted.
115126
func (d *Decoder) Extract() (ast.Expr, error) {
127+
if d.readAllErr != nil {
128+
return nil, d.readAllErr
129+
}
130+
116131
expr, err := d.extract()
117132
if err != nil {
118133
return expr, err
119134
}
120-
patchExpr(expr)
135+
patchExpr(expr, d.patchPos)
121136
return expr, nil
122137
}
123138

@@ -128,17 +143,25 @@ func (d *Decoder) extract() (ast.Expr, error) {
128143
return nil, err
129144
}
130145
if err != nil {
131-
pos := token.NewFile(d.path, -1, len(raw)).Pos(0, 0)
146+
pos := d.tokFile.Pos(int(d.dec.InputOffset()), 0)
132147
return nil, errors.Wrapf(err, pos, "invalid JSON for file %q", d.path)
133148
}
134149
expr, err := parser.ParseExpr(d.path, []byte(raw))
135150

136151
if err != nil {
137152
return nil, err
138153
}
154+
155+
d.startOffset = int(d.dec.InputOffset()) - len(raw)
139156
return expr, nil
140157
}
141158

159+
func (d *Decoder) patchPos(n ast.Node) {
160+
pos := n.Pos()
161+
realPos := d.tokFile.Pos(pos.Offset()+d.startOffset, pos.RelPos())
162+
ast.SetPos(n, realPos)
163+
}
164+
142165
// Decode converts the current JSON value to a CUE instance. It returns io.EOF
143166
// if the input has been exhausted.
144167
//
@@ -155,7 +178,7 @@ func (d *Decoder) Decode() (*cue.Instance, error) {
155178
// TODO: some of the modifications are already done in format, but are
156179
// a package deal of a more aggressive simplify. Other pieces of modification
157180
// should probably be moved to format.
158-
func patchExpr(n ast.Node) {
181+
func patchExpr(n ast.Node, patchPos func(n ast.Node)) {
159182
type info struct {
160183
reflow bool
161184
}
@@ -171,6 +194,10 @@ func patchExpr(n ast.Node) {
171194
var beforeFn func(n ast.Node) bool
172195

173196
beforeFn = func(n ast.Node) bool {
197+
if patchPos != nil {
198+
patchPos(n)
199+
}
200+
174201
isLarge := n.End().Offset()-n.Pos().Offset() > 50
175202
descent := true
176203

0 commit comments

Comments
 (0)