Skip to content

Commit

Permalink
Added methods for reducing tokens to signature tokens.
Browse files Browse the repository at this point in the history
  • Loading branch information
Rafael Winterhalter committed Feb 5, 2016
1 parent 147fcac commit fd54541
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,16 @@ public Token accept(TypeDescription.Generic.Visitor<? extends TypeDescription.Ge
annotations);
}

/**
* Creates a signature token that represents the method that is represented by this token.
*
* @param declaringType The declaring type of the field that this token represents.
* @return A signature token representing this token.
*/
public SignatureToken asSignatureToken(TypeDescription declaringType) {
return new SignatureToken(name, type.accept(new TypeDescription.Generic.Visitor.Reducing(declaringType)));
}

@Override
public boolean equals(Object other) {
if (this == other) return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ public interface MethodDescription extends TypeVariableSource,
/**
* Returns this methods receiver type. A receiver type is undefined for {@code static} methods
* where {@code null} is returned.
*
* @return This method's (annotated) receiver type.
*/
TypeDescription.Generic getReceiverType();
Expand Down Expand Up @@ -1462,6 +1463,21 @@ public Token accept(TypeDescription.Generic.Visitor<? extends TypeDescription.Ge
defaultValue);
}

/**
* Creates a signature token that represents the method that is represented by this token.
*
* @param declaringType The declaring type of the method that this token represents.
* @return A signature token representing this token.
*/
public SignatureToken asSignatureToken(TypeDescription declaringType) {
TypeDescription.Generic.Visitor<TypeDescription> visitor = new TypeDescription.Generic.Visitor.Reducing(declaringType, typeVariables);
List<TypeDescription> parameters = new ArrayList<TypeDescription>(parameterTokens.size());
for (ParameterDescription.Token parameter : parameterTokens) {
parameters.add(parameter.getType().accept(visitor));
}
return new SignatureToken(name, returnType.accept(visitor), parameters);
}

@Override
public boolean equals(Object other) {
if (this == other) return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2341,6 +2341,94 @@ public String toString() {
}
}
}

/**
* A visitor that reduces a detached generic type to its erasure.
*/
class Reducing implements Visitor<TypeDescription> {

/**
* The generic type's declaring type.
*/
private final TypeDescription declaringType;

/**
* Any type variables that are directly declared by the member that declares the type being reduced.
*/
private final List<? extends TypeVariableToken> typeVariableTokens;

/**
* Creates a new reducing type visitor.
*
* @param declaringType The generic type's declaring type.
*/
public Reducing(TypeDescription declaringType) {
this(declaringType, Collections.<TypeVariableToken>emptyList());
}

/**
* Creates a new reducing type visitor.
*
* @param declaringType The generic type's declaring type.
* @param typeVariableTokens Any type variables that are directly declared by the member that declares the type being reduced.
*/
public Reducing(TypeDescription declaringType, List<? extends TypeVariableToken> typeVariableTokens) {
this.declaringType = declaringType;
this.typeVariableTokens = typeVariableTokens;
}

@Override
public TypeDescription onGenericArray(Generic genericArray) {
return genericArray.asErasure();
}

@Override
public TypeDescription onWildcard(Generic wildcard) {
throw new IllegalStateException("A wildcard cannot be a top-level type: " + wildcard);
}

@Override
public TypeDescription onParameterizedType(Generic parameterizedType) {
return parameterizedType.asErasure();
}

@Override
public TypeDescription onTypeVariable(Generic typeVariable) {
for (TypeVariableToken typeVariableToken : typeVariableTokens) {
if (typeVariable.getSymbol().equals(typeVariableToken.getSymbol())) {
return typeVariableToken.getBounds().get(0).accept(this);
}
}
return declaringType.findVariable(typeVariable.getSymbol()).asErasure();
}

@Override
public TypeDescription onNonGenericType(Generic typeDescription) {
return typeDescription.asErasure();
}

@Override
public boolean equals(Object other) {
return this == other || !(other == null || getClass() != other.getClass())
&& declaringType.equals(((Reducing) other).declaringType)
&& typeVariableTokens.equals(((Reducing) other).typeVariableTokens);
}

@Override
public int hashCode() {
int result = declaringType.hashCode();
result = 31 * result + typeVariableTokens.hashCode();
return result;
}

@Override
public String toString() {
return "TypeDescription.Generic.Visitor.Reducing{" +
"declaringType=" + declaringType +
", typeVariableTokens=" + typeVariableTokens +
'}';
}
}
}

/**
Expand Down Expand Up @@ -3835,7 +3923,7 @@ public String toString() {
}

/**
* A chained annotation reader for reading an owner type.
* A chained annotation reader for reading an owner type.
*/
class ForOwnerType extends Delegator.Chained {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ public class FieldDescriptionTokenTest {
@Mock
private TypeDescription.Generic type, visitedType;

@Mock
private TypeDescription typeDescription, rawType;

@Mock
private AnnotationDescription annotation;

Expand Down Expand Up @@ -57,6 +60,13 @@ public void testVisitor() throws Exception {
is(new FieldDescription.Token(FOO, MODIFIERS, visitedType, Collections.singletonList(annotation))));
}

@Test
public void testSignatureTokenTransformation() throws Exception {
when(type.accept(new TypeDescription.Generic.Visitor.Reducing(typeDescription))).thenReturn(rawType);
assertThat(new FieldDescription.Token(FOO, MODIFIERS, type, Collections.singletonList(annotation)).asSignatureToken(typeDescription),
is(new FieldDescription.SignatureToken(FOO, rawType)));
}

@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(FieldDescription.Token.class).apply();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,17 @@ public class MethodDescriptionTokenTest {
public TestRule mockitoRule = new MockitoRule(this);

@Mock
private TypeDescription.Generic returnType, visitedReturnType, exceptionType, visitedExceptionType;
private TypeDescription.Generic returnType, visitedReturnType, exceptionType, visitedExceptionType, parameterType;

@Mock
private ParameterDescription.Token parameterToken, visitedParameterToken;

@Mock
private TypeVariableToken typeVariableToken, visitedTypeVariableToken;

@Mock
private TypeDescription typeDescription, rawReturnType, rawParameterType;

@Mock
private AnnotationDescription annotation;

Expand Down Expand Up @@ -99,6 +102,24 @@ public void testVisitor() throws Exception {
defaultValue)));
}

@Test
public void testSignatureTokenTransformation() throws Exception {
when(returnType.accept(new TypeDescription.Generic.Visitor.Reducing(typeDescription, Collections.singletonList(typeVariableToken))))
.thenReturn(rawReturnType);
when(parameterToken.getType()).thenReturn(parameterType);
when(parameterType.accept(new TypeDescription.Generic.Visitor.Reducing(typeDescription, Collections.singletonList(typeVariableToken))))
.thenReturn(rawParameterType);
assertThat(new MethodDescription.Token(FOO,
MODIFIERS,
Collections.singletonList(typeVariableToken),
returnType,
Collections.singletonList(parameterToken),
Collections.singletonList(exceptionType),
Collections.singletonList(annotation),
defaultValue).asSignatureToken(typeDescription),
is(new MethodDescription.SignatureToken(FOO, rawReturnType, Collections.singletonList(rawParameterType))));
}

@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(MethodDescription.Token.class).create(new ObjectPropertyAssertion.Creator<List<?>>() {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package net.bytebuddy.description.type;

import net.bytebuddy.test.utility.MockitoRule;
import net.bytebuddy.test.utility.ObjectPropertyAssertion;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestRule;
import org.mockito.Mock;

import java.util.Collections;

import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.*;

public class TypeDescriptionGenericVisitorReducingTest {

private static final String FOO = "foo", BAR = "bar";

@Rule
public TestRule mockitoRule = new MockitoRule(this);

@Mock
private TypeDescription.Generic typeDescription, bound, genericTypeDescription;

@Mock
private TypeDescription declaringType, rawTypeDescription;

@Mock
private TypeVariableToken typeVariableToken;

private TypeDescription.Generic.Visitor<TypeDescription> visitor;

@Before
public void setUp() throws Exception {
when(bound.asGenericType()).thenReturn(bound);
visitor = new TypeDescription.Generic.Visitor.Reducing(declaringType, Collections.singletonList(typeVariableToken));
}

@Test(expected = IllegalStateException.class)
public void testWildcardThrowsException() throws Exception {
visitor.onWildcard(typeDescription);
}

@Test
public void testGenericArray() throws Exception {
when(typeDescription.asErasure()).thenReturn(rawTypeDescription);
assertThat(visitor.onGenericArray(typeDescription), is(rawTypeDescription));
verify(typeDescription).asErasure();
verifyNoMoreInteractions(typeDescription);
}

@Test
public void testParameterizedType() throws Exception {
when(typeDescription.asErasure()).thenReturn(rawTypeDescription);
assertThat(visitor.onParameterizedType(typeDescription), is(rawTypeDescription));
verify(typeDescription).asErasure();
verifyNoMoreInteractions(typeDescription);
}

@Test
public void testNonGenericType() throws Exception {
when(typeDescription.asErasure()).thenReturn(rawTypeDescription);
assertThat(visitor.onNonGenericType(typeDescription), is(rawTypeDescription));
verify(typeDescription).asErasure();
verifyNoMoreInteractions(typeDescription);
}

@Test
public void testTypeVariableSelfDeclared() throws Exception {
when(typeDescription.getSymbol()).thenReturn(FOO);
when(typeVariableToken.getSymbol()).thenReturn(FOO);
when(typeVariableToken.getBounds()).thenReturn(new TypeList.Generic.Explicit(bound));
when(bound.accept(visitor)).thenReturn(rawTypeDescription);
assertThat(visitor.onTypeVariable(typeDescription), is(rawTypeDescription));
verify(typeDescription).getSymbol();
verifyNoMoreInteractions(typeDescription);
verify(typeVariableToken).getSymbol();
verify(typeVariableToken).getBounds();
verifyNoMoreInteractions(typeVariableToken);
}

@Test
public void testTypeVariableContextDeclared() throws Exception {
when(typeDescription.getSymbol()).thenReturn(FOO);
when(typeVariableToken.getSymbol()).thenReturn(BAR);
when(declaringType.findVariable(FOO)).thenReturn(genericTypeDescription);
when(genericTypeDescription.asErasure()).thenReturn(rawTypeDescription);
assertThat(visitor.onTypeVariable(typeDescription), is(rawTypeDescription));
verify(typeDescription, times(2)).getSymbol();
verifyNoMoreInteractions(typeDescription);
verify(typeVariableToken).getSymbol();
verifyNoMoreInteractions(typeVariableToken);
verify(declaringType).findVariable(FOO);
verifyNoMoreInteractions(declaringType);
}

@Test
public void testObjectProperties() throws Exception {
ObjectPropertyAssertion.of(TypeDescription.Generic.Visitor.Reducing.class).apply();
}
}

0 comments on commit fd54541

Please sign in to comment.