Analysis of a variable inside a method. JavaParser / ANTLR or something else?

I am writing java code analyzing a fragment that will determine the use of variables in a method. (more specifically, how many times the global class variable is read and written in the method). Can this be done using JavaParser? Anyone have any other recommendations? Does anyone know how class metrics are calculated? They are probably dealing with similar things.

+4
source share
3 answers

Thanks guys. Both of your answers led me towards solving this problem using the AST implementation in JAVAPARSER. Here is a code snippet to help others

class CatchNameExpr extends VoidVisitorAdapter { HashMap<String, ArrayList<Integer>> variableLineNumMap;`` ArrayList<String> variableList; boolean functionParsing = false; public CatchNameExpr(ArrayList<String> classVariables) { variableList=classVariables; } public void visit(MethodDeclaration method, Object arg) { System.out.println("---------------"); System.out.println(method.getName()); System.out.println("---------------"); variableLineNumMap = new HashMap<String, ArrayList<Integer>>(); System.out.println(); functionParsing = true; visit(method.getBody(),arg); // Analyze lines for variable usage. Add to list of vars after checking if its read or written or unknown. functionParsing = false; } public void visit(NameExpr n, Object arg) { if(!functionParsing) return; //TODO: check if this var was declared above it, as a local var to the func. if yes, return ArrayList<Integer> setOfLineNum; System.out.println(n.getBeginLine()+" NameExpr " + n.getName()); if(!variableList.contains(n.getName()) || n.getName().length()==0) return; if (!variableLineNumMap.containsKey(n.getName())) { setOfLineNum = new ArrayList<Integer>(); setOfLineNum.add(n.getBeginLine()); variableLineNumMap.put(n.getName(), setOfLineNum); } else { setOfLineNum = variableLineNumMap.get(n.getName()); setOfLineNum.add(n.getBeginLine()); variableLineNumMap.put(n.getName(), setOfLineNum); } } } 

Create an instance of the class --->

 CatchNameExpr nameExp = new CatchNameExpr(classVariables); nameExp.visit(classCompilationUnit, null); 

Similarly, you can visit the AST for the following expressions, operators, conditions, etc.

http://www.jarvana.com/jarvana/view/com/google/code/javaparser/javaparser/1.0.8/javaparser-1.0.8-javadoc.jar!/japa/parser/ast/visitor/VoidVisitorAdapter.html

I am well aware that a processor with byte code will be more efficient and do a better job than I can hope for. But, given the time constraints, this option set me better.

Thanks guys Jasmeet

+2
source

In order to perform the task of searching for variables, the parser signal with ANTLR must also produce AST. I'm pretty sure you can find a ready-made AST builder, but don't know where.

Another approach is to analyze class files with ASM , BCEL, or another class file analyzer. I think it is easier and will work faster. In addition, it will work for other jvm languages ​​(e.g. Scala).

+2
source

To ask whether the reading of the variable is “global” or not, you need what constitutes the full Java compiler interface, which parses the code, creates symbol tables and information about the corresponding type.

To the extent that the compiler has actually recorded this information in your class files, you can perform reflection operations to get your hands on it. To the extent that such information is present in .class files, you can access it using a class byte code handler, for example, mentioned in Kaygorodov’s answer.

ANTLR has a grammar for Java, but I do not believe in any support for building a symbol table. You cannot fake it yourself; Java rules are too complicated. You may be able to extend the ANTLR parser, but it will be a lot of work; "Java rules are too complicated."

I understand that the Java compiler offers some type of access to its internal structures; you can use this.

Our DMS Software Reengineering Toolkit has full Java parsers with name and type resolution and can be used for this purpose.

+2
source

All Articles