package de.plushnikov.intellij.lombok.psi;
import com.intellij.lang.ASTNode;
import com.intellij.lang.java.JavaLanguage;
import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.Modifier;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementFactory;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiIdentifier;
import com.intellij.psi.PsiManager;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiType;
import com.intellij.psi.impl.CheckUtil;
import com.intellij.psi.impl.light.LightIdentifier;
import com.intellij.psi.impl.light.LightMethodBuilder;
import com.intellij.psi.impl.light.LightModifierList;
import com.intellij.psi.impl.light.LightParameterListBuilder;
import com.intellij.util.IncorrectOperationException;
import com.intellij.util.StringBuilderSpinAllocator;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
/**
* @author Plushnikov Michail
*/
public class LombokLightMethodBuilder11Impl extends LightMethodBuilder implements LombokLightMethodBuilder {
private final LightIdentifier myNameIdentifier;
private ASTNode myASTNode;
public LombokLightMethodBuilder11Impl(@NotNull PsiManager manager, @NotNull String name) {
super(manager, JavaLanguage.INSTANCE, name,
new LightParameterListBuilder(manager, JavaLanguage.INSTANCE), new LombokLightModifierList11Impl(manager, JavaLanguage.INSTANCE));
myNameIdentifier = new LightIdentifier(manager, name);
}
@Override
public LombokLightMethodBuilder withNavigationElement(PsiElement navigationElement) {
setNavigationElement(navigationElement);
return this;
}
@Override
public LombokLightMethodBuilder withModifier(@Modifier @NotNull @NonNls String modifier) {
addModifier(modifier);
return this;
}
@Override
public LombokLightMethodBuilder withMethodReturnType(PsiType returnType) {
setMethodReturnType(returnType);
return this;
}
@Override
public LombokLightMethodBuilder withParameter(@NotNull String name, @NotNull PsiType type) {
addParameter(new LombokLightParameter11Impl(name, type, this, JavaLanguage.INSTANCE));
return this;
}
@Override
public LombokLightMethodBuilder withException(@NotNull PsiClassType type) {
addException(type);
return this;
}
@Override
public LombokLightMethodBuilder withException(@NotNull String fqName) {
addException(fqName);
return this;
}
@Override
public LombokLightMethodBuilder withContainingClass(@NotNull PsiClass containingClass) {
setContainingClass(containingClass);
return this;
}
@Override
public PsiIdentifier getNameIdentifier() {
return myNameIdentifier;
}
@Override
public PsiElement getParent() {
PsiElement result = super.getParent();
result = null != result ? result : getContainingClass();
return result;
}
@Nullable
@Override
public PsiFile getContainingFile() {
PsiClass containingClass = getContainingClass();
return containingClass != null ? containingClass.getContainingFile() : null;
}
@Override
public String getText() {
ASTNode node = getNode();
if (null != node) {
return node.getText();
}
return "";
}
@Override
public ASTNode getNode() {
if (null == myASTNode) {
myASTNode = rebuildMethodFromString().getNode();
}
return myASTNode;
}
private PsiMethod rebuildMethodFromString() {
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
try {
builder.append(getAllModifierProperties((LightModifierList) getModifierList()));
PsiType returnType = getReturnType();
if (null != returnType) {
builder.append(returnType.getCanonicalText()).append(' ');
}
builder.append(getName());
builder.append('(');
if (getParameterList().getParametersCount() > 0) {
for (PsiParameter parameter : getParameterList().getParameters()) {
builder.append(parameter.getType().getCanonicalText()).append(' ').append(parameter.getName()).append(',');
}
builder.deleteCharAt(builder.length() - 1);
}
builder.append(')');
builder.append('{').append(" ").append('}');
PsiElementFactory elementFactory = JavaPsiFacade.getInstance(getManager().getProject()).getElementFactory();
return elementFactory.createMethodFromText(builder.toString(), getContainingClass());
} finally {
StringBuilderSpinAllocator.dispose(builder);
}
}
public String getAllModifierProperties(LightModifierList modifierList) {
final StringBuilder builder = StringBuilderSpinAllocator.alloc();
try {
for (String modifier : modifierList.getModifiers()) {
if (!PsiModifier.PACKAGE_LOCAL.equals(modifier)) {
builder.append(modifier).append(' ');
}
}
return builder.toString();
} finally {
StringBuilderSpinAllocator.dispose(builder);
}
}
public PsiElement copy() {
return rebuildMethodFromString();
}
public String toString() {
return "LombokLightMethodBuilder: " + getName();
}
@Override
public PsiElement replace(@NotNull PsiElement newElement) throws IncorrectOperationException {
// just add new element to the containing class
final PsiClass containingClass = getContainingClass();
if (null != containingClass) {
CheckUtil.checkWritable(containingClass);
return containingClass.add(newElement);
}
return null;
}
@Override
public void delete() throws IncorrectOperationException {
// simple do nothing
}
@Override
public void checkDelete() throws IncorrectOperationException {
// simple do nothing
}
}