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
.javadoc
;
18 import com
.intellij
.lang
.ASTNode
;
19 import com
.intellij
.openapi
.util
.TextRange
;
20 import com
.intellij
.psi
.*;
21 import com
.intellij
.psi
.impl
.source
.Constants
;
22 import com
.intellij
.psi
.impl
.source
.tree
.CompositePsiElement
;
23 import com
.intellij
.psi
.impl
.source
.tree
.Factory
;
24 import com
.intellij
.psi
.impl
.source
.tree
.LeafElement
;
25 import com
.intellij
.psi
.impl
.source
.tree
.SharedImplUtil
;
26 import com
.intellij
.psi
.javadoc
.PsiDocTagValue
;
27 import com
.intellij
.psi
.javadoc
.PsiDocToken
;
28 import com
.intellij
.psi
.util
.PsiTreeUtil
;
29 import com
.intellij
.util
.ArrayUtil
;
30 import com
.intellij
.util
.CharTable
;
31 import com
.intellij
.util
.IncorrectOperationException
;
32 import org
.jetbrains
.annotations
.NotNull
;
37 public class PsiDocParamRef
extends CompositePsiElement
implements PsiDocTagValue
{
38 private volatile PsiReference myCachedReference
;
40 public PsiDocParamRef() {
41 super(Constants
.DOC_PARAMETER_REF
);
44 public void clearCaches() {
45 myCachedReference
= null;
49 public PsiReference
getReference() {
50 PsiReference cachedReference
= myCachedReference
;
51 if (cachedReference
!= null) return cachedReference
;
52 final PsiDocCommentOwner owner
= PsiTreeUtil
.getParentOfType(this, PsiDocCommentOwner
.class);
53 if (!(owner
instanceof PsiMethod
) &&
54 !(owner
instanceof PsiClass
)) return null;
55 final ASTNode valueToken
= findChildByType(JavaDocTokenType
.DOC_TAG_VALUE_TOKEN
);
56 if (valueToken
== null) return null;
57 myCachedReference
= cachedReference
= new PsiReference() {
58 public PsiElement
resolve() {
59 String name
= valueToken
.getText();
60 final PsiElement firstChild
= getFirstChild();
61 if (firstChild
instanceof PsiDocToken
&& ((PsiDocToken
)firstChild
).getTokenType().equals(JavaDocTokenType
.DOC_TAG_VALUE_LT
)) {
62 final PsiTypeParameter
[] typeParameters
= ((PsiTypeParameterListOwner
)owner
).getTypeParameters();
63 for (PsiTypeParameter typeParameter
: typeParameters
) {
64 if (typeParameter
.getName().equals(name
)) return typeParameter
;
67 else if (owner
instanceof PsiMethod
) {
68 final PsiParameter
[] parameters
= ((PsiMethod
)owner
).getParameterList().getParameters();
69 for (PsiParameter parameter
: parameters
) {
70 if (parameter
.getName().equals(name
)) return parameter
;
77 public String
getCanonicalText() {
78 return valueToken
.getText();
81 public PsiElement
handleElementRename(String newElementName
) {
82 final CharTable charTableByTree
= SharedImplUtil
.findCharTableByTree(getNode());
83 LeafElement newElement
= Factory
.createSingleLeafElement(JavaDocTokenType
.DOC_TAG_VALUE_TOKEN
, newElementName
, charTableByTree
, getManager());
84 replaceChild(valueToken
, newElement
);
85 return PsiDocParamRef
.this;
88 public PsiElement
bindToElement(@NotNull PsiElement element
) throws IncorrectOperationException
{
89 if (isReferenceTo(element
)) return PsiDocParamRef
.this;
90 if(!(element
instanceof PsiParameter
)) {
91 throw new IncorrectOperationException("Unsupported operation");
93 return handleElementRename(((PsiParameter
) element
).getName());
96 public boolean isReferenceTo(PsiElement element
) {
97 if (!(element
instanceof PsiNamedElement
)) return false;
98 PsiNamedElement namedElement
= (PsiNamedElement
)element
;
99 if (!getCanonicalText().equals(namedElement
.getName())) return false;
100 return getManager().areElementsEquivalent(resolve(), element
);
103 public Object
[] getVariants() {
104 final PsiElement firstChild
= getFirstChild();
105 if (firstChild
instanceof PsiDocToken
&& ((PsiDocToken
)firstChild
).getTokenType().equals(JavaDocTokenType
.DOC_TAG_VALUE_LT
)) {
106 return ((PsiTypeParameterListOwner
)owner
).getTypeParameters();
107 } else if (owner
instanceof PsiMethod
) {
108 return ((PsiMethod
)owner
).getParameterList().getParameters();
110 return ArrayUtil
.EMPTY_OBJECT_ARRAY
;
113 public boolean isSoft(){
117 public TextRange
getRangeInElement() {
118 final int startOffsetInParent
= valueToken
.getPsi().getStartOffsetInParent();
119 return new TextRange(startOffsetInParent
, startOffsetInParent
+ valueToken
.getTextLength());
122 public PsiElement
getElement() {
123 return PsiDocParamRef
.this;
126 return cachedReference
;
129 public void accept(@NotNull PsiElementVisitor visitor
) {
130 if (visitor
instanceof JavaElementVisitor
) {
131 ((JavaElementVisitor
)visitor
).visitDocTagValue(this);
134 visitor
.visitElement(this);