2
2
3
3
using System ;
4
4
using System . Collections . Generic ;
5
+ using System . IO ;
5
6
using System . Linq ;
7
+ using Cake . Core . IO ;
6
8
using Errata ;
7
9
using Spectre . Console ;
8
10
12
14
internal sealed class IssueDiagnostic : Diagnostic
13
15
{
14
16
private readonly IEnumerable < IIssue > issues ;
17
+ private readonly DirectoryPath repositoryRoot ;
15
18
16
19
/// <summary>
17
20
/// Initializes a new instance of the <see cref="IssueDiagnostic"/> class.
18
21
/// </summary>
19
22
/// <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 )
22
26
{
23
27
}
24
28
25
29
/// <summary>
26
30
/// Initializes a new instance of the <see cref="IssueDiagnostic"/> class.
27
31
/// </summary>
28
32
/// <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 )
30
35
31
36
: base ( issues . First ( ) . RuleId )
32
37
{
33
38
this . issues = issues ;
39
+ this . repositoryRoot = repositoryRoot ;
34
40
35
41
var firstIssue = this . issues . First ( ) ;
36
42
@@ -79,20 +85,60 @@ public IssueDiagnostic(IEnumerable<IIssue> issues)
79
85
/// </summary>
80
86
/// <param name="issue">Issue for which the location should be returned.</param>
81
87
/// <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 )
83
89
{
84
90
// Errata currently doesn't support file or line level diagnostics.
85
91
if ( ! issue . Line . HasValue || ! issue . Column . HasValue )
86
92
{
87
93
return default ;
88
94
}
89
95
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 ) ;
91
131
92
132
var length = 0 ;
93
133
if ( issue . EndColumn . HasValue )
94
134
{
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
+ }
96
142
}
97
143
98
144
return ( location , length ) ;
@@ -113,7 +159,7 @@ private void CreateLabels()
113
159
114
160
foreach ( var issue in this . issues )
115
161
{
116
- var ( location , length ) = GetLocation ( issue ) ;
162
+ var ( location , length ) = this . GetLocation ( issue ) ;
117
163
var label =
118
164
new Label (
119
165
issue . AffectedFileRelativePath . FullPath ,
0 commit comments