package com.intellij.lang.javascript.flex.flexunit.inspections;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.lang.ASTNode;
import com.intellij.lang.javascript.flex.FlexBundle;
import com.intellij.lang.javascript.flex.flexunit.FlexUnitSupport;
import com.intellij.lang.javascript.psi.JSFunction;
import com.intellij.lang.javascript.psi.JSRecursiveElementVisitor;
import com.intellij.lang.javascript.psi.JSReturnStatement;
import com.intellij.lang.javascript.psi.JSType;
import com.intellij.lang.javascript.psi.ecmal4.JSClass;
import com.intellij.lang.javascript.psi.types.primitives.JSVoidType;
import com.intellij.lang.javascript.validation.fixes.ChangeTypeFix;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
public class FlexUnitMethodReturnTypeInspection extends FlexUnitMethodInspectionBase {
@Nls
@NotNull
public String getDisplayName() {
return FlexBundle.message("flexunit.inspection.testmethodreturntype.displayname");
}
@NotNull
public String getShortName() {
return "FlexUnitMethodReturnTypeInspection";
}
protected void visitPotentialTestMethod(JSFunction method, ProblemsHolder holder, FlexUnitSupport support) {
if (FlexUnitSupport.getCustomRunner((JSClass)method.getParent()) != null) return;
if (method.getKind() != JSFunction.FunctionKind.SIMPLE) return;
if (support.isFlexUnit1Subclass((JSClass)method.getParent()) || support.isFlunitSubclass((JSClass)method.getParent())) {
return;
}
final JSType returnType = method.getReturnType();
if (returnType != null && !(returnType instanceof JSVoidType)) {
final ASTNode nameIdentifier = method.findNameIdentifier();
if (nameIdentifier != null) {
LocalQuickFix[] fix = canFix(method)
? new LocalQuickFix[]{
new ChangeTypeFix(method, "void", "javascript.fix.set.method.return.type")} : LocalQuickFix.EMPTY_ARRAY;
holder.registerProblem(nameIdentifier.getPsi(), FlexBundle.message("flexunit.inspection.testmethodreturntype.message"),
ProblemHighlightType.GENERIC_ERROR_OR_WARNING, fix);
}
}
}
private static boolean canFix(JSFunction method) {
final NonVoidReturnVisitor visitor = new NonVoidReturnVisitor(method);
method.acceptChildren(visitor);
return !visitor.hasNonVoidReturns();
}
private static class NonVoidReturnVisitor extends JSRecursiveElementVisitor {
private final JSFunction myFunction;
private boolean myHasNonVoidReturns = false;
NonVoidReturnVisitor(JSFunction myFunction) {
this.myFunction = myFunction;
}
@Override
public void visitJSReturnStatement(JSReturnStatement statement) {
super.visitJSReturnStatement(statement);
if (statement.getExpression() != null) {
final JSFunction containingFunction = PsiTreeUtil.getParentOfType(statement, JSFunction.class);
if (myFunction.equals(containingFunction)) {
myHasNonVoidReturns = true;
}
}
}
@Override
public void visitJSFunctionDeclaration(JSFunction function) {
// do nothing, so that it doesn't drill into nested functions
}
public boolean hasNonVoidReturns() {
return myHasNonVoidReturns;
}
}
}