Skip to main content
summaryrefslogtreecommitdiffstats
blob: 167dd3f6d5a9f8fed3d4b08bc20796ef9e537854 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
/*******************************************************************************
 * Copyright (c) 2006 IBM Corporation 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:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.debug.internal.ui.model.elements;

import java.util.ArrayList;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILogicalStructureType;
import org.eclipse.debug.core.model.IDebugElement;
import org.eclipse.debug.core.model.IIndexedValue;
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.debug.internal.ui.views.variables.IndexedVariablePartition;
import org.eclipse.debug.internal.ui.views.variables.VariablesView;
import org.eclipse.debug.ui.IDebugUIConstants;

/**
 * @since 3.3
 */
public class VariableContentProvider extends ElementContentProvider {

	/* (non-Javadoc)
	 * @see org.eclipse.debug.internal.ui.viewers.model.provisional.elements.ElementContentProvider#getChildCount(java.lang.Object, org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext)
	 */
	protected int getChildCount(Object element, IPresentationContext context) throws CoreException {
		return getAllChildren(element, context).length;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.internal.ui.viewers.model.provisional.elements.ElementContentProvider#getChildren(java.lang.Object, int, int, org.eclipse.debug.internal.ui.viewers.provisional.IPresentationContext)
	 */
	protected Object[] getChildren(Object parent, int index, int length, IPresentationContext context) throws CoreException {
		return getElements(getAllChildren(parent, context), index, length);
	}
	
	protected Object[] getAllChildren(Object parent, IPresentationContext context) throws CoreException {
        IVariable variable = (IVariable) parent;
        IValue value = variable.getValue();
        if (value != null) {
            return getValueChildren(variable, value, context);
        }
        return EMPTY;		
	}

	/* (non-Javadoc)
	 * @see org.eclipse.debug.internal.ui.viewers.model.provisional.elements.ElementContentProvider#supportsContextId(java.lang.String)
	 */
	protected boolean supportsContextId(String id) {
		 return id.equals(IDebugUIConstants.ID_EXPRESSION_VIEW) || id.equals(IDebugUIConstants.ID_VARIABLE_VIEW) || id.equals(IDebugUIConstants.ID_REGISTER_VIEW);
	}
	
    /**
     * Return whether to show compute a logical structure or a raw structure
     * in the specified context
     * 
     * @return whether to show compute a logical structure or a raw structure
     * in the specified context
     */
    protected boolean isShowLogicalStructure(IPresentationContext context) {
    	Boolean show = (Boolean) context.getProperty(VariablesView.PRESENTATION_SHOW_LOGICAL_STRUCTURES);
    	return show != null && show.booleanValue();
    }

    /**
     * Returns the number of entries that should be displayed in each partition
     * of an indexed collection.
     * 
     * @return the number of entries that should be displayed in each partition
     *         of an indexed collection
     */
    protected int getArrayPartitionSize() {
        // TODO: should fix this with a user preference
        return 100;
    }	
    
    /**
     * Returns any logical value for the raw value in the specified context
     * 
     * @param value
     * @param context
     * @return
     */
    protected IValue getLogicalValue(IValue value, IPresentationContext context) {
        return getLogicalValue(value, new ArrayList(), context);
    }
    
    /**
     * Returns children for the given value, creating array partitions if
     * required
     * 
     * @param parent expression or variable containing the given value
     * @param value the value to retrieve children for
     * @param context the context in which children have been requested
     * @return children for the given value, creating array partitions if
     *         required
     * @throws CoreException
     */
    protected Object[] getValueChildren(IDebugElement parent, IValue value, IPresentationContext context) throws CoreException {
        if (value == null) {
            return EMPTY;
        }
        IValue logicalValue = getLogicalValue(value, context);
        if (logicalValue instanceof IIndexedValue) {
            IIndexedValue indexedValue = (IIndexedValue) logicalValue;
            int partitionSize = computeParitionSize(indexedValue);
            if (partitionSize > 1) {
                int offset = indexedValue.getInitialOffset();
                int length = indexedValue.getSize();
                int numPartitions = length / partitionSize;
                int remainder = length % partitionSize;
                if (remainder > 0) {
                    numPartitions++;
                }
                IVariable[] partitions = new IVariable[numPartitions];
                for (int i = 0; i < (numPartitions - 1); i++) {
                    partitions[i] = new IndexedVariablePartition(parent, indexedValue, offset, partitionSize);
                    offset = offset + partitionSize;
                }
                if (remainder == 0) {
                    remainder = partitionSize;
                }
                partitions[numPartitions - 1] = new IndexedVariablePartition(parent, indexedValue, offset, remainder);
                return partitions;
            }
        }
        if (logicalValue == null) {
            // safeguard against an structure type returning null
            logicalValue = value;
        }
        return logicalValue.getVariables();
    }

    /**
     * Returns the partition size to use for the given indexed value. The
     * partition size is computed by determining the number of levels that an
     * indexed collection must be nested in order to partition the collection
     * sub-collections of the preferred partition size.
     * 
     * @param value
     *            indexed value
     * @return size of paritions the value should be subdivided into
     */
    protected int computeParitionSize(IIndexedValue value) {
        int partitionSize = 1;
        try {
            int length = value.getSize();
            int partitionDepth = 0;
            int preferredSize = getArrayPartitionSize();
            int remainder = length % preferredSize;
            length = length / preferredSize;
            while (length > 0) {
                if (remainder == 0 && length == 1) {
                    break;
                }
                partitionDepth++;
                remainder = length % preferredSize;
                length = length / preferredSize;
            }
            for (int i = 0; i < partitionDepth; i++) {
                partitionSize = partitionSize * preferredSize;
            }
        } catch (DebugException e) {
        }
        return partitionSize;
    }    
    
    /**
     * Returns any logical value for the raw value. This method will recurse
     * over the returned value until the same structure is encountered again (to
     * avoid infinite recursion).
     * 
     * @param value
     * @param previousStructureIds
     *            the list of logical structures that have already been applied
     *            to the returned value during the recursion of this method.
     *            Callers should always pass in a new, empty list.
     * @return
     */
    protected IValue getLogicalValue(IValue value, List previousStructureIds, IPresentationContext context) {
        if (isShowLogicalStructure(context)) {
            ILogicalStructureType[] types = DebugPlugin.getLogicalStructureTypes(value);
            if (types.length > 0) {
                ILogicalStructureType type = DebugPlugin.getDefaultStructureType(types);
                if (type != null && !previousStructureIds.contains(type.getId())) {
                    try {
                        value = type.getLogicalStructure(value);
                        previousStructureIds.add(type.getId());
                        return getLogicalValue(value, previousStructureIds, context);
                    } catch (CoreException e) {
                        // unable to display logical structure
                    }
                }
            }
        }
        return value;
    }    
}

Back to the top