1 /* 2 * 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.ClassTypeItem 20 import com.android.tools.metalava.model.ConstructorItem 21 import com.android.tools.metalava.model.DefaultModifierList 22 import com.android.tools.metalava.model.DefaultModifierList.Companion.PACKAGE_PRIVATE 23 import com.android.tools.metalava.model.ExceptionTypeItem 24 import com.android.tools.metalava.model.MethodItem 25 import com.android.tools.metalava.model.TypeParameterList 26 import com.android.tools.metalava.reporter.FileLocation 27 import com.intellij.psi.JavaPsiFacade 28 import com.intellij.psi.PsiClass 29 import com.intellij.psi.PsiMethod 30 import org.jetbrains.kotlin.psi.KtClassOrObject 31 import org.jetbrains.kotlin.psi.KtPrimaryConstructor 32 import org.jetbrains.uast.UMethod 33 34 class PsiConstructorItem 35 private constructor( 36 codebase: PsiBasedCodebase, 37 psiMethod: PsiMethod, 38 fileLocation: FileLocation = PsiFileLocation(psiMethod), 39 containingClass: PsiClassItem, 40 name: String, 41 modifiers: DefaultModifierList, 42 documentation: String, 43 parameters: List<PsiParameterItem>, 44 returnType: ClassTypeItem, 45 typeParameterList: TypeParameterList, 46 throwsTypes: List<ExceptionTypeItem>, 47 val implicitConstructor: Boolean = false, 48 override val isPrimary: Boolean = false 49 ) : 50 PsiMethodItem( 51 codebase = codebase, 52 modifiers = modifiers, 53 documentation = documentation, 54 psiMethod = psiMethod, 55 fileLocation = fileLocation, 56 containingClass = containingClass, 57 name = name, 58 returnType = returnType, 59 parameters = parameters, 60 typeParameterList = typeParameterList, 61 throwsTypes = throwsTypes, 62 ), 63 ConstructorItem { 64 isImplicitConstructornull65 override fun isImplicitConstructor(): Boolean = implicitConstructor 66 67 override fun isConstructor(): Boolean = true 68 69 override var superConstructor: ConstructorItem? = null 70 71 override fun superMethods(): List<MethodItem> = emptyList() 72 73 companion object { 74 internal fun create( 75 codebase: PsiBasedCodebase, 76 containingClass: PsiClassItem, 77 psiMethod: PsiMethod, 78 enclosingClassTypeItemFactory: PsiTypeItemFactory, 79 ): PsiConstructorItem { 80 assert(psiMethod.isConstructor) 81 val name = psiMethod.name 82 val commentText = javadoc(psiMethod, codebase.allowReadingComments) 83 val modifiers = modifiers(codebase, psiMethod, commentText) 84 // Create the TypeParameterList for this before wrapping any of the other types used by 85 // it as they may reference a type parameter in the list. 86 val (typeParameterList, constructorTypeItemFactory) = 87 PsiTypeParameterList.create( 88 codebase, 89 enclosingClassTypeItemFactory, 90 "constructor $name", 91 psiMethod 92 ) 93 val parameters = parameterList(codebase, psiMethod, constructorTypeItemFactory) 94 val constructor = 95 PsiConstructorItem( 96 codebase = codebase, 97 psiMethod = psiMethod, 98 containingClass = containingClass, 99 name = name, 100 documentation = commentText, 101 modifiers = modifiers, 102 parameters = parameters, 103 returnType = containingClass.type(), 104 implicitConstructor = false, 105 isPrimary = (psiMethod as? UMethod)?.isPrimaryConstructor ?: false, 106 typeParameterList = typeParameterList, 107 throwsTypes = throwsTypes(psiMethod, constructorTypeItemFactory), 108 ) 109 return constructor 110 } 111 112 fun createDefaultConstructor( 113 codebase: PsiBasedCodebase, 114 containingClass: PsiClassItem, 115 psiClass: PsiClass, 116 ): PsiConstructorItem { 117 val name = psiClass.name!! 118 119 val factory = JavaPsiFacade.getInstance(psiClass.project).elementFactory 120 val psiMethod = factory.createConstructor(name, psiClass) 121 val modifiers = DefaultModifierList(codebase, PACKAGE_PRIVATE, null) 122 modifiers.setVisibilityLevel(containingClass.modifiers.getVisibilityLevel()) 123 124 val item = 125 PsiConstructorItem( 126 codebase = codebase, 127 psiMethod = psiMethod, 128 // Use the location of the containing class for the implicit default 129 // constructor. 130 fileLocation = containingClass.fileLocation, 131 containingClass = containingClass, 132 name = name, 133 documentation = "", 134 modifiers = modifiers, 135 parameters = emptyList(), 136 returnType = containingClass.type(), 137 implicitConstructor = true, 138 typeParameterList = TypeParameterList.NONE, 139 throwsTypes = emptyList(), 140 ) 141 return item 142 } 143 144 private val UMethod.isPrimaryConstructor: Boolean 145 get() = sourcePsi is KtPrimaryConstructor || sourcePsi is KtClassOrObject 146 } 147 } 148