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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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<Object> { | |
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>"); | |
} | |
} | |
} |