Skip to content

Commit

Permalink
[feat] Handle content for the most common code elements #1
Browse files Browse the repository at this point in the history
  • Loading branch information
slarse committed Feb 17, 2020
1 parent 9254b7e commit 72cdd9f
Show file tree
Hide file tree
Showing 26 changed files with 746 additions and 9 deletions.
19 changes: 12 additions & 7 deletions src/main/java/se/kth/spork/merge/spoon/Spoon3dmMerge.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import spoon.reflect.code.CtLiteral;
import spoon.reflect.declaration.*;
import spoon.reflect.path.CtRole;
import spoon.reflect.reference.CtReference;

import java.util.HashMap;
import java.util.Iterator;
Expand Down Expand Up @@ -79,9 +80,8 @@ public static CtClass<?> merge(CtClass<?> base, CtClass<?> left, CtClass<?> righ
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.
* <p>
* TODO extract more types of content
* 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.
Expand All @@ -92,10 +92,15 @@ public RoledValue apply(SpoonNode wrapper) {
return null;

CtElement elem = wrapper.getElement();
if (elem instanceof CtModule || elem instanceof CtPackage) {
return null;
} else if (elem instanceof CtLiteral) {
return new RoledValue(((CtLiteral<?>) elem).getValue(), CtRole.VALUE);
if (elem instanceof CtLiteral) {
CtLiteral<?> lit = (CtLiteral<?>) elem;
return new RoledValue(lit.getValue(), CtRole.VALUE);
} else if (elem instanceof CtReference) {
CtReference ref = (CtReference) elem;
return new RoledValue(ref.getSimpleName(), CtRole.NAME);
} else if (elem instanceof CtNamedElement) {
CtNamedElement namedElem = (CtNamedElement) elem;
return new RoledValue(namedElem.getSimpleName(), CtRole.NAME);
}
return new RoledValue(elem.getShortRepresentation(), null);
}
Expand Down
26 changes: 24 additions & 2 deletions src/test/java/se/kth/spork/merge/spoon/Spoon3dmMergeTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,37 @@ class Spoon3dmMergeTest {
private static final Path bothModifiedDirpath = cleanMergeDirpath.resolve("both_modified");

@ParameterizedTest
@ValueSource(strings = {"add_parameter", "delete_method", "add_if_block", "delete_if_block"})
@ValueSource(strings = {
"add_parameter",
"delete_method",
"add_if_block",
"delete_if_block",
"rename_method",
"rename_class",
"change_declared_type",
"rename_variable",
"rename_parameter",
"rename_type_parameter",
})
void mergeToTree_shouldReturnExpectedTree_whenLeftVersionIsModified(String testName) throws IOException{
File testDir = leftModifiedDirpath.resolve(testName).toFile();
Util.TestSources sources = fromTestDirectory(testDir);
runTestMerge(sources);
}

@ParameterizedTest
@ValueSource(strings = {"add_parameter", "delete_method", "add_if_block", "delete_if_block"})
@ValueSource(strings = {
"add_parameter",
"delete_method",
"add_if_block",
"delete_if_block",
"rename_method",
"rename_class",
"change_declared_type",
"rename_variable",
"rename_parameter",
"rename_type_parameter",
})
void mergeToTree_shouldReturnExpectedTree_whenRightVersionIsModified(String testName) throws IOException{
File testDir = leftModifiedDirpath.resolve(testName).toFile();
Util.TestSources sources = fromTestDirectory(testDir);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public class Adder {
public int add(int a, int b) {
int result = a + b;
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public class Adder {
public long add(long a, long b) {
long result = a + b;
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public class Adder {
public long add(long a, long b) {
long result = a + b;
return result;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
public class Adder {
public int add(int a, int b) {
int result = a + b;
return result;
}
}
5 changes: 5 additions & 0 deletions src/test/resources/clean/left_modified/rename_class/Base.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class BadClass {
public static void main(String[] args) {
BadClass bc = new BadClass();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class GoodClass {
public static void main(String[] args) {
GoodClass bc = new GoodClass();
}
}
5 changes: 5 additions & 0 deletions src/test/resources/clean/left_modified/rename_class/Left.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class GoodClass {
public static void main(String[] args) {
GoodClass bc = new GoodClass();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
public class BadClass {
public static void main(String[] args) {
BadClass bc = new BadClass();
}
}
79 changes: 79 additions & 0 deletions src/test/resources/clean/left_modified/rename_method/Base.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import java.util.EmptyStackException;

/**
* An array-based implementation of the Stack interface.
*
* @author Simon Larsén
*/
public class ArrayStack<T> implements Stack<T> {
private static final int INITIAL_CAPACITY = 10;
private Object[] elements;
private int size;

/**
* Creat an empty ArrayStack.
*/
public ArrayStack() {
elements = new Object[INITIAL_CAPACITY];
}

@Override
public void push(T element) {
ensureCapacity(size + 1);
elements[size++] = element;
}

@Override
public T pop() {
T elem = checkedTop();
// null element to avoid blocking GC
elements[size--] = null;
return elem;
}

@Override
public T top() {
return checkedTop();
}

@Override
public int size() {
return size;
}

@Override
public boolean isEmpty() {
return size == 0;
}

/**
* Checked fetching of the top element, throws an EmptyStackException if
* the stack is empty.
*/
private T checkedTop() {
if (size == 0) {
throw new EmptyStackException();
}

return (T) elements[size - 1];
}

/**
* Ensure that the capacity is at least minCapacity.
*/
private void ensureCapacity(int minCapacity) {
if (minCapacity > elements.length) {
grow();
}
}

/**
* Replace the current backing array with a larger one and copy over the
* elements to the now array.
*/
private void grow() {
Object[] newElements = new Object[elements.length << 1];
System.arraycopy(elements, 0, newElements, 0, elements.length);
elements = newElements;
}
}
74 changes: 74 additions & 0 deletions src/test/resources/clean/left_modified/rename_method/Expected.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import java.util.EmptyStackException;

/**
* An array-based implementation of the Stack interface.
*
* @author Simon Larsén
*/
public class ArrayStack<T> implements Stack<T> {
private static final int INITIAL_CAPACITY = 10;
private Object[] elements;
private int size;

/**
* Creat an empty ArrayStack.
*/
public ArrayStack() {
elements = new Object[INITIAL_CAPACITY];
}

@Override
public void push(T element) {
ensureCapacity(size + 1);
elements[size++] = element;
}

@Override
public T pop() {
T elem = checkedGetTop();
// null element to avoid blocking GC
elements[size--] = null;
return elem;
}

@Override
public int size() {
return size;
}

@Override
public boolean isEmpty() {
return size == 0;
}

/**
* Checked fetching of the top element, throws an EmptyStackException if
* the stack is empty.
*/
private T checkedGetTop() {
if (size == 0) {
throw new EmptyStackException();
}

return (T) elements[size - 1];
}

/**
* Ensure that the capacity is at least minCapacity.
*/
private void ensureCapacity(int minCapacity) {
if (minCapacity > elements.length) {
grow();
}
}

/**
* Replace the current backing array with a larger one and copy over the
* elements to the now array.
*/
private void grow() {
Object[] newElements = new Object[elements.length << 1];
System.arraycopy(elements, 0, newElements, 0, elements.length);
elements = newElements;
}
}
74 changes: 74 additions & 0 deletions src/test/resources/clean/left_modified/rename_method/Left.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import java.util.EmptyStackException;

/**
* An array-based implementation of the Stack interface.
*
* @author Simon Larsén
*/
public class ArrayStack<T> implements Stack<T> {
private static final int INITIAL_CAPACITY = 10;
private Object[] elements;
private int size;

/**
* Creat an empty ArrayStack.
*/
public ArrayStack() {
elements = new Object[INITIAL_CAPACITY];
}

@Override
public void push(T element) {
ensureCapacity(size + 1);
elements[size++] = element;
}

@Override
public T pop() {
T elem = checkedGetTop();
// null element to avoid blocking GC
elements[size--] = null;
return elem;
}

@Override
public int size() {
return size;
}

@Override
public boolean isEmpty() {
return size == 0;
}

/**
* Checked fetching of the top element, throws an EmptyStackException if
* the stack is empty.
*/
private T checkedGetTop() {
if (size == 0) {
throw new EmptyStackException();
}

return (T) elements[size - 1];
}

/**
* Ensure that the capacity is at least minCapacity.
*/
private void ensureCapacity(int minCapacity) {
if (minCapacity > elements.length) {
grow();
}
}

/**
* Replace the current backing array with a larger one and copy over the
* elements to the now array.
*/
private void grow() {
Object[] newElements = new Object[elements.length << 1];
System.arraycopy(elements, 0, newElements, 0, elements.length);
elements = newElements;
}
}
Loading

0 comments on commit 72cdd9f

Please sign in to comment.