blob: 26e0652ef7fd9a44317d272a1cc71ded12fe88ac [file] [log] [blame]
/*
* Copyright 2000-2014 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 org.jetbrains.plugins.groovy.lang.psi.impl.statements;
import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.psi.*;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.ResolveScopeManager;
import com.intellij.psi.presentation.java.JavaPresentationUtil;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.stubs.IStubElementType;
import com.intellij.psi.util.CachedValueProvider;
import com.intellij.psi.util.CachedValuesManager;
import com.intellij.psi.util.PsiModificationTracker;
import com.intellij.ui.LayeredIcon;
import com.intellij.util.Function;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.containers.ContainerUtil;
import icons.JetgroovyIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.groovy.extensions.NamedArgumentDescriptor;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.api.GrDocComment;
import org.jetbrains.plugins.groovy.lang.groovydoc.psi.impl.GrDocCommentUtil;
import org.jetbrains.plugins.groovy.lang.lexer.GroovyTokenTypes;
import org.jetbrains.plugins.groovy.lang.parser.GroovyElementTypes;
import org.jetbrains.plugins.groovy.lang.psi.GroovyElementVisitor;
import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase;
import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElementFactory;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrField;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrNamedArgumentSearchVisitor;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrExpression;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.GrTypeDefinitionBody;
import org.jetbrains.plugins.groovy.lang.psi.api.statements.typedef.members.GrAccessorMethod;
import org.jetbrains.plugins.groovy.lang.psi.api.types.GrTypeElement;
import org.jetbrains.plugins.groovy.lang.psi.dataFlow.types.TypeInferenceHelper;
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GrAccessorMethodImpl;
import org.jetbrains.plugins.groovy.lang.psi.stubs.GrFieldStub;
import org.jetbrains.plugins.groovy.lang.psi.typeEnhancers.GrVariableEnhancer;
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil;
import javax.swing.*;
import java.util.Collections;
import java.util.Map;
/**
* User: Dmitry.Krasilschikov
* Date: 25.05.2007
*/
public class GrFieldImpl extends GrVariableBaseImpl<GrFieldStub> implements GrField, StubBasedPsiElement<GrFieldStub> {
public GrFieldImpl(@NotNull ASTNode node) {
super(node);
}
public GrFieldImpl(GrFieldStub stub) {
this(stub, GroovyElementTypes.FIELD);
}
public GrFieldImpl(GrFieldStub stub, IStubElementType nodeType) {
super(stub, nodeType);
}
@Override
public PsiElement getParent() {
return getParentByStub();
}
@Override
public void accept(GroovyElementVisitor visitor) {
visitor.visitField(this);
}
@Override
public GrTypeElement getTypeElementGroovy() {
final GrFieldStub stub = getStub();
if (stub != null) {
final String typeText = stub.getTypeText();
if (typeText == null) {
return null;
}
return GroovyPsiElementFactory.getInstance(getProject()).createTypeElement(typeText, this);
}
return super.getTypeElementGroovy();
}
public String toString() {
return "Field";
}
@Override
public PsiExpression getInitializer() {
return org.jetbrains.plugins.groovy.lang.psi.impl.PsiImplUtil.getOrCreatePisExpression(getInitializerGroovy());
}
@Override
public void setInitializer(@Nullable PsiExpression psiExpression) throws IncorrectOperationException {
GrExpression oldInitializer = getInitializerGroovy();
if (psiExpression == null) {
if (oldInitializer != null) {
oldInitializer.delete();
PsiElement assign = findChildByType(GroovyTokenTypes.mASSIGN);
if (assign != null) {
assign.delete();
}
}
return;
}
GrExpression newInitializer = GroovyPsiElementFactory.getInstance(getProject()).createExpressionFromText(psiExpression.getText());
if (oldInitializer != null) {
oldInitializer.replaceWithExpression(newInitializer, true);
}
else {
getNode().addLeaf(GroovyTokenTypes.mASSIGN, "=", getNode().getLastChildNode());
addAfter(newInitializer, getLastChild());
}
}
@Override
public boolean isDeprecated() {
final GrFieldStub stub = getStub();
if (stub != null) {
return stub.isDeprecatedByDocTag() || PsiImplUtil.isDeprecatedByAnnotation(this);
}
return PsiImplUtil.isDeprecatedByDocTag(this) || PsiImplUtil.isDeprecatedByAnnotation(this);
}
@Override
public PsiType getTypeGroovy() {
PsiType type = TypeInferenceHelper.getCurrentContext().getExpressionType(this, new Function<GrFieldImpl, PsiType>() {
@Override
public PsiType fun(GrFieldImpl field) {
if (getDeclaredType() == null && getInitializerGroovy() == null) {
final PsiType type = GrVariableEnhancer.getEnhancedType(field);
if (type != null) {
return type;
}
}
return null;
}
});
if (type != null) {
return type;
}
return super.getTypeGroovy();
}
@Override
public PsiClass getContainingClass() {
PsiElement parent = getParent().getParent();
if (parent instanceof GrTypeDefinitionBody) {
final PsiElement pparent = parent.getParent();
if (pparent instanceof PsiClass) {
return (PsiClass)pparent;
}
}
final PsiFile file = getContainingFile();
if (file instanceof GroovyFileBase) {
return ((GroovyFileBase)file).getScriptClass();
}
return null;
}
@Override
public boolean isProperty() {
final GrFieldStub stub = getStub();
if (stub != null) {
return stub.isProperty();
}
return PsiUtil.isProperty(this);
}
@Override
public GrAccessorMethod getSetter() {
return CachedValuesManager.getCachedValue(this, new CachedValueProvider<GrAccessorMethod>() {
@Nullable
@Override
public Result<GrAccessorMethod> compute() {
return Result.create(GrAccessorMethodImpl.createSetterMethod(GrFieldImpl.this), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
}
});
}
@Override
@NotNull
public GrAccessorMethod[] getGetters() {
return CachedValuesManager.getCachedValue(this, new CachedValueProvider<GrAccessorMethod[]>() {
@Nullable
@Override
public Result<GrAccessorMethod[]> compute() {
return Result.create(GrAccessorMethodImpl.createGetterMethods(GrFieldImpl.this), PsiModificationTracker.OUT_OF_CODE_BLOCK_MODIFICATION_COUNT);
}
});
}
@Override
@NotNull
public SearchScope getUseScope() {
if (isProperty()) {
return ResolveScopeManager.getElementUseScope(this); //maximal scope
}
return PsiImplUtil.getMemberUseScope(this);
}
@NotNull
@Override
public String getName() {
final GrFieldStub stub = getStub();
if (stub != null) {
return stub.getName();
}
return super.getName();
}
@Override
public ItemPresentation getPresentation() {
return JavaPresentationUtil.getFieldPresentation(this);
}
@Override
public PsiElement getOriginalElement() {
final PsiClass containingClass = getContainingClass();
if (containingClass == null) return this;
PsiClass originalClass = (PsiClass)containingClass.getOriginalElement();
PsiField originalField = originalClass.findFieldByName(getName(), false);
return originalField != null ? originalField : this;
}
@Nullable
@Override
protected Icon getElementIcon(@IconFlags int flags) {
Icon superIcon = JetgroovyIcons.Groovy.Field;
if (!isProperty()) return superIcon;
LayeredIcon rowIcon = new LayeredIcon(2);
rowIcon.setIcon(superIcon, 0);
rowIcon.setIcon(JetgroovyIcons.Groovy.Def, 1);
return rowIcon;
}
@Override
@NotNull
public Map<String, NamedArgumentDescriptor> getNamedParameters() {
final GrFieldStub stub = getStub();
if (stub != null) {
String[] namedParameters = stub.getNamedParameters();
if (namedParameters.length == 0) return Collections.emptyMap();
Map<String, NamedArgumentDescriptor> result = ContainerUtil.newHashMap();
for (String parameter : namedParameters) {
result.put(parameter, GrNamedArgumentSearchVisitor.CODE_NAMED_ARGUMENTS_DESCR);
}
return result;
}
return GrNamedArgumentSearchVisitor.find(this);
}
@Override
public GrDocComment getDocComment() {
return GrDocCommentUtil.findDocComment(this);
}
}