Search in sources :

Example 11 with BinaryExpression

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

the class IsIterableCanBeUsedInspector 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("is_array")) {
                final boolean isTargetVersion = PhpLanguageLevel.get(holder.getProject()).atLeast(PhpLanguageLevel.PHP710);
                if (isTargetVersion) {
                    final PsiElement[] arguments = reference.getParameters();
                    final PsiElement parent = reference.getParent();
                    if (parent instanceof BinaryExpression && arguments.length == 1) {
                        final BinaryExpression binary = (BinaryExpression) parent;
                        final IElementType operation = binary.getOperationType();
                        if (operation == PhpTokenTypes.opOR) {
                            /* find the high-level binary expression */
                            BinaryExpression context = binary;
                            while (context instanceof BinaryExpression) {
                                PsiElement up = context.getParent();
                                while (up instanceof ParenthesizedExpression) {
                                    up = up.getParent();
                                }
                                if (up instanceof BinaryExpression && ((BinaryExpression) up).getOperationType() == PhpTokenTypes.opOR) {
                                    context = (BinaryExpression) up;
                                } else {
                                    break;
                                }
                            }
                            /* check the pattern */
                            final List<PsiElement> fragments = this.extract(context, PhpTokenTypes.opOR);
                            if (!fragments.isEmpty()) {
                                if (fragments.size() > 1) {
                                    for (final PsiElement fragment : fragments) {
                                        if (fragment != reference && fragment instanceof BinaryExpression) {
                                            final BinaryExpression candidate = (BinaryExpression) fragment;
                                            if (candidate.getOperationType() == PhpTokenTypes.kwINSTANCEOF) {
                                                final PsiElement clazz = candidate.getRightOperand();
                                                if (clazz instanceof ClassReference && "Traversable".equals(((ClassReference) clazz).getName())) {
                                                    final PsiElement subject = candidate.getLeftOperand();
                                                    if (subject != null && OpenapiEquivalenceUtil.areEqual(subject, arguments[0])) {
                                                        final String argument = subject.getText();
                                                        holder.registerProblem(reference, String.format(MessagesPresentationUtil.prefixWithEa(message), argument, argument, argument));
                                                        break;
                                                    }
                                                }
                                            }
                                        }
                                    }
                                }
                                fragments.clear();
                            }
                        }
                    }
                }
            }
        }

        @NotNull
        private List<PsiElement> extract(@NotNull BinaryExpression binary, @Nullable IElementType operator) {
            final List<PsiElement> result = new ArrayList<>();
            if (binary.getOperationType() == operator) {
                Stream.of(binary.getLeftOperand(), binary.getRightOperand()).filter(Objects::nonNull).map(ExpressionSemanticUtil::getExpressionTroughParenthesis).forEach(expression -> {
                    if (expression instanceof BinaryExpression) {
                        result.addAll(this.extract((BinaryExpression) expression, operator));
                    } else {
                        result.add(expression);
                    }
                });
            } else {
                result.add(binary);
            }
            return result;
        }
    };
}
Also used : ParenthesizedExpression(com.jetbrains.php.lang.psi.elements.ParenthesizedExpression) ArrayList(java.util.ArrayList) NotNull(org.jetbrains.annotations.NotNull) IElementType(com.intellij.psi.tree.IElementType) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) BinaryExpression(com.jetbrains.php.lang.psi.elements.BinaryExpression) Objects(java.util.Objects) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) ClassReference(com.jetbrains.php.lang.psi.elements.ClassReference) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable) NotNull(org.jetbrains.annotations.NotNull)

Example 12 with BinaryExpression

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

the class AssertBoolOfComparisonStrategy method apply.

public static boolean apply(@NotNull String function, @NotNull MethodReference reference, @NotNull ProblemsHolder holder) {
    final PsiElement[] params = reference.getParameters();
    if (params.length > 0 && (function.equals("assertTrue") || function.equals("assertNotTrue") || function.equals("assertFalse") || function.equals("assertNotFalse"))) {
        final PsiElement param = ExpressionSemanticUtil.getExpressionTroughParenthesis(params[0]);
        if (param instanceof BinaryExpression) {
            final BinaryExpression argument = (BinaryExpression) param;
            final PsiElement left = argument.getLeftOperand();
            final PsiElement right = argument.getRightOperand();
            final IElementType operation = argument.getOperationType();
            if (left != null && right != null && OpenapiTypesUtil.tsCOMPARE_EQUALITY_OPS.contains(operation)) {
                final boolean isMethodInverting = function.equals("assertFalse") || function.equals("assertNotTrue");
                final boolean isOperationInverting = operation == PhpTokenTypes.opNOT_EQUAL || operation == PhpTokenTypes.opNOT_IDENTICAL;
                final boolean isTypeStrict = operation == PhpTokenTypes.opIDENTICAL || operation == PhpTokenTypes.opNOT_IDENTICAL;
                final String replacementMethod = "assert" + (isMethodInverting == isOperationInverting ? "" : "Not") + (isTypeStrict ? "Same" : "Equals");
                holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messagePattern.replace("%m%", replacementMethod)), new TheLocalFix(holder.getProject(), replacementMethod, left, right));
                return true;
            }
        }
    }
    return false;
}
Also used : IElementType(com.intellij.psi.tree.IElementType) BinaryExpression(com.jetbrains.php.lang.psi.elements.BinaryExpression) PsiElement(com.intellij.psi.PsiElement)

Example 13 with BinaryExpression

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

the class AssertRegexStrategy method apply.

public static boolean apply(@NotNull String methodName, @NotNull MethodReference reference, @NotNull ProblemsHolder holder) {
    boolean result = false;
    if (numberCompareTargets.containsKey(methodName)) {
        final PsiElement[] assertionArguments = reference.getParameters();
        if (assertionArguments.length >= 2 && OpenapiTypesUtil.isNumber(assertionArguments[0])) {
            final boolean isTarget = OpenapiTypesUtil.isFunctionReference(assertionArguments[1]);
            if (isTarget) {
                final FunctionReference candidate = (FunctionReference) assertionArguments[1];
                final String candidateName = candidate.getName();
                if (candidateName != null && candidateName.equals("preg_match")) {
                    final PsiElement[] functionArguments = candidate.getParameters();
                    if (functionArguments.length == 2) {
                        final String suggestedAssertion = assertionArguments[0].getText().equals(numberCompareTargets.get(methodName)) ? "assertRegExp" : "assertNotRegExp";
                        final String[] suggestedArguments = new String[assertionArguments.length];
                        suggestedArguments[0] = functionArguments[0].getText();
                        suggestedArguments[1] = functionArguments[1].getText();
                        if (assertionArguments.length > 2) {
                            suggestedArguments[2] = assertionArguments[2].getText();
                        }
                        holder.registerProblem(reference, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), suggestedAssertion), new PhpUnitAssertFixer(suggestedAssertion, suggestedArguments));
                        result = true;
                    }
                }
            }
        }
    } else if (binaryTargets.contains(methodName)) {
        final PsiElement[] assertionArguments = reference.getParameters();
        if (assertionArguments.length > 0 && assertionArguments[0] instanceof BinaryExpression) {
            final BinaryExpression binary = (BinaryExpression) assertionArguments[0];
            if (binary.getOperationType() == PhpTokenTypes.opGREATER) {
                final PsiElement left = binary.getLeftOperand();
                final PsiElement right = binary.getRightOperand();
                if (OpenapiTypesUtil.isNumber(right) && OpenapiTypesUtil.isFunctionReference(left)) {
                    final boolean isTargetNumber = right.getText().equals("0");
                    if (isTargetNumber) {
                        final FunctionReference candidate = (FunctionReference) left;
                        final String candidateName = candidate.getName();
                        if (candidateName != null && candidateName.equals("preg_match")) {
                            final PsiElement[] functionArguments = candidate.getParameters();
                            if (functionArguments.length == 2) {
                                final String suggestedAssertion = methodName.equals("assertTrue") ? "assertRegExp" : "assertNotRegExp";
                                final String[] suggestedArguments = new String[assertionArguments.length + 1];
                                suggestedArguments[0] = functionArguments[0].getText();
                                suggestedArguments[1] = functionArguments[1].getText();
                                if (assertionArguments.length > 1) {
                                    suggestedArguments[2] = assertionArguments[1].getText();
                                }
                                holder.registerProblem(reference, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), suggestedAssertion), new PhpUnitAssertFixer(suggestedAssertion, suggestedArguments));
                                result = true;
                            }
                        }
                    }
                }
            }
        }
    }
    return result;
}
Also used : BinaryExpression(com.jetbrains.php.lang.psi.elements.BinaryExpression) PhpUnitAssertFixer(com.kalessil.phpStorm.phpInspectionsEA.fixers.PhpUnitAssertFixer) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) PsiElement(com.intellij.psi.PsiElement)

Example 14 with BinaryExpression

use of com.jetbrains.php.lang.psi.elements.BinaryExpression 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)

Example 15 with BinaryExpression

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

the class PlainApiUseCheckStrategy method getPregMatchContext.

private static PsiElement getPregMatchContext(@NotNull FunctionReference reference) {
    PsiElement result = reference;
    final PsiElement parent = reference.getParent();
    if (ExpressionSemanticUtil.isUsedAsLogicalOperand(reference)) {
        if (parent instanceof UnaryExpression) {
            final UnaryExpression unary = (UnaryExpression) parent;
            if (OpenapiTypesUtil.is(unary.getOperation(), PhpTokenTypes.opNOT)) {
                result = parent;
            }
        }
    } else if (parent instanceof BinaryExpression) {
        final BinaryExpression binary = (BinaryExpression) parent;
        final IElementType operator = binary.getOperationType();
        final boolean isTargetOperator = OpenapiTypesUtil.tsCOMPARE_EQUALITY_OPS.contains(operator) || PhpTokenTypes.tsCOMPARE_ORDER_OPS.contains(operator);
        if (isTargetOperator) {
            final PsiElement second = OpenapiElementsUtil.getSecondOperand(binary, reference);
            if (OpenapiTypesUtil.isNumber(second)) {
                result = parent;
            }
        }
    }
    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

BinaryExpression (com.jetbrains.php.lang.psi.elements.BinaryExpression)35 PsiElement (com.intellij.psi.PsiElement)34 IElementType (com.intellij.psi.tree.IElementType)26 BasePhpElementVisitor (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor)25 NotNull (org.jetbrains.annotations.NotNull)25 FunctionReference (com.jetbrains.php.lang.psi.elements.FunctionReference)16 UnaryExpression (com.jetbrains.php.lang.psi.elements.UnaryExpression)9 ParenthesizedExpression (com.jetbrains.php.lang.psi.elements.ParenthesizedExpression)6 PhpType (com.jetbrains.php.lang.psi.resolve.types.PhpType)5 Nullable (org.jetbrains.annotations.Nullable)5 PhpTypedElement (com.jetbrains.php.lang.psi.elements.PhpTypedElement)4 StringLiteralExpression (com.jetbrains.php.lang.psi.elements.StringLiteralExpression)4 ProblemsHolder (com.intellij.codeInspection.ProblemsHolder)3 PsiElementVisitor (com.intellij.psi.PsiElementVisitor)3 PhpTokenTypes (com.jetbrains.php.lang.lexer.PhpTokenTypes)3 TernaryExpression (com.jetbrains.php.lang.psi.elements.TernaryExpression)3 BasePhpInspection (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpInspection)3 ArrayList (java.util.ArrayList)3 HashSet (java.util.HashSet)3 Objects (java.util.Objects)3