2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package org
.jetbrains
.plugins
.groovy
.lang
.psi
.impl
.statements
;
18 import com
.intellij
.lang
.ASTNode
;
19 import com
.intellij
.navigation
.ItemPresentation
;
20 import com
.intellij
.openapi
.editor
.colors
.TextAttributesKey
;
21 import com
.intellij
.psi
.*;
22 import com
.intellij
.psi
.impl
.PsiImplUtil
;
23 import com
.intellij
.psi
.search
.SearchScope
;
24 import com
.intellij
.psi
.stubs
.IStubElementType
;
25 import com
.intellij
.psi
.util
.CachedValue
;
26 import com
.intellij
.psi
.util
.CachedValueProvider
;
27 import com
.intellij
.psi
.util
.PsiModificationTracker
;
28 import com
.intellij
.ui
.LayeredIcon
;
29 import com
.intellij
.util
.IncorrectOperationException
;
30 import org
.jetbrains
.annotations
.NotNull
;
31 import org
.jetbrains
.annotations
.Nullable
;
32 import org
.jetbrains
.plugins
.groovy
.GroovyIcons
;
33 import org
.jetbrains
.plugins
.groovy
.lang
.groovydoc
.psi
.api
.GrDocComment
;
34 import org
.jetbrains
.plugins
.groovy
.lang
.groovydoc
.psi
.impl
.GrDocCommentUtil
;
35 import org
.jetbrains
.plugins
.groovy
.lang
.parser
.GroovyElementTypes
;
36 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.GroovyElementVisitor
;
37 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.GroovyFileBase
;
38 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.PropertyEnhancer
;
39 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.auxiliary
.modifiers
.GrModifierList
;
40 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.GrField
;
41 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.GrNamedArgumentSearchVisitor
;
42 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.blocks
.GrClosableBlock
;
43 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.expressions
.GrExpression
;
44 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.typedef
.GrTypeDefinition
;
45 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.typedef
.GrTypeDefinitionBody
;
46 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.api
.statements
.typedef
.members
.GrAccessorMethod
;
47 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.impl
.synthetic
.GrAccessorMethodImpl
;
48 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.stubs
.GrFieldStub
;
49 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.util
.GroovyPropertyUtils
;
50 import org
.jetbrains
.plugins
.groovy
.lang
.psi
.util
.PsiUtil
;
56 * User: Dmitry.Krasilschikov
59 public class GrFieldImpl
extends GrVariableBaseImpl
<GrFieldStub
> implements GrField
{
60 private GrAccessorMethod mySetter
;
61 private GrAccessorMethod
[] myGetters
;
63 private boolean mySetterInitialized
= false;
64 private boolean myGettersInitialized
= false;
66 private volatile CachedValue
<PsiType
> myEnhancedType
;
68 public GrFieldImpl(@NotNull ASTNode node
) {
72 public GrFieldImpl(GrFieldStub stub
) {
73 this(stub
, GroovyElementTypes
.FIELD
);
76 public GrFieldImpl(GrFieldStub stub
, IStubElementType nodeType
) {
77 super(stub
, nodeType
);
80 public void accept(GroovyElementVisitor visitor
) {
81 visitor
.visitField(this);
84 public String
toString() {
88 public void setInitializer(@Nullable PsiExpression psiExpression
) throws IncorrectOperationException
{
91 public boolean isDeprecated() {
96 public PsiType
getTypeGroovy() {
97 if (isProperty() && getDeclaredType() == null && getInitializer() == null) {
98 CachedValue
<PsiType
> enhancedType
= myEnhancedType
;
99 if (enhancedType
== null) {
100 myEnhancedType
= enhancedType
= getManager().getCachedValuesManager().createCachedValue(new CachedValueProvider
<PsiType
>() {
101 public Result
<PsiType
> compute() {
102 for (PropertyEnhancer enhancer
: PropertyEnhancer
.EP_NAME
.getExtensions()) {
103 final PsiType type
= enhancer
.getPropertyType(GrFieldImpl
.this);
105 return Result
.create(type
, PsiModificationTracker
.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
);
109 return Result
.create(null, PsiModificationTracker
.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT
);
113 final PsiType type
= enhancedType
.getValue();
118 return super.getTypeGroovy();
121 public PsiClass
getContainingClass() {
122 PsiElement parent
= getParent().getParent();
123 if (parent
instanceof GrTypeDefinitionBody
) {
124 final PsiElement pparent
= parent
.getParent();
125 if (pparent
instanceof PsiClass
) {
126 return (PsiClass
)pparent
;
130 final PsiFile file
= getContainingFile();
131 if (file
instanceof GroovyFileBase
) {
132 return ((GroovyFileBase
)file
).getScriptClass();
139 public boolean isProperty() {
140 // final String name = getName();
141 // if (!GroovyPropertyUtils.canBePropertyName(name)) return false;
142 final PsiClass clazz
= getContainingClass();
143 if (clazz
== null) return false;
144 if (clazz
.isInterface()) return false;
145 final GrModifierList modifierList
= getModifierList();
146 return modifierList
== null || !modifierList
.hasExplicitVisibilityModifiers();
149 public GrAccessorMethod
getSetter() {
150 if (mySetterInitialized
) return mySetter
;
154 if (isProperty() && !hasModifierProperty(PsiModifier
.FINAL
)) {
155 String name
= "set" + GroovyPropertyUtils
.capitalize(getName());
156 final GrAccessorMethod setter
= new GrAccessorMethodImpl(this, true, name
);
157 final PsiClass clazz
= getContainingClass();
158 if (!hasContradictingMethods(setter
, clazz
)) {
164 mySetterInitialized
= true;
168 public void clearCaches() {
169 mySetterInitialized
= myGettersInitialized
= false;
171 myGetters
= GrAccessorMethod
.EMPTY_ARRAY
;
172 myEnhancedType
= null;
176 public GrAccessorMethod
[] getGetters() {
177 if (myGettersInitialized
) return myGetters
;
179 myGetters
= GrAccessorMethod
.EMPTY_ARRAY
;
182 String name
= getName();
183 final PsiClass clazz
= getContainingClass();
184 name
= GroovyPropertyUtils
.capitalize(name
);
185 GrAccessorMethod getter1
= new GrAccessorMethodImpl(this, false, "get" + name
);
186 if (hasContradictingMethods(getter1
, clazz
)) getter1
= null;
188 GrAccessorMethod getter2
= null;
189 if (PsiType
.BOOLEAN
.equals(getDeclaredType())) {
190 getter2
= new GrAccessorMethodImpl(this, false, "is" + name
);
191 if (hasContradictingMethods(getter2
, clazz
)) getter2
= null;
194 if (getter1
!= null || getter2
!= null) {
195 if (getter1
!= null && getter2
!= null) {
196 myGetters
= new GrAccessorMethod
[]{getter1
, getter2
};
198 else if (getter1
!= null) {
199 myGetters
= new GrAccessorMethod
[]{getter1
};
202 myGetters
= new GrAccessorMethod
[]{getter2
};
208 myGettersInitialized
= true;
212 private boolean hasContradictingMethods(GrAccessorMethod proto
, PsiClass clazz
) {
213 PsiMethod
[] methods
= clazz
instanceof GrTypeDefinition
214 ?
((GrTypeDefinition
)clazz
).findCodeMethodsBySignature(proto
, true)
215 : clazz
.findMethodsBySignature(proto
, true);
216 for (PsiMethod method
: methods
) {
217 if (clazz
.equals(method
.getContainingClass())) return true;
219 if (PsiUtil
.isAccessible(clazz
, method
) && method
.hasModifierProperty(PsiModifier
.FINAL
)) return true;
222 //final property in supers
223 PsiClass aSuper
= clazz
.getSuperClass();
224 if (aSuper
!= null) {
225 PsiField field
= aSuper
.findFieldByName(getName(), true);
226 if (field
instanceof GrField
&& ((GrField
)field
).isProperty() && field
.hasModifierProperty(PsiModifier
.FINAL
)) return true;
233 public SearchScope
getUseScope() {
235 return getManager().getFileManager().getUseScope(this); //maximal scope
237 return PsiImplUtil
.getMemberUseScope(this);
241 public ItemPresentation
getPresentation() {
242 return new ItemPresentation() {
243 public String
getPresentableText() {
248 public String
getLocationString() {
249 PsiClass clazz
= getContainingClass();
250 if (clazz
== null) return "";
251 String name
= clazz
.getQualifiedName();
253 return "(in " + name
+ ")";
257 public Icon
getIcon(boolean open
) {
258 return GrFieldImpl
.this.getIcon(ICON_FLAG_VISIBILITY
| ICON_FLAG_READ_STATUS
);
262 public TextAttributesKey
getTextAttributesKey() {
268 public PsiElement
getOriginalElement() {
269 final PsiClass containingClass
= getContainingClass();
270 if (containingClass
== null) return this;
271 PsiClass originalClass
= (PsiClass
)containingClass
.getOriginalElement();
272 PsiField originalField
= originalClass
.findFieldByName(getName(), false);
273 return originalField
!= null ? originalField
: this;
277 public Icon
getIcon(int flags
) {
278 Icon superIcon
= GroovyIcons
.FIELD
;
279 if (!isProperty()) return superIcon
;
280 LayeredIcon rowIcon
= new LayeredIcon(2);
281 rowIcon
.setIcon(superIcon
, 0);
282 rowIcon
.setIcon(GroovyIcons
.DEF
, 1);
287 public Set
<String
>[] getNamedParametersArray() {
288 final GrExpression initializerGroovy
= getInitializerGroovy();
290 List
<Set
<String
>> namedParameters
= new LinkedList
<Set
<String
>>();
291 if (initializerGroovy
instanceof GrClosableBlock
) {
292 final GrClosableBlock closure
= (GrClosableBlock
)initializerGroovy
;
294 final PsiParameter
[] parameters
= closure
.getAllParameters();
295 final List
<PsiParameter
> parameterList
= Arrays
.asList(parameters
);
297 for (int i
= 0, parameterListSize
= parameterList
.size(); i
< parameterListSize
; i
++) {
298 PsiParameter parameter
= parameterList
.get(i
);
299 final String paramName
= parameter
.getName();
300 final HashSet
<String
> set
= new HashSet
<String
>();
301 namedParameters
.add(i
, set
);
303 closure
.accept(new GrNamedArgumentSearchVisitor(paramName
, set
));
306 return namedParameters
.toArray(new HashSet
[namedParameters
.size()]);
309 public GrDocComment
getGrDocComment() {
310 return GrDocCommentUtil
.findDocComment(this);