168 lines
4.8 KiB
Java
168 lines
4.8 KiB
Java
/*******************************************************************************
|
|
* Copyright (c) 2013 IBM Corporation.
|
|
* All rights reserved. This program and the accompanying materials
|
|
* are made available under the terms of the Eclipse Public License v1.0
|
|
* which accompanies this distribution, and is available at
|
|
* http://www.eclipse.org/legal/epl-v10.html
|
|
*
|
|
* Contributors:
|
|
* IBM Corporation - initial API and implementation
|
|
*******************************************************************************/
|
|
package com.ibm.wala.viz.viewer;
|
|
|
|
import java.awt.BorderLayout;
|
|
import java.io.BufferedReader;
|
|
import java.io.IOException;
|
|
import java.io.StringReader;
|
|
import java.util.HashSet;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
|
|
import javax.swing.DefaultListModel;
|
|
import javax.swing.JList;
|
|
import javax.swing.JPanel;
|
|
import javax.swing.JScrollPane;
|
|
import javax.swing.JTextField;
|
|
import javax.swing.ScrollPaneConstants;
|
|
import javax.swing.event.ListSelectionEvent;
|
|
import javax.swing.event.ListSelectionListener;
|
|
|
|
import com.ibm.wala.classLoader.IMethod;
|
|
import com.ibm.wala.ssa.IR;
|
|
import com.ibm.wala.util.collections.HashMapFactory;
|
|
|
|
public class IrViewer extends JPanel{
|
|
private JTextField methodName;
|
|
private DefaultListModel<String> irLineList = new DefaultListModel<>();
|
|
private JList<String> irLines;
|
|
|
|
// mapping from ir viewer list line to source code line number.
|
|
private Map<Integer, Integer> lineToPosition = null;
|
|
|
|
// Mapping for pc to line in the ir viewer list.
|
|
private Map<Integer, Integer> pcToLine = null;
|
|
private Map<Integer, Integer> lineToPc = null;
|
|
|
|
public interface SelectedPcListner{
|
|
void valueChanged(int pc);
|
|
}
|
|
Set<SelectedPcListner> selectedPcListners = new HashSet<SelectedPcListner>();
|
|
|
|
public IrViewer() {
|
|
super(new BorderLayout());
|
|
irLines = new JList<String>(irLineList);
|
|
methodName = new JTextField("IR");
|
|
this.add(methodName, BorderLayout.PAGE_START);
|
|
this.add(new JScrollPane(irLines, ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED,
|
|
ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED), BorderLayout.CENTER);
|
|
|
|
|
|
irLines.addListSelectionListener(new ListSelectionListener() {
|
|
@Override
|
|
public void valueChanged(ListSelectionEvent e) {
|
|
int index = irLines.getSelectedIndex();
|
|
Integer pc = lineToPc.get(index);
|
|
if (pc == null) {
|
|
pc = NA;
|
|
}
|
|
for (SelectedPcListner selectedPcListner : selectedPcListners) {
|
|
selectedPcListner.valueChanged(pc);
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
public void setIR(IR ir) {
|
|
this.lineToPosition = HashMapFactory.make();
|
|
this.pcToLine = HashMapFactory.make();
|
|
this.lineToPc = HashMapFactory.make();
|
|
|
|
int firstLineWithPosition = NA;
|
|
|
|
try {
|
|
methodName.setText("IR: " + ir.getMethod());
|
|
irLineList.clear();
|
|
BufferedReader br = new BufferedReader(new StringReader(ir.toString()));
|
|
int lineNum = 0;
|
|
int position = NA;
|
|
String line;
|
|
while ((line = br.readLine()) != null) {
|
|
irLineList.addElement(line);
|
|
int pc = parseIrLine(line);
|
|
if (pc != NA) {
|
|
IMethod m = ir.getMethod();
|
|
int newPosition = m.getLineNumber(pc);
|
|
if (newPosition != -1) {
|
|
position = newPosition;
|
|
}
|
|
lineToPc.put(lineNum, pc);
|
|
pcToLine.put(pc, lineNum);
|
|
|
|
if (position != NA) {
|
|
lineToPosition.put(lineNum, position);
|
|
if (firstLineWithPosition == NA){
|
|
firstLineWithPosition = lineNum;
|
|
}
|
|
}
|
|
}
|
|
lineNum++;
|
|
}
|
|
} catch (IOException e) {
|
|
// ???
|
|
assert false;
|
|
}
|
|
|
|
// focusing on the first line with position
|
|
if (firstLineWithPosition != NA){
|
|
irLines.setSelectedIndex(firstLineWithPosition);
|
|
irLines.ensureIndexIsVisible(firstLineWithPosition);
|
|
}
|
|
}
|
|
|
|
static final int NA = -1;
|
|
|
|
private int parseIrLine(String line) {
|
|
int firstSpace = line.indexOf(' ');
|
|
if (firstSpace > 0) {
|
|
String pcString = line.substring(0, firstSpace);
|
|
try {
|
|
return Integer.parseInt(pcString);
|
|
} catch (NumberFormatException e) {
|
|
return NA;
|
|
}
|
|
} else {
|
|
return NA;
|
|
}
|
|
}
|
|
|
|
public void addSelectedPcListner(SelectedPcListner selectedPcListner) {
|
|
this.selectedPcListners.add(selectedPcListner);
|
|
}
|
|
|
|
public void setPc(int pc){
|
|
Integer lineNum = pcToLine.get(pc);
|
|
if (lineNum != null){
|
|
irLines.ensureIndexIsVisible(lineNum);
|
|
irLines.setSelectedIndex(lineNum);
|
|
} else {
|
|
removeSelection();
|
|
}
|
|
}
|
|
|
|
public void setIRAndPc(IR ir, int pc) {
|
|
setIR(ir);
|
|
if (pc != NA){
|
|
setPc(pc);
|
|
} else {
|
|
removeSelection();
|
|
}
|
|
}
|
|
|
|
private void removeSelection() {
|
|
int curSelectedIndex = irLines.getSelectedIndex();
|
|
irLines.removeSelectionInterval(curSelectedIndex, curSelectedIndex);
|
|
}
|
|
|
|
|
|
}
|