Skip to content

Commit e3e0157

Browse files
Merge pull request #1254 from Checkmarx/other/benalvo/improve-line-parser-logic
Improve LineParser Logic (AST-102217, AST-102218)
2 parents d20b6d2 + 073f27b commit e3e0157

File tree

4 files changed

+56
-136
lines changed

4 files changed

+56
-136
lines changed

internal/services/realtimeengine/iacrealtime/line_parser.go

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
package iacrealtime
22

33
import (
4-
"os"
5-
"path/filepath"
64
"strings"
75
)
86

@@ -12,17 +10,8 @@ func NewLineParser() *LineParser {
1210
return &LineParser{}
1311
}
1412

15-
func (lp *LineParser) GetLineIndices(filePath string, lineNumber int) (startIndex, endIndex int) {
16-
if filePath == "" {
17-
return 0, 0
18-
}
19-
20-
data, err := os.ReadFile(filepath.Clean(filePath))
21-
if err != nil {
22-
return 0, 0
23-
}
24-
25-
lines := strings.Split(string(data), "\n")
13+
func (lp *LineParser) GetLineIndices(content string, lineNumber int) (startIndex, endIndex int) {
14+
lines := strings.Split(content, "\n")
2615

2716
if lineNumber < 0 || lineNumber >= len(lines) {
2817
return 0, 0
@@ -48,7 +37,7 @@ func (lp *LineParser) findContentBounds(line string) (start, end int) {
4837
if start == -1 {
4938
start = i
5039
}
51-
end = i
40+
end = i + 1
5241
}
5342
}
5443

internal/services/realtimeengine/iacrealtime/line_parser_test.go

Lines changed: 32 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package iacrealtime
22

33
import (
4-
"os"
54
"testing"
65
)
76

@@ -17,109 +16,87 @@ func TestLineParser_GetLineIndices(t *testing.T) {
1716
parser := NewLineParser()
1817

1918
// Create a test file with known content
20-
testContent := `line 0
19+
fileContent := `line 0
2120
line 1
2221
line 2 with spaces
2322
line 3 with tab
2423
empty line below
2524
2625
line 6`
2726

28-
tempFile, err := os.CreateTemp("", "test_line_parser_*.txt")
29-
if err != nil {
30-
t.Fatalf("Failed to create temp file: %v", err)
31-
}
32-
defer func() {
33-
if err := os.Remove(tempFile.Name()); err != nil && !os.IsNotExist(err) {
34-
t.Logf("Failed to remove temp file: %v", err)
35-
}
36-
}()
37-
38-
if _, err := tempFile.WriteString(testContent); err != nil {
39-
t.Fatalf("Failed to write to temp file: %v", err)
40-
}
41-
tempFile.Close()
42-
4327
tests := []struct {
4428
name string
45-
filePath string
29+
fileContent string
4630
lineNumber int
4731
expectedStart int
4832
expectedEnd int
4933
}{
5034
{
5135
name: "First line with content",
52-
filePath: tempFile.Name(),
36+
fileContent: fileContent,
5337
lineNumber: 0,
5438
expectedStart: 0,
55-
expectedEnd: 5, // "line 0" - ends at '0'
39+
expectedEnd: 6, // "line 0" - ends at '0'
5640
},
5741
{
5842
name: "Second line with content",
59-
filePath: tempFile.Name(),
43+
fileContent: fileContent,
6044
lineNumber: 1,
6145
expectedStart: 0,
62-
expectedEnd: 5, // "line 1" - ends at '1'
46+
expectedEnd: 6, // "line 1" - ends at '1'
6347
},
6448
{
6549
name: "Line with leading spaces",
66-
filePath: tempFile.Name(),
50+
fileContent: fileContent,
6751
lineNumber: 2,
6852
expectedStart: 2, // starts after " "
69-
expectedEnd: 19, // ends at last 's' in "spaces"
53+
expectedEnd: 20, // ends at last 's' in "spaces"
7054
},
7155
{
7256
name: "Line with tab",
73-
filePath: tempFile.Name(),
57+
fileContent: fileContent,
7458
lineNumber: 3,
7559
expectedStart: 1, // starts after tab
76-
expectedEnd: 15, // ends at 'b' in "tab"
60+
expectedEnd: 16, // ends at 'b' in "tab"
7761
},
7862
{
7963
name: "Empty line",
80-
filePath: tempFile.Name(),
64+
fileContent: fileContent,
8165
lineNumber: 4,
8266
expectedStart: 0,
83-
expectedEnd: 15, // "empty line below"
67+
expectedEnd: 16, // "empty line below"
8468
},
8569
{
8670
name: "Line with only whitespace",
87-
filePath: tempFile.Name(),
71+
fileContent: fileContent,
8872
lineNumber: 5,
8973
expectedStart: 0,
9074
expectedEnd: 0,
9175
},
9276
{
9377
name: "Valid line number",
94-
filePath: tempFile.Name(),
78+
fileContent: fileContent,
9579
lineNumber: 6,
9680
expectedStart: 0,
97-
expectedEnd: 5, // "line 6"
81+
expectedEnd: 6, // "line 6"
9882
},
9983
{
10084
name: "Invalid line number (negative)",
101-
filePath: tempFile.Name(),
85+
fileContent: fileContent,
10286
lineNumber: -1,
10387
expectedStart: 0,
10488
expectedEnd: 0,
10589
},
10690
{
10791
name: "Invalid line number (too large)",
108-
filePath: tempFile.Name(),
92+
fileContent: fileContent,
10993
lineNumber: 100,
11094
expectedStart: 0,
11195
expectedEnd: 0,
11296
},
11397
{
11498
name: "Empty file path",
115-
filePath: "",
116-
lineNumber: 0,
117-
expectedStart: 0,
118-
expectedEnd: 0,
119-
},
120-
{
121-
name: "Non-existent file",
122-
filePath: "/nonexistent/file.txt",
99+
fileContent: "",
123100
lineNumber: 0,
124101
expectedStart: 0,
125102
expectedEnd: 0,
@@ -129,7 +106,7 @@ line 6`
129106
for _, tt := range tests {
130107
ttt := tt
131108
t.Run(tt.name, func(t *testing.T) {
132-
start, end := parser.GetLineIndices(ttt.filePath, ttt.lineNumber)
109+
start, end := parser.GetLineIndices(ttt.fileContent, ttt.lineNumber)
133110
if start != ttt.expectedStart || end != ttt.expectedEnd {
134111
t.Errorf("GetLineIndices() = (%d, %d), want (%d, %d)",
135112
start, end, ttt.expectedStart, ttt.expectedEnd)
@@ -151,37 +128,37 @@ func TestLineParser_findContentBounds(t *testing.T) {
151128
name: "Normal line with content",
152129
line: "hello world",
153130
expectedStart: 0,
154-
expectedEnd: 10,
131+
expectedEnd: 11,
155132
},
156133
{
157134
name: "Line with leading spaces",
158135
line: " hello world",
159136
expectedStart: 2,
160-
expectedEnd: 12,
137+
expectedEnd: 13,
161138
},
162139
{
163140
name: "Line with trailing spaces",
164141
line: "hello world ",
165142
expectedStart: 0,
166-
expectedEnd: 10,
143+
expectedEnd: 11,
167144
},
168145
{
169146
name: "Line with leading and trailing spaces",
170147
line: " hello world ",
171148
expectedStart: 2,
172-
expectedEnd: 12,
149+
expectedEnd: 13,
173150
},
174151
{
175152
name: "Line with tabs",
176153
line: "\thello\tworld\t",
177154
expectedStart: 1,
178-
expectedEnd: 11,
155+
expectedEnd: 12,
179156
},
180157
{
181158
name: "Line with mixed whitespace",
182159
line: " \t hello world \t ",
183160
expectedStart: 3,
184-
expectedEnd: 13,
161+
expectedEnd: 14,
185162
},
186163
{
187164
name: "Empty line",
@@ -211,19 +188,19 @@ func TestLineParser_findContentBounds(t *testing.T) {
211188
name: "Single character",
212189
line: "a",
213190
expectedStart: 0,
214-
expectedEnd: 0,
191+
expectedEnd: 1,
215192
},
216193
{
217194
name: "Single character with spaces",
218195
line: " a ",
219196
expectedStart: 2,
220-
expectedEnd: 2,
197+
expectedEnd: 3,
221198
},
222199
{
223200
name: "Line with carriage return",
224201
line: "hello\rworld",
225202
expectedStart: 0,
226-
expectedEnd: 10,
203+
expectedEnd: 11,
227204
},
228205
}
229206

@@ -316,21 +293,6 @@ func TestLineParser_GetLineIndices_EdgeCases(t *testing.T) {
316293
// Test with a file that has different line endings
317294
testContent := "line1\nline2\r\nline3\rline4"
318295

319-
tempFile, err := os.CreateTemp("", "test_line_endings_*.txt")
320-
if err != nil {
321-
t.Fatalf("Failed to create temp file: %v", err)
322-
}
323-
defer func() {
324-
if err := os.Remove(tempFile.Name()); err != nil && !os.IsNotExist(err) {
325-
t.Logf("Failed to remove temp file: %v", err)
326-
}
327-
}()
328-
329-
if _, err := tempFile.WriteString(testContent); err != nil {
330-
t.Fatalf("Failed to write to temp file: %v", err)
331-
}
332-
tempFile.Close()
333-
334296
tests := []struct {
335297
name string
336298
lineNumber int
@@ -341,26 +303,26 @@ func TestLineParser_GetLineIndices_EdgeCases(t *testing.T) {
341303
name: "First line",
342304
lineNumber: 0,
343305
expectedStart: 0,
344-
expectedEnd: 4, // "line1"
306+
expectedEnd: 5, // "line1"
345307
},
346308
{
347309
name: "Second line with CRLF",
348310
lineNumber: 1,
349311
expectedStart: 0,
350-
expectedEnd: 4, // "line2"
312+
expectedEnd: 5, // "line2"
351313
},
352314
{
353315
name: "Third line with CR",
354316
lineNumber: 2,
355317
expectedStart: 0,
356-
expectedEnd: 10, // "line3\rline4" - ends at '4'
318+
expectedEnd: 11, // "line3\rline4" - ends at '4'
357319
},
358320
}
359321

360322
for _, tt := range tests {
361323
ttt := tt
362324
t.Run(tt.name, func(t *testing.T) {
363-
start, end := parser.GetLineIndices(tempFile.Name(), ttt.lineNumber)
325+
start, end := parser.GetLineIndices(testContent, ttt.lineNumber)
364326
if start != ttt.expectedStart || end != ttt.expectedEnd {
365327
t.Errorf("GetLineIndices() = (%d, %d), want (%d, %d)",
366328
start, end, ttt.expectedStart, ttt.expectedEnd)

internal/services/realtimeengine/iacrealtime/mapper.go

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package iacrealtime
22

33
import (
4+
"os"
5+
"path/filepath"
46
"strings"
57

68
"github.com/checkmarx/ast-cli/internal/services/realtimeengine"
@@ -24,12 +26,15 @@ func (m *Mapper) ConvertKicsToIacResults(
2426
iacResults := make([]IacRealtimeResult, 0)
2527
indexMap := make(map[int]LineIndex)
2628

29+
data, _ := os.ReadFile(filepath.Clean(filePath))
30+
fileContent := string(data)
31+
2732
for i := range results.Results {
2833
result := &results.Results[i]
2934
for j := range result.Locations {
3035
loc := &result.Locations[j]
3136
locLine := int(loc.Line) - 1
32-
lineIndex := m.getOrComputeLineIndex(filePath, locLine, indexMap)
37+
lineIndex := m.getOrComputeLineIndex(fileContent, locLine, indexMap)
3338

3439
iacResult := IacRealtimeResult{
3540
Title: result.QueryName,
@@ -51,12 +56,12 @@ func (m *Mapper) ConvertKicsToIacResults(
5156
return iacResults
5257
}
5358

54-
func (m *Mapper) getOrComputeLineIndex(filePath string, lineNum int, indexMap map[int]LineIndex) LineIndex {
59+
func (m *Mapper) getOrComputeLineIndex(content string, lineNum int, indexMap map[int]LineIndex) LineIndex {
5560
if value, exists := indexMap[lineNum]; exists {
5661
return value
5762
}
5863

59-
startIndex, endIndex := m.lineParser.GetLineIndices(filePath, lineNum)
64+
startIndex, endIndex := m.lineParser.GetLineIndices(content, lineNum)
6065
lineIndex := LineIndex{Start: startIndex, End: endIndex}
6166
indexMap[lineNum] = lineIndex
6267
return lineIndex

0 commit comments

Comments
 (0)