• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.ClassItem
20 import com.android.tools.metalava.model.FieldItem
21 import com.android.tools.metalava.model.TypeItem
22 import com.intellij.psi.PsiClass
23 import com.intellij.psi.PsiEnumConstant
24 import com.intellij.psi.PsiField
25 import com.intellij.psi.impl.JavaConstantExpressionEvaluator
26 import org.jetbrains.uast.UClass
27 
28 class PsiFieldItem(
29     override val codebase: PsiBasedCodebase,
30     private val psiField: PsiField,
31     private val containingClass: PsiClassItem,
32     private val name: String,
33     modifiers: PsiModifierItem,
34     documentation: String,
35     private val fieldType: PsiTypeItem,
36     private val isEnumConstant: Boolean,
37     private val initialValue: Any?
38 ) :
39     PsiItem(
40         codebase = codebase,
41         modifiers = modifiers,
42         documentation = documentation,
43         element = psiField
44     ),
45     FieldItem {
46 
47     override var property: PsiPropertyItem? = null
48 
typenull49     override fun type(): TypeItem = fieldType
50     override fun initialValue(requireConstant: Boolean): Any? {
51         if (initialValue != null) {
52             return initialValue
53         }
54         val constant = psiField.computeConstantValue()
55         if (constant != null) {
56             return constant
57         }
58 
59         return if (!requireConstant) {
60             val initializer = psiField.initializer ?: return null
61             JavaConstantExpressionEvaluator.computeConstantExpression(initializer, false)
62         } else {
63             null
64         }
65     }
66 
isEnumConstantnull67     override fun isEnumConstant(): Boolean = isEnumConstant
68     override fun name(): String = name
69     override fun containingClass(): ClassItem = containingClass
70 
71     override fun isCloned(): Boolean {
72         val psiClass = run {
73             val p = containingClass().psi() as? PsiClass ?: return false
74             if (p is UClass) {
75                 p.sourcePsi as? PsiClass ?: return false
76             } else {
77                 p
78             }
79         }
80         return psiField.containingClass != psiClass
81     }
82 
duplicatenull83     override fun duplicate(targetContainingClass: ClassItem): PsiFieldItem {
84         val duplicated = create(codebase, targetContainingClass as PsiClassItem, psiField)
85         duplicated.inheritedFrom = containingClass
86         duplicated.inheritedField = inheritedField
87 
88         // Preserve flags that may have been inherited (propagated) from surrounding packages
89         if (targetContainingClass.hidden) {
90             duplicated.hidden = true
91         }
92         if (targetContainingClass.removed) {
93             duplicated.removed = true
94         }
95         if (targetContainingClass.docOnly) {
96             duplicated.docOnly = true
97         }
98 
99         return duplicated
100     }
101 
102     override var inheritedFrom: ClassItem? = null
103     override var inheritedField: Boolean = false
104 
equalsnull105     override fun equals(other: Any?): Boolean {
106         if (this === other) {
107             return true
108         }
109         return other is FieldItem && name == other.name() && containingClass == other.containingClass()
110     }
111 
hashCodenull112     override fun hashCode(): Int {
113         return name.hashCode()
114     }
115 
toStringnull116     override fun toString(): String = "field ${containingClass.fullName()}.${name()}"
117 
118     companion object {
119         fun create(codebase: PsiBasedCodebase, containingClass: PsiClassItem, psiField: PsiField): PsiFieldItem {
120             val name = psiField.name
121             val commentText = javadoc(psiField)
122             val modifiers = modifiers(codebase, psiField, commentText)
123 
124             val fieldType = codebase.getType(psiField.type)
125             val isEnumConstant = psiField is PsiEnumConstant
126             val initialValue = null // compute lazily
127 
128             val field = PsiFieldItem(
129                 codebase = codebase,
130                 psiField = psiField,
131                 containingClass = containingClass,
132                 name = name,
133                 documentation = commentText,
134                 modifiers = modifiers,
135                 fieldType = fieldType,
136                 isEnumConstant = isEnumConstant,
137                 initialValue = initialValue
138             )
139             field.modifiers.setOwner(field)
140             return field
141         }
142     }
143 }
144