Skip to content

Commit

Permalink
Generalized the replacement of qualified names
Browse files Browse the repository at this point in the history
  • Loading branch information
tsantalis committed Oct 12, 2024
1 parent 1bf361b commit a37ac30
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 156 deletions.
125 changes: 5 additions & 120 deletions src/main/java/gr/uom/java/xmi/decomposition/Visitor.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,13 @@

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.ArrayType;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.BooleanLiteral;
import org.eclipse.jdt.core.dom.CastExpression;
import org.eclipse.jdt.core.dom.CatchClause;
Expand All @@ -26,11 +24,9 @@
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
import org.eclipse.jdt.core.dom.EnhancedForStatement;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.ExpressionMethodReference;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.InfixExpression;
import org.eclipse.jdt.core.dom.LambdaExpression;
import org.eclipse.jdt.core.dom.MarkerAnnotation;
Expand Down Expand Up @@ -61,7 +57,6 @@
import org.eclipse.jdt.core.dom.TypeLiteral;
import org.eclipse.jdt.core.dom.TypeMethodReference;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
import org.eclipse.jdt.core.dom.WildcardType;

import gr.uom.java.xmi.VariableDeclarationContainer;
Expand Down Expand Up @@ -727,77 +722,11 @@ public boolean visit(QualifiedName node) {
}
}
else if(qualifier instanceof SimpleName && !(node.getParent() instanceof QualifiedName)) {
String qualifierIdentifier = ((SimpleName)qualifier).getIdentifier();
MethodDeclaration parentMethodDeclaration = findParentMethodDeclaration(node);
if(parentMethodDeclaration != null) {
boolean qualifierIsParameter = false;
List<SingleVariableDeclaration> parameters = parentMethodDeclaration.parameters();
for(SingleVariableDeclaration parameter : parameters) {
if(parameter.getName().getIdentifier().equals(qualifierIdentifier)) {
qualifierIsParameter = true;
break;
}
}
boolean qualifierIsLocalVariableInTheSameBlock = false;
Block parentBlock = findParentBlock(node);
if(!qualifierIsParameter && parentBlock != null) {
List<Statement> statements = parentBlock.statements();
for(Statement statement : statements) {
if(statement instanceof VariableDeclarationStatement) {
VariableDeclarationStatement vds = (VariableDeclarationStatement)statement;
List<VariableDeclarationFragment> fragments = vds.fragments();
for(VariableDeclarationFragment fragment : fragments) {
if(fragment.getName().getIdentifier().equals(qualifierIdentifier)) {
qualifierIsLocalVariableInTheSameBlock = true;
break;
}
}
}
if(qualifierIsLocalVariableInTheSameBlock)
break;
}
}
boolean qualifierIsField = false;
if(!qualifierIsParameter && !qualifierIsLocalVariableInTheSameBlock && !parentMethodDeclaration.isConstructor()) {
AbstractTypeDeclaration parentTypeDeclaration = findParentTypeDeclaration(parentMethodDeclaration);
if(parentTypeDeclaration != null) {
List<BodyDeclaration> bodyDeclarations = parentTypeDeclaration.bodyDeclarations();
for(BodyDeclaration declaration : bodyDeclarations) {
if(declaration instanceof FieldDeclaration) {
FieldDeclaration fieldDeclaration = (FieldDeclaration)declaration;
List<VariableDeclarationFragment> fragments = fieldDeclaration.fragments();
for(VariableDeclarationFragment fragment : fragments) {
if(fragment.getName().getIdentifier().equals(qualifierIdentifier)) {
qualifierIsField = true;
break;
}
}
if(qualifierIsField) {
break;
}
}
}
}
}
if(qualifierIsParameter || qualifierIsField || qualifierIsLocalVariableInTheSameBlock || node.getName().getIdentifier().equals("length")) {
LeafExpression expression = new LeafExpression(cu, filePath, node, CodeElementType.QUALIFIED_NAME, container);
variables.add(expression);
if(current.getUserObject() != null) {
AnonymousClassDeclarationObject anonymous = (AnonymousClassDeclarationObject)current.getUserObject();
anonymous.getVariables().add(expression);
}
}
}
EnhancedForStatement enhancedFor = findParentEnhancedForStatement(node);
if(enhancedFor != null) {
if(enhancedFor.getParameter().getName().getIdentifier().equals(qualifierIdentifier)) {
LeafExpression expression = new LeafExpression(cu, filePath, node, CodeElementType.QUALIFIED_NAME, container);
variables.add(expression);
if(current.getUserObject() != null) {
AnonymousClassDeclarationObject anonymous = (AnonymousClassDeclarationObject)current.getUserObject();
anonymous.getVariables().add(expression);
}
}
LeafExpression expression = new LeafExpression(cu, filePath, node, CodeElementType.QUALIFIED_NAME, container);
variables.add(expression);
if(current.getUserObject() != null) {
AnonymousClassDeclarationObject anonymous = (AnonymousClassDeclarationObject)current.getUserObject();
anonymous.getVariables().add(expression);
}
}
else if(qualifier instanceof QualifiedName && !(node.getParent() instanceof QualifiedName)) {
Expand All @@ -811,50 +740,6 @@ else if(qualifier instanceof QualifiedName && !(node.getParent() instanceof Qual
return super.visit(node);
}

private EnhancedForStatement findParentEnhancedForStatement(ASTNode node) {
ASTNode parent = node.getParent();
while(parent != null) {
if(parent instanceof EnhancedForStatement) {
return (EnhancedForStatement)parent;
}
parent = parent.getParent();
}
return null;
}

private AbstractTypeDeclaration findParentTypeDeclaration(ASTNode node) {
ASTNode parent = node.getParent();
while(parent != null) {
if(parent instanceof AbstractTypeDeclaration) {
return (AbstractTypeDeclaration)parent;
}
parent = parent.getParent();
}
return null;
}

private Block findParentBlock(ASTNode node) {
ASTNode parent = node.getParent();
while(parent != null) {
if(parent instanceof Block) {
return (Block)parent;
}
parent = parent.getParent();
}
return null;
}

private MethodDeclaration findParentMethodDeclaration(ASTNode node) {
ASTNode parent = node.getParent();
while(parent != null) {
if(parent instanceof MethodDeclaration) {
return (MethodDeclaration)parent;
}
parent = parent.getParent();
}
return null;
}

public boolean visit(CastExpression node) {
Expression castExpression = node.getExpression();
if(castExpression instanceof SimpleName) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ private void processAddedOperation(UMLOperation addedOperation,
callTreeMap.put(root, callTree);
}
UMLOperationBodyMapper operationBodyMapper = createMapperForExtractedMethod(mapper, mapper.getContainer1(), addedOperation, addedOperationInvocation, false);
if(operationBodyMapper != null && !containsRefactoringWithIdenticalMappings(refactorings, operationBodyMapper)) {
if(operationBodyMapper != null && (!containsRefactoringWithIdenticalMappings(refactorings, operationBodyMapper) || parentMapperContainsOperationInvocation(mapper, operationBodyMapper, addedOperationInvocation))) {
List<AbstractCodeMapping> additionalExactMatches = new ArrayList<AbstractCodeMapping>();
List<CallTreeNode> nodesInBreadthFirstOrder = callTree.getNodesInBreadthFirstOrder();
for(int i=1; i<nodesInBreadthFirstOrder.size(); i++) {
Expand Down Expand Up @@ -292,6 +292,24 @@ private void processNestedMapper(UMLOperationBodyMapper mapper, UMLOperationBody
}
}

private boolean parentMapperContainsOperationInvocation(UMLOperationBodyMapper parentMapper, UMLOperationBodyMapper childMapper, AbstractCall addedOperationInvocation) {
AbstractCodeMapping callerMapping = null;
for(AbstractCodeMapping mapping : parentMapper.getMappings()) {
if(mapping.getFragment2().getLocationInfo().subsumes(addedOperationInvocation.getLocationInfo())) {
callerMapping = mapping;
break;
}
}
if(callerMapping != null) {
for(AbstractCodeMapping mapping : childMapper.getMappings()) {
if(mapping.getFragment1().equals(callerMapping.getFragment1())) {
return true;
}
}
}
return false;
}

private boolean containsRefactoringWithIdenticalMappings(List<ExtractOperationRefactoring> refactorings, UMLOperationBodyMapper mapper) {
Set<AbstractCodeMapping> newMappings = mapper.getMappings();
for(ExtractOperationRefactoring ref : refactorings) {
Expand Down
82 changes: 51 additions & 31 deletions src/main/java/gr/uom/java/xmi/diff/UMLModelDiff.java
Original file line number Diff line number Diff line change
Expand Up @@ -273,74 +273,88 @@ public UMLClassBaseDiff getUMLClassDiff(UMLType type) {
}

private UMLClassBaseDiff getUMLClassDiffWithAttribute(Replacement pattern) {
String before = new String(pattern.getBefore());
String after = new String(pattern.getAfter());
if(before.contains(".") && after.contains(".")) {
before = before.substring(before.lastIndexOf(".") + 1, before.length());
after = after.substring(after.lastIndexOf(".") + 1, after.length());
}
for(UMLClassDiff classDiff : commonClassDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getBefore()) != null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(before) != null &&
classDiff.findAttributeInNextClass(after) != null)
return classDiff;
}
for(UMLClassMoveDiff classDiff : classMoveDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getBefore()) != null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(before) != null &&
classDiff.findAttributeInNextClass(after) != null)
return classDiff;
}
for(UMLClassMoveDiff classDiff : innerClassMoveDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getBefore()) != null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(before) != null &&
classDiff.findAttributeInNextClass(after) != null)
return classDiff;
}
for(UMLClassRenameDiff classDiff : classRenameDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getBefore()) != null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(before) != null &&
classDiff.findAttributeInNextClass(after) != null)
return classDiff;
}
return null;
}

private List<UMLClassBaseDiff> getUMLClassDiffWithExistingAttributeAfter(Replacement pattern) {
List<UMLClassBaseDiff> classDiffs = new ArrayList<UMLClassBaseDiff>();
String after = new String(pattern.getAfter());
if(after.contains(".")) {
after = after.substring(after.lastIndexOf(".") + 1, after.length());
}
for(UMLClassDiff classDiff : commonClassDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getAfter()) != null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(after) != null &&
classDiff.findAttributeInNextClass(after) != null)
classDiffs.add(classDiff);
}
for(UMLClassMoveDiff classDiff : classMoveDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getAfter()) != null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(after) != null &&
classDiff.findAttributeInNextClass(after) != null)
classDiffs.add(classDiff);
}
for(UMLClassMoveDiff classDiff : innerClassMoveDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getAfter()) != null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(after) != null &&
classDiff.findAttributeInNextClass(after) != null)
classDiffs.add(classDiff);
}
for(UMLClassRenameDiff classDiff : classRenameDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getAfter()) != null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(after) != null &&
classDiff.findAttributeInNextClass(after) != null)
classDiffs.add(classDiff);
}
return classDiffs;
}

private List<UMLClassBaseDiff> getUMLClassDiffWithNewAttributeAfter(Replacement pattern) {
List<UMLClassBaseDiff> classDiffs = new ArrayList<UMLClassBaseDiff>();
String after = new String(pattern.getAfter());
if(after.contains(".")) {
after = after.substring(after.lastIndexOf(".") + 1, after.length());
}
for(UMLClassDiff classDiff : commonClassDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getAfter()) == null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(after) == null &&
classDiff.findAttributeInNextClass(after) != null)
classDiffs.add(classDiff);
}
for(UMLClassMoveDiff classDiff : classMoveDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getAfter()) == null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(after) == null &&
classDiff.findAttributeInNextClass(after) != null)
classDiffs.add(classDiff);
}
for(UMLClassMoveDiff classDiff : innerClassMoveDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getAfter()) == null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(after) == null &&
classDiff.findAttributeInNextClass(after) != null)
classDiffs.add(classDiff);
}
for(UMLClassRenameDiff classDiff : classRenameDiffList) {
if(classDiff.findAttributeInOriginalClass(pattern.getAfter()) == null &&
classDiff.findAttributeInNextClass(pattern.getAfter()) != null)
if(classDiff.findAttributeInOriginalClass(after) == null &&
classDiff.findAttributeInNextClass(after) != null)
classDiffs.add(classDiff);
}
return classDiffs;
Expand Down Expand Up @@ -2518,13 +2532,19 @@ public List<Refactoring> getRefactorings() throws RefactoringMinerTimedOutExcept
for(Replacement pattern : renameMap.keySet()) {
UMLClassBaseDiff diff = getUMLClassDiffWithAttribute(pattern);
Set<CandidateAttributeRefactoring> set = renameMap.get(pattern);
String before = new String(pattern.getBefore());
String after = new String(pattern.getAfter());
if(before.contains(".") && after.contains(".")) {
before = before.substring(before.lastIndexOf(".") + 1, before.length());
after = after.substring(after.lastIndexOf(".") + 1, after.length());
}
for(CandidateAttributeRefactoring candidate : set) {
if(candidate.getOriginalVariableDeclaration() == null && candidate.getRenamedVariableDeclaration() == null) {
if(diff != null) {
UMLAttribute a1 = diff.findAttributeInOriginalClass(pattern.getBefore());
UMLAttribute a2 = diff.findAttributeInNextClass(pattern.getAfter());
if(!diff.getOriginalClass().containsAttributeWithName(pattern.getAfter()) &&
!diff.getNextClass().containsAttributeWithName(pattern.getBefore()) &&
UMLAttribute a1 = diff.findAttributeInOriginalClass(before);
UMLAttribute a2 = diff.findAttributeInNextClass(after);
if(!diff.getOriginalClass().containsAttributeWithName(after) &&
!diff.getNextClass().containsAttributeWithName(before) &&
!attributeMerged(a1, a2, refactorings)) {
if(innerClassMoveDiffList.contains(diff)) {
if(a1 instanceof UMLEnumConstant && a2 instanceof UMLEnumConstant) {
Expand Down Expand Up @@ -2597,7 +2617,7 @@ else if(candidate.getOriginalVariableDeclaration() != null) {
}
}
}
UMLAttribute a2 = diff1.findAttributeInNextClass(pattern.getAfter());
UMLAttribute a2 = diff1.findAttributeInNextClass(after);
if(a2 != null) {
if(candidate.getOriginalVariableDeclaration().isAttribute()) {
if(originalClassDiff != null && originalClassDiff.removedAttributes.contains(candidate.getOriginalAttribute())) {
Expand Down Expand Up @@ -2634,7 +2654,7 @@ else if(!diffs2.isEmpty()) {
}
}
}
UMLAttribute a2 = diff2.findAttributeInNextClass(pattern.getAfter());
UMLAttribute a2 = diff2.findAttributeInNextClass(after);
if(a2 != null) {
if(candidate.getOriginalVariableDeclaration().isAttribute()) {
if(originalClassDiff != null && originalClassDiff.removedAttributes.contains(candidate.getOriginalAttribute())) {
Expand Down Expand Up @@ -3847,7 +3867,7 @@ private void checkForExtractedAndMovedOperations(List<UMLOperationBodyMapper> ma
Map<String, VariableDeclaration> childFieldDeclarationMap = childCallerClass != null ? childCallerClass.getFieldDeclarationMap() : null;
for(AbstractCall invocation : operationInvocations) {
if(invocation.matchesOperation(addedOperation, mapper.getContainer2(), mapper.getClassDiff(), this)) {
addedOperationInvocations.add(invocation);
addedOperationInvocations.add(0, invocation);
}
if(addedOperation.getClassName().startsWith(mapper.getContainer2().getClassName() + ".") &&
!addedOperation.isConstructor() && !addedOperation.isGetter() && !addedOperation.isSetter()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,6 @@ public void testAllRefactorings() throws Exception {
GitHistoryRefactoringMinerImpl detector = new GitHistoryRefactoringMinerImpl();
TestBuilder test = new TestBuilder(detector, REPOS, Refactorings.All.getValue());
RefactoringPopulator.feedRefactoringsInstances(Refactorings.All.getValue(), Systems.FSE.getValue(), test);
test.assertExpectationsWithGitHubAPI(12271, 20, 233);
test.assertExpectationsWithGitHubAPI(12274, 20, 232);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ line range:643-643==line range:560-560
line range:653-653==line range:570-570
line range:702-702==line range:619-619
line range:712-713==line range:629-630
line range:723-723==line range:639-639
line range:728-730==line range:644-646
line range:735-735==line range:651-651
line range:851-851==line range:767-767
Expand Down
Loading

0 comments on commit a37ac30

Please sign in to comment.