/** * Copyright (C) 2010-2017 Gordon Fraser, Andrea Arcuri and EvoSuite * contributors * * This file is part of EvoSuite. * * EvoSuite is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published * by the Free Software Foundation, either version 3.0 of the License, or * (at your option) any later version. * * EvoSuite is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with EvoSuite. If not, see <http://www.gnu.org/licenses/>. */ package org.evosuite.eclipse.quickfixes; import java.io.BufferedReader; import java.io.File; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.IOException; import java.text.MessageFormat; import java.util.ArrayList; import java.util.HashSet; import java.util.Set; import org.eclipse.core.resources.IMarker; import org.eclipse.core.resources.IResource; import org.eclipse.core.runtime.CoreException; import org.eclipse.jdt.core.IAnnotatable; import org.eclipse.jdt.core.IAnnotation; import org.eclipse.jdt.core.ICompilationUnit; import org.eclipse.jdt.core.IJavaElement; 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.ASTParser; import org.eclipse.jdt.core.dom.CompilationUnit; import org.eclipse.jdt.core.dom.MethodDeclaration; import org.eclipse.jface.preference.IPreferenceStore; import org.eclipse.swt.widgets.Display; import org.evosuite.result.BranchInfo; import org.evosuite.result.Failure; import org.evosuite.result.TestGenerationResult; import org.evosuite.eclipse.Activator; public class MarkerWriter { private final IResource res; private final TestGenerationResult tgr; private final ClassMethodVisitor testM; private final ClassMethodVisitor raw; private MarkerWriter(IResource res, TestGenerationResult tgr) { this.res = res; this.tgr = tgr; testM = new ClassMethodVisitor(); raw = new ClassMethodVisitor(); } public static void clearMarkers(IResource res) throws CoreException { if (res.exists()) { res.deleteMarkers("EvoSuiteQuickFixes.exceptionmarker", true, 1); res.deleteMarkers("EvoSuiteQuickFixes.notcoveredmarker", true, 1); res.deleteMarkers("EvoSuiteQuickFixes.uncoveredlinemarker", true, 1); res.deleteMarkers("EvoSuiteQuickFixes.lineremovedmarker", true, 1); } else System.out.println(MessageFormat.format("Resource {} does not exist.", res).toString()); } public void writeMarkers() { System.out.println(tgr); // ServerStatistics.getInstance().getX(); (getCoverage();) ASTParser parser = ASTParser.newParser(AST.JLS4); parser.setKind(ASTParser.K_COMPILATION_UNIT); parser.setResolveBindings(true); parser.setSource(tgr.getTestSuiteCode().toCharArray()); CompilationUnit compTest = (CompilationUnit) parser.createAST(null); IJavaElement jEle = JavaCore.create(res); if (jEle instanceof ICompilationUnit) { final ICompilationUnit icomp = (ICompilationUnit) jEle; // System.out.println(icomp); BufferedReader br; char[] varcontent = null; try { br = new BufferedReader(new FileReader(res.getLocation() .toFile())); int size = 0; while (br.read() != -1) { size++; } // String content = ""; // String line = br.readLine(); // content += line; // while ((line = br.readLine()) != null){ // content += line; // } // parser.setSource(content.toCharArray()); br = new BufferedReader(new FileReader(res.getLocation() .toFile())); varcontent = new char[size]; br.read(varcontent, 0, size); parser.setSource(varcontent); } catch (FileNotFoundException e2) { e2.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } final char[] content = varcontent; final CompilationUnit compClass = (CompilationUnit) parser .createAST(null); compTest.accept(testM); compClass.accept(raw); IJavaElement element = JavaCore.create(res); IJavaElement packageElement = element.getParent(); String packageName = packageElement.getElementName(); final String className = (!packageName.isEmpty() ? packageName + "." : "") + res.getName().replace(".java", "").replace(File.separator, "."); final char[] classContent = varcontent; if (tgr != null) { Display.getDefault().asyncExec(new Runnable() { @Override public void run() { ArrayList<Integer> lines = new ArrayList<Integer>(); Set<Integer> actualLines = new HashSet<Integer>(); actualLines.addAll(tgr.getUncoveredLines()); actualLines.addAll(tgr.getCoveredLines()); int contentPosition = 0; int line = 1; while (contentPosition != -2 && contentPosition != -1) { if (!actualLines.contains(line)) { lines.add(line); } contentPosition = compClass.getPosition(line, 0); line++; } IPreferenceStore store = Activator.getDefault() .getPreferenceStore(); if (store.getBoolean("removed")) { for (Integer i : lines) { // this line couldn't be reached in the test! IJavaElement currentElement = null; int position = compClass.getPosition(i, 0); int maxPosition = compClass.getPosition(i + 1, 0); if (position == -1 || position == -2) { continue; } while (position < classContent.length && Character .isWhitespace(classContent[position])) { // System.out.println(classContent); position++; } if (position > maxPosition) { continue; } while (maxPosition < classContent.length && Character .isWhitespace(classContent[maxPosition])) { // System.out.println(classContent); maxPosition++; } try { currentElement = icomp .getElementAt(position + 1); } catch (JavaModelException e1) { e1.printStackTrace(); } if (isMethodDeclaration(i, currentElement, content, compClass, icomp)) { continue; } IJavaElement nextElement = null; int nextPosition = compClass.getPosition(i + 1, 0); if (nextPosition != -1 || nextPosition != -2) { try { nextElement = icomp .getElementAt(nextPosition); if (nextElement != currentElement) { continue; } } catch (JavaModelException e) { e.printStackTrace(); } } if (position > maxPosition) { continue; } while (maxPosition < classContent.length && Character .isWhitespace(classContent[maxPosition])) { // System.out.println(classContent); maxPosition++; } try { currentElement = icomp .getElementAt(position + 1); } catch (JavaModelException e1) { e1.printStackTrace(); } if (content[position] == '/' && content[position + 1] == '/') { continue; } if (content[position] == '}') { continue; } if (getMethod(currentElement) == null) { continue; } boolean marker = shouldWriteMarkers(currentElement); if (marker) { try { IMarker m = res .createMarker("EvoSuiteQuickFixes.lineremovedmarker"); m.setAttribute(IMarker.MESSAGE, "This line appears to be removed by the Java Compiler."); m.setAttribute(IMarker.LINE_NUMBER, i); m.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH); m.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING); m.setAttribute(IMarker.LOCATION, res.getName()); m.setAttribute(IMarker.CHAR_START, position); m.setAttribute(IMarker.CHAR_END, compClass.getPosition(i + 1, 0)); } catch (CoreException e) { e.printStackTrace(); } } } } if (store.getBoolean("uncovered")) { for (Integer i : tgr.getUncoveredLines()) { // this line couldn't be reached in the test! IJavaElement currentElement = null; int position = compClass.getPosition(i, 0); if (position == -1) { continue; } while (position < classContent.length && Character .isWhitespace(classContent[position])) { // System.out.println(classContent); position++; } try { currentElement = icomp .getElementAt(position + 1); } catch (JavaModelException e1) { e1.printStackTrace(); } boolean marker = shouldWriteMarkers(currentElement); if (marker) { try { IMarker m = res .createMarker("EvoSuiteQuickFixes.uncoveredlinemarker"); m.setAttribute(IMarker.LINE_NUMBER, i); m.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH); m.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING); m.setAttribute(IMarker.LOCATION, res.getName()); m.setAttribute(IMarker.CHAR_START, position); m.setAttribute(IMarker.CHAR_END, compClass.getPosition(i + 1, 0)); } catch (CoreException e) { e.printStackTrace(); } } } } for (BranchInfo bi : tgr.getUncoveredBranches()) { int j = bi.getLineNo(); IJavaElement currentElement = null; int position = compClass.getPosition(j, 0); while (position < classContent.length && Character .isWhitespace(classContent[position])) { // System.out.println(classContent); position++; } try { currentElement = icomp .getElementAt(position + 1); } catch (JavaModelException e1) { e1.printStackTrace(); } boolean marker = shouldWriteMarkers(currentElement); if (marker) { try { IMarker m = res .createMarker("EvoSuiteQuickFixes.notcoveredmarker"); m.setAttribute( IMarker.MESSAGE, "This branch (starting line " + j + ") could not be covered by EvoSuite."); m.setAttribute(IMarker.LINE_NUMBER, j); m.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH); m.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING); m.setAttribute(IMarker.LOCATION, res.getName()); m = res.createMarker("EvoSuiteQuickFixes.uncoveredlinemarker"); // m.setAttribute(IMarker.LINE_NUMBER, j); m.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH); m.setAttribute(IMarker.SEVERITY, IMarker.SEVERITY_WARNING); m.setAttribute(IMarker.LOCATION, res.getName()); m.setAttribute(IMarker.CHAR_START, position); m.setAttribute(IMarker.CHAR_END, compClass.getPosition(j + 1, 0) - 1); m.setAttribute(IMarker.CHAR_START, position); m.setAttribute(IMarker.CHAR_END, compClass.getPosition(j + 1, 0) - 1); } catch (CoreException e) { e.printStackTrace(); } } } for (MethodDeclaration method : testM.getMethods()) { String test = method.getName() .getFullyQualifiedName(); Set<Failure> failures = tgr .getContractViolations(test); if (failures != null && failures.size() != 0) { // uncaught Exception! try { for (Failure f : failures) { if (f != null) { int lineNumber = 1; String message = ""; for (int i = 0; i < f .getStackTrace().length; i++) { if (f.getStackTrace()[i] .getClassName().equals( className)) { boolean found = false; for (MethodDeclaration method2 : raw .getMethods()) { String s = method2 .getName() .getFullyQualifiedName(); if (s.equals(f .getStackTrace()[i] .getMethodName())) { found = true; break; } } if (found) { message = f .getStackTrace()[i] .toString(); lineNumber = f .getStackTrace()[i] .getLineNumber(); break; } } } IJavaElement currentElement = null; int position = compClass .getPosition(lineNumber, 0); while (position < classContent.length && Character .isWhitespace(classContent[position])) { // System.out.println(classContent); position++; } try { currentElement = icomp .getElementAt(position + 1); } catch (JavaModelException e1) { e1.printStackTrace(); } boolean marker = shouldWriteMarkers(currentElement); if (marker) { IMarker m = res .createMarker("EvoSuiteQuickFixes.exceptionmarker"); m.setAttribute(IMarker.MESSAGE, f.getExceptionName() + " detected " + message); m.setAttribute( IMarker.LINE_NUMBER, lineNumber); m.setAttribute( IMarker.PRIORITY, IMarker.PRIORITY_HIGH); m.setAttribute( IMarker.SEVERITY, IMarker.SEVERITY_WARNING); m.setAttribute( IMarker.LOCATION, res.getName()); while (position < classContent.length && Character .isWhitespace(classContent[position])) { // System.out.println(classContent); position++; } m.setAttribute( IMarker.CHAR_START, position); m.setAttribute( IMarker.CHAR_END, compClass.getPosition( lineNumber + 1, 0) - 1); } } } } catch (CoreException e) { e.printStackTrace(); } } } } }); } } } public IJavaElement getMethod(IJavaElement e) { IJavaElement method = e; while (method != null && method.getElementType() != IJavaElement.METHOD) { method = method.getParent(); } return method; } private boolean isMethodDeclaration(int lineNumber, IJavaElement currentElement, char[] content, CompilationUnit cu, ICompilationUnit icu) { IJavaElement previousElement = null; int prevPosition = cu.getPosition(lineNumber - 1, 0); int limit = cu.getPosition(lineNumber, 0); while (Character.isWhitespace(content[limit])) { // System.out.println(classContent); limit++; } limit++; if (prevPosition != -1 && prevPosition != -2) { try { previousElement = icu.getElementAt(prevPosition + 1); if (previousElement != currentElement) { return true; } else { for (int i = prevPosition; i < limit; i++) { if (content[i] == '{') { return false; } } return isMethodDeclaration(lineNumber - 1, currentElement, content, cu, icu); } } catch (JavaModelException e) { e.printStackTrace(); } } return false; } private boolean shouldWriteMarkers(IJavaElement currentElement) { IJavaElement parent = currentElement; while (parent != null) { if (parent instanceof IAnnotatable) { IAnnotatable p = (IAnnotatable) parent; try { for (IAnnotation a : p.getAnnotations()) { if (a.getElementName().equalsIgnoreCase("EvoIgnore")) { return false; } } } catch (JavaModelException e) { e.printStackTrace(); } } parent = parent.getParent(); } return true; } public static void write(IResource res, TestGenerationResult tgr) { MarkerWriter mr = new MarkerWriter(res, tgr); mr.writeMarkers(); } }