Skip to content

Commit

Permalink
[fact] Refactor handling of node contents #1
Browse files Browse the repository at this point in the history
  • Loading branch information
slarse committed Feb 17, 2020
1 parent 9d432ef commit 9254b7e
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 18 deletions.
51 changes: 51 additions & 0 deletions src/main/java/se/kth/spork/merge/spoon/RoledValue.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package se.kth.spork.merge.spoon;

import spoon.reflect.path.CtRole;

import java.util.Objects;

/**
* Class representing some form of value in a Spoon node, along with the role the value has. This is for
* example the name of a method, or the value in a literal.
*
* @author Simon Larsén
*/
class RoledValue {
private final Object value;
private final CtRole role;

public RoledValue(Object value, CtRole role) {
this.value = value;
this.role = role;
}

public Object getValue() {
return value;
}

public CtRole getRole() {
return role;
}

@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
RoledValue roledValue1 = (RoledValue) o;
return role == roledValue1.role &&
Objects.equals(value, roledValue1.value);
}

@Override
public int hashCode() {
return Objects.hash(value, role);
}

@Override
public String toString() {
return "Value{" +
"value=" + value +
", role=" + role +
'}';
}
}
13 changes: 7 additions & 6 deletions src/main/java/se/kth/spork/merge/spoon/Spoon3dmMerge.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import se.kth.spork.merge.TdmMerge;
import spoon.reflect.code.CtLiteral;
import spoon.reflect.declaration.*;
import spoon.reflect.path.CtRole;

import java.util.HashMap;
import java.util.Iterator;
Expand Down Expand Up @@ -62,8 +63,8 @@ public static CtClass<?> merge(CtClass<?> base, CtClass<?> left, CtClass<?> righ
Set<Pcs<SpoonNode>> t2 = SpoonPcs.fromSpoon(right, Revision.RIGHT);

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

LOGGER.info("Resolving final PCS merge");
TdmMerge.resolveRawMerge(t0Star, delta);
Expand All @@ -75,7 +76,7 @@ public static CtClass<?> merge(CtClass<?> base, CtClass<?> left, CtClass<?> righ
/**
* This class determines what the content of any given type of node is.
*/
private static class GetContent implements Function<SpoonNode, Object> {
private static class GetContent implements Function<SpoonNode, RoledValue> {

/**
* Return the content of the supplied node. For example, the content of a CtLiteral is its value.
Expand All @@ -86,17 +87,17 @@ private static class GetContent implements Function<SpoonNode, Object> {
* @return The content of the node.
*/
@Override
public Object apply(SpoonNode wrapper) {
public RoledValue apply(SpoonNode wrapper) {
if (wrapper == null)
return null;

CtElement elem = wrapper.getElement();
if (elem instanceof CtModule || elem instanceof CtPackage) {
return null;
} else if (elem instanceof CtLiteral) {
return ((CtLiteral<?>) elem).getValue();
return new RoledValue(((CtLiteral<?>) elem).getValue(), CtRole.VALUE);
}
return elem.getShortRepresentation();
return new RoledValue(elem.getShortRepresentation(), null);
}
}

Expand Down
29 changes: 17 additions & 12 deletions src/main/java/se/kth/spork/merge/spoon/SpoonPcs.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import se.kth.spork.merge.Pcs;
import se.kth.spork.merge.Revision;
import se.kth.spork.merge.TdmMerge;
import spoon.reflect.code.CtLiteral;
import spoon.reflect.declaration.CtClass;
import spoon.reflect.declaration.CtElement;
import spoon.reflect.path.CtRole;
Expand Down Expand Up @@ -43,7 +42,7 @@ public static Set<Pcs<SpoonNode>> fromSpoon(CtClass<?> spoonClass, Revision revi
*/
public static CtClass<?> fromMergedPcs(
Set<Pcs<SpoonNode>> pcses,
Map<SpoonNode, Set<Content<SpoonNode,Object>>> contents,
Map<SpoonNode, Set<Content<SpoonNode, RoledValue>>> contents,
SpoonMapping baseLeft,
SpoonMapping baseRight) {
Builder builder = new Builder(contents, baseLeft, baseRight);
Expand Down Expand Up @@ -92,11 +91,11 @@ private static <V> void traversePcs(Map<V, Map<V, Pcs<V>>> rootToChildren, V cur
private static class Builder implements BiConsumer<SpoonNode, SpoonNode> {
private CtClass<?> actualRoot;
private Map<SpoonNode, SpoonNode> nodes;
private Map<SpoonNode, Set<Content<SpoonNode,Object>>> contents;
private Map<SpoonNode, Set<Content<SpoonNode, RoledValue>>> contents;
private SpoonMapping baseLeft;
private SpoonMapping baseRight;

private Builder(Map<SpoonNode, Set<Content<SpoonNode,Object>>> contents, SpoonMapping baseLeft, SpoonMapping baseRight) {
private Builder(Map<SpoonNode, Set<Content<SpoonNode, RoledValue>>> contents, SpoonMapping baseLeft, SpoonMapping baseRight) {
nodes = new HashMap<>();
this.contents = contents;
this.baseLeft = baseLeft;
Expand Down Expand Up @@ -226,18 +225,24 @@ private CtElement copyTree(CtElement tree, CtElement root) {
}
treeCopy.setAllMetadata(new HashMap<>()); // empty the metadata

// TODO properly set the content of types other than CtLiteral
if (treeCopy instanceof CtLiteral) {
SpoonNode wrapped = NodeFactory.wrap(tree);
Set<Content<SpoonNode,Object>> value = contents.get(wrapped);
if (value != null) {
((CtLiteral) treeCopy).setValue(value.iterator().next().getValue());
}
}
SpoonNode wrapped = NodeFactory.wrap(tree);
Set<Content<SpoonNode, RoledValue>> nodeContents = contents.get(wrapped);
setContent(treeCopy, nodeContents);

treeCopy.setParent(root);
return treeCopy;
}

private void setContent(CtElement node, Set<Content<SpoonNode, RoledValue>> nodeContents) {
if (nodeContents.size() > 1) {
throw new IllegalStateException("unexpected amount of content: " + nodeContents);
}

RoledValue roledValue = nodeContents.iterator().next().getValue();
if (roledValue.getRole() != null) {
node.setValueByRole(roledValue.getRole(), roledValue.getValue());
}
}
}

}

0 comments on commit 9254b7e

Please sign in to comment.