2 * Copyright 2000-2014 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.compiled;
18 import com.intellij.openapi.project.DumbService;
19 import com.intellij.openapi.roots.FileIndexFacade;
20 import com.intellij.openapi.util.AtomicNotNullLazyValue;
21 import com.intellij.openapi.util.NotNullLazyValue;
22 import com.intellij.psi.*;
23 import com.intellij.psi.codeStyle.JavaCodeStyleManager;
24 import com.intellij.psi.impl.ElementPresentationUtil;
25 import com.intellij.psi.impl.cache.TypeInfo;
26 import com.intellij.psi.impl.java.stubs.JavaStubElementTypes;
27 import com.intellij.psi.impl.java.stubs.PsiParameterStub;
28 import com.intellij.psi.impl.java.stubs.impl.PsiParameterStubImpl;
29 import com.intellij.psi.impl.source.SourceTreeToPsiMap;
30 import com.intellij.psi.impl.source.tree.TreeElement;
31 import com.intellij.psi.search.LocalSearchScope;
32 import com.intellij.psi.search.SearchScope;
33 import com.intellij.psi.stubs.StubElement;
34 import com.intellij.psi.util.CachedValueProvider;
35 import com.intellij.psi.util.CachedValuesManager;
36 import com.intellij.ui.RowIcon;
37 import com.intellij.util.IncorrectOperationException;
38 import com.intellij.util.PlatformIcons;
39 import org.jetbrains.annotations.NotNull;
40 import org.jetbrains.annotations.Nullable;
44 public class ClsParameterImpl extends ClsRepositoryPsiElement<PsiParameterStub> implements PsiParameter {
45 private final NotNullLazyValue<PsiTypeElement> myType;
46 private volatile String myName;
47 private volatile String myMirrorName;
49 public ClsParameterImpl(@NotNull PsiParameterStub stub) {
51 myType = new AtomicNotNullLazyValue<PsiTypeElement>() {
54 protected PsiTypeElement compute() {
55 PsiParameterStub stub = getStub();
56 String typeText = TypeInfo.createTypeText(stub.getType(false));
57 assert typeText != null : stub;
58 return new ClsTypeElementImpl(ClsParameterImpl.this, typeText, ClsTypeElementImpl.VARIANCE_NONE);
64 public PsiIdentifier getNameIdentifier() {
69 public String getName() {
70 return CachedValuesManager.getCachedValue(this, new CachedValueProvider<String>() {
73 public Result<String> compute() {
74 return Result.create(calcName(),
76 getContainingFile().getNavigationElement(),
77 FileIndexFacade.getInstance(getProject()).getRootModificationTracker());
83 private String calcName() {
84 PsiParameterStubImpl parameterStub = (PsiParameterStubImpl)getStub();
85 if (!parameterStub.isAutoGeneratedName()) {
86 return parameterStub.getName();
89 if (DumbService.getInstance(getProject()).isDumb()) {
93 ClsMethodImpl method = (ClsMethodImpl)getDeclarationScope();
94 PsiMethod sourceMethod = method.getSourceMirrorMethod();
95 if (sourceMethod != null) {
96 assert sourceMethod != method : method;
97 return sourceMethod.getParameterList().getParameters()[getIndex()].getName();
100 return getMirrorName();
103 public boolean isAutoGeneratedName() {
104 return ((PsiParameterStubImpl)getStub()).isAutoGeneratedName() &&
105 !DumbService.getInstance(getProject()).isDumb() &&
106 ((ClsMethodImpl)getDeclarationScope()).getSourceMirrorMethod() == null;
110 public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
111 throw new IncorrectOperationException(CAN_NOT_MODIFY_MESSAGE);
116 public PsiTypeElement getTypeElement() {
117 return myType.getValue();
122 public PsiType getType() {
123 return getTypeElement().getType();
128 public PsiModifierList getModifierList() {
129 final StubElement<PsiModifierList> child = getStub().findChildStubByType(JavaStubElementTypes.MODIFIER_LIST);
130 assert child != null;
131 return child.getPsi();
135 public boolean hasModifierProperty(@NotNull String name) {
136 return getModifierList().hasModifierProperty(name);
140 public PsiExpression getInitializer() {
145 public boolean hasInitializer() {
150 public Object computeConstantValue() {
155 public void normalizeDeclaration() throws IncorrectOperationException {
159 public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) {
160 PsiAnnotation[] annotations = getModifierList().getAnnotations();
161 for (PsiAnnotation annotation : annotations) {
162 appendText(annotation, indentLevel, buffer);
165 appendText(getTypeElement(), indentLevel, buffer, " ");
166 buffer.append(getMirrorName());
169 private String getMirrorName() {
170 String mirrorName = myMirrorName;
171 if (mirrorName == null) {
172 // parameter name may depend on a name of a previous one in a same parameter list
173 synchronized (getParent()) {
174 mirrorName = myMirrorName;
175 if (mirrorName == null) {
176 myMirrorName = mirrorName = calcNiceParameterName();
183 private String calcNiceParameterName() {
186 PsiParameterStubImpl stub = (PsiParameterStubImpl)getStub();
187 if (!stub.isAutoGeneratedName() || DumbService.getInstance(getProject()).isDumb()) {
188 name = stub.getName();
194 JavaCodeStyleManager codeStyleManager = JavaCodeStyleManager.getInstance(getProject());
195 String[] nameSuggestions = codeStyleManager.suggestCompiledParameterName(getType()).names;
196 if (nameSuggestions.length > 0 && nameSuggestions[0] != null) {
197 name = nameSuggestions[0];
204 for (PsiParameter parameter : ((PsiParameterList)getParent()).getParameters()) {
205 if (parameter == this) break AttemptsLoop;
206 String prevName = ((ClsParameterImpl)parameter).getMirrorName();
207 if (name.equals(prevName)) {
209 continue AttemptsLoop;
219 public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException {
220 setMirrorCheckingType(element, null);
222 PsiParameter mirror = SourceTreeToPsiMap.treeToPsiNotNull(element);
223 setMirror(getModifierList(), mirror.getModifierList());
224 setMirror(getTypeElement(), mirror.getTypeElement());
228 public void accept(@NotNull PsiElementVisitor visitor) {
229 if (visitor instanceof JavaElementVisitor) {
230 ((JavaElementVisitor)visitor).visitParameter(this);
233 visitor.visitElement(this);
239 public PsiElement getDeclarationScope() {
240 // only method parameters exist in compiled code
241 return getParent().getParent();
244 private int getIndex() {
245 final PsiParameterStub stub = getStub();
246 return stub.getParentStub().getChildrenStubs().indexOf(stub);
250 public boolean isVarArgs() {
251 final PsiParameterList paramList = (PsiParameterList)getParent();
252 final PsiMethod method = (PsiMethod)paramList.getParent();
253 return method.isVarArgs() && getIndex() == paramList.getParametersCount() - 1;
257 protected boolean isVisibilitySupported() {
262 public Icon getElementIcon(final int flags) {
263 final RowIcon baseIcon = createLayeredIcon(this, PlatformIcons.PARAMETER_ICON, 0);
264 return ElementPresentationUtil.addVisibilityIcon(this, flags, baseIcon);
269 public SearchScope getUseScope() {
270 return new LocalSearchScope(getDeclarationScope());
274 public String toString() {
275 return "PsiParameter";