@@ -16,6 +16,22 @@ public final class ArrayTypeView extends AbstractTypeView<GenericArrayType> { | |||
super(type); | |||
} | |||
public static ArrayTypeView build(TypeView componentType) { | |||
return build(componentType.unwrap()); | |||
} | |||
public static ArrayTypeView build(Type componentType) { | |||
return new ArrayTypeView(buildUnwrapped(componentType)); | |||
} | |||
public static GenericArrayType buildUnwrapped(TypeView componentType) { | |||
return buildUnwrapped(componentType.unwrap()); | |||
} | |||
public static GenericArrayType buildUnwrapped(Type componentType) { | |||
return new SyntheticGenericArrayType(componentType); | |||
} | |||
/** | |||
* Creates view over provided type. | |||
* | |||
@@ -6,16 +6,21 @@ import java.lang.reflect.TypeVariable; | |||
import java.util.Iterator; | |||
import java.util.List; | |||
import java.util.Optional; | |||
import java.util.stream.IntStream; | |||
import java.util.stream.Stream; | |||
import javax.annotation.Nonnull; | |||
import javax.annotation.Nullable; | |||
import com.google.common.collect.ImmutableList; | |||
import com.google.common.collect.ImmutableMap; | |||
import com.google.errorprone.annotations.CanIgnoreReturnValue; | |||
import kotlin.annotations.jvm.ReadOnly; | |||
import org.checkerframework.checker.nullness.qual.EnsuresNonNull; | |||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull; | |||
import org.checkerframework.checker.nullness.qual.NonNull; | |||
import org.checkerframework.checker.nullness.qual.Nullable; | |||
import static com.google.common.base.Preconditions.checkArgument; | |||
import static com.google.common.base.Preconditions.checkState; | |||
/** | |||
@@ -40,6 +45,10 @@ public final class ParameterizedTypeView extends AbstractTypeView<ParameterizedT | |||
return new ParameterizedTypeView(parameterized); | |||
} | |||
public static Builder builder(Class<?> baseType) { | |||
return new Builder(baseType); | |||
} | |||
@Override | |||
public Class<?> erasure() { | |||
return (Class<?>) type.getRawType(); | |||
@@ -343,4 +352,52 @@ public final class ParameterizedTypeView extends AbstractTypeView<ParameterizedT | |||
} | |||
return builder.build(); | |||
} | |||
public static final class Builder { | |||
private final Class<?> baseType; | |||
@Nullable | |||
private Type ownerType; | |||
private Type[] typeArguments; | |||
Builder(Class<?> baseType) { | |||
this.baseType = baseType; | |||
typeArguments = baseType.getTypeParameters().clone(); | |||
} | |||
@CanIgnoreReturnValue | |||
public Builder withOwner(Type newOwnerType) { | |||
ownerType = newOwnerType; | |||
return this; | |||
} | |||
@CanIgnoreReturnValue | |||
public Builder withSubstitution(String parameterName, Type substitute) { | |||
TypeVariable<? extends Class<?>>[] typeParameters = baseType.getTypeParameters(); | |||
int parameterNumber = IntStream.range(0, typeParameters.length) | |||
.filter(i -> typeParameters[i].getName().equals(parameterName)) | |||
.findFirst() | |||
.orElseThrow(() -> new IllegalArgumentException("No parameter with name " + parameterName)); | |||
return withSubstitution(parameterNumber, substitute); | |||
} | |||
@CanIgnoreReturnValue | |||
public Builder withSubstitution(int parameterNumber, Type substitute) { | |||
checkArgument(parameterNumber > 0, "Parameter number must be non-negative"); | |||
checkArgument(parameterNumber < typeArguments.length, "Type %s has no parameter %s", baseType, parameterNumber); | |||
typeArguments[parameterNumber] = substitute; | |||
return this; | |||
} | |||
public ParameterizedTypeView build() { | |||
ParameterizedType parameterizedType = buildUnwrapped(); | |||
return new ParameterizedTypeView(parameterizedType); | |||
} | |||
@Nonnull | |||
public ParameterizedType buildUnwrapped() { | |||
return new SyntheticParameterizedType(baseType, ownerType, typeArguments); | |||
} | |||
} | |||
} |
@@ -4,9 +4,13 @@ import java.lang.reflect.GenericDeclaration; | |||
import java.lang.reflect.Type; | |||
import java.lang.reflect.TypeVariable; | |||
import java.util.Collection; | |||
import java.util.HashSet; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import java.util.stream.Stream; | |||
import com.google.errorprone.annotations.CanIgnoreReturnValue; | |||
/** | |||
* {@link TypeView} that handles {@link TypeVariable}. | |||
* | |||
@@ -28,6 +32,10 @@ public final class TypeVariableView<D extends GenericDeclaration> extends Abstra | |||
return new TypeVariableView<>(variable); | |||
} | |||
public static <D extends GenericDeclaration> Builder<D> builder(String name, D declaration) { | |||
return new Builder(name, declaration); | |||
} | |||
@Override | |||
public Class<?> erasure() { | |||
Type[] bounds = type.getBounds(); | |||
@@ -191,4 +199,33 @@ public final class TypeVariableView<D extends GenericDeclaration> extends Abstra | |||
return Stream.of(type.getBounds()) | |||
.map(TypeView::of); | |||
} | |||
public static final class Builder<D extends GenericDeclaration> { | |||
private final D declaration; | |||
private final String name; | |||
private final Set<Type> bounds = new HashSet<>(); | |||
Builder(String name, D declaration) { | |||
this.name = name; | |||
this.declaration = declaration; | |||
} | |||
@CanIgnoreReturnValue | |||
public Builder withUpperBound(Type addedBound) { | |||
bounds.add(addedBound); | |||
return this; | |||
} | |||
public TypeVariableView<D> build() { | |||
return new TypeVariableView<>(buildUnwrapped()); | |||
} | |||
public TypeVariable<D> buildUnwrapped() { | |||
Type[] finalBounds = bounds.toArray(new Type[0]); | |||
return new SyntheticTypeVariable<>(name, declaration, finalBounds); | |||
} | |||
} | |||
} |
@@ -6,10 +6,13 @@ import java.lang.reflect.WildcardType; | |||
import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.Collection; | |||
import java.util.HashSet; | |||
import java.util.List; | |||
import java.util.Set; | |||
import java.util.stream.Collectors; | |||
import java.util.stream.Stream; | |||
import com.google.errorprone.annotations.CanIgnoreReturnValue; | |||
import kotlin.annotations.jvm.ReadOnly; | |||
/** | |||
@@ -30,6 +33,10 @@ public final class WildcardTypeView extends AbstractTypeView<WildcardType> { | |||
return new WildcardTypeView(wildcard); | |||
} | |||
public static Builder builder() { | |||
return new Builder(); | |||
} | |||
@Override | |||
public Class<?> erasure() { | |||
Type[] bounds = type.getUpperBounds(); | |||
@@ -237,4 +244,34 @@ public final class WildcardTypeView extends AbstractTypeView<WildcardType> { | |||
private static Type[] removeObjectClass(Type[] upperBounds) { | |||
return Stream.of(upperBounds).filter(bound -> !Object.class.equals(bound)).toArray(Type[]::new); | |||
} | |||
public static final class Builder { | |||
private final Set<Type> lowerBounds = new HashSet<>(); | |||
private final Set<Type> upperBounds = new HashSet<>(); | |||
Builder() { | |||
} | |||
@CanIgnoreReturnValue | |||
public Builder withLowerBound(Type addedBound) { | |||
lowerBounds.add(addedBound); | |||
return this; | |||
} | |||
@CanIgnoreReturnValue | |||
public Builder withUpperBound(Type addedBound) { | |||
upperBounds.add(addedBound); | |||
return this; | |||
} | |||
public WildcardTypeView build() { | |||
return new WildcardTypeView(buildUnwrapped()); | |||
} | |||
public WildcardType buildUnwrapped() { | |||
Type[] finalLowerBounds = lowerBounds.toArray(new Type[0]); | |||
Type[] finalUpperBounds = upperBounds.toArray(new Type[0]); | |||
return new SyntheticWildcardType(finalLowerBounds, finalUpperBounds); | |||
} | |||
} | |||
} |