package gw.plugin.ij.codeInspection.method;
import com.intellij.codeInspection.LocalInspectionToolSession;
import com.intellij.codeInspection.LocalQuickFix;
import com.intellij.codeInspection.ProblemDescriptor;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.codeInspection.ex.BaseLocalInspectionTool;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiElementVisitor;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiType;
import gw.lang.parser.IParseIssue;
import gw.lang.parser.IParsedElement;
import gw.lang.parser.exceptions.ICoercionIssue;
import gw.lang.parser.expressions.IArgumentListClause;
import gw.lang.parser.resources.Res;
import gw.plugin.ij.intentions.GosuAddTypeCastFix;
import gw.plugin.ij.lang.psi.IGosuPsiElement;
import gw.plugin.ij.lang.psi.impl.GosuBaseElementImpl;
import gw.plugin.ij.lang.psi.impl.GosuElementVisitor;
import gw.plugin.ij.lang.psi.impl.expressions.GosuExpressionListImpl;
import gw.plugin.ij.util.GosuBundle;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import java.util.List;
public class GosuAmbiguousMethodCallInspection extends BaseLocalInspectionTool {
@Nls
@NotNull
@Override
public String getGroupDisplayName() {
return GosuBundle.message("inspection.group.name.upgrade.issues");
}
@Nls
@NotNull
@Override
public String getDisplayName() {
return GosuBundle.message( "inspection.ambiguous.call" );
}
@Override
public boolean isEnabledByDefault() {
// Must turn this on explicitly, it's useful just for upgrades
return false;
}
@NotNull
@Override
public String getShortName() {
return "GosuAmbiguousMethodCallInspection";
}
@NotNull
@Override
public PsiElementVisitor buildVisitor( @NotNull final ProblemsHolder holder, boolean isOnTheFly, @NotNull LocalInspectionToolSession session ) {
return new GosuElementVisitor() {
@Override
public void visitExpressionList(GosuExpressionListImpl expressionList) {
IParsedElement pe = expressionList.getParsedElement();
if (pe instanceof IArgumentListClause && pe.getParent().hasParseException(Res.MSG_AMBIGUOUS_METHOD_INVOCATION)) {
final List<IParseIssue> issues = pe.getParseExceptions();
final PsiElement[] children = expressionList.getChildren();
if (issues == null) {
return;
}
for (IParseIssue issue : issues) {
if (issue instanceof ICoercionIssue) {
PsiElement psiElem = findArg(issue, children);
if (psiElem instanceof IGosuPsiElement) {
PsiType type = GosuBaseElementImpl.createType(((ICoercionIssue) issue).getTypeToCoerceTo(), psiElem);
if (type != null) {
holder.registerProblem(psiElem, GosuBundle.message("inspection.ambiguous.call"), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new AmbiguousMethodCallFix(type, (IGosuPsiElement) psiElem));
}
}
}
}
}
}
private PsiElement findArg(IParseIssue issue, PsiElement[] children) {
IParsedElement pe = issue.getSource();
int s = pe.getLocation().getOffset();
int e = pe.getLocation().getExtent() + 1;
for(PsiElement c : children) {
if(c.getTextRange().equalsToRange(s, e)) {
return c;
}
}
return null;
}
};
}
private class AmbiguousMethodCallFix implements LocalQuickFix {
private final GosuAddTypeCastFix _quickFix;
public AmbiguousMethodCallFix(PsiType type, IGosuPsiElement expression) {
_quickFix = new GosuAddTypeCastFix(type, expression);
}
@NotNull
public String getName() {
return _quickFix.getText();
}
@NotNull
public String getFamilyName() {
return GosuBundle.message( "inspection.group.name.upgrade.issues" );
}
public void applyFix( @NotNull Project project, @NotNull ProblemDescriptor descriptor ) {
PsiElement element = descriptor.getPsiElement();
if( element == null ) {
return;
}
final PsiFile psiFile = element.getContainingFile();
if( _quickFix.isAvailable( project, null, psiFile ) ) {
_quickFix.invokeImpl(project, null, psiFile);
}
}
}
}