@@ -8,26 +8,42 @@ import (
8
8
"gopkg.in/bblfsh/sdk.v2/uast/nodes"
9
9
)
10
10
11
- func TestFillLineColFromOffset (t * testing.T ) {
11
+ func offset (v int ) nodes.Object {
12
+ return uast.Position {Offset : uint32 (v )}.ToObject ()
13
+ }
14
+
15
+ func lineCol (line , col int ) nodes.Object {
16
+ return uast.Position {Line : uint32 (line ), Col : uint32 (col )}.ToObject ()
17
+ }
18
+
19
+ func fullPos (off , line , col int ) nodes.Object {
20
+ return uast.Position {Offset : uint32 (off ), Line : uint32 (line ), Col : uint32 (col )}.ToObject ()
21
+ }
22
+
23
+ func TestFillLineColNested (t * testing.T ) {
12
24
require := require .New (t )
13
25
14
26
data := "hello\n \n world"
15
27
16
28
input := nodes.Object {
17
- uast .KeyStart : uast.Position {Offset : 0 }.ToObject (),
18
- uast .KeyEnd : uast.Position {Offset : 4 }.ToObject (),
19
- "a" : nodes.Array {nodes.Object {
20
- uast .KeyStart : uast.Position {Offset : 7 }.ToObject (),
21
- uast .KeyEnd : uast.Position {Offset : 12 }.ToObject (),
29
+ "a" : nodes.Object {
30
+ uast .KeyStart : offset (0 ),
31
+ uast .KeyEnd : offset (4 ),
32
+ },
33
+ "b" : nodes.Array {nodes.Object {
34
+ uast .KeyStart : offset (7 ),
35
+ uast .KeyEnd : offset (12 ),
22
36
}},
23
37
}
24
38
25
39
expected := nodes.Object {
26
- uast .KeyStart : uast.Position {Offset : 0 , Line : 1 , Col : 1 }.ToObject (),
27
- uast .KeyEnd : uast.Position {Offset : 4 , Line : 1 , Col : 5 }.ToObject (),
28
- "a" : nodes.Array {nodes.Object {
29
- uast .KeyStart : uast.Position {Offset : 7 , Line : 3 , Col : 1 }.ToObject (),
30
- uast .KeyEnd : uast.Position {Offset : 12 , Line : 3 , Col : 6 }.ToObject (),
40
+ "a" : nodes.Object {
41
+ uast .KeyStart : fullPos (0 , 1 , 1 ),
42
+ uast .KeyEnd : fullPos (4 , 1 , 5 ),
43
+ },
44
+ "b" : nodes.Array {nodes.Object {
45
+ uast .KeyStart : fullPos (7 , 3 , 1 ),
46
+ uast .KeyEnd : fullPos (12 , 3 , 6 ),
31
47
}},
32
48
}
33
49
@@ -37,25 +53,30 @@ func TestFillLineColFromOffset(t *testing.T) {
37
53
require .Equal (expected , out )
38
54
}
39
55
40
- func TestFillOffsetFromLineCol (t * testing.T ) {
56
+ func TestFillOffsetNested (t * testing.T ) {
41
57
require := require .New (t )
42
58
43
59
data := "hello\n \n world"
60
+
44
61
input := nodes.Object {
45
- uast .KeyStart : uast.Position {Line : 1 , Col : 1 }.ToObject (),
46
- uast .KeyEnd : uast.Position {Line : 1 , Col : 5 }.ToObject (),
47
- "a" : nodes.Array {nodes.Object {
48
- uast .KeyStart : uast.Position {Line : 3 , Col : 1 }.ToObject (),
49
- uast .KeyEnd : uast.Position {Line : 3 , Col : 5 }.ToObject (),
62
+ "a" : nodes.Object {
63
+ uast .KeyStart : lineCol (1 , 1 ),
64
+ uast .KeyEnd : lineCol (1 , 5 ),
65
+ },
66
+ "b" : nodes.Array {nodes.Object {
67
+ uast .KeyStart : lineCol (3 , 1 ),
68
+ uast .KeyEnd : lineCol (3 , 6 ),
50
69
}},
51
70
}
52
71
53
72
expected := nodes.Object {
54
- uast .KeyStart : uast.Position {Offset : 0 , Line : 1 , Col : 1 }.ToObject (),
55
- uast .KeyEnd : uast.Position {Offset : 4 , Line : 1 , Col : 5 }.ToObject (),
56
- "a" : nodes.Array {nodes.Object {
57
- uast .KeyStart : uast.Position {Offset : 7 , Line : 3 , Col : 1 }.ToObject (),
58
- uast .KeyEnd : uast.Position {Offset : 11 , Line : 3 , Col : 5 }.ToObject (),
73
+ "a" : nodes.Object {
74
+ uast .KeyStart : fullPos (0 , 1 , 1 ),
75
+ uast .KeyEnd : fullPos (4 , 1 , 5 ),
76
+ },
77
+ "b" : nodes.Array {nodes.Object {
78
+ uast .KeyStart : fullPos (7 , 3 , 1 ),
79
+ uast .KeyEnd : fullPos (12 , 3 , 6 ),
59
80
}},
60
81
}
61
82
@@ -65,23 +86,58 @@ func TestFillOffsetFromLineCol(t *testing.T) {
65
86
require .Equal (expected , out )
66
87
}
67
88
68
- func TestEmptyFile (t * testing.T ) {
89
+ func TestFillOffsetEmptyFile (t * testing.T ) {
69
90
require := require .New (t )
70
91
71
92
data := ""
72
93
73
94
input := nodes.Object {
74
- uast .KeyStart : uast. Position { Line : 1 , Col : 1 }. ToObject ( ),
75
- uast .KeyEnd : uast. Position { Line : 1 , Col : 1 }. ToObject ( ),
95
+ uast .KeyStart : lineCol ( 1 , 1 ),
96
+ uast .KeyEnd : lineCol ( 1 , 1 ),
76
97
}
77
98
78
99
expected := nodes.Object {
79
- uast .KeyStart : uast. Position { Offset : 0 , Line : 1 , Col : 1 }. ToObject ( ),
80
- uast .KeyEnd : uast. Position { Offset : 0 , Line : 1 , Col : 1 }. ToObject ( ),
100
+ uast .KeyStart : fullPos ( 0 , 1 , 1 ),
101
+ uast .KeyEnd : fullPos ( 0 , 1 , 1 ),
81
102
}
82
103
83
104
p := NewFillOffsetFromLineCol ()
84
105
out , err := p .OnCode (data ).Do (input )
85
106
require .NoError (err )
86
107
require .Equal (expected , out )
87
108
}
109
+
110
+ func TestPosIndex (t * testing.T ) {
111
+ // Verify that a multi-byte Unicode rune does not displace offsets after
112
+ // its occurrence in the input. Test few other simple cases as well.
113
+ const source = `line1
114
+ ё2
115
+ a3`
116
+ var cases = []uast.Position {
117
+ {Offset : 0 , Line : 1 , Col : 1 },
118
+ {Offset : 4 , Line : 1 , Col : 5 },
119
+
120
+ // multi-byte unicode rune
121
+ {Offset : 6 , Line : 2 , Col : 1 },
122
+ {Offset : 8 , Line : 2 , Col : 3 }, // col is a byte offset+1, not a rune index
123
+
124
+ {Offset : 10 , Line : 3 , Col : 1 },
125
+ {Offset : 11 , Line : 3 , Col : 2 },
126
+
127
+ {Offset : 12 , Line : 3 , Col : 3 }, // special case — EOF position
128
+ }
129
+
130
+ ind := newPositionIndex ([]byte (source ))
131
+ for _ , c := range cases {
132
+ t .Run ("" , func (t * testing.T ) {
133
+ line , col , err := ind .LineCol (int (c .Offset ))
134
+ require .NoError (t , err )
135
+ require .Equal (t , c .Line , uint32 (line ))
136
+ require .Equal (t , c .Col , uint32 (col ))
137
+
138
+ off , err := ind .Offset (int (c .Line ), int (c .Col ))
139
+ require .NoError (t , err )
140
+ require .Equal (t , c .Offset , uint32 (off ))
141
+ })
142
+ }
143
+ }
0 commit comments