Search in sources :

Example 31 with BasePhpElementVisitor

use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.

the class StrtotimeUsageInspector 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("strtotime")) {
                return;
            }
            final PsiElement[] arguments = reference.getParameters();
            if (arguments.length == 0 || arguments.length > 2) {
                return;
            }
            /* handle case: strtotime("now") -> time() */
            if (arguments.length == 1) {
                if (arguments[0] instanceof StringLiteralExpression) {
                    final StringLiteralExpression pattern = (StringLiteralExpression) arguments[0];
                    if (pattern.getContents().equalsIgnoreCase("now")) {
                        holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messageUseTime), new UseTimeFunctionLocalFix());
                    }
                }
            } else /* handle case: strtotime(..., time()) -> date(...) */
            if (arguments.length == 2) {
                if (OpenapiTypesUtil.isFunctionReference(arguments[1])) {
                    final FunctionReference candidate = (FunctionReference) arguments[1];
                    final String candidateName = candidate.getName();
                    if (candidateName != null && candidateName.equals("time") && this.isFromRootNamespace(candidate)) {
                        final String replacement = "strtotime(%a%)".replace("%a%", arguments[0].getText());
                        holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messageDropTime), ProblemHighlightType.LIKE_UNUSED_SYMBOL, new DropTimeFunctionCallLocalFix(replacement));
                    }
                }
            }
        }
    };
}
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) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 32 with BasePhpElementVisitor

use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.

the class GetDebugTypeCanBeUsedInspector method buildVisitor.

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

        @Override
        public void visitPhpTernaryExpression(@NotNull TernaryExpression ternary) {
            if (!ternary.isShort()) {
                final PsiElement condition = ternary.getCondition();
                if (OpenapiTypesUtil.isFunctionReference(condition)) {
                    final FunctionReference reference = (FunctionReference) condition;
                    final String functionName = reference.getName();
                    if (functionName != null && functionName.equals("is_object")) {
                        final boolean isTargetVersion = PhpLanguageLevel.get(holder.getProject()).atLeast(PhpLanguageLevel.PHP800);
                        if (isTargetVersion) {
                            final PsiElement[] arguments = reference.getParameters();
                            if (arguments.length == 1 && arguments[0] != null) {
                                final PsiElement positive = ternary.getTrueVariant();
                                final PsiElement negative = ternary.getFalseVariant();
                                if (positive != null && negative != null) {
                                    final boolean isTarget = this.is(positive, "get_class", arguments[0]) && this.is(negative, "gettype", arguments[0]);
                                    if (isTarget && this.isFromRootNamespace(reference)) {
                                        final String replacement = String.format("%sget_debug_type(%s)", reference.getImmediateNamespaceName(), arguments[0].getText());
                                        holder.registerProblem(ternary, String.format(MessagesPresentationUtil.prefixWithEa(message), replacement), new UseGetDebugTypeFix(replacement));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        private boolean is(@NotNull PsiElement candidate, @NotNull String targetName, @NotNull PsiElement targetArgument) {
            if (OpenapiTypesUtil.isFunctionReference(candidate)) {
                final FunctionReference reference = (FunctionReference) candidate;
                final String functionName = reference.getName();
                if (functionName != null && functionName.equals(targetName)) {
                    final PsiElement[] arguments = reference.getParameters();
                    if (arguments.length == 1 && arguments[0] != null) {
                        return OpenapiEquivalenceUtil.areEqual(arguments[0], targetArgument) && this.isFromRootNamespace(reference);
                    }
                }
            }
            return false;
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) TernaryExpression(com.jetbrains.php.lang.psi.elements.TernaryExpression) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 33 with BasePhpElementVisitor

use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.

the class DynamicCallsToScopeIntrospectionInspector method buildVisitor.

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

        @Override
        public void visitPhpFunctionCall(@NotNull FunctionReference reference) {
            if (PhpLanguageLevel.get(holder.getProject()).atLeast(PhpLanguageLevel.PHP710)) {
                final String functionName = reference.getName();
                if (functionName != null) {
                    /* discover target element */
                    final PsiElement target;
                    if (functionName.isEmpty()) {
                        final PsiElement[] children = reference.getChildren();
                        target = children.length == 2 ? children[0] : null;
                    } else if (callbacksPositions.containsKey(functionName)) {
                        final int callbackPosition = callbacksPositions.get(functionName);
                        final PsiElement[] arguments = reference.getParameters();
                        target = arguments.length >= callbackPosition + 1 ? arguments[callbackPosition] : null;
                    } else {
                        target = null;
                    }
                    /* discover the target function */
                    if (target != null) {
                        final StringLiteralExpression literal = ExpressionSemanticUtil.resolveAsStringLiteral(target);
                        if (literal != null) {
                            final String raw = PhpStringUtil.unescapeText(literal.getContents(), literal.isSingleQuote());
                            final String callback = raw.startsWith("\\") ? raw.substring(1) : raw;
                            if (targetCalls.containsKey(callback)) {
                                holder.registerProblem(target, String.format(MessagesPresentationUtil.prefixWithEa(messagePattern), callback));
                            }
                        }
                    }
                }
            }
        }
    };
}
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) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 34 with BasePhpElementVisitor

use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.

the class CascadingDirnameCallsInspector 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("dirname")) {
                return;
            }
            final PsiElement[] arguments = reference.getParameters();
            if (arguments.length != 1 && arguments.length != 2) {
                return;
            }
            /* require PHP7+, where 2nd parameter has been added */
            if (PhpLanguageLevel.get(holder.getProject()).below(PhpLanguageLevel.PHP700)) {
                return;
            }
            /* don't report nested calls, we want to report the one on top level */
            final PsiElement parent = reference.getParent();
            if (parent instanceof ParameterList && parent.getParent() instanceof FunctionReference) {
                final FunctionReference parentReference = (FunctionReference) parent.getParent();
                final String parentName = parentReference.getName();
                if (parentName != null && parentName.equals("dirname")) {
                    final PsiElement[] parentArguments = parentReference.getParameters();
                    if (parentArguments.length == 1 || parentArguments.length == 2) {
                        return;
                    }
                }
            }
            int directoryLevel = 0;
            PsiElement argument = null;
            final List<PsiElement> levels = new ArrayList<>();
            FunctionReference current = reference;
            while (current instanceof FunctionReference) {
                final String currentName = current.getName();
                if (currentName == null || !currentName.equals("dirname")) {
                    break;
                }
                final PsiElement[] currentArguments = current.getParameters();
                if (currentArguments.length == 1) {
                    argument = currentArguments[0];
                    ++directoryLevel;
                } else if (currentArguments.length == 2) {
                    argument = currentArguments[0];
                    levels.add(currentArguments[1]);
                } else {
                    break;
                }
                if (!(currentArguments[0] instanceof FunctionReference)) {
                    break;
                }
                current = (FunctionReference) currentArguments[0];
            }
            /* if no nested dirname calls, stop analysis */
            if (current == reference) {
                levels.clear();
                return;
            }
            /* if we have 1+ nested call (top-level one is not considered) */
            if (argument != null && arguments[0] != argument) {
                /* process extracted level expressions: numbers to sum-up, expressions to stay */
                final List<String> reported = new ArrayList<>();
                for (PsiElement levelEntry : levels) {
                    try {
                        directoryLevel += Integer.parseInt(levelEntry.getText());
                    } catch (NumberFormatException fail) {
                        reported.add(levelEntry.getText());
                    }
                }
                levels.clear();
                /* do not report cases with one level extraction */
                if (1 == directoryLevel && reported.isEmpty()) {
                    return;
                }
                /* generate the replacement expression */
                reported.add(0, String.valueOf(directoryLevel));
                final String replacement = "dirname(%a%, %l%)".replace("%a%", argument.getText()).replace("%l%", String.join(" + ", reported));
                reported.clear();
                holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messagePattern.replace("%e%", replacement)), new TheLocalFix(replacement));
            }
        }
    };
}
Also used : ArrayList(java.util.ArrayList) NotNull(org.jetbrains.annotations.NotNull) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) ParameterList(com.jetbrains.php.lang.psi.elements.ParameterList) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 35 with BasePhpElementVisitor

use of com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor in project phpinspectionsea by kalessil.

the class FopenBinaryUnsafeUsageInspector 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("fopen")) {
                final PsiElement[] arguments = reference.getParameters();
                if (arguments.length >= 2) {
                    /* verify if mode provided and has no 'b' already */
                    final StringLiteralExpression mode = ExpressionSemanticUtil.resolveAsStringLiteral(arguments[1]);
                    final String modeText = mode == null ? null : mode.getContents();
                    if (modeText != null && !modeText.isEmpty()) {
                        if (modeText.indexOf('b') != -1) {
                            final boolean isCorrectlyPlaced = modeText.endsWith("b") || modeText.endsWith("b+");
                            if (!isCorrectlyPlaced) {
                                holder.registerProblem(arguments[1], MessagesPresentationUtil.prefixWithEa(messageMisplacedBinaryMode), ProblemHighlightType.GENERIC_ERROR, new TheLocalFix(holder.getProject(), mode));
                            }
                        } else if (modeText.indexOf('t') != -1) {
                            if (ENFORCE_BINARY_MODIFIER_USAGE) {
                                holder.registerProblem(arguments[1], MessagesPresentationUtil.prefixWithEa(messageReplaceWithBinaryMode), new TheLocalFix(holder.getProject(), mode));
                            }
                        } else {
                            if (ENFORCE_BINARY_MODIFIER_USAGE) {
                                holder.registerProblem(arguments[1], MessagesPresentationUtil.prefixWithEa(messageUseBinaryMode), new TheLocalFix(holder.getProject(), mode));
                            }
                        }
                    }
                }
            }
        }
    };
}
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) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

BasePhpElementVisitor (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor)169 NotNull (org.jetbrains.annotations.NotNull)169 PsiElement (com.intellij.psi.PsiElement)157 FunctionReference (com.jetbrains.php.lang.psi.elements.FunctionReference)43 ProblemsHolder (com.intellij.codeInspection.ProblemsHolder)40 BasePhpInspection (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpInspection)39 PsiElementVisitor (com.intellij.psi.PsiElementVisitor)37 PhpType (com.jetbrains.php.lang.psi.resolve.types.PhpType)33 IElementType (com.intellij.psi.tree.IElementType)32 com.jetbrains.php.lang.psi.elements (com.jetbrains.php.lang.psi.elements)29 Project (com.intellij.openapi.project.Project)25 BinaryExpression (com.jetbrains.php.lang.psi.elements.BinaryExpression)25 HashSet (java.util.HashSet)24 PsiTreeUtil (com.intellij.psi.util.PsiTreeUtil)22 MessagesPresentationUtil (com.kalessil.phpStorm.phpInspectionsEA.utils.MessagesPresentationUtil)19 StringLiteralExpression (com.jetbrains.php.lang.psi.elements.StringLiteralExpression)18 ArrayList (java.util.ArrayList)18 Set (java.util.Set)18 Nullable (org.jetbrains.annotations.Nullable)18 PhpTokenTypes (com.jetbrains.php.lang.lexer.PhpTokenTypes)17