/* * Copyright 2010-2015 JetBrains s.r.o. * * 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 org.jetbrains.kotlin.codegen; import org.jetbrains.annotations.NotNull; import org.jetbrains.kotlin.name.SpecialNames; import org.jetbrains.kotlin.test.ConfigurationKind; import org.jetbrains.org.objectweb.asm.Opcodes; import java.lang.reflect.*; import static org.jetbrains.kotlin.codegen.CodegenTestUtil.findDeclaredMethodByName; import static org.jetbrains.kotlin.codegen.CodegenTestUtil.findDeclaredMethodByNameOrNull; public class PropertyGenTest extends CodegenTestCase { @Override protected void setUp() throws Exception { super.setUp(); createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); } @NotNull @Override protected String getPrefix() { return "properties"; } public void testPrivateVal() throws Exception { loadFile(); generateClass("PrivateVal").getDeclaredField("prop"); } public void testPrivateVar() throws Exception { loadFile(); Class<?> aClass = generateClass("PrivateVar"); Object instance = aClass.newInstance(); Method setter = findDeclaredMethodByName(aClass, "setValueOfX"); setter.invoke(instance, 239); Method getter = findDeclaredMethodByName(aClass, "getValueOfX"); assertEquals(239, ((Integer) getter.invoke(instance)).intValue()); } public void testPublicVar() throws Exception { loadText("class PublicVar() { public var foo : Int = 0; }"); Class<?> aClass = generateClass("PublicVar"); Object instance = aClass.newInstance(); Method setter = findDeclaredMethodByName(aClass, "setFoo"); setter.invoke(instance, 239); Method getter = findDeclaredMethodByName(aClass, "getFoo"); assertEquals(239, ((Integer) getter.invoke(instance)).intValue()); } public void testAccessorsInInterface() { loadText("class AccessorsInInterface() { public var foo : Int = 0; }"); Class<?> aClass = generateClass("AccessorsInInterface"); assertNotNull(findDeclaredMethodByName(aClass, "getFoo")); assertNotNull(findDeclaredMethodByName(aClass, "setFoo")); } public void testPrivatePropertyInPackage() throws Exception { loadText("private val x = 239"); Class<?> nsClass = generateFacadeClass(); Field[] fields = nsClass.getDeclaredFields(); assertEquals(1, fields.length); Field field = fields[0]; field.setAccessible(true); assertEquals("x", field.getName()); assertEquals(Modifier.STATIC | Modifier.FINAL | Modifier.PRIVATE, field.getModifiers()); assertEquals(239, field.get(null)); } public void testFieldPropertyAccess() throws Exception { loadFile(); Method method = generateFunction("increment"); assertEquals(1, method.invoke(null)); assertEquals(2, method.invoke(null)); } public void testFieldGetter() throws Exception { loadText("val now: Long get() = 42L; fun foo() = now"); Method method = generateFunction("foo"); assertEquals(Long.valueOf(42), method.invoke(null)); } public void testFieldSetter() throws Exception { loadFile(); Method method = generateFunction("append"); method.invoke(null, "IntelliJ "); String value = (String) method.invoke(null, "IDEA"); if (!value.equals("IntelliJ IDEA")) { System.out.println(generateToText()); throw new AssertionError(value); } assertEquals("IntelliJ IDEA", value); } public void testFieldSetterPlusEq() throws Exception { loadFile(); Method method = generateFunction("append"); method.invoke(null, "IntelliJ "); String value = (String) method.invoke(null, "IDEA"); assertEquals("IntelliJ IDEA", value); } public void testAccessorsWithoutBody() throws Exception { loadText("class AccessorsWithoutBody() { protected var foo: Int = 349\n get\n private set\n fun setter() { foo = 610; } } "); Class<?> aClass = generateClass("AccessorsWithoutBody"); Object instance = aClass.newInstance(); Method getFoo = findDeclaredMethodByName(aClass, "getFoo"); getFoo.setAccessible(true); assertTrue((getFoo.getModifiers() & Modifier.PROTECTED) != 0); assertEquals(349, getFoo.invoke(instance)); Method setFoo = findDeclaredMethodByName(aClass, "setFoo"); setFoo.setAccessible(true); assertTrue((setFoo.getModifiers() & Modifier.PRIVATE) != 0); Method setter = findDeclaredMethodByName(aClass, "setter"); setter.invoke(instance); assertEquals(610, getFoo.invoke(instance)); } public void testPropertyReceiverOnStack() throws Exception { loadFile(); Class<?> aClass = generateClass("Evaluator"); Constructor constructor = aClass.getConstructor(StringBuilder.class); StringBuilder sb = new StringBuilder("xyzzy"); Object instance = constructor.newInstance(sb); Method method = aClass.getMethod("evaluateArg"); Integer result = (Integer) method.invoke(instance); assertEquals(5, result.intValue()); } public void testAbstractVal() throws Exception { loadText("abstract class Foo { public abstract val x: String }"); Class<?> aClass = generateClass("Foo"); assertNotNull(aClass.getMethod("getX")); } public void testKt160() throws Exception { loadText("internal val s = java.lang.Double.toString(1.0)"); Method method = generateFunction("getS"); method.setAccessible(true); assertEquals(method.invoke(null), "1.0"); } public void testKt1846() { loadFile(); Class<?> aClass = generateClass("A"); try { aClass.getMethod("getV1"); System.out.println(generateToText()); fail(); } catch (NoSuchMethodException e) { try { aClass.getMethod("setV1"); System.out.println(generateToText()); fail(); } catch (NoSuchMethodException ee) { // ok } } } public void testKt2589() throws Exception { loadFile(); Class<?> aClass = generateClass("Foo"); assertTrue((aClass.getModifiers() & Opcodes.ACC_FINAL) == 0); Field foo = aClass.getDeclaredField("foo"); assertTrue((foo.getModifiers() & Opcodes.ACC_PRIVATE) != 0); assertTrue((foo.getModifiers() & Opcodes.ACC_FINAL) == 0); Field bar = aClass.getDeclaredField("bar"); assertTrue((bar.getModifiers() & Opcodes.ACC_PRIVATE) != 0); assertTrue((bar.getModifiers() & Opcodes.ACC_FINAL) != 0); Method getFoo = aClass.getDeclaredMethod("getFoo"); assertTrue((getFoo.getModifiers() & Opcodes.ACC_PUBLIC) != 0); assertTrue((getFoo.getModifiers() & Opcodes.ACC_FINAL) != 0); Method getBar = aClass.getDeclaredMethod("getBar"); assertTrue((getBar.getModifiers() & Opcodes.ACC_PROTECTED) != 0); assertTrue((getBar.getModifiers() & Opcodes.ACC_FINAL) == 0); } public void testKt2677() throws Exception { loadFile(); Class<?> derived = generateClass("DerivedWeatherReport"); Class<?> weatherReport = derived.getSuperclass(); { Method get = derived.getDeclaredMethod("getForecast"); Type type = get.getGenericReturnType(); assertInstanceOf(type, ParameterizedType.class); ParameterizedType parameterizedType = (ParameterizedType) type; assertEquals(String.class, parameterizedType.getActualTypeArguments()[0]); Method set = derived.getDeclaredMethod("setForecast", (Class<?>) parameterizedType.getRawType()); type = set.getGenericParameterTypes()[0]; parameterizedType = (ParameterizedType) type; assertInstanceOf(type, ParameterizedType.class); assertEquals(String.class, parameterizedType.getActualTypeArguments()[0]); } { Method get = weatherReport.getDeclaredMethod("getForecast"); Type type = get.getGenericReturnType(); assertInstanceOf(type, ParameterizedType.class); ParameterizedType parameterizedType = (ParameterizedType) type; assertEquals(String.class, parameterizedType.getActualTypeArguments()[0]); Method set = weatherReport.getDeclaredMethod("setForecast", (Class<?>) parameterizedType.getRawType()); type = set.getGenericParameterTypes()[0]; parameterizedType = (ParameterizedType) type; assertInstanceOf(type, ParameterizedType.class); assertEquals(String.class, parameterizedType.getActualTypeArguments()[0]); } } public void testPrivateClassPropertyAccessors() throws Exception { loadFile(); Class<?> c = generateClass("C"); findDeclaredMethodByName(c, "getValWithGet"); findDeclaredMethodByName(c, "getVarWithGetSet"); findDeclaredMethodByName(c, "setVarWithGetSet"); findDeclaredMethodByName(c, "getDelegated"); findDeclaredMethodByName(c, "setDelegated"); findDeclaredMethodByName(c, "getExtension"); findDeclaredMethodByName(c, "setExtension"); findDeclaredMethodByName(initializedClassLoader.loadClass("C$" + SpecialNames.DEFAULT_NAME_FOR_COMPANION_OBJECT.asString()), "getClassObjectVal"); assertNull("Property should not have a getter", findDeclaredMethodByNameOrNull(c, "getVarNoAccessors")); assertNull("Property should not have a setter", findDeclaredMethodByNameOrNull(c, "setVarNoAccessors")); } }