44 *--------------------------------------------------------------------------------------------*/
55
66import * as vscode from 'vscode' ;
7- import { runningFuncTaskMap , stoppedFuncTasks , type IStoppedFuncTask } from '../funcCoreTools/funcHostTask' ;
8- import { localize } from '../localize' ;
7+ import { runningFuncTaskMap , stoppedFuncTasks } from '../funcCoreTools/funcHostTask' ;
8+ import { HostErrorNode } from './nodes/HostErrorNode' ;
9+ import { HostTaskNode } from './nodes/HostTaskNode' ;
10+ import { NoHostNode } from './nodes/NoHostNode' ;
11+ import { StoppedHostNode } from './nodes/StoppedHostNode' ;
912
10- enum FuncHostDebugContextValue {
11- HostTask = 'azFunc.funcHostDebug.hostTask' ,
12- StoppedHostTask = 'azFunc.funcHostDebug.stoppedHostTask' ,
13- HostError = 'azFunc.funcHostDebug.hostError' ,
14- }
15-
16- type FuncHostDebugNode = INoHostNode | IHostTaskNode | IStoppedHostNode | IHostErrorNode ;
13+ export { getScopeLabel } from './nodes/funcHostDebugUtils' ;
14+ export { HostErrorNode } from './nodes/HostErrorNode' ;
15+ export { HostTaskNode } from './nodes/HostTaskNode' ;
16+ export { StoppedHostNode } from './nodes/StoppedHostNode' ;
1717
18- interface INoHostNode {
19- kind : 'noHost' ;
20- }
21-
22- export interface IHostTaskNode {
23- kind : 'hostTask' ;
24- workspaceFolder : vscode . WorkspaceFolder | vscode . TaskScope ;
25- cwd ?: string ;
26- portNumber : string ;
27- startTime : Date ;
28- }
29-
30- export interface IStoppedHostNode {
31- kind : 'stoppedHost' ;
32- stoppedTask : IStoppedFuncTask ;
33- }
34-
35- export interface IHostErrorNode {
36- kind : 'hostError' ;
37- workspaceFolder : vscode . WorkspaceFolder | vscode . TaskScope ;
38- cwd ?: string ;
39- portNumber : string ;
40- message : string ;
41- }
42-
43- function formatTimestamp ( date : Date ) : string {
44- return date . toLocaleTimeString ( undefined , { hour : '2-digit' , minute : '2-digit' , second : '2-digit' } ) ;
45- }
46-
47- function buildHostTooltip ( opts : { label : string ; scopeLabel : string ; portNumber : string ; startTime : Date ; stopTime ?: Date ; cwd ?: string ; pid ?: number } ) : vscode . MarkdownString {
48- const tooltip = new vscode . MarkdownString ( undefined , true ) ;
49- tooltip . appendMarkdown ( `**${ opts . label } **\n\n` ) ;
50- tooltip . appendMarkdown ( `- ${ localize ( 'funcHostDebug.workspace' , 'Workspace' ) } : ${ opts . scopeLabel } \n` ) ;
51- if ( opts . pid !== undefined ) {
52- tooltip . appendMarkdown ( `- ${ localize ( 'funcHostDebug.pid' , 'PID' ) } : ${ opts . pid } \n` ) ;
53- }
54- tooltip . appendMarkdown ( `- ${ localize ( 'funcHostDebug.port' , 'Port' ) } : ${ opts . portNumber } \n` ) ;
55- tooltip . appendMarkdown ( `- ${ localize ( 'funcHostDebug.started' , 'Started' ) } : ${ opts . startTime . toLocaleString ( ) } \n` ) ;
56- if ( opts . stopTime ) {
57- tooltip . appendMarkdown ( `- ${ localize ( 'funcHostDebug.stopped' , 'Stopped' ) } : ${ opts . stopTime . toLocaleString ( ) } \n` ) ;
58- }
59- if ( opts . cwd ) {
60- tooltip . appendMarkdown ( `- ${ localize ( 'funcHostDebug.cwd' , 'CWD' ) } : ${ opts . cwd } \n` ) ;
61- }
62- return tooltip ;
63- }
64-
65- function getNoHostTreeItem ( ) : vscode . TreeItem {
66- const item = new vscode . TreeItem ( localize ( 'funcHostDebug.noneRunning' , 'No Function Host task is currently running.' ) , vscode . TreeItemCollapsibleState . None ) ;
67- item . description = localize ( 'funcHostDebug.startDebuggingHint' , 'Start debugging (F5) to launch the host.' ) ;
68- item . iconPath = new vscode . ThemeIcon ( 'debug' ) ;
69- return item ;
70- }
71-
72- function getHostErrorTreeItem ( element : IHostErrorNode ) : vscode . TreeItem {
73- const firstLine = element . message . split ( / \r ? \n / ) [ 0 ] . trim ( ) ;
74- const label = firstLine || localize ( 'funcHostDebug.errorDetected' , 'Error detected' ) ;
75-
76- const item = new vscode . TreeItem ( label , vscode . TreeItemCollapsibleState . None ) ;
77- item . iconPath = new vscode . ThemeIcon ( 'error' ) ;
78- item . tooltip = element . message ;
79- item . contextValue = FuncHostDebugContextValue . HostError ;
80- return item ;
81- }
82-
83- function getHostTaskTreeItem ( element : IHostTaskNode ) : vscode . TreeItem {
84- const task = runningFuncTaskMap . get ( element . workspaceFolder , element . cwd ) ;
85- const scopeLabel = typeof element . workspaceFolder === 'object'
86- ? element . workspaceFolder . name
87- : localize ( 'funcHostDebug.globalScope' , 'Global' ) ;
88-
89- const label = `${ scopeLabel } (${ element . portNumber } )` ;
90-
91- const tooltip = buildHostTooltip ( { label, scopeLabel, portNumber : element . portNumber , startTime : element . startTime , cwd : element . cwd , pid : task ?. processId } ) ;
92-
93- const item = new vscode . TreeItem ( label , vscode . TreeItemCollapsibleState . Expanded ) ;
94- item . description = formatTimestamp ( element . startTime ) ;
95- item . tooltip = tooltip ;
96- item . contextValue = FuncHostDebugContextValue . HostTask ;
97- item . iconPath = new vscode . ThemeIcon ( 'server-process' ) ;
98- return item ;
99- }
100-
101- function getStoppedHostTreeItem ( element : IStoppedHostNode ) : vscode . TreeItem {
102- const stopped = element . stoppedTask ;
103- const scopeLabel = typeof stopped . workspaceFolder === 'object'
104- ? stopped . workspaceFolder . name
105- : localize ( 'funcHostDebug.globalScope' , 'Global' ) ;
106-
107- const label = `${ scopeLabel } (${ stopped . portNumber } ) — Stopped` ;
108-
109- const tooltip = buildHostTooltip ( { label, scopeLabel, portNumber : stopped . portNumber , startTime : stopped . startTime , stopTime : stopped . stopTime , cwd : stopped . cwd } ) ;
110-
111- const errorCount = stopped . errorLogs . length ;
112- const item = new vscode . TreeItem ( label , errorCount > 0 ? vscode . TreeItemCollapsibleState . Expanded : vscode . TreeItemCollapsibleState . None ) ;
113- item . description = `${ formatTimestamp ( stopped . startTime ) } → ${ formatTimestamp ( stopped . stopTime ) } ` ;
114- item . tooltip = tooltip ;
115- item . contextValue = FuncHostDebugContextValue . StoppedHostTask ;
116- item . iconPath = new vscode . ThemeIcon ( 'debug-stop' , new vscode . ThemeColor ( 'disabledForeground' ) ) ;
117- return item ;
118- }
18+ export type FuncHostDebugNode = NoHostNode | HostTaskNode | StoppedHostNode | HostErrorNode ;
11919
12020export class FuncHostDebugViewProvider implements vscode . TreeDataProvider < FuncHostDebugNode > {
12121 private readonly _onDidChangeTreeDataEmitter = new vscode . EventEmitter < FuncHostDebugNode | undefined > ( ) ;
@@ -126,50 +26,12 @@ export class FuncHostDebugViewProvider implements vscode.TreeDataProvider<FuncHo
12626 }
12727
12828 public getTreeItem ( element : FuncHostDebugNode ) : vscode . TreeItem {
129- switch ( element . kind ) {
130- case 'noHost' :
131- return getNoHostTreeItem ( ) ;
132- case 'hostError' :
133- return getHostErrorTreeItem ( element ) ;
134- case 'hostTask' :
135- return getHostTaskTreeItem ( element ) ;
136- case 'stoppedHost' :
137- return getStoppedHostTreeItem ( element ) ;
138- default : {
139- // Exhaustive check: if we reach here, the FuncHostDebugNode union is out of sync with this switch.
140- throw new Error ( `Unexpected FuncHostDebugNode kind: ${ ( element as { kind ?: unknown } ) . kind } ` ) ;
141- }
142- }
29+ return element . getTreeItem ( ) ;
14330 }
14431
14532 public async getChildren ( element ?: FuncHostDebugNode ) : Promise < FuncHostDebugNode [ ] > {
146- if ( element ?. kind === 'hostTask' ) {
147- const task = runningFuncTaskMap . get ( element . workspaceFolder , element . cwd ) ;
148- const errors = task ?. errorLogs ?? [ ] ;
149- return errors
150- . slice ( )
151- . reverse ( )
152- . map ( ( message ) : IHostErrorNode => ( {
153- kind : 'hostError' ,
154- workspaceFolder : element . workspaceFolder ,
155- cwd : element . cwd ,
156- portNumber : element . portNumber ,
157- message,
158- } ) ) ;
159- } else if ( element ?. kind === 'stoppedHost' ) {
160- const stopped = element . stoppedTask ;
161- return stopped . errorLogs
162- . slice ( )
163- . reverse ( )
164- . map ( ( message ) : IHostErrorNode => ( {
165- kind : 'hostError' ,
166- workspaceFolder : stopped . workspaceFolder ,
167- cwd : stopped . cwd ,
168- portNumber : stopped . portNumber ,
169- message,
170- } ) ) ;
171- } else if ( element ) {
172- return [ ] ;
33+ if ( element ) {
34+ return element . getChildren ( ) ;
17335 }
17436
17537 const nodes : FuncHostDebugNode [ ] = [ ] ;
@@ -182,19 +44,19 @@ export class FuncHostDebugViewProvider implements vscode.TreeDataProvider<FuncHo
18244 continue ;
18345 }
18446 const cwd = ( t . taskExecution . task . execution as vscode . ShellExecution | undefined ) ?. options ?. cwd ;
185- nodes . push ( { kind : 'hostTask' , workspaceFolder : folder , cwd , portNumber : t . portNumber , startTime : t . startTime } ) ;
47+ nodes . push ( new HostTaskNode ( folder , t . portNumber , t . startTime , cwd ) ) ;
18648 hasRunning = true ;
18749 }
18850 }
18951
19052 // Always show the hint node when no host is actively running.
19153 if ( ! hasRunning ) {
192- nodes . push ( { kind : 'noHost' } ) ;
54+ nodes . push ( new NoHostNode ( ) ) ;
19355 }
19456
19557 // Stopped sessions (already newest-first in the array).
19658 for ( const stopped of stoppedFuncTasks ) {
197- nodes . push ( { kind : 'stoppedHost' , stoppedTask : stopped } ) ;
59+ nodes . push ( new StoppedHostNode ( stopped ) ) ;
19860 }
19961
20062 return nodes ;
0 commit comments