Skip to content

Commit

Permalink
#20: Refactor code to re-use same operation diff
Browse files Browse the repository at this point in the history
  • Loading branch information
mkshiblu committed Oct 19, 2020
1 parent f85b209 commit 704e481
Show file tree
Hide file tree
Showing 13 changed files with 430 additions and 31 deletions.
7 changes: 4 additions & 3 deletions src/io/jsrminer/JSRefactoringMiner.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package io.jsrminer;

import io.jsrminer.refactorings.IRefactoring;
import io.jsrminer.uml.diff.SourceDirDiff;
import io.jsrminer.uml.diff.SourceDirectory;
import io.jsrminer.uml.diff.UMLModelDiff;
Expand Down Expand Up @@ -59,7 +60,7 @@ private void detect(Repository repository, final RefactoringHandler handler, Ite
while (i.hasNext()) {
RevCommit currentCommit = i.next();
try {
List<Refactoring> refactoringsAtRevision = detectRefactorings(repository, currentCommit, handler);
List<IRefactoring> refactoringsAtRevision = detectRefactorings(repository, currentCommit, handler);
refactoringsCount += refactoringsAtRevision.size();

} catch (Exception e) {
Expand All @@ -80,9 +81,9 @@ private void detect(Repository repository, final RefactoringHandler handler, Ite
log.info(String.format("Analyzed %s [Commits: %d, Errors: %d, Refactorings: %d]", projectName, commitsCount, errorCommitsCount, refactoringsCount));
}

protected List<Refactoring> detectRefactorings(Repository repository, RevCommit currentCommit, RefactoringHandler handler) throws Exception {
protected List<IRefactoring> detectRefactorings(Repository repository, RevCommit currentCommit, RefactoringHandler handler) throws Exception {
RevCommit parentCommit = currentCommit.getParent(0);
List<Refactoring> refactoringsAtRevision = null;
List<IRefactoring> refactoringsAtRevision = null;
String commitId = currentCommit.getId().getName();

List<String> filePathsBefore = new ArrayList<String>();
Expand Down
4 changes: 0 additions & 4 deletions src/io/jsrminer/Refactoring.java

This file was deleted.

4 changes: 3 additions & 1 deletion src/io/jsrminer/RefactoringHandler.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package io.jsrminer;

import io.jsrminer.refactorings.IRefactoring;

import java.util.List;

/**
Expand All @@ -26,7 +28,7 @@ public boolean skipCommit(String commitId) {
* @param commitId The sha of the analyzed commit.
* @param refactorings List of refactorings detected in the commit.
*/
public void handle(String commitId, List<Refactoring> refactorings) {}
public void handle(String commitId, List<IRefactoring> refactorings) {}

/**
* This method is called whenever an exception is thrown during the analysis of the given commit.
Expand Down
112 changes: 112 additions & 0 deletions src/io/jsrminer/refactorings/AddParameterRefactoring.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
package io.jsrminer.refactorings;

import io.jsrminer.sourcetree.FunctionDeclaration;
import io.jsrminer.uml.UMLParameter;

public class AddParameterRefactoring extends Refactoring {
private UMLParameter parameter;
private FunctionDeclaration operationBefore;
private FunctionDeclaration operationAfter;

public AddParameterRefactoring(UMLParameter parameter, FunctionDeclaration operationBefore, FunctionDeclaration operationAfter) {
super(RefactoringType.ADD_PARAMETER);
this.parameter = parameter;
this.operationBefore = operationBefore;
this.operationAfter = operationAfter;
}

public UMLParameter getParameter() {
return parameter;
}

public FunctionDeclaration getOperationBefore() {
return operationBefore;
}

public FunctionDeclaration getOperationAfter() {
return operationAfter;
}

// @Override
// public List<CodeRange> leftSide() {
// List<CodeRange> ranges = new ArrayList<CodeRange>();
// ranges.add(operationBefore.codeRange()
// .setDescription("original method declaration")
// .setCodeElement(operationBefore.toString()));
// return ranges;
// }
//
// @Override
// public List<CodeRange> rightSide() {
// List<CodeRange> ranges = new ArrayList<CodeRange>();
// ranges.add(parameter.getVariableDeclaration().codeRange()
// .setDescription("added parameter")
// .setCodeElement(parameter.getVariableDeclaration().toString()));
// ranges.add(operationAfter.codeRange()
// .setDescription("method declaration with added parameter")
// .setCodeElement(operationAfter.toString()));
// return ranges;
// }

// @Override
// public Set<ImmutablePair<String, String>> getInvolvedClassesBeforeRefactoring() {
// Set<ImmutablePair<String, String>> pairs = new LinkedHashSet<ImmutablePair<String, String>>();
// pairs.add(new ImmutablePair<String, String>(getOperationBefore().getLocationInfo().getFilePath(), getOperationBefore().getClassName()));
// return pairs;
// }
//
// @Override
// public Set<ImmutablePair<String, String>> getInvolvedClassesAfterRefactoring() {
// Set<ImmutablePair<String, String>> pairs = new LinkedHashSet<ImmutablePair<String, String>>();
// pairs.add(new ImmutablePair<String, String>(getOperationAfter().getLocationInfo().getFilePath(), getOperationAfter().getClassName()));
// return pairs;
// }

// public String toString() {
// StringBuilder sb = new StringBuilder();
// sb.append(getName()).append("\t");
// sb.append(parameter.getVariableDeclaration());
// sb.append(" in method ");
// sb.append(operationAfter);
// sb.append(" from class ");
// sb.append(operationAfter.getClassName());
// return sb.toString();
// }
//
// @Override
// public int hashCode() {
// final int prime = 31;
// int result = 1;
// result = prime * result + ((parameter.getVariableDeclaration() == null) ? 0 : parameter.getVariableDeclaration().hashCode());
// result = prime * result + ((operationAfter == null) ? 0 : operationAfter.hashCode());
// result = prime * result + ((operationBefore == null) ? 0 : operationBefore.hashCode());
// return result;
// }
//
// @Override
// public boolean equals(Object obj) {
// if (this == obj)
// return true;
// if (obj == null)
// return false;
// if (getClass() != obj.getClass())
// return false;
// AddParameterRefactoring other = (AddParameterRefactoring) obj;
// if (parameter == null) {
// if (other.parameter != null)
// return false;
// } else if (!parameter.getVariableDeclaration().equals(other.parameter.getVariableDeclaration()))
// return false;
// if (operationAfter == null) {
// if (other.operationAfter != null)
// return false;
// } else if (!operationAfter.equals(other.operationAfter))
// return false;
// if (operationBefore == null) {
// if (other.operationBefore != null)
// return false;
// } else if (!operationBefore.equals(other.operationBefore))
// return false;
// return true;
// }
}
7 changes: 7 additions & 0 deletions src/io/jsrminer/refactorings/IRefactoring.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package io.jsrminer.refactorings;

public interface IRefactoring {
public String getName();

public RefactoringType getRefactoringType();
}
27 changes: 27 additions & 0 deletions src/io/jsrminer/refactorings/Refactoring.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package io.jsrminer.refactorings;

import org.eclipse.jgit.annotations.NonNull;

public class Refactoring implements IRefactoring {

protected RefactoringType refactoringType;

public Refactoring(@NonNull RefactoringType refactoringType) {
this.refactoringType = refactoringType;
}

@Override
public String getName() {
return this.refactoringType.getTitle();
}

@Override
public RefactoringType getRefactoringType() {
return refactoringType;
}

@Override
public String toString() {
return refactoringType.toString();
}
}
24 changes: 24 additions & 0 deletions src/io/jsrminer/refactorings/RefactoringType.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package io.jsrminer.refactorings;

public enum RefactoringType {

ADD_PARAMETER("Add Parameter", "Add Parameter (.+) in method (.+) from class (.+)"),
REMOVE_PARAMETER("Remove Parameter", "Remove Parameter (.+) in method (.+) from class (.+)");

private String title;
private String description;

RefactoringType(String title, String description) {
this.title = title;
this.description = description;
}

public String getTitle() {
return this.title;
}

@Override
public String toString() {
return title + " " + description;
}
}
114 changes: 114 additions & 0 deletions src/io/jsrminer/refactorings/RemoveParameterRefactoring.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
package io.jsrminer.refactorings;

import io.jsrminer.sourcetree.FunctionDeclaration;
import io.jsrminer.uml.UMLParameter;

public class RemoveParameterRefactoring extends Refactoring {
private UMLParameter parameter;
private FunctionDeclaration operationBefore;
private FunctionDeclaration operationAfter;

public RemoveParameterRefactoring(UMLParameter parameter, FunctionDeclaration operationBefore,
FunctionDeclaration operationAfter) {
super(RefactoringType.REMOVE_PARAMETER);
this.parameter = parameter;
this.operationBefore = operationBefore;
this.operationAfter = operationAfter;
}

public UMLParameter getParameter() {
return parameter;
}

public FunctionDeclaration getOperationBefore() {
return operationBefore;
}

public FunctionDeclaration getOperationAfter() {
return operationAfter;
}

// @Override
// public List<CodeRange> leftSide() {
// List<CodeRange> ranges = new ArrayList<CodeRange>();
// ranges.add(parameter.getVariableDeclaration().codeRange()
// .setDescription("removed parameter")
// .setCodeElement(parameter.getVariableDeclaration().toString()));
// ranges.add(operationBefore.codeRange()
// .setDescription("original method declaration")
// .setCodeElement(operationBefore.toString()));
// return ranges;
// }
//
// @Override
// public List<CodeRange> rightSide() {
// List<CodeRange> ranges = new ArrayList<CodeRange>();
// ranges.add(operationAfter.codeRange()
// .setDescription("method declaration with removed parameter")
// .setCodeElement(operationAfter.toString()));
// return ranges;
// }


// @Override
// public Set<ImmutablePair<String, String>> getInvolvedClassesBeforeRefactoring() {
// Set<ImmutablePair<String, String>> pairs = new LinkedHashSet<ImmutablePair<String, String>>();
// pairs.add(new ImmutablePair<String, String>(getOperationBefore().getLocationInfo().getFilePath(), getOperationBefore().getClassName()));
// return pairs;
// }
//
// @Override
// public Set<ImmutablePair<String, String>> getInvolvedClassesAfterRefactoring() {
// Set<ImmutablePair<String, String>> pairs = new LinkedHashSet<ImmutablePair<String, String>>();
// pairs.add(new ImmutablePair<String, String>(getOperationAfter().getLocationInfo().getFilePath(), getOperationAfter().getClassName()));
// return pairs;
// }
//
// public String toString() {
// StringBuilder sb = new StringBuilder();
// sb.append(getName()).append("\t");
// sb.append(parameter.getVariableDeclaration());
// sb.append(" in method ");
// sb.append(operationBefore);
// sb.append(" from class ");
// sb.append(operationBefore.getClassName());
// return sb.toString();
// }
//
// @Override
// public int hashCode() {
// final int prime = 31;
// int result = 1;
// result = prime * result + ((parameter.getVariableDeclaration() == null) ? 0 : parameter.getVariableDeclaration().hashCode());
// result = prime * result + ((operationAfter == null) ? 0 : operationAfter.hashCode());
// result = prime * result + ((operationBefore == null) ? 0 : operationBefore.hashCode());
// return result;
// }
//
// @Override
// public boolean equals(Object obj) {
// if (this == obj)
// return true;
// if (obj == null)
// return false;
// if (getClass() != obj.getClass())
// return false;
// RemoveParameterRefactoring other = (RemoveParameterRefactoring) obj;
// if (parameter == null) {
// if (other.parameter != null)
// return false;
// } else if (!parameter.getVariableDeclaration().equals(other.parameter.getVariableDeclaration()))
// return false;
// if (operationAfter == null) {
// if (other.operationAfter != null)
// return false;
// } else if (!operationAfter.equals(other.operationAfter))
// return false;
// if (operationBefore == null) {
// if (other.operationBefore != null)
// return false;
// } else if (!operationBefore.equals(other.operationBefore))
// return false;
// return true;
// }
}
16 changes: 11 additions & 5 deletions src/io/jsrminer/uml/diff/SourceFileModelDiffer.java
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
package io.jsrminer.uml.diff;

import io.jsrminer.refactorings.IRefactoring;
import io.jsrminer.sourcetree.FunctionDeclaration;
import io.jsrminer.sourcetree.SourceFileModel;
import io.jsrminer.uml.mapping.FunctionBodyMapper;

import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.*;

public class SourceFileModelDiffer {

public final SourceFileModel source1;
public final SourceFileModel source2;

private final Map<String, FunctionBodyMapper> functionBodyMappers = new HashMap<>();
protected List<IRefactoring> refactorings = new ArrayList<>();
private List<FunctionBodyMapper> bodyMappers = new ArrayList<>();

public SourceFileModelDiffer(final SourceFileModel source1, final SourceFileModel source2) {
this.source1 = source1;
Expand Down Expand Up @@ -68,12 +69,17 @@ protected void createBodyMappers(SourceFileModelDiff sourceDiff
// First map by fully qualified name? TODO revisit
for (FunctionDeclaration function1 : functionMap1.values()) {
final FunctionDeclaration function2 = functionMap2.get(function1.qualifiedName);
// If function exists in both file
// If function exists in both file, try to match their statements
if (function2 != null) {
FunctionBodyMapper mapper = new FunctionBodyMapper(function1, function2,

UMLOperationDiff operationDiff = new UMLOperationDiff(function1, function2);

FunctionBodyMapper mapper = new FunctionBodyMapper(operationDiff,
sourceDiff.getAddedOperations(),
sourceDiff.getRemovedOperations());
mapper.map();

this.refactorings.addAll(operationDiff.getRefactorings());
}
}

Expand Down
Loading

0 comments on commit 704e481

Please sign in to comment.