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.compatibility
20 import com.android.tools.metalava.model.AnnotationRetention
21 import com.android.tools.metalava.model.ClassItem
22 import com.android.tools.metalava.model.CompilationUnit
23 import com.android.tools.metalava.model.ConstructorItem
24 import com.android.tools.metalava.model.FieldItem
25 import com.android.tools.metalava.model.MethodItem
26 import com.android.tools.metalava.model.PackageItem
27 import com.android.tools.metalava.model.PropertyItem
28 import com.android.tools.metalava.model.TypeItem
29 import com.android.tools.metalava.model.TypeParameterList
30 import com.android.tools.metalava.model.VisibilityLevel
31 import com.intellij.lang.jvm.types.JvmReferenceType
32 import com.intellij.psi.PsiClass
33 import com.intellij.psi.PsiClassType
34 import com.intellij.psi.PsiCompiledFile
35 import com.intellij.psi.PsiModifier
36 import com.intellij.psi.PsiModifierListOwner
37 import com.intellij.psi.PsiType
38 import com.intellij.psi.PsiTypeParameter
39 import com.intellij.psi.SyntheticElement
40 import com.intellij.psi.impl.source.PsiClassReferenceType
41 import com.intellij.psi.util.PsiUtil
42 import org.jetbrains.kotlin.psi.KtProperty
43 import org.jetbrains.uast.UClass
44 import org.jetbrains.uast.UFile
45 import org.jetbrains.uast.UMethod
46 import org.jetbrains.uast.getParentOfType
47 import org.jetbrains.uast.kotlin.KotlinUClass
48 
49 open class PsiClassItem(
50     override val codebase: PsiBasedCodebase,
51     val psiClass: PsiClass,
52     private val name: String,
53     private val fullName: String,
54     private val qualifiedName: String,
55     private val hasImplicitDefaultConstructor: Boolean,
56     val classType: ClassType,
57     modifiers: PsiModifierItem,
58     documentation: String
59 ) :
60     PsiItem(
61         codebase = codebase,
62         modifiers = modifiers,
63         documentation = documentation,
64         element = psiClass
65     ), ClassItem {
66 
67     lateinit var containingPackage: PsiPackageItem
68 
69     override fun containingPackage(): PackageItem = containingClass?.containingPackage() ?: containingPackage
70     override fun simpleName(): String = name
71     override fun fullName(): String = fullName
72     override fun qualifiedName(): String = qualifiedName
73     override fun isDefined(): Boolean = codebase.unsupported()
74     override fun isInterface(): Boolean = classType == ClassType.INTERFACE
75     override fun isAnnotationType(): Boolean = classType == ClassType.ANNOTATION_TYPE
76     override fun isEnum(): Boolean = classType == ClassType.ENUM
77     override fun hasImplicitDefaultConstructor(): Boolean = hasImplicitDefaultConstructor
78 
79     private var superClass: ClassItem? = null
80     private var superClassType: TypeItem? = null
81     override fun superClass(): ClassItem? = superClass
82     override fun superClassType(): TypeItem? = superClassType
83 
84     override fun setSuperClass(superClass: ClassItem?, superClassType: TypeItem?) {
85         this.superClass = superClass
86         this.superClassType = superClassType
87     }
88 
89     override var stubConstructor: ConstructorItem? = null
90     override var artifact: String? = null
91 
92     private var containingClass: PsiClassItem? = null
93     override fun containingClass(): PsiClassItem? = containingClass
94 
95     override var hasPrivateConstructor: Boolean = false
96 
97     override fun interfaceTypes(): List<TypeItem> = interfaceTypes
98 
99     override fun setInterfaceTypes(interfaceTypes: List<TypeItem>) {
100         @Suppress("UNCHECKED_CAST")
101         setInterfaces(interfaceTypes as List<PsiTypeItem>)
102     }
103 
104     private fun setInterfaces(interfaceTypes: List<PsiTypeItem>) {
105         this.interfaceTypes = interfaceTypes
106     }
107 
108     private var allInterfaces: List<ClassItem>? = null
109 
110     override fun allInterfaces(): Sequence<ClassItem> {
111         if (allInterfaces == null) {
112             val classes = mutableSetOf<PsiClass>()
113             var curr: PsiClass? = psiClass
114             while (curr != null) {
115                 if (curr.isInterface && !classes.contains(curr)) {
116                     classes.add(curr)
117                 }
118                 addInterfaces(classes, curr.interfaces)
119                 curr = curr.superClass
120             }
121             val result = mutableListOf<ClassItem>()
122             for (cls in classes) {
123                 val item = codebase.findOrCreateClass(cls)
124                 result.add(item)
125             }
126 
127             allInterfaces = result
128         }
129 
130         return allInterfaces!!.asSequence()
131     }
132 
133     private fun addInterfaces(result: MutableSet<PsiClass>, interfaces: Array<out PsiClass>) {
134         for (itf in interfaces) {
135             if (itf.isInterface && !result.contains(itf)) {
136                 result.add(itf)
137                 addInterfaces(result, itf.interfaces)
138                 val superClass = itf.superClass
139                 if (superClass != null) {
140                     addInterfaces(result, arrayOf(superClass))
141                 }
142             }
143         }
144     }
145 
146     private lateinit var innerClasses: List<PsiClassItem>
147     private lateinit var interfaceTypes: List<TypeItem>
148     private lateinit var constructors: List<PsiConstructorItem>
149     private lateinit var methods: List<PsiMethodItem>
150     private lateinit var properties: List<PsiPropertyItem>
151     private lateinit var fields: List<FieldItem>
152 
153     /**
154      * If this item was created by filtering down a different codebase, this temporarily
155      * points to the original item during construction. This is used to let us initialize
156      * for example throws lists later, when all classes in the codebase have been
157      * initialized.
158      */
159     internal var source: PsiClassItem? = null
160 
161     override fun innerClasses(): List<PsiClassItem> = innerClasses
162     override fun constructors(): List<PsiConstructorItem> = constructors
163     override fun methods(): List<PsiMethodItem> = methods
164     override fun properties(): List<PropertyItem> = properties
165     override fun fields(): List<FieldItem> = fields
166 
167     override fun toType(): TypeItem {
168         return PsiTypeItem.create(codebase, codebase.getClassType(psiClass))
169     }
170 
171     override fun hasTypeVariables(): Boolean = psiClass.hasTypeParameters()
172 
173     override fun typeParameterList(): TypeParameterList {
174         if (psiClass.hasTypeParameters()) {
175             return PsiTypeParameterList(
176                 codebase, psiClass.typeParameterList
177                     ?: return TypeParameterList.NONE
178             )
179         } else {
180             return TypeParameterList.NONE
181         }
182     }
183 
184     override fun typeArgumentClasses(): List<ClassItem> {
185         return PsiTypeItem.typeParameterClasses(
186             codebase,
187             psiClass.typeParameterList
188         )
189     }
190 
191     override val isTypeParameter: Boolean
192         get() = psiClass is PsiTypeParameter
193 
194     override fun getCompilationUnit(): CompilationUnit? {
195         if (isInnerClass()) {
196             return null
197         }
198 
199         val containingFile = psiClass.containingFile ?: return null
200         if (containingFile is PsiCompiledFile) {
201             return null
202         }
203 
204         val uFile =
205             if (psiClass is UClass) {
206                 psiClass.getParentOfType<UFile>(UFile::class.java)
207             } else {
208                 null
209             }
210         return PsiCompilationUnit(codebase, uFile, containingFile)
211     }
212 
213     override fun finishInitialization() {
214         super.finishInitialization()
215 
216         for (method in methods) {
217             method.finishInitialization()
218         }
219         for (method in constructors) {
220             method.finishInitialization()
221         }
222         for (field in fields) {
223             // There may be non-Psi fields here later (thanks to addField) but not during construction
224             (field as PsiFieldItem).finishInitialization()
225         }
226         for (inner in innerClasses) {
227             inner.finishInitialization()
228         }
229 
230         // Delay initializing super classes and implemented interfaces for all inner classes: they may refer
231         // to *other* inner classes in this class, which would lead to an attempt to construct
232         // recursively. Instead, we wait until all the inner classes have been constructed, and at
233         // the very end, initialize super classes and interfaces recursively.
234         if (psiClass.containingClass == null) {
235             initializeSuperClasses()
236         }
237     }
238 
239     private fun initializeSuperClasses() {
240         val extendsListTypes = psiClass.extendsListTypes
241         if (extendsListTypes.isNotEmpty()) {
242             val type = PsiTypeItem.create(codebase, extendsListTypes[0])
243             this.superClassType = type
244             this.superClass = type.asClass()
245         } else {
246             val superType = psiClass.superClassType
247             if (superType is PsiType) {
248                 this.superClassType = PsiTypeItem.create(codebase, superType)
249                 this.superClass = this.superClassType?.asClass()
250             }
251         }
252 
253         // Add interfaces. If this class is an interface, it can implement both
254         // classes from the extends clause and from the implements clause.
255         val interfaces = psiClass.implementsListTypes
256         setInterfaces(if (interfaces.isEmpty() && extendsListTypes.size <= 1) {
257             emptyList()
258         } else {
259             val result = ArrayList<PsiTypeItem>(interfaces.size + extendsListTypes.size - 1)
260             val create: (PsiClassType) -> PsiTypeItem = {
261                 val type = PsiTypeItem.create(codebase, it)
262                 type.asClass() // ensure that we initialize classes eagerly too such that they're registered etc
263                 type
264             }
265             (1 until extendsListTypes.size).mapTo(result) { create(extendsListTypes[it]) }
266             interfaces.mapTo(result) { create(it) }
267             result
268         })
269 
270         for (inner in innerClasses) {
271             inner.initializeSuperClasses()
272         }
273     }
274 
275     protected fun initialize(
276         innerClasses: List<PsiClassItem>,
277         interfaceTypes: List<TypeItem>,
278         constructors: List<PsiConstructorItem>,
279         methods: List<PsiMethodItem>,
280         fields: List<FieldItem>
281     ) {
282         this.innerClasses = innerClasses
283         this.interfaceTypes = interfaceTypes
284         this.constructors = constructors
285         this.methods = methods
286         this.fields = fields
287     }
288 
289     override fun mapTypeVariables(target: ClassItem): Map<String, String> {
290         val targetPsi = target.psi() as PsiClass
291         val maps = mapTypeVariablesToSuperclass(
292             psiClass, targetPsi, considerSuperClasses = true,
293             considerInterfaces = targetPsi.isInterface
294         ) ?: return emptyMap()
295 
296         if (maps.isEmpty()) {
297             return emptyMap()
298         }
299 
300         if (maps.size == 1) {
301             return maps[0]
302         }
303 
304         val first = maps[0]
305         val flattened = mutableMapOf<String, String>()
306         for (key in first.keys) {
307             var variable: String? = key
308             for (map in maps) {
309                 val value = map[variable]
310                 variable = value
311                 if (value == null) {
312                     break
313                 } else {
314                     flattened[key] = value
315                 }
316             }
317         }
318         return flattened
319     }
320 
321     override fun equals(other: Any?): Boolean {
322         if (this === other) {
323             return true
324         }
325         return other is ClassItem && qualifiedName == other.qualifiedName()
326     }
327 
328     /**
329      * Creates a constructor in this class
330      */
331     override fun createDefaultConstructor(): ConstructorItem {
332         return PsiConstructorItem.createDefaultConstructor(codebase, this, psiClass)
333     }
334 
335     override fun createMethod(template: MethodItem): MethodItem {
336         val method = template as PsiMethodItem
337 
338         val replacementMap = mapTypeVariables(template.containingClass())
339         val newMethod: PsiMethodItem
340         if (replacementMap.isEmpty()) {
341             newMethod = PsiMethodItem.create(codebase, this, method)
342         } else {
343             val stub = method.toStub(replacementMap)
344             val psiMethod = codebase.createPsiMethod(stub, psiClass)
345             newMethod = PsiMethodItem.create(codebase, this, psiMethod)
346             newMethod.inheritedMethod = method.inheritedMethod
347             newMethod.documentation = method.documentation
348         }
349 
350         if (template.throwsTypes().isEmpty()) {
351             newMethod.setThrowsTypes(emptyList())
352         } else {
353             val throwsTypes = mutableListOf<ClassItem>()
354             for (type in template.throwsTypes()) {
355                 if (type.codebase === codebase) {
356                     throwsTypes.add(type)
357                 } else {
358                     throwsTypes.add(codebase.findOrCreateClass(((type as PsiClassItem).psiClass)))
359                 }
360             }
361             newMethod.setThrowsTypes(throwsTypes)
362         }
363 
364         return newMethod
365     }
366 
367     override fun addMethod(method: MethodItem) {
368         (methods as MutableList<PsiMethodItem>).add(method as PsiMethodItem)
369     }
370 
371     private var retention: AnnotationRetention? = null
372 
373     override fun getRetention(): AnnotationRetention {
374         retention?.let { return it }
375 
376         if (!isAnnotationType()) {
377             error("getRetention() should only be called on annotation classes")
378         }
379 
380         retention = ClassItem.findRetention(this)
381         return retention!!
382     }
383 
384     override fun hashCode(): Int = qualifiedName.hashCode()
385 
386     override fun toString(): String = "class ${qualifiedName()}"
387 
388     companion object {
389         private fun hasExplicitRetention(modifiers: PsiModifierItem, psiClass: PsiClass, isKotlin: Boolean): Boolean {
390             if (modifiers.findAnnotation("java.lang.annotation.Retention") != null) {
391                 return true
392             }
393             if (modifiers.findAnnotation("kotlin.annotation.Retention") != null) {
394                 return true
395             }
396             if (isKotlin && psiClass is UClass) {
397                 // In Kotlin some annotations show up on the Java facade only; for example,
398                 // a @DslMarker annotation will imply a runtime annotation which is present
399                 // in the java facade, not in the source list of annotations
400                 val modifierList = psiClass.modifierList
401                 if (modifierList != null && modifierList.annotations.any {
402                         val qualifiedName = it.qualifiedName
403                         qualifiedName == "kotlin.annotation.Retention" ||
404                             qualifiedName == "java.lang.annotation.Retention"
405                     }) {
406                     return true
407                 }
408             }
409             return false
410         }
411 
412         fun create(codebase: PsiBasedCodebase, psiClass: PsiClass): PsiClassItem {
413             if (psiClass is PsiTypeParameter) {
414                 return PsiTypeParameterItem.create(codebase, psiClass)
415             }
416             val simpleName = psiClass.name!!
417             val fullName = computeFullClassName(psiClass)
418             val qualifiedName = psiClass.qualifiedName ?: simpleName
419             val hasImplicitDefaultConstructor = hasImplicitDefaultConstructor(psiClass)
420             val classType = ClassType.getClassType(psiClass)
421 
422             val commentText = PsiItem.javadoc(psiClass)
423             val modifiers = modifiers(codebase, psiClass, commentText)
424             val item = PsiClassItem(
425                 codebase = codebase,
426                 psiClass = psiClass,
427                 name = simpleName,
428                 fullName = fullName,
429                 qualifiedName = qualifiedName,
430                 classType = classType,
431                 hasImplicitDefaultConstructor = hasImplicitDefaultConstructor,
432                 documentation = commentText,
433                 modifiers = modifiers
434             )
435             codebase.registerClass(item)
436             item.modifiers.setOwner(item)
437 
438             // Construct the children
439             val psiMethods = psiClass.methods
440             val methods: MutableList<PsiMethodItem> = ArrayList(psiMethods.size)
441             val isKotlin = isKotlin(psiClass)
442 
443             if (classType == ClassType.ENUM) {
444                 // In compatibility mode we want explicit valueOf and values methods.
445                 // UAST recently started including these in the AST (as synthetic elements),
446                 // so we no longer need to create those here, but we still need to create
447                 // the synthetic constructor
448                 if (compatibility.defaultEnumMethods) {
449                     // Also add a private constructor; used when emitting the private API
450                     val psiMethod = codebase.createConstructor("private ${psiClass.name}", psiClass)
451                     methods.add(PsiConstructorItem.create(codebase, item, psiMethod))
452                 }
453             } else if (classType == ClassType.ANNOTATION_TYPE && compatibility.explicitlyListClassRetention &&
454                 !hasExplicitRetention(modifiers, psiClass, isKotlin)
455             ) {
456                 // By policy, include explicit retention policy annotation if missing
457                 modifiers.addAnnotation(
458                     codebase.createAnnotation(
459                         "@java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.CLASS)",
460                         item, false
461                     )
462                 )
463             }
464 
465             val constructors: MutableList<PsiConstructorItem> = ArrayList(5)
466             for (psiMethod in psiMethods) {
467                 if (psiMethod.isConstructor) {
468                     val constructor = PsiConstructorItem.create(codebase, item, psiMethod)
469                     constructors.add(constructor)
470                 } else if (classType == ClassType.ENUM &&
471                     !compatibility.defaultEnumMethods &&
472                     psiMethod is SyntheticElement
473                 ) {
474                     // skip
475                 } else {
476                     val method = PsiMethodItem.create(codebase, item, psiMethod)
477                     methods.add(method)
478                 }
479             }
480 
481             if (hasImplicitDefaultConstructor) {
482                 assert(constructors.isEmpty())
483                 constructors.add(PsiConstructorItem.createDefaultConstructor(codebase, item, psiClass))
484             }
485 
486             val fields: MutableList<FieldItem> = mutableListOf()
487             val psiFields = psiClass.fields
488             if (psiFields.isNotEmpty()) {
489                 psiFields.asSequence()
490                     .mapTo(fields) {
491                         PsiFieldItem.create(codebase, item, it)
492                     }
493             }
494 
495             if (classType == ClassType.INTERFACE) {
496                 // All members are implicitly public, fields are implicitly static, non-static methods are abstract
497                 // (except in Java 1.9, where they can be private
498                 for (method in methods) {
499                     if (!method.isPrivate) {
500                         method.mutableModifiers().setVisibilityLevel(VisibilityLevel.PUBLIC)
501                     }
502                 }
503                 for (method in fields) {
504                     val m = method.mutableModifiers()
505                     m.setVisibilityLevel(VisibilityLevel.PUBLIC)
506                     m.setStatic(true)
507                 }
508             }
509 
510             item.constructors = constructors
511             item.methods = methods
512             item.fields = fields
513 
514             item.properties = emptyList()
515             if (isKotlin) {
516                 // Try to initialize the Kotlin properties
517                 val properties = mutableListOf<PsiPropertyItem>()
518                 for (method in psiMethods) {
519                     if (method is UMethod) {
520                         if (method.modifierList.hasModifierProperty(PsiModifier.STATIC)) {
521                             // Skip extension properties
522                             continue
523                         }
524                         val sourcePsi = method.sourcePsi
525                         if (sourcePsi is KtProperty) {
526                             if (method.name.startsWith("set")) {
527                                 continue
528                             }
529                             val name = sourcePsi.name ?: continue
530                             val psiType = method.returnType ?: continue
531                             properties.add(PsiPropertyItem.create(codebase, item, name, psiType, method))
532                         }
533                     }
534                 }
535                 item.properties = properties
536             }
537 
538             val psiInnerClasses = psiClass.innerClasses
539             item.innerClasses = if (psiInnerClasses.isEmpty()) {
540                 emptyList()
541             } else {
542                 val result = psiInnerClasses.asSequence()
543                     .map {
544                         val inner = codebase.findOrCreateClass(it)
545                         inner.containingClass = item
546                         inner
547                     }
548                     .toMutableList()
549                 result
550             }
551 
552             return item
553         }
554 
555         /**
556          * Computes the "full" class name; this is not the qualified class name (e.g. with package)
557          * but for an inner class it includes all the outer classes
558          */
559         fun computeFullClassName(cls: PsiClass): String {
560             if (cls.containingClass == null) {
561                 val name = cls.name
562                 return name!!
563             } else {
564                 val list = mutableListOf<String>()
565                 var curr: PsiClass? = cls
566                 while (curr != null) {
567                     val name = curr.name
568                     curr = if (name != null) {
569                         list.add(name)
570                         curr.containingClass
571                     } else {
572                         break
573                     }
574                 }
575                 return list.asReversed().asSequence().joinToString(separator = ".") { it }
576             }
577         }
578 
579         private fun hasImplicitDefaultConstructor(psiClass: PsiClass): Boolean {
580             if (psiClass.name?.startsWith("-") == true) {
581                 // Deliberately hidden; see examples like
582                 //     @file:JvmName("-ViewModelExtensions") // Hide from Java sources in the IDE.
583                 return false
584             }
585             if (psiClass is KotlinUClass && psiClass.sourcePsi == null) {
586                 // Top level kt classes (FooKt for Foo.kt) do not have implicit default constructor
587                 return false
588             }
589 
590             val constructors = psiClass.constructors
591             if (constructors.isEmpty() && !psiClass.isInterface && !psiClass.isAnnotationType && !psiClass.isEnum) {
592                 if (PsiUtil.hasDefaultConstructor(psiClass)) {
593                     return true
594                 }
595 
596                 // The above method isn't always right; for example, for the ContactsContract.Presence class
597                 // in the framework, which looks like this:
598                 //    @Deprecated
599                 //    public static final class Presence extends StatusUpdates {
600                 //    }
601                 // javac makes a default constructor:
602                 //    public final class android.provider.ContactsContract$Presence extends android.provider.ContactsContract$StatusUpdates {
603                 //        public android.provider.ContactsContract$Presence();
604                 //    }
605                 // but the above method returns false. So add some of our own heuristics:
606                 if (psiClass.hasModifierProperty(PsiModifier.FINAL) && !psiClass.hasModifierProperty(
607                         PsiModifier.ABSTRACT
608                     ) &&
609                     psiClass.hasModifierProperty(PsiModifier.PUBLIC)
610                 ) {
611                     return true
612                 }
613             }
614 
615             return false
616         }
617 
618         fun mapTypeVariablesToSuperclass(
619             psiClass: PsiClass,
620             targetClass: PsiClass,
621             considerSuperClasses: Boolean = true,
622             considerInterfaces: Boolean = psiClass.isInterface
623         ): MutableList<Map<String, String>>? {
624             // TODO: Prune search if type doesn't have type arguments!
625             if (considerSuperClasses) {
626                 val list = mapTypeVariablesToSuperclass(
627                     psiClass.superClassType, targetClass,
628                     considerSuperClasses, considerInterfaces
629                 )
630                 if (list != null) {
631                     return list
632                 }
633             }
634 
635             if (considerInterfaces) {
636                 for (interfaceType in psiClass.interfaceTypes) {
637                     val list = mapTypeVariablesToSuperclass(
638                         interfaceType, targetClass,
639                         considerSuperClasses, considerInterfaces
640                     )
641                     if (list != null) {
642                         return list
643                     }
644                 }
645             }
646 
647             return null
648         }
649 
650         private fun mapTypeVariablesToSuperclass(
651             type: JvmReferenceType?,
652             targetClass: PsiClass,
653             considerSuperClasses: Boolean = true,
654             considerInterfaces: Boolean = true
655         ): MutableList<Map<String, String>>? {
656             // TODO: Prune search if type doesn't have type arguments!
657             val superType = type as? PsiClassReferenceType
658             val superClass = superType?.resolve()
659             if (superClass != null) {
660                 if (superClass == targetClass) {
661                     val map = mapTypeVariablesToSuperclass(superType)
662                     return if (map != null) {
663                         mutableListOf(map)
664                     } else {
665                         null
666                     }
667                 } else {
668                     val list = mapTypeVariablesToSuperclass(
669                         superClass, targetClass, considerSuperClasses,
670                         considerInterfaces
671                     )
672                     if (list != null) {
673                         val map = mapTypeVariablesToSuperclass(superType)
674                         if (map != null) {
675                             list.add(map)
676                         }
677                         return list
678                     }
679                 }
680             }
681 
682             return null
683         }
684 
685         private fun mapTypeVariablesToSuperclass(superType: PsiClassReferenceType?): Map<String, String>? {
686             superType ?: return null
687 
688             val map = mutableMapOf<String, String>()
689             val superClass = superType.resolve()
690             if (superClass != null && superType.hasParameters()) {
691                 val superTypeParameters = superClass.typeParameters
692                 superType.parameters.forEachIndexed { index, parameter ->
693                     if (parameter is PsiClassReferenceType) {
694                         val parameterClass = parameter.resolve()
695                         if (parameterClass != null) {
696                             val parameterName = parameterClass.qualifiedName ?: parameterClass.name ?: parameter.name
697                             if (index < superTypeParameters.size) {
698                                 val superTypeParameter = superTypeParameters[index]
699                                 val superTypeName = superTypeParameter.qualifiedName ?: superTypeParameter.name
700                                 if (superTypeName != null) {
701                                     map[superTypeName] = parameterName
702                                 }
703                             }
704                         }
705                     }
706                 }
707             }
708 
709             return map
710         }
711     }
712 }
713 
PsiModifierListOwnernull714 fun PsiModifierListOwner.isPrivate(): Boolean = modifierList?.hasExplicitModifier(PsiModifier.PRIVATE) == true
715 fun PsiModifierListOwner.isPackagePrivate(): Boolean {
716     val modifiers = modifierList ?: return false
717     return !(modifiers.hasModifierProperty(PsiModifier.PUBLIC) ||
718         modifiers.hasModifierProperty(PsiModifier.PROTECTED))
719 }