diff --git a/src/clegoues/genprog4java/Search/package-info.java b/src/clegoues/genprog4java/Search/package-info.java deleted file mode 100644 index ae1592d1..00000000 --- a/src/clegoues/genprog4java/Search/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * - */ -package clegoues.genprog4java.Search; diff --git a/src/clegoues/genprog4java/fitness/Fitness.java b/src/clegoues/genprog4java/fitness/Fitness.java index eeda55f3..99787686 100644 --- a/src/clegoues/genprog4java/fitness/Fitness.java +++ b/src/clegoues/genprog4java/fitness/Fitness.java @@ -56,10 +56,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; -import java.util.HashSet; -import java.util.LinkedList; import java.util.List; -import java.util.Map; import java.util.regex.Pattern; import org.apache.commons.lang3.tuple.Pair; @@ -68,8 +65,6 @@ import org.junit.runner.Request; import clegoues.genprog4java.main.Configuration; -import clegoues.genprog4java.mut.Mutation; -import clegoues.genprog4java.mut.WeightedMutation; import clegoues.genprog4java.rep.Representation; import clegoues.util.ConfigurationBuilder; import junit.framework.Test; @@ -485,7 +480,7 @@ private int testPassCount(Representation rep, boolean shortCircuit, List desiredParent, ASTNode node) { ASTNode parent = node.getParent(); - while(parent != null && !(parent instanceof MethodDeclaration)){ + while (parent != null && !desiredParent.isInstance(parent)) { parent = parent.getParent(); } return parent; } - /** + public static ASTNode getEnclosingMethod(ASTNode node) { + return getEnclosing(MethodDeclaration.class, node); + } + + /** * @param node ASTNode of interest - * @return line number corresponding to the first line of the node in its CU. + * @return line number corresponding to the first line of the node in its CU. * Note that ASTNodes can span multiple lines; this returns the first. */ - public static int getLineNumber(ASTNode node) { + public static int getLineNumber(ASTNode node) { ASTNode root = node.getRoot(); int lineno = -1; if (root instanceof CompilationUnit) { @@ -86,9 +80,10 @@ public static int getLineNumber(ASTNode node) { /** * parses/creates java code from a string, rather than a file on disk. + * * @param progName - * @param code - * @return collection of objects containing the java code. + * @param code + * @return collection of objects containing the java code. */ public static Iterable getJavaSourceFromString( String progName, List> code) { @@ -105,46 +100,48 @@ public static Iterable getJavaSourceFromString( } - /** create a new Type object from a typeBinding, a hilariously + /** + * create a new Type object from a typeBinding, a hilariously * difficult thing to do. + * * @param ast * @param typeBinding * @return */ public static Type typeFromBinding(AST ast, ITypeBinding typeBinding) { - if( ast == null ) + if (ast == null) throw new NullPointerException("ast is null"); - if( typeBinding == null ) + if (typeBinding == null) throw new NullPointerException("typeBinding is null"); - if( typeBinding.isPrimitive() ) { + if (typeBinding.isPrimitive()) { return ast.newPrimitiveType( PrimitiveType.toCode(typeBinding.getName())); } - if( typeBinding.isCapture() ) { + if (typeBinding.isCapture()) { ITypeBinding wildCard = typeBinding.getWildcard(); WildcardType capType = ast.newWildcardType(); ITypeBinding bound = wildCard.getBound(); - if( bound != null ) { + if (bound != null) { capType.setBound(typeFromBinding(ast, bound), wildCard.isUpperbound()); } return capType; } - if( typeBinding.isArray() ) { + if (typeBinding.isArray()) { Type elType = typeFromBinding(ast, typeBinding.getElementType()); return ast.newArrayType(elType, typeBinding.getDimensions()); } - if( typeBinding.isParameterizedType() ) { + if (typeBinding.isParameterizedType()) { ParameterizedType type = ast.newParameterizedType( typeFromBinding(ast, typeBinding.getErasure())); @SuppressWarnings("unchecked") List newTypeArgs = type.typeArguments(); - for( ITypeBinding typeArg : typeBinding.getTypeArguments() ) { + for (ITypeBinding typeArg : typeBinding.getTypeArguments()) { newTypeArgs.add(typeFromBinding(ast, typeArg)); } @@ -153,7 +150,7 @@ public static Type typeFromBinding(AST ast, ITypeBinding typeBinding) { // simple or raw type String qualName = typeBinding.getQualifiedName(); - if( "".equals(qualName) ) { + if ("".equals(qualName)) { throw new IllegalArgumentException("No name for type binding."); } return ast.newSimpleType(ast.newName(qualName)); @@ -161,28 +158,37 @@ public static Type typeFromBinding(AST ast, ITypeBinding typeBinding) { private static MethodDeclaration getMethodDeclaration(ASTNode node) { - while(node != null && node.getParent() != null && !(node instanceof MethodDeclaration)) { + while (node != null && node.getParent() != null && !(node instanceof MethodDeclaration)) { node = node.getParent(); } return (MethodDeclaration) node; } + public static ASTNode getDefaultReturn(ASTNode node, AST hostAST) { MethodDeclaration md = getMethodDeclaration(node); - if(md == null) + if (md == null) return null; Type returnType = md.getReturnType2(); - if(returnType.isPrimitiveType()) { + if (returnType.isPrimitiveType()) { PrimitiveType casted = (PrimitiveType) returnType; PrimitiveType.Code tc = casted.getPrimitiveTypeCode(); - if(tc == PrimitiveType.BOOLEAN) { + if (tc == PrimitiveType.BOOLEAN) { return hostAST.newBooleanLiteral(false); } - if(tc == PrimitiveType.CHAR || tc == PrimitiveType.BYTE || tc == PrimitiveType.INT || tc == PrimitiveType.SHORT) + if (tc == PrimitiveType.CHAR || tc == PrimitiveType.BYTE || tc == PrimitiveType.INT || tc == PrimitiveType.SHORT) return hostAST.newNumberLiteral("0"); - if(tc == PrimitiveType.DOUBLE || tc == PrimitiveType.FLOAT || tc == PrimitiveType.LONG) + if (tc == PrimitiveType.DOUBLE || tc == PrimitiveType.FLOAT || tc == PrimitiveType.LONG) return hostAST.newNumberLiteral("0.0"); - } - return hostAST.newNullLiteral(); + } + return hostAST.newNullLiteral(); + } + + public static boolean isVariableDeclaration(ASTNode node) { + if (node instanceof ExpressionStatement) { + ExpressionStatement es = (ExpressionStatement) node; + if (es.getExpression() instanceof VariableDeclarationExpression) return true; + } + return node instanceof VariableDeclarationStatement; } } diff --git a/src/clegoues/genprog4java/java/CFBlockInfo.java b/src/clegoues/genprog4java/java/CFBlockInfo.java new file mode 100644 index 00000000..b467bcbb --- /dev/null +++ b/src/clegoues/genprog4java/java/CFBlockInfo.java @@ -0,0 +1,41 @@ +package clegoues.genprog4java.java; + +import org.eclipse.jdt.core.dom.*; + +import java.util.HashSet; +import java.util.Set; +import java.util.Stack; + +public class CFBlockInfo { + private Set lastStatementsInCFBlocks = new HashSet<>(); + private Stack currentCFBlock = new Stack<>(); + ASTNode currentNode; + + public boolean isLastStatementInCFBlock(ASTNode node) { + return lastStatementsInCFBlocks.contains(node); + } + + public void registerNode(ASTNode node) { + if(isCFStatement(node)) { + currentCFBlock.push(node); + } + currentNode = node; + } + + public void endOfNode(ASTNode node) { + if (node.equals(currentCFBlock.peek())) { + currentCFBlock.pop(); + lastStatementsInCFBlocks.add(currentNode); + } + } + + public static boolean isCFStatement(ASTNode node) { + return node instanceof EnhancedForStatement || + node instanceof ForStatement || + node instanceof DoStatement || + node instanceof IfStatement || + node instanceof SwitchStatement || + node instanceof TryStatement || + node instanceof WhileStatement; + } +} diff --git a/src/clegoues/genprog4java/java/JavaParser.java b/src/clegoues/genprog4java/java/JavaParser.java index 4bbbbcfc..f6e0951c 100644 --- a/src/clegoues/genprog4java/java/JavaParser.java +++ b/src/clegoues/genprog4java/java/JavaParser.java @@ -82,7 +82,7 @@ public class JavaParser */ private HashSet availableMethodsAndFields; - public JavaParser(ScopeInfo scopeList) + public JavaParser(ScopeInfo scopeList, CFBlockInfo cfBlockInfo) { this.stmts = new LinkedList(); this.methodReturnType = new HashMap(); @@ -94,6 +94,7 @@ public JavaParser(ScopeInfo scopeList) this.visitor.setNodeSet(this.stmts); this.visitor.setScopeList(scopeList); + this.visitor.setCFBlockInfo(cfBlockInfo); this.visitor.setMethodReturnType(methodReturnType); this.visitor.setVariableType(variableTypes); diff --git a/src/clegoues/genprog4java/java/JavaStatement.java b/src/clegoues/genprog4java/java/JavaStatement.java index b045b9b0..8ddc7530 100644 --- a/src/clegoues/genprog4java/java/JavaStatement.java +++ b/src/clegoues/genprog4java/java/JavaStatement.java @@ -42,50 +42,7 @@ import java.util.Map; import java.util.Set; -import org.eclipse.jdt.core.dom.ASTMatcher; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.ASTVisitor; -import org.eclipse.jdt.core.dom.ArrayAccess; -import org.eclipse.jdt.core.dom.ArrayType; -import org.eclipse.jdt.core.dom.Block; -import org.eclipse.jdt.core.dom.CastExpression; -import org.eclipse.jdt.core.dom.ClassInstanceCreation; -import org.eclipse.jdt.core.dom.ConditionalExpression; -import org.eclipse.jdt.core.dom.DoStatement; -import org.eclipse.jdt.core.dom.EnhancedForStatement; -import org.eclipse.jdt.core.dom.Expression; -import org.eclipse.jdt.core.dom.FieldAccess; -import org.eclipse.jdt.core.dom.ForStatement; -import org.eclipse.jdt.core.dom.IBinding; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.IVariableBinding; -import org.eclipse.jdt.core.dom.IfStatement; -import org.eclipse.jdt.core.dom.InfixExpression; -import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.NullLiteral; -import org.eclipse.jdt.core.dom.NumberLiteral; -import org.eclipse.jdt.core.dom.ParameterizedType; -import org.eclipse.jdt.core.dom.ParenthesizedExpression; -import org.eclipse.jdt.core.dom.PrimitiveType; -import org.eclipse.jdt.core.dom.QualifiedName; -import org.eclipse.jdt.core.dom.QualifiedType; -import org.eclipse.jdt.core.dom.ReturnStatement; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.SimpleType; -import org.eclipse.jdt.core.dom.Statement; -import org.eclipse.jdt.core.dom.SuperFieldAccess; -import org.eclipse.jdt.core.dom.SuperMethodInvocation; -import org.eclipse.jdt.core.dom.SwitchStatement; -import org.eclipse.jdt.core.dom.ThisExpression; -import org.eclipse.jdt.core.dom.Type; -import org.eclipse.jdt.core.dom.TypeDeclaration; -import org.eclipse.jdt.core.dom.UnionType; -import org.eclipse.jdt.core.dom.VariableDeclarationFragment; -import org.eclipse.jdt.core.dom.VariableDeclarationStatement; -import org.eclipse.jdt.core.dom.WhileStatement; -import org.eclipse.jdt.core.dom.WildcardType; +import org.eclipse.jdt.core.dom.*; import clegoues.genprog4java.rep.JavaRepresentation; @@ -97,17 +54,15 @@ public class JavaStatement implements Comparable{ private int stmtId; // unique private Set mustBeInScope; private Set namesDeclared; + private boolean isLastStatementInControlFlow; - public void setClassInfo(ClassInfo ci) { - this.classInfo = ci; - } - - public Set getNamesDeclared() { - return this.namesDeclared; + public JavaStatement(int stmtCounter, ASTNode node) { + this.setStmtId(stmtCounter); + this.setASTNode(node); } - public void setNamesDeclared(Set names) { - this.namesDeclared = names; + public void setClassInfo(ClassInfo ci) { + this.classInfo = ci; } public ClassInfo getClassInfo() { @@ -130,6 +85,14 @@ public void setASTNode(ASTNode node) { this.astNode = node; } + public Set getNamesDeclared() { + return this.namesDeclared; + } + + public void setNamesDeclared(Set names) { + this.namesDeclared = names; + } + public Set getRequiredNames() { return mustBeInScope; } @@ -138,6 +101,14 @@ public void setRequiredNames(Set scopes) { this.mustBeInScope = scopes; } + public void setIsLastStatementInControlFlow(boolean isLast) { + this.isLastStatementInControlFlow = isLast; + } + + public boolean isLastStatementInControlFlow() { + return isLastStatementInControlFlow; + } + public String toString() { if (astNode != null) return this.astNode.toString(); @@ -146,6 +117,7 @@ public String toString() { } // method to get the statemetn parent of an ASTnode. We traverse the ast upwards until the parent node is an instance of statement + private ASTNode getParent(ASTNode node) { ASTNode parent = node.getParent(); while(!(parent instanceof Statement)){ @@ -174,12 +146,12 @@ public boolean visit(ArrayAccess node) { if(!arrayAccesses.containsKey(parent)){ List arraynodes = new ArrayList(); arraynodes.add(node); - arrayAccesses.put(parent, arraynodes); + arrayAccesses.put(parent, arraynodes); }else{ List arraynodes = (List) arrayAccesses.get(parent); if(!arraynodes.contains(node)) arraynodes.add(node); - arrayAccesses.put(parent, arraynodes); + arrayAccesses.put(parent, arraynodes); } } return true; @@ -223,7 +195,7 @@ private ASTNode statementParent(ASTNode node) { } private boolean isNullCheckable(ASTNode node) { - if(node == null) + if(node == null) return false; if(node instanceof SimpleName) { SimpleName asSimpleName = (SimpleName) node; @@ -233,7 +205,7 @@ private boolean isNullCheckable(ASTNode node) { return node instanceof ArrayAccess || node instanceof CastExpression || node instanceof ClassInstanceCreation || node instanceof SuperMethodInvocation || node instanceof ParenthesizedExpression || - node instanceof SuperFieldAccess || node instanceof SuperMethodInvocation + node instanceof SuperFieldAccess || node instanceof SuperMethodInvocation ; /* maybe: ArrayCreation */ } @@ -271,7 +243,7 @@ public Map> getCasts() { this.getASTNode().accept(new ASTVisitor() { public boolean visit(CastExpression node) { - ASTNode parent = getParent(node); + ASTNode parent = getParent(node); List thisParentsCasts; if(casts.containsKey(parent)) { thisParentsCasts = casts.get(parent); @@ -343,7 +315,7 @@ public Map> getExtendableConditionalExpressions() { this.getASTNode().accept(new ASTVisitor() { public boolean visit(IfStatement node) { - handleCondition(node.getExpression()); + handleCondition(node.getExpression()); return true; } @@ -397,7 +369,7 @@ public Map> getReplacableMethodParameters() { private void handleCandidateReplacements(List args) { for(Expression arg : args) { ITypeBinding paramType = arg.resolveTypeBinding(); - if(paramType != null) { + if(paramType != null) { String typName = paramType.getName(); List replacements = JavaSemanticInfo.getMethodParamReplacementExpressions(methodName, md, typName); String argAsString = arg.toString(); @@ -435,7 +407,7 @@ public boolean visit(SuperMethodInvocation node) { } @SuppressWarnings("unchecked") - public boolean visit(MethodInvocation node) { + public boolean visit(MethodInvocation node) { List args = node.arguments(); handleCandidateReplacements(args); return true; @@ -448,7 +420,7 @@ public boolean visit(MethodInvocation node) { } - // FIXME: if the fix set is expanded, clear any of these caches?? + // FIXME: if the fix set is expanded, clear any of these caches?? private boolean paramTypesMatch(ArrayList firstList, ArrayList secondList) { for(int i = 0; i < firstList.size(); i++) { @@ -466,7 +438,7 @@ private ArrayList getParamTypes(IMethodBinding mb) { } private boolean compatibleMethodMatch(IMethodBinding method1, IMethodBinding method2, boolean checkShrinkable) { - if(method2.equals(method1) || (checkShrinkable && !method2.getName().equals(method1.getName()))) + if(method2.equals(method1) || (checkShrinkable && !method2.getName().equals(method1.getName()))) return false; ITypeBinding returnType1 = method1.getReturnType(); @@ -474,8 +446,8 @@ private boolean compatibleMethodMatch(IMethodBinding method1, IMethodBinding met if(!returnType1.isAssignmentCompatible(returnType2)) return false; - ArrayList paramTypes1 = getParamTypes(method1); - ArrayList paramTypes2 = getParamTypes(method2); + ArrayList paramTypes1 = getParamTypes(method1); + ArrayList paramTypes2 = getParamTypes(method2); if(checkShrinkable && (paramTypes2.size() < paramTypes1.size()) || (!checkShrinkable && (paramTypes2.size() == paramTypes1.size() ))) { @@ -585,7 +557,7 @@ public boolean visit(MethodInvocation node) { }); } - return extendableParameterMethods; + return extendableParameterMethods; } private List indexedCollectionObjects = null; @@ -604,7 +576,7 @@ public boolean visit(MethodInvocation node) { case "subList": break; case "add": - case "addAll": + case "addAll": if(node.arguments().size() > 1) { break; } @@ -618,10 +590,10 @@ public boolean visit(MethodInvocation node) { } ITypeBinding methodCallTypeBinding = methodCall.resolveTypeBinding(); - if(methodCallTypeBinding == null) + if(methodCallTypeBinding == null) return true; ITypeBinding td = methodCallTypeBinding.getTypeDeclaration(); - if(td == null) + if(td == null) return true; String name = td.getName(); ITypeBinding decl = methodCallTypeBinding.getTypeDeclaration(); @@ -629,7 +601,7 @@ public boolean visit(MethodInvocation node) { decl = decl.getSuperclass().getTypeDeclaration(); name = decl.getName(); } - if(!name.equals("AbstractList")) { + if(!name.equals("AbstractList")) { return true; } indexedCollectionObjects.add(node); @@ -659,7 +631,7 @@ collect method invocations of (@\textbf{[collection objects]}@) in B and put the insert a conditional expression that checks whether the index parameter is smaller than the size of its collection object } } -concatenate conditions using AND +concatenate conditions using AND if B include return statement { @@ -828,15 +800,6 @@ public boolean visit(MethodInvocation node) { return candidateMethodReplacements; } - - public ASTNode blockThatContainsThisStatement(){ - ASTNode parent = this.getASTNode().getParent(); - while(parent != null && !(parent instanceof Block)){ - parent = parent.getParent(); - } - return parent; - } - private static int howManyReturns = 0; public static boolean hasMoreThanOneReturn(MethodDeclaration method){ @@ -854,8 +817,8 @@ public boolean visit(ReturnStatement node) { public boolean canBeDeleted() { ASTNode faultyNode = this.getASTNode(); ASTNode parent = faultyNode.getParent(); - //Heuristic: Don't remove returns from functions that have only one return statement. - if(faultyNode instanceof ReturnStatement){ + // Heuristic: Don't remove returns from functions that have only one return statement. + if (faultyNode instanceof ReturnStatement){ parent = ASTUtils.getEnclosingMethod(this.getASTNode()); if(parent != null && parent instanceof MethodDeclaration) { if(!hasMoreThanOneReturn((MethodDeclaration)parent)) @@ -863,10 +826,14 @@ public boolean canBeDeleted() { } } + // Heuristic: don't remove variable declarations, other things need that + if (ASTUtils.isVariableDeclaration(faultyNode)) { + return false; + } + return true; } - private List casteeExpressions = null; public List getCasteeExpressions(){ if(casteeExpressions == null) { @@ -932,7 +899,7 @@ public boolean visit(ArrayAccess node) { return toReplaceCasteeExpressions; } - + private List casterTypes = null; public List getCasterTypes(){ if(casterTypes == null) { @@ -959,6 +926,7 @@ public boolean visit(CastExpression node) { } private List toReplaceCasterTypes = null; + public List getTypesToReplaceCaster(){ if(toReplaceCasterTypes == null) { toReplaceCasterTypes = new LinkedList(); @@ -1022,12 +990,12 @@ public boolean visit(WildcardType node) { }); } - return toReplaceCasterTypes; + return toReplaceCasterTypes; } public boolean isLikelyAConstructor() { ASTNode enclosingMethod = ASTUtils.getEnclosingMethod(this.getASTNode()); - return (enclosingMethod != null) && (enclosingMethod instanceof MethodDeclaration) && + return (enclosingMethod != null) && (enclosingMethod instanceof MethodDeclaration) && ((MethodDeclaration) enclosingMethod).isConstructor(); } @@ -1037,7 +1005,7 @@ public boolean parentMethodReturnsVoid() { // FIXME fix this. MethodDeclaration asMd = (MethodDeclaration) enclosingMethod; Type returnType = asMd.getReturnType2(); if(returnType != null) { - String asStr = returnType.toString(); + String asStr = returnType.toString(); return asStr.equalsIgnoreCase("void") || asStr.equalsIgnoreCase("null"); } else { return true; @@ -1048,30 +1016,12 @@ public boolean parentMethodReturnsVoid() { // FIXME fix this. public boolean isWithinLoopOrCase() { ASTNode buggyNode = this.getASTNode(); - if(buggyNode instanceof SwitchStatement - || buggyNode instanceof ForStatement - || buggyNode instanceof WhileStatement - || buggyNode instanceof DoStatement - || buggyNode instanceof EnhancedForStatement) - return true; - - while(buggyNode.getParent() != null){ - buggyNode = buggyNode.getParent(); - if(buggyNode instanceof SwitchStatement - || buggyNode instanceof ForStatement - || buggyNode instanceof WhileStatement - || buggyNode instanceof DoStatement - || buggyNode instanceof EnhancedForStatement) - return true; - } - return false; - } - public void setInfo(int stmtCounter, ASTNode node) { - this.setStmtId(stmtCounter); - this.setASTNode(node); + // less efficient implementation than before but .... + return ASTUtils.getEnclosing(SwitchStatement.class, buggyNode) != null + || ASTUtils.getEnclosing(ForStatement.class, buggyNode) != null + || ASTUtils.getEnclosing(WhileStatement.class, buggyNode) != null + || ASTUtils.getEnclosing(DoStatement.class, buggyNode) != null + || ASTUtils.getEnclosing(EnhancedForStatement.class, buggyNode) != null; } - - - } diff --git a/src/clegoues/genprog4java/java/SemanticInfoVisitor.java b/src/clegoues/genprog4java/java/SemanticInfoVisitor.java index d0a6e487..8ce1c09f 100644 --- a/src/clegoues/genprog4java/java/SemanticInfoVisitor.java +++ b/src/clegoues/genprog4java/java/SemanticInfoVisitor.java @@ -40,29 +40,7 @@ import java.util.Stack; import java.util.TreeSet; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.ASTVisitor; -import org.eclipse.jdt.core.dom.Assignment; -import org.eclipse.jdt.core.dom.Block; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.EnhancedForStatement; -import org.eclipse.jdt.core.dom.Expression; -import org.eclipse.jdt.core.dom.FieldAccess; -import org.eclipse.jdt.core.dom.FieldDeclaration; -import org.eclipse.jdt.core.dom.ForStatement; -import org.eclipse.jdt.core.dom.IBinding; -import org.eclipse.jdt.core.dom.IVariableBinding; -import org.eclipse.jdt.core.dom.ImportDeclaration; -import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.Modifier; -import org.eclipse.jdt.core.dom.Name; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.SingleVariableDeclaration; -import org.eclipse.jdt.core.dom.SuperFieldAccess; -import org.eclipse.jdt.core.dom.TypeDeclaration; -import org.eclipse.jdt.core.dom.VariableDeclarationExpression; -import org.eclipse.jdt.core.dom.VariableDeclarationFragment; -import org.eclipse.jdt.core.dom.VariableDeclarationStatement; +import org.eclipse.jdt.core.dom.*; import clegoues.genprog4java.rep.JavaRepresentation; @@ -70,6 +48,7 @@ public class SemanticInfoVisitor extends ASTVisitor { private List nodeSet; private ScopeInfo scopes; + private CFBlockInfo cfBlockInfo; private boolean containsFinalVar = false; private Stack finalVarStack = new Stack(); @@ -91,10 +70,10 @@ public class SemanticInfoVisitor extends ASTVisitor { private Stack> loopScopeStack = new Stack>(); // declared or imported; primitive types are always available; - private HashSet availableTypes; + private HashSet availableTypes; // it might make sense to store these separately, but for now, this will do // upon reflection, it makes more sense to do add these after the whole thing has been parsed - private HashSet availableMethodsAndFields; + private HashSet availableMethodsAndFields; private HashSet namesDeclared = new HashSet(); private Stack> namesDeclaredStack = new Stack>(); @@ -122,7 +101,7 @@ public void preVisit(ASTNode node) { finalVarStack.push(containsFinalVar); containsFinalVar = false; - if (JavaRepresentation.canRepair(node)) + if (JavaRepresentation.canRepair(node)) { // add scope information TreeSet newScope = new TreeSet(); @@ -133,9 +112,11 @@ public void preVisit(ASTNode node) { this.scopes.addToClassScope(this.availableMethodsAndFields); this.nodeSet.add(node); + // only register nodes we will later keep track of. + this.cfBlockInfo.registerNode(node); } - if(node instanceof EnhancedForStatement || + if(node instanceof EnhancedForStatement || node instanceof ForStatement) { loopScopeStack.push(currentLoopScope); currentLoopScope = new HashSet(currentLoopScope); @@ -146,17 +127,8 @@ public void preVisit(ASTNode node) { currentMethodScope = new HashSet(currentMethodScope); } - // if(node instanceof EnhancedForStatement || - // node instanceof ForStatement || - // node instanceof DoStatement || - // node instanceof IfStatement || - // node instanceof SwitchStatement || - // node instanceof TryStatement || - // node instanceof WhileStatement) { - // - // } - // - // + + this.namesDeclaredStack.push(namesDeclared); namesDeclared = new HashSet(); super.preVisit(node); @@ -190,6 +162,8 @@ public void postVisit(ASTNode node) { this.scopes.addRequiredNames(node,new HashSet(this.requiredNames)); this.scopes.setContainsFinalVarDecl(node, containsFinalVar); this.scopes.setNamesDeclared(node, new HashSet(this.namesDeclared)); + + this.cfBlockInfo.endOfNode(node); } if (node instanceof Block) { @@ -412,6 +386,10 @@ public void setScopeList(ScopeInfo scopeList) { this.scopes = scopeList; } + public void setCFBlockInfo(CFBlockInfo cfBlockInfo) { + this.cfBlockInfo = cfBlockInfo; + } + // @Override // public boolean visit(Initializer node) { // List mods = node.modifiers(); // FIXME need to deal with static. diff --git a/src/clegoues/genprog4java/localization/DefaultLocalization.java b/src/clegoues/genprog4java/localization/DefaultLocalization.java index 2170814c..9362c18a 100644 --- a/src/clegoues/genprog4java/localization/DefaultLocalization.java +++ b/src/clegoues/genprog4java/localization/DefaultLocalization.java @@ -6,8 +6,6 @@ import static clegoues.util.ConfigurationBuilder.STRING; import org.apache.log4j.Logger; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.MethodRef; import org.jacoco.core.analysis.Analyzer; import org.jacoco.core.analysis.CoverageBuilder; import org.jacoco.core.analysis.IClassCoverage; @@ -36,12 +34,11 @@ import java.util.Set; import java.util.TreeSet; -import clegoues.genprog4java.Search.GiveUpException; -import clegoues.genprog4java.Search.Search; +import clegoues.genprog4java.search.GiveUpException; +import clegoues.genprog4java.search.Search; import clegoues.genprog4java.fitness.Fitness; import clegoues.genprog4java.fitness.TestCase; import clegoues.genprog4java.java.ClassInfo; -import clegoues.genprog4java.java.JavaStatement; import clegoues.genprog4java.main.Configuration; import clegoues.genprog4java.mut.WeightedMutation; import clegoues.genprog4java.rep.JavaRepresentation; @@ -140,8 +137,8 @@ public DefaultLocalization(Representation orig) throws IOException, UnexpectedCo this.original = orig; this.computeLocalization(); - if(justTestingFaultLoc == true){ - logger.info("Fault localization was peprformed successfully"); + if(justTestingFaultLoc){ + logger.info("Fault localization was performed successfully"); System.exit(0); } } diff --git a/src/clegoues/genprog4java/localization/Localization.java b/src/clegoues/genprog4java/localization/Localization.java index f051cac1..a399dde2 100644 --- a/src/clegoues/genprog4java/localization/Localization.java +++ b/src/clegoues/genprog4java/localization/Localization.java @@ -5,7 +5,7 @@ import java.io.IOException; import java.util.ArrayList; -import clegoues.genprog4java.Search.GiveUpException; +import clegoues.genprog4java.search.GiveUpException; import clegoues.genprog4java.rep.WeightedAtom; import clegoues.util.ConfigurationBuilder; diff --git a/src/clegoues/genprog4java/main/Main.java b/src/clegoues/genprog4java/main/Main.java index 74cdeb3e..bd17bf94 100644 --- a/src/clegoues/genprog4java/main/Main.java +++ b/src/clegoues/genprog4java/main/Main.java @@ -39,12 +39,12 @@ import org.apache.log4j.BasicConfigurator; import org.apache.log4j.Logger; -import clegoues.genprog4java.Search.BruteForce; -import clegoues.genprog4java.Search.GeneticProgramming; -import clegoues.genprog4java.Search.OracleSearch; -import clegoues.genprog4java.Search.Population; -import clegoues.genprog4java.Search.RandomSingleEdit; -import clegoues.genprog4java.Search.Search; +import clegoues.genprog4java.search.BruteForce; +import clegoues.genprog4java.search.GeneticProgramming; +import clegoues.genprog4java.search.OracleSearch; +import clegoues.genprog4java.search.Population; +import clegoues.genprog4java.search.RandomSingleEdit; +import clegoues.genprog4java.search.Search; import clegoues.genprog4java.fitness.Fitness; import clegoues.genprog4java.localization.DefaultLocalization; import clegoues.genprog4java.localization.Localization; diff --git a/src/clegoues/genprog4java/mut/edits/java/JavaAppendOperation.java b/src/clegoues/genprog4java/mut/edits/java/JavaAppendOperation.java index 0e922998..e6328821 100644 --- a/src/clegoues/genprog4java/mut/edits/java/JavaAppendOperation.java +++ b/src/clegoues/genprog4java/mut/edits/java/JavaAppendOperation.java @@ -29,8 +29,8 @@ public void edit(final ASTRewrite rewriter) { Block newNode = locationNode.getAST().newBlock(); if(locationNode instanceof Statement && fixCodeNode instanceof Statement){ - ASTNode stm1 = (Statement)locationNode; - ASTNode stm2 = (Statement)fixCodeNode; + ASTNode stm1 = locationNode; + ASTNode stm2 = fixCodeNode; stm1 = ASTNode.copySubtree(locationNode.getAST(), stm1); stm2 = ASTNode.copySubtree(fixCodeNode.getAST(), stm2); diff --git a/src/clegoues/genprog4java/mut/edits/java/JavaEditFactory.java b/src/clegoues/genprog4java/mut/edits/java/JavaEditFactory.java index ec1bbb0c..5074d4c1 100644 --- a/src/clegoues/genprog4java/mut/edits/java/JavaEditFactory.java +++ b/src/clegoues/genprog4java/mut/edits/java/JavaEditFactory.java @@ -6,22 +6,9 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; import org.apache.log4j.Logger; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.Block; -import org.eclipse.jdt.core.dom.BreakStatement; -import org.eclipse.jdt.core.dom.ConstructorInvocation; -import org.eclipse.jdt.core.dom.Expression; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.MethodDeclaration; -import org.eclipse.jdt.core.dom.ReturnStatement; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.Statement; -import org.eclipse.jdt.core.dom.SuperConstructorInvocation; -import org.eclipse.jdt.core.dom.ThrowStatement; -import org.eclipse.jdt.core.dom.Type; +import org.eclipse.jdt.core.dom.*; import clegoues.genprog4java.java.ASTUtils; import clegoues.genprog4java.java.JavaStatement; @@ -112,7 +99,7 @@ private List scopeHelper(Location stmtId, JavaRepresentation varia // I *believe* this is just variable names and doesn't check required // types, which are also collected // at parse time and thus could be considered here. - if(!JavaRepresentation.semanticInfo.scopeCheckOK(potentiallyBuggyStmt, potentialFixStmt)) { + if (!JavaRepresentation.semanticInfo.scopeCheckOK(potentiallyBuggyStmt, potentialFixStmt)) { continue; } @@ -122,39 +109,27 @@ private List scopeHelper(Location stmtId, JavaRepresentation varia // different from what is now at that location. // this comes down to our having overloaded statement IDs to mean both location and statement ID // which is a problem I keep meaning to solve. - if(mut != Mutation.APPEND && faultAST.equals(fixAST)) { + if (mut != Mutation.APPEND && faultAST.equals(fixAST)) { continue; } //Heuristic: Do not insert a return statement on a func whose return type is void //Heuristic: Do not insert a return statement in a constructor - if(fixAST instanceof ReturnStatement){ - if(potentiallyBuggyStmt.parentMethodReturnsVoid() || + if (fixAST instanceof ReturnStatement){ + if (potentiallyBuggyStmt.parentMethodReturnsVoid() || potentiallyBuggyStmt.isLikelyAConstructor()) continue; - - //Heuristic: Swapping, Appending or Replacing a return stmt to the middle of a block will make the code after it unreachable - ASTNode parentBlock = potentiallyBuggyStmt.blockThatContainsThisStatement(); - if(parentBlock != null && parentBlock instanceof Block) { - List statementsInBlock = ((Block)parentBlock).statements(); - ASTNode lastStmtInTheBlock = statementsInBlock.get(statementsInBlock.size()-1); - if(!lastStmtInTheBlock.equals(faultAST)){ - continue; - } - } else { - continue; - } - + //If we move a return statement into a function, the parameter in the return must match the function’s return type ASTNode enclosingMethod = ASTUtils.getEnclosingMethod(faultAST); if (enclosingMethod instanceof MethodDeclaration) { String returnType = JavaRepresentation.semanticInfo.returnTypeOfThisMethod(((MethodDeclaration)enclosingMethod).getName().toString()); - if(returnType != null){ + if (returnType != null){ ReturnStatement potFix = (ReturnStatement) fixAST; - if(potFix.getExpression() instanceof SimpleName){ + if (potFix.getExpression() instanceof SimpleName){ String variableType = JavaRepresentation.semanticInfo.getVariableDataTypes().get(potFix.getExpression().toString()); - if( !returnType.equalsIgnoreCase(variableType)){ + if ( !returnType.equalsIgnoreCase(variableType)){ continue; } } @@ -162,13 +137,30 @@ private List scopeHelper(Location stmtId, JavaRepresentation varia } } + //Heuristic: Don't replace/swap returns within functions that have only one return statement + // (unless the replacer is also a return statement); could also check if it's a block or + // other sequence of statements with a return within it, but I'm lazy + if ((!(fixAST instanceof ReturnStatement)) && + faultAST instanceof ReturnStatement) { + ASTNode parent = ASTUtils.getEnclosingMethod(faultAST); + if(parent instanceof MethodDeclaration && + !JavaStatement.hasMoreThanOneReturn((MethodDeclaration)parent)) { + continue; + } + } + + //Heuristc: Don't throw or return in the middle of blocks, leaving unreachable statements + if (fixAST instanceof ReturnStatement || fixAST instanceof ThrowStatement) { + if (!potentiallyBuggyStmt.isLastStatementInControlFlow()) continue; + } + //Heuristic: Inserting methods like this() or super() somewhere that is not the First (or second, if super?) Stmt in the constructor, is wrong - if(fixAST instanceof ConstructorInvocation || + if (fixAST instanceof ConstructorInvocation || fixAST instanceof SuperConstructorInvocation){ - if(mut == Mutation.APPEND) continue; + if (mut == Mutation.APPEND) continue; ASTNode enclosingMethod = ASTUtils.getEnclosingMethod(faultAST); - if (enclosingMethod != null && + if (enclosingMethod != null && enclosingMethod instanceof MethodDeclaration && ((MethodDeclaration) enclosingMethod).isConstructor()) { List statementsInBlock = ((MethodDeclaration) enclosingMethod).getBody().statements(); @@ -181,27 +173,16 @@ private List scopeHelper(Location stmtId, JavaRepresentation varia } } - //Heuristic: Don't allow to move breaks outside of switch stmts + //Heuristic: Don't allow to move breaks or continues outside of switch stmts // OR loops! - // TODO: check for continues as well - if(fixAST instanceof BreakStatement && - !potentiallyBuggyStmt.isWithinLoopOrCase()){ - continue; - } - // FIXME: don't insert returns/throws into the middle of blocks, perhaps? - //Heuristic: Don't replace/swap returns within functions that have only one return statement - // (unless the replacer is also a return statement); could also check if it's a block or - // other sequence of statements with a return within it, but I'm lazy - if((!(fixAST instanceof ReturnStatement)) && - faultAST instanceof ReturnStatement) { - ASTNode parent = ASTUtils.getEnclosingMethod(faultAST); - if(parent instanceof MethodDeclaration && - !JavaStatement.hasMoreThanOneReturn((MethodDeclaration)parent)) { - continue; - } + // and don't cause unreachable statements by moving breaks into the middle of a block + if ((fixAST instanceof BreakStatement || fixAST instanceof ContinueStatement)){ + if (!potentiallyBuggyStmt.isWithinLoopOrCase()) continue; + else if (!potentiallyBuggyStmt.isLastStatementInControlFlow()) continue; } - // if we made it this far without continuing, we're good to go. + + // if we made it this far without continuing, we're good to go. retVal.add(potentialFixAtom); } JavaEditFactory.scopeSafeAtomMap.put(stmtId.getId(), retVal); @@ -241,7 +222,7 @@ public List editSources(JavaRepresentation variant, Location locat int atom = item.getAtom(); List inScopeThere = this.scopeHelper(variant.instantiateLocation(atom, item.getRight()), variant, editType); for (WeightedAtom there : inScopeThere) { - if (there.getAtom() != location.getId()) { + if (there.getAtom() == location.getId()) { JavaStatement potentialFixStmt = variant.getFromCodeBank(there.getAtom()); ASTNode fixAST = potentialFixStmt.getASTNode(); StatementHole stmtHole = new StatementHole((Statement) fixAST, potentialFixStmt.getStmtId()); @@ -266,10 +247,10 @@ public List editSources(JavaRepresentation variant, Location locat List retVal = new LinkedList(); Map> methodReplacements = locationStmt.getCandidateMethodReplacements(); for(Map.Entry> entry : methodReplacements.entrySet()) { - ASTNode replacableMethod = entry.getKey(); + ASTNode replaceableMethod = entry.getKey(); List possibleReplacements = entry.getValue(); for(IMethodBinding possibleReplacement : possibleReplacements) { - MethodInfoHole thisHole = new MethodInfoHole(replacableMethod, locationStmt.getStmtId(), possibleReplacement); + MethodInfoHole thisHole = new MethodInfoHole(replaceableMethod, locationStmt.getStmtId(), possibleReplacement); // method replacer chooses between multiple options uniformly at random retVal.add(new WeightedHole(thisHole)); } diff --git a/src/clegoues/genprog4java/rep/CachingRepresentation.java b/src/clegoues/genprog4java/rep/CachingRepresentation.java index 978953b6..bfb710ea 100644 --- a/src/clegoues/genprog4java/rep/CachingRepresentation.java +++ b/src/clegoues/genprog4java/rep/CachingRepresentation.java @@ -38,10 +38,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; -import java.io.ObjectStreamException; -import java.io.Serializable; import java.util.ArrayList; -import java.util.HashMap; import java.util.List; import org.apache.commons.exec.CommandLine; @@ -49,11 +46,9 @@ import org.apache.commons.exec.ExecuteException; import org.apache.commons.exec.ExecuteWatchdog; import org.apache.commons.exec.PumpStreamHandler; -import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.tuple.Pair; import org.apache.log4j.Logger; -import clegoues.genprog4java.Search.GiveUpException; import clegoues.genprog4java.fitness.Fitness; import clegoues.genprog4java.fitness.FitnessValue; import clegoues.genprog4java.fitness.TestCase; @@ -290,7 +285,6 @@ protected FitnessValue internalTestCase(String sanityExename, CommandLine command = this.internalTestCaseCommand(sanityExename, sanityFilename, thisTest, doingCoverage); - // System.out.println("command: " + command.toString()); ExecuteWatchdog watchdog = new ExecuteWatchdog(96000); DefaultExecutor executor = new DefaultExecutor(); String workingDirectory = System.getProperty("user.dir"); diff --git a/src/clegoues/genprog4java/rep/JavaRepresentation.java b/src/clegoues/genprog4java/rep/JavaRepresentation.java index 03f94131..1db1f3e9 100644 --- a/src/clegoues/genprog4java/rep/JavaRepresentation.java +++ b/src/clegoues/genprog4java/rep/JavaRepresentation.java @@ -33,84 +33,9 @@ package clegoues.genprog4java.rep; -import java.io.BufferedWriter; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileWriter; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.ObjectStreamException; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; - -import javax.tools.JavaCompiler; -import javax.tools.JavaFileObject; -import javax.tools.ToolProvider; - -import org.apache.commons.exec.CommandLine; -import org.apache.commons.io.FileUtils; -import org.apache.commons.lang3.tuple.Pair; -import org.apache.log4j.Logger; -import org.eclipse.jdt.core.dom.AST; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.AssertStatement; -import org.eclipse.jdt.core.dom.Block; -import org.eclipse.jdt.core.dom.BreakStatement; -import org.eclipse.jdt.core.dom.CompilationUnit; -import org.eclipse.jdt.core.dom.ConstructorInvocation; -import org.eclipse.jdt.core.dom.ContinueStatement; -import org.eclipse.jdt.core.dom.DoStatement; -import org.eclipse.jdt.core.dom.EmptyStatement; -import org.eclipse.jdt.core.dom.EnhancedForStatement; -import org.eclipse.jdt.core.dom.ExpressionStatement; -import org.eclipse.jdt.core.dom.ForStatement; -import org.eclipse.jdt.core.dom.IfStatement; -import org.eclipse.jdt.core.dom.LabeledStatement; -import org.eclipse.jdt.core.dom.MethodRef; -import org.eclipse.jdt.core.dom.ReturnStatement; -import org.eclipse.jdt.core.dom.SuperConstructorInvocation; -import org.eclipse.jdt.core.dom.SwitchCase; -import org.eclipse.jdt.core.dom.SwitchStatement; -import org.eclipse.jdt.core.dom.SynchronizedStatement; -import org.eclipse.jdt.core.dom.ThrowStatement; -import org.eclipse.jdt.core.dom.TryStatement; -import org.eclipse.jdt.core.dom.TypeDeclarationStatement; -import org.eclipse.jdt.core.dom.VariableDeclarationStatement; -import org.eclipse.jdt.core.dom.WhileStatement; -import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; -import org.eclipse.jface.text.BadLocationException; -import org.eclipse.jface.text.Document; -import org.eclipse.jface.text.IDocument; -import org.eclipse.text.edits.MalformedTreeException; -import org.eclipse.text.edits.TextEdit; -import org.jacoco.core.analysis.Analyzer; -import org.jacoco.core.analysis.CoverageBuilder; -import org.jacoco.core.analysis.IClassCoverage; -import org.jacoco.core.analysis.ICounter; -import org.jacoco.core.data.ExecutionData; -import org.jacoco.core.data.ExecutionDataReader; -import org.jacoco.core.data.ExecutionDataStore; -import org.jacoco.core.data.IExecutionDataVisitor; -import org.jacoco.core.data.ISessionInfoVisitor; -import org.jacoco.core.data.SessionInfo; - -import clegoues.genprog4java.Search.GiveUpException; -import clegoues.genprog4java.Search.Search; +import clegoues.genprog4java.search.Search; import clegoues.genprog4java.fitness.TestCase; -import clegoues.genprog4java.java.ASTUtils; -import clegoues.genprog4java.java.ClassInfo; -import clegoues.genprog4java.java.JavaParser; -import clegoues.genprog4java.java.JavaSemanticInfo; -import clegoues.genprog4java.java.JavaSourceInfo; -import clegoues.genprog4java.java.JavaStatement; -import clegoues.genprog4java.java.ScopeInfo; +import clegoues.genprog4java.java.*; import clegoues.genprog4java.localization.Localization; import clegoues.genprog4java.localization.Location; import clegoues.genprog4java.main.Configuration; @@ -123,6 +48,23 @@ import clegoues.genprog4java.mut.holes.java.JavaLocation; import clegoues.util.ConfigurationBuilder; import clegoues.util.GlobalUtils; +import org.apache.commons.exec.CommandLine; +import org.apache.commons.io.FileUtils; +import org.apache.commons.lang3.tuple.Pair; +import org.apache.log4j.Logger; +import org.eclipse.jdt.core.dom.*; +import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.Document; +import org.eclipse.jface.text.IDocument; +import org.eclipse.text.edits.MalformedTreeException; +import org.eclipse.text.edits.TextEdit; + +import javax.tools.JavaCompiler; +import javax.tools.JavaFileObject; +import javax.tools.ToolProvider; +import java.io.*; +import java.util.*; public class JavaRepresentation extends CachingRepresentation { @@ -156,13 +98,23 @@ public JavaRepresentation() { public List availableMutations(Location atomId) { List retVal = new LinkedList(); for (WeightedMutation mutation : Search.availableMutations) { - if(this.doesEditApply(atomId, (Mutation) mutation.getKey())) { - retVal.add(new WeightedMutation((Mutation) mutation.getKey(), (Double) mutation.getValue())); + if(this.doesEditApply(atomId, mutation.getKey())) { + retVal.add(new WeightedMutation(mutation.getKey(), mutation.getValue())); } } return retVal; } + @Override + public boolean hasAvailableMutations(Location atomId) { + for (WeightedMutation mutation : Search.availableMutations) { + if(this.doesEditApply(atomId, mutation.getKey())) { + return true; + } + } + return false; + } + public ArrayList atomIDofSourceLine(int lineno) { return sourceInfo.atomIDofSourceLine(lineno); } @@ -175,7 +127,8 @@ public ClassInfo getFileFromStmt(int stmtId){ public void fromSource(ClassInfo pair, String path, File sourceFile) throws IOException { ScopeInfo scopeInfo = new ScopeInfo(); - JavaParser myParser = new JavaParser(scopeInfo); + CFBlockInfo cfBlockInfo = new CFBlockInfo(); + JavaParser myParser = new JavaParser(scopeInfo, cfBlockInfo); String source = FileUtils.readFileToString(sourceFile); sourceInfo.addToOriginalSource(pair, source); @@ -190,16 +143,17 @@ public void fromSource(ClassInfo pair, String path, File sourceFile) throws IOEx for (ASTNode node : stmts) { if (JavaRepresentation.canRepair(node)) { - JavaStatement s = new JavaStatement(); - s.setStmtId(stmtCounter); - s.setClassInfo(pair); - s.setInfo(stmtCounter, node); + JavaStatement s = new JavaStatement(stmtCounter, node); stmtCounter++; - sourceInfo.augmentLineInfo(s.getStmtId(), node); - sourceInfo.storeStmtInfo(s, pair); + s.setClassInfo(pair); s.setRequiredNames(scopeInfo.getRequiredNames(node)); s.setNamesDeclared(scopeInfo.getNamesDeclared(node)); + s.setIsLastStatementInControlFlow(cfBlockInfo.isLastStatementInCFBlock(node)); + + sourceInfo.augmentLineInfo(s.getStmtId(), node); + sourceInfo.storeStmtInfo(s, pair); + scopeInfo.addToClassScope(knownTypesInScope); scopeInfo.addToClassScope(knownMethodsAndFields); @@ -226,28 +180,7 @@ public void fromSource(ClassInfo pair) throws IOException { public static boolean canRepair(ASTNode node) { // FIXME: variable declarations that have bodies? Or; difference between "can repair" and "can move/delete/replace" - return node instanceof AssertStatement - || node instanceof Block - || node instanceof BreakStatement - || node instanceof ConstructorInvocation - || node instanceof ContinueStatement - || node instanceof DoStatement - || node instanceof EmptyStatement - || node instanceof EnhancedForStatement - || node instanceof ExpressionStatement - || node instanceof ForStatement - || node instanceof IfStatement - || node instanceof LabeledStatement - || node instanceof ReturnStatement - || node instanceof SuperConstructorInvocation - || node instanceof SwitchCase - || node instanceof SwitchStatement - || node instanceof SynchronizedStatement - || node instanceof ThrowStatement - || node instanceof TryStatement - || node instanceof TypeDeclarationStatement - || node instanceof VariableDeclarationStatement - || node instanceof WhileStatement; + return node instanceof Statement; } public ArrayList getGenome() { diff --git a/src/clegoues/genprog4java/rep/Representation.java b/src/clegoues/genprog4java/rep/Representation.java index 573624e2..d8c13ba6 100644 --- a/src/clegoues/genprog4java/rep/Representation.java +++ b/src/clegoues/genprog4java/rep/Representation.java @@ -40,14 +40,12 @@ import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.Set; import org.apache.commons.exec.CommandLine; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.tuple.Pair; import org.apache.log4j.Logger; -import clegoues.genprog4java.Search.GiveUpException; import clegoues.genprog4java.fitness.FitnessValue; import clegoues.genprog4java.fitness.TestCase; import clegoues.genprog4java.java.ClassInfo; @@ -137,6 +135,8 @@ public abstract void load(ArrayList classNames) throws IOException, public abstract List availableMutations( Location faultyLocation); + public abstract boolean hasAvailableMutations(Location faultyLocation); + protected transient int myHashCode = -1; @Override public int hashCode() { diff --git a/src/clegoues/genprog4java/Search/BruteForce.java b/src/clegoues/genprog4java/search/BruteForce.java similarity index 97% rename from src/clegoues/genprog4java/Search/BruteForce.java rename to src/clegoues/genprog4java/search/BruteForce.java index 930d2d32..fa7a43a9 100644 --- a/src/clegoues/genprog4java/Search/BruteForce.java +++ b/src/clegoues/genprog4java/search/BruteForce.java @@ -1,14 +1,10 @@ -package clegoues.genprog4java.Search; +package clegoues.genprog4java.search; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.Set; import java.util.TreeSet; import org.apache.commons.lang3.tuple.Pair; diff --git a/src/clegoues/genprog4java/Search/GeneticProgramming.java b/src/clegoues/genprog4java/search/GeneticProgramming.java similarity index 97% rename from src/clegoues/genprog4java/Search/GeneticProgramming.java rename to src/clegoues/genprog4java/search/GeneticProgramming.java index 04b1dd17..edd396b9 100644 --- a/src/clegoues/genprog4java/Search/GeneticProgramming.java +++ b/src/clegoues/genprog4java/search/GeneticProgramming.java @@ -1,8 +1,7 @@ -package clegoues.genprog4java.Search; +package clegoues.genprog4java.search; import clegoues.genprog4java.fitness.Fitness; import clegoues.genprog4java.mut.EditOperation; -import clegoues.genprog4java.rep.JavaRepresentation; import clegoues.genprog4java.rep.Representation; public class GeneticProgramming extends Search{ diff --git a/src/clegoues/genprog4java/Search/GiveUpException.java b/src/clegoues/genprog4java/search/GiveUpException.java similarity index 58% rename from src/clegoues/genprog4java/Search/GiveUpException.java rename to src/clegoues/genprog4java/search/GiveUpException.java index a9232f16..b02c88e7 100644 --- a/src/clegoues/genprog4java/Search/GiveUpException.java +++ b/src/clegoues/genprog4java/search/GiveUpException.java @@ -1,4 +1,4 @@ -package clegoues.genprog4java.Search; +package clegoues.genprog4java.search; public class GiveUpException extends Exception{ diff --git a/src/clegoues/genprog4java/Search/OracleSearch.java b/src/clegoues/genprog4java/search/OracleSearch.java similarity index 94% rename from src/clegoues/genprog4java/Search/OracleSearch.java rename to src/clegoues/genprog4java/search/OracleSearch.java index 012a609d..1e9a1fd2 100644 --- a/src/clegoues/genprog4java/Search/OracleSearch.java +++ b/src/clegoues/genprog4java/search/OracleSearch.java @@ -1,9 +1,7 @@ -package clegoues.genprog4java.Search; +package clegoues.genprog4java.search; import static clegoues.util.ConfigurationBuilder.STRING; -import java.util.Properties; - import clegoues.genprog4java.fitness.Fitness; import clegoues.genprog4java.mut.EditOperation; import clegoues.genprog4java.rep.Representation; diff --git a/src/clegoues/genprog4java/Search/Population.java b/src/clegoues/genprog4java/search/Population.java similarity index 98% rename from src/clegoues/genprog4java/Search/Population.java rename to src/clegoues/genprog4java/search/Population.java index cec92d15..5ff672f4 100644 --- a/src/clegoues/genprog4java/Search/Population.java +++ b/src/clegoues/genprog4java/search/Population.java @@ -31,7 +31,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package clegoues.genprog4java.Search; +package clegoues.genprog4java.search; import static clegoues.util.ConfigurationBuilder.DOUBLE; import static clegoues.util.ConfigurationBuilder.INT; @@ -42,12 +42,10 @@ import java.util.Comparator; import java.util.Iterator; import java.util.List; -import java.util.Properties; import java.util.TreeSet; import org.apache.log4j.Logger; -import clegoues.genprog4java.fitness.Fitness; import clegoues.genprog4java.main.Configuration; import clegoues.genprog4java.mut.EditOperation; import clegoues.genprog4java.rep.Representation; @@ -56,7 +54,7 @@ public class Population implements Iterable>{ - protected static Logger logger = Logger.getLogger(Fitness.class); + protected static Logger logger = Logger.getLogger(Population.class); public static final ConfigurationBuilder.RegistryToken token = ConfigurationBuilder.getToken(); diff --git a/src/clegoues/genprog4java/Search/RandomSingleEdit.java b/src/clegoues/genprog4java/search/RandomSingleEdit.java similarity index 97% rename from src/clegoues/genprog4java/Search/RandomSingleEdit.java rename to src/clegoues/genprog4java/search/RandomSingleEdit.java index 7bf21d25..e85ef5a6 100644 --- a/src/clegoues/genprog4java/Search/RandomSingleEdit.java +++ b/src/clegoues/genprog4java/search/RandomSingleEdit.java @@ -1,4 +1,4 @@ -package clegoues.genprog4java.Search; +package clegoues.genprog4java.search; import static clegoues.util.ConfigurationBuilder.INT; diff --git a/src/clegoues/genprog4java/Search/RepairFoundException.java b/src/clegoues/genprog4java/search/RepairFoundException.java similarity index 60% rename from src/clegoues/genprog4java/Search/RepairFoundException.java rename to src/clegoues/genprog4java/search/RepairFoundException.java index 09346b3f..fe7c0a1d 100644 --- a/src/clegoues/genprog4java/Search/RepairFoundException.java +++ b/src/clegoues/genprog4java/search/RepairFoundException.java @@ -1,4 +1,4 @@ -package clegoues.genprog4java.Search; +package clegoues.genprog4java.search; public class RepairFoundException extends Exception { diff --git a/src/clegoues/genprog4java/Search/ReplacementModel.java b/src/clegoues/genprog4java/search/ReplacementModel.java similarity index 99% rename from src/clegoues/genprog4java/Search/ReplacementModel.java rename to src/clegoues/genprog4java/search/ReplacementModel.java index 82a35634..6e1e3888 100644 --- a/src/clegoues/genprog4java/Search/ReplacementModel.java +++ b/src/clegoues/genprog4java/search/ReplacementModel.java @@ -1,4 +1,4 @@ -package clegoues.genprog4java.Search; +package clegoues.genprog4java.search; import java.io.BufferedReader; import java.io.FileNotFoundException; @@ -8,7 +8,6 @@ import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Set; import org.apache.commons.lang3.tuple.Pair; import org.eclipse.jdt.core.dom.ASTNode; diff --git a/src/clegoues/genprog4java/Search/Search.java b/src/clegoues/genprog4java/search/Search.java similarity index 93% rename from src/clegoues/genprog4java/Search/Search.java rename to src/clegoues/genprog4java/search/Search.java index 197aa93c..3463152e 100644 --- a/src/clegoues/genprog4java/Search/Search.java +++ b/src/clegoues/genprog4java/search/Search.java @@ -31,9 +31,8 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -package clegoues.genprog4java.Search; +package clegoues.genprog4java.search; -// oneday FIXME: lowercase the package name because it annoys me... import static clegoues.util.ConfigurationBuilder.BOOLEAN; import static clegoues.util.ConfigurationBuilder.DOUBLE; import static clegoues.util.ConfigurationBuilder.INT; @@ -42,13 +41,8 @@ import java.io.File; import java.util.ArrayList; import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; import java.util.LinkedList; import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.TreeSet; import org.apache.commons.lang3.tuple.Pair; import org.apache.log4j.Logger; @@ -57,7 +51,6 @@ import clegoues.genprog4java.localization.Localization; import clegoues.genprog4java.localization.Location; import clegoues.genprog4java.main.Configuration; -import clegoues.genprog4java.mut.EditHole; import clegoues.genprog4java.mut.EditOperation; import clegoues.genprog4java.mut.Mutation; import clegoues.genprog4java.mut.WeightedHole; @@ -263,41 +256,51 @@ public void mutate(Representation variant) throws GiveUpException { ArrayList faultyAtoms = localization.getFaultLocalization(); - ArrayList proMutList = new ArrayList(); boolean foundMutationThatCanApplyToAtom = false; boolean alreadySetAllStmtsToFixLoc = false; while(!foundMutationThatCanApplyToAtom){ + ArrayList proMutList = new ArrayList(); //promut default is 1 // promut stands for proportional mutation rate, which controls the probability that a genome is mutated in the mutation step in terms of the number of genes within it should be modified. for (int i = 0; i < Search.promut; i++) { //chooses a random location - Pair wa = null; - boolean alreadyOnList = false; + Location wa = null; + boolean foundUsableLoc = false; + //If it already picked all the fix atoms from current FixLocalization, then start picking from the ones that remain if(proMutList.size()>=faultyAtoms.size()){ localization.setAllPossibleStmtsToFixLocalization(); alreadySetAllStmtsToFixLoc = true; + faultyAtoms = localization.getFaultLocalization(); } - //only adds the random atom if it is different from the others already added - do { + + //only adds the random atom if it is different from the others already added & it has available mutations + while(!foundUsableLoc) { //chooses a random faulty atom from the subset of faulty atoms - wa = localization.getRandomLocation(Configuration.randomizer.nextDouble()); - // insert a check to see if this location has any valid mutations? If not, look again - // if not, somehow tell the variant to remove that location from the list of faulty atoms - alreadyOnList = proMutList.contains(wa); - } while(alreadyOnList); - proMutList.add((Location)wa); + wa = (Location) GlobalUtils.chooseOneWeighted(new ArrayList(faultyAtoms), Configuration.randomizer.nextDouble()); + + if (wa == null) { + // unable to find another mutation + if (alreadySetAllStmtsToFixLoc && proMutList.isEmpty()) { + // if we've completely exhausted the statements and found nothing + throw new GiveUpException(); + } else { + // continue with for loop or continue on to trying the mutations already in proMutList + break; + } + } else if (!variant.hasAvailableMutations(wa)) { + faultyAtoms.remove(wa); + } else { + foundUsableLoc = !proMutList.contains(wa); + } + } + proMutList.add(wa); + foundMutationThatCanApplyToAtom = true; } + for (Location location : proMutList) { //the available mutations for this stmt List availableMutations = variant.availableMutations(location); - if(availableMutations.isEmpty()){ - if(alreadySetAllStmtsToFixLoc && proMutList.size()>=faultyAtoms.size() && location==proMutList.get(proMutList.size())){ - throw new GiveUpException(); - } - continue; - }else{ - foundMutationThatCanApplyToAtom = true; - } + //choose a mutation List availableMutationsAL = rescaleMutations(availableMutations); Pair chosenMutation = (Pair) GlobalUtils.chooseOneWeighted(availableMutationsAL); @@ -309,7 +312,6 @@ public void mutate(Representation variant) throws GiveUpException { .chooseOneWeighted(new ArrayList(allowed)); variant.performEdit(mut, location, selected.getHole()); } - } } } diff --git a/src/clegoues/genprog4java/search/package-info.java b/src/clegoues/genprog4java/search/package-info.java new file mode 100644 index 00000000..60c39ea7 --- /dev/null +++ b/src/clegoues/genprog4java/search/package-info.java @@ -0,0 +1,4 @@ +/** + * + */ +package clegoues.genprog4java.search;