Search in sources :

Example 1 with UnaryExpression

use of com.jetbrains.php.lang.psi.elements.UnaryExpression in project phpinspectionsea by kalessil.

the class FileFunctionMissUseInspector method buildVisitor.

@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
    return new BasePhpElementVisitor() {

        @Override
        public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
            final String functionName = reference.getName();
            if (functionName == null || !functionName.equals("file")) {
                return;
            }
            final PsiElement[] arguments = reference.getParameters();
            if (arguments.length != 1) {
                return;
            }
            /* function can be silenced, get parent for this case; validate parent structure */
            PsiElement parent = reference.getParent();
            if (parent instanceof UnaryExpression) {
                final PsiElement operation = ((UnaryExpression) parent).getOperation();
                if (OpenapiTypesUtil.is(operation, PhpTokenTypes.opSILENCE)) {
                    parent = parent.getParent();
                }
            }
            if (!(parent instanceof ParameterList) || !OpenapiTypesUtil.isFunctionReference(parent.getParent())) {
                return;
            }
            /* validate parent functions' name (implode or join) and amount of arguments */
            final FunctionReference parentReference = (FunctionReference) parent.getParent();
            final String parentName = parentReference.getName();
            if (parentName == null || (!parentName.equals("implode") && !parentName.equals("join"))) {
                return;
            }
            final PsiElement[] parentParams = parentReference.getParameters();
            if (parentParams.length != 2) {
                return;
            }
            /* validate if glue is not empty */
            final StringLiteralExpression glue = ExpressionSemanticUtil.resolveAsStringLiteral(parentParams[0]);
            if (glue != null && !glue.getContents().isEmpty()) {
                return;
            }
            final String message = String.format(messagePattern, arguments[0].getText());
            holder.registerProblem(parentReference, message, ProblemHighlightType.GENERIC_ERROR, new TheLocalFix());
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) StringLiteralExpression(com.jetbrains.php.lang.psi.elements.StringLiteralExpression) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) ParameterList(com.jetbrains.php.lang.psi.elements.ParameterList) UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with UnaryExpression

use of com.jetbrains.php.lang.psi.elements.UnaryExpression in project phpinspectionsea by kalessil.

the class IssetAndNullComparisonStrategy method apply.

public static boolean apply(@NotNull List<PsiElement> conditions, @NotNull ProblemsHolder holder) {
    /* first ensure that we have null identity checks at all */
    final Map<PsiElement, PsiElement> nullTestSubjects = new HashMap<>();
    for (final PsiElement oneCondition : conditions) {
        if (oneCondition instanceof BinaryExpression) {
            final BinaryExpression expression = (BinaryExpression) oneCondition;
            /* we need only !== and === operations */
            final IElementType operator = expression.getOperationType();
            if (operator != PhpTokenTypes.opIDENTICAL && operator != PhpTokenTypes.opNOT_IDENTICAL) {
                continue;
            }
            /* quickly check if any operands is a constant */
            final PsiElement left = expression.getLeftOperand();
            final PsiElement right = expression.getRightOperand();
            if (!(left instanceof ConstantReference) && !(right instanceof ConstantReference)) {
                continue;
            }
            /* store null test subjects */
            if (PhpLanguageUtil.isNull(right)) {
                if (null != left) {
                    nullTestSubjects.put(expression, left);
                }
                continue;
            }
            if (PhpLanguageUtil.isNull(left)) {
                if (null != right) {
                    nullTestSubjects.put(expression, right);
                }
            // continue;
            }
        }
    }
    if (0 == nullTestSubjects.size()) {
        return false;
    }
    boolean hasReportedExpressions = false;
    for (final PsiElement oneCondition : conditions) {
        /* do not process null identity checks */
        if (nullTestSubjects.containsKey(oneCondition)) {
            continue;
        }
        /* unwrap ! and () */
        PsiElement issetCandidate = oneCondition;
        if (issetCandidate instanceof UnaryExpression) {
            final PsiElement notOperatorCandidate = ((UnaryExpression) issetCandidate).getOperation();
            if (null != notOperatorCandidate && notOperatorCandidate.getNode().getElementType() == PhpTokenTypes.opNOT) {
                PsiElement invertedValue = ((UnaryExpression) issetCandidate).getValue();
                invertedValue = ExpressionSemanticUtil.getExpressionTroughParenthesis(invertedValue);
                if (null == invertedValue) {
                    continue;
                }
                issetCandidate = invertedValue;
            }
        }
        if (!(issetCandidate instanceof PhpIsset) || 0 == ((PhpIsset) issetCandidate).getVariables().length) {
            continue;
        }
        /* process isset constructions */
        for (final PsiElement issetArgument : ((PhpIsset) issetCandidate).getVariables()) {
            /* compare with know null identity checked subjects */
            for (final Map.Entry<PsiElement, PsiElement> nullTestPair : nullTestSubjects.entrySet()) {
                if (!OpeanapiEquivalenceUtil.areEqual(nullTestPair.getValue(), issetArgument)) {
                    continue;
                }
                hasReportedExpressions = true;
                final PsiElement nullTestExpression = nullTestPair.getKey();
                final String message = messagePattern.replace("%e%", nullTestExpression.getText());
                holder.registerProblem(nullTestExpression, message, ProblemHighlightType.WEAK_WARNING);
            }
        }
    }
    nullTestSubjects.clear();
    return hasReportedExpressions;
}
Also used : IElementType(com.intellij.psi.tree.IElementType) ConstantReference(com.jetbrains.php.lang.psi.elements.ConstantReference) BinaryExpression(com.jetbrains.php.lang.psi.elements.BinaryExpression) HashMap(java.util.HashMap) UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) HashMap(java.util.HashMap) Map(java.util.Map) PsiElement(com.intellij.psi.PsiElement) PhpIsset(com.jetbrains.php.lang.psi.elements.PhpIsset)

Example 3 with UnaryExpression

use of com.jetbrains.php.lang.psi.elements.UnaryExpression in project phpinspectionsea by kalessil.

the class StrEndsWithCanBeUsedInspector method buildVisitor.

@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, final boolean isOnTheFly) {
    return new BasePhpElementVisitor() {

        @Override
        public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
            final String functionName = reference.getName();
            if (functionName != null && (functionName.equals("substr") || functionName.equals("mb_substr"))) {
                final boolean isTargetVersion = PhpLanguageLevel.get(holder.getProject()).atLeast(PhpLanguageLevel.PHP800);
                if (isTargetVersion) {
                    final PsiElement[] arguments = reference.getParameters();
                    if (arguments.length == 2) {
                        final PsiElement context = reference.getParent();
                        if (context instanceof BinaryExpression) {
                            final BinaryExpression binary = (BinaryExpression) context;
                            final IElementType operation = binary.getOperationType();
                            if (operation == PhpTokenTypes.opNOT_IDENTICAL || operation == PhpTokenTypes.opIDENTICAL) {
                                final PsiElement limitArgument = this.extractLimitArgument(arguments[1]);
                                final PsiElement second = OpenapiElementsUtil.getSecondOperand(binary, reference);
                                if (second != null && limitArgument != null && OpenapiEquivalenceUtil.areEqual(second, limitArgument)) {
                                    final String replacement = String.format("%s%sstr_ends_with(%s, %s)", operation == PhpTokenTypes.opNOT_IDENTICAL ? "! " : "", reference.getImmediateNamespaceName(), arguments[0].getText(), second.getText());
                                    holder.registerProblem(binary, String.format(MessagesPresentationUtil.prefixWithEa(message), replacement), new UseStrEndsWithFix(replacement));
                                }
                            }
                        }
                    }
                }
            }
        }

        @Nullable
        private PsiElement extractLimitArgument(@Nullable PsiElement expression) {
            if (expression instanceof UnaryExpression) {
                final UnaryExpression unary = (UnaryExpression) expression;
                if (OpenapiTypesUtil.is(unary.getOperation(), PhpTokenTypes.opMINUS)) {
                    final PsiElement argument = unary.getValue();
                    if (OpenapiTypesUtil.isFunctionReference(argument)) {
                        final FunctionReference reference = (FunctionReference) argument;
                        final String functionName = reference.getName();
                        if (functionName != null && (functionName.equals("strlen") || functionName.equals("mb_strlen"))) {
                            final PsiElement[] arguments = reference.getParameters();
                            if (arguments.length == 1) {
                                return arguments[0];
                            }
                        }
                    }
                }
            }
            return null;
        }
    };
}
Also used : IElementType(com.intellij.psi.tree.IElementType) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) BinaryExpression(com.jetbrains.php.lang.psi.elements.BinaryExpression) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with UnaryExpression

use of com.jetbrains.php.lang.psi.elements.UnaryExpression in project phpinspectionsea by kalessil.

the class StrStrUsedAsStrPosInspector method buildVisitor.

@Override
@NotNull
public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) {
    return new BasePhpElementVisitor() {

        @Override
        public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
            final String functionName = reference.getName();
            if (functionName != null && mapping.containsKey(functionName)) {
                final PsiElement[] arguments = reference.getParameters();
                if (arguments.length >= 2) {
                    /* checks implicit boolean comparison pattern */
                    final PsiElement parent = reference.getParent();
                    if (parent instanceof BinaryExpression) {
                        final BinaryExpression binary = (BinaryExpression) parent;
                        if (OpenapiTypesUtil.tsCOMPARE_EQUALITY_OPS.contains(binary.getOperationType())) {
                            final PsiElement secondOperand = OpenapiElementsUtil.getSecondOperand(binary, reference);
                            if (PhpLanguageUtil.isFalse(secondOperand)) {
                                final PsiElement operationNode = binary.getOperation();
                                if (operationNode != null) {
                                    String operation = operationNode.getText();
                                    operation = operation.length() == 2 ? operation + '=' : operation;
                                    final String call = String.format("%s%s(%s, %s)", reference.getImmediateNamespaceName(), mapping.get(functionName), arguments[0].getText(), arguments[1].getText());
                                    final boolean isRegular = ComparisonStyle.isRegular();
                                    final String replacement = String.format("%s %s %s", isRegular ? call : "false", operation, isRegular ? "false" : call);
                                    holder.registerProblem(binary, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), replacement), new UseStrposFix(replacement));
                                    return;
                                }
                            }
                        }
                    }
                    /* checks non-implicit boolean comparison patternS */
                    if (ExpressionSemanticUtil.isUsedAsLogicalOperand(reference)) {
                        final String operation = parent instanceof UnaryExpression ? "===" : "!==";
                        final String call = String.format("%s%s(%s, %s)", reference.getImmediateNamespaceName(), mapping.get(functionName), arguments[0].getText(), arguments[1].getText());
                        final boolean isRegular = ComparisonStyle.isRegular();
                        final String replacement = String.format("%s %s %s", isRegular ? call : "false", operation, isRegular ? "false" : call);
                        holder.registerProblem(parent instanceof UnaryExpression ? parent : reference, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), replacement), new UseStrposFix(replacement));
                    }
                }
            }
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) BinaryExpression(com.jetbrains.php.lang.psi.elements.BinaryExpression) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with UnaryExpression

use of com.jetbrains.php.lang.psi.elements.UnaryExpression in project phpinspectionsea by kalessil.

the class PlainApiUseCheckStrategy method isPregMatchInverted.

private static boolean isPregMatchInverted(@NotNull FunctionReference reference) {
    boolean result = false;
    final PsiElement parent = reference.getParent();
    if (ExpressionSemanticUtil.isUsedAsLogicalOperand(reference)) {
        if (parent instanceof UnaryExpression) {
            result = OpenapiTypesUtil.is(((UnaryExpression) parent).getOperation(), PhpTokenTypes.opNOT);
        }
    } else if (parent instanceof BinaryExpression) {
        // inverted: < 1, == 0, === 0, != 1, !== 1
        // not inverted: > 0, == 1, === 1, != 0, !== 0
        final BinaryExpression binary = (BinaryExpression) parent;
        final IElementType operator = binary.getOperationType();
        if (operator == PhpTokenTypes.opLESS || OpenapiTypesUtil.tsCOMPARE_EQUALITY_OPS.contains(operator)) {
            final PsiElement second = OpenapiElementsUtil.getSecondOperand(binary, reference);
            if (OpenapiTypesUtil.isNumber(second)) {
                final String number = second.getText();
                result = operator == PhpTokenTypes.opLESS && number.equals("1") || operator == PhpTokenTypes.opEQUAL && number.equals("0") || operator == PhpTokenTypes.opIDENTICAL && number.equals("0") || operator == PhpTokenTypes.opNOT_EQUAL && number.equals("1") || operator == PhpTokenTypes.opNOT_IDENTICAL && number.equals("1");
            }
        }
    }
    return result;
}
Also used : IElementType(com.intellij.psi.tree.IElementType) BinaryExpression(com.jetbrains.php.lang.psi.elements.BinaryExpression) UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) PsiElement(com.intellij.psi.PsiElement)

Aggregations

PsiElement (com.intellij.psi.PsiElement)17 UnaryExpression (com.jetbrains.php.lang.psi.elements.UnaryExpression)17 IElementType (com.intellij.psi.tree.IElementType)10 BinaryExpression (com.jetbrains.php.lang.psi.elements.BinaryExpression)9 BasePhpElementVisitor (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor)7 NotNull (org.jetbrains.annotations.NotNull)7 FunctionReference (com.jetbrains.php.lang.psi.elements.FunctionReference)6 Nullable (org.jetbrains.annotations.Nullable)4 ParenthesizedExpression (com.jetbrains.php.lang.psi.elements.ParenthesizedExpression)3 PhpIsset (com.jetbrains.php.lang.psi.elements.PhpIsset)3 PhpTypedElement (com.jetbrains.php.lang.psi.elements.PhpTypedElement)2 PhpType (com.jetbrains.php.lang.psi.resolve.types.PhpType)2 PsiWhiteSpace (com.intellij.psi.PsiWhiteSpace)1 ArrayAccessExpression (com.jetbrains.php.lang.psi.elements.ArrayAccessExpression)1 AssignmentExpression (com.jetbrains.php.lang.psi.elements.AssignmentExpression)1 ConstantReference (com.jetbrains.php.lang.psi.elements.ConstantReference)1 If (com.jetbrains.php.lang.psi.elements.If)1 ParameterList (com.jetbrains.php.lang.psi.elements.ParameterList)1 PhpPsiElement (com.jetbrains.php.lang.psi.elements.PhpPsiElement)1 StringLiteralExpression (com.jetbrains.php.lang.psi.elements.StringLiteralExpression)1