Search in sources :

Example 11 with UnaryExpression

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

the class StrlenInEmptyStringCheckContextInspection 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("strlen") || functionName.equals("mb_strlen"))) {
                final PsiElement[] arguments = reference.getParameters();
                if (arguments.length > 0 && ExpressionSemanticUtil.getBlockScope(reference) != null) {
                    boolean isMatchedPattern = false;
                    boolean isEmptyString = false;
                    PsiElement target = null;
                    /* check explicit numbers comparisons */
                    final PsiElement parent = reference.getParent();
                    if (parent instanceof BinaryExpression) {
                        final BinaryExpression binary = (BinaryExpression) parent;
                        final PsiElement left = binary.getLeftOperand();
                        final PsiElement secondOperand = OpenapiElementsUtil.getSecondOperand(binary, reference);
                        /* second operand should be a number */
                        if (OpenapiTypesUtil.isNumber(secondOperand)) {
                            final String number = secondOperand.getText();
                            /* check cases when comparing with 1 */
                            final IElementType operator = binary.getOperationType();
                            if (operator == PhpTokenTypes.opGREATER) {
                                isMatchedPattern = left == reference && number.equals("0");
                                target = binary;
                                isEmptyString = false;
                            } else if (operator == PhpTokenTypes.opLESS || operator == PhpTokenTypes.opGREATER_OR_EQUAL) {
                                isMatchedPattern = left == reference && number.equals("1");
                                target = binary;
                                isEmptyString = operator == PhpTokenTypes.opLESS;
                            }
                            /* check cases when checking equality to 0 */
                            if (!isMatchedPattern && OpenapiTypesUtil.tsCOMPARE_EQUALITY_OPS.contains(operator)) {
                                isMatchedPattern = number.equals("0");
                                target = binary;
                                isEmptyString = operator == PhpTokenTypes.opIDENTICAL || operator == PhpTokenTypes.opEQUAL;
                            }
                        }
                    }
                    /* checks NON-implicit boolean comparison patterns */
                    if (!isMatchedPattern && ExpressionSemanticUtil.isUsedAsLogicalOperand(reference)) {
                        isMatchedPattern = true;
                        target = reference;
                        final PsiElement operation = parent instanceof UnaryExpression ? ((UnaryExpression) parent).getOperation() : null;
                        if (operation != null) {
                            isEmptyString = OpenapiTypesUtil.is(operation, PhpTokenTypes.opNOT);
                            target = parent;
                        }
                    }
                    /* investigate possible issues */
                    if (isMatchedPattern) {
                        final boolean isRegular = ComparisonStyle.isRegular();
                        final String operator = (isEmptyString ? "=" : "!") + (this.canApplyIdentityOperator(arguments[0]) ? "==" : "=");
                        final String replacement = String.format(isRegular ? "%s %s ''" : "'' %s %s", isRegular ? arguments[0].getText() : operator, isRegular ? operator : arguments[0].getText());
                        holder.registerProblem(target, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), replacement), new CompareToEmptyStringFix(replacement));
                    }
                }
            }
        }

        private boolean canApplyIdentityOperator(@NotNull PsiElement value) {
            if (value instanceof PhpTypedElement) {
                final PhpType resolved = OpenapiResolveUtil.resolveType((PhpTypedElement) value, holder.getProject());
                if (resolved != null && resolved.size() == 1) {
                    return Types.strString.equals(Types.getType(resolved.getTypes().iterator().next()));
                }
            }
            return false;
        }
    };
}
Also used : UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) NotNull(org.jetbrains.annotations.NotNull) PhpType(com.jetbrains.php.lang.psi.resolve.types.PhpType) 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) PhpTypedElement(com.jetbrains.php.lang.psi.elements.PhpTypedElement) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 12 with UnaryExpression

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

the class UnclearOperationsPriorityStrategy method apply.

public static boolean apply(@NotNull BinaryExpression expression, @NotNull ProblemsHolder holder) {
    final IElementType operator = expression.getOperationType();
    final PsiElement parent = expression.getParent();
    if (operator == PhpTokenTypes.opAND || operator == PhpTokenTypes.opOR) {
        /* binary expressions, already wrapped into parentheses can be skipped */
        if (parent instanceof BinaryExpression) {
            final IElementType parentOperator = ((BinaryExpression) parent).getOperationType();
            if (parentOperator != operator && (parentOperator == PhpTokenTypes.opAND || parentOperator == PhpTokenTypes.opOR)) {
                final String replacement = '(' + expression.getText() + ')';
                holder.registerProblem(expression, MessagesPresentationUtil.prefixWithEa(message), new WrapItAsItIsFix(replacement));
                return true;
            }
        } else /* assignment dramatically changing precedence */
        if (OpenapiTypesUtil.isAssignment(parent) && !OpenapiTypesUtil.isStatementImpl(parent.getParent())) {
            final String replacement = '(' + expression.getText() + ')';
            holder.registerProblem(expression, MessagesPresentationUtil.prefixWithEa(message), new WrapItAsItIsFix(replacement));
            return true;
        }
    } else if (PhpTokenTypes.tsCOMPARE_OPS.contains(operator)) {
        if (OpenapiTypesUtil.isAssignment(parent) && parent.getParent() instanceof If) {
            final AssignmentExpression assignment = (AssignmentExpression) parent;
            final PsiElement assignedValue = assignment.getValue();
            if (assignedValue != null) {
                final String value = assignedValue.getText();
                final String replacement = assignment.getText().replace(value, '(' + value + ')');
                holder.registerProblem(parent, MessagesPresentationUtil.prefixWithEa(message), new WrapItAsItIsFix(replacement));
                return true;
            }
        } else if (PhpTokenTypes.tsCOMPARE_ORDER_OPS.contains(operator) && operator != PhpTokenTypes.opSPACESHIP) {
            final PsiElement left = expression.getLeftOperand();
            if (left instanceof UnaryExpression) {
                final UnaryExpression candidate = (UnaryExpression) left;
                if (OpenapiTypesUtil.is(candidate.getOperation(), PhpTokenTypes.opNOT)) {
                    final String value = candidate.getText();
                    final String replacement = expression.getText().replace(value, '(' + value + ')');
                    holder.registerProblem(expression, MessagesPresentationUtil.prefixWithEa(message), new WrapItAsItIsFix(replacement));
                    return true;
                }
            }
        }
    }
    return false;
}
Also used : IElementType(com.intellij.psi.tree.IElementType) BinaryExpression(com.jetbrains.php.lang.psi.elements.BinaryExpression) AssignmentExpression(com.jetbrains.php.lang.psi.elements.AssignmentExpression) UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) If(com.jetbrains.php.lang.psi.elements.If) PsiElement(com.intellij.psi.PsiElement)

Example 13 with UnaryExpression

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

the class AssertBoolInvertedStrategy 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("assertFalse"))) {
        final PsiElement param = ExpressionSemanticUtil.getExpressionTroughParenthesis(params[0]);
        if (param instanceof UnaryExpression) {
            final UnaryExpression not = (UnaryExpression) param;
            if (!OpenapiTypesUtil.is(not.getOperation(), PhpTokenTypes.opNOT)) {
                return false;
            }
            final PsiElement invertedParam = ExpressionSemanticUtil.getExpressionTroughParenthesis(not.getValue());
            if (null == invertedParam) {
                return false;
            }
            final String replacementMethod = function.equals("assertTrue") ? "assertNotTrue" : "assertNotFalse";
            holder.registerProblem(reference, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), replacementMethod), new TheLocalFix(holder.getProject(), replacementMethod, invertedParam));
            return true;
        }
    }
    return false;
}
Also used : UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) PsiElement(com.intellij.psi.PsiElement)

Example 14 with UnaryExpression

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

the class GenerateAlternativeFromIssetStrategy method generate.

@Nullable
public static String generate(@NotNull TernaryExpression expression) {
    /* handle inverted cases */
    PsiElement issetCandidate = ExpressionSemanticUtil.getExpressionTroughParenthesis(expression.getCondition());
    boolean isInverted = false;
    if (issetCandidate instanceof UnaryExpression) {
        final PsiElement operator = ((UnaryExpression) issetCandidate).getOperation();
        if (null != operator && PhpTokenTypes.opNOT == operator.getNode().getElementType()) {
            isInverted = true;
            issetCandidate = ((UnaryExpression) issetCandidate).getValue();
        }
    }
    /* verify condition structure */
    final PhpIsset isset = issetCandidate instanceof PhpIsset ? (PhpIsset) issetCandidate : null;
    if (null == isset || 1 != isset.getVariables().length) {
        return null;
    }
    /* verify subject match and alternative availability */
    final PsiElement subject = ExpressionSemanticUtil.getExpressionTroughParenthesis(isset.getVariables()[0]);
    final PsiElement value = ExpressionSemanticUtil.getExpressionTroughParenthesis(isInverted ? expression.getFalseVariant() : expression.getTrueVariant());
    final PsiElement alternative = ExpressionSemanticUtil.getExpressionTroughParenthesis(isInverted ? expression.getTrueVariant() : expression.getFalseVariant());
    if (null == subject || null == value || null == alternative || !OpenapiEquivalenceUtil.areEqual(subject, value)) {
        return null;
    }
    return subject.getText() + " ?? " + alternative.getText();
}
Also used : UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) PsiElement(com.intellij.psi.PsiElement) PhpIsset(com.jetbrains.php.lang.psi.elements.PhpIsset) Nullable(org.jetbrains.annotations.Nullable)

Example 15 with UnaryExpression

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

the class GenerateAlternativeFromArrayKeyExistsStrategy method generate.

@Nullable
public static String generate(@NotNull TernaryExpression expression) {
    /* handle inverted cases */
    PsiElement callCandidate = ExpressionSemanticUtil.getExpressionTroughParenthesis(expression.getCondition());
    boolean isInverted = false;
    if (callCandidate instanceof UnaryExpression) {
        final PsiElement operator = ((UnaryExpression) callCandidate).getOperation();
        if (null != operator && PhpTokenTypes.opNOT == operator.getNode().getElementType()) {
            isInverted = true;
            callCandidate = ((UnaryExpression) callCandidate).getValue();
        }
    }
    /* verify condition structure */
    final FunctionReference call = OpenapiTypesUtil.isFunctionReference(callCandidate) ? (FunctionReference) callCandidate : null;
    final String functionName = null == call ? null : call.getName();
    if (null == functionName || 2 != call.getParameters().length || !functionName.equals("array_key_exists")) {
        return null;
    }
    /* array_key_exists is valid only with null-alternatives */
    final PsiElement alternative = ExpressionSemanticUtil.getExpressionTroughParenthesis(isInverted ? expression.getTrueVariant() : expression.getFalseVariant());
    final PsiElement value = ExpressionSemanticUtil.getExpressionTroughParenthesis(isInverted ? expression.getFalseVariant() : expression.getTrueVariant());
    if (!(value instanceof ArrayAccessExpression) || !PhpLanguageUtil.isNull(alternative)) {
        return null;
    }
    /* verify condition and variant structure */
    final PsiElement[] params = call.getParameters();
    final ArrayAccessExpression array = (ArrayAccessExpression) value;
    final PsiElement container = array.getValue();
    final PsiElement index = null == array.getIndex() ? null : array.getIndex().getValue();
    if (null == params[0] || null == params[1] || null == container || null == index) {
        return null;
    }
    if (!OpenapiEquivalenceUtil.areEqual(params[1], container) || !OpenapiEquivalenceUtil.areEqual(params[0], index)) {
        return null;
    }
    return value.getText() + " ?? " + alternative.getText();
}
Also used : FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) ArrayAccessExpression(com.jetbrains.php.lang.psi.elements.ArrayAccessExpression) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable)

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