diff --git a/org.ntlab.reverseDebugger/plugin.xml b/org.ntlab.reverseDebugger/plugin.xml index f9ab0e4..f915beb 100644 --- a/org.ntlab.reverseDebugger/plugin.xml +++ b/org.ntlab.reverseDebugger/plugin.xml @@ -18,7 +18,7 @@ + + diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/JavaEditorOperator.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/JavaEditorOperator.java index 2927341..90e695c 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/JavaEditorOperator.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/JavaEditorOperator.java @@ -71,7 +71,7 @@ openInJavaEditor(type, method); } - private IType findIType(JDIInstanceMethodCaller meCaller) throws InvalidTypeException, + public IType findIType(JDIInstanceMethodCaller meCaller) throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { StringReference declaringClassName = (StringReference)meCaller.callInstanceMethod("getDeclaringClassName"); String projectPath = getLoaderPath(meCaller, declaringClassName); @@ -154,7 +154,7 @@ return method; } - private IMethod findIMethod(IType type, String methodSignature) { + public IMethod findIMethod(IType type, String methodSignature) { try { for (IMethod method : type.getMethods()) { if (checkMethodSignature(type, method, methodSignature)) { diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ReverseDebuggerPerspective.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ReverseDebuggerPerspective.java index 6eb0664..405f846 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ReverseDebuggerPerspective.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/ReverseDebuggerPerspective.java @@ -21,6 +21,10 @@ // �E���ɃI�u�W�F�N�g�t���[�G�C���A�X�̃r���[��z�u IFolderLayout bottomRight = layout.createFolder("bottomRight", IPageLayout.RIGHT, 0.5f, editorArea); - bottomRight.addView(ObjectFlowAliasView.ID); + bottomRight.addView(ObjectFlowAliasView.ID); + + // �E��ɕϐ��̃r���[��z�u + IFolderLayout topRight2 = layout.createFolder("topRight2", IPageLayout.RIGHT, 0.5f, "topLeft"); + topRight2.addView(VariableView.ID); } } diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasView.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasView.java index 15ff709..88c879b 100644 --- a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasView.java +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/SeedAliasView.java @@ -28,7 +28,7 @@ private IAction refreshAction; private IAction resetAction; private IAction getObjectFlowAction; - private JDIInstanceMethodCaller selectSeedAlias; + private static JDIInstanceMethodCaller selectSeedAlias; private static SeedAliases seedAliases = new SeedAliases(); private static JavaEditorOperator javaEditorOperator = new JavaEditorOperator(); public static final String ID = "org.ntlab.reverseDebugger.seedAliasView"; @@ -69,6 +69,7 @@ Object element = sel.getFirstElement(); if (element instanceof JDIInstanceMethodCaller) { selectSeedAlias = (JDIInstanceMethodCaller)element; + VariableView.updateVariablesByAlias(selectSeedAlias); javaEditorOperator.openSrcFileOfAlias(selectSeedAlias); } } @@ -151,10 +152,12 @@ public static void createSeedAliasesByAlias(JDIInstanceMethodCaller alias) { seedAliases.createSeedAliasesByAlias(alias); + VariableView.updateVariablesByAlias(alias); } public static void createSeedAliasesByMethodExecution(JDIInstanceMethodCaller methodExecution) { seedAliases.createSeedAliasesByMethodExecution(methodExecution); + VariableView.updateVariablesByMethodExecution(methodExecution); } public static void refresh() { @@ -162,6 +165,7 @@ seedAliases.initSeedAliases(); javaEditorOperator.openSrcFileOfMethodExecution(seedAliases.getDebuggerStopMethodExecution()); CallStackView.reset(); + VariableView.updateVariablesByMethodExecution(seedAliases.getDebuggerStopMethodExecution()); } viewer.refresh(); } @@ -178,4 +182,8 @@ ObjectFlowAliasView.refresh(); } } + + public static JDIInstanceMethodCaller getSelectSeedAlias() { + return selectSeedAlias; + } } diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableLabelProvider.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableLabelProvider.java new file mode 100644 index 0000000..02cf95f --- /dev/null +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableLabelProvider.java @@ -0,0 +1,37 @@ +package org.ntlab.reverseDebugger; + +import org.eclipse.jface.viewers.ITableLabelProvider; +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.jface.viewers.TreeNode; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.ISharedImages; +import org.eclipse.ui.PlatformUI; + +public class VariableLabelProvider extends LabelProvider implements ITableLabelProvider { + @Override + public String getColumnText(Object element, int columnIndex) { + if (element instanceof TreeNode) { + Object value = ((TreeNode)element).getValue(); + if (value instanceof VariableData) { + VariableData variableData = (VariableData)value; + switch (columnIndex) { + case 0: + return variableData.getVariableName(); + case 1: + return variableData.getClassName() + " (" + "id = " + variableData.getId() + ")"; + } + } + } + return "�e�X�g�p�e�L�X�g" + columnIndex; + } + + @Override + public Image getColumnImage(Object element, int columnIndex) { + return getImage(element); + } + + @Override + public Image getImage(Object element) { + return PlatformUI.getWorkbench().getSharedImages().getImage(ISharedImages.IMG_OBJ_ELEMENT); + } +} diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableView.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableView.java new file mode 100644 index 0000000..8b35044 --- /dev/null +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/VariableView.java @@ -0,0 +1,120 @@ +package org.ntlab.reverseDebugger; + +import org.eclipse.jface.action.IMenuManager; +import org.eclipse.jface.action.IToolBarManager; +import org.eclipse.jface.viewers.TreeNodeContentProvider; +import org.eclipse.jface.viewers.TreeViewer; +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Tree; +import org.eclipse.swt.widgets.TreeColumn; +import org.eclipse.ui.part.ViewPart; +import org.ntlab.onlineAccessor.JDIInstanceMethodCaller; + +public class VariableView extends ViewPart { + private static TreeViewer viewer; +// private IAction refreshAction; +// private IAction resetAction; + private static JDIInstanceMethodCaller selectedAlias; + private static Variables variables = new Variables(); + public static final String ID = "org.ntlab.reverseDebugger.variableView"; + + public VariableView() { + // TODO Auto-generated constructor stub + System.out.println("VariableView�N���X���������ꂽ��!"); + } + + @Override + public void createPartControl(Composite parent) { + // TODO Auto-generated method stub + System.out.println("VariableView#createPartControl(Composite)���Ă΂ꂽ��!"); + viewer = new TreeViewer(parent, SWT.BORDER | SWT.H_SCROLL | SWT.V_SCROLL); + Tree tree = viewer.getTree(); + tree.setHeaderVisible(true); + tree.setLinesVisible(true); + + String[] treeColumnTexts = {"Name", "Value"}; + int[] treeColumnWidth = {100, 200}; + TreeColumn[] treeColumns = new TreeColumn[treeColumnTexts.length]; + for (int i = 0; i < treeColumns.length; i++) { + 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()); + JDIInstanceMethodCaller methodExecution = SeedAliasView.getDebuggerStopMethodExecution(); + if (methodExecution != null) { + variables.getAllObjectDataByMethodExecution(methodExecution); + viewer.setInput(variables.getVariablesTreeNodes()); + } + createActions(); + createToolBar(); + createMenuBar(); + } + + @Override + public void setFocus() { + // TODO Auto-generated method stub + viewer.getControl().setFocus(); + } + + private void createActions() { +// refreshAction = new Action() { +// @Override +// public void run() { +// refresh(); +// } +// }; +// refreshAction.setText("refresh"); +// refreshAction.setToolTipText("refresh"); +// refreshAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_ELCL_SYNCED)); +// +// resetAction = new Action() { +// @Override +// public void run() { +// reset(); +// } +// }; +// resetAction.setText("reset"); +// resetAction.setToolTipText("reset"); +// resetAction.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_ETOOL_HOME_NAV)); + } + + private void createToolBar() { + IToolBarManager mgr = getViewSite().getActionBars().getToolBarManager(); +// mgr.add(refreshAction); +// mgr.add(resetAction); + } + + private void createMenuBar() { + IMenuManager mgr = getViewSite().getActionBars().getMenuManager(); +// mgr.add(refreshAction); +// mgr.add(resetAction); + } + +// public static void refresh() { +// selectedAlias = SeedAliasView.getSelectSeedAlias(); +// if (selectedAlias != null) { +// variables.getAllObjectDataByAlias(selectedAlias); +// viewer.setInput(variables.getVariablesTreeNodes()); +// } +// } + +// private void reset() { +// selectedAlias = SeedAliasView.getSelectSeedAlias(); +// if (selectedAlias != null) { +// updateVariablesByAlias(selectedAlias); +// } +// } + + public static void updateVariablesByMethodExecution(JDIInstanceMethodCaller methodExecution) { + variables.getAllObjectDataByMethodExecution(methodExecution); + viewer.setInput(variables.getVariablesTreeNodes()); + } + + public static void updateVariablesByAlias(JDIInstanceMethodCaller alias) { + variables.getAllObjectDataByAlias(alias); + viewer.setInput(variables.getVariablesTreeNodes()); + } +} diff --git a/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/Variables.java b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/Variables.java new file mode 100644 index 0000000..b8f14b2 --- /dev/null +++ b/org.ntlab.reverseDebugger/src/org/ntlab/reverseDebugger/Variables.java @@ -0,0 +1,321 @@ +package org.ntlab.reverseDebugger; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +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.onlineAccessor.JDIInstanceMethodCaller; +import com.sun.jdi.ClassNotLoadedException; +import com.sun.jdi.ClassType; +import com.sun.jdi.Field; +import com.sun.jdi.IncompatibleThreadStateException; +import com.sun.jdi.IntegerValue; +import com.sun.jdi.InvalidTypeException; +import com.sun.jdi.InvocationException; +import com.sun.jdi.ObjectReference; +import com.sun.jdi.ReferenceType; +import com.sun.jdi.StringReference; +import com.sun.jdi.ThreadReference; +import com.sun.jdi.Value; +import com.sun.jdi.VirtualMachine; + +public class Variables { + private VariableData rootThisObjData; + private List argsData = new ArrayList<>(); + private List allObjData = new ArrayList<>(); + private static final String TRACER = "org.ntlab.traceAnalysisPlatform.tracer.trace"; + + public TreeNode[] getVariablesTreeNodes() { + TreeNode[] roots = new TreeNode[allObjData.size()]; + if (allObjData.isEmpty()) { + return roots; + } + for (int i = 0; i < allObjData.size(); i++) { + VariableData rootVariableData = allObjData.get(i); + createVariablesTreeNode(null, roots, i, rootVariableData); + } + return roots; + } + + private void createVariablesTreeNode(TreeNode parentNode, TreeNode[] addingNodes, int index, VariableData addingVariableData) { + TreeNode newNode = new TreeNode(addingVariableData); + newNode.setParent(parentNode); + addingNodes[index] = newNode; + TreeNode[] childNodes = new TreeNode[addingVariableData.getChildren().size()]; + addingNodes[index].setChildren(childNodes); + for (int i = 0; i < addingVariableData.getChildren().size(); i++) { + VariableData child = addingVariableData.getChildren().get(i); + createVariablesTreeNode(newNode, childNodes, i, child); + } + } + + public List getAllObjectDataByMethodExecution(JDIInstanceMethodCaller methodExecution) { + if (methodExecution == null) return new ArrayList<>(); + try { + VirtualMachine vm = methodExecution.getVm(); + ThreadReference thread = methodExecution.getThread(); + ObjectReference method = methodExecution.getReceiver(); + + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, method); + ObjectReference statements = (ObjectReference)mc.callInstanceMethod("getStatements"); + mc.changeReceiver(statements); + int lastOrder = ((IntegerValue)mc.callInstanceMethod("size")).value() - 1; + mc.changeReceiver(method); + ObjectReference tp = (ObjectReference)mc.callInstanceMethod("getTracePoint", vm.mirrorOf(lastOrder)); +// methodExecution.getTracePoint(methodExecution.getStatements().size() - 1); + + getAllObjectData(vm, thread, method, tp); + } catch (InvalidTypeException | ClassNotLoadedException + | InvocationException | IncompatibleThreadStateException e) { + e.printStackTrace(); + } + return allObjData; + } + + public List getAllObjectDataByAlias(JDIInstanceMethodCaller alias) { + if (alias == null) return new ArrayList<>(); + try { + VirtualMachine vm = alias.getVm(); + ThreadReference thread = alias.getThread(); + ObjectReference methodExecution = (ObjectReference)alias.callInstanceMethod("getMethodExecution"); + ObjectReference tp = (ObjectReference)alias.callInstanceMethod("getOccurrencePoint"); + getAllObjectData(vm, thread, methodExecution, tp); + } catch (InvalidTypeException | ClassNotLoadedException | InvocationException + | IncompatibleThreadStateException e) { + e.printStackTrace(); + } + return allObjData; + } + + private void getAllObjectData(VirtualMachine vm, ThreadReference thread, Value methodExecution, Value tp) { + try { + resetData(); + + // this��ID��Type���擾���ĕ\�� + getRootThisState(vm, thread, (ObjectReference)methodExecution); + + // this�̎��ƒt�B�[���h��ID��Type��\�� (�Ăяo����ōċA) + getFieldsState(vm, thread, rootThisObjData, tp, ""); + + // ������ID��Type �y�т��̈��������ƒt�B�[���h��ID��Type��\�� (�Ăяo����ōċA) + getArgsState(vm, thread, methodExecution, tp, ""); + + allObjData.add(rootThisObjData); + for (VariableData argData : argsData) { + allObjData.add(argData); + } + } catch (InvalidTypeException | ClassNotLoadedException + | InvocationException | IncompatibleThreadStateException e) { + e.printStackTrace(); + } + printAllObjData(); // �m�F�p + } + + private void getRootThisState(VirtualMachine vm, ThreadReference thread, ObjectReference methodExecution) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, methodExecution); + String thisObjId = ((StringReference)mc.callInstanceMethod("getThisObjId")).value(); + String thisClassName = ((StringReference)mc.callInstanceMethod("getThisClassName")).value(); + rootThisObjData = new VariableData("this", thisClassName, thisObjId); + } + + private void getFieldsState(VirtualMachine vm, ThreadReference thread, VariableData thisObjData, Value tp, String indent) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + // �t�B�[���h��ID��Type���擾���ĕ\�� + List classes = vm.classesByName(thisObjData.getClassName()); + ClassType type = (ClassType)classes.get(0); + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null); + ObjectReference trace = (ObjectReference)mc.callStaticMethod(TRACER, "TraceJSON", "getInstance"); + for (Field field : type.allFields()) { + if (field.isStatic()) continue; // static�t�B�[���h�͔�΂� (��낤�Ƃ��Ă��AID��Type�����Ȃ�) + String fieldName = field.declaringType().name() + "." + field.name(); // ���S����N���X�� + + // ���̃t�B�[���h�ɂ‚��Ă̍ŐV�̍X�V�����擾(FieldUpdate) + mc.changeReceiver(trace); + ObjectReference fieldUpdate = (ObjectReference)mc.callInstanceMethod("getRecentlyFieldUpdate", vm.mirrorOf(thisObjData.getId()), vm.mirrorOf(fieldName), tp); + if (fieldUpdate == null) continue; + + // �t�B�[���h��ID��Type���擾(String) + mc.changeReceiver(fieldUpdate); + String fieldObjId = ((StringReference)mc.callInstanceMethod("getValueObjId")).value(); + String fieldType = ((StringReference)mc.callInstanceMethod("getValueClassName")).value(); + VariableData fieldData = new VariableData(fieldName, fieldType, fieldObjId); + thisObjData.addChild(fieldData); + + // �擾�����t�B�[���h���I�u�W�F�N�g��z��̏ꍇ�ɁA���̃I�u�W�F�N�g��z�񂪎��ƒt�B�[���h�ɂ‚��Ă̏������s�� + callDeepHierarchyFieldState(vm, thread, fieldData, tp, (indent + " ")); + } + } + + /** + * �����œn�����t�B�[���h���Q�ƌ^�̏ꍇ��A�z��̏ꍇ�ɁA
+ * ���̎Q�ƌ^�I�u�W�F�N�g�������Ă���t�B�[���h��A�z��̊e�v�f�̃I�u�W�F�N�g�ɂ‚��āA
+ * ���ꂼ��ɑΉ��������\�b�h������ɌĂяo�� (���̃��\�b�h�ƑΉ����\�b�h�Ƃ̑��ݍċA) + */ + private void callDeepHierarchyFieldState(VirtualMachine vm, ThreadReference thread, VariableData thisObjData, Value tp, String indent) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + // �t�B�[���h��ID��Type���Ȃ��ꍇ��AType(=ActualType)��"---"�̏ꍇ�͉������Ȃ� + if (thisObjData.getId() == null || thisObjData.getId().isEmpty() + || thisObjData.getClassName() == null || thisObjData.getClassName().isEmpty()) { + return; + } + final String NULL_ACTUAL_TYPE = "---"; // �t�B�[���h�ɑ΂��Ė����I��null����ꂽ�ꍇ��ActualType�̎擾������ + if (thisObjData.getClassName().equals(NULL_ACTUAL_TYPE)) return; + + final String ARRAY_SIGNATURE_HEAD = "["; // �z��̃V�O�l�`���̐擪�́A�z��̎��������� [ ���A�Ȃ� + if (thisObjData.getClassName().startsWith(ARRAY_SIGNATURE_HEAD)) { + // �t�B�[���h��Type���z��^(�@[ �Ŏn�܂�@)�ꍇ (���̔z�񂪎��Še�v�f�ɂ‚��Ă���Ȃ�f�[�^�擾�������Ăяo��) + getArrayState(vm, thread, thisObjData, tp, indent); + } else { + String[] primitives = {"byte", "short", "int", "long", "float", "double", "char", "boolean"}; + if (!Arrays.asList(primitives).contains(thisObjData.getClassName())) { + // �t�B�[���h��Type���Q�ƌ^(=�I�u�W�F�N�g)�̏ꍇ (���̃I�u�W�F�N�g�������Ă���t�B�[���h�ɂ‚��Ă���Ȃ�f�[�^�擾�������Ăяo��) + getFieldsState(vm, thread, thisObjData, tp, indent); + } + } + } + + private void getArrayState(VirtualMachine vm, ThreadReference thread, VariableData arrayData, Value tp, String indent) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, null); + ObjectReference trace = (ObjectReference)mc.callStaticMethod(TRACER, "TraceJSON", "getInstance"); + for (int i = 0;; i++){ + // ���̔z��v�f�ɂ‚��Ă̍ŐV�̍X�V�����擾(ArrayUpdate) + IntegerValue index = vm.mirrorOf(i); + mc.changeReceiver(trace); + ObjectReference arrayUpdate = (ObjectReference)mc.callInstanceMethod("getRecentlyArrayUpdate", vm.mirrorOf(arrayData.getId()), index, tp); + if (arrayUpdate == null) { + // �z��̃T�C�Y���擾�ł��Ȃ����߁A�C���f�b�N�X���T�C�Y���߂̂Ƃ��Ɋm���ɔ���������@�Ƃ��ĉ����� + // �������A�z��v�f�̓r���ɖ���`���������ꍇ�ł��A�����Ă��܂��̂����_ + break; + } + String arrayIndexName = arrayData.getVariableName() + "[" + index.value() + "]"; + + // �z��v�f��ID��Type���擾(String) + mc.changeReceiver(arrayUpdate); + String valueObjId = ((StringReference)mc.callInstanceMethod("getValueObjectId")).value(); + String valueType = ((StringReference)mc.callInstanceMethod("getValueClassName")).value(); + VariableData arrayIndexData = new VariableData(arrayIndexName, valueType, valueObjId); + arrayData.addChild(arrayIndexData); + + // �擾�����z��v�f���I�u�W�F�N�g��z��̏ꍇ�ɁA���̃I�u�W�F�N�g��z�񂪎��ƒt�B�[���h�ɂ‚��Ă̏������s�� + callDeepHierarchyFieldState(vm, thread, arrayIndexData, tp, (indent + " ")); + } + } + + private void getArgsState(VirtualMachine vm, ThreadReference thread, Value methodExecution, Value tp, String indent) + throws InvalidTypeException, ClassNotLoadedException, InvocationException, IncompatibleThreadStateException { + // methodExecution������arguments���擾(ArrayList)���A����arguments�̃T�C�Y���擾(int) + JDIInstanceMethodCaller mc = new JDIInstanceMethodCaller(vm, thread, (ObjectReference)methodExecution); + ObjectReference args = (ObjectReference)mc.callInstanceMethod("getArguments"); + final int ARGUMENTS_NUM = ((IntegerValue)mc.changeReceiver(args).callInstanceMethod("size")).value(); + if (ARGUMENTS_NUM > 0) { + JavaEditorOperator javaEditorOperator = new JavaEditorOperator(); + IType type = javaEditorOperator.findIType(new JDIInstanceMethodCaller(vm, thread, (ObjectReference)methodExecution)); + mc.changeReceiver((ObjectReference)methodExecution); + String methodSignature = ((StringReference)mc.callInstanceMethod("getSignature")).value(); + IMethod method = javaEditorOperator.findIMethod(type, methodSignature); + String[] argNames = getParameterNames(method); // ������IMethod���牼���������擾���� + for (int i = 0; i < ARGUMENTS_NUM; i++) { + String argName = (argNames.length == ARGUMENTS_NUM) ? argNames[i] : "arg" + i; // ���Ȃ��Ƃ������̌����s��v�̂Ƃ��͐����������������Ă��Ȃ� + mc.changeReceiver(args); + ObjectReference arg = (ObjectReference)mc.callInstanceMethod("get", vm.mirrorOf(i)); + mc.changeReceiver(arg); + String argId = ((StringReference)mc.callInstanceMethod("getId")).value(); + String argType = ((StringReference)mc.callInstanceMethod("getActualType")).value(); + VariableData argData = new VariableData(argName, argType, argId); + argsData.add(argData); + callDeepHierarchyFieldState(vm, thread, argData, tp, (indent + " ")); + } + } + } + + private String[] getParameterNames(IMethod method) { + String[] argNames = new String[0]; + if (method != null) { + try { + argNames = method.getParameterNames(); + } catch (JavaModelException e) { + e.printStackTrace(); + } + } + return argNames; + } + + public void resetData() { + rootThisObjData = null; + argsData.clear(); + allObjData.clear(); + } + + private void printAllObjData() { + System.out.println(); + System.out.println("this"); + printObjData(allObjData.get(0), ""); + System.out.println(); + System.out.println("args"); + for (int i = 1; i < allObjData.size(); i++) { + printObjData(allObjData.get(i), ""); + } + System.out.println(); + } + + private void printObjData(VariableData data, String indent) { + StringBuilder sb = new StringBuilder(); + sb.append(data.getVariableName() + ": "); + sb.append(data.getClassName()); + sb.append("(" + "id = " + data.getId() + ")"); + System.out.println(indent + sb); + for (VariableData child : data.getChildren()) { + printObjData(child, indent + " "); + } + } +} + +class VariableData { + private String variableName; + private String className; + private String id; + private VariableData parent; + private List children = new ArrayList<>(); + + VariableData(String variableName, String className, String id) { + this.variableName = variableName; + this.className = className; + this.id = id; + } + + String getVariableName() { + return variableName; + } + + String getClassName() { + return className; + } + + String getId() { + return id; + } + + VariableData getParent() { + return parent; + } + + List getChildren() { + return children; + } + + void addChild(VariableData child) { + children.add(child); + child.parent = this; + } + + @Override + public String toString() { + return variableName + ": " + className + "(" + "id = " + id + ")"; + } +} \ No newline at end of file