1 /* 2 * Copyright (C) 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.tools.metalava.model.psi 18 19 import com.android.tools.metalava.model.VisibilityLevel 20 import com.android.tools.metalava.model.testsuite.BaseModelTest 21 import com.android.tools.metalava.testing.KnownSourceFiles.jetbrainsNullableTypeUseSource 22 import com.android.tools.metalava.testing.java 23 import com.android.tools.metalava.testing.kotlin 24 import com.google.common.truth.Truth.assertThat 25 import kotlin.test.Test 26 import kotlin.test.assertEquals 27 import kotlin.test.assertFalse 28 import kotlin.test.assertTrue 29 30 class PsiModifierItemTest : BaseModelTest() { 31 @Test Test type-use nullability annotation used from Java and Kotlin sourcenull32 fun `Test type-use nullability annotation used from Java and Kotlin source`() { 33 val javaSource = 34 java( 35 """ 36 package test.pkg; 37 public class Foo { 38 public @org.jetbrains.annotations.Nullable String foo() {} 39 } 40 """ 41 .trimIndent() 42 ) 43 val kotlinSource = 44 kotlin( 45 """ 46 package test.pkg 47 class Foo { 48 fun foo(): String? 49 } 50 """ 51 .trimIndent() 52 ) 53 54 runCodebaseTest( 55 inputSet(javaSource, jetbrainsNullableTypeUseSource), 56 inputSet(kotlinSource, jetbrainsNullableTypeUseSource), 57 ) { 58 val method = codebase.assertClass("test.pkg.Foo").methods().single() 59 // For now, the nullability annotation needs to be attached to the method. 60 assertThat(method.annotationNames()) 61 .containsExactly("org.jetbrains.annotations.Nullable") 62 } 63 } 64 65 @Test Kotlin implicit internal visibility inheritancenull66 fun `Kotlin implicit internal visibility inheritance`() { 67 runCodebaseTest( 68 kotlin( 69 """ 70 open class Base { 71 internal open fun method(): Int = 1 72 internal open val property: Int = 2 73 } 74 75 class Inherited : Base() { 76 override fun method(): Int = 3 77 override val property = 4 78 } 79 """ 80 ) 81 ) { 82 val inherited = codebase.assertClass("Inherited") 83 val method = inherited.methods().first { it.name().startsWith("method") } 84 val property = inherited.properties().single() 85 86 assertEquals(VisibilityLevel.INTERNAL, method.modifiers.getVisibilityLevel()) 87 assertEquals(VisibilityLevel.INTERNAL, property.modifiers.getVisibilityLevel()) 88 } 89 } 90 91 @Test Kotlin class visibility modifiersnull92 fun `Kotlin class visibility modifiers`() { 93 runCodebaseTest( 94 kotlin( 95 """ 96 internal class Internal 97 public class Public 98 class DefaultPublic 99 abstract class Outer { 100 private class Private 101 protected class Protected 102 } 103 """ 104 ) 105 ) { 106 assertTrue(codebase.assertClass("Internal").isInternal) 107 assertTrue(codebase.assertClass("Public").isPublic) 108 assertTrue(codebase.assertClass("DefaultPublic").isPublic) 109 assertTrue(codebase.assertClass("Outer.Private").isPrivate) 110 assertTrue(codebase.assertClass("Outer.Protected").isProtected) 111 } 112 } 113 114 @Test Kotlin class abstract and final modifiersnull115 fun `Kotlin class abstract and final modifiers`() { 116 runCodebaseTest( 117 kotlin( 118 """ 119 abstract class Abstract 120 sealed class Sealed 121 open class Open 122 final class Final 123 class FinalDefault 124 interface Interface 125 annotation class Annotation 126 """ 127 ) 128 ) { 129 codebase.assertClass("Abstract").modifiers.let { 130 assertTrue(it.isAbstract()) 131 assertFalse(it.isSealed()) 132 assertFalse(it.isFinal()) 133 } 134 135 codebase.assertClass("Sealed").modifiers.let { 136 assertTrue(it.isAbstract()) 137 assertTrue(it.isSealed()) 138 assertFalse(it.isFinal()) 139 } 140 141 codebase.assertClass("Open").modifiers.let { 142 assertFalse(it.isAbstract()) 143 assertFalse(it.isFinal()) 144 } 145 146 codebase.assertClass("Final").modifiers.let { 147 assertFalse(it.isAbstract()) 148 assertTrue(it.isFinal()) 149 } 150 151 codebase.assertClass("FinalDefault").modifiers.let { 152 assertFalse(it.isAbstract()) 153 assertTrue(it.isFinal()) 154 } 155 156 codebase.assertClass("Interface").modifiers.let { 157 assertTrue(it.isAbstract()) 158 assertFalse(it.isFinal()) 159 } 160 161 codebase.assertClass("Annotation").modifiers.let { 162 assertTrue(it.isAbstract()) 163 assertFalse(it.isFinal()) 164 } 165 } 166 } 167 168 @Test Kotlin class type modifiersnull169 fun `Kotlin class type modifiers`() { 170 runCodebaseTest( 171 kotlin( 172 """ 173 inline class Inline(val value: Int) 174 value class Value(val value: Int) 175 data class Data(val data: Int) { 176 companion object { 177 const val DATA = 0 178 } 179 } 180 fun interface FunInterface { 181 fun foo() 182 } 183 """ 184 ) 185 ) { 186 assertTrue(codebase.assertClass("Inline").modifiers.isInline()) 187 assertTrue(codebase.assertClass("Value").modifiers.isValue()) 188 assertTrue(codebase.assertClass("Data").modifiers.isData()) 189 assertTrue(codebase.assertClass("Data.Companion").modifiers.isCompanion()) 190 assertTrue(codebase.assertClass("FunInterface").modifiers.isFunctional()) 191 } 192 } 193 194 @Test Kotlin class static modifiersnull195 fun `Kotlin class static modifiers`() { 196 runCodebaseTest( 197 kotlin( 198 """ 199 class TopLevel { 200 inner class Inner 201 class Nested 202 interface Interface 203 annotation class Annotation 204 object Object 205 } 206 object Object 207 """ 208 ) 209 ) { 210 assertFalse(codebase.assertClass("TopLevel").modifiers.isStatic()) 211 assertFalse(codebase.assertClass("TopLevel.Inner").modifiers.isStatic()) 212 assertFalse(codebase.assertClass("Object").modifiers.isStatic()) 213 214 assertTrue(codebase.assertClass("TopLevel.Nested").modifiers.isStatic()) 215 assertTrue(codebase.assertClass("TopLevel.Interface").modifiers.isStatic()) 216 assertTrue(codebase.assertClass("TopLevel.Annotation").modifiers.isStatic()) 217 assertTrue(codebase.assertClass("TopLevel.Object").modifiers.isStatic()) 218 } 219 } 220 221 @Test Kotlin vararg parametersnull222 fun `Kotlin vararg parameters`() { 223 runCodebaseTest( 224 kotlin( 225 "Foo.kt", 226 """ 227 fun varArg(vararg parameter: Int) { TODO() } 228 fun nonVarArg(parameter: Int) { TODO() } 229 """ 230 ) 231 ) { 232 val facade = codebase.assertClass("FooKt") 233 val varArg = facade.methods().single { it.name() == "varArg" }.parameters().single() 234 val nonVarArg = 235 facade.methods().single { it.name() == "nonVarArg" }.parameters().single() 236 237 assertTrue(varArg.modifiers.isVarArg()) 238 assertFalse(nonVarArg.modifiers.isVarArg()) 239 } 240 } 241 } 242