Skip to content

Commit

Permalink
[fix] Check for content equality in mapping inference, fix #90
Browse files Browse the repository at this point in the history
  • Loading branch information
slarse committed Mar 29, 2020
1 parent 44a7e55 commit 871c026
Show file tree
Hide file tree
Showing 3 changed files with 96 additions and 73 deletions.
82 changes: 82 additions & 0 deletions src/main/java/se/kth/spork/spoon/ContentResolver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package se.kth.spork.spoon;

import spoon.reflect.code.*;
import spoon.reflect.declaration.*;
import spoon.reflect.path.CtRole;
import spoon.reflect.reference.CtReference;
import spoon.reflect.reference.CtWildcardReference;

import java.util.function.Function;

/**
* This class determines what the content of any given type of node is.
*
* @author Simon Larsén
*/
class ContentResolver implements Function<SpoonNode, RoledValues> {

/**
* Return the content of the supplied node. For example, the content of a CtLiteral is its value, and the
* content of a CtNamedElement is its simple name.
*
* @param node A node to resolve the content for.
* @return The content of the node.
*/
@Override
public RoledValues apply(SpoonNode node) {
return getContent(node.getElement());
}

/**
* Return the content of the supplied Spoon element. For example, the content of a CtLiteral is its value, and the
* content of a CtNamedElement is its simple name.
*
* @param elem A node to resolve the content for.
* @return The content of the node.
*/
public static RoledValues getContent(CtElement elem) {
RoledValues rvs = new RoledValues(elem);

// general values
rvs.add(CtRole.IS_IMPLICIT, elem.isImplicit());

// element-specific values
if (elem instanceof CtLiteral) {
CtLiteral<?> lit = (CtLiteral<?>) elem;
rvs.add(CtRole.VALUE, lit.getValue());
} else if (elem instanceof CtReference || elem instanceof CtNamedElement) {
String name = elem.getValueByRole(CtRole.NAME);
if (!name.matches("\\d+")) {
// Only pick up name if it's not a digit.
// A digit implies anonymous function, see https://github.com/kth/spork/issues/86 for why we don't
// want those.
rvs.add(CtRole.NAME, elem.getValueByRole(CtRole.NAME));
}
} else if (elem instanceof CtBinaryOperator || elem instanceof CtUnaryOperator || elem instanceof CtOperatorAssignment) {
rvs.add(CtRole.OPERATOR_KIND, elem.getValueByRole(CtRole.OPERATOR_KIND));
}

if (elem instanceof CtParameter) {
rvs.add(CtRole.IS_VARARGS, elem.getValueByRole(CtRole.IS_VARARGS));
}
if (elem instanceof CtModifiable) {
rvs.add(CtRole.MODIFIER, elem.getValueByRole(CtRole.MODIFIER));
}
if (elem instanceof CtWildcardReference) {
rvs.add(CtRole.IS_UPPER, elem.getValueByRole(CtRole.IS_UPPER));
}
if (elem instanceof CtComment) {
String rawContent = ((CtComment) elem).getRawContent();
RoledValue content = new RoledValue(CtRole.COMMENT_CONTENT, elem.getValueByRole(CtRole.COMMENT_CONTENT));
content.putMetadata(RoledValue.Key.RAW_CONTENT, rawContent);

rvs.add(content);
rvs.add(CtRole.COMMENT_TYPE, elem.getValueByRole(CtRole.COMMENT_TYPE));
}
if (elem instanceof CtMethod) {
rvs.add(CtRole.IS_DEFAULT, elem.getValueByRole(CtRole.IS_DEFAULT));
}

return rvs;
}
}
75 changes: 3 additions & 72 deletions src/main/java/se/kth/spork/spoon/Spoon3dmMerge.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,10 @@
import org.slf4j.LoggerFactory;
import se.kth.spork.base3dm.*;
import se.kth.spork.util.Pair;
import spoon.reflect.code.*;
import spoon.reflect.declaration.*;
import spoon.reflect.path.CtRole;
import spoon.reflect.reference.CtReference;
import spoon.reflect.reference.CtWildcardReference;

import java.nio.file.Path;
import java.util.*;
import java.util.function.Function;

/**
* Spoon specialization of the 3DM merge algorithm.
Expand Down Expand Up @@ -86,8 +81,8 @@ public static <T extends CtElement> Pair<T, Boolean> merge(T base, T left, T rig
Set<Pcs<SpoonNode>> t2 = PcsBuilder.fromSpoon(right, Revision.RIGHT);

LOGGER.info("Computing raw PCS merge");
ChangeSet<SpoonNode, RoledValues> delta = new ChangeSet<>(classRepMap, new GetContent(), t0, t1, t2);
ChangeSet<SpoonNode, RoledValues> t0Star = new ChangeSet<>(classRepMap, new GetContent(), t0);
ChangeSet<SpoonNode, RoledValues> delta = new ChangeSet<>(classRepMap, new ContentResolver(), t0, t1, t2);
ChangeSet<SpoonNode, RoledValues> t0Star = new ChangeSet<>(classRepMap, new ContentResolver(), t0);

LOGGER.info("Resolving final PCS merge");
TdmMerge.resolveRawMerge(t0Star, delta);
Expand All @@ -103,7 +98,7 @@ public static <T extends CtElement> Pair<T, Boolean> merge(T base, T left, T rig
base, left, right, baseLeft, baseRight, leftRight);

LOGGER.info("Computing raw PCS merge");
delta = new ChangeSet<>(classRepMap, new GetContent(), t0, t1, t2);
delta = new ChangeSet<>(classRepMap, new ContentResolver(), t0, t1, t2);

LOGGER.info("Resolving final PCS merge");
TdmMerge.resolveRawMerge(t0Star, delta);
Expand Down Expand Up @@ -219,70 +214,6 @@ private static List<CtImport> mergeImportStatements(CtElement base, CtElement le
return ret;
}

/**
* This class determines what the content of any given type of node is.
*/
private static class GetContent implements Function<SpoonNode, RoledValues> {

/**
* Return the content of the supplied node. For example, the content of a CtLiteral is its value, and the
* content of a CtNamedElement is its simple name.
*
* @param wrapper A wrapped Spoon node.
* @return The content of the node.
*/
@Override
public RoledValues apply(SpoonNode wrapper) {
if (wrapper == null || wrapper.getElement() == null)
return null;

CtElement elem = wrapper.getElement();
RoledValues rvs = new RoledValues(elem);

// general values
rvs.add(CtRole.IS_IMPLICIT, elem.isImplicit());

// element-specific values
if (elem instanceof CtLiteral) {
CtLiteral<?> lit = (CtLiteral<?>) elem;
rvs.add(CtRole.VALUE, lit.getValue());
} else if (elem instanceof CtReference || elem instanceof CtNamedElement) {
String name = elem.getValueByRole(CtRole.NAME);
if (!name.matches("\\d+")) {
// Only pick up name if it's not a digit.
// A digit implies anonymous function, see https://github.com/kth/spork/issues/86 for why we don't
// want those.
rvs.add(CtRole.NAME, elem.getValueByRole(CtRole.NAME));
}
} else if (elem instanceof CtBinaryOperator || elem instanceof CtUnaryOperator || elem instanceof CtOperatorAssignment) {
rvs.add(CtRole.OPERATOR_KIND, elem.getValueByRole(CtRole.OPERATOR_KIND));
}

if (elem instanceof CtParameter) {
rvs.add(CtRole.IS_VARARGS, elem.getValueByRole(CtRole.IS_VARARGS));
}
if (elem instanceof CtModifiable) {
rvs.add(CtRole.MODIFIER, elem.getValueByRole(CtRole.MODIFIER));
}
if (elem instanceof CtWildcardReference) {
rvs.add(CtRole.IS_UPPER, elem.getValueByRole(CtRole.IS_UPPER));
}
if (elem instanceof CtComment) {
String rawContent = ((CtComment) elem).getRawContent();
RoledValue content = new RoledValue(CtRole.COMMENT_CONTENT, elem.getValueByRole(CtRole.COMMENT_CONTENT));
content.putMetadata(RoledValue.Key.RAW_CONTENT, rawContent);

rvs.add(content);
rvs.add(CtRole.COMMENT_TYPE, elem.getValueByRole(CtRole.COMMENT_TYPE));
}
if (elem instanceof CtMethod) {
rvs.add(CtRole.IS_DEFAULT, elem.getValueByRole(CtRole.IS_DEFAULT));
}

return rvs;
}
}

private static Matcher matchTrees(ITree src, ITree dst) {
Matcher matcher = Matchers.getInstance().getMatcher(src, dst);
matcher.match();
Expand Down
12 changes: 11 additions & 1 deletion src/main/java/se/kth/spork/spoon/SpoonMapping.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import se.kth.spork.util.GumTreeSpoonAstDiff;
import spoon.reflect.declaration.CtAnnotation;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.declaration.CtTypeInformation;
import spoon.reflect.path.CtRole;

import java.util.ArrayList;
Expand Down Expand Up @@ -97,6 +98,13 @@ private static boolean ignoreMapping(CtElement src, CtElement dst) {
return false;
}

private static boolean isPrimitiveType(CtElement elem) {
if (elem instanceof CtTypeInformation) {
return ((CtTypeInformation) elem).isPrimitive();
}
return false;
}

private static boolean isAnnotationValue(CtElement elem) {
return elem.getParent() instanceof CtAnnotation && elem.getRoleInParent() == CtRole.VALUE;
}
Expand Down Expand Up @@ -138,7 +146,9 @@ private List<Pair<CtElement, CtElement>> inferAdditionalMappings(CtElement src,
} else if (hasDst(dstChild) || !GumTreeSpoonAstDiff.isToIgnore(dstChild)) {
dstIdx++;
} else {
if (srcChild.getClass() == dstChild.getClass()) {
boolean sameClass = srcChild.getClass() == dstChild.getClass();
boolean sameContent = ContentResolver.getContent(srcChild).equals(ContentResolver.getContent(dstChild));
if (sameClass && sameContent) {
put(srcChild, dstChild);
newMatches.add(new Pair<>(srcChild, dstChild));
}
Expand Down

0 comments on commit 871c026

Please sign in to comment.