4747import com .microsoft .java .debug .core .protocol .Requests .Arguments ;
4848import com .microsoft .java .debug .core .protocol .Requests .Command ;
4949import com .microsoft .java .debug .core .protocol .Requests .VariablesArguments ;
50+ import com .microsoft .java .debug .core .protocol .Types .VariablePresentationHint ;
5051import com .microsoft .java .debug .core .protocol .Responses ;
5152import com .microsoft .java .debug .core .protocol .Types ;
5253import com .sun .jdi .AbsentInformationException ;
@@ -94,6 +95,15 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
9495 }
9596
9697 VariableProxy containerNode = (VariableProxy ) container ;
98+
99+ if (containerNode .isLazyVariable () && DebugSettings .getCurrent ().showToString ) {
100+ Types .Variable typedVariable = this .resolveLazyVariable (context , containerNode , variableFormatter , options , evaluationEngine );
101+ if (typedVariable != null ) {
102+ list .add (typedVariable );
103+ response .body = new Responses .VariablesResponseBody (list );
104+ return CompletableFuture .completedFuture (response );
105+ }
106+ }
97107 List <Variable > childrenList = new ArrayList <>();
98108 IStackFrameManager stackFrameManager = context .getStackFrameManager ();
99109 String containerEvaluateName = containerNode .getEvaluateName ();
@@ -266,10 +276,9 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
266276 }
267277 }
268278
269- int referenceId = 0 ;
279+ VariableProxy varProxy = null ;
270280 if (indexedVariables > 0 || (indexedVariables < 0 && value instanceof ObjectReference )) {
271- VariableProxy varProxy = new VariableProxy (containerNode .getThread (), containerNode .getScope (), value , containerNode , evaluateName );
272- referenceId = context .getRecyclableIdPool ().addObject (containerNode .getThreadId (), varProxy );
281+ varProxy = new VariableProxy (containerNode .getThread (), containerNode .getScope (), value , containerNode , evaluateName );
273282 varProxy .setIndexedVariable (indexedVariables >= 0 );
274283 varProxy .setUnboundedType (javaVariable .isUnboundedType ());
275284 }
@@ -296,26 +305,38 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
296305 typeString = "" ;
297306 }
298307
299- Types .Variable typedVariables = new Types .Variable (name , valueString , typeString , referenceId , evaluateName );
300- typedVariables .indexedVariables = Math .max (indexedVariables , 0 );
301-
302308 String detailsValue = null ;
303309 if (hasErrors ) {
304310 // If failed to resolve the variable value, skip the details info as well.
305311 } else if (sizeValue != null ) {
306312 detailsValue = "size=" + variableFormatter .valueToString (sizeValue , options );
307313 } else if (DebugSettings .getCurrent ().showToString ) {
308- try {
309- detailsValue = VariableDetailUtils .formatDetailsValue (value , containerNode .getThread (), variableFormatter , options , evaluationEngine );
310- } catch (OutOfMemoryError e ) {
311- logger .log (Level .SEVERE , "Failed to compute the toString() value of a large object" , e );
312- detailsValue = "<Unable to display the details of a large object>" ;
313- } catch (Exception e ) {
314- logger .log (Level .SEVERE , "Failed to compute the toString() value" , e );
315- detailsValue = "<Failed to resolve the variable details due to \" " + e .getMessage () + "\" >" ;
314+ if (VariableDetailUtils .isLazyLoadingSupported (value ) && varProxy != null ) {
315+ varProxy .setLazyVariable (true );
316+ } else {
317+ try {
318+ detailsValue = VariableDetailUtils .formatDetailsValue (value , containerNode .getThread (), variableFormatter , options , evaluationEngine );
319+ } catch (OutOfMemoryError e ) {
320+ logger .log (Level .SEVERE , "Failed to compute the toString() value of a large object" , e );
321+ detailsValue = "<Unable to display the details of a large object>" ;
322+ } catch (Exception e ) {
323+ logger .log (Level .SEVERE , "Failed to compute the toString() value" , e );
324+ detailsValue = "<Failed to resolve the variable details due to \" " + e .getMessage () + "\" >" ;
325+ }
316326 }
317327 }
318328
329+ int referenceId = 0 ;
330+ if (varProxy != null ) {
331+ referenceId = context .getRecyclableIdPool ().addObject (containerNode .getThreadId (), varProxy );
332+ }
333+
334+ Types .Variable typedVariables = new Types .Variable (name , valueString , typeString , referenceId , evaluateName );
335+ typedVariables .indexedVariables = Math .max (indexedVariables , 0 );
336+ if (varProxy != null && varProxy .isLazyVariable ()) {
337+ typedVariables .presentationHint = new VariablePresentationHint (true );
338+ }
339+
319340 if (detailsValue != null ) {
320341 typedVariables .value = typedVariables .value + " " + detailsValue ;
321342 }
@@ -331,6 +352,25 @@ public CompletableFuture<Response> handle(Command command, Arguments arguments,
331352 return CompletableFuture .completedFuture (response );
332353 }
333354
355+ private Types .Variable resolveLazyVariable (IDebugAdapterContext context , VariableProxy containerNode , IVariableFormatter variableFormatter ,
356+ Map <String , Object > options , IEvaluationProvider evaluationEngine ) {
357+ VariableProxy valueReferenceProxy = new VariableProxy (containerNode .getThread (), containerNode .getScope (),
358+ containerNode .getProxiedVariable (), null /** container */ , containerNode .getEvaluateName ());
359+ valueReferenceProxy .setIndexedVariable (containerNode .isIndexedVariable ());
360+ valueReferenceProxy .setUnboundedType (containerNode .isUnboundedType ());
361+ int referenceId = context .getRecyclableIdPool ().addObject (containerNode .getThreadId (), valueReferenceProxy );
362+ // this proxiedVariable is intermediate object, see https://github.com/microsoft/vscode/issues/135147#issuecomment-1076240074
363+ Object proxiedVariable = containerNode .getProxiedVariable ();
364+ if (proxiedVariable instanceof ObjectReference ) {
365+ ObjectReference variable = (ObjectReference ) proxiedVariable ;
366+ String valueString = variableFormatter .valueToString (variable , options );
367+ String detailString = VariableDetailUtils .formatDetailsValue (variable , containerNode .getThread (), variableFormatter , options ,
368+ evaluationEngine );
369+ return new Types .Variable ("" , valueString + " " + detailString , "" , referenceId , containerNode .getEvaluateName ());
370+ }
371+ return null ;
372+ }
373+
334374 private Set <String > getDuplicateNames (Collection <String > list ) {
335375 Set <String > result = new HashSet <>();
336376 Set <String > set = new HashSet <>();
0 commit comments