package com.redhat.ceylon.eclipse.core.debug.presentation; import static com.redhat.ceylon.eclipse.core.debug.DebugUtils.producedTypeFromTypeDescriptor; import static com.redhat.ceylon.eclipse.core.debug.presentation.CeylonJDIModelPresentation.fixVariableName; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.debug.core.DebugException; import org.eclipse.debug.core.model.IValue; import org.eclipse.debug.core.model.IVariable; import org.eclipse.debug.internal.ui.viewers.model.provisional.IPresentationContext; import org.eclipse.jdt.debug.core.IJavaValue; import org.eclipse.jdt.debug.core.IJavaVariable; import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIPlaceholderVariable; import org.eclipse.jdt.internal.debug.core.model.JDIDebugTarget; import org.eclipse.jdt.internal.debug.core.model.JDIFieldVariable; import org.eclipse.jdt.internal.debug.core.model.JDILocalVariable; import org.eclipse.jdt.internal.debug.core.model.JDIValue; import com.redhat.ceylon.compiler.java.codegen.Naming; import com.redhat.ceylon.compiler.java.language.VariableBox; import com.redhat.ceylon.eclipse.core.debug.DebugUtils; public class CeylonContentProviderFilter { public static Object[] filterVariables(Object[] variables, IPresentationContext context) throws DebugException { List<Object> keep = new LinkedList<Object>(); Set<String> localVariableCeylonNames = new HashSet<>(); Map<String, JDIValue> typeParameters = new HashMap<String, JDIValue>(); for (int i = 0; i < variables.length; i++) { boolean filter = false; if (variables[i] instanceof IJavaVariable){ IJavaVariable variable = (IJavaVariable) variables[i]; boolean isLocalVariable = variable instanceof JDILocalVariable; do { String name = variable.getName(); if (name.startsWith(Naming.Prefix.$reified$.toString())) { String typeParameterName = name.substring(Naming.Prefix.$reified$.toString().length()); JDIDebugTarget debugTarget = (JDIDebugTarget) variable.getDebugTarget(); IJavaValue value = (IJavaValue) variable.getValue(); String reifiedTypeName = DebugUtils.getTypeName(value, producedTypeFromTypeDescriptor); if (reifiedTypeName != null) { typeParameters.put(typeParameterName, new JDIValue(debugTarget, debugTarget.getVM().mirrorOf(reifiedTypeName)) { IVariable[] variables = new IVariable[0]; @Override public boolean hasVariables() throws DebugException { return false; } @Override public IVariable[] getVariables() throws DebugException { return variables; } }); } } if (variable.isSynthetic()) { filter = true; break; } String fixedName = fixVariableName(name, isLocalVariable, false); if (fixedName.contains("$")){ filter = true; break; } if (isLocalVariable) { if (!localVariableCeylonNames.contains(fixedName)) { localVariableCeylonNames.add(fixedName); } else { filter = true; break; } } } while (false); } if (!filter){ keep.add(variables[i]); } } for (int i=0; i<keep.size(); i++) { final Object element = keep.get(i); Object replacedVariable = unBoxIfVariableBoxed(element); if (replacedVariable != null) { keep.set(i, replacedVariable); } } if (! typeParameters.isEmpty()) { JDIPlaceholderVariable typeParametersNode = new JDIPlaceholderVariable("Type Parameters", new JDITypeParameterNodeValue(typeParameters)); keep.add(typeParametersNode); } return keep.toArray(new Object[keep.size()]); } public static <Type> Type unBoxIfVariableBoxed(final Type element) throws DebugException { return unBoxIfVariableBoxed(element, ""); } @SuppressWarnings("unchecked") public static <Type> Type unBoxIfVariableBoxed(final Type element, final String namePrefix) throws DebugException { Type replacedVariable = element; if (element instanceof IJavaVariable) { if (VariableBox.class.getName().equals(((IJavaVariable) element).getReferenceTypeName())) { IJavaValue value = (IJavaValue) ((IJavaVariable) element).getValue(); IVariable[] children = value.getVariables(); if (children.length > 0) { for (IVariable child : children) { if (child instanceof JDIFieldVariable) { if ("ref".equals(child.getName())) { JDIFieldVariable refVariable = (JDIFieldVariable) child; replacedVariable = (Type) new JDIFieldVariable( refVariable.getJavaDebugTarget(), refVariable.getField(), refVariable.getObjectReference(), null) { public String getName() throws DebugException { return (namePrefix + fixVariableName(((IJavaVariable) element).getName(), ((IJavaVariable) element).isLocal(), ((IJavaVariable) element).isSynthetic())); } }; break; } } } } } else if (! namePrefix.isEmpty() && element instanceof JDIPlaceholderVariable) { final JDIPlaceholderVariable placeHolderVariable = (JDIPlaceholderVariable) element; IValue value = placeHolderVariable.getValue(); if (value instanceof IJavaValue) replacedVariable = (Type) new JDIPlaceholderVariable( placeHolderVariable.getName(), (IJavaValue) placeHolderVariable.getValue()) { public String getName() { return (namePrefix + fixVariableName(placeHolderVariable.getName(), false, false)); } }; } else if (! namePrefix.isEmpty() && element instanceof JDIFieldVariable) { final JDIFieldVariable fieldVariable = (JDIFieldVariable) element; replacedVariable = (Type) new JDIFieldVariable( fieldVariable.getJavaDebugTarget(), fieldVariable.getField(), fieldVariable.getObjectReference(), null) { public String getName() throws DebugException { return (namePrefix + fixVariableName(fieldVariable.getName(), fieldVariable.isLocal(), fieldVariable.isSynthetic())); } }; } } return replacedVariable; } }