package com.nvlad.yii2support.views.inspections;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.util.ArrayUtil;
import com.jetbrains.php.lang.inspections.PhpInspection;
import com.jetbrains.php.lang.psi.elements.ArrayCreationExpression;
import com.jetbrains.php.lang.psi.elements.FunctionReference;
import com.jetbrains.php.lang.psi.elements.MethodReference;
import com.jetbrains.php.lang.psi.elements.StringLiteralExpression;
import com.jetbrains.php.lang.psi.visitors.PhpElementVisitor;
import com.nvlad.yii2support.common.PhpUtil;
import com.nvlad.yii2support.views.ViewsUtil;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
/**
* Created by NVlad on 23.01.2017.
*/
public class RequireParameterInspection extends PhpInspection {
@NotNull
@Override
public String getShortName() {
return "RequireParameterInspection";
}
@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean isOnTheFly) {
return new PhpElementVisitor() {
@Override
public void visitPhpMethodReference(MethodReference reference) {
if (!ViewsUtil.isValidRenderMethod(reference)) {
return;
}
final String name = reference.getName();
if (name == null || !ArrayUtil.contains(name, ViewsUtil.renderMethods)) {
return;
}
final PsiElement[] parameters = reference.getParameters();
if (parameters.length == 0 || !(parameters[0] instanceof StringLiteralExpression)) {
return;
}
final PsiFile file = ViewsUtil.getViewFile(parameters[0]);
if (file == null) {
return;
}
final ArrayList<String> viewParameters = ViewsUtil.getViewVariables(file);
if (viewParameters.size() > 0) {
final Collection<String> existKeys;
if (parameters.length > 1) {
if (parameters[1] instanceof ArrayCreationExpression) {
existKeys = PhpUtil.getArrayKeys((ArrayCreationExpression) parameters[1]);
} else if (parameters[1] instanceof FunctionReference) {
FunctionReference function = (FunctionReference) parameters[1];
if (function.getName() != null && function.getName().equals("compact")) {
existKeys = new HashSet<>();
for (PsiElement element : function.getParameters()) {
if (element instanceof StringLiteralExpression) {
existKeys.add(((StringLiteralExpression) element).getContents());
}
}
} else {
return;
}
} else {
return;
}
} else {
existKeys = new HashSet<>();
}
if (existKeys.size() == 0 && isOnTheFly) {
String errorRequireParameters = "View %view% require parameters.";
RequireParameterLocalQuickFix fix = new RequireParameterLocalQuickFix(viewParameters);
problemsHolder.registerProblem(reference, errorRequireParameters.replace("%view%", parameters[0].getText()), fix);
return;
}
viewParameters.removeIf(existKeys::contains);
if (viewParameters.size() > 0) {
String errorRequireParameter = "View %view% require %parameter% parameter";
for (String parameter : viewParameters) {
RequireParameterLocalQuickFix fix = new RequireParameterLocalQuickFix(viewParameters);
String description = errorRequireParameter
.replace("%view%", parameters[0].getText())
.replace("%parameter%", parameter);
problemsHolder.registerProblem(reference, description, fix);
}
}
}
}
};
}
}