Skip to content

Commit 420c6d7

Browse files
committed
Fix column position validation to prevent Errata "label column cannot start at the end of the line" errors
1 parent 42c276f commit 420c6d7

File tree

2 files changed

+55
-9
lines changed

2 files changed

+55
-9
lines changed

src/Cake.Issues.Reporting.Console/ConsoleIssueReportGenerator.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,14 +76,14 @@ protected override FilePath InternalCreateReport(IEnumerable<IIssue> issues)
7676
{
7777
foreach (var issueGroup in diagnosticIssues.GroupBy(x => x.RuleId))
7878
{
79-
_ = report.AddDiagnostic(new IssueDiagnostic(issueGroup));
79+
_ = report.AddDiagnostic(new IssueDiagnostic(issueGroup, this.Settings.RepositoryRoot));
8080
}
8181
}
8282
else
8383
{
8484
foreach (var issue in diagnosticIssues)
8585
{
86-
_ = report.AddDiagnostic(new IssueDiagnostic(issue));
86+
_ = report.AddDiagnostic(new IssueDiagnostic(issue, this.Settings.RepositoryRoot));
8787
}
8888
}
8989

src/Cake.Issues.Reporting.Console/IssueDiagnostic.cs

Lines changed: 53 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
using System;
44
using System.Collections.Generic;
5+
using System.IO;
56
using System.Linq;
7+
using Cake.Core.IO;
68
using Errata;
79
using Spectre.Console;
810

@@ -12,25 +14,29 @@
1214
internal sealed class IssueDiagnostic : Diagnostic
1315
{
1416
private readonly IEnumerable<IIssue> issues;
17+
private readonly DirectoryPath repositoryRoot;
1518

1619
/// <summary>
1720
/// Initializes a new instance of the <see cref="IssueDiagnostic"/> class.
1821
/// </summary>
1922
/// <param name="issue">Issue which the diagnostic should describe.</param>
20-
public IssueDiagnostic(IIssue issue)
21-
: this([issue])
23+
/// <param name="repositoryRoot">Root directory of the repository.</param>
24+
public IssueDiagnostic(IIssue issue, DirectoryPath repositoryRoot = null)
25+
: this([issue], repositoryRoot)
2226
{
2327
}
2428

2529
/// <summary>
2630
/// Initializes a new instance of the <see cref="IssueDiagnostic"/> class.
2731
/// </summary>
2832
/// <param name="issues">Issues which the diagnostic should describe.</param>
29-
public IssueDiagnostic(IEnumerable<IIssue> issues)
33+
/// <param name="repositoryRoot">Root directory of the repository.</param>
34+
public IssueDiagnostic(IEnumerable<IIssue> issues, DirectoryPath repositoryRoot = null)
3035

3136
: base(issues.First().RuleId)
3237
{
3338
this.issues = issues;
39+
this.repositoryRoot = repositoryRoot;
3440

3541
var firstIssue = this.issues.First();
3642

@@ -79,20 +85,60 @@ public IssueDiagnostic(IEnumerable<IIssue> issues)
7985
/// </summary>
8086
/// <param name="issue">Issue for which the location should be returned.</param>
8187
/// <returns>Location for the diagnostic.</returns>
82-
private static (Location Location, int Lenght) GetLocation(IIssue issue)
88+
private (Location Location, int Lenght) GetLocation(IIssue issue)
8389
{
8490
// Errata currently doesn't support file or line level diagnostics.
8591
if (!issue.Line.HasValue || !issue.Column.HasValue)
8692
{
8793
return default;
8894
}
8995

90-
var location = new Location(issue.Line.Value, issue.Column.Value);
96+
var line = issue.Line.Value;
97+
var column = issue.Column.Value;
98+
99+
// Try to validate column position against actual file content if possible
100+
if (this.repositoryRoot != null && issue.AffectedFileRelativePath != null)
101+
{
102+
try
103+
{
104+
var fullPath = this.repositoryRoot.CombineWithFilePath(issue.AffectedFileRelativePath).FullPath;
105+
if (File.Exists(fullPath))
106+
{
107+
var fileContent = File.ReadAllText(fullPath);
108+
var lines = fileContent.Split(['\r', '\n'], StringSplitOptions.None);
109+
110+
if (line > 0 && line <= lines.Length)
111+
{
112+
var lineContent = lines[line - 1]; // Convert to 0-based indexing
113+
var lineLength = lineContent.Length;
114+
115+
// If column is beyond the end of the line, adjust it to the last valid position
116+
if (column > lineLength)
117+
{
118+
column = Math.Max(1, lineLength); // Position at end of line content, minimum column 1
119+
}
120+
}
121+
}
122+
}
123+
catch
124+
{
125+
// If file reading fails, proceed with original column position
126+
// This ensures we don't break functionality when files are not accessible
127+
}
128+
}
129+
130+
var location = new Location(line, column);
91131

92132
var length = 0;
93133
if (issue.EndColumn.HasValue)
94134
{
95-
length = issue.EndColumn.Value - issue.Column.Value;
135+
length = issue.EndColumn.Value - column;
136+
137+
// Ensure length is non-negative
138+
if (length < 0)
139+
{
140+
length = 0;
141+
}
96142
}
97143

98144
return (location, length);
@@ -113,7 +159,7 @@ private void CreateLabels()
113159

114160
foreach (var issue in this.issues)
115161
{
116-
var (location, length) = GetLocation(issue);
162+
var (location, length) = this.GetLocation(issue);
117163
var label =
118164
new Label(
119165
issue.AffectedFileRelativePath.FullPath,

0 commit comments

Comments
 (0)