package de.plushnikov.intellij.plugin.inspection;
import com.intellij.codeInsight.daemon.GroupNames;
import com.intellij.codeInspection.BaseJavaLocalInspectionTool;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.JavaElementVisitor;
import com.intellij.psi.JavaResolveResult;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiExpressionList;
import com.intellij.psi.PsiKeyword;
import com.intellij.psi.PsiLocalVariable;
import com.intellij.psi.PsiMethodCallExpression;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiReferenceExpression;
import de.plushnikov.intellij.plugin.problem.LombokProblem;
import de.plushnikov.intellij.plugin.processor.Processor;
import de.plushnikov.intellij.plugin.processor.ValProcessor;
import de.plushnikov.intellij.plugin.provider.LombokProcessorProvider;
import de.plushnikov.intellij.plugin.psi.LombokLightMethodBuilder;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
import java.util.HashSet;
/**
* @author Plushnikov Michail
*/
public class LombokInspection extends BaseJavaLocalInspectionTool {
private final ValProcessor valProcessor;
public LombokInspection() {
valProcessor = new ValProcessor();
}
@NotNull
@Override
public String getDisplayName() {
return "Lombok annotations inspection";
}
@NotNull
@Override
public String getGroupDisplayName() {
return GroupNames.BUGS_GROUP_NAME;
}
@NotNull
@Override
public String getShortName() {
return "Lombok";
}
@Override
public boolean isEnabledByDefault() {
return true;
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
return new LombokElementVisitor(holder);
}
private class LombokElementVisitor extends JavaElementVisitor {
private final ProblemsHolder holder;
public LombokElementVisitor(ProblemsHolder holder) {
this.holder = holder;
}
@Override
public void visitLocalVariable(PsiLocalVariable variable) {
super.visitLocalVariable(variable);
valProcessor.verifyVariable(variable, holder);
}
@Override
public void visitParameter(PsiParameter parameter) {
super.visitParameter(parameter);
valProcessor.verifyParameter(parameter, holder);
}
@Override
public void visitAnnotation(PsiAnnotation annotation) {
super.visitAnnotation(annotation);
final Collection<LombokProblem> problems = new HashSet<LombokProblem>();
final LombokProcessorProvider processorProvider = LombokProcessorProvider.getInstance(annotation.getProject());
for (Processor inspector : processorProvider.getProcessors(annotation)) {
problems.addAll(inspector.verifyAnnotation(annotation));
}
for (LombokProblem problem : problems) {
holder.registerProblem(annotation, problem.getMessage(), problem.getHighlightType(), problem.getQuickFixes());
}
}
/**
* Check MethodCallExpressions for calls for default (argument less) constructor
* Produce an error if resolved constructor method is build by lombok and contains some arguments
*/
@Override
public void visitMethodCallExpression(PsiMethodCallExpression methodCall) {
super.visitMethodCallExpression(methodCall);
PsiExpressionList list = methodCall.getArgumentList();
PsiReferenceExpression referenceToMethod = methodCall.getMethodExpression();
boolean isThisOrSuper = referenceToMethod.getReferenceNameElement() instanceof PsiKeyword;
final int parameterCount = list.getExpressions().length;
if (isThisOrSuper && parameterCount == 0) {
JavaResolveResult[] results = referenceToMethod.multiResolve(true);
JavaResolveResult resolveResult = results.length == 1 ? results[0] : JavaResolveResult.EMPTY;
PsiElement resolved = resolveResult.getElement();
if (resolved instanceof LombokLightMethodBuilder && ((LombokLightMethodBuilder) resolved).getParameterList().getParameters().length != 0) {
holder.registerProblem(methodCall, "Default constructor doesn't exist", ProblemHighlightType.ERROR);
}
}
}
}
}