public void testMethodSignatures() throws IOException { CompilationUnit unit = translateType( "A", "class A<X,Y> { " + "void a() {} " + "int b(boolean z) { return 0; } " + "void c(int i) throws IndexOutOfBoundsException {} " + "X d() { return null; } " + "void e(X x, Y y) {} " + "<T extends Throwable> void rethrow(Throwable t) {}" + "}"); IMethodBinding[] methods = unit.getTypes().get(0).getTypeBinding().getDeclaredMethods(); assertEquals(7, methods.length); // methods[0] is the default constructor. // Verify a, b and c don't return a signature, since they aren't generic types. assertNull(SignatureGenerator.createMethodTypeSignature(methods[1])); assertNull(SignatureGenerator.createMethodTypeSignature(methods[2])); assertNull(SignatureGenerator.createMethodTypeSignature(methods[3])); assertEquals("()TX;", SignatureGenerator.createMethodTypeSignature(methods[4])); assertEquals("(TX;TY;)V", SignatureGenerator.createMethodTypeSignature(methods[5])); assertEquals( "<T:Ljava/lang/Throwable;>(Ljava/lang/Throwable;)V", SignatureGenerator.createMethodTypeSignature(methods[6])); }
public void testClassSignatures() throws IOException { CompilationUnit unit = translateType( "A", "import java.lang.ref.*; import java.util.concurrent.*; " + "class A {} " + "class B<X> {} " + "class C<X,Y,Z> {} " + "abstract class D extends java.util.AbstractList<String> {} " + "class E<C extends Comparable<? super C>> {}" + "class F extends WeakReference<ForkJoinTask<?>> { " + " F(ForkJoinTask<?> task, Throwable ex, F next) { super(task, null); }}"); List<AbstractTypeDeclaration> decls = unit.getTypes(); assertEquals(6, decls.size()); // Verify A doesn't return a signature, since it isn't a generic type. assertNull(SignatureGenerator.createClassSignature(decls.get(0).getTypeBinding())); assertEquals( "<X:Ljava/lang/Object;>Ljava/lang/Object;", SignatureGenerator.createClassSignature(decls.get(1).getTypeBinding())); assertEquals( "<X:Ljava/lang/Object;Y:Ljava/lang/Object;Z:Ljava/lang/Object;>Ljava/lang/Object;", SignatureGenerator.createClassSignature(decls.get(2).getTypeBinding())); assertEquals( "Ljava/util/AbstractList<Ljava/lang/String;>;", SignatureGenerator.createClassSignature(decls.get(3).getTypeBinding())); assertEquals( "<C::Ljava/lang/Comparable<-TC;>;>Ljava/lang/Object;", SignatureGenerator.createClassSignature(decls.get(4).getTypeBinding())); assertEquals( "Ljava/lang/ref/WeakReference<Ljava/util/concurrent/ForkJoinTask<*>;>;", SignatureGenerator.createClassSignature(decls.get(5).getTypeBinding())); }
public void testGenericInterface() throws IOException { CompilationUnit unit = translateType("A", "interface A<E> extends java.util.Collection<E> {}"); List<AbstractTypeDeclaration> decls = unit.getTypes(); assertEquals(1, decls.size()); assertEquals( "<E:Ljava/lang/Object;>Ljava/lang/Object;Ljava/util/Collection<TE;>;", SignatureGenerator.createClassSignature(decls.get(0).getTypeBinding())); }
public void testMultipleBounds() throws IOException { CompilationUnit unit = translateType("A", "class A <T extends Number & java.io.Serializable >{}"); List<AbstractTypeDeclaration> decls = unit.getTypes(); assertEquals(1, decls.size()); assertEquals( "<T:Ljava/lang/Number;:Ljava/io/Serializable;>Ljava/lang/Object;", SignatureGenerator.createClassSignature(decls.get(0).getTypeBinding())); }
public void testJniSignatures() throws IOException { CompilationUnit unit = translateType( "D", "package foo.bar; class D {" + "native void foo(int i, float f, String s);" + "native void a_b$c();" + "native void 你好世界();" + "native void bar();" + "native void bar(String s);" + "native void bar(boolean b, String s);" + "native void bar(String[] s); " + "static class 测试 { native void mumble(); }}"); List<AbstractTypeDeclaration> decls = unit.getTypes(); assertEquals(2, decls.size()); IMethodBinding[] methods = decls.get(0).getTypeBinding().getDeclaredMethods(); assertEquals(8, methods.length); // methods[0] is the default constructor. // Expected JNI signatures were copied from javah output. // Verify no parameters, since foo isn't overloaded. assertEquals("Java_foo_bar_D_foo", SignatureGenerator.createJniFunctionSignature(methods[6])); // Verify underscores and dollar signs in names are mangled. assertEquals( "Java_foo_bar_D_a_1b_00024c", SignatureGenerator.createJniFunctionSignature(methods[1])); // Verify Unicode characters are mangled. assertEquals( "Java_foo_bar_D__04f60_0597d_04e16_0754c", SignatureGenerator.createJniFunctionSignature(methods[7])); // Verify overloaded methods have parameter suffixes. assertEquals("Java_foo_bar_D_bar__", SignatureGenerator.createJniFunctionSignature(methods[2])); assertEquals( "Java_foo_bar_D_bar__Ljava_lang_String_2", SignatureGenerator.createJniFunctionSignature(methods[3])); assertEquals( "Java_foo_bar_D_bar__ZLjava_lang_String_2", SignatureGenerator.createJniFunctionSignature(methods[4])); assertEquals( "Java_foo_bar_D_bar___3Ljava_lang_String_2", SignatureGenerator.createJniFunctionSignature(methods[5])); // Check Unicode class name mangling. methods = decls.get(1).getTypeBinding().getDeclaredMethods(); assertEquals(2, methods.length); assertEquals( "Java_foo_bar_D_00024_06d4b_08bd5_mumble", SignatureGenerator.createJniFunctionSignature(methods[1])); }
@Override public void endVisit(CompilationUnit unit) { for (SuperMethodBindingPair superMethod : superMethods) { String funcName = getSuperFunctionName(superMethod); String signature = getSuperFunctionSignature(superMethod.method); // Add declarations for the function pointers to call. unit.getNativeBlocks() .add( NativeDeclaration.newOuterDeclaration( null, "static " + UnicodeUtils.format(signature, funcName) + ";")); // Look up the implementations in the static initialization. AbstractTypeDeclaration typeNode = typeMap.get(superMethod.type.getTypeDeclaration()); assert typeNode != null : "Type is expected to be in this compilation unit"; String superclassName = nameTable.getFullName(superMethod.type.getSuperclass()); typeNode .getClassInitStatements() .add( 0, new NativeStatement( UnicodeUtils.format( "%s = (%s)[%s instanceMethodForSelector:@selector(%s)];", funcName, UnicodeUtils.format(signature, ""), superclassName, nameTable.getMethodSelector(superMethod.method)))); } }
public void testVariableDeclarationsInSwitchStatement2() throws IOException { CompilationUnit unit = translateType( "A", "public class A { public void doSomething(int i) { switch (i) { " + "case 1: int j = i * 2; log(j); break; " + "case 2: log(i); break; " + "case 3: log(i); int k = i, l = 42; break; }}" + "private void log(int i) {}}"); TypeDeclaration testType = (TypeDeclaration) unit.getTypes().get(0); MethodDeclaration method = TreeUtil.getMethodDeclarationsList(testType).get(0); List<Statement> stmts = method.getBody().getStatements(); assertEquals(1, stmts.size()); Block block = (Block) stmts.get(0); stmts = block.getStatements(); assertEquals(3, stmts.size()); assertTrue(stmts.get(0) instanceof VariableDeclarationStatement); assertTrue(stmts.get(1) instanceof VariableDeclarationStatement); assertTrue(stmts.get(2) instanceof SwitchStatement); }
/** * Verify that interface methods declaring methods implemented by super-class have a forwarding * method. */ public void testInterfaceOfSuperclassMethodInAnonymousInner() { String source = "interface Equateable { boolean equals(Object o); }" + "public class Test { public void foo() { Equateable e = new Equateable() { }; } } "; CompilationUnit unit = translateType("Test", source); assertEquals(3, unit.getTypes().size()); TypeDeclaration innerType = (TypeDeclaration) unit.getTypes().get(2); assertEquals("$1", innerType.getName().toString()); List<MethodDeclaration> methods = TreeUtil.getMethodDeclarationsList(innerType); assertEquals(2, methods.size()); // isEqual, init MethodDeclaration equalsMethod = methods.get(0); assertEquals("isEqual", equalsMethod.getName().getIdentifier()); assertEquals(1, equalsMethod.getParameters().size()); assertTrue(equalsMethod.getParameters().get(0) instanceof SingleVariableDeclaration); List<Statement> stmts = equalsMethod.getBody().getStatements(); assertEquals(1, stmts.size()); Statement stmt = stmts.get(0); assertTrue(stmt instanceof ReturnStatement); assertTrue(((ReturnStatement) stmt).getExpression() instanceof SuperMethodInvocation); }
/** Verify that super-interface methods are also added. */ public void testAbstractClassGrandfatherInterface() { String source = "public class Test {" + " public interface I1 { void foo(); } " + " public interface I2 extends I1 { void bar(); } " + " public abstract class Inner implements I2 { } }"; CompilationUnit unit = translateType("Test", source); List<AbstractTypeDeclaration> types = unit.getTypes(); assertEquals(4, types.size()); assertTrue(types.get(3) instanceof TypeDeclaration); TypeDeclaration innerType = (TypeDeclaration) types.get(3); assertEquals("Inner", innerType.getName().toString()); List<MethodDeclaration> methods = TreeUtil.getMethodDeclarationsList(innerType); assertEquals(3, methods.size()); String name0 = methods.get(0).getName().getIdentifier(); assertTrue(name0.matches("foo|bar")); String name1 = methods.get(1).getName().getIdentifier(); assertTrue(name1.matches("foo|bar")); assertNotSame(name0, name1); }
/** List has a toArray() method that uses array types. */ public void testAbstractMethodsAddedWithArrayType() { String source = "import java.util.List; public abstract class Test implements List<Object> { " + "public boolean isEmpty() { return true; } }"; CompilationUnit unit = translateType("Test", source); List<AbstractTypeDeclaration> types = unit.getTypes(); assertEquals(1, types.size()); assertTrue(types.get(0) instanceof TypeDeclaration); TypeDeclaration testType = (TypeDeclaration) types.get(0); List<MethodDeclaration> methods = TreeUtil.getMethodDeclarationsList(testType); assertEquals(26, methods.size()); // verify added methods are abstract, and that existing method wasn't changed for (MethodDeclaration m : methods) { int modifiers = m.getModifiers(); String name = m.getName().getIdentifier(); if (name.equals("isEmpty")) { assertFalse(Modifier.isAbstract(modifiers)); } else if (name.equals(NameTable.FINALIZE_METHOD) || name.equals(NameTable.DEALLOC_METHOD) || name.equals(NameTable.INIT_NAME)) { // it's ok. } else { // it's an added method assertTrue(Modifier.isAbstract(modifiers)); ITypeBinding returnType = m.getReturnType().getTypeBinding(); if (name.equals("toArray")) { assertEquals("IOSObjectArray", returnType.getName()); if (!m.getParameters().isEmpty()) { assertEquals(1, m.getParameters().size()); SingleVariableDeclaration param = m.getParameters().get(0); IVariableBinding paramBinding = param.getVariableBinding(); assertTrue(paramBinding.getType().isArray()); } } } } }
/** Verifies that abstract methods to implement an interface are added to an abstract class. */ public void testAbstractMethodsAdded() { String source = "import java.util.Iterator; public abstract class Test implements Iterator<Test> { " + "public boolean hasNext() { return true; } }"; CompilationUnit unit = translateType("Test", source); List<AbstractTypeDeclaration> types = unit.getTypes(); assertEquals(1, types.size()); assertTrue(types.get(0) instanceof TypeDeclaration); TypeDeclaration testType = (TypeDeclaration) types.get(0); List<MethodDeclaration> methods = TreeUtil.getMethodDeclarationsList(testType); assertEquals(4, methods.size()); // verify added methods are abstract, and that existing method wasn't changed for (MethodDeclaration m : methods) { int modifiers = m.getModifiers(); String name = m.getName().getIdentifier(); if (name.equals("hasNext")) { assertFalse(Modifier.isAbstract(modifiers)); } else if (name.equals(NameTable.FINALIZE_METHOD) || name.equals(NameTable.DEALLOC_METHOD) || name.equals(NameTable.INIT_NAME)) { // it's ok. } else { // it's an added method assertTrue(Modifier.isAbstract(modifiers)); assertEquals(0, m.getParameters().size()); if (name.equals("next")) { assertEquals(testType.getTypeBinding(), m.getReturnType().getTypeBinding()); } else if (name.equals("remove")) { ITypeBinding voidType = Types.resolveJavaType("void"); assertEquals(voidType, m.getReturnType().getTypeBinding()); } else { fail("unknown method added: " + name); } } } }
public void testFieldSignatures() throws IOException { CompilationUnit unit = translateType( "A", "class A<X,Y,Z> { int a; double[] b; X c; Y[] d; " + "Class<?> e; java.util.List<X> f; Comparable<? super X> g; " + "A<? extends Number, ?, String> h; }"); IVariableBinding[] vars = unit.getTypes().get(0).getTypeBinding().getDeclaredFields(); assertEquals(8, vars.length); // Verify a and b don't return a signature, since they aren't generic types. assertNull(SignatureGenerator.createFieldTypeSignature(vars[0])); assertNull(SignatureGenerator.createFieldTypeSignature(vars[1])); assertEquals("TX;", SignatureGenerator.createFieldTypeSignature(vars[2])); assertEquals("[TY;", SignatureGenerator.createFieldTypeSignature(vars[3])); assertEquals("Ljava/lang/Class<*>;", SignatureGenerator.createFieldTypeSignature(vars[4])); assertEquals("Ljava/util/List<TX;>;", SignatureGenerator.createFieldTypeSignature(vars[5])); assertEquals( "Ljava/lang/Comparable<-TX;>;", SignatureGenerator.createFieldTypeSignature(vars[6])); assertEquals( "LA<+Ljava/lang/Number;*Ljava/lang/String;>;", SignatureGenerator.createFieldTypeSignature(vars[7])); }