Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 3 additions & 14 deletions internal/services/realtimeengine/iacrealtime/line_parser.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package iacrealtime

import (
"os"
"path/filepath"
"strings"
)

Expand All @@ -12,17 +10,8 @@ func NewLineParser() *LineParser {
return &LineParser{}
}

func (lp *LineParser) GetLineIndices(filePath string, lineNumber int) (startIndex, endIndex int) {
if filePath == "" {
return 0, 0
}

data, err := os.ReadFile(filepath.Clean(filePath))
if err != nil {
return 0, 0
}

lines := strings.Split(string(data), "\n")
func (lp *LineParser) GetLineIndices(content string, lineNumber int) (startIndex, endIndex int) {
lines := strings.Split(content, "\n")

if lineNumber < 0 || lineNumber >= len(lines) {
return 0, 0
Expand All @@ -48,7 +37,7 @@ func (lp *LineParser) findContentBounds(line string) (start, end int) {
if start == -1 {
start = i
}
end = i
end = i + 1
}
}

Expand Down
102 changes: 32 additions & 70 deletions internal/services/realtimeengine/iacrealtime/line_parser_test.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package iacrealtime

import (
"os"
"testing"
)

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

// Create a test file with known content
testContent := `line 0
fileContent := `line 0
line 1
line 2 with spaces
line 3 with tab
empty line below

line 6`

tempFile, err := os.CreateTemp("", "test_line_parser_*.txt")
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
defer func() {
if err := os.Remove(tempFile.Name()); err != nil && !os.IsNotExist(err) {
t.Logf("Failed to remove temp file: %v", err)
}
}()

if _, err := tempFile.WriteString(testContent); err != nil {
t.Fatalf("Failed to write to temp file: %v", err)
}
tempFile.Close()

tests := []struct {
name string
filePath string
fileContent string
lineNumber int
expectedStart int
expectedEnd int
}{
{
name: "First line with content",
filePath: tempFile.Name(),
fileContent: fileContent,
lineNumber: 0,
expectedStart: 0,
expectedEnd: 5, // "line 0" - ends at '0'
expectedEnd: 6, // "line 0" - ends at '0'
},
{
name: "Second line with content",
filePath: tempFile.Name(),
fileContent: fileContent,
lineNumber: 1,
expectedStart: 0,
expectedEnd: 5, // "line 1" - ends at '1'
expectedEnd: 6, // "line 1" - ends at '1'
},
{
name: "Line with leading spaces",
filePath: tempFile.Name(),
fileContent: fileContent,
lineNumber: 2,
expectedStart: 2, // starts after " "
expectedEnd: 19, // ends at last 's' in "spaces"
expectedEnd: 20, // ends at last 's' in "spaces"
},
{
name: "Line with tab",
filePath: tempFile.Name(),
fileContent: fileContent,
lineNumber: 3,
expectedStart: 1, // starts after tab
expectedEnd: 15, // ends at 'b' in "tab"
expectedEnd: 16, // ends at 'b' in "tab"
},
{
name: "Empty line",
filePath: tempFile.Name(),
fileContent: fileContent,
lineNumber: 4,
expectedStart: 0,
expectedEnd: 15, // "empty line below"
expectedEnd: 16, // "empty line below"
},
{
name: "Line with only whitespace",
filePath: tempFile.Name(),
fileContent: fileContent,
lineNumber: 5,
expectedStart: 0,
expectedEnd: 0,
},
{
name: "Valid line number",
filePath: tempFile.Name(),
fileContent: fileContent,
lineNumber: 6,
expectedStart: 0,
expectedEnd: 5, // "line 6"
expectedEnd: 6, // "line 6"
},
{
name: "Invalid line number (negative)",
filePath: tempFile.Name(),
fileContent: fileContent,
lineNumber: -1,
expectedStart: 0,
expectedEnd: 0,
},
{
name: "Invalid line number (too large)",
filePath: tempFile.Name(),
fileContent: fileContent,
lineNumber: 100,
expectedStart: 0,
expectedEnd: 0,
},
{
name: "Empty file path",
filePath: "",
lineNumber: 0,
expectedStart: 0,
expectedEnd: 0,
},
{
name: "Non-existent file",
filePath: "/nonexistent/file.txt",
fileContent: "",
lineNumber: 0,
expectedStart: 0,
expectedEnd: 0,
Expand All @@ -129,7 +106,7 @@ line 6`
for _, tt := range tests {
ttt := tt
t.Run(tt.name, func(t *testing.T) {
start, end := parser.GetLineIndices(ttt.filePath, ttt.lineNumber)
start, end := parser.GetLineIndices(ttt.fileContent, ttt.lineNumber)
if start != ttt.expectedStart || end != ttt.expectedEnd {
t.Errorf("GetLineIndices() = (%d, %d), want (%d, %d)",
start, end, ttt.expectedStart, ttt.expectedEnd)
Expand All @@ -151,37 +128,37 @@ func TestLineParser_findContentBounds(t *testing.T) {
name: "Normal line with content",
line: "hello world",
expectedStart: 0,
expectedEnd: 10,
expectedEnd: 11,
},
{
name: "Line with leading spaces",
line: " hello world",
expectedStart: 2,
expectedEnd: 12,
expectedEnd: 13,
},
{
name: "Line with trailing spaces",
line: "hello world ",
expectedStart: 0,
expectedEnd: 10,
expectedEnd: 11,
},
{
name: "Line with leading and trailing spaces",
line: " hello world ",
expectedStart: 2,
expectedEnd: 12,
expectedEnd: 13,
},
{
name: "Line with tabs",
line: "\thello\tworld\t",
expectedStart: 1,
expectedEnd: 11,
expectedEnd: 12,
},
{
name: "Line with mixed whitespace",
line: " \t hello world \t ",
expectedStart: 3,
expectedEnd: 13,
expectedEnd: 14,
},
{
name: "Empty line",
Expand Down Expand Up @@ -211,19 +188,19 @@ func TestLineParser_findContentBounds(t *testing.T) {
name: "Single character",
line: "a",
expectedStart: 0,
expectedEnd: 0,
expectedEnd: 1,
},
{
name: "Single character with spaces",
line: " a ",
expectedStart: 2,
expectedEnd: 2,
expectedEnd: 3,
},
{
name: "Line with carriage return",
line: "hello\rworld",
expectedStart: 0,
expectedEnd: 10,
expectedEnd: 11,
},
}

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

tempFile, err := os.CreateTemp("", "test_line_endings_*.txt")
if err != nil {
t.Fatalf("Failed to create temp file: %v", err)
}
defer func() {
if err := os.Remove(tempFile.Name()); err != nil && !os.IsNotExist(err) {
t.Logf("Failed to remove temp file: %v", err)
}
}()

if _, err := tempFile.WriteString(testContent); err != nil {
t.Fatalf("Failed to write to temp file: %v", err)
}
tempFile.Close()

tests := []struct {
name string
lineNumber int
Expand All @@ -341,26 +303,26 @@ func TestLineParser_GetLineIndices_EdgeCases(t *testing.T) {
name: "First line",
lineNumber: 0,
expectedStart: 0,
expectedEnd: 4, // "line1"
expectedEnd: 5, // "line1"
},
{
name: "Second line with CRLF",
lineNumber: 1,
expectedStart: 0,
expectedEnd: 4, // "line2"
expectedEnd: 5, // "line2"
},
{
name: "Third line with CR",
lineNumber: 2,
expectedStart: 0,
expectedEnd: 10, // "line3\rline4" - ends at '4'
expectedEnd: 11, // "line3\rline4" - ends at '4'
},
}

for _, tt := range tests {
ttt := tt
t.Run(tt.name, func(t *testing.T) {
start, end := parser.GetLineIndices(tempFile.Name(), ttt.lineNumber)
start, end := parser.GetLineIndices(testContent, ttt.lineNumber)
if start != ttt.expectedStart || end != ttt.expectedEnd {
t.Errorf("GetLineIndices() = (%d, %d), want (%d, %d)",
start, end, ttt.expectedStart, ttt.expectedEnd)
Expand Down
11 changes: 8 additions & 3 deletions internal/services/realtimeengine/iacrealtime/mapper.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package iacrealtime

import (
"os"
"path/filepath"
"strings"

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

data, _ := os.ReadFile(filepath.Clean(filePath))
fileContent := string(data)

for i := range results.Results {
result := &results.Results[i]
for j := range result.Locations {
loc := &result.Locations[j]
locLine := int(loc.Line) - 1
lineIndex := m.getOrComputeLineIndex(filePath, locLine, indexMap)
lineIndex := m.getOrComputeLineIndex(fileContent, locLine, indexMap)

iacResult := IacRealtimeResult{
Title: result.QueryName,
Expand All @@ -51,12 +56,12 @@ func (m *Mapper) ConvertKicsToIacResults(
return iacResults
}

func (m *Mapper) getOrComputeLineIndex(filePath string, lineNum int, indexMap map[int]LineIndex) LineIndex {
func (m *Mapper) getOrComputeLineIndex(content string, lineNum int, indexMap map[int]LineIndex) LineIndex {
if value, exists := indexMap[lineNum]; exists {
return value
}

startIndex, endIndex := m.lineParser.GetLineIndices(filePath, lineNum)
startIndex, endIndex := m.lineParser.GetLineIndices(content, lineNum)
lineIndex := LineIndex{Start: startIndex, End: endIndex}
indexMap[lineNum] = lineIndex
return lineIndex
Expand Down
Loading
Loading