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