Reputation: 404
I am trying to write a basic static code analysis tool for code written in beanshell that would perform some basic checks like unused variables, methods and possibly conditions that would never evaluate to true.
I have tried using the parser that comes with the beanshell source distribution in the way shown in a few examples like following:
import java.io.FileInputStream;
import java.io.IOException;
import bsh.ParseException;
import bsh.Parser;
import bsh.SimpleNode;
public class FindUnusedVariablesTask {
String sourseFilePath;
public FindUnusedVariablesTask(String sourseFilePath) {
this.sourseFilePath = sourseFilePath;
}
public String perform() throws ParseException, IOException {
FileInputStream sourceStream = new FileInputStream(sourseFilePath);
Parser p = new Parser(sourceStream);
while (!p.Line()) {
SimpleNode node = p.popNode();
System.out.println(node.getText());
for (int i=0; i<node.jjtGetNumChildren(); i++)
System.out.println(node.getChild(i).getText());
}
sourceStream.close();
return "";
}
}
For the following beanshell code:
f1 () {
return 1;
}
String f2(String x) {
return x + f1() + " OK";
}
The output is as follows:
f1 ( ) {
( )
{
String f2 ( String x ) {
String
( String x )
{
Basically I'm only getting the parsed method declarations. I cannot find a way access the parsed statements within. How can that be done?
Upvotes: 0
Views: 542
Reputation: 2303
The BeanShell parser produces an AST. Generally speaking, ASTs can be fairly deep in their structure. The code you give above only looks 1 layer deep into the AST.
Try a recursive traversal (I don't have the devkit, so consider this as pseudocode):
import bsh.Node; //you need this as well
public String perform() throws ParseException, IOException {
FileInputStream sourceStream = new FileInputStream(sourseFilePath);
Parser p = new Parser(sourceStream);
while (!p.Line()) {
recursive_print(p.popNode(), "");
}
sourceStream.close();
return "";
}
public void recursive_print(Node node, String prefix)
{
System.out.println(prefix + node.getText());
for (int i=0; i<node.jjtGetNumChildren(); i++)
recursive_print(node.getChild(i), prefix+" ");
}
Upvotes: 2