package com.google.jstestdriver.idea.assertFramework.support;
import com.google.jstestdriver.idea.execution.JstdSettingsUtil;
import com.google.jstestdriver.idea.util.JstdResolveUtil;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.javascript.inspections.JSInspection;
import com.intellij.lang.javascript.psi.JSCallExpression;
import com.intellij.lang.javascript.psi.JSElementVisitor;
import com.intellij.lang.javascript.psi.JSFile;
import com.intellij.lang.javascript.psi.JSReferenceExpression;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.util.ObjectUtils;
import org.jetbrains.annotations.NotNull;
public abstract class AbstractMethodBasedInspection extends JSInspection {
@Override
public boolean isEnabledByDefault() {
return false;
}
protected abstract boolean isSuitableElement(@NotNull JSFile jsFile, @NotNull JSCallExpression callExpression);
protected abstract IntentionAction getFix();
protected abstract String getProblemDescription();
@NotNull
@Override
protected final JSElementVisitor createVisitor(final ProblemsHolder holder, LocalInspectionToolSession session) {
if (holder == null) {
return JSElementVisitor.NOP_ELEMENT_VISITOR;
}
Project project = holder.getProject();
if (!ApplicationManager.getApplication().isUnitTestMode()) {
if (!JstdSettingsUtil.areJstdConfigFilesInProjectCached(project)) {
return JSElementVisitor.NOP_ELEMENT_VISITOR;
}
}
return new JSElementVisitor() {
@Override
public void visitJSCallExpression(final JSCallExpression jsCallExpression) {
JSFile jsFile = null;
if (jsCallExpression != null) {
jsFile = ObjectUtils.tryCast(jsCallExpression.getContainingFile(), JSFile.class);
}
if (jsFile == null) {
return;
}
JSReferenceExpression methodExpression = ObjectUtils.tryCast(jsCallExpression.getMethodExpression(), JSReferenceExpression.class);
if (methodExpression == null) {
return;
}
boolean suitableSymbol = isSuitableElement(jsFile, jsCallExpression);
if (suitableSymbol) {
boolean resolved = isResolved(methodExpression);
if (!resolved) {
TextRange rangeInElement = TextRange.create(0, methodExpression.getTextLength());
HintWrapperQuickFix fix = new HintWrapperQuickFix(
methodExpression,
rangeInElement,
getFix()
);
holder.registerProblem(
methodExpression,
getProblemDescription(),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING,
rangeInElement,
fix
);
}
}
}
};
}
protected boolean isResolved(JSReferenceExpression methodExpression) {
return JstdResolveUtil.isResolvedToFunction(methodExpression);
}
}