Search in sources :

Example 1 with ParenthesizedExpression

use of com.jetbrains.php.lang.psi.elements.ParenthesizedExpression 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 2 with ParenthesizedExpression

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

the class IssetConstructsCanBeMergedInspector method buildVisitor.

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

        @Override
        public void visitPhpBinaryExpression(@NotNull BinaryExpression expression) {
            final IElementType operator = expression.getOperationType();
            if (operator != null && (operator == PhpTokenTypes.opAND || operator == PhpTokenTypes.opOR)) {
                /* false-positives: part of another condition */
                final PsiElement parent = expression.getParent();
                final PsiElement context = parent instanceof ParenthesizedExpression ? parent.getParent() : parent;
                if (context instanceof BinaryExpression && ((BinaryExpression) context).getOperationType() == operator) {
                    return;
                }
                final List<PsiElement> fragments = this.extract(expression, operator);
                if (fragments.size() > 1) {
                    if (operator == PhpTokenTypes.opAND) {
                        /* handle isset && isset ... */
                        PsiElement firstHit = null;
                        int hitsCount = 0;
                        for (final PsiElement fragment : fragments) {
                            if (fragment instanceof PhpIsset) {
                                if (++hitsCount > 1 && firstHit != null) {
                                    fragments.remove(firstHit);
                                    fragments.remove(fragment);
                                    holder.registerProblem(fragment, MessagesPresentationUtil.prefixWithEa(messageIsset), new MergeConstructsFix(holder.getProject(), expression, fragments, (PhpIsset) firstHit, (PhpIsset) fragment, operator));
                                    break;
                                }
                                firstHit = firstHit == null ? fragment : firstHit;
                            }
                        }
                    } else {
                        /* handle !isset || !isset ... */
                        PsiElement firstHit = null;
                        int hitsCount = 0;
                        for (final PsiElement fragment : fragments) {
                            if (fragment instanceof UnaryExpression) {
                                final PsiElement candidate = ((UnaryExpression) fragment).getValue();
                                if (candidate instanceof PhpIsset) {
                                    if (++hitsCount > 1 && firstHit != null) {
                                        fragments.remove(firstHit.getParent());
                                        fragments.remove(fragment);
                                        holder.registerProblem(candidate, MessagesPresentationUtil.prefixWithEa(messageIvertedIsset), new MergeConstructsFix(holder.getProject(), expression, fragments, (PhpIsset) firstHit, (PhpIsset) candidate, operator));
                                        break;
                                    }
                                    firstHit = firstHit == null ? candidate : firstHit;
                                }
                            }
                        }
                    }
                }
                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) UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) 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) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable) PhpIsset(com.jetbrains.php.lang.psi.elements.PhpIsset) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with ParenthesizedExpression

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

the class IsCountableCanBeUsedInspector 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.PHP740);
                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 && "Countable".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 4 with ParenthesizedExpression

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

the class NullableArgumentComparisonStrategy method apply.

public static boolean apply(@NotNull BinaryExpression expression, @NotNull ProblemsHolder holder) {
    boolean result = false;
    final IElementType operator = expression.getOperationType();
    if (mapping.containsKey(operator)) {
        PsiElement parent = expression.getParent();
        while (parent instanceof ParenthesizedExpression) {
            parent = parent.getParent();
        }
        final PsiElement argument = expression.getLeftOperand();
        final PsiElement value = expression.getRightOperand();
        if (parent instanceof UnaryExpression && argument instanceof PhpTypedElement && value != null) {
            final UnaryExpression target = (UnaryExpression) parent;
            if (OpenapiTypesUtil.is(target.getOperation(), PhpTokenTypes.opNOT)) {
                final PhpType type = OpenapiResolveUtil.resolveType((PhpTypedElement) argument, holder.getProject());
                if (type != null && !type.hasUnknown()) {
                    final Set<String> types = new HashSet<>();
                    type.getTypes().forEach(t -> types.add(Types.getType(t)));
                    if (types.contains(Types.strNull) || types.contains(Types.strBoolean)) {
                        final String replacement = String.format("%s %s %s", argument.getText(), mapping.get(operator), value.getText());
                        holder.registerProblem(target, MessagesPresentationUtil.prefixWithEa(String.format(messagePattern, replacement)), new NullableArgumentComparisonFix(replacement));
                        result = true;
                    }
                    types.clear();
                }
            }
        }
    }
    return result;
}
Also used : IElementType(com.intellij.psi.tree.IElementType) ParenthesizedExpression(com.jetbrains.php.lang.psi.elements.ParenthesizedExpression) PhpTypedElement(com.jetbrains.php.lang.psi.elements.PhpTypedElement) UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) PsiElement(com.intellij.psi.PsiElement) PhpType(com.jetbrains.php.lang.psi.resolve.types.PhpType) HashSet(java.util.HashSet)

Example 5 with ParenthesizedExpression

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

the class SummerTimeUnsafeTimeManipulationInspector method buildVisitor.

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

        @Override
        public void visitPhpBinaryExpression(@NotNull BinaryExpression expression) {
            if (targetOperations.contains(expression.getOperationType())) {
                final PsiElement left = expression.getLeftOperand();
                final PsiElement right = expression.getRightOperand();
                if (right != null && this.isTargetMagicNumber(right) && this.isTargetContext(right)) {
                    if (!this.isTestContext(expression)) {
                        holder.registerProblem(expression, message);
                    }
                } else if (left != null && this.isTargetMagicNumber(left) && this.isTargetContext(left)) {
                    if (!this.isTestContext(expression)) {
                        holder.registerProblem(expression, message);
                    }
                }
            }
        }

        @Override
        public void visitPhpSelfAssignmentExpression(@NotNull SelfAssignmentExpression expression) {
            if (targetAssignments.contains(expression.getOperationType())) {
                final PsiElement value = expression.getValue();
                if (value != null && this.isTargetMagicNumber(value) && !this.isTestContext(expression)) {
                    holder.registerProblem(expression, message);
                }
            }
        }

        private boolean isTargetContext(@NotNull PsiElement magicNumber) {
            boolean result = magicNumber.textMatches("86400");
            if (!result) {
                PsiElement expression = magicNumber.getParent();
                while (expression instanceof ParenthesizedExpression || expression instanceof BinaryExpression) {
                    expression = expression.getParent();
                }
                result = PsiTreeUtil.findChildrenOfType(expression, PhpExpression.class).stream().filter(OpenapiTypesUtil::isNumber).anyMatch(candidate -> {
                    final String text = candidate.getText();
                    return text.equals("60") || text.endsWith("3600");
                });
            }
            return result;
        }

        private boolean isTargetMagicNumber(@NotNull PsiElement candidate) {
            boolean result = false;
            if (OpenapiTypesUtil.isNumber(candidate)) {
                result = candidate.textMatches("24") || candidate.textMatches("86400");
            }
            return result;
        }
    };
}
Also used : SelfAssignmentExpression(com.jetbrains.php.lang.psi.elements.SelfAssignmentExpression) ParenthesizedExpression(com.jetbrains.php.lang.psi.elements.ParenthesizedExpression) BasePhpInspection(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpInspection) IElementType(com.intellij.psi.tree.IElementType) PhpTokenTypes(com.jetbrains.php.lang.lexer.PhpTokenTypes) Set(java.util.Set) SelfAssignmentExpression(com.jetbrains.php.lang.psi.elements.SelfAssignmentExpression) HashSet(java.util.HashSet) PsiTreeUtil(com.intellij.psi.util.PsiTreeUtil) ParenthesizedExpression(com.jetbrains.php.lang.psi.elements.ParenthesizedExpression) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) OpenapiTypesUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.OpenapiTypesUtil) BinaryExpression(com.jetbrains.php.lang.psi.elements.BinaryExpression) PhpExpression(com.jetbrains.php.lang.psi.elements.PhpExpression) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull) PsiElementVisitor(com.intellij.psi.PsiElementVisitor) ProblemsHolder(com.intellij.codeInspection.ProblemsHolder) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) BinaryExpression(com.jetbrains.php.lang.psi.elements.BinaryExpression) OpenapiTypesUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.OpenapiTypesUtil) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

PsiElement (com.intellij.psi.PsiElement)7 ParenthesizedExpression (com.jetbrains.php.lang.psi.elements.ParenthesizedExpression)7 IElementType (com.intellij.psi.tree.IElementType)6 BinaryExpression (com.jetbrains.php.lang.psi.elements.BinaryExpression)6 BasePhpElementVisitor (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor)6 NotNull (org.jetbrains.annotations.NotNull)6 UnaryExpression (com.jetbrains.php.lang.psi.elements.UnaryExpression)3 ArrayList (java.util.ArrayList)3 Objects (java.util.Objects)3 Nullable (org.jetbrains.annotations.Nullable)3 ClassReference (com.jetbrains.php.lang.psi.elements.ClassReference)2 FunctionReference (com.jetbrains.php.lang.psi.elements.FunctionReference)2 HashSet (java.util.HashSet)2 ProblemsHolder (com.intellij.codeInspection.ProblemsHolder)1 PsiElementVisitor (com.intellij.psi.PsiElementVisitor)1 PsiTreeUtil (com.intellij.psi.util.PsiTreeUtil)1 PhpTokenTypes (com.jetbrains.php.lang.lexer.PhpTokenTypes)1 PhpExpression (com.jetbrains.php.lang.psi.elements.PhpExpression)1 PhpIsset (com.jetbrains.php.lang.psi.elements.PhpIsset)1 PhpTypedElement (com.jetbrains.php.lang.psi.elements.PhpTypedElement)1