• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.noOpAnnotationManager
21 import com.android.tools.metalava.model.testsuite.BaseModelTest
22 import com.android.tools.metalava.testing.KnownSourceFiles.jetbrainsNullableTypeUseSource
23 import com.android.tools.metalava.testing.java
24 import com.android.tools.metalava.testing.kotlin
25 import com.google.common.truth.Truth.assertThat
26 import kotlin.test.Test
27 import kotlin.test.assertEquals
28 import kotlin.test.assertFalse
29 import kotlin.test.assertTrue
30 
31 class PsiModifierItemTest : BaseModelTest() {
32     @Test
Test type-use nullability annotation used from Java and Kotlin sourcenull33     fun `Test type-use nullability annotation used from Java and Kotlin source`() {
34         val javaSource =
35             java(
36                 """
37             package test.pkg;
38             public class Foo {
39                 public @org.jetbrains.annotations.Nullable String foo() {}
40             }
41         """
42                     .trimIndent()
43             )
44         val kotlinSource =
45             kotlin(
46                 """
47                 package test.pkg
48                 class Foo {
49                     fun foo(): String?
50                 }
51             """
52                     .trimIndent()
53             )
54 
55         runCodebaseTest(
56             inputSet(javaSource, jetbrainsNullableTypeUseSource),
57             inputSet(kotlinSource, jetbrainsNullableTypeUseSource),
58             testFixture =
59                 TestFixture(
60                     // Use the noOpAnnotationManager to avoid annotation name normalizing as the
61                     // annotation names are important for this test.
62                     annotationManager = noOpAnnotationManager,
63                 ),
64         ) {
65             val method = codebase.assertClass("test.pkg.Foo").methods().single()
66             // For now, the nullability annotation needs to be attached to the method.
67             assertThat(method.annotationNames())
68                 .containsExactly("org.jetbrains.annotations.Nullable")
69         }
70     }
71 
72     @Test
Kotlin implicit internal visibility inheritancenull73     fun `Kotlin implicit internal visibility inheritance`() {
74         runCodebaseTest(
75             kotlin(
76                 """
77                     open class Base {
78                         internal open fun method(): Int = 1
79                         internal open val property: Int = 2
80                     }
81 
82                     class Inherited : Base() {
83                         override fun method(): Int = 3
84                         override val property = 4
85                     }
86                 """
87             )
88         ) {
89             val inherited = codebase.assertClass("Inherited")
90             val method = inherited.methods().first { it.name().startsWith("method") }
91             val property = inherited.properties().single()
92 
93             assertEquals(VisibilityLevel.INTERNAL, method.modifiers.getVisibilityLevel())
94             assertEquals(VisibilityLevel.INTERNAL, property.modifiers.getVisibilityLevel())
95         }
96     }
97 
98     @Test
Kotlin class visibility modifiersnull99     fun `Kotlin class visibility modifiers`() {
100         runCodebaseTest(
101             kotlin(
102                 """
103                     internal class Internal
104                     public class Public
105                     class DefaultPublic
106                     abstract class Outer {
107                         private class Private
108                         protected class Protected
109                     }
110                 """
111             )
112         ) {
113             assertTrue(codebase.assertResolvedClass("Internal").isInternal)
114             assertTrue(codebase.assertClass("Public").isPublic)
115             assertTrue(codebase.assertClass("DefaultPublic").isPublic)
116             assertTrue(codebase.assertClass("Outer.Private").isPrivate)
117             assertTrue(codebase.assertClass("Outer.Protected").isProtected)
118         }
119     }
120 
121     @Test
Kotlin class abstract and final modifiersnull122     fun `Kotlin class abstract and final modifiers`() {
123         runCodebaseTest(
124             kotlin(
125                 """
126                     abstract class Abstract
127                     sealed class Sealed
128                     open class Open
129                     final class Final
130                     class FinalDefault
131                     interface Interface
132                     annotation class Annotation
133                 """
134             )
135         ) {
136             codebase.assertClass("Abstract").modifiers.let {
137                 assertTrue(it.isAbstract())
138                 assertFalse(it.isSealed())
139                 assertFalse(it.isFinal())
140             }
141 
142             codebase.assertClass("Sealed").modifiers.let {
143                 assertTrue(it.isAbstract())
144                 assertTrue(it.isSealed())
145                 assertFalse(it.isFinal())
146             }
147 
148             codebase.assertClass("Open").modifiers.let {
149                 assertFalse(it.isAbstract())
150                 assertFalse(it.isFinal())
151             }
152 
153             codebase.assertClass("Final").modifiers.let {
154                 assertFalse(it.isAbstract())
155                 assertTrue(it.isFinal())
156             }
157 
158             codebase.assertClass("FinalDefault").modifiers.let {
159                 assertFalse(it.isAbstract())
160                 assertTrue(it.isFinal())
161             }
162 
163             codebase.assertClass("Interface").modifiers.let {
164                 assertTrue(it.isAbstract())
165                 assertFalse(it.isFinal())
166             }
167 
168             codebase.assertClass("Annotation").modifiers.let {
169                 assertTrue(it.isAbstract())
170                 assertFalse(it.isFinal())
171             }
172         }
173     }
174 
175     @Test
Kotlin class type modifiersnull176     fun `Kotlin class type modifiers`() {
177         runCodebaseTest(
178             kotlin(
179                 """
180                     inline class Inline(val value: Int)
181                     value class Value(val value: Int)
182                     data class Data(val data: Int) {
183                         companion object {
184                             const val DATA = 0
185                         }
186                     }
187                     fun interface FunInterface {
188                         fun foo()
189                     }
190                 """
191             )
192         ) {
193             assertTrue(codebase.assertClass("Inline").modifiers.isInline())
194             assertTrue(codebase.assertClass("Value").modifiers.isValue())
195             assertTrue(codebase.assertClass("Data").modifiers.isData())
196             assertTrue(codebase.assertClass("Data.Companion").modifiers.isCompanion())
197             assertTrue(codebase.assertClass("FunInterface").modifiers.isFunctional())
198         }
199     }
200 
201     @Test
Kotlin class static modifiersnull202     fun `Kotlin class static modifiers`() {
203         runCodebaseTest(
204             kotlin(
205                 """
206                     class TopLevel {
207                         inner class Inner
208                         class Nested
209                         interface Interface
210                         annotation class Annotation
211                         object Object
212                     }
213                     object Object
214                 """
215             )
216         ) {
217             assertFalse(codebase.assertClass("TopLevel").modifiers.isStatic())
218             assertFalse(codebase.assertClass("TopLevel.Inner").modifiers.isStatic())
219             assertFalse(codebase.assertClass("Object").modifiers.isStatic())
220 
221             assertTrue(codebase.assertClass("TopLevel.Nested").modifiers.isStatic())
222             assertTrue(codebase.assertClass("TopLevel.Interface").modifiers.isStatic())
223             assertTrue(codebase.assertClass("TopLevel.Annotation").modifiers.isStatic())
224             assertTrue(codebase.assertClass("TopLevel.Object").modifiers.isStatic())
225         }
226     }
227 
228     @Test
Kotlin vararg parametersnull229     fun `Kotlin vararg parameters`() {
230         runCodebaseTest(
231             kotlin(
232                 "Foo.kt",
233                 """
234                     fun varArg(vararg parameter: Int) { TODO() }
235                     fun nonVarArg(parameter: Int) { TODO() }
236                 """
237             )
238         ) {
239             val facade = codebase.assertClass("FooKt")
240             val varArg = facade.methods().single { it.name() == "varArg" }.parameters().single()
241             val nonVarArg =
242                 facade.methods().single { it.name() == "nonVarArg" }.parameters().single()
243 
244             assertTrue(varArg.modifiers.isVarArg())
245             assertFalse(nonVarArg.modifiers.isVarArg())
246         }
247     }
248 }
249