/*******************************************************************************
* Copyright (c) 2014 Bruno Medeiros and other Contributors.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Bruno Medeiros - initial API and implementation
*******************************************************************************/
package melnorme.lang.ide.debug.ui.viewmodel;
import java.util.Map;
import melnorme.lang.ide.core.LangCore;
import melnorme.utilbox.core.CommonException;
import melnorme.utilbox.misc.StringUtil;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.ErrorLabelText;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.IDebugVMConstants;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.MessagesForDebugVM;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.numberformat.FormattedValueLabelText;
import org.eclipse.cdt.dsf.debug.ui.viewmodel.variable.SyncVariableDataAccess;
import org.eclipse.cdt.dsf.gdb.internal.ui.viewmodel.GdbVariableVMNode;
import org.eclipse.cdt.dsf.mi.service.MIExpressions;
import org.eclipse.cdt.dsf.service.DsfSession;
import org.eclipse.cdt.dsf.ui.viewmodel.datamodel.AbstractDMVMProvider;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelAttribute;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.LabelColumnInfo;
import org.eclipse.cdt.dsf.ui.viewmodel.properties.PropertiesBasedLabelProvider;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.debug.internal.ui.viewers.model.provisional.IElementLabelProvider;
//@SuppressWarnings("restriction")
public class GdbVariableVMNode_Override extends GdbVariableVMNode {
GdbVariableVMNode_Override(AbstractDMVMProvider provider, DsfSession session,
SyncVariableDataAccess syncVariableDataAccess) {
super(provider, session, syncVariableDataAccess);
}
@Override
protected IElementLabelProvider createLabelProvider() {
// Note: beware of changes in the super method:
IElementLabelProvider labelProvider = super.createLabelProvider();
if(labelProvider instanceof PropertiesBasedLabelProvider) { // Shoud be true
PropertiesBasedLabelProvider provider = (PropertiesBasedLabelProvider) labelProvider;
customizeLabelProvider(provider);
}
return labelProvider;
}
/**
* This method modifies CDT's default label provider in two ways:
* See {@link FormattedValueLabelText_Override} and {@link ErrorLabelText_Extension}
*/
protected static void customizeLabelProvider(PropertiesBasedLabelProvider provider) {
LabelColumnInfo columnInfo = provider.getColumnInfo(IDebugVMConstants.COLUMN_ID__VALUE);
LabelAttribute[] labelAttributes = columnInfo.getLabelAttributes();
int preferredIndex = -1;
// Find the best FormattedValueLabelText to replace (the one that would print "details" format)
// this should the one at index 1, according to super.createLabelProvider() in
// org.eclipse.cdt.dsf.ui_2.4.0.201402142303
for (int i = 0; i < labelAttributes.length; i++) {
LabelAttribute labelAttribute = labelAttributes[i];
if(labelAttribute instanceof FormattedValueLabelText) {
preferredIndex = i;
}
if(labelAttribute instanceof ErrorLabelText) {
labelAttributes[i] = new ErrorLabelText_Extension();
}
}
if(preferredIndex != -1) {
labelAttributes[preferredIndex] = new FormattedValueLabelText_Override();
} else {
LangCore.logInternalError(new CommonException(
" Failed to replace CDT's FormattedValueLabelText for the Variables view"));
}
provider.setColumnInfo(IDebugVMConstants.COLUMN_ID__VALUE, new LabelColumnInfo(labelAttributes));
}
/**
* Override parent behaviour: don't add "(Details)" suffix
*/
public static class FormattedValueLabelText_Override extends FormattedValueLabelText {
protected String PROP_ACTIVE_FORMAT = IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT;
protected String PROP_ACTIVE_FORMAT_VALUE = IDebugVMConstants.PROP_FORMATTED_VALUE_ACTIVE_FORMAT_VALUE;
public FormattedValueLabelText_Override() {
}
@Override
protected Object getPropertyValue(String propertyName, IStatus status, Map<String, Object> properties) {
if ( PROP_ACTIVE_FORMAT_VALUE.equals(propertyName) ) {
Object activeFormat = properties.get(PROP_ACTIVE_FORMAT);
if(activeFormat.equals(MIExpressions.DETAILS_FORMAT)){
return properties.get(propertyName);
}
}
return super.getPropertyValue(propertyName, status, properties);
}
}
/**
* Trim certain error messages from the backend.
* TODO: review this with future versions of CDT
*/
public static final class ErrorLabelText_Extension extends ErrorLabelText {
protected static final String[] MESSAGES_TO_TRIM = {
"Cannot access memory at address",
"There is no member named",
};
@Override
protected Object getPropertyValue(String propertyName, IStatus status,
Map<String, Object> properties) {
if (PROP_ERROR_MESSAGE.equals(propertyName)) {
String message = status.getMessage();
if (status.getChildren().length < 2) {
if(message.contains("Error message from debugger back end:")) {
for (String messageToTrim : MESSAGES_TO_TRIM) {
if(message.contains(messageToTrim)) {
message = StringUtil.substringFromMatch(messageToTrim, message);
break;
}
}
}
return replaceNewlines(message);
} else {
StringBuffer buf = new StringBuffer(message);
for (IStatus childStatus : status.getChildren()) {
buf.append(MessagesForDebugVM.ErrorLabelText_Error_message__text_page_break_delimiter);
buf.append( replaceNewlines(childStatus.getMessage()) );
}
return buf.toString();
}
}
return super.getPropertyValue(propertyName, status, properties);
}
protected String replaceNewlines(String message) {
return message.replaceAll("\n",
MessagesForDebugVM.ErrorLabelText_Error_message__text_page_break_delimiter); //$NON-NLS-1$
}
}
}