Ability to filter types in parameter presentable text (PY-26582)

This commit is contained in:
Semyon Proshev
2017-12-04 19:28:50 +03:00
parent bd44fd5faa
commit 89a9b2c4ca
5 changed files with 49 additions and 5 deletions
@@ -6,6 +6,8 @@ import com.jetbrains.python.psi.PyParameter;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.function.Predicate;
/**
* @author vlan
*/
@@ -70,6 +72,20 @@ public interface PyCallableParameter {
@NotNull
String getPresentableText(boolean includeDefaultValue, @Nullable TypeEvalContext context);
/**
* @param includeDefaultValue if true, include the default value after an "=".
* @param context context to be used to resolve argument type
* @param typeFilter predicate to be used to ignore resolved argument type
* @return canonical representation of parameter.
* Includes asterisks for *param and **param.
* Also includes argument type if {@code context} is not null and filter returns `false` for it.
* @apiNote This method will be marked as abstract in 2018.3.
*/
@NotNull
default String getPresentableText(boolean includeDefaultValue, @Nullable TypeEvalContext context, @NotNull Predicate<PyType> typeFilter) {
return getPresentableText(includeDefaultValue, context);
}
/**
* @param context context to be used to resolve argument type
* @return argument type. Returns element type for *param and value type for **param.
@@ -21,6 +21,7 @@ import com.jetbrains.python.psi.impl.PyPsiUtils;
import com.jetbrains.python.psi.resolve.PyResolveContext;
import com.jetbrains.python.psi.types.PyCallableParameter;
import com.jetbrains.python.psi.types.PyCallableParameterImpl;
import com.jetbrains.python.psi.types.PyStructuralType;
import com.jetbrains.python.psi.types.TypeEvalContext;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -393,7 +394,7 @@ public class PyParameterInfoHandler implements ParameterInfoHandler<PyArgumentLi
public void visitNonPsiParameter(@NotNull PyCallableParameter parameter, boolean first, boolean last) {
indexToNamedParameter.put(currentParameterIndex[0], parameter);
final StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append(parameter.getPresentableText(true, context));
stringBuilder.append(parameter.getPresentableText(true, context, type -> type == null || type instanceof PyStructuralType));
if (!last) stringBuilder.append(", ");
final int hintIndex = hintsList.size();
parameterToHintIndex.put(parameter, hintIndex);
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Objects;
import java.util.function.Predicate;
/**
* @author vlan
@@ -139,6 +140,12 @@ public class PyCallableParameterImpl implements PyCallableParameter {
@NotNull
@Override
public String getPresentableText(boolean includeDefaultValue, @Nullable TypeEvalContext context) {
return getPresentableText(includeDefaultValue, context, Objects::isNull);
}
@NotNull
@Override
public String getPresentableText(boolean includeDefaultValue, @Nullable TypeEvalContext context, @NotNull Predicate<PyType> typeFilter) {
if (myElement instanceof PyNamedParameter || myElement == null) {
final StringBuilder sb = new StringBuilder();
@@ -148,10 +155,12 @@ public class PyCallableParameterImpl implements PyCallableParameter {
final String name = getName();
sb.append(name != null ? name : "...");
final PyType argumentType = context == null ? null : getArgumentType(context);
if (argumentType != null) {
sb.append(": ");
sb.append(PythonDocumentationProvider.getTypeDescription(argumentType, context));
if (context != null) {
final PyType argumentType = getArgumentType(context);
if (!typeFilter.test(argumentType)) {
sb.append(": ");
sb.append(PythonDocumentationProvider.getTypeDescription(argumentType, context));
}
}
final String defaultValue = getDefaultValueText();
@@ -0,0 +1,6 @@
def foo(p1, p2: int):
p1[0] = 1
return p1, p2
foo(<arg1>)
@@ -708,6 +708,18 @@ public class PyParameterInfoTest extends LightMarkedTestCase {
);
}
// PY-26582
public void testStructuralType() {
runWithLanguageLevel(
LanguageLevel.PYTHON35,
() -> {
final Map<String, PsiElement> marks = loadTest(1);
feignCtrlP(marks.get("<arg1>").getTextOffset()).check("p1, p2: int", new String[]{"p1, "});
}
);
}
/**
* Imitates pressing of Ctrl+P; fails if results are not as expected.
* @param offset offset of 'cursor' where Ctrl+P is pressed.