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
;
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
) {
42 public PsiReferenceBase(T element
, TextRange range
) {
47 public PsiReferenceBase(T element
, boolean soft
) {
52 public PsiReferenceBase(@NotNull T element
) {
57 public void setRangeInElement(TextRange range
) {
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
+ "'");
69 return range
.substring(text
);
73 public T
getElement() {
77 public TextRange
getRangeInElement() {
78 if (myRange
== null) {
79 myRange
= calculateDefaultRangeInElement();
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() {
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
{
117 public PsiElement
resolve() {
121 public Object
[] getVariants() {
128 ElementManipulator
<T
> getManipulator() {
129 return ElementManipulators
.getManipulator(myElement
);
132 public boolean isSoft() {
136 public static abstract class Poly
<T
extends PsiElement
> extends PsiReferenceBase
<T
> implements PsiPolyVariantReference
{
138 public Poly(final T 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
)) {
161 public PsiElement
resolve() {
162 ResolveResult
[] resolveResults
= multiResolve(false);
163 return resolveResults
.length
== 1 ? resolveResults
[0].getElement() : null;