@@ -86,14 +86,22 @@ export async function diagnosticsToProblemsString(
8686 const fileStats = new Map < vscode . Uri , vscode . FileStat > ( )
8787 let result = ""
8888
89- // If we have a limit, we need to collect all diagnostics first, sort by severity, then limit
89+ // If we have a limit, we need to use size-based limiting instead of count-based
9090 if ( maxDiagnosticMessages && maxDiagnosticMessages > 0 ) {
91+ // Convert maxDiagnosticMessages to a character limit
92+ // Assuming average diagnostic message is ~1000 characters, multiply by the count
93+ const MAX_PROBLEMS_CONTENT_SIZE = maxDiagnosticMessages * 1000
94+ let currentSize = 0
95+ let includedCount = 0
96+ let totalCount = 0
97+
9198 // Flatten all diagnostics with their URIs
92- const allDiagnostics : { uri : vscode . Uri ; diagnostic : vscode . Diagnostic } [ ] = [ ]
99+ const allDiagnostics : { uri : vscode . Uri ; diagnostic : vscode . Diagnostic ; formattedText ?: string } [ ] = [ ]
93100 for ( const [ uri , fileDiagnostics ] of diagnostics ) {
94101 const filtered = fileDiagnostics . filter ( ( d ) => severities . includes ( d . severity ) )
95102 for ( const diagnostic of filtered ) {
96103 allDiagnostics . push ( { uri, diagnostic } )
104+ totalCount ++
97105 }
98106 }
99107
@@ -104,68 +112,88 @@ export async function diagnosticsToProblemsString(
104112 return a . diagnostic . range . start . line - b . diagnostic . range . start . line
105113 } )
106114
107- // Take only the first maxDiagnosticMessages
108- const limitedDiagnostics = allDiagnostics . slice ( 0 , maxDiagnosticMessages )
115+ // Process diagnostics and track size
116+ const includedDiagnostics : typeof allDiagnostics = [ ]
117+ for ( const item of allDiagnostics ) {
118+ // Format the diagnostic to calculate its size
119+ let label : string
120+ switch ( item . diagnostic . severity ) {
121+ case vscode . DiagnosticSeverity . Error :
122+ label = "Error"
123+ break
124+ case vscode . DiagnosticSeverity . Warning :
125+ label = "Warning"
126+ break
127+ case vscode . DiagnosticSeverity . Information :
128+ label = "Information"
129+ break
130+ case vscode . DiagnosticSeverity . Hint :
131+ label = "Hint"
132+ break
133+ default :
134+ label = "Diagnostic"
135+ }
136+ const line = item . diagnostic . range . start . line + 1
137+ const source = item . diagnostic . source ? `${ item . diagnostic . source } ` : ""
138+
139+ // Pre-format the diagnostic text
140+ let diagnosticText = ""
141+ try {
142+ let fileStat = fileStats . get ( item . uri )
143+ if ( ! fileStat ) {
144+ fileStat = await vscode . workspace . fs . stat ( item . uri )
145+ fileStats . set ( item . uri , fileStat )
146+ }
147+ if ( fileStat . type === vscode . FileType . File ) {
148+ const document = documents . get ( item . uri ) || ( await vscode . workspace . openTextDocument ( item . uri ) )
149+ documents . set ( item . uri , document )
150+ const lineContent = document . lineAt ( item . diagnostic . range . start . line ) . text
151+ diagnosticText = `\n- [${ source } ${ label } ] ${ line } | ${ lineContent } : ${ item . diagnostic . message } `
152+ } else {
153+ diagnosticText = `\n- [${ source } ${ label } ] 1 | (directory) : ${ item . diagnostic . message } `
154+ }
155+ } catch {
156+ diagnosticText = `\n- [${ source } ${ label } ] ${ line } | (unavailable) : ${ item . diagnostic . message } `
157+ }
158+
159+ // Check if adding this diagnostic would exceed the size limit
160+ const diagnosticSize = diagnosticText . length + path . relative ( cwd , item . uri . fsPath ) . toPosix ( ) . length + 2 // +2 for newlines
161+ if ( currentSize + diagnosticSize > MAX_PROBLEMS_CONTENT_SIZE && includedCount > 0 ) {
162+ break // Stop before exceeding limit
163+ }
164+
165+ item . formattedText = diagnosticText
166+ includedDiagnostics . push ( item )
167+ currentSize += diagnosticSize
168+ includedCount ++
169+ }
109170
110- // Group back by URI for processing
111- const groupedDiagnostics = new Map < string , { uri : vscode . Uri ; diagnostics : vscode . Diagnostic [ ] } > ( )
112- for ( const { uri , diagnostic } of limitedDiagnostics ) {
113- const key = uri . toString ( )
171+ // Group included diagnostics by URI for output
172+ const groupedDiagnostics = new Map < string , { uri : vscode . Uri ; diagnostics : typeof allDiagnostics } > ( )
173+ for ( const item of includedDiagnostics ) {
174+ const key = item . uri . toString ( )
114175 if ( ! groupedDiagnostics . has ( key ) ) {
115- groupedDiagnostics . set ( key , { uri, diagnostics : [ ] } )
176+ groupedDiagnostics . set ( key , { uri : item . uri , diagnostics : [ ] } )
116177 }
117- groupedDiagnostics . get ( key ) ! . diagnostics . push ( diagnostic )
178+ groupedDiagnostics . get ( key ) ! . diagnostics . push ( item )
118179 }
119180
120- // Process the limited diagnostics
181+ // Build the output
121182 for ( const { uri, diagnostics : fileDiagnostics } of groupedDiagnostics . values ( ) ) {
122- const problems = fileDiagnostics . sort ( ( a , b ) => a . range . start . line - b . range . start . line )
123- if ( problems . length > 0 ) {
183+ const sortedDiagnostics = fileDiagnostics . sort (
184+ ( a , b ) => a . diagnostic . range . start . line - b . diagnostic . range . start . line ,
185+ )
186+ if ( sortedDiagnostics . length > 0 ) {
124187 result += `\n\n${ path . relative ( cwd , uri . fsPath ) . toPosix ( ) } `
125- for ( const diagnostic of problems ) {
126- let label : string
127- switch ( diagnostic . severity ) {
128- case vscode . DiagnosticSeverity . Error :
129- label = "Error"
130- break
131- case vscode . DiagnosticSeverity . Warning :
132- label = "Warning"
133- break
134- case vscode . DiagnosticSeverity . Information :
135- label = "Information"
136- break
137- case vscode . DiagnosticSeverity . Hint :
138- label = "Hint"
139- break
140- default :
141- label = "Diagnostic"
142- }
143- const line = diagnostic . range . start . line + 1 // VSCode lines are 0-indexed
144- const source = diagnostic . source ? `${ diagnostic . source } ` : ""
145- try {
146- let fileStat = fileStats . get ( uri )
147- if ( ! fileStat ) {
148- fileStat = await vscode . workspace . fs . stat ( uri )
149- fileStats . set ( uri , fileStat )
150- }
151- if ( fileStat . type === vscode . FileType . File ) {
152- const document = documents . get ( uri ) || ( await vscode . workspace . openTextDocument ( uri ) )
153- documents . set ( uri , document )
154- const lineContent = document . lineAt ( diagnostic . range . start . line ) . text
155- result += `\n- [${ source } ${ label } ] ${ line } | ${ lineContent } : ${ diagnostic . message } `
156- } else {
157- result += `\n- [${ source } ${ label } ] 1 | (directory) : ${ diagnostic . message } `
158- }
159- } catch {
160- result += `\n- [${ source } ${ label } ] ${ line } | (unavailable) : ${ diagnostic . message } `
161- }
188+ for ( const item of sortedDiagnostics ) {
189+ result += item . formattedText
162190 }
163191 }
164192 }
165193
166194 // Add a note if we hit the limit
167- if ( allDiagnostics . length > maxDiagnosticMessages ) {
168- result += `\n\n(Showing ${ maxDiagnosticMessages } of ${ allDiagnostics . length } total diagnostics) `
195+ if ( totalCount > includedCount ) {
196+ result += `\n\n... ${ totalCount - includedCount } more problems omitted to prevent context overflow `
169197 }
170198 } else {
171199 // No limit, process all diagnostics as before
0 commit comments