String (ObjectReference objRef, @Nullable ValueDescriptor descriptor, @Nullable DescriptorLabelListener labelListener) { final ClassRenderer classRenderer = NodeRendererSettings.getInstance().getClassRenderer(); if (objRef instanceof StringReference && !classRenderer.SHOW_STRINGS_TYPE) { return null; } StringBuilder buf = new StringBuilder(); final boolean showConcreteType = !classRenderer.SHOW_DECLARED_TYPE || (!(objRef instanceof StringReference) && !(objRef instanceof ClassObjectReference) && !isEnumConstant(objRef)); if (showConcreteType || classRenderer.SHOW_OBJECT_ID) { //buf.append('{'); if (showConcreteType) { buf.append(classRenderer.renderTypeName(objRef.type().name())); } if (classRenderer.SHOW_OBJECT_ID) { buf.append('@'); if (ApplicationManager.getApplication().isUnitTestMode()) { buf.append("uniqueID"); } else { buf.append(objRef.uniqueID()); } } //buf.append('}'); } if (objRef instanceof ArrayReference) { int idx = buf.indexOf("["); if (idx >= 0) { if (labelListener == null || descriptor == null) { buf.insert(idx + 1, ((ArrayReference)objRef).length()); } else { CompletableFuture<String> asyncId = DebuggerUtilsAsync.length((ArrayReference)objRef) .thenApply(length -> buf.insert(idx + 1, length).toString()); if (asyncId.isDone()) { return asyncId.join(); } else { asyncId.thenAccept(res -> { descriptor.setIdLabel(res); labelListener.labelChanged(); }); } } } } return buf.toString(); }