2 * Copyright 2000-2015 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package org.jetbrains.debugger
18 import com.intellij.xdebugger.frame.XCompositeNode
19 import com.intellij.xdebugger.frame.XValueChildrenList
20 import com.intellij.xdebugger.frame.XValueGroup
21 import org.jetbrains.debugger.values.ObjectValue
22 import org.jetbrains.debugger.values.ValueType
25 internal fun lazyVariablesGroup(variables: ObjectValue, start: Int, end: Int, context: VariableContext) = LazyVariablesGroup(variables, start, end, context)
27 class LazyVariablesGroup(private val value: ObjectValue, private val startInclusive: Int, private val endInclusive: Int, private val context: VariableContext, private val componentType: ValueType? = null, private val sparse: Boolean = true) : XValueGroup(String.format("[%,d \u2026 %,d]", startInclusive, endInclusive)) {
28 override fun computeChildren(node: XCompositeNode) {
29 node.setAlreadySorted(true)
31 val bucketThreshold = XCompositeNode.MAX_CHILDREN_TO_SHOW
32 if (!sparse && endInclusive - startInclusive > bucketThreshold) {
33 node.addChildren(XValueChildrenList.topGroups(computeNotSparseGroups(value, context, startInclusive, endInclusive + 1, bucketThreshold)), true)
37 value.getIndexedProperties(startInclusive, endInclusive + 1, bucketThreshold, object : VariableView.ObsolescentIndexedVariablesConsumer(node) {
38 override fun consumeRanges(ranges: IntArray?) {
40 val groupList = XValueChildrenList()
41 addGroups(value, ::lazyVariablesGroup, groupList, startInclusive, endInclusive, XCompositeNode.MAX_CHILDREN_TO_SHOW, context)
42 node.addChildren(groupList, true)
45 addRanges(value, ranges, node, context, true)
49 override fun consumeVariables(variables: List<Variable>) {
50 node.addChildren(createVariablesList(variables, context, null), true)
56 fun computeNotSparseGroups(value: ObjectValue, context: VariableContext, _fromInclusive: Int, toExclusive: Int, bucketThreshold: Int): List<XValueGroup> {
57 var fromInclusive = _fromInclusive
58 val size = toExclusive - fromInclusive
59 val bucketSize = Math.pow(bucketThreshold.toDouble(), Math.ceil(Math.log(size.toDouble()) / Math.log(bucketThreshold.toDouble())) - 1).toInt()
60 val groupList = ArrayList<XValueGroup>(Math.ceil((size / bucketSize).toDouble()).toInt())
61 while (fromInclusive < toExclusive) {
62 groupList.add(LazyVariablesGroup(value, fromInclusive, fromInclusive + (Math.min(bucketSize, toExclusive - fromInclusive) - 1), context, ValueType.NUMBER, false))
63 fromInclusive += bucketSize
68 fun addRanges(value: ObjectValue, ranges: IntArray, node: XCompositeNode, context: VariableContext, isLast: Boolean) {
69 val groupList = XValueChildrenList(ranges.size / 2)
73 groupList.addTopGroup(LazyVariablesGroup(value, ranges[i], ranges[i + 1], context))
76 node.addChildren(groupList, isLast)
79 internal fun <T> addGroups(data: T,
80 groupFactory: (data: T, start: Int, end: Int, context: VariableContext) -> XValueGroup,
81 groupList: XValueChildrenList,
85 context: VariableContext) {
87 var to = Math.min(bucketSize, limit)
94 to = from + Math.min(bucketSize, limit - from)
96 // don't create group for only one member
101 groupList.addTopGroup(groupFactory(data, groupFrom, groupTo, context))