@@ -52,6 +52,22 @@ function getExitCodeStatus(
5252 return Status . WA ;
5353}
5454
55+ function coerceToObject ( data : unknown ) : unknown {
56+ if ( typeof data === 'object' && data !== null ) {
57+ return data ;
58+ }
59+ return { } ;
60+ }
61+ function coerceToArray ( data : unknown ) : unknown [ ] {
62+ const arr = [ ] ;
63+ if ( Array . isArray ( data ) ) {
64+ for ( const obj of data ) {
65+ arr . push ( coerceToObject ( obj ) ) ;
66+ }
67+ }
68+ return arr ;
69+ }
70+
5571export default class extends BaseViewProvider < ProviderMessage , WebviewMessage > {
5672 private _state : Map < number , IState > = new Map ( ) ; // Map also remembers insertion order :D
5773 private _timeLimit = 0 ;
@@ -63,7 +79,7 @@ export default class extends BaseViewProvider<ProviderMessage, WebviewMessage> {
6379 this . loadCurrentFileData ( ) ;
6480 break ;
6581 case ProviderMessageType . NEXT :
66- void this . _run ( this . addTestcaseToFile ( ) , true ) ;
82+ this . _nextTestcase ( ) ;
6783 break ;
6884 case ProviderMessageType . ACTION :
6985 this . _action ( msg ) ;
@@ -101,6 +117,7 @@ export default class extends BaseViewProvider<ProviderMessage, WebviewMessage> {
101117 for ( const id of this . _state . keys ( ) ) {
102118 super . _postMessage ( { type : WebviewMessageType . DELETE , id } ) ;
103119 }
120+ this . _timeLimit = 0 ;
104121 this . _state . clear ( ) ;
105122
106123 const file = vscode . window . activeTextEditor ?. document . fileName ;
@@ -110,22 +127,14 @@ export default class extends BaseViewProvider<ProviderMessage, WebviewMessage> {
110127 }
111128 super . _postMessage ( { type : WebviewMessageType . SHOW , visible : true } ) ;
112129
113- const fileData = super . readStorage ( ) [ file ] ;
114- const data : Partial < IFileData > =
115- typeof fileData === 'object' && fileData !== null ? fileData : { } ;
116- this . _timeLimit = data . timeLimit ?? 0 ;
117-
118- const testcases = Array . isArray ( data . testcases ) ? data . testcases : [ ] ;
130+ const fileData = coerceToObject (
131+ super . readStorage ( ) [ file ] ,
132+ ) as Partial < IFileData > ;
133+ const testcases = coerceToArray ( fileData . testcases ) ;
134+ this . _timeLimit = fileData . timeLimit ?? 0 ;
119135 for ( let i = 0 ; i < testcases . length ; i ++ ) {
120- const testcase : Partial < ITestcase > =
121- testcases [ i ] !== null && typeof testcases [ i ] === 'object'
122- ? ( testcases [ i ] as Partial < ITestcase > )
123- : { } ;
124- this . _state . set (
125- this . _newId ,
126- this . _createTestcaseState ( this . _newId , testcase ) ,
127- ) ;
128- this . _newId ++ ;
136+ const testcase = coerceToObject ( testcases [ i ] ) as Partial < ITestcase > ;
137+ this . _addTestcase ( testcase ) ;
129138 }
130139
131140 super . _postMessage ( {
@@ -149,40 +158,46 @@ export default class extends BaseViewProvider<ProviderMessage, WebviewMessage> {
149158 } ;
150159 } ) ;
151160
152- if ( file === vscode . window . activeTextEditor ?. document . fileName ) {
161+ // biome-ignore lint/style/noNonNullAssertion: Caller guarantees there is an active editor and passes a non-empty string
162+ if ( file === vscode . window . activeTextEditor ! . document . fileName ) {
153163 this . deleteAll ( ) ;
154-
164+ this . _timeLimit = data . timeLimit ;
155165 for ( const testcase of testcases ) {
156- this . addTestcaseToFile ( file , testcase ) ;
166+ this . _addTestcase ( testcase ) ;
157167 }
168+ this . _saveFileData ( ) ;
169+
170+ super . _postMessage ( {
171+ type : WebviewMessageType . INITIAL_STATE ,
172+ timeLimit : data . timeLimit ,
173+ } ) ;
158174 } else {
159- super . writeStorage ( file , testcases ) ;
175+ const fileData : IFileData = {
176+ timeLimit : data . timeLimit ,
177+ testcases,
178+ } ;
179+ super . writeStorage ( file , fileData ) ;
160180 }
161181 }
162182
163- addTestcaseToFile ( file ?: string , testcase ?: ITestcase ) {
164- const pickedFile =
165- file ?? vscode . window . activeTextEditor ?. document . fileName ;
166- if ( ! pickedFile ) {
167- return - 1 ;
168- }
183+ addTestcaseToFile ( file : string , testcase : ITestcase ) {
184+ // used by stress view
169185
170- if ( pickedFile === vscode . window . activeTextEditor ?. document . fileName ) {
171- this . _state . set (
172- this . _newId ,
173- this . _createTestcaseState ( this . _newId , testcase ) ,
174- ) ;
175- this . _saveFileData ( ) ;
176- return this . _newId ++ ;
177- }
178- if ( testcase ) {
179- const fileData = super . readStorage ( ) [ pickedFile ] ;
180- const state = Array . isArray ( fileData ) ? fileData : [ ] ;
181- state . push ( testcase ) ;
182- super . writeStorage ( pickedFile , state ) ;
186+ // biome-ignore lint/style/noNonNullAssertion: Caller guarantees there is an active editor and passes a non-empty string
187+ if ( file === vscode . window . activeTextEditor ! . document . fileName ) {
188+ this . _addTestcase ( testcase ) ;
189+ } else {
190+ const fileData = coerceToObject (
191+ super . readStorage ( ) [ file ] ,
192+ ) as Partial < IFileData > ;
193+ const testcases = coerceToArray ( fileData . testcases ) ;
194+ testcases . push ( testcase ) ;
195+ const data : IFileData = {
196+ timeLimit : fileData . timeLimit ?? 0 ,
197+ testcases,
198+ } ;
199+ super . writeStorage ( file , data ) ;
183200 }
184-
185- return - 1 ;
186201 }
187202
188203 runAll ( ) {
@@ -203,6 +218,10 @@ export default class extends BaseViewProvider<ProviderMessage, WebviewMessage> {
203218 }
204219 }
205220
221+ private _nextTestcase ( ) {
222+ void this . _run ( this . _addTestcase ( ) , true ) ;
223+ }
224+
206225 private _action ( { id, action } : IActionMessage ) {
207226 switch ( action ) {
208227 case Action . RUN :
@@ -262,6 +281,14 @@ export default class extends BaseViewProvider<ProviderMessage, WebviewMessage> {
262281 super . writeStorage ( file , fileData ) ;
263282 }
264283
284+ private _addTestcase ( testcase ?: Partial < ITestcase > ) {
285+ this . _state . set (
286+ this . _newId ,
287+ this . _createTestcaseState ( this . _newId , testcase ) ,
288+ ) ;
289+ return this . _newId ++ ;
290+ }
291+
265292 private _createTestcaseState ( id : number , testcase ?: Partial < ITestcase > ) {
266293 // using partial type to have backward compatibility with old testcases
267294 // create a new testcase in webview and fill it in later
0 commit comments