@@ -252,6 +252,7 @@ suite("TreeView E2E Tests", () => {
252252 suite ( "Private Make And Mise Tasks" , ( ) => {
253253 const makeRelativePath = "private-targets/Makefile" ;
254254 const miseRelativePath = "private-targets/mise.toml" ;
255+ const privateDivider = "---------------- private ----------------" ;
255256 const publicLabels = [ "alpha_public" , "zeta_public" ] ;
256257 const privateLabels = [ "_beta_private" , "_omega_private" ] ;
257258
@@ -269,6 +270,19 @@ suite("TreeView E2E Tests", () => {
269270 ) ;
270271 }
271272
273+ async function getFolderChildrenForCategory ( categoryLabel : string , folderLabel : string ) : Promise < CommandTreeItem [ ] > {
274+ const provider = getCommandTreeProvider ( ) ;
275+ const categories = await provider . getChildren ( ) ;
276+ const category = categories . find ( ( item ) => getLabelString ( item . label ) . includes ( categoryLabel ) ) ;
277+ assert . ok ( category !== undefined , `Should find category ${ categoryLabel } ` ) ;
278+
279+ const children = await provider . getChildren ( category ) ;
280+ const folder = children . find ( ( item ) => getLabelString ( item . label ) === folderLabel ) ;
281+ assert . ok ( folder !== undefined , `Should find folder ${ folderLabel } ` ) ;
282+
283+ return await provider . getChildren ( folder ) ;
284+ }
285+
272286 setup ( async function ( ) {
273287 this . timeout ( 15000 ) ;
274288
@@ -321,6 +335,14 @@ suite("TreeView E2E Tests", () => {
321335
322336 const items = await getItemsForFile ( "make" , makeRelativePath ) ;
323337 const labels = items . map ( ( item ) => getLabelString ( item . label ) ) ;
338+ const folderChildren = await getFolderChildrenForCategory ( "Make Targets" , "private-targets" ) ;
339+ const folderLabels = folderChildren . map ( ( item ) => getLabelString ( item . label ) ) ;
340+
341+ assert . deepStrictEqual (
342+ folderLabels ,
343+ [ ...publicLabels , privateDivider , ...privateLabels ] ,
344+ "Make targets should insert a divider between public and _-prefixed private targets"
345+ ) ;
324346
325347 assert . deepStrictEqual (
326348 labels ,
@@ -350,6 +372,14 @@ suite("TreeView E2E Tests", () => {
350372
351373 const items = await getItemsForFile ( "mise" , miseRelativePath ) ;
352374 const labels = items . map ( ( item ) => getLabelString ( item . label ) ) ;
375+ const folderChildren = await getFolderChildrenForCategory ( "Mise Tasks" , "private-targets" ) ;
376+ const folderLabels = folderChildren . map ( ( item ) => getLabelString ( item . label ) ) ;
377+
378+ assert . deepStrictEqual (
379+ folderLabels ,
380+ [ ...publicLabels , privateDivider , ...privateLabels ] ,
381+ "Mise tasks should insert a divider between public and _-prefixed private tasks"
382+ ) ;
353383
354384 assert . deepStrictEqual (
355385 labels ,
@@ -374,4 +404,91 @@ suite("TreeView E2E Tests", () => {
374404 }
375405 } ) ;
376406 } ) ;
407+
408+ suite ( "Make Target Conventions" , ( ) => {
409+ const makeRelativePath = "make-conventions/Makefile" ;
410+ const privateDivider = "---------------- private ----------------" ;
411+
412+ async function getFolderChildrenForCategory ( categoryLabel : string , folderLabel : string ) : Promise < CommandTreeItem [ ] > {
413+ const provider = getCommandTreeProvider ( ) ;
414+ const categories = await provider . getChildren ( ) ;
415+ const category = categories . find ( ( item ) => getLabelString ( item . label ) . includes ( categoryLabel ) ) ;
416+ assert . ok ( category !== undefined , `Should find category ${ categoryLabel } ` ) ;
417+
418+ const children = await provider . getChildren ( category ) ;
419+ const folder = children . find ( ( item ) => getLabelString ( item . label ) === folderLabel ) ;
420+ assert . ok ( folder !== undefined , `Should find folder ${ folderLabel } ` ) ;
421+
422+ return await provider . getChildren ( folder ) ;
423+ }
424+
425+ async function getMakeItemsForFile ( relativePath : string ) : Promise < CommandTreeItem [ ] > {
426+ const provider = getCommandTreeProvider ( ) ;
427+ const items = await collectLeafItems ( provider ) ;
428+ return items . filter (
429+ ( item ) => isCommandItem ( item . data ) && item . data . type === "make" && item . data . filePath . endsWith ( relativePath )
430+ ) ;
431+ }
432+
433+ setup ( async function ( ) {
434+ this . timeout ( 15000 ) ;
435+
436+ writeFile (
437+ makeRelativePath ,
438+ [
439+ ".PHONY: help build _private" ,
440+ "" ,
441+ "aaa_file:" ,
442+ '\t@echo "file target"' ,
443+ "" ,
444+ "help:" ,
445+ '\t@echo "help target"' ,
446+ "" ,
447+ "build:" ,
448+ '\t@echo "build target"' ,
449+ "" ,
450+ "%.o: %.c" ,
451+ '\t@echo "pattern rule"' ,
452+ "" ,
453+ ".DEFAULT:" ,
454+ '\t@echo "special target"' ,
455+ "" ,
456+ "_private:" ,
457+ '\t@echo "private target"' ,
458+ ] . join ( "\n" )
459+ ) ;
460+
461+ await refreshTasks ( ) ;
462+ } ) ;
463+
464+ teardown ( async function ( ) {
465+ this . timeout ( 15000 ) ;
466+ deleteFile ( makeRelativePath ) ;
467+ await refreshTasks ( ) ;
468+ } ) ;
469+
470+ test ( "make help is pinned to the top, phony targets sort before non-phony ones, and special targets stay hidden" , async function ( ) {
471+ this . timeout ( 15000 ) ;
472+
473+ const folderChildren = await getFolderChildrenForCategory ( "Make Targets" , "make-conventions" ) ;
474+ const folderLabels = folderChildren . map ( ( item ) => getLabelString ( item . label ) ) ;
475+ const items = await getMakeItemsForFile ( makeRelativePath ) ;
476+ const labels = items . map ( ( item ) => getLabelString ( item . label ) ) ;
477+
478+ assert . deepStrictEqual (
479+ folderLabels ,
480+ [ "help" , "build" , "aaa_file" , privateDivider , "_private" ] ,
481+ "Make targets should pin help first, prefer phony public targets over non-phony ones, and separate private targets"
482+ ) ;
483+
484+ assert . deepStrictEqual (
485+ labels ,
486+ [ "help" , "build" , "aaa_file" , "_private" ] ,
487+ "Only invokable make targets should remain after hiding special and pattern rules"
488+ ) ;
489+
490+ assert . ok ( ! labels . includes ( "%.o" ) , "Pattern rules should be hidden from Make discovery" ) ;
491+ assert . ok ( ! labels . includes ( ".DEFAULT" ) , "Dot-prefixed special targets should be hidden from Make discovery" ) ;
492+ } ) ;
493+ } ) ;
377494} ) ;
0 commit comments