/* * 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 static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertSame; import com.facebook.buck.jvm.java.testutil.compiler.CompilerTreeApiParameterized; import java.io.IOException; import java.util.List; import javax.lang.model.element.Element; import javax.lang.model.element.ElementKind; import javax.lang.model.element.TypeElement; import javax.lang.model.element.TypeParameterElement; import javax.lang.model.type.TypeMirror; import javax.lang.model.util.SimpleElementVisitor8; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(CompilerTreeApiParameterized.class) public class TreeBackedTypeParameterElementTest extends CompilerTreeApiParameterizedTest { @Test public void testGetSimpleName() throws IOException { compile("class Foo<T> { }"); TypeElement fooElement = elements.getTypeElement("Foo"); final List<? extends TypeParameterElement> typeParameters = fooElement.getTypeParameters(); assertSame(1, typeParameters.size()); TypeParameterElement typeParam = typeParameters.get(0); assertNameEquals("T", typeParam.getSimpleName()); } @Test public void testGetSimpleNameWithBoundedParameter() throws IOException { compile("class Foo<T extends java.lang.Runnable> { }"); TypeElement fooElement = elements.getTypeElement("Foo"); final List<? extends TypeParameterElement> typeParameters = fooElement.getTypeParameters(); assertSame(1, typeParameters.size()); TypeParameterElement typeParam = typeParameters.get(0); assertNameEquals("T", typeParam.getSimpleName()); } @Test public void testGetKind() throws IOException { compile("class Foo<T> { }"); assertSame( ElementKind.TYPE_PARAMETER, elements.getTypeElement("Foo").getTypeParameters().get(0).getKind()); } @Test public void testAccept() throws IOException { compile("class Foo<T> { }"); TypeParameterElement expectedTypeParameter = elements.getTypeElement("Foo").getTypeParameters().get(0); Object expectedResult = new Object(); Object actualResult = expectedTypeParameter.accept( new SimpleElementVisitor8<Object, Object>() { @Override protected Object defaultAction(Element e, Object o) { return null; } @Override public Object visitTypeParameter(TypeParameterElement actualTypeParameter, Object o) { assertSame(expectedTypeParameter, actualTypeParameter); return o; } }, expectedResult); assertSame(expectedResult, actualResult); } @Test public void testToString() throws IOException { compile("class Foo<T extends java.lang.Runnable> { }"); TypeParameterElement typeParam = elements.getTypeElement("Foo").getTypeParameters().get(0); assertEquals("T", typeParam.toString()); } @Test public void testGetGenericElement() throws IOException { compile("class Foo<T> { }"); TypeElement fooElement = elements.getTypeElement("Foo"); final List<? extends TypeParameterElement> typeParameters = fooElement.getTypeParameters(); assertSame(1, typeParameters.size()); TypeParameterElement typeParam = typeParameters.get(0); assertSame(fooElement, typeParam.getGenericElement()); } @Test public void testGetEnclosingElement() throws IOException { compile("class Foo<T> { }"); TypeElement fooElement = elements.getTypeElement("Foo"); final List<? extends TypeParameterElement> typeParameters = fooElement.getTypeParameters(); assertSame(1, typeParameters.size()); TypeParameterElement typeParam = typeParameters.get(0); assertSame(fooElement, typeParam.getGenericElement()); } @Test public void testUnboundedTypeParameter() throws IOException { compile("class Foo<T> { }"); TypeElement fooElement = elements.getTypeElement("Foo"); TypeMirror objectType = elements.getTypeElement("java.lang.Object").asType(); List<? extends TypeParameterElement> typeParameters = fooElement.getTypeParameters(); assertSame(1, typeParameters.size()); TypeParameterElement typeParam = typeParameters.get(0); List<? extends TypeMirror> bounds = typeParam.getBounds(); assertSame(1, bounds.size()); assertSameType(objectType, bounds.get(0)); } @Test public void testMultipleTypeParameters() throws IOException { compile("class Foo<T, U extends java.lang.CharSequence> { }"); TypeMirror objectType = elements.getTypeElement("java.lang.Object").asType(); TypeMirror charSequenceType = elements.getTypeElement("java.lang.CharSequence").asType(); TypeElement fooElement = elements.getTypeElement("Foo"); List<? extends TypeParameterElement> typeParameters = fooElement.getTypeParameters(); assertSame(2, typeParameters.size()); TypeParameterElement tParam = typeParameters.get(0); List<? extends TypeMirror> bounds = tParam.getBounds(); assertSame(1, bounds.size()); assertSameType(objectType, bounds.get(0)); TypeParameterElement uParam = typeParameters.get(1); bounds = uParam.getBounds(); assertSame(1, bounds.size()); assertSameType(charSequenceType, bounds.get(0)); } @Test public void testSuperclassBoundedTypeParameter() throws IOException { compile("class Foo<T extends java.lang.CharSequence> { }"); TypeMirror charSequenceType = elements.getTypeElement("java.lang.CharSequence").asType(); TypeElement fooElement = elements.getTypeElement("Foo"); List<? extends TypeParameterElement> typeParameters = fooElement.getTypeParameters(); assertSame(1, typeParameters.size()); TypeParameterElement typeParam = typeParameters.get(0); List<? extends TypeMirror> bounds = typeParam.getBounds(); assertSame(1, bounds.size()); assertSameType(charSequenceType, bounds.get(0)); } @Test public void testTypeParameterBoundedTypeParameter() throws IOException { compile("class Foo<T, U extends T> { }"); TypeElement fooElement = elements.getTypeElement("Foo"); TypeParameterElement uElement = fooElement.getTypeParameters().get(1); TypeMirror tType = fooElement.getTypeParameters().get(0).asType(); assertSameType(tType, uElement.getBounds().get(0)); } @Test public void testForwardReferenceTypeParameterBoundedTypeParameter() throws IOException { compile("class Foo<T extends U, U> { }"); TypeElement fooElement = elements.getTypeElement("Foo"); TypeParameterElement tElement = fooElement.getTypeParameters().get(0); TypeMirror uType = fooElement.getTypeParameters().get(1).asType(); assertSameType(uType, tElement.getBounds().get(0)); } @Test public void testMultipleBoundedTypeParameter() throws IOException { compile( "class Foo<T extends java.lang.CharSequence & java.lang.Runnable & java.io.Closeable> { }"); TypeMirror charSequenceType = elements.getTypeElement("java.lang.CharSequence").asType(); TypeMirror runnableType = elements.getTypeElement("java.lang.Runnable").asType(); TypeMirror closeableType = elements.getTypeElement("java.io.Closeable").asType(); TypeElement fooElement = elements.getTypeElement("Foo"); List<? extends TypeParameterElement> typeParameters = fooElement.getTypeParameters(); assertSame(1, typeParameters.size()); TypeParameterElement typeParam = typeParameters.get(0); List<? extends TypeMirror> bounds = typeParam.getBounds(); assertSame(3, bounds.size()); assertSameType(charSequenceType, bounds.get(0)); assertSameType(runnableType, bounds.get(1)); assertSameType(closeableType, bounds.get(2)); } @Test public void testEnclosingElementDoesNotEnclose() throws IOException { compile("class Foo<T> { }"); TypeElement fooElement = elements.getTypeElement("Foo"); TypeParameterElement tElement = fooElement.getTypeParameters().get(0); assertSame(fooElement, tElement.getEnclosingElement()); assertFalse(fooElement.getEnclosedElements().contains(tElement)); } }