Skip to content

Commit ab2b573

Browse files
authored
fix: cache countLines. add comments. (#34)
1 parent c669ce0 commit ab2b573

File tree

6 files changed

+44
-10
lines changed

6 files changed

+44
-10
lines changed

lang/collect/export.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,12 @@ func (c *Collector) fileLine(loc Location) uniast.FileLine {
4040
rel = filepath.Base(loc.URI.File())
4141
}
4242
text := c.cli.GetFile(loc.URI).Text
43+
file_uri := string(loc.URI)
4344
return uniast.FileLine{
4445
File: rel,
4546
Line: loc.Range.Start.Line,
46-
StartOffset: lsp.PositionOffset(text, loc.Range.Start),
47-
EndOffset: lsp.PositionOffset(text, loc.Range.End),
47+
StartOffset: lsp.PositionOffset(file_uri, text, loc.Range.Start),
48+
EndOffset: lsp.PositionOffset(file_uri, text, loc.Range.End),
4849
}
4950
}
5051

lang/cxx/spec.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ func (c *CxxSpec) FunctionSymbol(sym lsp.DocumentSymbol) (int, []int, []int, []i
166166
// TODO: attributes may contain parens. also inline structs.
167167

168168
endRelOffset := 0
169-
lines := utils.CountLinesCached(sym.Text)
169+
lines := utils.CountLinesPooled(sym.Text)
170170
phase := 0
171171
for i, tok := range sym.Tokens {
172172
switch phase {

lang/lsp/utils.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ import (
3636
)
3737

3838
func GetDistance(text string, start Position, pos Position) int {
39-
lines := utils.CountLinesCached(text)
39+
lines := utils.CountLinesPooled(text)
4040
defer utils.PutCount(lines)
4141
// find the line of the position
4242
return (*lines)[pos.Line-start.Line] + pos.Character - start.Character
@@ -59,13 +59,15 @@ func RelativePostionWithLines(lines []int, textPos Position, pos Position) int {
5959
return lines[l] + pos.Character - textPos.Character
6060
}
6161

62-
func PositionOffset(text string, pos Position) int {
62+
func PositionOffset(file_uri string, text string, pos Position) int {
6363
if pos.Line < 0 || pos.Character < 0 {
6464
log.Error("invalid text position: %+v", pos)
6565
return -1
6666
}
67-
lines := utils.CountLinesCached(text)
68-
defer utils.PutCount(lines)
67+
lines := utils.CountLinesCached(file_uri, text)
68+
69+
// lines := utils.CountLinesPooled(text)
70+
// defer utils.PutCount(lines)
6971

7072
return RelativePostionWithLines(*lines, Position{Line: 0, Character: 0}, pos)
7173
}

lang/lsp/utils_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func TestPositionOffset(t *testing.T) {
7373

7474
for _, tt := range tests {
7575
t.Run(tt.name, func(t *testing.T) {
76-
result := PositionOffset(tt.text, tt.pos)
76+
result := PositionOffset(tt.name, tt.text, tt.pos)
7777
if result != tt.expected {
7878
t.Errorf("PositionOffset() = %v, expected %v", result, tt.expected)
7979
}

lang/rust/spec.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ func (c *RustSpec) FunctionSymbol(sym lsp.DocumentSymbol) (int, []int, []int, []
261261
if where == -1 {
262262
where = len(tokens) - 1
263263
}
264-
lines := utils.CountLinesCached(sym.Text)
264+
lines := utils.CountLinesPooled(sym.Text)
265265

266266
// find the typeParam's type token between "fn" and "("
267267
var typeParams []int

lang/utils/strings.go

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,40 @@ var countPool = sync.Pool{
2323
},
2424
}
2525

26+
var countCache = sync.Map{}
27+
28+
// USE AND ONLY USE in pairs with CountLinesPooled.
2629
func PutCount(count *[]int) {
2730
*count = (*count)[:0]
2831
countPool.Put(count)
2932
}
3033

31-
func CountLinesCached(text string) *[]int {
34+
// The cached version of CountLines.
35+
// Avoids redundant computations for the same text.
36+
// Use when the same text is processed multiple times, such as contents of a file.
37+
//
38+
// The key MUST uniquely identify the text i.e. for any two invocations
39+
//
40+
// CountLinesCached(key1, text1) and CountLinesCached(key2, text2),
41+
//
42+
// if key1 == key2, then text1 must be equal to text2 (and also vice versa).
43+
func CountLinesCached(key string, text string) *[]int {
44+
if cached, ok := countCache.Load(key); ok {
45+
res := cached.([]int)
46+
return &res
47+
}
48+
49+
lines := CountLines(text)
50+
countCache.Store(key, lines)
51+
return &lines
52+
}
53+
54+
// The pooled version of CountLines.
55+
// Eases burden on allocation and GC.
56+
// Use when invocation on small text is frequent.
57+
//
58+
// MUST manually invoke `PutCount` when done with the result to return the slice to the pool.
59+
func CountLinesPooled(text string) *[]int {
3260
tmp := countPool.Get().(*[]int)
3361
*tmp = append(*tmp, 0)
3462
for i, c := range text {
@@ -39,6 +67,9 @@ func CountLinesCached(text string) *[]int {
3967
return tmp
4068
}
4169

70+
// CountLines calculates the starting offsets of lines in a given text.
71+
// Each offset marks the byte position of the character immediately following a newline character,
72+
// or 0 for the very beginning of the text.
4273
func CountLines(text string) []int {
4374
var ret []int
4475
ret = append(ret, 0)

0 commit comments

Comments
 (0)