Honor onTheFly and don't put html in batch mode (PY-25325, PY-27306)

This commit is contained in:
Semyon Proshev
2018-06-18 21:49:26 +03:00
parent 961ef35712
commit 7d25828c73
2 changed files with 64 additions and 21 deletions
@@ -268,7 +268,10 @@ public class PyArgumentListInspection extends PyInspection {
}
else {
// all mappings have unmapped arguments so we couldn't determine desired argument list and suggest appropriate quick fixes
holder.registerProblem(node, addPossibleCalleesRepresentationAndWrapInHtml(PyBundle.message("INSP.unexpected.arg(s)"), mappings, context));
holder.registerProblem(
node,
addPossibleCalleesRepresentation(PyBundle.message("INSP.unexpected.arg(s)"), mappings, context, holder.isOnTheFly())
);
}
}
@@ -288,7 +291,7 @@ public class PyArgumentListInspection extends PyInspection {
ContainerUtil.exists(mappings.get(0).getUnmappedParameters(), parameter -> parameter.getName() == null)) {
holder.registerProblem(
psi,
addPossibleCalleesRepresentationAndWrapInHtml(PyBundle.message("INSP.parameter(s).unfilled"), mappings, context)
addPossibleCalleesRepresentation(PyBundle.message("INSP.parameter(s).unfilled"), mappings, context, holder.isOnTheFly())
);
}
else {
@@ -303,27 +306,43 @@ public class PyArgumentListInspection extends PyInspection {
}
@NotNull
private static String addPossibleCalleesRepresentationAndWrapInHtml(@NotNull String prefix,
@NotNull List<PyCallExpression.PyArgumentsMapping> mappings,
@NotNull TypeEvalContext context) {
final String possibleCalleesRepresentation = XmlStringUtil.escapeString(calculatePossibleCalleesRepresentation(mappings, context));
return XmlStringUtil.wrapInHtml(prefix + "<br>" + PyBundle.message("INSP.possible.callees") + ":<br>" + possibleCalleesRepresentation);
private static String addPossibleCalleesRepresentation(@NotNull String prefix,
@NotNull List<PyCallExpression.PyArgumentsMapping> mappings,
@NotNull TypeEvalContext context,
boolean isOnTheFly) {
final String separator = isOnTheFly ? "<br>" : " ";
final String possibleCalleesRepresentation = calculatePossibleCalleesRepresentation(mappings, context, isOnTheFly);
if (isOnTheFly) {
return XmlStringUtil.wrapInHtml(
prefix + separator +
PyBundle.message("INSP.possible.callees") + ":" + separator +
XmlStringUtil.escapeString(possibleCalleesRepresentation)
);
}
else {
return prefix + "." + separator +
PyBundle.message("INSP.possible.callees") + ":" + separator +
possibleCalleesRepresentation;
}
}
@NotNull
private static String calculatePossibleCalleesRepresentation(@NotNull List<PyCallExpression.PyArgumentsMapping> mappings,
@NotNull TypeEvalContext context) {
@NotNull TypeEvalContext context,
boolean isOnTheFly) {
return StreamEx
.of(mappings)
.map(PyCallExpression.PyArgumentsMapping::getMarkedCallee)
.nonNull()
.map(markedCallee -> calculatePossibleCalleeRepresentation(markedCallee, context))
.nonNull()
.collect(Collectors.joining("<br>"));
.collect(Collectors.joining(isOnTheFly ? "<br>" : " "));
}
@Nullable
private static String calculatePossibleCalleeRepresentation(@NotNull PyCallExpression.PyMarkedCallee markedCallee, @NotNull TypeEvalContext context) {
private static String calculatePossibleCalleeRepresentation(@NotNull PyCallExpression.PyMarkedCallee markedCallee,
@NotNull TypeEvalContext context) {
final String name = markedCallee.getElement() != null ? markedCallee.getElement().getName() : "";
final List<PyCallableParameter> callableParameters = markedCallee.getCallableType().getParameters(context);
if (callableParameters == null) return null;
@@ -17,6 +17,7 @@ package com.jetbrains.python.inspections;
import com.google.common.collect.Sets;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.codeInspection.ProblemsHolder;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.util.ObjectUtils;
@@ -75,7 +76,7 @@ class PyTypeCheckerInspectionProblemRegistrar {
}
else {
visitor.registerProblem(getMultiCalleeElementToHighlight(callSite),
getMultiCalleeProblemMessage(argumentTypes, calleesResults, context),
getMultiCalleeProblemMessage(argumentTypes, calleesResults, context, isOnTheFly(visitor)),
getMultiCalleeHighlightType(calleesResults));
}
}
@@ -143,9 +144,11 @@ class PyTypeCheckerInspectionProblemRegistrar {
registerSingleCalleeProblem(visitor, preferredOperatorsResults.get(0), context);
}
else {
visitor.registerProblem(allCalleesAreRightOperators ? binaryExpression.getLeftExpression() : binaryExpression.getRightExpression(),
getMultiCalleeProblemMessage(argumentTypes, preferredOperatorsResults, context),
getMultiCalleeHighlightType(preferredOperatorsResults));
visitor.registerProblem(
allCalleesAreRightOperators ? binaryExpression.getLeftExpression() : binaryExpression.getRightExpression(),
getMultiCalleeProblemMessage(argumentTypes, preferredOperatorsResults, context, isOnTheFly(visitor)),
getMultiCalleeHighlightType(preferredOperatorsResults)
);
}
}
@@ -175,11 +178,26 @@ class PyTypeCheckerInspectionProblemRegistrar {
@NotNull
private static String getMultiCalleeProblemMessage(@NotNull List<PyType> argumentTypes,
@NotNull List<PyTypeCheckerInspection.AnalyzeCalleeResults> calleesResults,
@NotNull TypeEvalContext context) {
return XmlStringUtil.wrapInHtml("Unexpected type(s):<br>" +
XmlStringUtil.escapeString(getMultiCalleeActualTypesRepresentation(argumentTypes, context)) + "<br>" +
"Possible types:<br>" +
XmlStringUtil.escapeString(getMultiCalleePossibleExpectedTypesRepresentation(calleesResults, context)));
@NotNull TypeEvalContext context,
boolean isOnTheFly) {
final String separator = isOnTheFly ? "<br>" : " ";
final String actualTypesRepresentation = getMultiCalleeActualTypesRepresentation(argumentTypes, context);
final String expectedTypesRepresentation = getMultiCalleePossibleExpectedTypesRepresentation(calleesResults, context, isOnTheFly);
if (isOnTheFly) {
return XmlStringUtil.wrapInHtml(
"Unexpected type(s):" + separator +
XmlStringUtil.escapeString(actualTypesRepresentation) + separator +
"Possible types:" + separator +
XmlStringUtil.escapeString(expectedTypesRepresentation)
);
}
else {
return "Unexpected type(s):" + separator +
actualTypesRepresentation + separator +
"Possible types:" + separator +
expectedTypesRepresentation;
}
}
/**
@@ -197,6 +215,11 @@ class PyTypeCheckerInspectionProblemRegistrar {
return allExpectedTypesWereSubstituted ? ProblemHighlightType.WEAK_WARNING : ProblemHighlightType.GENERIC_ERROR_OR_WARNING;
}
private static boolean isOnTheFly(@NotNull PyInspectionVisitor visitor) {
final ProblemsHolder holder = visitor.getHolder();
return holder != null && holder.isOnTheFly();
}
@Nullable
private static Set<String> getAttributes(@NotNull PyType type, @NotNull TypeEvalContext context) {
if (type instanceof PyStructuralType) {
@@ -231,11 +254,12 @@ class PyTypeCheckerInspectionProblemRegistrar {
@NotNull
private static String getMultiCalleePossibleExpectedTypesRepresentation(@NotNull List<PyTypeCheckerInspection.AnalyzeCalleeResults> calleesResults,
@NotNull TypeEvalContext context) {
@NotNull TypeEvalContext context,
boolean isOnTheFly) {
return calleesResults
.stream()
.map(calleeResult -> getMultiCalleeExpectedTypesRepresentation(calleeResult.getResults(), context))
.collect(Collectors.joining("<br>"));
.collect(Collectors.joining(isOnTheFly ? "<br>" : " "));
}
@NotNull