@@ -190,6 +190,17 @@ suite('Extension Test Suite', () => {
190190 severity
191191 ) ;
192192 diagnostic . source = 'phpmd' ;
193+
194+ // Add rule code and external info URL if available
195+ if ( violation . externalInfoUrl ) {
196+ diagnostic . code = {
197+ value : violation . rule ,
198+ target : vscode . Uri . parse ( violation . externalInfoUrl )
199+ } ;
200+ } else {
201+ diagnostic . code = violation . rule ;
202+ }
203+
193204 diagnostics . push ( diagnostic ) ;
194205 }
195206 }
@@ -218,4 +229,102 @@ suite('Extension Test Suite', () => {
218229 assert . strictEqual ( diagnostics [ 1 ] . message . includes ( 'ShortVariable' ) , true ) ;
219230 assert . strictEqual ( diagnostics [ 1 ] . severity , vscode . DiagnosticSeverity . Error ) ;
220231 } ) ;
232+
233+ // Test for external info URL in diagnostics
234+ test ( 'Diagnostics include external info URL when available' , async ( ) => {
235+ // Define the same function as in the previous test
236+ const processPhpmdResults = ( output : string ) : vscode . Diagnostic [ ] => {
237+ try {
238+ const results = JSON . parse ( output ) ;
239+ const diagnostics : vscode . Diagnostic [ ] = [ ] ;
240+
241+ if ( results && results . files && results . files . length > 0 ) {
242+ for ( const file of results . files ) {
243+ for ( const violation of file . violations ) {
244+ const lineNum = violation . beginLine - 1 ; // Convert to 0-based
245+ const range = new vscode . Range (
246+ new vscode . Position ( lineNum , 0 ) ,
247+ new vscode . Position ( lineNum , Number . MAX_VALUE )
248+ ) ;
249+
250+ // Map the priority to severity
251+ let severity : vscode . DiagnosticSeverity ;
252+ switch ( violation . priority ) {
253+ case 1 :
254+ severity = vscode . DiagnosticSeverity . Error ;
255+ break ;
256+ case 2 :
257+ case 3 :
258+ severity = vscode . DiagnosticSeverity . Warning ;
259+ break ;
260+ default :
261+ severity = vscode . DiagnosticSeverity . Information ;
262+ }
263+
264+ const diagnostic = new vscode . Diagnostic (
265+ range ,
266+ `${ violation . description } (${ violation . rule } )` ,
267+ severity
268+ ) ;
269+ diagnostic . source = 'phpmd' ;
270+
271+ // Add rule code and external info URL if available
272+ if ( violation . externalInfoUrl ) {
273+ diagnostic . code = {
274+ value : violation . rule ,
275+ target : vscode . Uri . parse ( violation . externalInfoUrl )
276+ } ;
277+ } else {
278+ diagnostic . code = violation . rule ;
279+ }
280+
281+ diagnostics . push ( diagnostic ) ;
282+ }
283+ }
284+ }
285+
286+ return diagnostics ;
287+ } catch ( error ) {
288+ console . error ( 'Error processing PHPMD output:' , error ) ;
289+ throw error ;
290+ }
291+ } ;
292+
293+ // Process sample output
294+ const diagnostics = processPhpmdResults ( SAMPLE_PHPMD_OUTPUT ) ;
295+
296+ // Check that the first diagnostic has an external info URL
297+ assert . ok ( diagnostics [ 0 ] . code , 'Diagnostic should have a code property' ) ;
298+
299+ // When externalInfoUrl is provided, code should be an object with target
300+ if ( typeof diagnostics [ 0 ] . code === 'object' ) {
301+ assert . strictEqual (
302+ ( diagnostics [ 0 ] . code as any ) . value ,
303+ 'ExcessiveParameterList' ,
304+ 'Code value should match the rule name'
305+ ) ;
306+ assert . ok (
307+ ( diagnostics [ 0 ] . code as any ) . target instanceof vscode . Uri ,
308+ 'Code target should be a VS Code URI'
309+ ) ;
310+ assert . strictEqual (
311+ ( diagnostics [ 0 ] . code as any ) . target . toString ( ) ,
312+ 'https://phpmd.org/rules/codesize.html#excessiveparameterlist' ,
313+ 'URI should match the external info URL'
314+ ) ;
315+ } else {
316+ assert . fail ( 'Code should be an object with target property when externalInfoUrl is available' ) ;
317+ }
318+
319+ // Ensure the second diagnostic also has the correct code
320+ if ( typeof diagnostics [ 1 ] . code === 'object' ) {
321+ assert . strictEqual ( ( diagnostics [ 1 ] . code as any ) . value , 'ShortVariable' ) ;
322+ assert . strictEqual (
323+ ( diagnostics [ 1 ] . code as any ) . target . toString ( ) ,
324+ 'https://phpmd.org/rules/naming.html#shortvariable'
325+ ) ;
326+ } else {
327+ assert . fail ( 'Second diagnostic should also have code object with target' ) ;
328+ }
329+ } ) ;
221330} ) ;
0 commit comments