/*
* Copyright 2016-present Facebook, Inc.
*
* 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 com.facebook.buck.jvm.java.abi.source;
import com.facebook.buck.util.liteinfersupport.Nullable;
import com.facebook.buck.util.liteinfersupport.Preconditions;
import com.sun.source.tree.ClassTree;
import com.sun.source.tree.ModifiersTree;
import com.sun.source.util.TreePath;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
import javax.lang.model.element.ElementVisitor;
import javax.lang.model.element.Name;
import javax.lang.model.element.NestingKind;
import javax.lang.model.element.TypeElement;
import javax.lang.model.type.TypeMirror;
/**
* An implementation of {@link TypeElement} that uses only the information available from a {@link
* ClassTree}. This results in an incomplete implementation; see documentation for individual
* methods and {@link com.facebook.buck.jvm.java.abi.source} for more information.
*/
class TreeBackedTypeElement extends TreeBackedParameterizable implements TypeElement {
private final TypeElement underlyingElement;
@Nullable private final ClassTree tree;
@Nullable private StandaloneDeclaredType typeMirror;
@Nullable private TypeMirror superclass;
@Nullable private List<? extends TypeMirror> interfaces;
TreeBackedTypeElement(
TypeElement underlyingElement,
TreeBackedElement enclosingElement,
@Nullable TreePath path,
TreeBackedElementResolver resolver) {
super(underlyingElement, enclosingElement, path, resolver);
this.underlyingElement = underlyingElement;
tree = path != null ? (ClassTree) path.getLeaf() : null;
enclosingElement.addEnclosedElement(this);
}
@Override
public TreeBackedElement getEnclosingElement() {
return Preconditions.checkNotNull(super.getEnclosingElement());
}
@Override
public NestingKind getNestingKind() {
return underlyingElement.getNestingKind();
}
@Override
public Name getQualifiedName() {
return underlyingElement.getQualifiedName();
}
@Override
public StandaloneDeclaredType asType() {
if (typeMirror == null) {
typeMirror = getResolver().createType(this);
}
return typeMirror;
}
@Override
@Nullable
protected ModifiersTree getModifiersTree() {
return tree != null ? tree.getModifiers() : null;
}
@Override
public TypeMirror getSuperclass() {
if (superclass == null) {
superclass = getResolver().getCanonicalType(underlyingElement.getSuperclass());
}
return superclass;
}
@Override
public List<? extends TypeMirror> getInterfaces() {
if (interfaces == null) {
interfaces =
Collections.unmodifiableList(
underlyingElement
.getInterfaces()
.stream()
.map(getResolver()::getCanonicalType)
.collect(Collectors.toList()));
}
return interfaces;
}
@Override
public <R, P> R accept(ElementVisitor<R, P> v, P p) {
return v.visitType(this, p);
}
}