@@ -85,46 +85,41 @@ export namespace CopilotHelper {
8585 Commands . JAVA_PROJECT_GET_IMPORT_CLASS_CONTENT ,
8686 normalizedUri
8787 ) as Promise < IImportClassContentResult > ;
88+
89+ // Build promises array for race condition
90+ // Note: Client-side timeout is NECESSARY even if backend has timeout because:
91+ // 1. Network delays may prevent backend response from arriving
92+ // 2. Process hangs won't trigger backend timeout
93+ // 3. Command dispatch failures need to be caught
94+ const promises : Promise < IImportClassContentResult > [ ] = [
95+ commandPromise ,
96+ new Promise < IImportClassContentResult > ( ( _ , reject ) => {
97+ setTimeout ( ( ) => {
98+ reject ( new Error ( ErrorMessage . OperationTimedOut ) ) ;
99+ } , 80 ) ; // 80ms client-side timeout (independent of backend timeout)
100+ } )
101+ ] ;
102+
103+ // Add cancellation promise if token provided
88104 if ( cancellationToken ) {
89- const result = await Promise . race ( [
90- commandPromise ,
105+ promises . push (
91106 new Promise < IImportClassContentResult > ( ( _ , reject ) => {
92107 cancellationToken . onCancellationRequested ( ( ) => {
93108 reject ( new Error ( ErrorMessage . OperationCancelled ) ) ;
94109 } ) ;
95- } ) ,
96- new Promise < IImportClassContentResult > ( ( _ , reject ) => {
97- setTimeout ( ( ) => {
98- reject ( new Error ( ErrorMessage . OperationTimedOut ) ) ;
99- } , 80 ) ; // 80ms timeout
100- } )
101- ] ) ;
102- if ( ! result ) {
103- return {
104- classInfoList : [ ] ,
105- emptyReason : EmptyReason . CommandNullResult ,
106- isEmpty : true
107- } ;
108- }
109- return result ;
110- } else {
111- const result = await Promise . race ( [
112- commandPromise ,
113- new Promise < IImportClassContentResult > ( ( _ , reject ) => {
114- setTimeout ( ( ) => {
115- reject ( new Error ( ErrorMessage . OperationTimedOut ) ) ;
116- } , 80 ) ; // 80ms timeout
117110 } )
118- ] ) ;
119- if ( ! result ) {
120- return {
121- classInfoList : [ ] ,
122- emptyReason : EmptyReason . CommandNullResult ,
123- isEmpty : true
124- } ;
125- }
126- return result ;
111+ ) ;
112+ }
113+
114+ const result = await Promise . race ( promises ) ;
115+ if ( ! result ) {
116+ return {
117+ classInfoList : [ ] ,
118+ emptyReason : EmptyReason . CommandNullResult ,
119+ isEmpty : true
120+ } ;
127121 }
122+ return result ;
128123 } catch ( error : any ) {
129124 if ( error . message === ErrorMessage . OperationCancelled ) {
130125 return {
@@ -194,46 +189,40 @@ export namespace CopilotHelper {
194189 normalizedUri
195190 ) as Promise < IProjectDependenciesResult > ;
196191
192+ // Build promises array for race condition
193+ // Note: Client-side timeout is NECESSARY even if backend has timeout because:
194+ // 1. Network delays may prevent backend response from arriving
195+ // 2. Process hangs won't trigger backend timeout
196+ // 3. Command dispatch failures need to be caught
197+ const promises : Promise < IProjectDependenciesResult > [ ] = [
198+ commandPromise ,
199+ new Promise < IProjectDependenciesResult > ( ( _ , reject ) => {
200+ setTimeout ( ( ) => {
201+ reject ( new Error ( ErrorMessage . OperationTimedOut ) ) ;
202+ } , 40 ) ; // 40ms client-side timeout (independent of backend timeout)
203+ } )
204+ ] ;
205+
206+ // Add cancellation promise if token provided
197207 if ( cancellationToken ) {
198- const result = await Promise . race ( [
199- commandPromise ,
208+ promises . push (
200209 new Promise < IProjectDependenciesResult > ( ( _ , reject ) => {
201210 cancellationToken . onCancellationRequested ( ( ) => {
202211 reject ( new Error ( ErrorMessage . OperationCancelled ) ) ;
203212 } ) ;
204- } ) ,
205- new Promise < IProjectDependenciesResult > ( ( _ , reject ) => {
206- setTimeout ( ( ) => {
207- reject ( new Error ( ErrorMessage . OperationTimedOut ) ) ;
208- } , 40 ) ; // 40ms timeout
209- } )
210- ] ) ;
211- if ( ! result ) {
212- return {
213- dependencyInfoList : [ ] ,
214- emptyReason : EmptyReason . CommandNullResult ,
215- isEmpty : true
216- } ;
217- }
218- return result ;
219- } else {
220- const result = await Promise . race ( [
221- commandPromise ,
222- new Promise < IProjectDependenciesResult > ( ( _ , reject ) => {
223- setTimeout ( ( ) => {
224- reject ( new Error ( ErrorMessage . OperationTimedOut ) ) ;
225- } , 40 ) ; // 40ms timeout
226213 } )
227- ] ) ;
228- if ( ! result ) {
229- return {
230- dependencyInfoList : [ ] ,
231- emptyReason : EmptyReason . CommandNullResult ,
232- isEmpty : true
233- } ;
234- }
235- return result ;
214+ ) ;
215+ }
216+
217+ const result = await Promise . race ( promises ) ;
218+ if ( ! result ) {
219+ return {
220+ dependencyInfoList : [ ] ,
221+ emptyReason : EmptyReason . CommandNullResult ,
222+ isEmpty : true
223+ } ;
236224 }
225+ return result ;
237226 } catch ( error : any ) {
238227 if ( error . message === ErrorMessage . OperationCancelled ) {
239228 return {
0 commit comments