diff --git a/src/org/ntlab/traceDebugger/DebuggingController.java b/src/org/ntlab/traceDebugger/DebuggingController.java index 420d8e3..0d73667 100644 --- a/src/org/ntlab/traceDebugger/DebuggingController.java +++ b/src/org/ntlab/traceDebugger/DebuggingController.java @@ -1,10 +1,5 @@ package org.ntlab.traceDebugger; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - import org.eclipse.jface.dialogs.InputDialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.swt.SWT; @@ -18,7 +13,6 @@ import org.ntlab.traceAnalysisPlatform.tracer.trace.BlockEnter; import org.ntlab.traceAnalysisPlatform.tracer.trace.FieldUpdate; import org.ntlab.traceAnalysisPlatform.tracer.trace.MethodExecution; -import org.ntlab.traceAnalysisPlatform.tracer.trace.MethodInvocation; import org.ntlab.traceAnalysisPlatform.tracer.trace.Statement; import org.ntlab.traceAnalysisPlatform.tracer.trace.TraceJSON; import org.ntlab.traceAnalysisPlatform.tracer.trace.TracePoint; @@ -144,48 +138,31 @@ refresh(null, debuggingTp, false); return true; } - -// public boolean stepOverAction() { -// if (debuggingTp == null) return false; -// TracePoint previousTp = debuggingTp; -// debuggingTp = debuggingTp.duplicate(); -// int currentLineNo = debuggingTp.getStatement().getLineNo(); -// boolean isReturned; -// while (!(isReturned = !(debuggingTp.stepOver()))) { -// if (currentLineNo != debuggingTp.getStatement().getLineNo()) break; -// previousTp = debuggingTp.duplicate(); -// } -// if (debuggingTp.getStatement() instanceof BlockEnter) { -// debuggingTp.stepFull(); -// } -// if (!debuggingTp.isValid()) { -// terminateAction(); -// MessageDialog.openInformation(null, "Terminate", "This trace is terminated"); -// return false; -// } -// refresh(previousTp, debuggingTp, isReturned); -// return true; -// } public boolean stepOverAction() { if (debuggingTp == null) return false; TracePoint previousTp = debuggingTp; debuggingTp = debuggingTp.duplicate(); int currentLineNo = debuggingTp.getStatement().getLineNo(); - boolean isThroughOnMethodInvocation = false; boolean isReturned = false; + + // �X�e�b�v�I�[�o�[��p���ē��B�_�����‚��Ă��� + TracePoint startTp = debuggingTp.duplicate(); + while (!(isReturned = !(debuggingTp.stepOver()))) { + if (currentLineNo != debuggingTp.getStatement().getLineNo()) break; + previousTp = debuggingTp.duplicate(); + } + TracePoint goalTp = debuggingTp.duplicate(); + + // �X�e�b�v�t����p���č��x�͌Ăяo����ɂ�����Ȃ���\�ߌ��‚��Ă��������B�_�܂Ői�܂��� (�ϐ������X�V�̂��ߓr���̃A�b�v�f�[�g��S�ďE��) + debuggingTp = startTp; do { Statement statement = debuggingTp.getStatement(); - if (currentLineNo != statement.getLineNo()) break; - if (!isThroughOnMethodInvocation) { - if (statement instanceof MethodInvocation) { - isThroughOnMethodInvocation = true; - } else if (statement instanceof FieldUpdate || statement instanceof ArrayUpdate) { - Variables.getInstance().addDifferentialUpdatePoint(debuggingTp); - } + if (statement.equals(goalTp.getStatement())) break; + if (statement instanceof FieldUpdate || statement instanceof ArrayUpdate) { + Variables.getInstance().addDifferentialUpdatePoint(debuggingTp); } - previousTp = debuggingTp.duplicate(); - } while (!(isReturned = !(debuggingTp.stepOver()))); + } while (debuggingTp.stepFull()); if (debuggingTp.getStatement() instanceof BlockEnter) { debuggingTp.stepFull(); @@ -195,7 +172,7 @@ MessageDialog.openInformation(null, "Terminate", "This trace is terminated"); return false; } - refresh(previousTp, debuggingTp, isReturned, !isThroughOnMethodInvocation); + refresh(previousTp, debuggingTp, isReturned, true); return true; } @@ -217,14 +194,20 @@ if (debuggingTp == null) return false; TracePoint previousTp = debuggingTp; debuggingTp = debuggingTp.duplicate(); - boolean isThroughOnMethodInvocation = false; - Statement statement = debuggingTp.getStatement(); - if (statement instanceof MethodInvocation) { - isThroughOnMethodInvocation = true; - } else if (statement instanceof FieldUpdate || statement instanceof ArrayUpdate) { - Variables.getInstance().addDifferentialUpdatePoint(debuggingTp); - } + TracePoint startTp = debuggingTp.duplicate(); debuggingTp.stepNext(); + TracePoint goalTp = debuggingTp.duplicate(); + + // �X�e�b�v�t����p���č��x�͌Ăяo����ɂ�����Ȃ���\�ߌ��‚��Ă��������B�_�܂Ői�܂��� (�ϐ������X�V�̂��ߓr���̃A�b�v�f�[�g��S�ďE��) + debuggingTp = startTp; + do { + Statement statement = debuggingTp.getStatement(); + if (statement.equals(goalTp.getStatement())) break; + if (statement instanceof FieldUpdate || statement instanceof ArrayUpdate) { + Variables.getInstance().addDifferentialUpdatePoint(debuggingTp); + } + } while (debuggingTp.stepFull()); + if (debuggingTp.getStatement() instanceof BlockEnter) { debuggingTp.stepFull(); } @@ -234,7 +217,7 @@ return false; } boolean isReturned = false; - refresh(previousTp, debuggingTp, isReturned, !isThroughOnMethodInvocation); + refresh(previousTp, debuggingTp, isReturned, true); return true; } @@ -336,11 +319,10 @@ callStackView.updateByTracePoint(to); VariableView variableView = ((VariableView)getOtherView(VariableView.ID)); if (!isReturned && canDifferentialUpdateVariables) { - variableView.updateVariablesForDifferential(); + variableView.updateVariablesForDifferential(from, to, isReturned); } else { variableView.updateVariablesByTracePoint(from, to, isReturned); } -// ((VariableView)getOtherView(VariableView.ID)).updateVariablesByTracePoint(from, to, isReturned); } private IViewPart getOtherView(String viewId) { diff --git a/src/org/ntlab/traceDebugger/MyTreeNode.java b/src/org/ntlab/traceDebugger/MyTreeNode.java new file mode 100644 index 0000000..a8eb255 --- /dev/null +++ b/src/org/ntlab/traceDebugger/MyTreeNode.java @@ -0,0 +1,39 @@ +package org.ntlab.traceDebugger; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import org.eclipse.jface.viewers.TreeNode; + +public class MyTreeNode extends TreeNode { + private List children = new ArrayList<>(); + + public MyTreeNode(Object value) { + super(value); + } + + @Override + public MyTreeNode[] getChildren() { + if (children != null && children.size() == 0) { + return null; + } + return children.toArray(new MyTreeNode[children.size()]); + } + + public List getChildList() { + return children; + } + + @Override + public boolean hasChildren() { + return children != null && children.size() > 0; + } + + public void setChildren(final MyTreeNode[] children) { + this.children = new ArrayList(Arrays.asList(children)); + } + + public void setChildList(final List children) { + this.children = children; + } +} diff --git a/src/org/ntlab/traceDebugger/MyTreeNodeContentProvider.java b/src/org/ntlab/traceDebugger/MyTreeNodeContentProvider.java new file mode 100644 index 0000000..81a2e76 --- /dev/null +++ b/src/org/ntlab/traceDebugger/MyTreeNodeContentProvider.java @@ -0,0 +1,17 @@ +package org.ntlab.traceDebugger; + +import java.util.List; + +import org.eclipse.jface.viewers.TreeNodeContentProvider; + +public class MyTreeNodeContentProvider extends TreeNodeContentProvider { + @Override + public Object[] getElements(final Object inputElement) { + if (inputElement instanceof List) { + List list = (List)inputElement; + MyTreeNode[] nodes = list.toArray(new MyTreeNode[list.size()]); + return super.getElements(nodes); + } + return new Object[0]; + } +} diff --git a/src/org/ntlab/traceDebugger/Variable.java b/src/org/ntlab/traceDebugger/Variable.java index 8fd9f40..bb4c2cf 100644 --- a/src/org/ntlab/traceDebugger/Variable.java +++ b/src/org/ntlab/traceDebugger/Variable.java @@ -61,6 +61,10 @@ this.before = before; this.isReturned = isReturned; this.deepHierarchy = checkDeepHierarchy(); + this.alreadyCreatedChildHierarchy = false; + this.alreadyCreatedGrandChildHierarchy = false; + this.children.clear(); + this.additionalAttributes.clear(); } public void update(String valueClassName, String valueId, TracePoint lastUpdatePoint, boolean isReturned) { @@ -193,22 +197,28 @@ // �t�B�[���h��ID��Type���擾���ĕ\�� IType type = JavaEditorOperator.findIType(null, valueClassName); if (type == null) return; - getFieldsState(type); - - // �e�N���X��k���Ă����A�����̃N���X�Œ�`���ꂽ�t�B�[���h�̏����擾���Ă��� (�������������������Ĕ��ɏd���Ȃ�) -// try { -// while (true) { -// String superClassName = type.getSuperclassName(); -// if (superClassName == null) break; -// String fullyQualifiedSuperClassName = JavaEditorOperator.resolveType(type, superClassName); -// if (fullyQualifiedSuperClassName == null) break; -// type = JavaEditorOperator.findIType(null, fullyQualifiedSuperClassName); -// if (type == null) break; -// getFieldsState(type); -// } -// } catch (JavaModelException e) { -// e.printStackTrace(); -// } + getFieldsState(type); +// getFieldStateForSuperClass(type); // �e�N���X��k���Ă����A�����̃N���X�Œ�`���ꂽ�t�B�[���h�̏����擾���Ă��� (�������������������Ĕ��ɏd���Ȃ�) + } + + /** + * // �e�N���X��k���Ă����A�����̃N���X�Œ�`���ꂽ�t�B�[���h�̏����擾���Ă��� (�������������������Ĕ��ɏd���Ȃ�) + * @param type �N�_�ƂȂ�N���X + */ + private void getFieldStateForSuperClass(IType type) { + try { + while (true) { + String superClassName = type.getSuperclassName(); + if (superClassName == null) break; + String fullyQualifiedSuperClassName = JavaEditorOperator.resolveType(type, superClassName); + if (fullyQualifiedSuperClassName == null) break; + type = JavaEditorOperator.findIType(null, fullyQualifiedSuperClassName); + if (type == null) break; + getFieldsState(type); + } + } catch (JavaModelException e) { + e.printStackTrace(); + } } private void getFieldsState(IType type) { diff --git a/src/org/ntlab/traceDebugger/VariableView.java b/src/org/ntlab/traceDebugger/VariableView.java index 1d12b41..7b21c82 100644 --- a/src/org/ntlab/traceDebugger/VariableView.java +++ b/src/org/ntlab/traceDebugger/VariableView.java @@ -1,5 +1,6 @@ package org.ntlab.traceDebugger; +import java.util.ArrayList; import java.util.HashMap; import java.util.HashSet; import java.util.List; @@ -22,7 +23,6 @@ import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.TreeExpansionEvent; import org.eclipse.jface.viewers.TreeNode; -import org.eclipse.jface.viewers.TreeNodeContentProvider; import org.eclipse.jface.viewers.TreeViewer; import org.eclipse.swt.SWT; import org.eclipse.swt.widgets.Composite; @@ -74,9 +74,9 @@ treeColumns[i] = new TreeColumn(tree, SWT.NULL); treeColumns[i].setText(treeColumnTexts[i]); treeColumns[i].setWidth(treeColumnWidth[i]); - } - viewer.setContentProvider(new TreeNodeContentProvider()); - viewer.setLabelProvider(new VariableLabelProvider()); + } + viewer.setContentProvider(new MyTreeNodeContentProvider()); + viewer.setLabelProvider(new VariableLabelProvider()); viewer.addSelectionChangedListener(new ISelectionChangedListener() { @Override public void selectionChanged(SelectionChangedEvent event) { @@ -86,7 +86,7 @@ Object value = ((TreeNode)element).getValue(); if (value instanceof Variable) { selectedVariable = (Variable)value; - } + } } } }); @@ -95,29 +95,28 @@ public void treeExpanded(TreeExpansionEvent event) { // �c���[���J������Ɏ��s�����B �����ł͊J�����m�[�h����3��̃m�[�h�𐶐����Ēlj�����B Object element = event.getElement(); - if (!(element instanceof TreeNode)) return; - TreeNode expandedNode = (TreeNode)element; + if (!(element instanceof MyTreeNode)) return; + MyTreeNode expandedNode = (MyTreeNode)element; Object value = expandedNode.getValue(); if (!(value instanceof Variable)) return; - TreeNode[] childNodes = expandedNode.getChildren(); + List childNodes = expandedNode.getChildList(); if (childNodes == null) return; - for (TreeNode childNode : childNodes) { - TreeNode[] grandChildNodes = childNode.getChildren(); + for (MyTreeNode childNode : childNodes) { + List grandChildNodes = childNode.getChildList(); if (grandChildNodes == null) continue; - for (TreeNode grandChildNode : grandChildNodes) { + for (MyTreeNode grandChildNode : grandChildNodes) { Variable grandChildVariable = (Variable)grandChildNode.getValue(); grandChildVariable.createNextHierarchyState(); List list = grandChildVariable.getChildren(); - TreeNode[] nodes = new TreeNode[list.size()]; + List nodes = new ArrayList<>(); for (int i = 0; i < list.size(); i++) { - nodes[i] = new TreeNode(list.get(i)); + nodes.add(i, new MyTreeNode(list.get(i))); } - grandChildNode.setChildren(nodes); + grandChildNode.setChildList(nodes); } } viewer.refresh(); } - @Override public void treeCollapsed(TreeExpansionEvent event) {} }); @@ -212,7 +211,7 @@ public void reset() { variables.resetData(); - viewer.setInput(variables.getVariablesTreeNodes()); + viewer.setInput(variables.getVariablesTreeNodesList()); viewer.refresh(); } @@ -259,11 +258,12 @@ public void updateVariablesByTracePoint(TracePoint from, TracePoint to, boolean isReturned) { variables.updateAllObjectDataByTracePoint(from, to, isReturned); - viewer.setInput(variables.getVariablesTreeNodes()); + viewer.setInput(variables.getVariablesTreeNodesList()); } - public void updateVariablesForDifferential() { - variables.updateForDifferential(); + public void updateVariablesForDifferential(TracePoint from, TracePoint to, boolean isReturned) { + variables.updateForDifferentialAndReturnValue(from, to, isReturned); +// viewer.setInput(variables.getVariablesTreeNodes()); viewer.refresh(); } @@ -320,7 +320,7 @@ if (variable.getAdditionalAttribute("markerId") != null) { TreeNode parent = node.getParent(); if (parent != null) { - expandedNodes.add(parent); + expandedNodes.add(parent); } } TreeNode[] children = node.getChildren(); diff --git a/src/org/ntlab/traceDebugger/Variables.java b/src/org/ntlab/traceDebugger/Variables.java index 42eb16a..530e729 100644 --- a/src/org/ntlab/traceDebugger/Variables.java +++ b/src/org/ntlab/traceDebugger/Variables.java @@ -9,7 +9,6 @@ import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaModelException; -import org.eclipse.jface.viewers.TreeNode; import org.ntlab.traceAnalysisPlatform.tracer.trace.ArrayUpdate; import org.ntlab.traceAnalysisPlatform.tracer.trace.FieldUpdate; import org.ntlab.traceAnalysisPlatform.tracer.trace.MethodExecution; @@ -18,40 +17,43 @@ import org.ntlab.traceAnalysisPlatform.tracer.trace.Statement; import org.ntlab.traceAnalysisPlatform.tracer.trace.TracePoint; +import com.sun.org.apache.regexp.internal.RE; + public class Variables { private static final Variables theInstance = new Variables(); private List roots = new ArrayList<>(); - private Map> containerIdToDifferentialUpdateTracePoints = new HashMap<>(); + private List rootTreeNodes = new ArrayList<>(); + private Map> containerIdToDifferentialUpdateTracePoints = new HashMap<>(); // �ϐ������X�V�ӏ����L�� public static final String RETURN_VARIABLE_NAME = "return"; public static Variables getInstance() { return theInstance; } - public TreeNode[] getVariablesTreeNodes() { - TreeNode[] rootNodes = new TreeNode[roots.size()]; + public List getVariablesTreeNodesList() { + rootTreeNodes.clear(); if (roots.isEmpty()) { - return rootNodes; + return rootTreeNodes; } for (int i = 0; i < roots.size(); i++) { Variable rootVariableData = roots.get(i); - createVariablesTreeNode(null, rootNodes, i, rootVariableData); + createVariablesTreeNodeList(null, rootTreeNodes, i, rootVariableData); } - return rootNodes; + return rootTreeNodes; } - private void createVariablesTreeNode(TreeNode parentNode, TreeNode[] addingNodes, int index, Variable addingVariableData) { - TreeNode newNode = new TreeNode(addingVariableData); + private void createVariablesTreeNodeList(MyTreeNode parentNode, List addingNodes, int index, Variable addingVariableData) { + MyTreeNode newNode = new MyTreeNode(addingVariableData); newNode.setParent(parentNode); - addingNodes[index] = newNode; - TreeNode[] childNodes = new TreeNode[addingVariableData.getChildren().size()]; - addingNodes[index].setChildren(childNodes); + addingNodes.add(index, newNode); + List childNodes = new ArrayList<>(); + addingNodes.get(index).setChildList(childNodes); for (int i = 0; i < addingVariableData.getChildren().size(); i++) { Variable child = addingVariableData.getChildren().get(i); - createVariablesTreeNode(newNode, childNodes, i, child); + createVariablesTreeNodeList(newNode, childNodes, i, child); } } - + public void updateAllObjectDataByMethodExecution(MethodExecution methodExecution) { if (methodExecution == null) return; List statements = methodExecution.getStatements(); @@ -91,8 +93,13 @@ String thisObjId = me.getThisObjId(); String thisClassName = me.getThisClassName(); Variable variable = new Variable(RETURN_VARIABLE_NAME, thisClassName, thisObjId, returnValueClassName, returnValueId, from, isReturned); - roots.add(variable); - variable.createNextHierarchyState(); + variable.createNextHierarchyState(); + Variable old = roots.get(0); + if (old.getVariableName().equals(RETURN_VARIABLE_NAME)) { + roots.set(0, variable); + } else { + roots.add(0, variable); + } } } @@ -153,10 +160,6 @@ addAdditionalAttributes(child, idSet, additionalAttributes); } } - - public boolean canDifferentalUpdatePoint() { - return !(containerIdToDifferentialUpdateTracePoints.isEmpty()); - } public void addDifferentialUpdatePoint(TracePoint tp) { Statement statement = tp.getStatement(); @@ -184,6 +187,27 @@ containerIdToDifferentialUpdateTracePoints.clear(); } + public void updateForDifferentialAndReturnValue(TracePoint from, TracePoint to, boolean isReturned) { + updateForDifferential(); + updateReturnValue(from, to, isReturned); + Variable variable = roots.get(0); + if (variable.getVariableName().equals(RETURN_VARIABLE_NAME)) { + MyTreeNode node = new MyTreeNode(variable); + Object top = rootTreeNodes.get(0).getValue(); + if (top instanceof Variable && ((Variable)top).getVariableName().equals(RETURN_VARIABLE_NAME)) { + rootTreeNodes.set(0, node); + } else { + rootTreeNodes.add(0, node); + } + List childList = new ArrayList<>(); + node.setChildList(childList); + for (int i = 0; i < variable.getChildren().size(); i++) { + Variable childVariable = variable.getChildren().get(i); + createVariablesTreeNodeList(node, childList, i, childVariable); + } + } + } + private void updateForDifferential(Variable variable) { Set containerIdList = containerIdToDifferentialUpdateTracePoints.keySet(); String containerId = variable.getContainerId(); @@ -193,17 +217,13 @@ if (statement instanceof FieldUpdate) { FieldUpdate fu = (FieldUpdate)statement; if (variable.getFullyQualifiedVariableName().equals(fu.getFieldName())) { - String valueClassName = fu.getValueClassName(); - String valueId = fu.getValueObjId(); - variable.update(valueClassName, valueId, tp, false); + updateForDifferentialField(variable, fu.getValueClassName(), fu.getValueObjId(), tp); } } else if (statement instanceof ArrayUpdate) { ArrayUpdate au = (ArrayUpdate)statement; String fullyQualifiedVariableName = variable.getFullyQualifiedVariableName(); if (fullyQualifiedVariableName.contains("[" + au.getIndex() + "]")) { - String valueClassName = au.getValueClassName(); - String valueId = au.getValueObjectId(); - variable.update(valueClassName, valueId, tp, false); + updateForDifferentialField(variable, au.getValueClassName(), au.getValueObjectId(), tp); } } } @@ -213,8 +233,30 @@ } } + private void updateForDifferentialField(Variable variable, String valueClassName, String valueId, TracePoint lastUpdatePoint) { + variable.update(valueClassName, valueId, lastUpdatePoint, false); + variable.createNextHierarchyState(); + MyTreeNode node = getTreeNodeFor(variable, rootTreeNodes); + List childList = node.getChildList(); + childList.clear(); + for (int i = 0; i < variable.getChildren().size(); i++) { + Variable childVariable = variable.getChildren().get(i); + createVariablesTreeNodeList(node, childList, i, childVariable); + } + } + public void resetData() { roots.clear(); + rootTreeNodes.clear(); containerIdToDifferentialUpdateTracePoints.clear(); } + + private MyTreeNode getTreeNodeFor(Variable variable, List nodes) { + for (MyTreeNode node : nodes) { + if (node.getValue().equals(variable)) return node; + MyTreeNode deep = getTreeNodeFor(variable, node.getChildList()); + if (deep != null) return deep; + } + return null; + } }