/* * 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.gen; import com.google.devtools.j2objc.GenerationTest; import java.io.IOException; /** * Tests for {@link TypeImplementationGenerator}. * * @author Keith Stanger */ public class TypeImplementationGeneratorTest extends GenerationTest { public void testFieldAnnotationMethodForAnnotationType() throws IOException { String translation = translateSourceFile( "import java.lang.annotation.*; @Retention(RetentionPolicy.RUNTIME) " + "@interface A { @Deprecated int I = 5; }", "A", "A.m"); assertTranslatedLines(translation, "IOSObjectArray *A__Annotations$0() {", " return [IOSObjectArray arrayWithObjects:(id[]){ " + "create_JavaLangDeprecated() } count:1 " + "type:JavaLangAnnotationAnnotation_class_()];", "}"); } public void testFieldAnnotationMethodForInterfaceType() throws IOException { String translation = translateSourceFile( "interface I { @Deprecated int I = 5; }", "I", "I.m"); assertTranslatedLines(translation, "IOSObjectArray *I__Annotations$0() {", " return [IOSObjectArray arrayWithObjects:(id[]){ " + "create_JavaLangDeprecated() } count:1 " + "type:JavaLangAnnotationAnnotation_class_()];", "}"); } public void testFunctionLineNumbers() throws IOException { options.setEmitLineDirectives(true); String translation = translateSourceFile("class A {\n\n" + " static void test() {\n" + " System.out.println(A.class);\n" + " }}", "A", "A.m"); assertTranslatedLines(translation, "#line 3", "void A_test() {", "A_initialize();", "", "#line 4", "[((JavaIoPrintStream *) nil_chk(JreLoadStatic(JavaLangSystem, out))) " + "printlnWithId:A_class_()];"); } // Regression for non-static constants used in switch statements. // https://github.com/google/j2objc/issues/492 public void testNonStaticPrimitiveConstant() throws IOException { String translation = translateSourceFile( "class Test { final int I = 1; void test(int i) { switch(i) { case I: return; } } }", "Test", "Test.h"); assertTranslation(translation, "#define Test_I 1"); translation = getTranslatedFile("Test.m"); assertTranslation(translation, "case Test_I:"); } public void testDesignatedInitializer() throws IOException { String translation = translateSourceFile( "class Test extends Number { Test(int i) {} public double doubleValue() { return 0; } " + " public float floatValue() { return 0; } public int intValue() { return 0; } " + " public long longValue() { return 0; }}", "Test", "Test.m"); assertTranslatedLines(translation, "J2OBJC_IGNORE_DESIGNATED_BEGIN", "- (instancetype)initWithInt:(jint)i {", " Test_initWithInt_(self, i);", " return self;", "}", "J2OBJC_IGNORE_DESIGNATED_END"); } // Verify that accessor methods for static vars and constants are generated on request. public void testStaticFieldAccessorMethods() throws IOException { options.setStaticAccessorMethods(true); String source = "class Test { " + "static String ID; " + "private static int i; " + "public static final int VERSION = 1; " + "static final Test DEFAULT = new Test(); }"; String translation = translateSourceFile(source, "Test", "Test.m"); assertTranslatedLines(translation, "+ (NSString *)ID {", "return Test_ID;"); assertTranslatedLines(translation, "+ (void)setID:(NSString *)value {", "JreStrongAssign(&Test_ID, value);"); assertTranslatedLines(translation, "+ (jint)VERSION {", "return Test_VERSION;"); assertTranslatedLines(translation, "+ (Test *)DEFAULT {", "return Test_DEFAULT;"); assertNotInTranslation(translation, "+ (void)setDEFAULT:(Test *)value"); // Read-only assertNotInTranslation(translation, "+ (jint)i"); // Private assertNotInTranslation(translation, "+ (void)setI:(jint)value"); // Private } // Verify that accessor methods for static vars and constants aren't generated by default. public void testNoStaticFieldAccessorMethods() throws IOException { String source = "class Test { " + "static String ID; " + "private static int i; " + "public static final int VERSION = 1; " + "static final Test DEFAULT = new Test(); }"; String translation = translateSourceFile(source, "Test", "Test.m"); assertNotInTranslation(translation, "+ (NSString *)ID"); assertNotInTranslation(translation, "+ (void)setID:(NSString *)value"); assertNotInTranslation(translation, "+ (void)setI:(jint)value"); assertNotInTranslation(translation, "+ (jint)VERSION"); assertNotInTranslation(translation, "+ (Test *)DEFAULT"); } // Verify that accessor methods for enum constants are generated on request. public void testEnumConstantAccessorMethods() throws IOException { options.setStaticAccessorMethods(true); String source = "enum Test { ONE, TWO, EOF }"; String translation = translateSourceFile(source, "Test", "Test.m"); assertTranslatedLines(translation, "+ (Test *)ONE {", "return JreEnum(Test, ONE);"); assertTranslatedLines(translation, "+ (Test *)TWO {", "return JreEnum(Test, TWO);"); assertTranslatedLines(translation, "+ (Test *)EOF_ {", "return JreEnum(Test, EOF);"); } // Verify that accessor methods for enum constants are not generated by default. public void testNoEnumConstantAccessorMethods() throws IOException { String source = "enum Test { ONE, TWO }"; String translation = translateSourceFile(source, "Test", "Test.m"); assertNotInTranslation(translation, "+ (TestEnum *)ONE"); assertNotInTranslation(translation, "+ (TestEnum *)TWO"); } // Verify that specified properties are synthesized. public void testSynthesizeProperties() throws IOException { String source = "import com.google.j2objc.annotations.Property; class Test { " + "@Property(\"getter=getFoo\") private final Integer foo = 42;" + "private final Integer bar = 84; }"; String translation = translateSourceFile(source, "Test", "Test.m"); assertTranslation(translation, "@synthesize foo = foo_;"); assertNotInTranslation(translation, "@synthesize bar"); } }