Skip to content

Commit

Permalink
Support the detection of refactorings (issue #715)
Browse files Browse the repository at this point in the history
Extract And Move Method	public execute(visitor BstVMVisitor, ctx ParserRuleContext, bstEntry BstEntry) : void extracted from private VM(tree CommonTree) in class org.jabref.logic.bst.VM & moved to class org.jabref.logic.bst.BstFunctions.BstAssignFunction

Inline Method	private assign(context BstEntry, o1 Object, o2 Object) : boolean inlined to public execute(visitor BstVMVisitor, ctx ParserRuleContext, bstEntry BstEntry) : void in class org.jabref.logic.bst.BstFunctions.BstAssignFunction
  • Loading branch information
tsantalis committed May 24, 2024
1 parent c4dcf76 commit 3d984a8
Showing 1 changed file with 100 additions and 21 deletions.
121 changes: 100 additions & 21 deletions src/main/java/gr/uom/java/xmi/diff/UMLModelDiff.java
Original file line number Diff line number Diff line change
Expand Up @@ -3600,6 +3600,26 @@ private void checkForExtractedAndMovedLambdas(List<UMLOperationBodyMapper> mappe
}
}
}
for(AbstractCall creation : operation.getAllCreations()) {
if(addedOperation.getClassName().endsWith("." + creation.getName())) {
//check for indirect call
boolean indirectCallFound = false;
for(UMLOperationBodyMapper mapper : mappers) {
for(AbstractCall inv : mapper.getInvocationsInSourceOperationAfterExtraction()) {
if(inv.matchesOperation(operation, mapper.getContainer2(), mapper.getClassDiff(), this)) {
indirectCallFound = true;
break;
}
}
if(indirectCallFound) {
break;
}
}
if(indirectCallFound) {
addedOperationInvocations.add(creation);
}
}
}
}
}
if(!addedOperationInvocations.isEmpty()) {
Expand Down Expand Up @@ -3657,27 +3677,7 @@ private void checkForExtractedAndMovedLambdas(List<UMLOperationBodyMapper> mappe
!conflictingExpression(addedOperationInvocation, addedOperation, mapper.getContainer2().variableDeclarationMap()) &&
operationBodyMapper.getMappings().size() >= lambdaStatementCount - castingStatements &&
extractAndMoveMatchCondition(operationBodyMapper, mapper, addedOperationInvocation)) {
if(className.equals(addedOperation.getClassName())) {
//extract inside moved or renamed class
createExtractAndMoveMethodRefactoring(addedOperation, mapper, addedOperationInvocations, operationBodyMapper);
}
else if(isSubclassOf(className, addedOperation.getClassName())) {
createExtractAndMoveMethodRefactoring(addedOperation, mapper, addedOperationInvocations, operationBodyMapper);
}
else if(isSubclassOf(addedOperation.getClassName(), className)) {
createExtractAndMoveMethodRefactoring(addedOperation, mapper, addedOperationInvocations, operationBodyMapper);
}
else if(addedOperation.getClassName().startsWith(className + ".")) {
createExtractAndMoveMethodRefactoring(addedOperation, mapper, addedOperationInvocations, operationBodyMapper);
}
else if(className.startsWith(addedOperation.getClassName() + ".")) {
createExtractAndMoveMethodRefactoring(addedOperation, mapper, addedOperationInvocations, operationBodyMapper);
}
else if(sourceClassImportsTargetClass(className, addedOperation.getClassName()) ||
sourceClassImportsSuperclassOfTargetClass(className, addedOperation.getClassName()) ||
targetClassImportsSourceClass(className, addedOperation.getClassName())) {
createExtractAndMoveMethodRefactoring(addedOperation, mapper, addedOperationInvocations, operationBodyMapper);
}
createExtractAndMoveMethodRefactoring(addedOperation, mapper, addedOperationInvocations, operationBodyMapper);
for(AbstractCodeMapping mapping : operationBodyMapper.getMappings()) {
if(fragment.getLambdas().get(0).getLocationInfo().subsumes(mapping.getFragment1().getLocationInfo())) {
mapper.getNonMappedLeavesT1().remove(fragment);
Expand All @@ -3687,6 +3687,85 @@ else if(sourceClassImportsTargetClass(className, addedOperation.getClassName())
break;
}
}
else if(lambdaStatementCount < addedOperationStatementCount) {
//check if a possibly inlined method is called
Map<UMLOperation, AbstractCall> possiblyInlinedOperations = new LinkedHashMap<UMLOperation, AbstractCall>();
for(AbstractCodeFragment f : fragment.getLambdas().get(0).getBody().getCompositeStatement().getLeaves()) {
AbstractCall inlinedInvocation = f.invocationCoveringEntireFragment();
if(inlinedInvocation != null && mapper.getClassDiff() != null && (inlinedInvocation.getExpression() == null || (inlinedInvocation.getExpression() != null && inlinedInvocation.getExpression().endsWith(JAVA.THIS_DOT)))) {
for(UMLOperation removedOperation : mapper.getClassDiff().getRemovedOperations()) {
if(inlinedInvocation.matchesOperation(removedOperation, mapper.getContainer1(), mapper.getClassDiff(), this)) {
possiblyInlinedOperations.put(removedOperation, inlinedInvocation);
break;
}
}
}
}
int inlinedOperationStatementCount = 0;
for(UMLOperation inlinedOperation : possiblyInlinedOperations.keySet()) {
inlinedOperationStatementCount += inlinedOperation.getBody() != null ? inlinedOperation.getBody().statementCountIncludingBlocks() - 1 : 0;
}
int leftSideStatementCount = lambdaStatementCount + inlinedOperationStatementCount - possiblyInlinedOperations.size();
if(possiblyInlinedOperations.size() > 0 && leftSideStatementCount == addedOperationStatementCount) {
AbstractCall addedOperationInvocation = addedOperationInvocations.get(0);
ArrayList<AbstractCodeFragment> subList = new ArrayList<AbstractCodeFragment>();
subList.add(fragment);
UMLOperationBodyMapper operationBodyMapper = createMapperForExtractAndMove(addedOperation,
mapper, className, addedOperationInvocation, Optional.of(subList));
if(!anotherAddedMethodExistsWithBetterMatchingInvocationExpression(addedOperationInvocation, addedOperation, addedOperations) &&
!conflictingExpression(addedOperationInvocation, addedOperation, mapper.getContainer2().variableDeclarationMap()) &&
operationBodyMapper.getMappings().size() >= lambdaStatementCount - castingStatements - possiblyInlinedOperations.size() &&
extractAndMoveMatchCondition(operationBodyMapper, mapper, addedOperationInvocation)) {
createExtractAndMoveMethodRefactoring(addedOperation, mapper, addedOperationInvocations, operationBodyMapper);
for(UMLOperation inlinedOperation : possiblyInlinedOperations.keySet()) {
AbstractCall inlinedOperationInvocation = possiblyInlinedOperations.get(inlinedOperation);
List<String> arguments = inlinedOperationInvocation.arguments();
List<String> parameters = inlinedOperation.getParameterNameList();
Map<String, String> parameterToArgumentMap1 = new LinkedHashMap<String, String>();
//special handling for methods with varargs parameter for which no argument is passed in the matching invocation
int size = Math.min(arguments.size(), parameters.size());
for(int i=0; i<size; i++) {
parameterToArgumentMap1.put(parameters.get(i), arguments.get(i));
}
Map<String, String> parameterToArgumentMap2 = new LinkedHashMap<String, String>();
String expression = inlinedOperationInvocation.getExpression();
if(expression != null && !inlinedOperation.getClassName().endsWith("." + expression)) {
parameterToArgumentMap2.put(expression + ".", "");
parameterToArgumentMap1.put(JAVA.THIS_DOT, "");
}
UMLOperationBodyMapper inlinedOperationBodyMapper = new UMLOperationBodyMapper(inlinedOperation, operationBodyMapper, parameterToArgumentMap1, parameterToArgumentMap2, getUMLClassDiff(inlinedOperation.getClassName()), inlinedOperationInvocation, false);
if(moveAndInlineMatchCondition(inlinedOperationBodyMapper, operationBodyMapper)) {
InlineOperationRefactoring inlineOperationRefactoring = new InlineOperationRefactoring(inlinedOperationBodyMapper, operationBodyMapper.getContainer1(), List.of(inlinedOperationInvocation));
Set<Refactoring> refactoringsToBeRemoved = new LinkedHashSet<Refactoring>();
boolean skip = false;
for(Refactoring r : refactorings) {
if(r instanceof InlineOperationRefactoring) {
InlineOperationRefactoring inline = (InlineOperationRefactoring)r;
if(inline.getBodyMapper().identicalMappings(inlinedOperationBodyMapper)) {
if(inlineOperationRefactoring.getRefactoringType().equals(RefactoringType.INLINE_OPERATION) &&
inline.getRefactoringType().equals(RefactoringType.MOVE_AND_INLINE_OPERATION)) {
refactoringsToBeRemoved.add(inline);
}
else if(inlineOperationRefactoring.getRefactoringType().equals(RefactoringType.MOVE_AND_INLINE_OPERATION) &&
inline.getRefactoringType().equals(RefactoringType.INLINE_OPERATION)) {
skip = true;
}
}
}
}
refactorings.removeAll(refactoringsToBeRemoved);
if(!skip) {
refactorings.add(inlineOperationRefactoring);
deleteRemovedOperation(inlinedOperation);
mapper.addChildMapper(inlinedOperationBodyMapper);
MappingOptimizer optimizer = new MappingOptimizer(mapper.getClassDiff());
optimizer.optimizeDuplicateMappingsForInline(mapper, refactorings);
}
}
}
}
}
}
}
}
}
Expand Down

0 comments on commit 3d984a8

Please sign in to comment.