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 com
.intellij
.psi
.impl
.source
.tree
.java
;
18 import com
.intellij
.lang
.ASTNode
;
19 import com
.intellij
.openapi
.diagnostic
.Logger
;
20 import com
.intellij
.openapi
.util
.TextRange
;
21 import com
.intellij
.psi
.*;
22 import com
.intellij
.psi
.impl
.PsiImplUtil
;
23 import com
.intellij
.psi
.impl
.source
.Constants
;
24 import com
.intellij
.psi
.impl
.source
.SourceTreeToPsiMap
;
25 import com
.intellij
.psi
.impl
.source
.tree
.*;
26 import com
.intellij
.psi
.tree
.ChildRoleBase
;
27 import com
.intellij
.psi
.util
.MethodSignature
;
28 import com
.intellij
.psi
.util
.MethodSignatureUtil
;
29 import com
.intellij
.util
.ArrayUtil
;
30 import com
.intellij
.util
.CharTable
;
31 import com
.intellij
.util
.IncorrectOperationException
;
32 import org
.jetbrains
.annotations
.NotNull
;
38 //Retrieves method reference from this pair, do NOT reuse!!!
39 public class PsiNameValuePairImpl
extends CompositePsiElement
implements PsiNameValuePair
, Constants
{
40 private static final Logger LOG
= Logger
.getInstance("#com.intellij.psi.impl.source.tree.java.PsiNameValuePairImpl");
41 private volatile String myCachedName
= null;
42 private volatile PsiIdentifier myCachedNameIdentifier
= null;
43 private volatile PsiAnnotationMemberValue myCachedValue
= null;
44 private volatile boolean myNameCached
= false;
46 public void clearCaches() {
49 myCachedNameIdentifier
= null;
54 public PsiNameValuePairImpl() {
55 super(NAME_VALUE_PAIR
);
58 public PsiIdentifier
getNameIdentifier() {
59 PsiIdentifier cachedNameIdentifier
= myCachedNameIdentifier
;
61 myCachedNameIdentifier
= cachedNameIdentifier
= (PsiIdentifier
)findChildByRoleAsPsiElement(ChildRole
.NAME
);
62 myCachedName
= cachedNameIdentifier
== null ?
null : cachedNameIdentifier
.getText();
65 return cachedNameIdentifier
;
68 public String
getName() {
69 String cachedName
= myCachedName
;
71 PsiIdentifier identifier
;
72 myCachedNameIdentifier
= identifier
= (PsiIdentifier
)findChildByRoleAsPsiElement(ChildRole
.NAME
);
73 myCachedName
= cachedName
= identifier
== null ?
null : identifier
.getText();
79 public PsiAnnotationMemberValue
getValue() {
80 PsiAnnotationMemberValue cachedValue
= myCachedValue
;
81 if (cachedValue
== null) {
82 myCachedValue
= cachedValue
= (PsiAnnotationMemberValue
)findChildByRoleAsPsiElement(ChildRole
.ANNOTATION_VALUE
);
89 public PsiAnnotationMemberValue
setValue(@NotNull PsiAnnotationMemberValue newValue
) {
90 getValue().replace(newValue
);
94 public int getChildRole(ASTNode child
) {
95 if (ANNOTATION_MEMBER_VALUE_BIT_SET
.contains(child
.getElementType())) {
96 return ChildRole
.ANNOTATION_VALUE
;
98 else if (child
.getElementType() == IDENTIFIER
) {
99 return ChildRole
.NAME
;
101 else if (child
.getElementType() == EQ
) {
102 return ChildRole
.OPERATION_SIGN
;
105 return ChildRoleBase
.NONE
;
108 public ASTNode
findChildByRole(int role
) {
109 if (role
== ChildRole
.NAME
) {
110 return findChildByType(IDENTIFIER
);
112 else if (role
== ChildRole
.ANNOTATION_VALUE
) {
113 return findChildByType(ANNOTATION_MEMBER_VALUE_BIT_SET
);
115 else if (role
== ChildRole
.OPERATION_SIGN
) {
116 return findChildByType(EQ
);
122 public String
toString() {
123 return "PsiNameValuePair";
126 public PsiReference
getReference() {
127 return new PsiReference() {
128 private PsiClass
getReferencedClass () {
129 LOG
.assertTrue(getTreeParent().getElementType() == ANNOTATION_PARAMETER_LIST
&& getTreeParent().getTreeParent().getElementType() == ANNOTATION
);
130 PsiAnnotationImpl annotation
= (PsiAnnotationImpl
)getTreeParent().getTreeParent().getPsi();
131 PsiJavaCodeReferenceElement nameRef
= annotation
.getNameReferenceElement();
132 return nameRef
== null ?
null : (PsiClass
)nameRef
.resolve();
135 public PsiElement
getElement() {
136 PsiIdentifier nameIdentifier
= getNameIdentifier();
137 if (nameIdentifier
!= null) {
138 return nameIdentifier
;
140 return PsiNameValuePairImpl
.this;
144 public TextRange
getRangeInElement() {
145 PsiIdentifier id
= getNameIdentifier();
147 return new TextRange(0, id
.getTextLength());
149 return new TextRange(0, 0);
152 public PsiElement
resolve() {
153 PsiClass refClass
= getReferencedClass();
154 if (refClass
== null) return null;
155 String name
= getName();
156 if (name
== null) name
= PsiAnnotation
.DEFAULT_REFERENCED_METHOD_NAME
;
157 MethodSignature signature
= MethodSignatureUtil
.createMethodSignature(name
, PsiType
.EMPTY_ARRAY
, PsiTypeParameter
.EMPTY_ARRAY
, PsiSubstitutor
.EMPTY
);
158 return MethodSignatureUtil
.findMethodBySignature(refClass
, signature
, false);
161 public String
getCanonicalText() {
162 String name
= getName();
163 return name
!= null ? name
: PsiAnnotation
.DEFAULT_REFERENCED_METHOD_NAME
;
166 public PsiElement
handleElementRename(String newElementName
) throws IncorrectOperationException
{
167 PsiIdentifier nameIdentifier
= getNameIdentifier();
168 if (nameIdentifier
!= null) {
169 PsiImplUtil
.setName(nameIdentifier
, newElementName
);
171 else if (ANNOTATION_MEMBER_VALUE_BIT_SET
.contains(getFirstChildNode().getElementType())) {
172 PsiElementFactory factory
= JavaPsiFacade
.getInstance(getProject()).getElementFactory();
173 nameIdentifier
= factory
.createIdentifier(newElementName
);
174 addBefore(nameIdentifier
, SourceTreeToPsiMap
.treeElementToPsi(getFirstChildNode()));
177 return PsiNameValuePairImpl
.this;
180 public PsiElement
bindToElement(@NotNull PsiElement element
) throws IncorrectOperationException
{
181 throw new IncorrectOperationException("Not implemented");
184 public boolean isReferenceTo(PsiElement element
) {
185 return element
instanceof PsiMethod
&& element
.equals(resolve());
188 public Object
[] getVariants() {
189 return ArrayUtil
.EMPTY_OBJECT_ARRAY
;
192 public boolean isSoft() {
198 public final void accept(@NotNull PsiElementVisitor visitor
) {
199 if (visitor
instanceof JavaElementVisitor
) {
200 ((JavaElementVisitor
)visitor
).visitNameValuePair(this);
203 visitor
.visitElement(this);
207 public TreeElement
addInternal(TreeElement first
, ASTNode last
, ASTNode anchor
, Boolean before
) {
208 final CharTable treeCharTab
= SharedImplUtil
.findCharTableByTree(this);
209 final TreeElement treeElement
= super.addInternal(first
, last
, anchor
, before
);
210 if (first
== last
&& first
.getElementType() == ElementType
.IDENTIFIER
) {
211 LeafElement eq
= Factory
.createSingleLeafElement(ElementType
.EQ
, "=", 0, 1, treeCharTab
, getManager());
212 super.addInternal(eq
, eq
, first
, Boolean
.FALSE
);
217 public void deleteChildInternal(@NotNull ASTNode child
) {
218 super.deleteChildInternal(child
);
219 if (child
.getElementType() == JavaTokenType
.IDENTIFIER
) {
220 super.deleteChildInternal(findChildByRole(ChildRole
.OPERATION_SIGN
));