• 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     ), FieldItem {
45 
typenull46     override fun type(): TypeItem = fieldType
47     override fun initialValue(requireConstant: Boolean): Any? {
48         if (initialValue != null) {
49             return initialValue
50         }
51         val constant = psiField.computeConstantValue()
52         if (constant != null) {
53             return constant
54         }
55 
56         return if (!requireConstant) {
57             val initializer = psiField.initializer ?: return null
58             JavaConstantExpressionEvaluator.computeConstantExpression(initializer, false)
59         } else {
60             null
61         }
62     }
63 
isEnumConstantnull64     override fun isEnumConstant(): Boolean = isEnumConstant
65     override fun name(): String = name
66     override fun containingClass(): ClassItem = containingClass
67 
68     override fun isCloned(): Boolean {
69         val psiClass = run {
70             val p = containingClass().psi() as? PsiClass ?: return false
71             if (p is UClass) {
72                 p.sourcePsi as? PsiClass ?: return false
73             } else {
74                 p
75             }
76         }
77         return psiField.containingClass != psiClass
78     }
79 
duplicatenull80     override fun duplicate(targetContainingClass: ClassItem): PsiFieldItem {
81         val duplicated = create(codebase, targetContainingClass as PsiClassItem, psiField)
82         duplicated.inheritedFrom = containingClass
83         duplicated.inheritedField = inheritedField
84 
85         // Preserve flags that may have been inherited (propagated) from surrounding packages
86         if (targetContainingClass.hidden) {
87             duplicated.hidden = true
88         }
89         if (targetContainingClass.removed) {
90             duplicated.removed = true
91         }
92         if (targetContainingClass.docOnly) {
93             duplicated.docOnly = true
94         }
95 
96         return duplicated
97     }
98 
99     override var inheritedFrom: ClassItem? = null
100     override var inheritedField: Boolean = false
101 
equalsnull102     override fun equals(other: Any?): Boolean {
103         if (this === other) {
104             return true
105         }
106         return other is FieldItem && name == other.name() && containingClass == other.containingClass()
107     }
108 
hashCodenull109     override fun hashCode(): Int {
110         return name.hashCode()
111     }
112 
toStringnull113     override fun toString(): String = "field ${containingClass.fullName()}.${name()}"
114 
115     companion object {
116         fun create(codebase: PsiBasedCodebase, containingClass: PsiClassItem, psiField: PsiField): PsiFieldItem {
117             val name = psiField.name
118             val commentText = javadoc(psiField)
119             val modifiers = modifiers(codebase, psiField, commentText)
120 
121             val fieldType = codebase.getType(psiField.type)
122             val isEnumConstant = psiField is PsiEnumConstant
123             val initialValue = null // compute lazily
124 
125             val field = PsiFieldItem(
126                 codebase = codebase,
127                 psiField = psiField,
128                 containingClass = containingClass,
129                 name = name,
130                 documentation = commentText,
131                 modifiers = modifiers,
132                 fieldType = fieldType,
133                 isEnumConstant = isEnumConstant,
134                 initialValue = initialValue
135             )
136             field.modifiers.setOwner(field)
137             return field
138         }
139     }
140 }