package org.robotframework.ide.eclipse.main.plugin.debug.utils; import java.util.Map; import org.eclipse.debug.core.model.IStackFrame; import org.robotframework.ide.eclipse.main.plugin.debug.model.RobotStackFrame; import org.robotframework.ide.eclipse.main.plugin.debug.model.RobotThread; public class RobotDebugStackFrameManager { private boolean hasStackFramesCreated; private IStackFrame[] stackFrames; private RobotThread thread; public RobotDebugStackFrameManager(final RobotThread thread) { this.thread = thread; } public IStackFrame[] getStackFrames(final Map<String, KeywordContext> currentKeywordsContextMap) { if (!hasStackFramesCreated) { if (!hasVariablesInitialized(currentKeywordsContextMap)) { if (stackFrames != null) { return stackFrames; } return new IStackFrame[0]; } int numberOfStackFramesToCopy = countNumberOfStackFramesToCopy(currentKeywordsContextMap); initStackFrameArray(currentKeywordsContextMap); final IStackFrame[] newStackFrames = new IStackFrame[currentKeywordsContextMap.size()]; int currentKeywordsCounter = 1; for (final String keywordName : currentKeywordsContextMap.keySet()) { final KeywordContext keywordContext = currentKeywordsContextMap.get(keywordName); // only the highest level of StackFrames is created, lower levels are copied from // previous StackFrames final int lowestStackFrameLevel = currentKeywordsContextMap.size() - currentKeywordsCounter; if (currentKeywordsCounter > numberOfStackFramesToCopy) { if (shouldSetupExistingStackFrame(currentKeywordsContextMap, lowestStackFrameLevel)) { ((RobotStackFrame) stackFrames[lowestStackFrameLevel]).setStackFrameData( currentKeywordsCounter, keywordName, keywordContext); newStackFrames[lowestStackFrameLevel] = stackFrames[lowestStackFrameLevel]; } else { newStackFrames[lowestStackFrameLevel] = new RobotStackFrame(thread, currentKeywordsCounter, keywordName, keywordContext); } } else { IStackFrame previousStackFrame = extractPreviousStackFrame(currentKeywordsContextMap, numberOfStackFramesToCopy, currentKeywordsCounter); if(previousStackFrame == null) return new IStackFrame[0]; ((RobotStackFrame) previousStackFrame).setStackFrameData(currentKeywordsCounter, keywordName, keywordContext); newStackFrames[lowestStackFrameLevel] = previousStackFrame; } currentKeywordsCounter++; } stackFrames = newStackFrames; hasStackFramesCreated = true; } return stackFrames; } private boolean hasVariablesInitialized(final Map<String, KeywordContext> currentKeywordsContextMap) { if (currentKeywordsContextMap != null && !currentKeywordsContextMap.isEmpty()) { final KeywordContext lastKeywordContext = (KeywordContext) currentKeywordsContextMap.values().toArray()[currentKeywordsContextMap.size() - 1]; return lastKeywordContext.getVariables() != null; } return false; } private int countNumberOfStackFramesToCopy(final Map<String, KeywordContext> currentKeywordsContextMap) { int numberOfStackTracesToCopy = 0; if (stackFrames != null) { if (stackFrames.length < currentKeywordsContextMap.size()) { numberOfStackTracesToCopy = stackFrames.length; } else { numberOfStackTracesToCopy = currentKeywordsContextMap.size() - 1; } } return numberOfStackTracesToCopy; } private void initStackFrameArray(final Map<String, KeywordContext> currentKeywordsContextMap) { if (stackFrames == null || stackFrames.length == 0) { stackFrames = new IStackFrame[currentKeywordsContextMap.size()]; } } private boolean shouldSetupExistingStackFrame(final Map<String, KeywordContext> currentKeywordsContextMap, final int lowestStackFrameLevel) { return stackFrames.length == currentKeywordsContextMap.size() && stackFrames[lowestStackFrameLevel] != null; } private IStackFrame extractPreviousStackFrame(final Map<String, KeywordContext> currentKeywordsContextMap, int numberOfStackFramesToCopy, int currentKeywordsCounter) { IStackFrame previousStackFrame = null; if (stackFrames.length < currentKeywordsContextMap.size()) { previousStackFrame = stackFrames[numberOfStackFramesToCopy - currentKeywordsCounter]; } else { previousStackFrame = stackFrames[stackFrames.length - currentKeywordsCounter]; } return previousStackFrame; } public void setHasStackFramesCreated(boolean hasStackFramesCreated) { this.hasStackFramesCreated = hasStackFramesCreated; } public void setStackFrames(IStackFrame[] stackFrames) { this.stackFrames = stackFrames; } public boolean hasStackFramesCreated() { return hasStackFramesCreated; } }