Search in sources :

Example 16 with PyType

use of com.jetbrains.python.psi.types.PyType in project intellij-community by JetBrains.

the class PyStringConcatenationToFormatIntention method doInvoke.

public void doInvoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
    PsiElement element = PsiTreeUtil.getTopmostParentOfType(file.findElementAt(editor.getCaretModel().getOffset()), PyBinaryExpression.class);
    if (element == null)
        return;
    final LanguageLevel languageLevel = LanguageLevel.forElement(element);
    final boolean useFormatMethod = languageLevel.isAtLeast(LanguageLevel.PYTHON27);
    NotNullFunction<String, String> escaper = StringUtil.escaper(false, "\"\'\\");
    StringBuilder stringLiteral = new StringBuilder();
    List<String> parameters = new ArrayList<>();
    Pair<String, String> quotes = Pair.create("\"", "\"");
    boolean quotesDetected = false;
    final TypeEvalContext context = TypeEvalContext.userInitiated(file.getProject(), file);
    int paramCount = 0;
    boolean isUnicode = false;
    final PyClassTypeImpl unicodeType = PyBuiltinCache.getInstance(element).getObjectType("unicode");
    for (PyExpression expression : getSimpleExpressions((PyBinaryExpression) element)) {
        if (expression instanceof PyStringLiteralExpression) {
            final PyType type = context.getType(expression);
            if (type != null && type.equals(unicodeType)) {
                isUnicode = true;
            }
            if (!quotesDetected) {
                quotes = PyStringLiteralUtil.getQuotes(expression.getText());
                quotesDetected = true;
            }
            String value = ((PyStringLiteralExpression) expression).getStringValue();
            if (!useFormatMethod) {
                value = value.replace("%", "%%");
            }
            stringLiteral.append(escaper.fun(value));
        } else {
            addParamToString(stringLiteral, paramCount, useFormatMethod);
            parameters.add(expression.getText());
            ++paramCount;
        }
    }
    if (quotes == null)
        quotes = Pair.create("\"", "\"");
    stringLiteral.insert(0, quotes.getFirst());
    if (isUnicode && !quotes.getFirst().toLowerCase().contains("u"))
        stringLiteral.insert(0, "u");
    stringLiteral.append(quotes.getSecond());
    PyElementGenerator elementGenerator = PyElementGenerator.getInstance(project);
    if (!parameters.isEmpty()) {
        if (useFormatMethod) {
            stringLiteral.append(".format(").append(StringUtil.join(parameters, ",")).append(")");
        } else {
            final String paramString = parameters.size() > 1 ? "(" + StringUtil.join(parameters, ",") + ")" : StringUtil.join(parameters, ",");
            stringLiteral.append(" % ").append(paramString);
        }
        final PyExpression expression = elementGenerator.createFromText(LanguageLevel.getDefault(), PyExpressionStatement.class, stringLiteral.toString()).getExpression();
        element.replace(expression);
    } else {
        PyStringLiteralExpression stringLiteralExpression = elementGenerator.createStringLiteralAlreadyEscaped(stringLiteral.toString());
        element.replace(stringLiteralExpression);
    }
}
Also used : PyClassTypeImpl(com.jetbrains.python.psi.types.PyClassTypeImpl) ArrayList(java.util.ArrayList) TypeEvalContext(com.jetbrains.python.psi.types.TypeEvalContext) PyType(com.jetbrains.python.psi.types.PyType) PsiElement(com.intellij.psi.PsiElement)

Example 17 with PyType

use of com.jetbrains.python.psi.types.PyType in project intellij-community by JetBrains.

the class PyAddSpecifierToFormatQuickFix method applyFix.

public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
    final PsiElement element = descriptor.getPsiElement();
    final PyBinaryExpression expression = PsiTreeUtil.getParentOfType(element, PyBinaryExpression.class);
    if (expression == null)
        return;
    PyExpression rightExpression = expression.getRightExpression();
    if (rightExpression instanceof PyParenthesizedExpression) {
        rightExpression = ((PyParenthesizedExpression) rightExpression).getContainedExpression();
    }
    if (rightExpression == null)
        return;
    final PsiFile file = element.getContainingFile();
    final Document document = FileDocumentManager.getInstance().getDocument(file.getVirtualFile());
    if (document == null)
        return;
    final int offset = element.getTextOffset();
    final TypeEvalContext context = TypeEvalContext.userInitiated(file.getProject(), file);
    final PyClassType strType = PyBuiltinCache.getInstance(element).getStrType();
    final PyClassType floatType = PyBuiltinCache.getInstance(element).getFloatType();
    final PyClassType intType = PyBuiltinCache.getInstance(element).getIntType();
    final PyExpression leftExpression = expression.getLeftExpression();
    if (leftExpression instanceof PyStringLiteralExpression) {
        final List<PyStringFormatParser.SubstitutionChunk> chunks = filterSubstitutions(parsePercentFormat(((PyStringLiteralExpression) leftExpression).getStringValue()));
        PyExpression[] elements;
        if (rightExpression instanceof PyTupleExpression) {
            elements = ((PyTupleExpression) rightExpression).getElements();
        } else {
            elements = new PyExpression[] { rightExpression };
        }
        int shift = 2;
        for (int i = 0; i < chunks.size(); i++) {
            final PyStringFormatParser.SubstitutionChunk chunk = chunks.get(i);
            if (elements.length <= i)
                return;
            final PyType type = context.getType(elements[i]);
            final char conversionType = chunk.getConversionType();
            if (conversionType == '') {
                final int insertOffset = offset + chunk.getStartIndex() + shift;
                if (insertOffset > leftExpression.getTextRange().getEndOffset())
                    return;
                if (PyTypeChecker.match(strType, type, context)) {
                    document.insertString(insertOffset, "s");
                    shift += 1;
                }
                if (PyTypeChecker.match(intType, type, context) || PyTypeChecker.match(floatType, type, context)) {
                    document.insertString(insertOffset, "d");
                    shift += 1;
                }
            }
        }
    }
}
Also used : PyClassType(com.jetbrains.python.psi.types.PyClassType) Document(com.intellij.openapi.editor.Document) TypeEvalContext(com.jetbrains.python.psi.types.TypeEvalContext) PyStringFormatParser(com.jetbrains.python.inspections.PyStringFormatParser) PyType(com.jetbrains.python.psi.types.PyType) PsiFile(com.intellij.psi.PsiFile) PsiElement(com.intellij.psi.PsiElement)

Example 18 with PyType

use of com.jetbrains.python.psi.types.PyType in project intellij-community by JetBrains.

the class PyCreatePropertyQuickFix method applyFix.

public void applyFix(@NotNull final Project project, @NotNull final ProblemDescriptor descriptor) {
    final PsiElement element = descriptor.getPsiElement();
    if (element instanceof PyQualifiedExpression) {
        final PyExpression qualifier = ((PyQualifiedExpression) element).getQualifier();
        if (qualifier != null) {
            final PyType type = TypeEvalContext.codeAnalysis(element.getProject(), element.getContainingFile()).getType(qualifier);
            if (type instanceof PyClassType) {
                final PyClass cls = ((PyClassType) type).getPyClass();
                final String propertyName = ((PyQualifiedExpression) element).getName();
                if (propertyName == null)
                    return;
                final String fieldName = "_" + propertyName;
                final PyElementGenerator generator = PyElementGenerator.getInstance(project);
                final PyFunction property = generator.createProperty(LanguageLevel.forElement(cls), propertyName, fieldName, myAccessDirection);
                PyUtil.addElementToStatementList(property, cls.getStatementList(), myAccessDirection == AccessDirection.READ);
            }
        }
    }
}
Also used : PyClassType(com.jetbrains.python.psi.types.PyClassType) PyType(com.jetbrains.python.psi.types.PyType) PsiElement(com.intellij.psi.PsiElement)

Example 19 with PyType

use of com.jetbrains.python.psi.types.PyType in project intellij-community by JetBrains.

the class AddMethodQuickFix method applyFix.

public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
    try {
        // there can be no name clash, else the name would have resolved, and it hasn't.
        final PsiElement problemElement = descriptor.getPsiElement();
        final PyClassType type = getClassType(problemElement);
        if (type == null)
            return;
        final PyClass cls = type.getPyClass();
        boolean callByClass = type.isDefinition();
        PyStatementList clsStmtList = cls.getStatementList();
        sure(FileModificationService.getInstance().preparePsiElementForWrite(clsStmtList));
        // try to at least match parameter count
        // TODO: get parameter style from code style
        PyFunctionBuilder builder = new PyFunctionBuilder(myIdentifier, cls);
        PsiElement pe = problemElement.getParent();
        // set to non-null to add a decorator
        String decoratorName = null;
        PyExpression[] args = PyExpression.EMPTY_ARRAY;
        if (pe instanceof PyCallExpression) {
            PyArgumentList arglist = ((PyCallExpression) pe).getArgumentList();
            if (arglist == null)
                return;
            args = arglist.getArguments();
        }
        boolean madeInstance = false;
        if (callByClass) {
            if (args.length > 0) {
                final TypeEvalContext context = TypeEvalContext.userInitiated(cls.getProject(), cls.getContainingFile());
                final PyType firstArgType = context.getType(args[0]);
                if (firstArgType instanceof PyClassType && ((PyClassType) firstArgType).getPyClass().isSubclass(cls, context)) {
                    // class, first arg ok: instance method
                    // NOTE: might use a name other than 'self', according to code style.
                    builder.parameter("self");
                    madeInstance = true;
                }
            }
            if (!madeInstance) {
                // class, first arg absent or of different type: classmethod
                // NOTE: might use a name other than 'cls', according to code style.
                builder.parameter("cls");
                decoratorName = PyNames.CLASSMETHOD;
            }
        } else {
            // instance method
            // NOTE: might use a name other than 'self', according to code style.
            builder.parameter("self");
        }
        // ClassFoo.meth(foo_instance)
        boolean skipFirst = callByClass && madeInstance;
        for (PyExpression arg : args) {
            if (skipFirst) {
                skipFirst = false;
                continue;
            }
            if (arg instanceof PyKeywordArgument) {
                // foo(bar) -> def foo(self, bar_1)
                builder.parameter(((PyKeywordArgument) arg).getKeyword());
            } else if (arg instanceof PyReferenceExpression) {
                PyReferenceExpression refex = (PyReferenceExpression) arg;
                builder.parameter(refex.getReferencedName());
            } else {
                // use a boring name
                builder.parameter("param");
            }
        }
        PyFunction method = builder.buildFunction(project, LanguageLevel.getDefault());
        if (decoratorName != null) {
            PyElementGenerator generator = PyElementGenerator.getInstance(project);
            PyDecoratorList decoratorList = generator.createFromText(LanguageLevel.getDefault(), PyDecoratorList.class, "@" + decoratorName + "\ndef foo(): pass", new int[] { 0, 0 });
            // in the very beginning
            method.addBefore(decoratorList, method.getFirstChild());
        }
        method = (PyFunction) PyUtil.addElementToStatementList(method, clsStmtList, PyNames.INIT.equals(method.getName()));
        if (myReplaceUsage) {
            showTemplateBuilder(method);
        }
    } catch (IncorrectOperationException ignored) {
        // we failed. tell about this
        PyUtil.showBalloon(project, PyBundle.message("QFIX.failed.to.add.method"), MessageType.ERROR);
    }
}
Also used : PyClassType(com.jetbrains.python.psi.types.PyClassType) TypeEvalContext(com.jetbrains.python.psi.types.TypeEvalContext) PyFunctionBuilder(com.jetbrains.python.psi.impl.PyFunctionBuilder) PyType(com.jetbrains.python.psi.types.PyType) IncorrectOperationException(com.intellij.util.IncorrectOperationException) PsiElement(com.intellij.psi.PsiElement)

Example 20 with PyType

use of com.jetbrains.python.psi.types.PyType in project intellij-community by JetBrains.

the class AddFieldQuickFix method getClassType.

private static PyClassType getClassType(@NotNull final PsiElement element) {
    if (element instanceof PyQualifiedExpression) {
        final PyExpression qualifier = ((PyQualifiedExpression) element).getQualifier();
        if (qualifier == null)
            return null;
        final PyType type = TypeEvalContext.userInitiated(element.getProject(), element.getContainingFile()).getType(qualifier);
        return type instanceof PyClassType ? (PyClassType) type : null;
    }
    final PyClass aClass = PsiTreeUtil.getParentOfType(element, PyClass.class);
    return aClass != null ? new PyClassTypeImpl(aClass, false) : null;
}
Also used : PyClassTypeImpl(com.jetbrains.python.psi.types.PyClassTypeImpl) PyClassType(com.jetbrains.python.psi.types.PyClassType) PyType(com.jetbrains.python.psi.types.PyType)

Aggregations

PyType (com.jetbrains.python.psi.types.PyType)42 TypeEvalContext (com.jetbrains.python.psi.types.TypeEvalContext)13 PsiElement (com.intellij.psi.PsiElement)11 Nullable (org.jetbrains.annotations.Nullable)9 PyClassType (com.jetbrains.python.psi.types.PyClassType)6 NotNull (org.jetbrains.annotations.NotNull)6 PsiFile (com.intellij.psi.PsiFile)5 ArrayList (java.util.ArrayList)5 PyClassLikeType (com.jetbrains.python.psi.types.PyClassLikeType)4 PyClassTypeImpl (com.jetbrains.python.psi.types.PyClassTypeImpl)4 NumpyDocString (com.jetbrains.python.documentation.docstrings.NumpyDocString)3 PyExpression (com.jetbrains.python.psi.PyExpression)3 FileASTNode (com.intellij.lang.FileASTNode)2 TextRange (com.intellij.openapi.util.TextRange)2 PsiReference (com.intellij.psi.PsiReference)2 IncorrectOperationException (com.intellij.util.IncorrectOperationException)2 ScopeOwner (com.jetbrains.python.codeInsight.controlflow.ScopeOwner)2 PyClass (com.jetbrains.python.psi.PyClass)2 PyFunctionBuilder (com.jetbrains.python.psi.impl.PyFunctionBuilder)2 PyStructuralType (com.jetbrains.python.psi.types.PyStructuralType)2