package com.jetbrains.actionscript.profiler.calltreetable;
import com.intellij.openapi.util.Pair;
import com.intellij.pom.Navigatable;
import com.intellij.psi.search.GlobalSearchScope;
import com.intellij.util.ArrayUtil;
import com.jetbrains.actionscript.profiler.base.FilePathProducer;
import com.jetbrains.actionscript.profiler.base.FrameInfoProducer;
import com.jetbrains.actionscript.profiler.base.LazyNode;
import com.jetbrains.actionscript.profiler.base.NavigatableDataProducer;
import com.jetbrains.actionscript.profiler.calltree.CallTree;
import com.jetbrains.actionscript.profiler.sampler.FrameInfo;
import com.jetbrains.actionscript.profiler.sampler.Sample;
import com.jetbrains.actionscript.profiler.sampler.SampleLocationResolver;
import com.jetbrains.actionscript.profiler.util.ResolveUtil;
import com.jetbrains.actionscript.profiler.vo.CallInfo;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
public class MergedCallNode<T extends Sample> extends LazyNode implements NavigatableDataProducer, FrameInfoProducer, FilePathProducer {
private final CallTree callTree;
private final FrameInfo[] callFrames;
private final boolean backTrace;
private final GlobalSearchScope scope;
private SampleLocationResolver sampleLocationResolver;
public MergedCallNode(CallInfo callInfo,
CallTree callTree,
FrameInfo[] callFrames,
boolean backTrace,
GlobalSearchScope scope) {
setUserObject(callInfo);
this.callTree = callTree;
this.callFrames = callFrames;
this.backTrace = backTrace;
this.scope = scope;
}
public CallTree getCallTree() {
return callTree;
}
@Nullable
public CallInfo getCallInfo() {
if (getUserObject() instanceof CallInfo) {
return (CallInfo)getUserObject();
}
return null;
}
@Nullable
public FrameInfo getFrameInfo() {
final CallInfo callInfo = getCallInfo();
return callInfo != null ? callInfo.getFrameInfo() : null;
}
@Override
protected void doLoadChildren() {
FrameInfo[] frames = Arrays.copyOf(callFrames, callFrames.length + 1);
frames[frames.length - 1] = getFrameInfo();
Pair<Map<FrameInfo, Long>, Map<FrameInfo, Long>> countMaps;
if (backTrace) {
countMaps = callTree.getCallersTimeMaps(frames);
}
else {
countMaps = callTree.getCalleesTimeMaps(ArrayUtil.reverseArray(frames));
}
final Map<FrameInfo, Long> countMap = countMaps.getFirst();
final Map<FrameInfo, Long> selfCountMap = countMaps.getSecond();
List<FrameInfo> traces = ResolveUtil.filterByScope(countMap.keySet(), scope);
ArrayList<CallInfo> callInfos = new ArrayList<>();
for (final FrameInfo t : traces) {
callInfos.add(new CallInfo(t, countMap.get(t), selfCountMap.get(t)));
}
for (int index = 0; index < callInfos.size(); ++index) {
insert(new MergedCallNode<T>(callInfos.get(index), callTree, frames, backTrace, scope), index);
}
}
@Override
public String toString() {
final FrameInfo frameInfo = getFrameInfo();
return frameInfo != null ? frameInfo.toString() : "";
}
@Override
public Navigatable getNavigatable() {
if (sampleLocationResolver == null) {
sampleLocationResolver = new SampleLocationResolver(getFrameInfo(), scope);
}
return sampleLocationResolver;
}
@Nullable
@Override
public String getFilePath() {
final FrameInfo frameInfo = getFrameInfo();
return frameInfo != null ? frameInfo.getFilePath() : null;
}
}