Skip to content

Commit

Permalink
cross-validation + training for feature envy
Browse files Browse the repository at this point in the history
  • Loading branch information
antoineBarbez committed Oct 11, 2018
1 parent ba5a222 commit 218be1b
Show file tree
Hide file tree
Showing 243 changed files with 43,860 additions and 1,415 deletions.
Binary file modified .DS_Store
Binary file not shown.
Binary file modified assets/.DS_Store
Binary file not shown.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Binary file added assets/jar/JDMetricsFileCreator.jar
Binary file not shown.
File renamed without changes.
Binary file not shown.
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
import org.apache.commons.lang.ArrayUtils;


public class GodClassMetricsFileCreator {
public class DecorMetricsFileCreator {

// The (csv) lines that compose the metrics file
private static List<String> metricsFileLines = new ArrayList<String>();
Expand Down Expand Up @@ -58,7 +58,6 @@ public static void main(String[] args) throws IOException {
}

createMetricsFile(name, repositoryPath, dirsToAnalyze, metricsFilePath);

}

private static void createMetricsFile(
Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
import org.eclipse.jdt.core.dom.CompilationUnit;


public class FeatureEnvyMetricsFileCreator {
public class InCodeMetricsFileCreator {
public static void main(String[] args) {
String name;
String repositoryPath;
Expand Down
134 changes: 134 additions & 0 deletions assets/src/jdeodorant/ASTReader.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.CompilationUnit;

public class ASTReader {
private List<String> types = new ArrayList<String>();
private Set<String> staticEntities = new HashSet<String>();
private Map<String, String> accessorToAccessedFieldMap = new LinkedHashMap<String,String>();
private Map<String, Set<String>> classToEntitySetMap = new LinkedHashMap<String,Set<String>>();
private Map<String, Set<String>> methodToEntitySetMap = new LinkedHashMap<String,Set<String>>();
private Map<String, Set<String>> methodToTargetClassSetMap = new LinkedHashMap<String,Set<String>>();

public ASTReader(String[] sourcePaths) {
int nbProcessedFiles = 0;
for (int i=0;i<sourcePaths.length;i++) {
Collection<File> filesInDirectory = FileUtils.listFiles(new File(sourcePaths[i]), new String[]{"java"}, true);
for (File file : filesInDirectory) {
String fileName = FilenameUtils.normalize(file.getAbsolutePath(), true).substring(sourcePaths[i].length());
try {
parseAST(file, fileName, sourcePaths);
}
catch (IOException e) {
e.printStackTrace();
}

nbProcessedFiles++;
if ((nbProcessedFiles % 500) == 0) {
System.out.println(nbProcessedFiles + " files have been processed.");
}
}
}

replaceAccessorsByAccessedFields(methodToEntitySetMap);

removeSystemMemberAccesses(classToEntitySetMap);
removeSystemMemberAccesses(methodToEntitySetMap);

removeStaticEntities(methodToEntitySetMap);
}

private void parseAST(File file, String fileName, String[] sourcePaths) throws IOException {
String fileString = FileUtils.readFileToString(file, "UTF-8");

ASTParser parser = ASTParser.newParser(AST.JLS8);
parser.setKind(ASTParser.K_COMPILATION_UNIT);
parser.setResolveBindings(true);
parser.setBindingsRecovery(true);
parser.setCompilerOptions(JavaCore.getOptions());
parser.setUnitName(fileName);

parser.setEnvironment(null, sourcePaths, null, true);
parser.setSource(fileString.toCharArray());

CompilationUnit cu = (CompilationUnit) parser.createAST(null);

FileVisitor visitor = new FileVisitor();
cu.accept(visitor);

types.addAll(visitor.getTypes());
staticEntities.addAll(visitor.getStaticEntities());
accessorToAccessedFieldMap.putAll(visitor.getaccessorToAccessedFieldMap());
classToEntitySetMap.putAll(visitor.getClassToEntitySetMap());
methodToEntitySetMap.putAll(visitor.getMethodToEntitySetMap());
methodToTargetClassSetMap.putAll(visitor.getMethodToTargetClassSetMap());
}

public Map<String, Set<String>> getClassToEntitySetMap() {
return this.classToEntitySetMap;
}

public Map<String, Set<String>> getMethodToEntitySetMap() {
return this.methodToEntitySetMap;
}

public Map<String, Set<String>> getMethodToTargetClassSetMap() {
return this.methodToTargetClassSetMap;
}

private void replaceAccessorsByAccessedFields(Map<String, Set<String>> map) {
for(Map.Entry<String, Set<String>> entry : map.entrySet()) {
List<String> entitiesToRemove = new ArrayList<String>();
List<String> entitiesToAdd = new ArrayList<String>();
for(String entity :entry.getValue()) {
if (accessorToAccessedFieldMap.containsKey(entity)) {
entitiesToRemove.add(entity);
entitiesToAdd.add(accessorToAccessedFieldMap.get(entity));
}
}
map.get(entry.getKey()).removeAll(entitiesToRemove);
map.get(entry.getKey()).addAll(entitiesToAdd);
}
}

private void removeSystemMemberAccesses(Map<String, Set<String>> map) {
Pattern p = Pattern.compile(".+:(.+)");

for(Map.Entry<String, Set<String>> entry : map.entrySet()) {
List<String> entitiesToRemove = new ArrayList<String>();
for(String entity :entry.getValue()) {
Matcher m = p.matcher(entity);
if (m.matches())
if(types.contains(m.group(1)))
entitiesToRemove.add(entity);
}
map.get(entry.getKey()).removeAll(entitiesToRemove);
}
}

private void removeStaticEntities(Map<String, Set<String>> map) {
for(Map.Entry<String, Set<String>> entry : map.entrySet()) {
List<String> entitiesToRemove = new ArrayList<String>();
for(String entity :entry.getValue()) {
if (staticEntities.contains(entity))
entitiesToRemove.add(entity);
}
map.get(entry.getKey()).removeAll(entitiesToRemove);
}
}
}
171 changes: 171 additions & 0 deletions assets/src/jdeodorant/ClassVisitor.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,171 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

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.ExpressionStatement;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
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.SingleVariableDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;


public class ClassVisitor extends ASTVisitor {
private Set<String> staticEntities = new HashSet<String>();
private Set<String> entitySet = new HashSet<String>();
private Map<String, String> accessorToAccessedFieldMap = new LinkedHashMap<String,String>();
private Map<String,Set<String>> methodToEntitySetMap = new LinkedHashMap<String,Set<String>>();
private Map<String,Set<String>> methodToTargetClassSetMap = new LinkedHashMap<String,Set<String>>();
private String className;

public ClassVisitor(String className) {
this.className = className;
}

public Set<String> getStaticEntities() {
return this.staticEntities;
}

public Set<String> getEntitySet() {
return this.entitySet;
}

public Map<String,Set<String>> getMethodToEntitySetMap() {
return this.methodToEntitySetMap;
}

public Map<String,Set<String>> getMethodToTargetClassSetMap() {
return this.methodToTargetClassSetMap;
}

public Map<String, String> getaccessorToAccessedFieldMap() {
return this.accessorToAccessedFieldMap;
}

@Override
public boolean visit(FieldDeclaration node) {
ITypeBinding bind = node.getType().resolveBinding();
if (bind == null) {
return true;
}

Set<String> attributes = new HashSet<String>();
String type = bind.getQualifiedName();
for (VariableDeclarationFragment vdf : (List<VariableDeclarationFragment>) node.fragments()) {
String attributeName = className + '.' + vdf.getName().getIdentifier() + ':' + type;

attributes.add(attributeName);
}

for (Object modifier : node.modifiers()) {
if(modifier.toString().equals("static")) {
staticEntities.addAll(attributes);
return true;
}
}

entitySet.addAll(attributes);
return true;
}

@Override
public boolean visit(MethodDeclaration node) {
if (node.isConstructor() || node.getBody() == null) {
return true;
}

// Construct the method's name.
List<String> params = new ArrayList<>();
for (SingleVariableDeclaration var : (List<SingleVariableDeclaration>) node.parameters()) {
IVariableBinding varBind = var.resolveBinding();
if (varBind == null) {
params.add(var.toString().split("\\s+")[0]);
}else {
params.add(varBind.getType().getQualifiedName());
}
}
Collections.sort(params, String.CASE_INSENSITIVE_ORDER);

StringBuffer buffer = new StringBuffer();
buffer.append(node.getName().getIdentifier());
buffer.append("(");
buffer.append(String.join(", ", params));
buffer.append(")");

String methodName = className + '.' + buffer.toString();

for (Object modifier : node.modifiers()) {
if(modifier.toString().equals("static")) {
staticEntities.add(methodName);
return true;
}
}


// Visit the body of the method.
MethodVisitor visitor = new MethodVisitor();
node.getBody().accept(visitor);


// Check if the method is an accessor
if (isSetter(visitor) != null && params.size() == 1) {
accessorToAccessedFieldMap.put(methodName, isSetter(visitor));
return true;
}

if (isGetter(visitor) != null && params.size() == 0) {
accessorToAccessedFieldMap.put(methodName, isGetter(visitor));
return true;
}


entitySet.add(methodName);
methodToEntitySetMap.put(methodName, visitor.getEntitySet());
methodToTargetClassSetMap.put(methodName, visitor.getTargetClassSet());

return true;
}

public String isGetter(MethodVisitor visitor) {
List<ASTNode> abstractStatements = visitor.getAbstractSatements();
if(abstractStatements.size() == 1) {
ASTNode node = abstractStatements.get(0);
if(node instanceof ReturnStatement) {
ReturnStatement returnStatement = (ReturnStatement) node;
if((returnStatement.getExpression() instanceof SimpleName || returnStatement.getExpression() instanceof FieldAccess) && visitor.getFieldInstructions().size() == 1 && visitor.getMethodInvocations().size() == 0 &&
visitor.getLocalVariableDeclarations().size() == 0 && visitor.getLocalVariableInstructions().size() == 0) {
return visitor.getFieldInstructions().iterator().next();
}
}
}
return null;
}

public String isSetter(MethodVisitor visitor) {
List<ASTNode> abstractStatements = visitor.getAbstractSatements();
if(abstractStatements.size() == 1) {
ASTNode node = abstractStatements.get(0);
if(node instanceof ExpressionStatement) {
ExpressionStatement expressionStatement = (ExpressionStatement)node;
if(expressionStatement.getExpression() instanceof Assignment && visitor.getFieldInstructions().size() == 1 && visitor.getMethodInvocations().size() == 0 &&
visitor.getLocalVariableDeclarations().size() == 0 && visitor.getLocalVariableInstructions().size() == 1) {
Assignment assignment = (Assignment)expressionStatement.getExpression();
if((assignment.getLeftHandSide() instanceof SimpleName || assignment.getLeftHandSide() instanceof FieldAccess) && assignment.getRightHandSide() instanceof SimpleName)
return visitor.getFieldInstructions().iterator().next();
}
}
}
return null;
}
}
Loading

0 comments on commit 218be1b

Please sign in to comment.