/* * Copyright 2000-2013 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.intellij.psi.impl.compiled; import com.intellij.navigation.ItemPresentation; import com.intellij.navigation.ItemPresentationProviders; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.*; import com.intellij.psi.*; import com.intellij.psi.impl.*; import com.intellij.psi.impl.cache.TypeInfo; import com.intellij.psi.impl.java.stubs.JavaStubElementTypes; import com.intellij.psi.impl.java.stubs.PsiFieldStub; import com.intellij.psi.impl.source.SourceTreeToPsiMap; import com.intellij.psi.impl.source.tree.TreeElement; import com.intellij.psi.search.SearchScope; import com.intellij.util.IncorrectOperationException; import gnu.trove.THashSet; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import javax.swing.*; import java.util.Set; public class ClsFieldImpl extends ClsMemberImpl<PsiFieldStub> implements PsiField, PsiVariableEx, ClsModifierListOwner { private final NotNullLazyValue<PsiTypeElement> myType; private final NullableLazyValue<PsiExpression> myInitializer; public ClsFieldImpl(@NotNull PsiFieldStub stub) { super(stub); myType = new AtomicNotNullLazyValue<PsiTypeElement>() { @NotNull @Override protected PsiTypeElement compute() { PsiFieldStub stub = getStub(); String typeText = TypeInfo.createTypeText(stub.getType(false)); assert typeText != null : stub; return new ClsTypeElementImpl(ClsFieldImpl.this, typeText, ClsTypeElementImpl.VARIANCE_NONE); } }; myInitializer = new VolatileNullableLazyValue<PsiExpression>() { @Nullable @Override protected PsiExpression compute() { String initializerText = getStub().getInitializerText(); return initializerText != null && !Comparing.equal(PsiFieldStub.INITIALIZER_TOO_LONG, initializerText) ? ClsParsingUtil.createExpressionFromText(initializerText, getManager(), ClsFieldImpl.this) : null; } }; } @Override @NotNull public PsiElement[] getChildren() { return getChildren(getDocComment(), getModifierList(), getTypeElement(), getNameIdentifier()); } @Override public PsiClass getContainingClass() { return (PsiClass)getParent(); } @Override @NotNull public PsiType getType() { return getTypeElement().getType(); } @Override @NotNull public PsiTypeElement getTypeElement() { return myType.getValue(); } @Override public PsiModifierList getModifierList() { return getStub().findChildStubByType(JavaStubElementTypes.MODIFIER_LIST).getPsi(); } @Override public boolean hasModifierProperty(@NotNull String name) { return getModifierList().hasModifierProperty(name); } @Override public PsiExpression getInitializer() { return myInitializer.getValue(); } @Override public boolean hasInitializer() { return getInitializer() != null; } @Override public Object computeConstantValue() { return computeConstantValue(new THashSet<PsiVariable>()); } @Override public Object computeConstantValue(Set<PsiVariable> visitedVars) { if (!hasModifierProperty(PsiModifier.FINAL)) return null; PsiExpression initializer = getInitializer(); if (initializer == null) return null; final PsiClass containingClass = getContainingClass(); final String qName = containingClass != null ? containingClass.getQualifiedName() : null; if ("java.lang.Float".equals(qName)) { @NonNls final String name = getName(); if ("POSITIVE_INFINITY".equals(name)) return new Float(Float.POSITIVE_INFINITY); if ("NEGATIVE_INFINITY".equals(name)) return new Float(Float.NEGATIVE_INFINITY); if ("NaN".equals(name)) return new Float(Float.NaN); } else if ("java.lang.Double".equals(qName)) { @NonNls final String name = getName(); if ("POSITIVE_INFINITY".equals(name)) return new Double(Double.POSITIVE_INFINITY); if ("NEGATIVE_INFINITY".equals(name)) return new Double(Double.NEGATIVE_INFINITY); if ("NaN".equals(name)) return new Double(Double.NaN); } return PsiConstantEvaluationHelperImpl.computeCastTo(initializer, getType(), visitedVars); } @Override public boolean isDeprecated() { return getStub().isDeprecated(); } @Override public void normalizeDeclaration() throws IncorrectOperationException { } @Override public void appendMirrorText(int indentLevel, @NotNull StringBuilder buffer) { appendText(getDocComment(), indentLevel, buffer, NEXT_LINE); appendText(getModifierList(), indentLevel, buffer, ""); appendText(getTypeElement(), indentLevel, buffer, " "); appendText(getNameIdentifier(), indentLevel, buffer); PsiExpression initializer = getInitializer(); if (initializer != null) { buffer.append(" = "); buffer.append(initializer.getText()); } buffer.append(';'); } @Override public void setMirror(@NotNull TreeElement element) throws InvalidMirrorException { setMirrorCheckingType(element, null); PsiField mirror = SourceTreeToPsiMap.treeToPsiNotNull(element); setMirrorIfPresent(getDocComment(), mirror.getDocComment()); setMirror(getModifierList(), mirror.getModifierList()); setMirror(getTypeElement(), mirror.getTypeElement()); setMirror(getNameIdentifier(), mirror.getNameIdentifier()); } @Override public void accept(@NotNull PsiElementVisitor visitor) { if (visitor instanceof JavaElementVisitor) { ((JavaElementVisitor)visitor).visitField(this); } else { visitor.visitElement(this); } } @Override @NotNull public PsiElement getNavigationElement() { for (ClsCustomNavigationPolicy customNavigationPolicy : Extensions.getExtensions(ClsCustomNavigationPolicy.EP_NAME)) { PsiElement navigationElement = customNavigationPolicy.getNavigationElement(this); if (navigationElement != null) { return navigationElement; } } PsiClass sourceClassMirror = ((ClsClassImpl)getParent()).getSourceMirrorClass(); PsiElement sourceFieldMirror = sourceClassMirror != null ? sourceClassMirror.findFieldByName(getName(), false) : null; return sourceFieldMirror != null ? sourceFieldMirror.getNavigationElement() : this; } @Override public ItemPresentation getPresentation() { return ItemPresentationProviders.getItemPresentation(this); } @Override public void setInitializer(PsiExpression initializer) throws IncorrectOperationException { throw new IncorrectOperationException(); } @Override public boolean isEquivalentTo(final PsiElement another) { return PsiClassImplUtil.isFieldEquivalentTo(this, another); } @Override @NotNull public SearchScope getUseScope() { return PsiImplUtil.getMemberUseScope(this); } @Override public PsiType getTypeNoResolve() { return getType(); //todo? } @Override protected boolean isVisibilitySupported() { return true; } @Override public String toString() { return "PsiField:" + getName(); } }