Search in sources :

Example 1 with PyMarkedCallee

use of com.jetbrains.python.psi.PyCallExpression.PyMarkedCallee in project intellij-community by JetBrains.

the class PyParameterInfoHandler method collectHighlights.

/**
   * match params to available args, highlight current param(s)
   *
   * @return index of last parameter
   */
private static int collectHighlights(@NotNull final PyCallExpression.PyArgumentsMapping mapping, @NotNull final List<PyParameter> parameterList, @NotNull final Map<PyNamedParameter, Integer> parameterToIndex, @NotNull final Map<Integer, EnumSet<ParameterInfoUIContextEx.Flag>> hintFlags, @NotNull final List<PyExpression> flatArgs, int currentParamOffset) {
    final PyMarkedCallee callee = mapping.getMarkedCallee();
    assert callee != null;
    int lastParamIndex = callee.getImplicitOffset();
    final Map<PyExpression, PyNamedParameter> mappedParameters = mapping.getMappedParameters();
    final Map<PyExpression, PyTupleParameter> mappedTupleParameters = mapping.getMappedTupleParameters();
    for (PyExpression arg : flatArgs) {
        final boolean mustHighlight = arg.getTextRange().contains(currentParamOffset);
        PsiElement seeker = arg;
        // An argument tuple may have been flattened; find it
        while (!(seeker instanceof PyArgumentList) && seeker instanceof PyExpression && !mappedParameters.containsKey(seeker)) {
            seeker = seeker.getParent();
        }
        if (seeker instanceof PyExpression) {
            final PyNamedParameter parameter = mappedParameters.get((PyExpression) seeker);
            lastParamIndex = Math.max(lastParamIndex, parameterList.indexOf(parameter));
            if (parameter != null) {
                highlightParameter(parameter, parameterToIndex, hintFlags, mustHighlight);
            }
        } else if (PyCallExpressionHelper.isVariadicPositionalArgument(arg)) {
            for (PyNamedParameter parameter : mapping.getParametersMappedToVariadicPositionalArguments()) {
                lastParamIndex = Math.max(lastParamIndex, parameterList.indexOf(parameter));
                highlightParameter(parameter, parameterToIndex, hintFlags, mustHighlight);
            }
        } else if (PyCallExpressionHelper.isVariadicKeywordArgument(arg)) {
            for (PyNamedParameter parameter : mapping.getParametersMappedToVariadicKeywordArguments()) {
                lastParamIndex = Math.max(lastParamIndex, parameterList.indexOf(parameter));
                highlightParameter(parameter, parameterToIndex, hintFlags, mustHighlight);
            }
        } else {
            final PyTupleParameter tupleParameter = mappedTupleParameters.get(arg);
            if (tupleParameter != null) {
                for (PyNamedParameter parameter : getFlattenedTupleParameterComponents(tupleParameter)) {
                    lastParamIndex = Math.max(lastParamIndex, parameterList.indexOf(parameter));
                    highlightParameter(parameter, parameterToIndex, hintFlags, mustHighlight);
                }
            }
        }
    }
    return lastParamIndex;
}
Also used : PyMarkedCallee(com.jetbrains.python.psi.PyCallExpression.PyMarkedCallee) PsiElement(com.intellij.psi.PsiElement)

Example 2 with PyMarkedCallee

use of com.jetbrains.python.psi.PyCallExpression.PyMarkedCallee in project intellij-community by JetBrains.

the class PyParameterInfoHandler method updateUI.

@Override
public void updateUI(@NotNull Pair<PyCallExpression, PyMarkedCallee> callAndCallee, @NotNull ParameterInfoUIContext context) {
    final PyCallExpression callExpression = callAndCallee.getFirst();
    PyPsiUtils.assertValid(callExpression);
    final TypeEvalContext typeEvalContext = TypeEvalContext.userInitiated(callExpression.getProject(), callExpression.getContainingFile());
    final PyCallExpression.PyArgumentsMapping mapping = PyCallExpressionHelper.mapArguments(callExpression, callAndCallee.getSecond(), typeEvalContext);
    final PyMarkedCallee markedCallee = mapping.getMarkedCallee();
    if (markedCallee == null)
        return;
    final List<PyParameter> parameters = PyUtil.getParameters(markedCallee.getCallable(), typeEvalContext);
    final List<PyNamedParameter> namedParameters = new ArrayList<>(parameters.size());
    // param -> hint index. indexes are not contiguous, because some hints are parentheses.
    final Map<PyNamedParameter, Integer> parameterToIndex = new HashMap<>();
    // formatting of hints: hint index -> flags. this includes flags for parens.
    final Map<Integer, EnumSet<ParameterInfoUIContextEx.Flag>> hintFlags = new HashMap<>();
    final List<String> hintsList = buildParameterListHint(parameters, namedParameters, parameterToIndex, hintFlags, typeEvalContext);
    // in Python mode, we get an offset here, not an index!
    final int currentParamOffset = context.getCurrentParameterIndex();
    // gray out enough first parameters as implicit (self, cls, ...)
    for (int i = 0; i < markedCallee.getImplicitOffset(); i++) {
        // show but mark as absent
        hintFlags.get(parameterToIndex.get(namedParameters.get(i))).add(ParameterInfoUIContextEx.Flag.DISABLE);
    }
    final List<PyExpression> flattenedArguments = PyUtil.flattenedParensAndLists(callExpression.getArguments());
    final int lastParamIndex = collectHighlights(mapping, parameters, parameterToIndex, hintFlags, flattenedArguments, currentParamOffset);
    highlightNext(markedCallee, parameters, namedParameters, parameterToIndex, hintFlags, flattenedArguments.isEmpty(), lastParamIndex);
    String[] hints = ArrayUtil.toStringArray(hintsList);
    if (context instanceof ParameterInfoUIContextEx) {
        final ParameterInfoUIContextEx pic = (ParameterInfoUIContextEx) context;
        EnumSet[] flags = new EnumSet[hintFlags.size()];
        for (int i = 0; i < flags.length; i++) flags[i] = hintFlags.get(i);
        if (hints.length < 1) {
            hints = new String[] { NO_PARAMS_MSG };
            flags = new EnumSet[] { EnumSet.of(ParameterInfoUIContextEx.Flag.DISABLE) };
        }
        //noinspection unchecked
        pic.setupUIComponentPresentation(hints, flags, context.getDefaultParameterColor());
    } else {
        // fallback, no highlight
        final StringBuilder signatureBuilder = new StringBuilder();
        if (hints.length > 1) {
            for (String s : hints) signatureBuilder.append(s);
        } else {
            signatureBuilder.append(XmlStringUtil.escapeString(NO_PARAMS_MSG));
        }
        context.setupUIComponentPresentation(signatureBuilder.toString(), -1, 0, false, false, false, context.getDefaultParameterColor());
    }
}
Also used : TypeEvalContext(com.jetbrains.python.psi.types.TypeEvalContext) PyMarkedCallee(com.jetbrains.python.psi.PyCallExpression.PyMarkedCallee)

Aggregations

PyMarkedCallee (com.jetbrains.python.psi.PyCallExpression.PyMarkedCallee)2 PsiElement (com.intellij.psi.PsiElement)1 TypeEvalContext (com.jetbrains.python.psi.types.TypeEvalContext)1