/*
* 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.google.devtools.j2objc.types;
import com.google.devtools.j2objc.GenerationTest;
import com.google.devtools.j2objc.ast.AbstractTypeDeclaration;
import com.google.devtools.j2objc.ast.BodyDeclaration;
import com.google.devtools.j2objc.ast.CompilationUnit;
import com.google.devtools.j2objc.ast.MethodDeclaration;
import com.google.devtools.j2objc.ast.ReturnStatement;
import com.google.devtools.j2objc.util.ElementUtil;
import com.google.devtools.j2objc.util.TypeUtil;
import java.io.IOException;
import javax.lang.model.type.TypeMirror;
/**
* Unit tests for the Java 8 compound types.
*
* @author Tom Ball
*/
public class CompoundTypeTest extends GenerationTest {
// Test TypeUtil.isIntersection(TypeMirror).
public void testIsCompound() throws Exception {
String source = "interface Test<T> extends java.util.Comparator<T> {"
+ " default Test<T> thenTesting(Test<? super T> other) { "
+ " return (Test<T> & java.io.Serializable) (c1, c2) -> { "
+ " int res = compare(c1, c2); "
+ " return (res != 0) ? res : other.compare(c1, c2); }; }}";
CompilationUnit unit = compileType("Test", source);
AbstractTypeDeclaration decl = unit.getTypes().get(0);
int methodsFound = 0;
for (BodyDeclaration body : decl.getBodyDeclarations()) {
if (body instanceof MethodDeclaration) {
MethodDeclaration method = (MethodDeclaration) body;
if (ElementUtil.getName(method.getExecutableElement()).equals("thenTesting")) {
// Verify a normal type isn't marked as compound.
TypeMirror returnType = method.getReturnTypeMirror();
assertFalse(TypeUtil.isIntersection(returnType));
// The method's return type isn't compound, but the cast expression in
// its return statement is.
ReturnStatement stmt = (ReturnStatement) method.getBody().getStatements().get(0);
assertTrue(TypeUtil.isIntersection(stmt.getExpression().getTypeMirror()));
methodsFound++;
}
}
}
assertEquals(1, methodsFound);
}
// Test NameTable.getObjCType(TypeMirror).
public void testCompoundTypeFullName() throws IOException {
String source = "package foo.bar; interface Test<T> extends java.util.Comparator<T> {"
+ " default Test<T> thenTesting(Test<? super T> other) { "
+ " return (Test<T> & java.io.Serializable) (c1, c2) -> { "
+ " int res = compare(c1, c2); "
+ " return (res != 0) ? res : other.compare(c1, c2); }; }}";
CompilationUnit unit = compileType("Test", source);
AbstractTypeDeclaration decl = unit.getTypes().get(0);
for (BodyDeclaration body : decl.getBodyDeclarations()) {
if (body instanceof MethodDeclaration) {
MethodDeclaration method = (MethodDeclaration) body;
if (ElementUtil.getName(method.getExecutableElement()).equals("thenTesting")) {
// The method's return type isn't compound, but the cast expression in
// its return statement is.
ReturnStatement stmt = (ReturnStatement) method.getBody().getStatements().get(0);
TypeMirror mirror = stmt.getExpression().getTypeMirror();
String typeName = unit.getEnv().nameTable().getObjCType(mirror);
assertEquals("id<FooBarTest, JavaIoSerializable>", typeName);
return;
}
}
}
fail("thenTesting method not found");
}
// Verify that an include for ".h" isn't generated with a compound type.
public void testCompoundTypeImport() throws IOException {
String source = "interface Test<T> extends java.util.Comparator<T> {"
+ " default Test<T> thenTesting(Test<? super T> other) { "
+ " return (Test<T> & java.io.Serializable) (c1, c2) -> { "
+ " int res = compare(c1, c2); "
+ " return (res != 0) ? res : other.compare(c1, c2); }; }}";
String translation = translateSourceFile(source, "Test", "Test.m");
assertNotInTranslation(translation, "#include \".h\"");
assertTranslation(translation, "#include \"Test.h\"");
}
}