rename: remember 'Search for text occurrences' checkbox state (IDEA-21328)
[fedora-idea.git] / java / java-impl / src / com / intellij / codeInsight / TargetElementUtil.java
blob47b67ca3296a0536758d8c1a0bfa5a94e35d6274
1 /*
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.codeInsight;
18 import com.intellij.openapi.editor.Editor;
19 import com.intellij.psi.*;
20 import com.intellij.psi.util.PsiTreeUtil;
21 import com.intellij.psi.util.PsiUtil;
22 import com.intellij.psi.xml.XmlAttribute;
23 import com.intellij.psi.xml.XmlAttributeValue;
24 import com.intellij.psi.xml.XmlTag;
25 import com.intellij.psi.xml.XmlText;
26 import org.jetbrains.annotations.NotNull;
27 import org.jetbrains.annotations.Nullable;
29 import java.util.ArrayList;
30 import java.util.Arrays;
31 import java.util.Collection;
32 import java.util.List;
34 public class TargetElementUtil extends TargetElementUtilBase {
35 public static final int NEW_AS_CONSTRUCTOR = 0x04;
36 public static final int THIS_ACCEPTED = 0x10;
37 public static final int SUPER_ACCEPTED = 0x20;
39 @Override
40 public int getAllAccepted() {
41 return super.getAllAccepted() | NEW_AS_CONSTRUCTOR | THIS_ACCEPTED | SUPER_ACCEPTED;
44 public int getDefinitionSearchFlags() {
45 return super.getDefinitionSearchFlags() | THIS_ACCEPTED | SUPER_ACCEPTED;
48 public int getReferenceSearchFlags() {
49 return super.getReferenceSearchFlags() | NEW_AS_CONSTRUCTOR;
52 @Nullable
53 @Override
54 public PsiElement findTargetElement(final Editor editor, final int flags, final int offset) {
55 final PsiElement element = super.findTargetElement(editor, flags, offset);
56 if (element instanceof PsiKeyword) {
57 if (element.getParent() instanceof PsiThisExpression) {
58 if ((flags & THIS_ACCEPTED) == 0) return null;
59 PsiType type = ((PsiThisExpression)element.getParent()).getType();
60 if (!(type instanceof PsiClassType)) return null;
61 return ((PsiClassType)type).resolve();
64 if (element.getParent() instanceof PsiSuperExpression) {
65 if ((flags & SUPER_ACCEPTED) == 0) return null;
66 PsiType type = ((PsiSuperExpression)element.getParent()).getType();
67 if (!(type instanceof PsiClassType)) return null;
68 return ((PsiClassType)type).resolve();
71 return element;
74 protected boolean isAcceptableReferencedElement(final PsiElement element, final PsiElement referenceOrReferencedElement) {
75 return super.isAcceptableReferencedElement(element, referenceOrReferencedElement) &&
76 !isEnumConstantReference(element, referenceOrReferencedElement);
79 private static boolean isEnumConstantReference(final PsiElement element, final PsiElement referenceOrReferencedElement) {
80 return element != null &&
81 element.getParent() instanceof PsiEnumConstant &&
82 referenceOrReferencedElement instanceof PsiMethod &&
83 ((PsiMethod)referenceOrReferencedElement).isConstructor();
86 @Nullable
87 protected PsiElement getReferenceOrReferencedElement(PsiFile file, Editor editor, int flags, int offset) {
88 PsiElement refElement = super.getReferenceOrReferencedElement(file, editor, flags, offset);
89 PsiReference ref = null;
90 if (refElement == null) {
91 ref = TargetElementUtilBase.findReference(editor, offset);
92 if (ref instanceof PsiJavaReference) {
93 refElement = ((PsiJavaReference)ref).advancedResolve(true).getElement();
97 if (refElement != null) {
98 if ((flags & NEW_AS_CONSTRUCTOR) != 0) {
99 if (ref == null) {
100 ref = TargetElementUtilBase.findReference(editor, offset);
102 if (ref != null) {
103 PsiElement parent = ref.getElement().getParent();
104 if (parent instanceof PsiAnonymousClass) {
105 parent = parent.getParent();
107 if (parent instanceof PsiNewExpression) {
108 PsiMethod constructor = ((PsiNewExpression)parent).resolveConstructor();
109 if (constructor != null) {
110 refElement = constructor;
115 if (refElement instanceof PsiClass) {
116 final PsiFile containingFile = refElement.getContainingFile();
117 if (containingFile != null && containingFile.getVirtualFile() == null) { // in mirror file of compiled class
118 String qualifiedName = ((PsiClass)refElement).getQualifiedName();
119 if (qualifiedName == null) return null;
120 return JavaPsiFacade.getInstance(refElement.getProject()).findClass(qualifiedName, refElement.getResolveScope());
124 return refElement;
128 protected PsiElement getNamedElement(final PsiElement element) {
129 PsiElement parent = element.getParent();
130 if (element instanceof PsiIdentifier) {
131 if (parent instanceof PsiClass && element.equals(((PsiClass)parent).getNameIdentifier())) {
132 return parent;
134 else if (parent instanceof PsiVariable && element.equals(((PsiVariable)parent).getNameIdentifier())) {
135 return parent;
137 else if (parent instanceof PsiMethod && element.equals(((PsiMethod)parent).getNameIdentifier())) {
138 return parent;
140 else if (parent instanceof PsiLabeledStatement && element.equals(((PsiLabeledStatement)parent).getLabelIdentifier())) {
141 return parent;
144 else if ((parent = PsiTreeUtil.getParentOfType(element, PsiNamedElement.class, false)) != null) {
145 // A bit hacky depends on navigation offset correctly overridden
146 if (parent.getTextOffset() == element.getTextRange().getStartOffset() && !(parent instanceof XmlAttribute)) {
147 return parent;
150 return null;
153 @Nullable
154 public static PsiReferenceExpression findReferenceExpression(Editor editor) {
155 final PsiReference ref = findReference(editor);
156 return ref instanceof PsiReferenceExpression ? (PsiReferenceExpression)ref : null;
159 @Override
160 public PsiElement adjustReference(@NotNull final PsiReference ref) {
161 final PsiElement parent = ref.getElement().getParent();
162 if (parent instanceof PsiMethodCallExpression) return parent;
163 return super.adjustReference(ref);
166 @Nullable
167 @Override
168 public PsiElement adjustElement(final Editor editor, final int flags, final PsiElement element, final PsiElement contextElement) {
169 if (element != null) {
170 if (element instanceof PsiAnonymousClass) {
171 return ((PsiAnonymousClass)element).getBaseClassType().resolve();
173 return element;
175 if (contextElement == null) return null;
176 final PsiElement parent = contextElement.getParent();
177 if (parent instanceof XmlText || parent instanceof XmlAttributeValue) {
178 return TargetElementUtilBase.getInstance().findTargetElement(editor, flags, parent.getParent().getTextRange().getStartOffset() + 1);
180 else if (parent instanceof XmlTag || parent instanceof XmlAttribute) {
181 return TargetElementUtilBase.getInstance().findTargetElement(editor, flags, parent.getTextRange().getStartOffset() + 1);
183 return null;
186 public Collection<PsiElement> getTargetCandidates(final PsiReference reference) {
187 PsiElement parent = reference.getElement().getParent();
188 if (parent instanceof PsiMethodCallExpression) {
189 PsiMethodCallExpression callExpr = (PsiMethodCallExpression)parent;
190 boolean allowStatics = false;
191 PsiExpression qualifier = callExpr.getMethodExpression().getQualifierExpression();
192 if (qualifier == null) {
193 allowStatics = true;
195 else if (qualifier instanceof PsiJavaCodeReferenceElement) {
196 PsiElement referee = ((PsiJavaCodeReferenceElement)qualifier).advancedResolve(true).getElement();
197 if (referee instanceof PsiClass) allowStatics = true;
199 PsiResolveHelper helper = JavaPsiFacade.getInstance(parent.getProject()).getResolveHelper();
200 PsiElement[] candidates = PsiUtil.mapElements(helper.getReferencedMethodCandidates(callExpr, false));
201 ArrayList<PsiElement> methods = new ArrayList<PsiElement>();
202 for (PsiElement candidate1 : candidates) {
203 PsiMethod candidate = (PsiMethod)candidate1;
204 if (candidate.hasModifierProperty(PsiModifier.STATIC) && !allowStatics) continue;
205 List<PsiMethod> supers = Arrays.asList(candidate.findSuperMethods());
206 if (supers.isEmpty()) {
207 methods.add(candidate);
209 else {
210 methods.addAll(supers);
213 return methods;
216 return super.getTargetCandidates(reference);
219 public PsiElement getGotoDeclarationTarget(final PsiElement element, final PsiElement navElement) {
220 if (navElement == element && element instanceof PsiCompiledElement && element instanceof PsiMethod) {
221 PsiMethod method = (PsiMethod)element;
222 if (method.isConstructor() && method.getParameterList().getParametersCount() == 0) {
223 PsiClass aClass = method.getContainingClass();
224 PsiElement navClass = aClass.getNavigationElement();
225 if (aClass != navClass) return navClass;
228 return super.getGotoDeclarationTarget(element, navElement);
231 @Override
232 public boolean includeSelfInGotoImplementation(final PsiElement element) {
233 if (element instanceof PsiModifierListOwner && ((PsiModifierListOwner)element).hasModifierProperty(PsiModifier.ABSTRACT)) {
234 return false;
236 return super.includeSelfInGotoImplementation(element);