mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-07-19 06:55:23 +02:00
Applied patch for 209793. Persist the format selection and cast-to-type of variables. Adds a generic mechanism for storing collections of such setting types as a single launch configuration setting. In other words, persisting the format of 10 variables will not result in 10 launch config settings, but rather one.
This commit is contained in:
parent
048b012111
commit
a64cedd926
8 changed files with 522 additions and 21 deletions
|
@ -209,20 +209,32 @@ public class CDebugUtils {
|
|||
* Serializes a XML document into a string - encoded in UTF8 format, with platform line separators.
|
||||
*
|
||||
* @param doc document to serialize
|
||||
* @param indent if the xml text should be indented.
|
||||
*
|
||||
* @return the document as a string
|
||||
*/
|
||||
public static String serializeDocument( Document doc ) throws IOException, TransformerException {
|
||||
public static String serializeDocument( Document doc, boolean indent ) throws IOException, TransformerException {
|
||||
ByteArrayOutputStream s = new ByteArrayOutputStream();
|
||||
TransformerFactory factory = TransformerFactory.newInstance();
|
||||
Transformer transformer = factory.newTransformer();
|
||||
transformer.setOutputProperty( OutputKeys.METHOD, "xml" ); //$NON-NLS-1$
|
||||
transformer.setOutputProperty( OutputKeys.INDENT, "yes" ); //$NON-NLS-1$
|
||||
transformer.setOutputProperty( OutputKeys.INDENT, indent ? "yes" : "no" ); //$NON-NLS-1$
|
||||
DOMSource source = new DOMSource( doc );
|
||||
StreamResult outputTarget = new StreamResult( s );
|
||||
transformer.transform( source, outputTarget );
|
||||
return s.toString( "UTF8" ); //$NON-NLS-1$
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes a XML document into a string - encoded in UTF8 format, with platform line separators.
|
||||
*
|
||||
* @param doc document to serialize
|
||||
* @return the document as a string
|
||||
*/
|
||||
public static String serializeDocument( Document doc ) throws IOException, TransformerException {
|
||||
return serializeDocument(doc, true);
|
||||
}
|
||||
|
||||
public static Number getFloatingPointValue( ICValue value ) {
|
||||
if ( value instanceof CFloatingPointValue ) {
|
||||
try {
|
||||
|
|
|
@ -175,6 +175,12 @@ public interface ICDTLaunchConfigurationConstants {
|
|||
*/
|
||||
public static final String ATTR_DEBUGGER_GLOBAL_VARIABLES = CDT_LAUNCH_ID + ".GLOBAL_VARIABLES"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Launch configuration attribute key. The value is a format list'
|
||||
* memento.
|
||||
*/
|
||||
public static final String ATTR_DEBUGGER_FORMAT = CDT_LAUNCH_ID + ".FORMAT"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Launch configuration attribute key. The value is a memory blocks' memento.
|
||||
*/
|
||||
|
|
|
@ -16,35 +16,41 @@ package org.eclipse.cdt.debug.core.model;
|
|||
public class CVariableFormat {
|
||||
|
||||
private final String fName;
|
||||
private final int fNum;
|
||||
|
||||
private CVariableFormat( String name ) {
|
||||
private CVariableFormat( String name, int num ) {
|
||||
this.fName = name;
|
||||
this.fNum= num;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.fName;
|
||||
}
|
||||
|
||||
public int getFormatNumber() {
|
||||
return this.fNum;
|
||||
}
|
||||
|
||||
public static CVariableFormat getFormat( int code ) {
|
||||
switch( code ) {
|
||||
case 0:
|
||||
if ( code == NATURAL.getFormatNumber() ) {
|
||||
return NATURAL;
|
||||
case 1:
|
||||
} else if ( code == DECIMAL.getFormatNumber() ) {
|
||||
return DECIMAL;
|
||||
case 2:
|
||||
} else if ( code == BINARY.getFormatNumber() ) {
|
||||
return BINARY;
|
||||
case 3:
|
||||
} else if ( code == OCTAL.getFormatNumber() ) {
|
||||
return OCTAL;
|
||||
case 4:
|
||||
} else if ( code == HEXADECIMAL.getFormatNumber() ) {
|
||||
return HEXADECIMAL;
|
||||
default:
|
||||
} else {
|
||||
// unexpected value, mapping to NATURAL
|
||||
return NATURAL;
|
||||
}
|
||||
}
|
||||
|
||||
public static final CVariableFormat NATURAL = new CVariableFormat( "natural" ); //$NON-NLS-1$
|
||||
public static final CVariableFormat DECIMAL = new CVariableFormat( "decimal" ); //$NON-NLS-1$
|
||||
public static final CVariableFormat BINARY = new CVariableFormat( "binary" ); //$NON-NLS-1$
|
||||
public static final CVariableFormat OCTAL = new CVariableFormat( "octal" ); //$NON-NLS-1$
|
||||
public static final CVariableFormat HEXADECIMAL = new CVariableFormat( "hexadecimal" ); //$NON-NLS-1$
|
||||
public static final CVariableFormat NATURAL = new CVariableFormat( "natural", 0 ); //$NON-NLS-1$
|
||||
public static final CVariableFormat DECIMAL = new CVariableFormat( "decimal", 1 ); //$NON-NLS-1$
|
||||
public static final CVariableFormat BINARY = new CVariableFormat( "binary", 2 ); //$NON-NLS-1$
|
||||
public static final CVariableFormat OCTAL = new CVariableFormat( "octal", 3 ); //$NON-NLS-1$
|
||||
public static final CVariableFormat HEXADECIMAL = new CVariableFormat( "hexadecimal", 4 ); //$NON-NLS-1$
|
||||
}
|
||||
|
|
|
@ -0,0 +1,267 @@
|
|||
/*******************************************************************************
|
||||
* Copyright (c) 2007 Freescale Semiconductor and others.
|
||||
* 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:
|
||||
* Freescale Semiconductor - Initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.eclipse.cdt.debug.internal.core;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
|
||||
import org.eclipse.cdt.debug.core.CDebugUtils;
|
||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.debug.internal.core.model.CDebugTarget;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.ILaunchConfiguration;
|
||||
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
|
||||
import org.eclipse.debug.core.model.IDebugTarget;
|
||||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.w3c.dom.Node;
|
||||
import org.w3c.dom.NodeList;
|
||||
import org.xml.sax.InputSource;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Settings manager
|
||||
*
|
||||
* The settings manager stores a set of settings,
|
||||
* (key/value) pairs in the launch configuration so they exist across debug sessions.
|
||||
*
|
||||
* All active settings are stored together in a single configuration entry
|
||||
* (ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_FORMAT).
|
||||
*
|
||||
* Every setting is identified by a string identifier. That string identifier can be used to
|
||||
* store an additional setting, to remove an exiting one or to retrieve a previously stored setting.
|
||||
*
|
||||
* The setting value consists of a String.
|
||||
*
|
||||
* Settings fade out automatically so clients do not necessarily need to delete old settings. This makes it
|
||||
* possible to build the string identifiers with names out of the user application, like function names or
|
||||
* variable names, without the danger of a constantly growing launch configuration.
|
||||
* However it also causes that the settings manager must only be used for configurations and customizations for which
|
||||
* always reasonable defaults exist.
|
||||
*
|
||||
* As cleanup policy the settings manager only keeps a certain number of settings and drops the
|
||||
* least recently used one when more settings are added. The least recently used order is maintained
|
||||
* across debug sessions.
|
||||
*
|
||||
*/
|
||||
|
||||
public class CSettingsManager {
|
||||
|
||||
/**
|
||||
* the name of the XML node for the list
|
||||
*/
|
||||
private static final String CONTENT_LIST = "contentList"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* the name of the XML node for every format entry
|
||||
*/
|
||||
private static final String CONTENT = "content"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* the attribute name used to identify the object to store the content for.
|
||||
*/
|
||||
private static final String ATTR_CONTENT_ID = "id"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* the attribute name of the actual content
|
||||
*/
|
||||
private static final String ATTR_CONTENT_VALUE = "val"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* Number defining how many settings are stored.
|
||||
* Whenever an additional setting is added when there are already MAX_USED_COUNT settings, the
|
||||
* least recently used setting is dropped.
|
||||
*
|
||||
* The actual value is chosen to be high enough for normal use cases, but still low enough to avoid that the launch configuration
|
||||
* gets arbitrarily large
|
||||
*/
|
||||
private static int MAX_ELEMENT_COUNT = 100;
|
||||
|
||||
/**
|
||||
* the map used to actually store the format information
|
||||
* as key String are used, values are of type String too.
|
||||
*
|
||||
* The map automatically is limited to MAX_ELEMENT_COUNT
|
||||
* elements, dropping the least recently used one
|
||||
* when more elements are added.
|
||||
*/
|
||||
private Map fContentMap = new LinkedHashMap(MAX_ELEMENT_COUNT, 0.75f, true) {
|
||||
private static final long serialVersionUID = 1;
|
||||
protected boolean removeEldestEntry(Map.Entry eldest) {
|
||||
return size() > MAX_ELEMENT_COUNT;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* the debug target we store the values for
|
||||
*/
|
||||
private CDebugTarget fDebugTarget;
|
||||
|
||||
/**
|
||||
* Store the value for the given id.
|
||||
* @param id used to identify the information. Different objects/topics should use different identifiers.
|
||||
* @param value content to be stored
|
||||
*/
|
||||
public synchronized void putValue( String id, String value ) {
|
||||
fContentMap.put(id, value);
|
||||
}
|
||||
/**
|
||||
* remove the stored format for the given id.
|
||||
* @param id used to identify the formatting information. Different objects/topics should use different identifiers.
|
||||
*/
|
||||
public synchronized void removeValue( String id ) {
|
||||
fContentMap.remove( id );
|
||||
}
|
||||
|
||||
/** Retrieve the value for the given id.
|
||||
* @param id used to identify the formatting information. Different objects/topics should use different identifiers.
|
||||
* @return returns the entry information for the given id, or null if no such information is available.
|
||||
*/
|
||||
public synchronized String getValue( String id ) {
|
||||
String entry= (String) fContentMap.get( id );
|
||||
return entry;
|
||||
}
|
||||
|
||||
/** constructor.
|
||||
* @param debugTarget
|
||||
*/
|
||||
public CSettingsManager( CDebugTarget debugTarget ) {
|
||||
fDebugTarget = debugTarget;
|
||||
initialize();
|
||||
}
|
||||
|
||||
/** get the string format of the current content.
|
||||
* Only stores entries which have been used in the last MAX_USED_COUNT debug sessions.
|
||||
* @return
|
||||
*/
|
||||
private String getMemento() {
|
||||
Document document = null;
|
||||
try {
|
||||
document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
|
||||
Element node = document.createElement( CONTENT_LIST );
|
||||
document.appendChild( node );
|
||||
Set entrySet = fContentMap.entrySet();
|
||||
Iterator it = entrySet.iterator();
|
||||
while ( it.hasNext() ) {
|
||||
Map.Entry entry= (Map.Entry) it.next();
|
||||
String id= (String)entry.getKey();
|
||||
String value= (String)entry.getValue();
|
||||
Element child = document.createElement( CONTENT );
|
||||
child.setAttribute( ATTR_CONTENT_ID, id );
|
||||
child.setAttribute( ATTR_CONTENT_VALUE, value );
|
||||
node.appendChild( child );
|
||||
}
|
||||
return CDebugUtils.serializeDocument( document, false );
|
||||
}
|
||||
catch( ParserConfigurationException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
catch( IOException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
catch( TransformerException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/** set the current state to the one given by the memento.
|
||||
* @param memento a string representation of the state to be loaded.
|
||||
* @throws CoreException
|
||||
*/
|
||||
private void initializeFromMemento( String memento ) throws CoreException {
|
||||
try {
|
||||
fContentMap.clear();
|
||||
DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
|
||||
StringReader reader = new StringReader( memento );
|
||||
InputSource source = new InputSource( reader );
|
||||
Element root = parser.parse( source ).getDocumentElement();
|
||||
if ( root.getNodeName().equalsIgnoreCase( CONTENT_LIST ) ) {
|
||||
NodeList list = root.getChildNodes();
|
||||
int i = list.getLength() - 1; // backwards to keep least recent access order.
|
||||
for( ; i >= 0; i-- ) {
|
||||
Node node = list.item( i );
|
||||
short type = node.getNodeType();
|
||||
if ( type == Node.ELEMENT_NODE ) {
|
||||
Element elem = (Element)node;
|
||||
if ( elem.getNodeName().equalsIgnoreCase( CONTENT ) ) {
|
||||
String id = elem.getAttribute( ATTR_CONTENT_ID );
|
||||
String value= elem.getAttribute( ATTR_CONTENT_VALUE );
|
||||
if ( id == null || id.length() == 0 ) {
|
||||
DebugPlugin.logMessage( "unexpected entry in CSettingsManager.initializeFromMemento", null ); //$NON-NLS-1$
|
||||
continue;
|
||||
}
|
||||
putValue( id, value );
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
DebugPlugin.logMessage( "unexpected content", null ); //$NON-NLS-1$
|
||||
}
|
||||
catch( ParserConfigurationException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
catch( SAXException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
catch( IOException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* read the stored format from the launch configuration
|
||||
*/
|
||||
private void initialize() {
|
||||
ILaunchConfiguration config = getDebugTarget().getLaunch().getLaunchConfiguration();
|
||||
try {
|
||||
String memento = config.getAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_FORMAT, "" ); //$NON-NLS-1$
|
||||
if ( memento != null && memento.trim().length() != 0 )
|
||||
initializeFromMemento( memento );
|
||||
}
|
||||
catch( CoreException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* store the current content in the launch configuration.
|
||||
*/
|
||||
public synchronized void save() {
|
||||
ILaunchConfiguration config = getDebugTarget().getLaunch().getLaunchConfiguration();
|
||||
try {
|
||||
ILaunchConfigurationWorkingCopy wc = config.getWorkingCopy();
|
||||
wc.setAttribute( ICDTLaunchConfigurationConstants.ATTR_DEBUGGER_FORMAT, getMemento() );
|
||||
wc.doSave();
|
||||
}
|
||||
catch( CoreException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* accessor to the debug target
|
||||
*/
|
||||
IDebugTarget getDebugTarget() {
|
||||
return fDebugTarget;
|
||||
}
|
||||
}
|
|
@ -85,6 +85,7 @@ import org.eclipse.cdt.debug.core.model.IRegisterDescriptor;
|
|||
import org.eclipse.cdt.debug.core.sourcelookup.ICSourceLocator;
|
||||
import org.eclipse.cdt.debug.core.sourcelookup.ISourceLookupChangeListener;
|
||||
import org.eclipse.cdt.debug.internal.core.CBreakpointManager;
|
||||
import org.eclipse.cdt.debug.internal.core.CSettingsManager;
|
||||
import org.eclipse.cdt.debug.internal.core.CGlobalVariableManager;
|
||||
import org.eclipse.cdt.debug.internal.core.CMemoryBlockRetrievalExtension;
|
||||
import org.eclipse.cdt.debug.internal.core.CRegisterManager;
|
||||
|
@ -197,6 +198,11 @@ public class CDebugTarget extends CDebugElement implements ICDebugTarget, ICDIEv
|
|||
*/
|
||||
private CGlobalVariableManager fGlobalVariableManager;
|
||||
|
||||
/**
|
||||
* container for Default format information
|
||||
*/
|
||||
private CSettingsManager fFormatManager;
|
||||
|
||||
/**
|
||||
* The executable binary file associated with this target.
|
||||
*/
|
||||
|
@ -256,6 +262,7 @@ public class CDebugTarget extends CDebugElement implements ICDebugTarget, ICDIEv
|
|||
setRegisterManager( new CRegisterManager( this ) );
|
||||
setBreakpointManager( new CBreakpointManager( this ) );
|
||||
setGlobalVariableManager( new CGlobalVariableManager( this ) );
|
||||
setFormatManager( new CSettingsManager( this ) );
|
||||
setMemoryBlockRetrieval( new CMemoryBlockRetrievalExtension( this ) );
|
||||
initialize();
|
||||
DebugPlugin.getDefault().getLaunchManager().addLaunchListener( this );
|
||||
|
@ -997,6 +1004,7 @@ public class CDebugTarget extends CDebugElement implements ICDebugTarget, ICDIEv
|
|||
getCDISession().getEventManager().removeEventListener( this );
|
||||
DebugPlugin.getDefault().getExpressionManager().removeExpressionListener( this );
|
||||
DebugPlugin.getDefault().getLaunchManager().removeLaunchListener( this );
|
||||
saveFormats();
|
||||
saveGlobalVariables();
|
||||
disposeGlobalVariableManager();
|
||||
disposeModuleManager();
|
||||
|
@ -1436,6 +1444,10 @@ public class CDebugTarget extends CDebugElement implements ICDebugTarget, ICDIEv
|
|||
fGlobalVariableManager.save();
|
||||
}
|
||||
|
||||
protected void saveFormats() {
|
||||
fFormatManager.save();
|
||||
}
|
||||
|
||||
protected void disposeGlobalVariableManager() {
|
||||
fGlobalVariableManager.dispose();
|
||||
}
|
||||
|
@ -1635,6 +1647,14 @@ public class CDebugTarget extends CDebugElement implements ICDebugTarget, ICDIEv
|
|||
fGlobalVariableManager = globalVariableManager;
|
||||
}
|
||||
|
||||
protected CSettingsManager getFormatManager() {
|
||||
return fFormatManager;
|
||||
}
|
||||
|
||||
private void setFormatManager( CSettingsManager formatManager ) {
|
||||
fFormatManager = formatManager;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.eclipse.cdt.debug.core.model.ICDebugTarget#isPostMortem()
|
||||
*/
|
||||
|
|
|
@ -55,6 +55,7 @@ public class CExpression extends CLocalVariable implements IExpression {
|
|||
fText = cdiExpression.getExpressionText();
|
||||
fCDIExpression = cdiExpression;
|
||||
fStackFrame = frame;
|
||||
setInitialFormat();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
|
|
@ -326,6 +326,7 @@ public class CRegister extends CVariable implements ICRegister {
|
|||
protected CRegister( CRegisterGroup parent, IRegisterDescriptor descriptor ) {
|
||||
super( parent, ((CRegisterDescriptor)descriptor).getCDIDescriptor() );
|
||||
setFormat( CVariableFormat.getFormat( CDebugCorePlugin.getDefault().getPluginPreferences().getInt( ICDebugConstants.PREF_DEFAULT_REGISTER_FORMAT ) ) );
|
||||
setInitialFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -334,6 +335,7 @@ public class CRegister extends CVariable implements ICRegister {
|
|||
protected CRegister( CRegisterGroup parent, IRegisterDescriptor descriptor, String message ) {
|
||||
super( parent, ((CRegisterDescriptor)descriptor).getCDIDescriptor(), message );
|
||||
setFormat( CVariableFormat.getFormat( CDebugCorePlugin.getDefault().getPluginPreferences().getInt( ICDebugConstants.PREF_DEFAULT_REGISTER_FORMAT ) ) );
|
||||
setInitialFormat();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
package org.eclipse.cdt.debug.internal.core.model;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
|
||||
import org.eclipse.cdt.debug.core.CDebugCorePlugin;
|
||||
import org.eclipse.cdt.debug.core.ICDTLaunchConfigurationConstants;
|
||||
import org.eclipse.cdt.debug.core.ICDebugConstants;
|
||||
|
@ -30,9 +31,11 @@ import org.eclipse.cdt.debug.core.model.CVariableFormat;
|
|||
import org.eclipse.cdt.debug.core.model.ICDebugElementStatus;
|
||||
import org.eclipse.cdt.debug.core.model.ICType;
|
||||
import org.eclipse.cdt.debug.core.model.ICValue;
|
||||
import org.eclipse.cdt.debug.internal.core.CSettingsManager;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.debug.core.DebugEvent;
|
||||
import org.eclipse.debug.core.DebugException;
|
||||
import org.eclipse.debug.core.DebugPlugin;
|
||||
import org.eclipse.debug.core.model.IValue;
|
||||
|
||||
/**
|
||||
|
@ -101,6 +104,7 @@ public abstract class CVariable extends AbstractCVariable implements ICDIEventLi
|
|||
}
|
||||
fIsEnabled = ( parent instanceof AbstractCValue ) ? ((AbstractCValue)parent).getParentVariable().isEnabled() : !isBookkeepingEnabled();
|
||||
getCDISession().getEventManager().addEventListener( this );
|
||||
setInitialFormat();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -115,6 +119,7 @@ public abstract class CVariable extends AbstractCVariable implements ICDIEventLi
|
|||
fIsEnabled = !isBookkeepingEnabled();
|
||||
setStatus( ICDebugElementStatus.ERROR, MessageFormat.format( CoreModelMessages.getString( "CVariable.1" ), new String[]{ errorMessage } ) ); //$NON-NLS-1$
|
||||
getCDISession().getEventManager().addEventListener( this );
|
||||
setInitialFormat();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -262,6 +267,7 @@ public abstract class CVariable extends AbstractCVariable implements ICDIEventLi
|
|||
*/
|
||||
public void changeFormat( CVariableFormat format ) throws DebugException {
|
||||
setFormat( format );
|
||||
storeFormat( format );
|
||||
resetValue();
|
||||
}
|
||||
|
||||
|
@ -297,6 +303,7 @@ public abstract class CVariable extends AbstractCVariable implements ICDIEventLi
|
|||
// If casting of variable to a type or array causes an error, the status
|
||||
// of the variable is set to "error" and it can't be reset by subsequent castings.
|
||||
resetValue();
|
||||
storeCastToArray( startIndex, length );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,6 +400,7 @@ public abstract class CVariable extends AbstractCVariable implements ICDIEventLi
|
|||
// If casting of variable to a type or array causes an error, the status
|
||||
// of the variable is set to "error" and it can't be reset by subsequent castings.
|
||||
resetValue();
|
||||
storeCast(type);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -412,6 +420,8 @@ public abstract class CVariable extends AbstractCVariable implements ICDIEventLi
|
|||
// If casting of variable to a type or array causes an error, the status
|
||||
// of the variable is set to "error" and it can't be reset by subsequent castings.
|
||||
resetValue();
|
||||
forgetCast();
|
||||
forgetCastToArray();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -621,4 +631,181 @@ public abstract class CVariable extends AbstractCVariable implements ICDIEventLi
|
|||
protected void setName( String name ) {
|
||||
fName = name;
|
||||
}
|
||||
|
||||
protected CSettingsManager getFormatManager() {
|
||||
return ((CDebugTarget) getDebugTarget()).getFormatManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* used to concatenate multiple names to a single identifier
|
||||
*/
|
||||
private final static String NAME_PART_SEPARATOR = "-"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* suffix used to identify format informations
|
||||
*/
|
||||
private final static String FORMAT_SUFFIX = NAME_PART_SEPARATOR + "(format)"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* suffix used to identify cast settings
|
||||
*/
|
||||
private final static String CAST_SUFFIX = NAME_PART_SEPARATOR + "(cast)"; //$NON-NLS-1$
|
||||
|
||||
/**
|
||||
* suffix used to identify cast to array settings
|
||||
*/
|
||||
private final static String CAST_TO_ARRAY_SUFFIX = NAME_PART_SEPARATOR + "(cast_to_array)";
|
||||
|
||||
/** retrieve the identification for this variable.
|
||||
* @return a string identifying this variable, to be used to store settings
|
||||
* @throws DebugException
|
||||
*/
|
||||
String getVariableID() throws DebugException {
|
||||
return getName(); // TODO: better identification if multiple variables have the same name
|
||||
}
|
||||
|
||||
/** helper to generate a string id used to persist the settings.
|
||||
* @param next_obj next object to encode into the id
|
||||
* @param buf contains the id of the part encoded so far.
|
||||
* @throws DebugException
|
||||
*/
|
||||
static private void buildPesistID( CDebugElement next_obj, StringBuffer buf ) throws DebugException {
|
||||
if ( next_obj instanceof CVariable ) {
|
||||
CVariable cVariableParent = (CVariable) next_obj;
|
||||
buf.append( NAME_PART_SEPARATOR );
|
||||
buf.append( cVariableParent.getVariableID() );
|
||||
buildPesistID( cVariableParent.getParent(), buf );
|
||||
} else if ( next_obj instanceof CStackFrame ) {
|
||||
buf.append(NAME_PART_SEPARATOR);
|
||||
// TODO: better identification if multiple functions have the same name (say for static functions)
|
||||
buf.append( ((CStackFrame)next_obj ).getFunction() );
|
||||
} else if ( next_obj instanceof CDebugTarget ) {
|
||||
// global, we use a root NAME_PART_SEPARATOR as indicator of that
|
||||
buf.append( NAME_PART_SEPARATOR );
|
||||
} else if ( next_obj instanceof AbstractCValue ) {
|
||||
// index or indirection.
|
||||
AbstractCValue av = (AbstractCValue) next_obj;
|
||||
buildPesistID( av.getParentVariable(), buf );
|
||||
}
|
||||
}
|
||||
|
||||
/** returns an string used to identify this variable
|
||||
* @return
|
||||
* @throws DebugException
|
||||
*/
|
||||
private final String getPersistID() throws DebugException {
|
||||
StringBuffer id = new StringBuffer();
|
||||
id.append( getVariableID() );
|
||||
buildPesistID( getParent(), id );
|
||||
return id.toString();
|
||||
}
|
||||
|
||||
/** stores the given format
|
||||
* @param format the format to be used for this variable
|
||||
*/
|
||||
protected void storeFormat( CVariableFormat format ) {
|
||||
try {
|
||||
String formatString = Integer.toString( format.getFormatNumber() );
|
||||
|
||||
getFormatManager().putValue( getPersistID() + FORMAT_SUFFIX, formatString );
|
||||
} catch ( DebugException e ) {
|
||||
// if we do not get the name, we use the default format, no reason for the creation to fail too.
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
}
|
||||
|
||||
/** stores the cast information.
|
||||
* @param type the type to be displayed instead
|
||||
*/
|
||||
protected void storeCast( String type ) {
|
||||
try {
|
||||
String id = getPersistID() + CAST_SUFFIX;
|
||||
getFormatManager().putValue( id, type );
|
||||
} catch ( DebugException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
}
|
||||
|
||||
/** drops the cast information.
|
||||
*/
|
||||
protected void forgetCast() {
|
||||
try {
|
||||
String id = getPersistID() + CAST_SUFFIX;
|
||||
getFormatManager().removeValue( id );
|
||||
} catch ( DebugException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
}
|
||||
|
||||
/** stores the cast array information.
|
||||
* @param startIndex the first item to be displayed in the cast array operation
|
||||
* @param length the number of elements to display
|
||||
*/
|
||||
protected void storeCastToArray(int startIndex, int length) {
|
||||
try {
|
||||
// we persist the information in a (startIndex):(Length) format.
|
||||
String content = Integer.toString( startIndex ) + ":" + Integer.toString( length ); //$NON-NLS-1$
|
||||
getFormatManager().putValue( getPersistID() + CAST_TO_ARRAY_SUFFIX, content );
|
||||
} catch ( DebugException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
}
|
||||
|
||||
/** drops previously stored cast array information.
|
||||
*/
|
||||
protected void forgetCastToArray() {
|
||||
try {
|
||||
String id = getPersistID() + CAST_TO_ARRAY_SUFFIX;
|
||||
getFormatManager().removeValue( id );
|
||||
} catch ( DebugException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* restore the format stored previously for this variable.
|
||||
* Only sets explictly retrieved formats in order to maintain defaults.
|
||||
*/
|
||||
protected void setInitialFormat() {
|
||||
try {
|
||||
String persistID= getPersistID();
|
||||
String stringFormat = getFormatManager().getValue( persistID + FORMAT_SUFFIX );
|
||||
if ( stringFormat != null ) {
|
||||
try {
|
||||
CVariableFormat format = CVariableFormat.getFormat( Integer.parseInt( stringFormat ) );
|
||||
setFormat( format );
|
||||
} catch ( NumberFormatException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
}
|
||||
|
||||
if ( canCast() ) {
|
||||
String castString = getFormatManager().getValue( persistID + CAST_SUFFIX );
|
||||
if ( castString != null ) {
|
||||
cast( castString );
|
||||
}
|
||||
}
|
||||
if ( canCastToArray() ) {
|
||||
String castToArrayString = getFormatManager().getValue( persistID + CAST_TO_ARRAY_SUFFIX );
|
||||
if (castToArrayString != null) {
|
||||
int index = castToArrayString.indexOf( ':' );
|
||||
if ( index > 0 ) {
|
||||
try {
|
||||
int beg = Integer.parseInt( castToArrayString.substring( 0, index ) );
|
||||
int num = Integer.parseInt( castToArrayString.substring( index + 1 ) );
|
||||
castToArray( beg, num );
|
||||
} catch ( NumberFormatException e ) {
|
||||
DebugPlugin.log( e );
|
||||
}
|
||||
} else {
|
||||
DebugPlugin.logMessage( "did not find expected : for cast to array", null ); //$NON-NLS-1$
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch ( DebugException e ) {
|
||||
DebugPlugin.log( e );
|
||||
// we drop (and log) the exception here.
|
||||
// even if the initial setup fails, we still want the complete creation to be successful
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue