better isEquivalenTo for PsiClasses
[fedora-idea.git] / platform / lang-api / src / com / intellij / psi / PsiReferenceBase.java
blob4b83cd2cdbfa6ea4a1a6b60792f3c8e597c1707d
1 /*
2 * Copyright 2000-2007 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.
17 package com.intellij.psi;
19 import com.intellij.openapi.diagnostic.Logger;
20 import com.intellij.openapi.util.TextRange;
21 import com.intellij.util.IncorrectOperationException;
22 import org.jetbrains.annotations.NotNull;
23 import org.jetbrains.annotations.Nullable;
25 /**
26 * @author Dmitry Avdeev
28 public abstract class PsiReferenceBase<T extends PsiElement> implements PsiReference {
30 private static final Logger LOG = Logger.getInstance("#com.intellij.psi.PsiReferenceBase");
32 protected final T myElement;
33 private TextRange myRange;
34 protected boolean mySoft;
36 public PsiReferenceBase(T element, TextRange range, boolean soft) {
37 myElement = element;
38 myRange = range;
39 mySoft = soft;
42 public PsiReferenceBase(T element, TextRange range) {
43 this(element);
44 myRange = range;
47 public PsiReferenceBase(T element, boolean soft) {
48 myElement = element;
49 mySoft = soft;
52 public PsiReferenceBase(@NotNull T element) {
53 myElement = element;
54 mySoft = false;
57 public void setRangeInElement(TextRange range) {
58 myRange = range;
61 @NotNull
62 public String getValue() {
63 String text = myElement.getText();
64 final TextRange range = getRangeInElement();
65 if (range.getEndOffset() > text.length() || range.getStartOffset() > text.length() || range.getStartOffset() < 0 || range.getEndOffset() < 0) {
66 LOG.error("Wrong range in reference " + this + ": " + range + ". Reference text: '" + text + "'");
67 return text;
69 return range.substring(text);
73 public T getElement() {
74 return myElement;
77 public TextRange getRangeInElement() {
78 if (myRange == null) {
79 myRange = calculateDefaultRangeInElement();
81 return myRange;
84 protected TextRange calculateDefaultRangeInElement() {
85 final ElementManipulator<T> manipulator = getManipulator();
86 assert manipulator != null: "Cannot find manipulator for " + myElement;
87 return manipulator.getRangeInElement(myElement);
90 public String getCanonicalText() {
91 return getValue();
94 public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException {
95 final ElementManipulator<T> manipulator = getManipulator();
96 assert manipulator != null: "Cannot find manipulator for " + myElement;
97 return manipulator.handleContentChange(myElement, getRangeInElement(), newElementName);
100 public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException {
101 throw new IncorrectOperationException("Rebind cannot be performed for " + getClass());
104 public boolean isReferenceTo(PsiElement element) {
105 return getElement().getManager().areElementsEquivalent(resolve(), element);
108 public static <T extends PsiElement> PsiReferenceBase<T> createSelfReference(T element, final PsiElement resolveTo) {
110 return new PsiReferenceBase<T>(element,true) {
111 //do nothing. the element will be renamed via PsiMetaData (com.intellij.refactoring.rename.RenameUtil.doRenameGenericNamedElement())
112 public PsiElement handleElementRename(final String newElementName) throws IncorrectOperationException {
113 return getElement();
116 @Nullable
117 public PsiElement resolve() {
118 return resolveTo;
121 public Object[] getVariants() {
122 return EMPTY_ARRAY;
127 @Nullable
128 ElementManipulator<T> getManipulator() {
129 return ElementManipulators.getManipulator(myElement);
132 public boolean isSoft() {
133 return mySoft;
136 public static abstract class Poly<T extends PsiElement> extends PsiReferenceBase<T> implements PsiPolyVariantReference {
138 public Poly(final T psiElement) {
139 super(psiElement);
142 public Poly(final T element, final boolean soft) {
143 super(element, soft);
146 public Poly(final T element, final TextRange range, final boolean soft) {
147 super(element, range, soft);
150 public boolean isReferenceTo(PsiElement element) {
151 final ResolveResult[] results = multiResolve(false);
152 for (ResolveResult result : results) {
153 if (element.getManager().areElementsEquivalent(result.getElement(), element)) {
154 return true;
157 return false;
160 @Nullable
161 public PsiElement resolve() {
162 ResolveResult[] resolveResults = multiResolve(false);
163 return resolveResults.length == 1 ? resolveResults[0].getElement() : null;