[groovy] tweak isEquivalentTo() in accessors and light variables
[idea/community.git] / plugins / groovy / groovy-psi / src / org / jetbrains / plugins / groovy / lang / psi / impl / synthetic / GrLightVariable.java
1 /*
2  * Copyright 2000-2014 JetBrains s.r.o.
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 package org.jetbrains.plugins.groovy.lang.psi.impl.synthetic;
17
18 import com.intellij.psi.*;
19 import com.intellij.psi.impl.source.tree.LeafElement;
20 import com.intellij.psi.search.LocalSearchScope;
21 import com.intellij.psi.search.SearchScope;
22 import com.intellij.psi.xml.XmlAttributeValue;
23 import com.intellij.psi.xml.XmlToken;
24 import com.intellij.util.IncorrectOperationException;
25 import org.jetbrains.annotations.NonNls;
26 import org.jetbrains.annotations.NotNull;
27 import org.jetbrains.plugins.groovy.lang.psi.api.statements.arguments.GrArgumentLabel;
28 import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression;
29 import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils;
30
31 import java.util.Collections;
32 import java.util.List;
33
34 /**
35 * @author sergey.evdokimov
36 */
37 public class GrLightVariable extends GrImplicitVariableImpl implements NavigatablePsiElement {
38
39   private final List<PsiElement> myDeclarations;
40
41   private Object myCreatorKey;
42
43   public GrLightVariable(PsiManager manager,
44                          @NonNls String name,
45                          @NonNls @NotNull String type,
46                          @NotNull PsiElement navigationElement) {
47     this(manager, name, type, Collections.singletonList(navigationElement), getDeclarationScope(navigationElement));
48   }
49
50   public GrLightVariable(PsiManager manager,
51                          @NonNls String name,
52                          @NonNls @NotNull String type,
53                          @NotNull List<PsiElement> declarations,
54                          @NotNull PsiElement scope) {
55     this(manager, name, JavaPsiFacade.getElementFactory(manager.getProject()).createTypeFromText(type, scope), declarations, scope);
56   }
57
58   public GrLightVariable(PsiManager manager,
59                          @NonNls String name,
60                          @NotNull PsiType type,
61                          @NotNull PsiElement navigationElement) {
62     this(manager, name, type, Collections.singletonList(navigationElement), getDeclarationScope(navigationElement));
63   }
64
65   public GrLightVariable(PsiManager manager,
66                          @NonNls String name,
67                          @NotNull PsiType type,
68                          @NotNull List<PsiElement> declarations,
69                          @NotNull PsiElement scope) {
70     super(manager, new GrLightIdentifier(manager, name), type, false, scope);
71
72     myDeclarations = declarations;
73     if (!myDeclarations.isEmpty()) {
74       setNavigationElement(myDeclarations.get(0));
75     }
76   }
77
78   private static PsiElement getDeclarationScope(PsiElement navigationElement) {
79     return navigationElement.getContainingFile();
80   }
81
82   @Override
83   public boolean isWritable() {
84     return getNavigationElement() != this;
85   }
86
87   @Override
88   public PsiFile getContainingFile() {
89     if (!myDeclarations.isEmpty()) {
90       return myDeclarations.get(0).getContainingFile();
91     }
92     else {
93       return getDeclarationScope().getContainingFile();
94     }
95   }
96
97   @Override
98   public boolean isValid() {
99     for (PsiElement declaration : myDeclarations) {
100       if (!declaration.isValid()) return false;
101     }
102
103     return true;
104   }
105
106   @NotNull
107   @Override
108   public SearchScope getUseScope() {
109     return new LocalSearchScope(getDeclarationScope());
110   }
111
112   @Override
113   public boolean isEquivalentTo(PsiElement another) {
114     if (another instanceof GrLightVariable) {
115       return myDeclarations.equals(((GrLightVariable)another).getDeclarations());
116     }
117     return myDeclarations.contains(another) || super.isEquivalentTo(another);
118   }
119
120   @Override
121   public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
122     for (PsiElement declaration : myDeclarations) {
123       if (declaration instanceof PsiNamedElement) {
124         if (declaration instanceof PsiMethod) {
125           name = GroovyPropertyUtils.getGetterNameNonBoolean(name);
126         }
127         ((PsiNamedElement)declaration).setName(name);
128       }
129       else if (declaration instanceof GrArgumentLabel) {
130         ((GrArgumentLabel)declaration).setName(name);
131       }
132       else if (declaration instanceof XmlAttributeValue) {
133         PsiElement leftQuote = declaration.getFirstChild();
134
135         if (!(leftQuote instanceof XmlToken)) continue;
136
137         PsiElement textToken = leftQuote.getNextSibling();
138
139         if (!(textToken instanceof XmlToken)) continue;
140
141         PsiElement rightQuote = textToken.getNextSibling();
142
143         if (!(rightQuote instanceof XmlToken) || rightQuote.getNextSibling() != null) continue;
144
145         ((LeafElement)textToken).replaceWithText(name);
146       }
147       else if (declaration instanceof GrReferenceExpression) {
148         ((GrReferenceExpression)declaration).handleElementRename(name);
149       }
150     }
151
152     return getNameIdentifier().replace(new GrLightIdentifier(myManager, name));
153   }
154
155   public Object getCreatorKey() {
156     return myCreatorKey;
157   }
158
159   public void setCreatorKey(Object creatorKey) {
160     myCreatorKey = creatorKey;
161   }
162
163   public List<PsiElement> getDeclarations() {
164     return myDeclarations;
165   }
166 }