Skip to content

Commit 768842c

Browse files
ellahathawayCopilotadamint
authored
Show discovered AppHosts in Aspire pane (#17506)
* Show idle AppHosts in Aspire pane with Run/Debug context menu * Rename view ID from runningAppHosts to appHosts * Rename context key from noRunningAppHosts to noAppHosts * Keep panel visible when stopped AppHost has workspace candidates When an AppHost stops, the noAppHosts context key now considers workspace candidates. This ensures the panel shows idle AppHosts instead of the empty welcome view after a running AppHost is stopped. * Fix noAppHosts assertions: workspace candidates keep panel visible The _updateWorkspaceContext change (0e312f9) added !hasWorkspaceCandidates to the noAppHosts condition, meaning the panel stays visible when idle AppHosts are discovered. Two tests asserted noAppHosts=true after describe exit, but the legacy format candidate is treated as buildable (toAppHostCandidate defaults null status to 'buildable'), so workspace candidates persist and noAppHosts is correctly false. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Make workspace AppHosts expandable with launch actions * Address review feedback for PR #17506 Fix #1: Rename command IDs in package.json menus and walkthrough so they target the new aspire-vscode.runAppHostCommand and aspire-vscode.debugAppHostCommand registrations introduced in this PR. Without this the editor title bar, explorer context menu, and Get Started walkthrough Run/Debug buttons silently no-op. Fix #2: Wrap vscode.debug.startDebugging in try/catch in AppHostLaunchService.launch so a 'false' return value (debug adapter rejected) or thrown error clears the launching state. Otherwise the tree item is stuck showing the 'Starting...' spinner forever and the user cannot retry. Fix #3: Make AspireAppHostTreeProvider.runAppHost async and await launch so launch failures surface via showErrorMessage instead of being dropped as unhandled promise rejections. Fix #4: In workspace mode with multiple candidate AppHost paths, match running AppHosts to candidates by directory equivalence (isMatchingAppHostPath) rather than exact path. This is the same matching used elsewhere in AppHostDataRepository when correlating 'aspire ps' output to candidate paths, so canonicalization differences (case, separators, trailing slashes) no longer cause a running AppHost to display as idle. Fix #5: Introduce aspire.noRunningAppHosts context key so the Open Dashboard palette command is only enabled when at least one AppHost is actually running. Previously the palette appeared when only idle candidates were known and then silently no-oped. Fix #6: Widen the workspaceResources contextValue regex in package.json so the read-only 'Open AppHost Source' and 'Copy AppHost Path' actions appear on bare 'workspaceResources' items, not only on 'workspaceResources:hasAppHost'. The destructive 'Stop AppHost' menu remains gated on :hasAppHost. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: Adam Ratzman <adam@adamratzman.com>
1 parent 12c9980 commit 768842c

16 files changed

Lines changed: 966 additions & 156 deletions

extension/loc/xlf/aspire-vscode.xlf

Lines changed: 20 additions & 17 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

extension/package.json

Lines changed: 87 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -66,30 +66,30 @@
6666
"views": {
6767
"aspire-panel": [
6868
{
69-
"id": "aspire-vscode.runningAppHosts",
70-
"name": "%views.runningAppHosts.name%"
69+
"id": "aspire-vscode.appHosts",
70+
"name": "%views.appHosts.name%"
7171
}
7272
]
7373
},
7474
"viewsWelcome": [
7575
{
76-
"view": "aspire-vscode.runningAppHosts",
77-
"contents": "%views.runningAppHosts.loading%",
76+
"view": "aspire-vscode.appHosts",
77+
"contents": "%views.appHosts.loading%",
7878
"when": "aspire.loading"
7979
},
8080
{
81-
"view": "aspire-vscode.runningAppHosts",
82-
"contents": "%views.runningAppHosts.welcome%",
83-
"when": "aspire.noRunningAppHosts && !aspire.fetchAppHostsError && !aspire.loading && aspire.viewMode != 'global'"
81+
"view": "aspire-vscode.appHosts",
82+
"contents": "%views.appHosts.welcome%",
83+
"when": "aspire.noAppHosts && !aspire.fetchAppHostsError && !aspire.loading && aspire.viewMode != 'global'"
8484
},
8585
{
86-
"view": "aspire-vscode.runningAppHosts",
87-
"contents": "%views.runningAppHosts.globalWelcome%",
88-
"when": "aspire.noRunningAppHosts && !aspire.fetchAppHostsError && !aspire.loading && aspire.viewMode == 'global'"
86+
"view": "aspire-vscode.appHosts",
87+
"contents": "%views.appHosts.globalWelcome%",
88+
"when": "aspire.noAppHosts && !aspire.fetchAppHostsError && !aspire.loading && aspire.viewMode == 'global'"
8989
},
9090
{
91-
"view": "aspire-vscode.runningAppHosts",
92-
"contents": "%views.runningAppHosts.errorWelcome%",
91+
"view": "aspire-vscode.appHosts",
92+
"contents": "%views.appHosts.errorWelcome%",
9393
"when": "aspire.fetchAppHostsError && !aspire.loading"
9494
}
9595
],
@@ -261,8 +261,26 @@
261261
"icon": "$(debug-all)"
262262
},
263263
{
264-
"command": "aspire-vscode.refreshRunningAppHosts",
265-
"title": "%command.refreshRunningAppHosts%",
264+
"command": "aspire-vscode.runAppHostCommand",
265+
"title": "%command.runAppHost%",
266+
"category": "Aspire",
267+
"icon": "$(run-all)"
268+
},
269+
{
270+
"command": "aspire-vscode.debugAppHostCommand",
271+
"title": "%command.debugAppHost%",
272+
"category": "Aspire",
273+
"icon": "$(debug-all)"
274+
},
275+
{
276+
"command": "aspire-vscode.globalRefreshAppHosts",
277+
"title": "%command.globalRefreshAppHosts%",
278+
"category": "Aspire",
279+
"icon": "$(refresh)"
280+
},
281+
{
282+
"command": "aspire-vscode.refreshAppHosts",
283+
"title": "%command.refreshAppHosts%",
266284
"category": "Aspire",
267285
"icon": "$(refresh)"
268286
},
@@ -443,24 +461,24 @@
443461
"menus": {
444462
"explorer/context": [
445463
{
446-
"command": "aspire-vscode.runAppHost",
464+
"command": "aspire-vscode.runAppHostCommand",
447465
"when": "resourceFilename =~ /apphost\\.(cs|ts|js)$/i",
448466
"group": "aspire_actions@1"
449467
},
450468
{
451-
"command": "aspire-vscode.debugAppHost",
469+
"command": "aspire-vscode.debugAppHostCommand",
452470
"when": "resourceFilename =~ /apphost\\.(cs|ts|js)$/i",
453471
"group": "aspire_actions@2"
454472
}
455473
],
456474
"editor/title/run": [
457475
{
458-
"command": "aspire-vscode.runAppHost",
476+
"command": "aspire-vscode.runAppHostCommand",
459477
"when": "(aspire.fileIsAppHost || aspire.workspaceHasAppHost) && aspire.editorSupportsRunDebug",
460478
"group": "navigation@-4"
461479
},
462480
{
463-
"command": "aspire-vscode.debugAppHost",
481+
"command": "aspire-vscode.debugAppHostCommand",
464482
"when": "(aspire.fileIsAppHost || aspire.workspaceHasAppHost) && aspire.editorSupportsRunDebug",
465483
"group": "navigation@-3"
466484
}
@@ -475,7 +493,19 @@
475493
"when": "false"
476494
},
477495
{
478-
"command": "aspire-vscode.refreshRunningAppHosts",
496+
"command": "aspire-vscode.runAppHostCommand",
497+
"when": "false"
498+
},
499+
{
500+
"command": "aspire-vscode.debugAppHostCommand",
501+
"when": "false"
502+
},
503+
{
504+
"command": "aspire-vscode.globalRefreshAppHosts",
505+
"when": "false"
506+
},
507+
{
508+
"command": "aspire-vscode.refreshAppHosts",
479509
"when": "false"
480510
},
481511
{
@@ -582,104 +612,119 @@
582612
"view/title": [
583613
{
584614
"command": "aspire-vscode.switchToGlobalView",
585-
"when": "view == 'aspire-vscode.runningAppHosts' && aspire.viewMode != 'global'",
615+
"when": "view == 'aspire-vscode.appHosts' && aspire.viewMode != 'global'",
586616
"group": "navigation"
587617
},
588618
{
589619
"command": "aspire-vscode.switchToWorkspaceView",
590-
"when": "view == 'aspire-vscode.runningAppHosts' && aspire.viewMode == 'global'",
620+
"when": "view == 'aspire-vscode.appHosts' && aspire.viewMode == 'global'",
591621
"group": "navigation"
592622
},
593623
{
594-
"command": "aspire-vscode.refreshRunningAppHosts",
595-
"when": "view == 'aspire-vscode.runningAppHosts'",
624+
"command": "aspire-vscode.globalRefreshAppHosts",
625+
"when": "view == 'aspire-vscode.appHosts' && aspire.viewMode == 'global'",
626+
"group": "navigation"
627+
},
628+
{
629+
"command": "aspire-vscode.refreshAppHosts",
630+
"when": "view == 'aspire-vscode.appHosts' && aspire.viewMode != 'global'",
596631
"group": "navigation"
597632
}
598633
],
599634
"view/item/context": [
600635
{
601636
"command": "aspire-vscode.openDashboard",
602-
"when": "view == aspire-vscode.runningAppHosts && viewItem =~ /^(appHost$|workspaceResources(:|$))/",
637+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^(appHost$|workspaceResources(:|$))/",
603638
"group": "inline"
604639
},
605640
{
606641
"command": "aspire-vscode.expandAll",
607-
"when": "view == aspire-vscode.runningAppHosts && viewItem =~ /^(appHost$|workspaceResources(:|$))/",
642+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^(appHost$|workspaceResources(:|$))/",
608643
"group": "inline"
609644
},
610645
{
611646
"command": "aspire-vscode.openAppHostSource",
612-
"when": "view == aspire-vscode.runningAppHosts && viewItem =~ /^(appHost$|workspaceResources(:|$))/",
647+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^(appHost$|workspaceResources(:hasAppHost)?|workspaceAppHost)$/",
613648
"group": "1_open@1"
614649
},
650+
{
651+
"command": "aspire-vscode.runAppHost",
652+
"when": "view == aspire-vscode.appHosts && viewItem == workspaceAppHost",
653+
"group": "2_actions@1"
654+
},
655+
{
656+
"command": "aspire-vscode.debugAppHost",
657+
"when": "view == aspire-vscode.appHosts && viewItem == workspaceAppHost",
658+
"group": "2_actions@2"
659+
},
615660
{
616661
"command": "aspire-vscode.stopAppHost",
617-
"when": "view == aspire-vscode.runningAppHosts && viewItem == appHost",
662+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^(appHost$|workspaceResources:hasAppHost)$/",
618663
"group": "2_actions@1"
619664
},
620665
{
621666
"command": "aspire-vscode.copyAppHostPath",
622-
"when": "view == aspire-vscode.runningAppHosts && viewItem == appHost",
667+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^(appHost$|workspaceResources(:hasAppHost)?|workspaceAppHost)$/",
623668
"group": "3_clipboard@1"
624669
},
625670
{
626671
"command": "aspire-vscode.stopResource",
627-
"when": "view == aspire-vscode.runningAppHosts && viewItem =~ /^resource.*:canStop/",
672+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^resource.*:canStop/",
628673
"group": "2_actions@1"
629674
},
630675
{
631676
"command": "aspire-vscode.startResource",
632-
"when": "view == aspire-vscode.runningAppHosts && viewItem =~ /^resource.*:canStart/",
677+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^resource.*:canStart/",
633678
"group": "2_actions@2"
634679
},
635680
{
636681
"command": "aspire-vscode.restartResource",
637-
"when": "view == aspire-vscode.runningAppHosts && viewItem =~ /^resource.*:canRestart/",
682+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^resource.*:canRestart/",
638683
"group": "2_actions@3"
639684
},
640685
{
641686
"command": "aspire-vscode.executeResourceCommand",
642-
"when": "view == aspire-vscode.runningAppHosts && viewItem =~ /^resource(:|$)/",
687+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^resource(:|$)/",
643688
"group": "2_actions@4"
644689
},
645690
{
646691
"command": "aspire-vscode.viewResourceLogs",
647-
"when": "view == aspire-vscode.runningAppHosts && viewItem =~ /^resource(:|$)/",
692+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^resource(:|$)/",
648693
"group": "3_info@1"
649694
},
650695
{
651696
"command": "aspire-vscode.openInExternalBrowser",
652-
"when": "view == aspire-vscode.runningAppHosts && viewItem == endpointUrl",
697+
"when": "view == aspire-vscode.appHosts && viewItem == endpointUrl",
653698
"group": "1_open@1"
654699
},
655700
{
656701
"command": "aspire-vscode.openInIntegratedBrowser",
657-
"when": "view == aspire-vscode.runningAppHosts && viewItem == endpointUrl",
702+
"when": "view == aspire-vscode.appHosts && viewItem == endpointUrl",
658703
"group": "1_open@2"
659704
},
660705
{
661706
"command": "aspire-vscode.copyEndpointUrl",
662-
"when": "view == aspire-vscode.runningAppHosts && viewItem =~ /^endpointUrl/",
707+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^endpointUrl/",
663708
"group": "3_clipboard@1"
664709
},
665710
{
666711
"command": "aspire-vscode.copyResourceName",
667-
"when": "view == aspire-vscode.runningAppHosts && viewItem =~ /^resource(:|$)/",
712+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^resource(:|$)/",
668713
"group": "3_info@2"
669714
},
670715
{
671716
"command": "aspire-vscode.viewAppHostSource",
672-
"when": "view == aspire-vscode.runningAppHosts && viewItem =~ /^(appHost|workspaceResources:hasAppHost)$/",
717+
"when": "view == aspire-vscode.appHosts && viewItem =~ /^(appHost|workspaceResources:hasAppHost)$/",
673718
"group": "1_open@2"
674719
},
675720
{
676721
"command": "aspire-vscode.viewAppHostLogFile",
677-
"when": "view == aspire-vscode.runningAppHosts && viewItem == logFileItem",
722+
"when": "view == aspire-vscode.appHosts && viewItem == logFileItem",
678723
"group": "1_open@1"
679724
},
680725
{
681726
"command": "aspire-vscode.copyLogFilePath",
682-
"when": "view == aspire-vscode.runningAppHosts && viewItem == logFileItem",
727+
"when": "view == aspire-vscode.appHosts && viewItem == logFileItem",
683728
"group": "3_clipboard@1"
684729
}
685730
]
@@ -855,8 +900,8 @@
855900
"markdown": "walkthrough/runApp.md"
856901
},
857902
"completionEvents": [
858-
"onCommand:aspire-vscode.runAppHost",
859-
"onCommand:aspire-vscode.debugAppHost"
903+
"onCommand:aspire-vscode.runAppHostCommand",
904+
"onCommand:aspire-vscode.debugAppHostCommand"
860905
]
861906
},
862907
{

0 commit comments

Comments
 (0)