Skip to content

Commit

Permalink
#113: Parameterize container diff to allow source and class diff to r…
Browse files Browse the repository at this point in the history
…e-use the same diff
  • Loading branch information
mkshiblu committed Jul 5, 2021
1 parent 4d748be commit 72f1619
Show file tree
Hide file tree
Showing 5 changed files with 20 additions and 162 deletions.
162 changes: 9 additions & 153 deletions src/io/jsrminer/uml/diff/ClassDiffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,20 +20,16 @@
import java.util.List;
import java.util.TreeSet;

public class ClassDiffer extends BaseDiffer {
private final IClassDeclaration class1;
private final IClassDeclaration class2;
private final ClassDiff classDiff;

public class ClassDiffer extends ContainerDiffer<IClassDeclaration, ClassDiff> {
ClassDiff classDiff;
public ClassDiffer(IClassDeclaration class1, IClassDeclaration class2) {
this.class1 = class1;
this.class2 = class2;
this.classDiff = new ClassDiff(class1, class2);
super(new ClassDiff(class1, class2));
this.classDiff = super.containerDiff;
}

public ClassDiff diff() {
reportAddedAndRemovedOperations();
createBodyMapperForCommonNamedFunctions();
super.reportAddedAndRemovedOperations();
super.createBodyMapperForCommonFunctions();

// processAnonymousFunctions(sourceDiff);
checkForOperationSignatureChanges();
Expand All @@ -42,147 +38,7 @@ public ClassDiff diff() {
checkForInlinedOperations();
checkForExtractedOperations();

return this.classDiff;
}

// Adds the added and removed ops in the model diff
private void reportAddedAndRemovedOperations() {
// region Find uncommon functions between the two files
// For model1 uncommon / not matched functions are the functions that were removed
// For model2 uncommon/ not matched functions are the functions that were added
boolean isEqual;
for (IFunctionDeclaration function1 : this.class1.getFunctionDeclarations()) {
isEqual = false;
for (IFunctionDeclaration function2 : this.class2.getFunctionDeclarations()) {
if (isEqual = FunctionUtil.isEqual(function1, function2)) {
break;
}
}

// If no match on model2 report as removed
if (!isEqual)
classDiff.reportRemovedOperation((FunctionDeclaration) function1);
}
for (IFunctionDeclaration function2 : classDiff.getContainer2().getFunctionDeclarations()) {
isEqual = false;
for (IFunctionDeclaration function1 : classDiff.getContainer1().getFunctionDeclarations()) {
if (isEqual = FunctionUtil.isEqual(function2, function1)) {
break;
}
}

// If no match report as added
if (!isEqual)
classDiff.reportAddedOperation((FunctionDeclaration) function2);
}
}

protected void createBodyMapperForCommonNamedFunctions() {
final List<IFunctionDeclaration> functions1 = classDiff.getContainer1().getFunctionDeclarations();
final List<IFunctionDeclaration> functions2 = classDiff.getContainer2().getFunctionDeclarations();
// First match by equalsQualified
// (In RM it's equals signature which checks modifiers, qualified name and parameter types
for (IFunctionDeclaration if1 : functions1) {
FunctionDeclaration function1 = (FunctionDeclaration) if1;

IFunctionDeclaration function2 = functions2.stream()
.filter(f2 -> FunctionUtil.equalsNameParentQualifiedNameAndParamerNames(f2, function1))
.findFirst()
.orElse(null);

if (function2 != null) {
// if (getModelDiff() != null) {
// List<FunctionBodyMapper> mappers
// = getModelDiff().findMappersWithMatchingSignature2(function2);
// if (mappers.size() > 0) {
// var operation1 = mappers.get(0).getOperation1();
// if (!FunctionUtil.equalNameAndParameterCount(operation1, function1)//operation1.equalSignature(function1)
// && getModelDiff().commonlyImplementedOperations(operation1, function2, this)) {
// if (!containerDiff.getRemovedOperations().contains(function1)) {
// containerDiff.getRemovedOperations().add(function1);
// }
// break;
// }
// }
// }

// Map and find refactorings between two functions
UMLOperationDiff operationDiff = new UMLOperationDiff(function1, (FunctionDeclaration) function2);
FunctionBodyMapper mapper = new FunctionBodyMapper(operationDiff, classDiff);
operationDiff.setMappings(mapper.getMappings());
this.classDiff.getRefactoringsBeforePostProcessing().addAll(operationDiff.getRefactorings());
// save the mapper TODO
this.classDiff.getOperationBodyMapperList().add(mapper);
}
}

// Second Not qualified but the 2nd file contains the operation
for (IFunctionDeclaration if1 : functions1) {
FunctionDeclaration function1 = (FunctionDeclaration) if1;
IFunctionDeclaration function2 = functions2.stream()
.filter(f2 -> FunctionUtil.isEqual(f2, function1))
.findFirst()
.orElse(null);

if (function2 != null
&& !containsMapperForOperation(function1)
// && functions2.getOperations().contains(operation)
&& !classDiff.getRemovedOperations().contains(function1)) {

// int index = functions2.indexOf(operation);
// int lastIndex = functions2.lastIndexOf(operation);
// int finalIndex = index;
// if (index != lastIndex) {
// double d1 = operation.getReturnParameter().getType()
// .normalizedNameDistance(nextClass.getOperations().get(index).getReturnParameter().getType());
// double d2 = operation.getReturnParameter().getType()
// .normalizedNameDistance(nextClass.getOperations().get(lastIndex).getReturnParameter().getType());
// if (d2 < d1) {
// finalIndex = lastIndex;
// }
// }

UMLOperationDiff operationDiff = new UMLOperationDiff(function1, (FunctionDeclaration) function2);
FunctionBodyMapper bodyMapper
= new FunctionBodyMapper(operationDiff, classDiff);
operationDiff.setMappings(bodyMapper.getMappings());
classDiff.getRefactoringsBeforePostProcessing().addAll(operationDiff.getRefactorings());
classDiff.getOperationBodyMapperList().add(bodyMapper);
}
}

List<FunctionDeclaration> removedOperationsToBeRemoved = new ArrayList<>();
List<FunctionDeclaration> addedOperationsToBeRemoved = new ArrayList<>();
for (FunctionDeclaration removedOperation : classDiff.getRemovedOperations()) {
for (FunctionDeclaration addedOperation : classDiff.getAddedOperations()) {
/*if (removedOperation.equalsIgnoringVisibility(addedOperation)) {
UMLOperationBodyMapper operationBodyMapper = new UMLOperationBodyMapper(removedOperation, addedOperation, this);
UMLOperationDiff operationSignatureDiff = new UMLOperationDiff(removedOperation, addedOperation, operationBodyMapper.getMappings());
refactorings.addAll(operationSignatureDiff.getRefactorings());
this.addOperationBodyMapper(operationBodyMapper);
removedOperationsToBeRemoved.add(removedOperation);
addedOperationsToBeRemoved.add(addedOperation);
} else*/
if (FunctionUtil.nameEqualsIgnoreCaseAndEqualParameterCount(removedOperation, addedOperation)) {
UMLOperationDiff operationDiff = new UMLOperationDiff(removedOperation, addedOperation);
FunctionBodyMapper bodyMapper
= new FunctionBodyMapper(operationDiff, classDiff);
operationDiff.setMappings(bodyMapper.getMappings());
classDiff.getRefactoringsBeforePostProcessing().addAll(operationDiff.getRefactorings());

if (!removedOperation.getName().equals(addedOperation.getName()) &&
!(removedOperation.isConstructor() && addedOperation.isConstructor())) {
RenameOperationRefactoring rename = new RenameOperationRefactoring(bodyMapper);
classDiff.getRefactoringsBeforePostProcessing().add(rename);
}
classDiff.getOperationBodyMapperList().add(bodyMapper);
removedOperationsToBeRemoved.add(removedOperation);
addedOperationsToBeRemoved.add(addedOperation);
}
}
}
classDiff.getRemovedOperations().removeAll(removedOperationsToBeRemoved);
classDiff.getAddedOperations().removeAll(addedOperationsToBeRemoved);
return this.containerDiff;
}

private void checkForOperationSignatureChanges() {
Expand Down Expand Up @@ -332,8 +188,8 @@ private void checkForExtractedOperations() {
}

protected void processAttributes() {
var originalClass = class1;
var nextClass = class2;
var originalClass = classDiff.getContainer1();
var nextClass = classDiff.getContainer1();

for (UMLAttribute attribute : originalClass.getAttributes()) {
var matchingAttribute = ClassUtil.containsAttribute(nextClass, attribute);
Expand Down
10 changes: 5 additions & 5 deletions src/io/jsrminer/uml/diff/ContainerDiffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@
import java.util.List;
import java.util.TreeSet;

public class ContainerDiffer<T extends IContainer> extends BaseDiffer<T> {
protected final ContainerDiff<T> containerDiff;
public class ContainerDiffer<T extends IContainer, D extends ContainerDiff<T>> extends BaseDiffer<T> {
protected final D containerDiff;

public ContainerDiffer(T container1, T container2) {
this.containerDiff = new ContainerDiff<>(container1, container2);
public ContainerDiffer(D containerDiff) {
this.containerDiff = containerDiff;
}

/**
Expand Down Expand Up @@ -262,7 +262,7 @@ private void checkForExtractedOperations() {
}

// Adds the added and removed ops in the model diff
private void reportAddedAndRemovedOperations() {
void reportAddedAndRemovedOperations() {
// region Find uncommon functions between the two files
// For model1 uncommon / not matched functions are the functions that were removed
// For model2 uncommon/ not matched functions are the functions that were added
Expand Down
4 changes: 2 additions & 2 deletions src/io/jsrminer/uml/diff/SourceFileDiffer.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,12 @@
/**
* Diff between two source File?
*/
public class SourceFileDiffer extends ContainerDiffer<ISourceFile> {
public class SourceFileDiffer extends ContainerDiffer<ISourceFile, ContainerDiff<ISourceFile>> {

public final UMLModelDiff modelDiff;

public SourceFileDiffer(final ISourceFile container1, final ISourceFile container2, final UMLModelDiff modelDiff) {
super(container1, container2);
super(new ContainerDiff<>(container1, container2));
this.modelDiff = modelDiff;
}

Expand Down
3 changes: 2 additions & 1 deletion src/io/jsrminer/uml/mapping/FunctionBodyMapper.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,8 @@ private Set<BlockStatement> getBlockStatementsRecursiveOrder(List<Statement> sta
private void mapChildFunctionDeclarations(FunctionDeclaration function1, FunctionDeclaration function2) {
// Maps the functions that are immediately declared into this mapper
if (function1.getFunctionDeclarations().size() > 0 && function2.getFunctionDeclarations().size() > 0) {
var differ = new ContainerDiffer<IFunctionDeclaration>(function1, function2);
var differ = new ContainerDiffer<IFunctionDeclaration, ContainerDiff<IFunctionDeclaration>>
(new ContainerDiff<>(function1, function2));
var diff = differ.diffChildFunctions();
this.refactorings.addAll(diff.getAllRefactorings());
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ void matchAnonymousContainers(List<IAnonymousFunctionDeclaration> anonymousConta
}

Replacement diffAnonymousPair(IAnonymousFunctionDeclaration anonymousFunctionDeclaration1, IAnonymousFunctionDeclaration anonymousClassDeclaration2) {
ContainerDiffer<IAnonymousFunctionDeclaration> differ = new ContainerDiffer<>(anonymousFunctionDeclaration1, anonymousClassDeclaration2);
ContainerDiffer<IAnonymousFunctionDeclaration, ContainerDiff<IAnonymousFunctionDeclaration>> differ
= new ContainerDiffer<>(new ContainerDiff<>(anonymousFunctionDeclaration1, anonymousClassDeclaration2));
var diff = differ.diff();
// for (IFunctionDeclaration operation1 : anonymousClass1.getFunctionDeclarations()) {
// for (IFunctionDeclaration operation2 : anonymousClass2.getFunctionDeclarations()) {
Expand Down

0 comments on commit 72f1619

Please sign in to comment.