/*
* 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.freebuilder.processor;
import com.google.common.collect.ImmutableList;
import org.inferred.freebuilder.processor.util.NameImpl;
import org.inferred.freebuilder.processor.util.NoTypes;
import org.inferred.freebuilder.processor.util.PackageElementImpl;
import org.inferred.freebuilder.processor.util.Partial;
import org.inferred.freebuilder.processor.util.ValueType;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.ElementVisitor;
import javax.lang.model.element.ExecutableElement;
import javax.lang.model.element.Name;
import javax.lang.model.element.NestingKind;
import javax.lang.model.element.PackageElement;
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.TypeParameterElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.DeclaredType;
import javax.lang.model.type.TypeKind;
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.TypeVisitor;
import javax.lang.model.util.AbstractElementVisitor6;
abstract class GenericTypeElementImpl extends ValueType
implements javax.lang.model.element.TypeElement {
public static GenericTypeElementImpl newTopLevelGenericType(String qualifiedName) {
String pkg = qualifiedName.substring(0, qualifiedName.lastIndexOf('.'));
String simpleName = qualifiedName.substring(qualifiedName.lastIndexOf('.') + 1);
PackageElement enclosingElement = PackageElementImpl.create(pkg);
return Partial.of(GenericTypeElementImpl.class, enclosingElement, NoTypes.NONE, simpleName);
}
private final Element enclosingElement;
private final TypeMirror enclosingType;
private final String simpleName;
GenericTypeElementImpl(Element enclosingElement, TypeMirror enclosingType, String simpleName) {
this.enclosingElement = enclosingElement;
this.enclosingType = enclosingType;
this.simpleName = simpleName;
}
@Override
protected void addFields(FieldReceiver fields) {
fields.add("enclosingElement", enclosingElement);
fields.add("enclosingType", enclosingType);
fields.add("simpleName", simpleName);
}
public GenericTypeMirrorImpl newMirror(TypeMirror... typeArguments) {
return Partial.of(GenericTypeMirrorImpl.class, this, ImmutableList.copyOf(typeArguments));
}
@Override
public ElementKind getKind() {
return ElementKind.CLASS;
}
@Override
public <R, P> R accept(ElementVisitor<R, P> v, P p) {
return v.visitType(this, p);
}
@Override
public NestingKind getNestingKind() {
return (enclosingElement.getKind() == ElementKind.PACKAGE)
? NestingKind.TOP_LEVEL : NestingKind.MEMBER;
}
@Override
public Name getQualifiedName() {
return new NameImpl(GET_QUALIFIED_NAME.visit(enclosingElement) + "." + simpleName);
}
@Override
public Name getSimpleName() {
return new NameImpl(simpleName);
}
@Override
public Element getEnclosingElement() {
return enclosingElement;
}
abstract class GenericTypeMirrorImpl extends ValueType implements DeclaredType {
private final ImmutableList<TypeMirror> typeArguments;
GenericTypeMirrorImpl(ImmutableList<TypeMirror> typeArguments) {
this.typeArguments = typeArguments;
}
@Override
protected void addFields(FieldReceiver fields) {
fields.add("GenericTypeElementImpl.this", GenericTypeElementImpl.this);
fields.add("typeArguments", typeArguments);
}
@Override
public TypeKind getKind() {
return TypeKind.DECLARED;
}
@Override
public <R, P> R accept(TypeVisitor<R, P> v, P p) {
return v.visitDeclared(this, p);
}
@Override
public GenericTypeElementImpl asElement() {
return GenericTypeElementImpl.this;
}
@Override
public TypeMirror getEnclosingType() {
return enclosingType;
}
@Override
public ImmutableList<TypeMirror> getTypeArguments() {
return typeArguments;
}
}
private static final AbstractElementVisitor6<Name, ?> GET_QUALIFIED_NAME =
new AbstractElementVisitor6<Name, Void>() {
@Override
public Name visitPackage(PackageElement e, Void p) {
return e.getQualifiedName();
}
@Override
public Name visitType(TypeElement e, Void p) {
return e.getQualifiedName();
}
@Override
public Name visitVariable(VariableElement e, Void p) {
throw new IllegalArgumentException();
}
@Override
public Name visitExecutable(ExecutableElement e, Void p) {
throw new IllegalArgumentException();
}
@Override
public Name visitTypeParameter(TypeParameterElement e, Void p) {
throw new IllegalArgumentException();
}
};
}