package com.redhat.ceylon.eclipse.core.debug.presentation;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IValue;
import org.eclipse.debug.internal.ui.DefaultLabelProvider;
import org.eclipse.jdt.debug.core.IJavaArray;
import org.eclipse.jdt.debug.core.IJavaFieldVariable;
import org.eclipse.jdt.debug.core.IJavaObject;
import org.eclipse.jdt.debug.core.IJavaType;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIAllInstancesValue;
import org.eclipse.jdt.internal.debug.core.model.JDILocalVariable;
import org.eclipse.jdt.internal.debug.core.model.JDINullValue;
import org.eclipse.jdt.internal.debug.core.model.JDIReferenceListValue;
import org.eclipse.jdt.internal.debug.ui.DebugUIMessages;
import org.eclipse.jdt.internal.debug.ui.JDIModelPresentation;
import org.eclipse.osgi.util.NLS;
import com.redhat.ceylon.common.JVMModuleUtil;
import com.redhat.ceylon.compiler.java.codegen.Naming;
import com.redhat.ceylon.eclipse.core.debug.DebugUtils;
import com.redhat.ceylon.eclipse.core.debug.presentation.CeylonPresentationContext.PresentationType;
public class CeylonJDIModelPresentation extends JDIModelPresentation {
private static final String ceylonStringTypeName = ceylon.language.String.class.getName();
private static final String ceylonStringValueFieldName = "value";
@Override
public String getValueText(IJavaValue value) throws DebugException {
if (!CeylonPresentationContext.isCeylonContext(value, PresentationType.LABEL)) {
return super.getValueText(value);
}
String refTypeName= value.getReferenceTypeName();
String valueString= value.getValueString();
boolean isString= refTypeName.equals(fgStringName);
if (isString) {
return super.getValueText(value);
}
if (refTypeName.equals(ceylonStringTypeName)) {
isString = true;
IJavaFieldVariable javaStringValueField = ((IJavaObject)value).getField(ceylonStringValueFieldName, false);
if (javaStringValueField != null) {
IValue javaStringValue = javaStringValueField.getValue();
if (javaStringValue != null) {
valueString = javaStringValue.getValueString();
}
}
}
IJavaType type= value.getJavaType();
String signature= null;
if (type != null) {
signature= type.getSignature();
}
if (!isObjectValue(signature)) {
return super.getValueText(value);
}
boolean isArray= value instanceof IJavaArray;
StringBuffer buffer= new StringBuffer();
if (!isString && (refTypeName.length() > 0)) {
// Don't show type name for instances and references
if (!(value instanceof JDIReferenceListValue || value instanceof JDIAllInstancesValue)){
String qualTypeName= getCeylonReifiedTypeName(value);
if (isArray) {
qualTypeName= adjustTypeNameForArrayIndex(qualTypeName, ((IJavaArray)value).getLength());
}
buffer.append(qualTypeName);
buffer.append(' ');
}
}
// Put double quotes around Strings
if (valueString != null && (isString || valueString.length() > 0)) {
if (isString) {
buffer.append('"');
}
buffer.append(DefaultLabelProvider.escapeSpecialChars(valueString));
if (isString) {
buffer.append('"');
if(value instanceof IJavaObject){
buffer.append(" "); //$NON-NLS-1$
buffer.append(NLS.bind(DebugUIMessages.JDIModelPresentation_118, new String[]{String.valueOf(((IJavaObject)value).getUniqueId())}));
}
}
}
return buffer.toString().trim();
}
public String getCeylonReifiedTypeName(IValue value) throws DebugException {
if (value instanceof JDINullValue) {
return "Null";
}
String result = DebugUtils.getTypeName(value, DebugUtils.producedTypeFromInstance);
if(result == null || result.isEmpty()) {
result = getQualifiedName(value.getReferenceTypeName());
}
return result;
}
@Override
public String getVariableText(IJavaVariable var) {
boolean isCeylonContext = CeylonPresentationContext.isCeylonContext(var, PresentationType.LABEL);
String varLabel= DebugUIMessages.JDIModelPresentation_unknown_name__1;
try {
varLabel= var.getName();
if (isCeylonContext) {
varLabel = CeylonJDIModelPresentation.fixVariableName(varLabel,
var instanceof JDILocalVariable,
var.isSynthetic());
}
} catch (DebugException exception) {
}
IJavaValue javaValue= null;
try {
javaValue = (IJavaValue) var.getValue();
} catch (DebugException e1) {
}
boolean showTypes= isShowVariableTypeNames();
StringBuffer buff= new StringBuffer();
String typeName= DebugUIMessages.JDIModelPresentation_unknown_type__2;
try {
typeName= var.getReferenceTypeName();
if (isCeylonContext) {
typeName = CeylonJDIModelPresentation.fixObjectTypeName(typeName);
}
if (showTypes) {
typeName= getQualifiedName(typeName);
}
} catch (DebugException exception) {
}
if (showTypes) {
buff.append(typeName);
buff.append(' ');
}
buff.append(varLabel);
// add declaring type name if required
if (var instanceof IJavaFieldVariable) {
IJavaFieldVariable field = (IJavaFieldVariable)var;
if (isDuplicateName(field)) {
try {
String decl = field.getDeclaringType().getName();
if (isCeylonContext) {
decl = CeylonJDIModelPresentation.fixObjectTypeName(decl);
}
buff.append(NLS.bind(" ({0})", new String[]{getQualifiedName(decl)})); //$NON-NLS-1$
} catch (DebugException e) {
}
}
}
String valueString= getFormattedValueText(javaValue);
//do not put the equal sign for array partitions
if (valueString.length() != 0) {
buff.append("= "); //$NON-NLS-1$
buff.append(valueString);
}
return buff.toString();
}
private final static Pattern localVariablePattern = Pattern.compile("([^$]+)\\$[0-9]+");
public static String fixVariableName(String name, boolean isLocalVariable, boolean isSynthetic) {
if (isSynthetic
&& name.startsWith("val$")) {
name = name.substring(4);
}
if (name.charAt(0) == '$') {
if (JVMModuleUtil.isJavaKeyword(name, 1, name.length())) {
name = name.substring(1);
}
}
if (isLocalVariable || isSynthetic
&& name.contains("$")) {
if(name.endsWith(Naming.Suffix.$param$.name())) {
return name.substring(0, name.length() - Naming.Suffix.$param$.name().length());
}
Matcher matcher = localVariablePattern.matcher(name);
if (matcher.matches()) {
name = matcher.group(1);
}
}
return name;
}
static String fixObjectTypeName(String typeName)
throws DebugException {
if (typeName.isEmpty()) {
return typeName;
}
int index = typeName.lastIndexOf('.');
if (index > 0) {
typeName = typeName.substring(index+1);
}
if (!Character.isUpperCase(typeName.codePointAt(0)) &&
typeName.endsWith("_")) {
typeName = typeName.substring(0, typeName.length() - 1);
}
return typeName;
}
}