package bug; import java.io.File; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Hashtable; import java.util.Vector; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IMethod; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragmentRoot; import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.JavaCore; import org.eclipse.jdt.core.JavaModelException; import org.eclipse.jdt.core.dom.AST; import org.eclipse.jdt.core.dom.ASTNode; import org.eclipse.jdt.core.dom.ASTParser; import org.eclipse.jdt.core.dom.ASTVisitor; import org.eclipse.jdt.core.dom.Block; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.IMethodBinding; import org.eclipse.jdt.core.dom.IfStatement; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jdt.core.dom.MethodInvocation; import org.eclipse.jdt.core.dom.Statement; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; import org.eclipse.jdt.core.dom.rewrite.ListRewrite; import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants; import org.eclipse.jdt.internal.corext.codemanipulation.OrganizeImportsOperation; import org.eclipse.jface.text.BadLocationException; import org.eclipse.jface.text.Document; import org.eclipse.text.edits.MalformedTreeException; public class StmtRemover { private static final int DEFAULT_READING_SIZE = 8192; public final static String UTF_8 = "UTF-8"; //$NON-NLS-1$ private static final char[] NO_CHAR = new char[0]; CompilationUnit testClassCU; // ICompilationUnit testClassICU; // IFile testClassFile; IJavaProject JabRefProject; public StmtRemover(String testClassName) { JabRefProject = JavaCore.create(ResourcesPlugin.getWorkspace().getRoot().getProject("JabRef2.5")); ArrayList projCUs = getIJavaProjectTCsCompilationUnits(JabRefProject); for(CompilationUnit curUnit: projCUs) { if(curUnit.getJavaElement().getElementName().equals(testClassName)) testClassCU = curUnit; } } public MethodDeclaration getMethodNode(final String methodName) { final Vector matchedMethods = new Vector(); testClassCU.accept(new ASTVisitor(){ public boolean visit(MethodDeclaration m) { if(m.getName().toString().contains(methodName)) matchedMethods.add(m); return super.visit(m); } }); return matchedMethods.get(0); } public void removeInvocationsOfMethod(MethodDeclaration sourceMethodNode, final String callToRemove) { final Vector matchedInvocations = new Vector(); if (sourceMethodNode != null) sourceMethodNode.accept(new ASTVisitor() { public boolean visit(MethodInvocation node) { if(node.getName().toString().contains(callToRemove)) { matchedInvocations.add(node); } return super.visit(node); } }); ASTRewrite rewrite = ASTRewrite.create(testClassCU.getAST()); if(matchedInvocations.isEmpty()) return; //The code works properly till here, where it captures all the method invocations inside the testFieldAndFormat test case for (ASTNode n : matchedInvocations) { Statement s = getContainingStatement(n); if (s instanceof IfStatement) ; //Option 1 //START: Code for node comment out ASTNode placeHolder = rewrite.createStringPlaceholder( "/** Removed node: \n", ASTNode.EMPTY_STATEMENT); ListRewrite list = rewrite.getListRewrite(s.getParent(), Block.STATEMENTS_PROPERTY); list.insertBefore(placeHolder, s, null); placeHolder = rewrite.createStringPlaceholder("\n*/", ASTNode.EMPTY_STATEMENT); list = rewrite.getListRewrite(s.getParent(), Block.STATEMENTS_PROPERTY); list.insertAfter(placeHolder, s, null); //END code for node comment out //Option 2 //START: Code for node removal //ListRewrite list = rewrite.getListRewrite(s.getParent(),Block.STATEMENTS_PROPERTY); //where s is the statement to remove //list.remove(s, null); //END: Code for node removal } sourceMethodNode.setProperty("RewriteInfo", rewrite); //Write down the modified Compilation unit writeCUDown(sourceMethodNode); } private void writeCUDown(ASTNode node) { try{ IType it = JabRefProject.findType("net.sf.jabref.UtilTest"); IPath ip = it.getPath(); IPath path = ip.removeFirstSegments(1); IFile file = JabRefProject.getProject().getFile(path); StringBuilder sb = new StringBuilder(); InputStream is = file.getContents(); sb.append(getInputStreamAsCharArray(is, -1, UTF_8)); ASTRewrite rewrite = (ASTRewrite) node.getProperty("RewriteInfo"); Document doc = new Document(sb.toString()); // FORMATTER_PUT_EMPTY_STATEMENT_ON_NEW_LINE Hashtable options = JavaCore.getDefaultOptions(); options.put(DefaultCodeFormatterConstants.FORMATTER_PUT_EMPTY_STATEMENT_ON_NEW_LINE,DefaultCodeFormatterConstants.TRUE); org.eclipse.text.edits.TextEdit te = rewrite.rewriteAST(doc, options); te.apply(doc); file.setContents(new java.io.StringBufferInputStream(doc.get()), IResource.FORCE, null); } catch(Exception e) { System.out.println("Error in file rewrite"); } } private Statement getContainingStatement(ASTNode n) { if (n instanceof Statement) return (Statement) n; else return getContainingStatement(n.getParent()); } protected static CompilationUnit parse(ICompilationUnit unit) { ASTParser parser = ASTParser.newParser(AST.JLS3); parser.setKind(ASTParser.K_COMPILATION_UNIT); parser.setSource(unit); // set source parser.setResolveBindings(true); // we need bindings later on return (CompilationUnit) parser.createAST(null /* IProgressMonitor */); // parse } //This method is copied with modifications from http://www.eclipse.org/forums/index.php?t=msg&goto=257037& public static ArrayList getIJavaProjectTCsCompilationUnits(IJavaProject srcProj) { IPackageFragmentRoot[] ipfr; // Vector icu = new Vector(); ArrayList projTCsCompilationUnits = new ArrayList(); try { // acces the package root for Java resources ipfr = srcProj.getAllPackageFragmentRoots(); for (int i = 0; i < ipfr.length; i++) { // select internal resources if (!ipfr[i].isExternal()) { // get the inner packages IJavaElement [] ije = ipfr[i].getChildren(); for (int j = 0; j < ije.length; j++) { // cast needed here IPackageFragment pf = (IPackageFragment) ije[j]; //if that package is a source package if(pf.getKind()== IPackageFragmentRoot.K_SOURCE ) if(pf.getCompilationUnits().length >0) { for(ICompilationUnit curUnit: pf.getCompilationUnits()) { if(curUnit.getElementName().contains("test") || curUnit.getElementName().contains("Test")) { projTCsCompilationUnits.add(parse(curUnit)); } } } } } } } catch (JavaModelException e) { e.printStackTrace(); } return projTCsCompilationUnits; } public static char[] getInputStreamAsCharArray(InputStream stream, int length, String encoding) throws IOException { BufferedReader reader = null; try { reader = encoding == null ? new BufferedReader( new InputStreamReader(stream)) : new BufferedReader( new InputStreamReader(stream, encoding)); } catch (UnsupportedEncodingException e) { // encoding is not supported reader = new BufferedReader(new InputStreamReader(stream)); } char[] contents; int totalRead = 0; if (length == -1) { contents = NO_CHAR; } else { // length is a good guess when the encoding produces less or the // same amount of characters than the file length contents = new char[length]; // best guess } while (true) { int amountRequested; if (totalRead < length) { // until known length is met, reuse same array sized eagerly amountRequested = length - totalRead; } else { // reading beyond known length int current = reader.read(); if (current < 0) break; amountRequested = Math.max(stream.available(), DEFAULT_READING_SIZE); // read at least 8K // resize contents if needed if (totalRead + 1 + amountRequested > contents.length) System.arraycopy(contents, 0, contents = new char[totalRead + 1 + amountRequested], 0, totalRead); // add current character contents[totalRead++] = (char) current; // coming from // totalRead==length } // read as many chars as possible int amountRead = reader.read(contents, totalRead, amountRequested); if (amountRead < 0) break; totalRead += amountRead; } // Do not keep first character for UTF-8 BOM encoding int start = 0; if (totalRead > 0 && UTF_8.equals(encoding)) { if (contents[0] == 0xFEFF) { // if BOM char then skip totalRead--; start = 1; } } // resize contents if necessary if (totalRead < contents.length) System.arraycopy(contents, start, contents = new char[totalRead], 0, totalRead); return contents; } }