Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 2 additions & 7 deletions .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -183,7 +183,7 @@ protected Expression visitNewArray(final NewArrayExpression node) {
return node.update(visit(node.getExpressions()));
}

protected <T> LambdaExpression<T> visitLambda(final LambdaExpression<T> node) {
protected <T> Expression visitLambda(final LambdaExpression<T> node) {
return node.update(visit(node.getBody()), visitAndConvertList(node.getParameters(), "visitLambda"));
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ final class FieldExpression extends MemberExpression {
}

@Override
FieldInfo getMember() {
public FieldInfo getMember() {
return _field;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ public final Expression getTarget() {
return _target;
}

MemberInfo getMember() {
public MemberInfo getMember() {
throw ContractUtils.unreachable();
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ static Expression optimize(final Expression node) {
}

static <T> LambdaExpression<T> optimize(final LambdaExpression<T> node) {
return OPTIMIZER.visitLambda(node);
final @SuppressWarnings("unchecked") LambdaExpression<T> lambda = (LambdaExpression<T>) OPTIMIZER.visitLambda(node);
return lambda;
}

@Override
Expand All @@ -52,7 +53,7 @@ protected Expression visitBinary(final BinaryExpression node) {

return super.visitBinary(node);
}

@Override
protected Expression visitUnary(final UnaryExpression node) {
Expression reduced = reduceNullConstantCheck(node);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,14 +122,14 @@ public boolean equals(final Object o) {

@Override
public int hashCode() {
final int nameHash = HashUtilities.hashCode(getName());
final int baseHash = HashUtilities.combineHashCodes(getName(), getErasedSignature());
final Type t = getDeclaringType();

if (t != null) {
return HashUtilities.combineHashCodes(t.hashCode(), nameHash);
return HashUtilities.combineHashCodes(t.getInternalName(), baseHash);
}

return nameHash;
return baseHash;
}

public boolean isEquivalentTo(final MemberInfo m) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -772,7 +772,7 @@ public Type<?> visitField(final Field field, final Frame frame) {
final ReflectedField reflectedField = new ReflectedField(
declaringType,
field,
frame.resolveType(field.getType())
frame.resolveType(field.getGenericType())
);

declaringType.addField(reflectedField);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -331,13 +331,11 @@ public boolean containsGenericParameter(final Type<?> genericParameter) {
return this.isEquivalentTo(genericParameter);
}

if (isGenericTypeDefinition()) {
final TypeBindings typeArguments = getTypeBindings();
final TypeBindings typeArguments = getTypeBindings();

for (int i = 0, n = typeArguments.size(); i < n; i++) {
if (typeArguments.getBoundType(i).containsGenericParameter(genericParameter)) {
return true;
}
for (int i = 0, n = typeArguments.size(); i < n; i++) {
if (typeArguments.getBoundType(i).containsGenericParameter(genericParameter)) {
return true;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

import com.strobel.core.Comparer;
import com.strobel.core.HashUtilities;
import com.strobel.reflection.emit.TypeBuilder;
import com.strobel.util.TypeUtils;

import java.util.LinkedHashMap;
Expand All @@ -36,20 +37,19 @@ public Key key(final Type<?> type, final TypeList typeArguments) {
return new Key(type.isGenericType() ? type.getGenericTypeDefinition() : type, typeArguments);
}

public Type find(final Key key) {
public Type<?> find(final Key key) {
return _map.get(key);
}

public <T> Type<T[]> getArrayType(final Type<T> elementType) {
add(elementType);

Type<T[]> arrayType = (Type<T[]>) _arrayMap.get(elementType);

if (arrayType != null) {
return arrayType;
if (arrayType == null) {
_arrayMap.put(elementType, arrayType = elementType.createArrayType());
}

arrayType = elementType.createArrayType();
add(arrayType);

return arrayType;
}

Expand All @@ -59,15 +59,15 @@ public <T> Type<T> getGenericType(final Type<T> type, final TypeList typeArgumen
typeArguments
);

Type genericType = _map.get(key);
Type<T> genericType = (Type<T>) _map.get(key);

if (genericType == null) {
genericType = new GenericType(
genericType = new GenericType<>(
type.getGenericTypeDefinition(),
typeArguments
);

final Type existing = _map.put(key, genericType);
final Type<T> existing = (Type<T>) _map.put(key, genericType);

if (existing != null) {
return existing;
Expand All @@ -85,7 +85,7 @@ public int size() {
return _map.size();
}

public void put(final Key key, final Type type) {
void put(final Key key, final Type<?> type) {
final String descriptor = key.descriptor;

if (!_definitionMap.containsKey(descriptor)) {
Expand All @@ -102,26 +102,29 @@ public void put(final Key key, final Type type) {
}

_map.put(key, type);
}

if (type.isArray()) {
final Type elementType = type.getElementType();
if (!_arrayMap.containsKey(elementType)) {
_arrayMap.put(elementType, type);
}
public void add(final Type<?> type) {
Type<?> coreType = type;

while (coreType.isArray()) {
coreType = coreType.getElementType();
}

if (coreType.isWildcardType() || coreType.isGenericParameter() || coreType instanceof TypeBuilder<?>) {
return;
}
}

public void add(final Type type) {
final TypeList typeArguments;

if (type.isGenericType()) {
typeArguments = type.getTypeBindings().getBoundTypes();
if (coreType.isGenericType()) {
typeArguments = coreType.getTypeBindings().getBoundTypes();
}
else {
typeArguments = TypeList.empty();
}

put(key(type, typeArguments), type);
put(key(coreType, typeArguments), coreType);
}

final static class Key {
Expand Down Expand Up @@ -181,8 +184,8 @@ public final boolean equals(final Object o) {
}

for (int i = 0, n = typeArguments.size(); i < n; ++i) {
final Type argument = typeArguments.get(i);
final Type otherArgument = otherArguments.get(i);
final Type<?> argument = typeArguments.get(i);
final Type<?> otherArgument = otherArguments.get(i);

if (!Comparer.equals(argument, otherArgument)) {
return false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
Expand Down Expand Up @@ -169,4 +170,47 @@ public void testGetUnderlyingType() throws Throwable {
assertSame(gd, uea);
assertSame(gd, uia);
}

@Test
public void testBoundGenericFields() {
@SuppressWarnings("unused")
class GenericTestObject<T> {
public List<T> items;

public T sum(final List<T> values) {
throw new UnsupportedOperationException();
}
}

final class TestObject extends GenericTestObject<Double> {
}

final FieldInfo items = Type.of(TestObject.class).getField("items");

assertEquals(Types.List.makeGenericType(Types.Double),
items.getFieldType());
}

@Test
public void genericParameterArrayTypesDoNotCollideInTypeCache() {
class MyClass {
public <T> Iterable<T> enumerate(final T[] items) {
return Arrays.asList(items);
}
}

class MyOtherClass {
public Object getFirstOrNull(final Object... values) {
return values.length > 0 ? values[0] : null;
}
}

final Type<MyClass> c1 = Type.of(MyClass.class); // Load class with method having T[] parameter
c1.getMethods(); // Load methods of class with method having T[] parameter
final Type<MyOtherClass> c2 = Type.of(MyOtherClass.class); // Load class with method having Object[] parameter
final Type<Object[]> objectArrayType = Types.Object.makeArrayType(); // Prepare Object[] type for comparison
final MethodInfo method = c2.getMethod("getFirstOrNull", objectArrayType); // Load specific method having Object[] parameter
final Type<?> methodParameterType = method.getParameters().getParameterTypes().get(0); // Retrieve method parameter type (expected to be Object[])
assertEquals(objectArrayType, methodParameterType); // The method parameter type should match the expected Object[], but will be T[]
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -363,6 +363,11 @@ public void testTypeBuilderArrayTypes() throws Throwable {
final Type<?> createdTypeVariable = createdType.getGenericTypeParameters().get(0);
final Type<?> createdTypeVariableArray = createdTypeVariable.makeArrayType();

assertNotSame(createdType, type);
assertNotSame(createdArrayType, arrayType);
assertNotSame(createdTypeVariable, typeVariable);
assertNotSame(createdTypeVariableArray, typeVariableArray);

assertTrue(type.isEquivalentTo(createdType));
assertTrue(createdType.isEquivalentTo(type));
assertTrue(arrayType.isEquivalentTo(createdArrayType));
Expand Down