Friday, October 07, 2011

Clean sysouts from java project

Recently I was working in a project that had a lot of sysouts (System.out.println) peppered all over the code. I tried the usual sed approach find . -name '*.java' | xargs sed -i '/System.out.println/d' and that din't work out too well because of multiline sysouts. So, I decided to try the AST approach using the java parser from http://code.google.com/p/javaparser/. So, create a maven project add the javaparser repository and dependency in the pom.xml as given below
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.fc</groupId>
<artifactId>sysout-cleanup</artifactId>
<version>1.0</version>
<repositories>
<repository>
<id>javaparser</id>
<name>JavaParser Repository</name>
<url>http://javaparser.googlecode.com/svn/maven2</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<properties>
<commons-io-version>2.0.1</commons-io-version>
<java-parser-version>1.0.8</java-parser-version>
</properties>
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>${commons-io-version}</version>
</dependency>
<dependency>
<groupId>com.google.code.javaparser</groupId>
<artifactId>javaparser</artifactId>
<version>${java-parser-version}</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
view raw pom.xml hosted with ❤ by GitHub
And the java code that creates the AST and looks for the System.out.println method call
package org.fc;
import japa.parser.JavaParser;
import japa.parser.ast.CompilationUnit;
import japa.parser.ast.expr.FieldAccessExpr;
import japa.parser.ast.expr.MethodCallExpr;
import japa.parser.ast.expr.NameExpr;
import japa.parser.ast.stmt.BlockStmt;
import japa.parser.ast.stmt.ExpressionStmt;
import japa.parser.ast.stmt.Statement;
import japa.parser.ast.visitor.VoidVisitorAdapter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
public class CleanupSysOut {
File inputFile;
File outputFile;
Map<String, String> namespaceMap = new HashMap<String, String>();
public CleanupSysOut(File file) {
inputFile = file;
}
public CleanupSysOut(File in, File out) {
inputFile = in;
outputFile = out;
}
protected CompilationUnit getCompilationUnit() {
CompilationUnit cu = null;
InputStream in = null;
try {
in = new FileInputStream(inputFile);
cu = JavaParser.parse(in);
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
IOUtils.closeQuietly(in);
}
return cu;
}
protected void writeOutput(CompilationUnit cu) throws IOException {
PrintStream out = new PrintStream(new FileOutputStream(outputFile));
out.println(cu.toString());
IOUtils.closeQuietly(out);
}
protected String debugPrint(CompilationUnit cu) throws IOException {
return cu.toString();
}
// MethodVisitor
private class MethodVisitor extends VoidVisitorAdapter&lt;Object&gt; {
private boolean isSysout(MethodCallExpr methodCall) {
if ( "println".equals(methodCall.getName()) ) {
if ( methodCall.getScope() instanceof FieldAccessExpr ) {
FieldAccessExpr fieldExpr = (FieldAccessExpr) methodCall.getScope();
if ( "out".equals(fieldExpr.getField()) ) {
if ( fieldExpr.getScope() instanceof NameExpr ) {
NameExpr clazz = (NameExpr) fieldExpr.getScope();
if ( "System".equals(clazz.getName()) ) {
return true;
}
}
}
}
}
return false;
}
@Override
public void visit(BlockStmt blockStmt, Object arg) {
List<Statement> stmts = blockStmt.getStmts();
if ( null != stmts ) {
Iterator<Statement> itr = stmts.iterator();
while ( itr.hasNext() ) {
Statement stmt = itr.next();
if ( stmt instanceof ExpressionStmt ) {
if ( ((ExpressionStmt) stmt).getExpression() instanceof MethodCallExpr ) {
MethodCallExpr methodCall = (MethodCallExpr) ((ExpressionStmt) stmt).getExpression();
if ( isSysout(methodCall) ) {
itr.remove();
}
}
} else {
stmt.accept(this, arg);
}
}
}
}
}
// MethodVisitor ends
public void doCleanup() {
try {
CompilationUnit cu = getCompilationUnit();
new MethodVisitor().visit(cu, null);
if ( null != outputFile ) {
writeOutput(cu);
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
static void cleanupDir(File inputDir, File outputDir) {
for ( File java : FileUtils.listFiles(inputDir, new String[] { "java" }, true) ) {
String relativePath = java.getAbsolutePath().replace(inputDir.getAbsolutePath(), "").substring(1);
File outputFile = new File(outputDir, relativePath);
outputFile.getParentFile().mkdirs();
new CleanupSysOut(java, outputFile).doCleanup();
}
}
public static void main(String[] args) {
if ( args.length == 2 ) {
cleanupDir(new File(args[0]), new File(args[1]));
} else {
System.err.println("Usage: java " + CleanupSysOut.class.getName() + " <input-dir> <output-dir>");
}
}
}

No comments: