• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
<lambda>null2  * Copyright (C) 2017 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.ANDROID_DEPRECATED_FOR_SDK
20 import com.android.tools.metalava.model.AnnotationItem
21 import com.android.tools.metalava.model.BaseModifierList
22 import com.android.tools.metalava.model.JAVA_LANG_ANNOTATION_TARGET
23 import com.android.tools.metalava.model.JAVA_LANG_TYPE_USE_TARGET
24 import com.android.tools.metalava.model.JVM_STATIC
25 import com.android.tools.metalava.model.ModifierFlags.Companion.ABSTRACT
26 import com.android.tools.metalava.model.ModifierFlags.Companion.ACTUAL
27 import com.android.tools.metalava.model.ModifierFlags.Companion.COMPANION
28 import com.android.tools.metalava.model.ModifierFlags.Companion.CONST
29 import com.android.tools.metalava.model.ModifierFlags.Companion.DATA
30 import com.android.tools.metalava.model.ModifierFlags.Companion.DEFAULT
31 import com.android.tools.metalava.model.ModifierFlags.Companion.EXPECT
32 import com.android.tools.metalava.model.ModifierFlags.Companion.FINAL
33 import com.android.tools.metalava.model.ModifierFlags.Companion.FUN
34 import com.android.tools.metalava.model.ModifierFlags.Companion.INFIX
35 import com.android.tools.metalava.model.ModifierFlags.Companion.INLINE
36 import com.android.tools.metalava.model.ModifierFlags.Companion.INTERNAL
37 import com.android.tools.metalava.model.ModifierFlags.Companion.NATIVE
38 import com.android.tools.metalava.model.ModifierFlags.Companion.OPERATOR
39 import com.android.tools.metalava.model.ModifierFlags.Companion.PACKAGE_PRIVATE
40 import com.android.tools.metalava.model.ModifierFlags.Companion.PRIVATE
41 import com.android.tools.metalava.model.ModifierFlags.Companion.PROTECTED
42 import com.android.tools.metalava.model.ModifierFlags.Companion.PUBLIC
43 import com.android.tools.metalava.model.ModifierFlags.Companion.SEALED
44 import com.android.tools.metalava.model.ModifierFlags.Companion.STATIC
45 import com.android.tools.metalava.model.ModifierFlags.Companion.STRICT_FP
46 import com.android.tools.metalava.model.ModifierFlags.Companion.SUSPEND
47 import com.android.tools.metalava.model.ModifierFlags.Companion.SYNCHRONIZED
48 import com.android.tools.metalava.model.ModifierFlags.Companion.TRANSIENT
49 import com.android.tools.metalava.model.ModifierFlags.Companion.VALUE
50 import com.android.tools.metalava.model.ModifierFlags.Companion.VARARG
51 import com.android.tools.metalava.model.ModifierFlags.Companion.VOLATILE
52 import com.android.tools.metalava.model.MutableModifierList
53 import com.android.tools.metalava.model.VisibilityLevel
54 import com.android.tools.metalava.model.createMutableModifiers
55 import com.android.tools.metalava.model.hasAnnotation
56 import com.android.tools.metalava.model.isNullnessAnnotation
57 import com.intellij.psi.PsiAnnotation
58 import com.intellij.psi.PsiAnnotationMemberValue
59 import com.intellij.psi.PsiArrayInitializerMemberValue
60 import com.intellij.psi.PsiElement
61 import com.intellij.psi.PsiField
62 import com.intellij.psi.PsiMethod
63 import com.intellij.psi.PsiModifier
64 import com.intellij.psi.PsiModifierList
65 import com.intellij.psi.PsiModifierListOwner
66 import com.intellij.psi.PsiParameter
67 import com.intellij.psi.PsiPrimitiveType
68 import com.intellij.psi.PsiReferenceExpression
69 import com.intellij.psi.impl.light.LightModifierList
70 import org.jetbrains.annotations.NotNull
71 import org.jetbrains.annotations.Nullable
72 import org.jetbrains.kotlin.analysis.api.analyze
73 import org.jetbrains.kotlin.analysis.api.symbols.KaSymbolVisibility
74 import org.jetbrains.kotlin.asJava.elements.KtLightElement
75 import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
76 import org.jetbrains.kotlin.lexer.KtModifierKeywordToken
77 import org.jetbrains.kotlin.lexer.KtTokens
78 import org.jetbrains.kotlin.psi.KtAnnotated
79 import org.jetbrains.kotlin.psi.KtClass
80 import org.jetbrains.kotlin.psi.KtConstructor
81 import org.jetbrains.kotlin.psi.KtDeclaration
82 import org.jetbrains.kotlin.psi.KtElement
83 import org.jetbrains.kotlin.psi.KtFunction
84 import org.jetbrains.kotlin.psi.KtModifierList
85 import org.jetbrains.kotlin.psi.KtModifierListOwner
86 import org.jetbrains.kotlin.psi.KtNamedFunction
87 import org.jetbrains.kotlin.psi.KtProperty
88 import org.jetbrains.kotlin.psi.KtPropertyAccessor
89 import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
90 import org.jetbrains.kotlin.psi.psiUtil.isTopLevelKtOrJavaMember
91 import org.jetbrains.kotlin.psi.psiUtil.visibilityModifier
92 import org.jetbrains.uast.UAnnotated
93 import org.jetbrains.uast.UAnnotation
94 import org.jetbrains.uast.UElement
95 import org.jetbrains.uast.UMethod
96 import org.jetbrains.uast.UVariable
97 import org.jetbrains.uast.kotlin.KotlinUMethodWithFakeLightDelegateBase
98 import org.jetbrains.uast.toUElement
99 
100 internal object PsiModifierItem {
101     fun create(
102         codebase: PsiBasedCodebase,
103         element: PsiModifierListOwner,
104     ): MutableModifierList {
105         val modifiers =
106             if (element is UAnnotated) {
107                 createFromUAnnotated(codebase, element, element)
108             } else {
109                 createFromPsiElement(codebase, element)
110             }
111 
112         // Sometimes Psi/Kotlin interoperation goes a little awry and adds nullability annotations
113         // that it should not, so this removes them.
114         if (shouldRemoveNullnessAnnotations(modifiers)) {
115             modifiers.mutateAnnotations { removeIf { it.isNullnessAnnotation() } }
116         }
117 
118         if (
119             hasDeprecatedAnnotation(modifiers) ||
120                 // Check for @Deprecated on sourcePsi
121                 isDeprecatedFromSourcePsi(element)
122         ) {
123             modifiers.setDeprecated(true)
124         }
125 
126         return modifiers
127     }
128 
129     /**
130      * Creates modifiers for the property represented by [ktDeclaration] using the [KtModifierList]
131      * and from the property. Uses annotations from the [getter] if it exists in addition to
132      * property annotations because property modifiers used to be created just from the getter and
133      * some places rely on the old behavior for annotations (@RestrictTo in AndroidX is only
134      * applicable to accessors, not properties themselves).
135      */
136     fun createForProperty(
137         codebase: PsiBasedCodebase,
138         ktDeclaration: KtDeclaration,
139         getter: PsiMethodItem?,
140         setter: PsiMethodItem?,
141     ): MutableModifierList {
142         val ktModifierList = ktDeclaration.modifierList
143         val visibilityFlags =
144             visibilityFlags(
145                 psiModifierList = null,
146                 ktModifierList = ktModifierList,
147                 element = ktDeclaration,
148                 sourcePsi = ktDeclaration
149             )
150         val kotlinFlags = kotlinFlags { token ->
151             ktModifierList?.hasModifier(token) ?: ktDeclaration.hasModifier(token)
152         }
153         val javaFlags = javaFlagsForKotlinElement(ktDeclaration)
154         val flags = visibilityFlags or kotlinFlags or javaFlags
155 
156         // Use the flags computed from the property, and the getter annotations, if they exist.
157         val modifiers =
158             createMutableModifiers(
159                 flags,
160                 // Filter deprecated annotations: the property will pull effectivelyDeprecated
161                 // status from its getter, but the originallyDeprecated value should reflect
162                 // the property itself, to avoid propagating deprecation from getter to property to
163                 // setter. The setter should only inherit deprecation from the property itself.
164                 getter?.modifiers?.annotations()?.filter { !isDeprecatedAnnotation(it) }
165                     ?: emptyList()
166             )
167 
168         // Correct visibility of accessors (work around K2 bugs with value class type properties)
169         // https://youtrack.jetbrains.com/issue/KT-74205
170         // The getter must have the same visibility as the property
171         val propertyVisibility = modifiers.getVisibilityLevel()
172         if (getter != null && getter.modifiers.getVisibilityLevel() != propertyVisibility) {
173             getter.mutateModifiers { setVisibilityLevel(modifiers.getVisibilityLevel()) }
174         }
175         // The setter cannot be more visible than the property
176         if (setter != null && setter.modifiers.getVisibilityLevel() > propertyVisibility) {
177             setter.mutateModifiers { setVisibilityLevel(modifiers.getVisibilityLevel()) }
178         }
179 
180         // Annotations whose target is property won't be bound to anywhere in LC/UAST, if the
181         // property doesn't need a backing field. Same for unspecified use-site target.
182         // Add all annotations applied to the property by examining source PSI directly.
183         for (ktAnnotationEntry in ktDeclaration.annotationEntries) {
184             val useSiteTarget = ktAnnotationEntry.useSiteTarget?.getAnnotationUseSiteTarget()
185             if (useSiteTarget == null || useSiteTarget == AnnotationUseSiteTarget.PROPERTY) {
186                 val uAnnotation = ktAnnotationEntry.toUElement() as? UAnnotation ?: continue
187                 val annotationItem = UAnnotationItem.create(codebase, uAnnotation) ?: continue
188                 if (annotationItem !in modifiers.annotations()) {
189                     modifiers.addAnnotation(annotationItem)
190                 }
191                 // Make sure static definitions are marked
192                 if (annotationItem.qualifiedName == JVM_STATIC) {
193                     modifiers.setStatic(true)
194                 }
195             }
196         }
197 
198         if (hasDeprecatedAnnotation(modifiers)) {
199             modifiers.setDeprecated(true)
200         }
201 
202         return modifiers
203     }
204 
205     /**
206      * Creates modifiers for a [ktDeclaration] that does not have an equivalent psi element which
207      * can be used with [create]. If the [ktDeclaration] is a property, [createForProperty] should
208      * be used instead.
209      */
210     fun createForKtDeclaration(
211         codebase: PsiBasedCodebase,
212         ktDeclaration: KtDeclaration
213     ): MutableModifierList {
214         val ktModifierList = ktDeclaration.modifierList
215         val visibilityFlags =
216             visibilityFlags(
217                 psiModifierList = null,
218                 ktModifierList = ktModifierList,
219                 element = ktDeclaration,
220                 sourcePsi = ktDeclaration
221             )
222         val kotlinFlags = kotlinFlags { token ->
223             ktModifierList?.hasModifier(token) ?: ktDeclaration.hasModifier(token)
224         }
225         val flags = visibilityFlags or kotlinFlags
226 
227         val annotations =
228             ktDeclaration.annotationEntries.mapNotNull { ktAnnotationEntry ->
229                 (ktAnnotationEntry.toUElement() as? UAnnotation)?.let { uAnnotation ->
230                     UAnnotationItem.create(codebase, uAnnotation)
231                 }
232             }
233 
234         val modifiers =
235             createMutableModifiers(
236                 flags,
237                 annotations,
238             )
239 
240         if (hasDeprecatedAnnotation(modifiers)) {
241             modifiers.setDeprecated(true)
242         }
243 
244         return modifiers
245     }
246 
247     /** Determine whether nullness annotations need removing from [modifiers]. */
248     private fun shouldRemoveNullnessAnnotations(
249         modifiers: BaseModifierList,
250     ): Boolean {
251         // Kotlin varargs are not nullable but can sometimes and up with an @Nullable annotation
252         // added to the [PsiParameter] so remove it from the modifiers. Only Kotlin varargs have a
253         // `vararg` modifier.
254         if (modifiers.isVarArg()) {
255             return true
256         }
257 
258         return false
259     }
260 
261     private fun hasDeprecatedAnnotation(modifiers: BaseModifierList) =
262         modifiers.hasAnnotation(::isDeprecatedAnnotation)
263 
264     private fun isDeprecatedAnnotation(annotationItem: AnnotationItem): Boolean =
265         annotationItem.qualifiedName.let { qualifiedName ->
266             qualifiedName == "Deprecated" ||
267                 qualifiedName.endsWith(".Deprecated") ||
268                 // DeprecatedForSdk that do not apply to this API surface have been filtered
269                 // out so if any are left then treat it as a standard Deprecated annotation.
270                 qualifiedName == ANDROID_DEPRECATED_FOR_SDK
271         }
272 
273     private fun isDeprecatedFromSourcePsi(element: PsiModifierListOwner): Boolean {
274         if (element is UMethod) {
275             // NB: we can't use sourcePsi.annotationEntries directly due to
276             // annotation use-site targets. The given `javaPsi` as a light element,
277             // which spans regular functions, property accessors, etc., is already
278             // built with targeted annotations. Even KotlinUMethod is using LC annotations.
279             return element.javaPsi.isDeprecated
280         }
281         return ((element as? UElement)?.sourcePsi as? KtAnnotated)?.annotationEntries?.any {
282             it.shortName?.toString() == "Deprecated"
283         }
284             ?: false
285     }
286 
287     private fun computeFlag(element: PsiModifierListOwner, modifierList: PsiModifierList): Int {
288         // Look for a KtModifierList to compute visibility and Kotlin-specific modifiers.
289         var ktModifierList: KtModifierList? = null
290         val sourcePsi = (element as? UElement)?.sourcePsi
291         when (modifierList) {
292             is KtLightElement<*, *> -> {
293                 ktModifierList = modifierList.kotlinOrigin as? KtModifierList
294             }
295             is LightModifierList -> {
296                 if (sourcePsi is KtModifierListOwner) {
297                     ktModifierList = sourcePsi.modifierList
298                 }
299             }
300         }
301 
302         // Compute flags that exist in java.
303         var flags =
304             if (
305                 element is KotlinUMethodWithFakeLightDelegateBase<*> && sourcePsi is KtDeclaration
306             ) {
307                 // Fake elements from kotlin (e.g. methods that use value class types) may not have
308                 // the correct modifiers (https://youtrack.jetbrains.com/issue/KTIJ-33047). Compute
309                 // them directly from the source instead.
310                 // Use the property element directly for accessors because some values aren't
311                 // defined for accessors (e.g. containingClassOrObject is null).
312                 javaFlagsForKotlinElement((sourcePsi as? KtPropertyAccessor)?.property ?: sourcePsi)
313             } else {
314                 javaFlags(modifierList)
315             }
316 
317         // Merge in the visibility flags.
318         val visibilityFlags = visibilityFlags(modifierList, ktModifierList, element, sourcePsi)
319         flags = flags or visibilityFlags
320 
321         // Merge in kotlin flags
322         if (ktModifierList != null) {
323             flags = flags or kotlinFlags { token -> ktModifierList.hasModifier(token) }
324         }
325         return flags
326     }
327 
328     /** Determine the element visibility, which can come from several sources. */
329     private fun visibilityFlags(
330         psiModifierList: PsiModifierList?,
331         ktModifierList: KtModifierList?,
332         element: PsiElement?,
333         sourcePsi: PsiElement?
334     ): Int {
335         var visibilityFlags =
336             when {
337                 psiModifierList?.hasModifierProperty(PsiModifier.PUBLIC) == true -> PUBLIC
338                 psiModifierList?.hasModifierProperty(PsiModifier.PROTECTED) == true -> PROTECTED
339                 psiModifierList?.hasModifierProperty(PsiModifier.PRIVATE) == true -> PRIVATE
340                 ktModifierList != null ->
341                     when {
342                         ktModifierList.hasModifier(KtTokens.PRIVATE_KEYWORD) -> PRIVATE
343                         ktModifierList.hasModifier(KtTokens.PROTECTED_KEYWORD) -> PROTECTED
344                         ktModifierList.hasModifier(KtTokens.INTERNAL_KEYWORD) -> INTERNAL
345                         else -> PUBLIC
346                     }
347                 // UAST workaround: fake light method for inline/hidden function may not have a
348                 // concrete modifier list, but overrides `hasModifierProperty` to mimic
349                 // modifiers.
350                 element is KotlinUMethodWithFakeLightDelegateBase<*> ->
351                     when {
352                         element.hasModifierProperty(PsiModifier.PUBLIC) -> PUBLIC
353                         element.hasModifierProperty(PsiModifier.PROTECTED) -> PROTECTED
354                         element.hasModifierProperty(PsiModifier.PRIVATE) -> PRIVATE
355                         else -> PUBLIC
356                     }
357                 sourcePsi is KtModifierListOwner ->
358                     when {
359                         sourcePsi.hasModifier(KtTokens.PRIVATE_KEYWORD) -> PRIVATE
360                         sourcePsi.hasModifier(KtTokens.PROTECTED_KEYWORD) -> PROTECTED
361                         sourcePsi.hasModifier(KtTokens.INTERNAL_KEYWORD) -> INTERNAL
362                         else -> PUBLIC
363                     }
364                 else -> PACKAGE_PRIVATE
365             }
366         if (ktModifierList != null) {
367             if (ktModifierList.hasModifier(KtTokens.INTERNAL_KEYWORD)) {
368                 // Reset visibilityFlags to INTERNAL if the internal modifier is explicitly
369                 // present on the element
370                 visibilityFlags = INTERNAL
371             } else if (
372                 ktModifierList.hasModifier(KtTokens.OVERRIDE_KEYWORD) &&
373                     ktModifierList.visibilityModifier() == null &&
374                     sourcePsi is KtElement
375             ) {
376                 // Reset visibilityFlags to INTERNAL if the element has no explicit visibility
377                 // modifier, but overrides an internal declaration. Adapted from
378                 // org.jetbrains.kotlin.asJava.classes.UltraLightMembersCreator.isInternal
379                 analyze(sourcePsi) {
380                     val symbol = (sourcePsi as? KtDeclaration)?.symbol
381                     val visibility = symbol?.visibility
382                     if (visibility == KaSymbolVisibility.INTERNAL) {
383                         visibilityFlags = INTERNAL
384                     }
385                 }
386             }
387         }
388 
389         if (ktModifierList?.hasModifier(KtTokens.INLINE_KEYWORD) == true) {
390             // Workaround for b/117565118:
391             val func = sourcePsi as? KtNamedFunction
392             if (
393                 func != null &&
394                     (func.typeParameterList?.text ?: "").contains(KtTokens.REIFIED_KEYWORD.value) &&
395                     !ktModifierList.hasModifier(KtTokens.PRIVATE_KEYWORD) &&
396                     !ktModifierList.hasModifier(KtTokens.INTERNAL_KEYWORD)
397             ) {
398                 // Switch back from private to public
399                 visibilityFlags = PUBLIC
400             }
401         }
402 
403         // Methods that are property accessors inherit visibility from the source element
404         if (element is UMethod && (element.sourceElement is KtPropertyAccessor)) {
405             val sourceElement = element.sourceElement
406             if (sourceElement is KtModifierListOwner) {
407                 val sourceModifierList = sourceElement.modifierList
408                 if (sourceModifierList != null) {
409                     if (sourceModifierList.hasModifier(KtTokens.INTERNAL_KEYWORD)) {
410                         visibilityFlags = INTERNAL
411                     }
412                 }
413             }
414         }
415 
416         return visibilityFlags
417     }
418 
419     /**
420      * Computes flags that exist in Java, excluding visibility flags. These are for both Java and
421      * Kotlin source elements.
422      */
423     private fun javaFlags(modifierList: PsiModifierList): Int {
424         var flags = 0
425         if (modifierList.hasModifierProperty(PsiModifier.STATIC)) {
426             flags = flags or STATIC
427         }
428         if (modifierList.hasModifierProperty(PsiModifier.ABSTRACT)) {
429             flags = flags or ABSTRACT
430         }
431         if (modifierList.hasModifierProperty(PsiModifier.FINAL)) {
432             flags = flags or FINAL
433         }
434         if (modifierList.hasModifierProperty(PsiModifier.NATIVE)) {
435             flags = flags or NATIVE
436         }
437         if (modifierList.hasModifierProperty(PsiModifier.SYNCHRONIZED)) {
438             flags = flags or SYNCHRONIZED
439         }
440         if (modifierList.hasModifierProperty(PsiModifier.STRICTFP)) {
441             flags = flags or STRICT_FP
442         }
443         if (modifierList.hasModifierProperty(PsiModifier.TRANSIENT)) {
444             flags = flags or TRANSIENT
445         }
446         if (modifierList.hasModifierProperty(PsiModifier.VOLATILE)) {
447             flags = flags or VOLATILE
448         }
449         if (modifierList.hasModifierProperty(PsiModifier.DEFAULT)) {
450             flags = flags or DEFAULT
451         }
452         return flags
453     }
454 
455     /** Computes Kotlin-specific flags. */
456     private fun kotlinFlags(hasModifier: (KtModifierKeywordToken) -> Boolean): Int {
457         var flags = 0
458         if (hasModifier(KtTokens.VARARG_KEYWORD)) {
459             flags = flags or VARARG
460         }
461         if (hasModifier(KtTokens.SEALED_KEYWORD)) {
462             flags = flags or SEALED
463         }
464         if (hasModifier(KtTokens.INFIX_KEYWORD)) {
465             flags = flags or INFIX
466         }
467         if (hasModifier(KtTokens.CONST_KEYWORD)) {
468             flags = flags or CONST
469         }
470         if (hasModifier(KtTokens.OPERATOR_KEYWORD)) {
471             flags = flags or OPERATOR
472         }
473         if (hasModifier(KtTokens.INLINE_KEYWORD)) {
474             flags = flags or INLINE
475         }
476         if (hasModifier(KtTokens.VALUE_KEYWORD)) {
477             flags = flags or VALUE
478         }
479         if (hasModifier(KtTokens.SUSPEND_KEYWORD)) {
480             flags = flags or SUSPEND
481         }
482         if (hasModifier(KtTokens.COMPANION_KEYWORD)) {
483             flags = flags or COMPANION
484         }
485         if (hasModifier(KtTokens.FUN_KEYWORD)) {
486             flags = flags or FUN
487         }
488         if (hasModifier(KtTokens.DATA_KEYWORD)) {
489             flags = flags or DATA
490         }
491         if (hasModifier(KtTokens.EXPECT_KEYWORD)) {
492             flags = flags or EXPECT
493         }
494         if (hasModifier(KtTokens.ACTUAL_KEYWORD)) {
495             flags = flags or ACTUAL
496         }
497         return flags
498     }
499 
500     /** Creates Java-equivalent flags for the Kotlin element. */
501     private fun javaFlagsForKotlinElement(ktDeclaration: KtDeclaration): Int {
502         return if (
503             // const values are static, and anything in a file-facade class (which top level
504             // [KtDeclaration]s are) is also static
505             ktDeclaration.hasModifier(KtTokens.CONST_KEYWORD) ||
506                 ktDeclaration.isTopLevelKtOrJavaMember()
507         ) {
508             FINAL or STATIC
509         } else if (ktDeclaration.isAbstract()) {
510             ABSTRACT
511         } else if (ktDeclaration.isDefault()) {
512             DEFAULT
513         } else if (ktDeclaration.isFinal()) {
514             FINAL
515         } else {
516             0
517         }
518     }
519 
520     private fun KtDeclaration.isFromInterface(): Boolean {
521         // Can't use containingClass() here -- don't count definitions in interface companions
522         return (containingClassOrObject as? KtClass)?.isInterface() == true
523     }
524 
525     /**
526      * Checks if the [KtDeclaration] needs the abstract modifier:
527      * - if the definition used the abstract modifier
528      * - if the definition is an annotation property
529      * - if the definition is an interface property without a defined getter
530      * - if the definition is an interface function without a body
531      */
532     private fun KtDeclaration.isAbstract(): Boolean {
533         return hasModifier(KtTokens.ABSTRACT_KEYWORD) ||
534             (containingClassOrObject as? KtClass)?.isAnnotation() == true ||
535             (this is KtProperty && isFromInterface() && getter?.hasBody() != true) ||
536             (this is KtFunction && isFromInterface() && !hasBody())
537     }
538 
539     /**
540      * Checks if the [KtDeclaration] needs the default modifier:
541      * - if the definition is an interface property with a defined getter (interface properties
542      *   cannot have backing fields, so this is the only way they can have a default implementation)
543      * - if the definition is an interface function with a body
544      */
545     private fun KtDeclaration.isDefault(): Boolean {
546         return isFromInterface() &&
547             ((this is KtProperty && getter?.hasBody() == true) || (this is KtFunction && hasBody()))
548     }
549 
550     /**
551      * Checks if the [KtDeclaration] needs the final modifier. This should only be called if the
552      * definition does not need the abstract or default modifiers.
553      * - if the definition uses the final keyword
554      * - if the definition does not use the open keyword and does not use the override keyword
555      * - the definition is not a constructor -- the final modifier isn't needed for constructors as
556      *   constructors can never be overridden
557      */
558     private fun KtDeclaration.isFinal(): Boolean {
559         return hasModifier(KtTokens.FINAL_KEYWORD) ||
560             (!hasModifier(KtTokens.OPEN_KEYWORD) &&
561                 !hasModifier(KtTokens.OVERRIDE_KEYWORD) &&
562                 this !is KtConstructor<*>)
563     }
564 
565     /**
566      * Returns a list of the targets this annotation is defined to apply to, as qualified names
567      * (e.g. "java.lang.annotation.ElementType.TYPE_USE").
568      *
569      * If the annotation can't be resolved or does not use `@Target`, returns an empty list.
570      */
571     private fun PsiAnnotation.targets(): List<String> {
572         return resolveAnnotationType()
573             ?.annotations
574             ?.firstOrNull { it.hasQualifiedName(JAVA_LANG_ANNOTATION_TARGET) }
575             ?.findAttributeValue("value")
576             ?.targets()
577             ?: emptyList()
578     }
579 
580     /**
581      * Returns the element types listed in the annotation value, if the value is a direct reference
582      * or an array of direct references.
583      */
584     private fun PsiAnnotationMemberValue.targets(): List<String> {
585         return when (this) {
586             is PsiReferenceExpression -> listOf(qualifiedName)
587             is PsiArrayInitializerMemberValue ->
588                 initializers.mapNotNull { (it as? PsiReferenceExpression)?.qualifiedName }
589             else -> emptyList()
590         }
591     }
592 
593     /**
594      * Annotations which are only `TYPE_USE` should only apply to types, not the owning item of the
595      * type. However, psi incorrectly applies these items to both their types and owning items.
596      *
597      * If an annotation targets both `TYPE_USE` and other use sites, it should be applied to both
598      * types and owning items of the type if the owning item is one of the targeted use sites. See
599      * https://docs.oracle.com/javase/specs/jls/se11/html/jls-9.html#jls-9.7.4 for more detail.
600      *
601      * To work around psi incorrectly applying exclusively `TYPE_USE` annotations to non-type items,
602      * this filters all annotations which should apply to types but not the [forOwner] item.
603      */
604     private fun List<PsiAnnotation>.filterIncorrectTypeUseAnnotations(
605         forOwner: PsiModifierListOwner
606     ): List<PsiAnnotation> {
607         val expectedTarget =
608             when (forOwner) {
609                 is PsiMethod -> "java.lang.annotation.ElementType.METHOD"
610                 is PsiParameter -> "java.lang.annotation.ElementType.PARAMETER"
611                 is PsiField -> "java.lang.annotation.ElementType.FIELD"
612                 else -> return this
613             }
614 
615         return filter { annotation ->
616             val applicableTargets = annotation.targets()
617             // If the annotation is not type use, it has been correctly applied to the item.
618             !applicableTargets.contains(JAVA_LANG_TYPE_USE_TARGET) ||
619                 // If the annotation has the item type as a target, it should be applied here.
620                 applicableTargets.contains(expectedTarget) ||
621                 // For now, leave in nullness annotations until they are specially handled.
622                 isNullnessAnnotation(annotation.qualifiedName.orEmpty())
623         }
624     }
625 
626     private fun createFromPsiElement(
627         codebase: PsiBasedCodebase,
628         element: PsiModifierListOwner
629     ): MutableModifierList {
630         var flags =
631             element.modifierList?.let { modifierList -> computeFlag(element, modifierList) }
632                 ?: PACKAGE_PRIVATE
633 
634         val psiAnnotations = element.annotations
635         return if (psiAnnotations.isEmpty()) {
636             createMutableModifiers(flags)
637         } else {
638             val annotations =
639                 // psi sometimes returns duplicate annotations, using distinct() to counter
640                 // that.
641                 psiAnnotations
642                     .distinct()
643                     // Remove any type-use annotations that psi incorrectly applied to the item.
644                     .filterIncorrectTypeUseAnnotations(element)
645                     .mapNotNull { PsiAnnotationItem.create(codebase, it) }
646                     .filter { !it.isDeprecatedForSdk() }
647             createMutableModifiers(flags, annotations)
648         }
649     }
650 
651     private fun createFromUAnnotated(
652         codebase: PsiBasedCodebase,
653         element: PsiModifierListOwner,
654         annotated: UAnnotated
655     ): MutableModifierList {
656         val modifierList =
657             element.modifierList ?: return createMutableModifiers(VisibilityLevel.PACKAGE_PRIVATE)
658         val uAnnotations = annotated.uAnnotations
659         val psiAnnotations =
660             modifierList.annotations.takeIf { it.isNotEmpty() }
661                 ?: (annotated.javaPsi as? PsiModifierListOwner)?.annotations
662                     ?: PsiAnnotation.EMPTY_ARRAY
663 
664         var flags = computeFlag(element, modifierList)
665 
666         return if (uAnnotations.isEmpty()) {
667             if (psiAnnotations.isNotEmpty()) {
668                 val annotations =
669                     psiAnnotations.mapNotNull { PsiAnnotationItem.create(codebase, it) }
670                 createMutableModifiers(flags, annotations)
671             } else {
672                 createMutableModifiers(flags)
673             }
674         } else {
675             val isPrimitiveVariable = element is UVariable && element.type is PsiPrimitiveType
676 
677             var annotations =
678                 uAnnotations
679                     // Uast sometimes puts nullability annotations on primitives!?
680                     .filter {
681                         !isPrimitiveVariable ||
682                             it.qualifiedName == null ||
683                             !it.isKotlinNullabilityAnnotation
684                     }
685                     .mapNotNull { UAnnotationItem.create(codebase, it) }
686                     .filter { !it.isDeprecatedForSdk() }
687 
688             if (!isPrimitiveVariable) {
689                 if (psiAnnotations.isNotEmpty() && annotations.none { it.isNullnessAnnotation() }) {
690                     val ktNullAnnotation =
691                         psiAnnotations.firstOrNull { psiAnnotation ->
692                             psiAnnotation.qualifiedName?.let { isNullnessAnnotation(it) } == true
693                         }
694                     ktNullAnnotation?.let {
695                         PsiAnnotationItem.create(codebase, it)?.let { annotationItem ->
696                             annotations =
697                                 annotations.toMutableList().run {
698                                     add(annotationItem)
699                                     toList()
700                                 }
701                         }
702                     }
703                 }
704             }
705 
706             createMutableModifiers(flags, annotations)
707         }
708     }
709 
710     /** Returns whether this is a `@DeprecatedForSdk` annotation **that should be skipped**. */
711     private fun AnnotationItem.isDeprecatedForSdk(): Boolean {
712         if (qualifiedName != ANDROID_DEPRECATED_FOR_SDK) {
713             return false
714         }
715 
716         val allowIn = findAttribute(ATTR_ALLOW_IN) ?: return false
717 
718         for (api in allowIn.leafValues()) {
719             val annotationName = api.value() as? String ?: continue
720             if (annotationContext.annotationManager.isShowAnnotationName(annotationName)) {
721                 return true
722             }
723         }
724 
725         return false
726     }
727 
728     private val NOT_NULL = NotNull::class.qualifiedName
729     private val NULLABLE = Nullable::class.qualifiedName
730 
731     private val UAnnotation.isKotlinNullabilityAnnotation: Boolean
732         get() = qualifiedName == NOT_NULL || qualifiedName == NULLABLE
733 }
734 
735 private const val ATTR_ALLOW_IN = "allowIn"
736