Skip to content

Commit 1d261bf

Browse files
committed
fix: collect/export outputs 0-based linenos. fix checker.
This fixes the invalid offset warnings and invalid StartOffsets. The checker has a --implheads option that allows relaxed comparisons, because for rust sym.Content may contain extra implheads.
1 parent 82cf7cc commit 1d261bf

File tree

6 files changed

+47
-25
lines changed

6 files changed

+47
-25
lines changed

src/lang/check.py

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,16 @@
55
# 应当成功,尤其应当是 --zero_linebase(行号从 0 开始)
66
$ python3 check.py --json lang.json --base . --zero_linebase
77
8-
"""
8+
检查 rust 项目
99
10+
$ ./lang -d -v --no-need-comment collect rust ../../testdata/rust2 > rust2.json
11+
$ python3 check.py --json lang.json --base . --zero_linebase --implheads
12+
"""
1013
import json
1114
import os
1215
import argparse
13-
from collections import defaultdict
1416
import sys
17+
from collections import defaultdict
1518

1619

1720
def trim_multiline(s, max_lines=5):
@@ -35,6 +38,7 @@ def verify_function_content(
3538
filter_files=None,
3639
filter_funcs=None,
3740
zero_linebase=False,
41+
implheads=False,
3842
):
3943
with open(json_path, "r", encoding="utf-8") as f:
4044
data = json.load(f)
@@ -72,7 +76,6 @@ def verify_function_content(
7276
actual_bytes = content_bytes[start:end]
7377
actual_content = safe_decode(actual_bytes)
7478

75-
# Line check
7679
line_number = func["Line"]
7780
content_str = safe_decode(content_bytes)
7881
file_lines = content_str.splitlines()
@@ -85,12 +88,20 @@ def verify_function_content(
8588
except IndexError:
8689
actual_line_content = "<out of range>"
8790

88-
expected_line_start = (
89-
expected_content.splitlines()[0].strip() if expected_content else ""
90-
)
91-
92-
offset_match = actual_content == expected_content
93-
line_match = actual_line_content == expected_line_start
91+
if implheads:
92+
offset_match = actual_content in expected_content
93+
line_match = any(
94+
line.strip() == actual_line_content.strip()
95+
for line in expected_content.splitlines()
96+
)
97+
else:
98+
offset_match = actual_content == expected_content
99+
expected_line_start = (
100+
expected_content.splitlines()[0].strip()
101+
if expected_content
102+
else ""
103+
)
104+
line_match = actual_line_content == expected_line_start
94105

95106
print(f"[{module_name}/{package_name}] Checking function: {func_name}")
96107
if not offset_match:
@@ -100,8 +111,13 @@ def verify_function_content(
100111
if not line_match:
101112
display_line_number = line_number if zero_linebase else line_number
102113
print(f" [Mismatch] Line {display_line_number} mismatch:")
103-
print(f" Expected line: {expected_line_start}")
104-
print(f" Actual line: {actual_line_content}")
114+
print(f" Expected line (from JSON content):")
115+
if implheads:
116+
print(f" Any line in expected content matching actual line:")
117+
else:
118+
print(f" {expected_line_start}")
119+
print(f" Actual line:")
120+
print(f" {actual_line_content}")
105121
if not offset_match or not line_match:
106122
errors[file_name].append(func_name)
107123
if bail_on_error:
@@ -149,6 +165,11 @@ def verify_function_content(
149165
action="store_true",
150166
help="Line numbers in JSON are 0-based instead of 1-based",
151167
)
168+
parser.add_argument(
169+
"--implheads",
170+
action="store_true",
171+
help="Allow actual content to be a substring of expected content and lines to match any line",
172+
)
152173

153174
args = parser.parse_args()
154175
filter_files = set(args.filter_file.split(",")) if args.filter_file else None
@@ -161,4 +182,5 @@ def verify_function_content(
161182
filter_files=filter_files,
162183
filter_funcs=filter_funcs,
163184
zero_linebase=args.zero_linebase,
185+
implheads=args.implheads,
164186
)

src/lang/collect/export.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ func (c *Collector) fileLine(loc Location) uniast.FileLine {
4242
text := c.cli.GetFile(loc.URI).Text
4343
return uniast.FileLine{
4444
File: rel,
45-
Line: loc.Range.Start.Line + 1,
45+
Line: loc.Range.Start.Line,
4646
StartOffset: lsp.PositionOffset(text, loc.Range.Start),
4747
EndOffset: lsp.PositionOffset(text, loc.Range.End),
4848
}

src/lang/lsp/lsp.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ type Location struct {
9898
}
9999

100100
func (l Location) String() string {
101-
return fmt.Sprintf("%s:%d:%d-%d:%d", l.URI, l.Range.Start.Line+1, l.Range.Start.Character+1, l.Range.End.Line+1, l.Range.End.Character+1)
101+
return fmt.Sprintf("%s:%d:%d-%d:%d", l.URI, l.Range.Start.Line, l.Range.Start.Character, l.Range.End.Line, l.Range.End.Character)
102102
}
103103

104104
var locationMarshalJSONInline = true

src/lang/lsp/lsp_test.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
// Copyright 2025 CloudWeGo Authors
2-
//
2+
//
33
// Licensed under the Apache License, Version 2.0 (the "License");
44
// you may not use this file except in compliance with the License.
55
// You may obtain a copy of the License at
6-
//
6+
//
77
// https://www.apache.org/licenses/LICENSE-2.0
8-
//
8+
//
99
// Unless required by applicable law or agreed to in writing, software
1010
// distributed under the License is distributed on an "AS IS" BASIS,
1111
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

src/lang/lsp/utils.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,12 +60,12 @@ func RelativePostionWithLines(lines []int, textPos Position, pos Position) int {
6060
}
6161

6262
func PositionOffset(text string, pos Position) int {
63-
if pos.Line < 1 || pos.Character < 1 {
63+
if pos.Line < 0 || pos.Character < 0 {
6464
log.Error("invalid text position: %+v", pos)
6565
return -1
6666
}
6767
lines := utils.CountLinesCached(text)
6868
defer utils.PutCount(lines)
6969

70-
return RelativePostionWithLines(*lines, Position{Line: 1, Character: 1}, pos)
70+
return RelativePostionWithLines(*lines, Position{Line: 0, Character: 0}, pos)
7171
}

src/lang/lsp/utils_test.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,43 +30,43 @@ func TestPositionOffset(t *testing.T) {
3030
{
3131
name: "Single line text, position at start",
3232
text: "Hello, World!",
33-
pos: Position{Line: 1, Character: 1},
33+
pos: Position{Line: 0, Character: 0},
3434
expected: 0,
3535
},
3636
{
3737
name: "Single line text, position at end",
3838
text: "Hello, World!",
39-
pos: Position{Line: 1, Character: 14},
39+
pos: Position{Line: 0, Character: 13},
4040
expected: 13,
4141
},
4242
{
4343
name: "Multi-line text, position at start of first line",
4444
text: "Line 1\nLine 2\nLine 3",
45-
pos: Position{Line: 1, Character: 1},
45+
pos: Position{Line: 0, Character: 0},
4646
expected: 0,
4747
},
4848
{
4949
name: "Multi-line text, position at end of first line",
5050
text: "Line 1\nLine 2\nLine 3",
51-
pos: Position{Line: 1, Character: 7},
51+
pos: Position{Line: 0, Character: 6},
5252
expected: 6,
5353
},
5454
{
5555
name: "Multi-line text, position at start of second line",
5656
text: "Line 1\nLine 2\nLine 3",
57-
pos: Position{Line: 2, Character: 1},
57+
pos: Position{Line: 1, Character: 0},
5858
expected: 7,
5959
},
6060
{
6161
name: "Multi-line text, position at end of last line",
6262
text: "Line 1\nLine 2\nLine 3",
63-
pos: Position{Line: 3, Character: 7},
63+
pos: Position{Line: 2, Character: 6},
6464
expected: 20,
6565
},
6666
{
6767
name: "Empty text, position at start",
6868
text: "",
69-
pos: Position{Line: 1, Character: 1},
69+
pos: Position{Line: 0, Character: 0},
7070
expected: 0,
7171
},
7272
}

0 commit comments

Comments
 (0)