org.inferred.internal.testing.unit.GenericElementParameter Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of source-testing Show documentation
Show all versions of source-testing Show documentation
A Java library for testing code generators
The newest version!
/*
* Copyright 2015 Google Inc. All rights reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.inferred.internal.testing.unit;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Iterables.getOnlyElement;
import static org.inferred.internal.testing.unit.ClassTypeImpl.newTopLevelClass;
import static org.inferred.internal.testing.unit.NullTypeImpl.NULL;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import org.inferred.internal.testing.Partial;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.lang.model.element.AnnotationMirror;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ElementVisitor;
import javax.lang.model.element.Modifier;
import javax.lang.model.element.Name;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVariable;
import javax.lang.model.type.TypeVisitor;
/**
* Fake implementation of a formal type parameter of a {@link GenericElement}.
*/
public abstract class GenericElementParameter implements TypeParameterElement {
/**
* Builder of {@link GenericElementParameter} instances.
*/
public static class Builder {
private final String simpleName;
private final List bounds = new ArrayList<>();
private final AtomicReference element = new AtomicReference<>();
Builder(String simpleName) {
this.simpleName = simpleName;
}
public Builder addBound(TypeMirror bound) {
checkState(element.get() == null,
"Cannot modify a %s after calling build()", Builder.class.getName());
bounds.add(bound);
return this;
}
public TypeVariableImpl asType() {
return Partial.of(TypeVariableImpl.class, element);
}
GenericElementParameter build(GenericElement genericElement) {
GenericElementParameter impl =
Partial.of(GenericElementParameter.class, genericElement, simpleName, bounds);
boolean notYetSet = element.compareAndSet(null, impl);
checkState(notYetSet, "Cannot call build() twice on a %s", Builder.class.getName());
return impl;
}
}
private final GenericElement genericElement;
private final String simpleName;
private final ImmutableList bounds;
GenericElementParameter(
GenericElement genericElement, String simpleName, Iterable extends TypeMirror> bounds) {
this.genericElement = genericElement;
this.simpleName = simpleName;
this.bounds = ImmutableList.copyOf(bounds);
}
@Override
public TypeVariableImpl asType() {
return Partial.of(TypeVariableImpl.class, new AtomicReference<>(this));
}
@Override
public ElementKind getKind() {
return ElementKind.TYPE_PARAMETER;
}
@Override
public List extends AnnotationMirror> getAnnotationMirrors() {
return ImmutableList.of();
}
@Override
public A getAnnotation(Class annotationType) {
return null;
}
@Override
public Set getModifiers() {
return ImmutableSet.of();
}
@Override
public Name getSimpleName() {
return new NameImpl(simpleName);
}
@Override
public List extends Element> getEnclosedElements() {
return ImmutableList.of();
}
@Override
public R accept(ElementVisitor v, P p) {
return v.visitTypeParameter(this, p);
}
@Override
public GenericElement getGenericElement() {
return genericElement;
}
@Override
public List extends TypeMirror> getBounds() {
return bounds;
}
@Override
public GenericElement getEnclosingElement() {
return genericElement;
}
@Override
public String toString() {
return simpleName;
}
/**
* Fake implementation of a type variable declared by a {@link GenericElement}.
*/
public abstract static class TypeVariableImpl implements TypeVariable {
private final AtomicReference element;
TypeVariableImpl(AtomicReference element) {
this.element = element;
}
@Override
public TypeKind getKind() {
return TypeKind.TYPEVAR;
}
@Override
public R accept(TypeVisitor v, P p) {
return v.visitTypeVariable(this, p);
}
@Override
public GenericElementParameter asElement() {
GenericElementParameter impl = getImpl("asElement()");
return impl;
}
@Override
public TypeMirror getUpperBound() {
GenericElementParameter impl = getImpl("getUpperBound()");
switch (impl.bounds.size()) {
case 0:
return newTopLevelClass("java.lang.Object");
case 1:
return getOnlyElement(impl.bounds);
default:
throw new UnsupportedOperationException();
}
}
@Override
public TypeMirror getLowerBound() {
return NULL;
}
@Override
public String toString() {
return getImpl("toString()").simpleName;
}
private GenericElementParameter getImpl(String calledMethod) {
GenericElementParameter impl = element.get();
checkState(impl != null,
"Cannot call %s on a TypeVariable returned from a %s before it is built",
calledMethod,
GenericElementParameter.Builder.class.getName());
return impl;
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy