blob: ae2ab543eab9735288406381e524f34bbf5d46e1 [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 com.intellij.psi.impl.light;
import com.intellij.psi.OriginInfoAwareElement;
import com.intellij.lang.Language;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.navigation.ItemPresentation;
import com.intellij.navigation.ItemPresentationProviders;
import com.intellij.openapi.util.Computable;
import com.intellij.psi.*;
import com.intellij.psi.impl.ElementPresentationUtil;
import com.intellij.psi.impl.PsiClassImplUtil;
import com.intellij.psi.impl.PsiImplUtil;
import com.intellij.psi.impl.PsiSuperMethodImplUtil;
import com.intellij.psi.javadoc.PsiDocComment;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.util.MethodSignature;
import com.intellij.psi.util.MethodSignatureBackedByPsiMethod;
import com.intellij.ui.RowIcon;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.PlatformIcons;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.List;
/**
* @author peter
*/
public class LightMethodBuilder extends LightElement implements PsiMethod, OriginInfoAwareElement {
private final String myName;
private Computable<PsiType> myReturnType;
private final PsiModifierList myModifierList;
private final PsiParameterList myParameterList;
private final PsiTypeParameterList myTypeParameterList;
private final PsiReferenceList myThrowsList;
private Icon myBaseIcon;
private PsiClass myContainingClass;
private boolean myConstructor;
private String myMethodKind = "LightMethodBuilder";
private String myOriginInfo = null;
public LightMethodBuilder(PsiClass constructedClass, Language language) {
this(constructedClass.getManager(), language, constructedClass.getName());
setContainingClass(constructedClass);
}
public LightMethodBuilder(PsiManager manager, String name) {
this(manager, JavaLanguage.INSTANCE, name);
}
public LightMethodBuilder(PsiManager manager, Language language, String name) {
this(manager, language, name, new LightParameterListBuilder(manager, language), new LightModifierList(manager, language));
}
public LightMethodBuilder(PsiManager manager,
Language language,
String name,
PsiParameterList parameterList,
PsiModifierList modifierList) {
this(manager, language, name, parameterList, modifierList,
new LightReferenceListBuilder(manager, language, PsiReferenceList.Role.THROWS_LIST),
new LightTypeParameterListBuilder(manager, language));
}
public LightMethodBuilder(PsiManager manager,
Language language,
String name,
PsiParameterList parameterList,
PsiModifierList modifierList,
PsiReferenceList throwsList,
PsiTypeParameterList typeParameterList) {
super(manager, language);
myName = name;
myParameterList = parameterList;
myModifierList = modifierList;
myThrowsList = throwsList;
myTypeParameterList = typeParameterList;
}
@Override
public ItemPresentation getPresentation() {
return ItemPresentationProviders.getItemPresentation(this);
}
@Override
public boolean hasTypeParameters() {
return PsiImplUtil.hasTypeParameters(this);
}
@Override
@NotNull
public PsiTypeParameter[] getTypeParameters() {
return PsiImplUtil.getTypeParameters(this);
}
@Override
public PsiTypeParameterList getTypeParameterList() {
return myTypeParameterList;
}
@Override
public PsiDocComment getDocComment() {
//todo
return null;
}
@Override
public boolean isDeprecated() {
return PsiImplUtil.isDeprecatedByDocTag(this) || PsiImplUtil.isDeprecatedByAnnotation(this);
}
@Override
public PsiElement setName(@NotNull String name) throws IncorrectOperationException {
final String className = myContainingClass == null ? "null" : myContainingClass.getQualifiedName();
throw new UnsupportedOperationException("Please don't rename light methods: writable=" + isWritable() +
"; class=" + getClass() +
"; name=" + getName() +
"; inClass=" + className);
}
@Override
@NotNull
public String getName() {
return myName;
}
@Override
@NotNull
public HierarchicalMethodSignature getHierarchicalMethodSignature() {
return PsiSuperMethodImplUtil.getHierarchicalMethodSignature(this);
}
@Override
public boolean hasModifierProperty(@NotNull String name) {
return getModifierList().hasModifierProperty(name);
}
@Override
@NotNull
public PsiModifierList getModifierList() {
return myModifierList;
}
public LightMethodBuilder addModifiers(String... modifiers) {
for (String modifier : modifiers) {
addModifier(modifier);
}
return this;
}
public LightMethodBuilder addModifier(String modifier) {
((LightModifierList)myModifierList).addModifier(modifier);
return this;
}
public LightMethodBuilder setModifiers(String... modifiers) {
((LightModifierList)myModifierList).clearModifiers();
addModifiers(modifiers);
return this;
}
@Override
public PsiType getReturnType() {
return myReturnType == null ? null : myReturnType.compute();
}
public LightMethodBuilder setMethodReturnType(Computable<PsiType> returnType) {
myReturnType = returnType;
return this;
}
public LightMethodBuilder setMethodReturnType(PsiType returnType) {
return setMethodReturnType(new Computable.PredefinedValueComputable<PsiType>(returnType));
}
public LightMethodBuilder setMethodReturnType(@NotNull final String returnType) {
return setMethodReturnType(new Computable.NotNullCachedComputable<PsiType>() {
@NotNull
@Override
protected PsiType internalCompute() {
return JavaPsiFacade.getInstance(myManager.getProject()).getElementFactory().createTypeByFQClassName(returnType, getResolveScope());
}
});
}
@Override
public PsiTypeElement getReturnTypeElement() {
return null;
}
@Override
@NotNull
public PsiParameterList getParameterList() {
return myParameterList;
}
public LightMethodBuilder addParameter(@NotNull PsiParameter parameter) {
((LightParameterListBuilder)myParameterList).addParameter(parameter);
return this;
}
public LightMethodBuilder addParameter(@NotNull String name, @NotNull String type) {
return addParameter(name, JavaPsiFacade.getElementFactory(getProject()).createTypeFromText(type, this));
}
public LightMethodBuilder addParameter(@NotNull String name, @NotNull PsiType type) {
return addParameter(new LightParameter(name, type, this, JavaLanguage.INSTANCE));
}
public LightMethodBuilder addParameter(@NotNull String name, @NotNull PsiType type, boolean isVarArgs) {
if (isVarArgs && !(type instanceof PsiEllipsisType)) {
type = new PsiEllipsisType(type);
}
return addParameter(new LightParameter(name, type, this, JavaLanguage.INSTANCE, isVarArgs));
}
public LightMethodBuilder addException(PsiClassType type) {
((LightReferenceListBuilder)myThrowsList).addReference(type);
return this;
}
public LightMethodBuilder addException(String fqName) {
((LightReferenceListBuilder)myThrowsList).addReference(fqName);
return this;
}
@Override
@NotNull
public PsiReferenceList getThrowsList() {
return myThrowsList;
}
@Override
public PsiCodeBlock getBody() {
return null;
}
public LightMethodBuilder setConstructor(boolean constructor) {
myConstructor = constructor;
return this;
}
@Override
public boolean isConstructor() {
return myConstructor;
}
@Override
public boolean isVarArgs() {
return PsiImplUtil.isVarArgs(this);
}
@Override
@NotNull
public MethodSignature getSignature(@NotNull PsiSubstitutor substitutor) {
return MethodSignatureBackedByPsiMethod.create(this, substitutor);
}
@Override
public PsiIdentifier getNameIdentifier() {
return null;
}
@Override
@NotNull
public PsiMethod[] findSuperMethods() {
return PsiSuperMethodImplUtil.findSuperMethods(this);
}
@Override
@NotNull
public PsiMethod[] findSuperMethods(boolean checkAccess) {
return PsiSuperMethodImplUtil.findSuperMethods(this, checkAccess);
}
@Override
@NotNull
public PsiMethod[] findSuperMethods(PsiClass parentClass) {
return PsiSuperMethodImplUtil.findSuperMethods(this, parentClass);
}
@Override
@NotNull
public List<MethodSignatureBackedByPsiMethod> findSuperMethodSignaturesIncludingStatic(boolean checkAccess) {
return PsiSuperMethodImplUtil.findSuperMethodSignaturesIncludingStatic(this, checkAccess);
}
@Override
public PsiMethod findDeepestSuperMethod() {
return PsiSuperMethodImplUtil.findDeepestSuperMethod(this);
}
@Override
@NotNull
public PsiMethod[] findDeepestSuperMethods() {
return PsiSuperMethodImplUtil.findDeepestSuperMethods(this);
}
@Override
public void accept(@NotNull PsiElementVisitor visitor) {
if (visitor instanceof JavaElementVisitor) {
((JavaElementVisitor)visitor).visitMethod(this);
}
}
@Override
public PsiClass getContainingClass() {
return myContainingClass;
}
public LightMethodBuilder setContainingClass(PsiClass containingClass) {
myContainingClass = containingClass;
return this;
}
public LightMethodBuilder setMethodKind(String debugKindName) {
myMethodKind = debugKindName;
return this;
}
public String toString() {
return myMethodKind + ":" + getName();
}
@Override
public Icon getElementIcon(final int flags) {
Icon methodIcon = myBaseIcon != null ? myBaseIcon :
hasModifierProperty(PsiModifier.ABSTRACT) ? PlatformIcons.ABSTRACT_METHOD_ICON : PlatformIcons.METHOD_ICON;
RowIcon baseIcon = ElementPresentationUtil.createLayeredIcon(methodIcon, this, false);
return ElementPresentationUtil.addVisibilityIcon(this, flags, baseIcon);
}
@Override
protected boolean isVisibilitySupported() {
return true;
}
public LightMethodBuilder setBaseIcon(Icon baseIcon) {
myBaseIcon = baseIcon;
return this;
}
@Override
public boolean isEquivalentTo(final PsiElement another) {
return PsiClassImplUtil.isMethodEquivalentTo(this, another);
}
@Override
@NotNull
public SearchScope getUseScope() {
return PsiImplUtil.getMemberUseScope(this);
}
@Nullable
@Override
public PsiFile getContainingFile() {
final PsiClass containingClass = getContainingClass();
return containingClass == null ? null : containingClass.getContainingFile();
}
@Override
public PsiElement getContext() {
final PsiElement navElement = getNavigationElement();
if (navElement != this) {
return navElement;
}
final PsiClass cls = getContainingClass();
if (cls != null) {
return cls;
}
return getContainingFile();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LightMethodBuilder that = (LightMethodBuilder)o;
if (myConstructor != that.myConstructor) return false;
if (myBaseIcon != null ? !myBaseIcon.equals(that.myBaseIcon) : that.myBaseIcon != null) return false;
if (myContainingClass != null ? !myContainingClass.equals(that.myContainingClass) : that.myContainingClass != null) return false;
if (!myMethodKind.equals(that.myMethodKind)) return false;
if (!myModifierList.equals(that.myModifierList)) return false;
if (!myName.equals(that.myName)) return false;
if (!myParameterList.equals(that.myParameterList)) return false;
if (myReturnType != null ? !myReturnType.equals(that.myReturnType) : that.myReturnType != null) return false;
return true;
}
@Override
public int hashCode() {
int result = myName.hashCode();
result = 31 * result + (myReturnType != null ? myReturnType.hashCode() : 0);
result = 31 * result + myModifierList.hashCode();
result = 31 * result + myParameterList.hashCode();
result = 31 * result + (myBaseIcon != null ? myBaseIcon.hashCode() : 0);
result = 31 * result + (myContainingClass != null ? myContainingClass.hashCode() : 0);
result = 31 * result + (myConstructor ? 1 : 0);
result = 31 * result + myMethodKind.hashCode();
return result;
}
public LightMethodBuilder addTypeParameter(PsiTypeParameter parameter) {
((LightTypeParameterListBuilder)myTypeParameterList).addParameter(new LightTypeParameter(parameter));
return this;
}
@Nullable
@Override
public String getOriginInfo() {
return myOriginInfo;
}
public void setOriginInfo(@Nullable String originInfo) {
myOriginInfo = originInfo;
}
}