Search in sources :

Example 71 with BasePhpElementVisitor

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

the class IncorrectRandomRangeInspector 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 && functions.contains(functionName)) {
                final PsiElement[] arguments = reference.getParameters();
                if (arguments.length == 2) {
                    final Set<PsiElement> fromVariants = PossibleValuesDiscoveryUtil.discover(arguments[0]);
                    if (fromVariants.size() == 1) {
                        final PsiElement from = fromVariants.iterator().next();
                        if (OpenapiTypesUtil.isNumber(from)) {
                            final Set<PsiElement> toVariants = PossibleValuesDiscoveryUtil.discover(arguments[1]);
                            if (toVariants.size() == 1) {
                                final PsiElement to = toVariants.iterator().next();
                                if (OpenapiTypesUtil.isNumber(to)) {
                                    boolean isTarget;
                                    try {
                                        isTarget = Long.parseLong(to.getText()) < Long.parseLong(from.getText());
                                    } catch (final NumberFormatException wrongFormat) {
                                        isTarget = false;
                                    }
                                    if (isTarget) {
                                        holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(message));
                                    }
                                }
                            }
                            toVariants.clear();
                        }
                    }
                    fromVariants.clear();
                }
            }
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 72 with BasePhpElementVisitor

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

the class OffsetOperationsInspector method buildVisitor.

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

        @Override
        public void visitPhpArrayAccessExpression(@NotNull ArrayAccessExpression expression) {
            final PsiElement bracketNode = expression.getLastChild();
            if (null == bracketNode || null == expression.getValue()) {
                return;
            }
            // ensure offsets operations are supported, do nothing if no types were resolved
            final Set<String> allowedIndexTypes = new HashSet<>();
            if (!isContainerSupportsArrayAccess(holder.getProject(), expression, allowedIndexTypes) && !allowedIndexTypes.isEmpty()) {
                holder.registerProblem(expression, String.format(MessagesPresentationUtil.prefixWithEa(patternNoOffsetSupport), expression.getValue().getText(), allowedIndexTypes.toString()));
                allowedIndexTypes.clear();
                return;
            }
            // TODO: hash-elements e.g. array initialization
            if (!allowedIndexTypes.isEmpty() && expression.getIndex() != null) {
                final PhpPsiElement indexValue = expression.getIndex().getValue();
                if (indexValue instanceof PhpTypedElement) {
                    final PhpType resolved = OpenapiResolveUtil.resolveType((PhpTypedElement) indexValue, holder.getProject());
                    if (resolved != null) {
                        final Set<String> indexTypes = new HashSet<>();
                        resolved.filterUnknown().getTypes().forEach(t -> indexTypes.add(Types.getType(t)));
                        if (!indexTypes.isEmpty()) {
                            filterPossibleTypesWhichAreNotAllowed(indexTypes, allowedIndexTypes);
                            if (!indexTypes.isEmpty()) {
                                holder.registerProblem(indexValue, String.format(MessagesPresentationUtil.prefixWithEa(patternInvalidIndex), indexTypes.toString(), allowedIndexTypes.toString()));
                                indexTypes.clear();
                            }
                        }
                    }
                }
            }
            // clear valid types collection
            allowedIndexTypes.clear();
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) PhpType(com.jetbrains.php.lang.psi.resolve.types.PhpType) HashSet(java.util.HashSet) NotNull(org.jetbrains.annotations.NotNull)

Example 73 with BasePhpElementVisitor

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

the class IncrementDecrementOperationEquivalentInspector method buildVisitor.

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

        /* ensures we are not touching arrays only, not strings and not objects */
        private boolean isArrayAccessOrString(@Nullable PhpPsiElement variable) {
            if (variable instanceof ArrayAccessExpression) {
                final PsiElement container = ((ArrayAccessExpression) variable).getValue();
                if (container instanceof PhpTypedElement) {
                    final PhpType resolved = OpenapiResolveUtil.resolveType((PhpTypedElement) container, holder.getProject());
                    if (resolved != null) {
                        final Set<String> types = new HashSet<>();
                        resolved.filterUnknown().getTypes().forEach(t -> types.add(Types.getType(t)));
                        final boolean isArray = types.contains(Types.strArray) && !types.contains(Types.strString);
                        types.clear();
                        return !isArray;
                    }
                }
            }
            return false;
        }

        @Override
        public void visitPhpSelfAssignmentExpression(@NotNull SelfAssignmentExpression expression) {
            final IElementType operation = expression.getOperationType();
            final PhpPsiElement value = expression.getValue();
            final PhpPsiElement variable = expression.getVariable();
            if (null != value && null != operation && null != variable) {
                if (operation == PhpTokenTypes.opPLUS_ASGN) {
                    if (value.getText().equals("1") && !isArrayAccessOrString(variable)) {
                        final String replacement = PREFER_PREFIX_STYLE ? ("++" + variable.getText()) : (variable.getText() + "++");
                        holder.registerProblem(expression, MessagesPresentationUtil.prefixWithEa(patternMessage.replace("%e%", replacement)), new UseIncrementFix(replacement));
                    }
                } else if (operation == PhpTokenTypes.opMINUS_ASGN) {
                    if (value.getText().equals("1") && !isArrayAccessOrString(variable)) {
                        final String replacement = PREFER_PREFIX_STYLE ? ("--" + variable.getText()) : (variable.getText() + "--");
                        holder.registerProblem(expression, MessagesPresentationUtil.prefixWithEa(patternMessage.replace("%e%", replacement)), new UseDecrementFix(replacement));
                    }
                }
            }
        }

        @Override
        public void visitPhpAssignmentExpression(@NotNull AssignmentExpression assignmentExpression) {
            final PhpPsiElement variable = assignmentExpression.getVariable();
            if (variable != null && assignmentExpression.getValue() instanceof BinaryExpression) {
                final BinaryExpression value = (BinaryExpression) assignmentExpression.getValue();
                /* operation and operands provided */
                final PsiElement leftOperand = value.getLeftOperand();
                final PsiElement rightOperand = value.getRightOperand();
                final IElementType operation = value.getOperationType();
                if (null == leftOperand || null == rightOperand || null == operation) {
                    return;
                }
                if (operation == PhpTokenTypes.opPLUS) {
                    /* plus operation: operand position NOT important */
                    if ((leftOperand.getText().equals("1") && OpenapiEquivalenceUtil.areEqual(rightOperand, variable)) || (rightOperand.getText().equals("1") && OpenapiEquivalenceUtil.areEqual(leftOperand, variable))) {
                        if (!isArrayAccessOrString(variable)) {
                            final String replacement = PREFER_PREFIX_STYLE ? ("++" + variable.getText()) : (variable.getText() + "++");
                            holder.registerProblem(assignmentExpression, MessagesPresentationUtil.prefixWithEa(patternMessage.replace("%e%", replacement)), new UseIncrementFix(replacement));
                        }
                    }
                } else if (operation == PhpTokenTypes.opMINUS) {
                    /* minus operation: operand position IS important */
                    if (rightOperand.getText().equals("1") && OpenapiEquivalenceUtil.areEqual(leftOperand, variable) && !isArrayAccessOrString(variable)) {
                        final String replacement = PREFER_PREFIX_STYLE ? ("--" + variable.getText()) : (variable.getText() + "--");
                        holder.registerProblem(assignmentExpression, MessagesPresentationUtil.prefixWithEa(patternMessage.replace("%e%", replacement)), new UseDecrementFix(replacement));
                    }
                }
            }
        }
    };
}
Also used : 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) Nullable(org.jetbrains.annotations.Nullable) PsiElement(com.intellij.psi.PsiElement) HashSet(java.util.HashSet) NotNull(org.jetbrains.annotations.NotNull)

Example 74 with BasePhpElementVisitor

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

the class AutoloadingIssuesInspector method buildVisitor.

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

        @Override
        public void visitPhpFile(@NotNull PhpFile file) {
            final String fileName = file.getName();
            if (fileName.endsWith(".php") && !ignoredFiles.contains(fileName) && !laravelMigration.matcher(fileName).matches()) {
                final List<PhpClass> classes = new ArrayList<>();
                file.getTopLevelDefs().values().stream().filter(definition -> definition instanceof PhpClass).forEach(definition -> classes.add((PhpClass) definition));
                if (classes.size() == 1) {
                    final PhpClass clazz = classes.get(0);
                    final String className = clazz.getName();
                    /* PSR-0 classloading (Package_Subpackage_Class) naming */
                    String extractedClassName = className;
                    if (clazz.getFQN().lastIndexOf('\\') == 0 && extractedClassName.indexOf('_') != -1) {
                        extractedClassName = extractedClassName.substring(1 + extractedClassName.lastIndexOf('_'));
                    }
                    /* check the file name as per extraction compliant with PSR-0/PSR-4 standards */
                    final String expectedClassName = fileName.substring(0, fileName.indexOf('.'));
                    if (this.isBreakingPsrStandard(className, expectedClassName, extractedClassName) && !this.isWordpressStandard(className, fileName)) {
                        final PsiElement classNameNode = NamedElementUtil.getNameIdentifier(clazz);
                        if (classNameNode != null) {
                            holder.registerProblem(classNameNode, MessagesPresentationUtil.prefixWithEa(message));
                        }
                    }
                }
                classes.clear();
            }
        }

        private boolean isBreakingPsrStandard(@NotNull String className, @NotNull String expectedClassName, @NotNull String extractedClassName) {
            return !expectedClassName.equals(extractedClassName) && !expectedClassName.equals(className);
        }

        private boolean isWordpressStandard(@NotNull String className, @NotNull String fileName) {
            final String wordpressFileName = String.format("class-%s.php", className.toLowerCase().replaceAll("_", "-"));
            return fileName.endsWith(wordpressFileName);
        }
    };
}
Also used : PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) BasePhpInspection(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpInspection) Collection(java.util.Collection) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) List(java.util.List) PhpFile(com.jetbrains.php.lang.psi.PhpFile) MessagesPresentationUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.MessagesPresentationUtil) PsiElement(com.intellij.psi.PsiElement) NamedElementUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.NamedElementUtil) Pattern(java.util.regex.Pattern) NotNull(org.jetbrains.annotations.NotNull) PsiElementVisitor(com.intellij.psi.PsiElementVisitor) ProblemsHolder(com.intellij.codeInspection.ProblemsHolder) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) PhpFile(com.jetbrains.php.lang.psi.PhpFile) PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) ArrayList(java.util.ArrayList) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 75 with BasePhpElementVisitor

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

the class ClassMethodNameMatchesFieldNameInspector method buildVisitor.

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

        @Override
        public void visitPhpMethod(@NotNull Method method) {
            final PhpClass clazz = method.getContainingClass();
            if (clazz != null && !clazz.isInterface()) {
                final Field field = OpenapiResolveUtil.resolveField(clazz, method.getName());
                if (field != null) {
                    final PsiElement nameNode = NamedElementUtil.getNameIdentifier(method);
                    final PhpType resolvedType = OpenapiResolveUtil.resolveType(field, holder.getProject());
                    if (resolvedType != null && nameNode != null) {
                        final PhpType knownType = resolvedType.filterUnknown();
                        if (knownType.isEmpty()) {
                            holder.registerProblem(nameNode, MessagesPresentationUtil.prefixWithEa(messageFieldType));
                        } else {
                            final boolean isCallable = knownType.getTypes().stream().anyMatch(t -> Types.getType(t).equals(Types.strCallable));
                            if (isCallable) {
                                holder.registerProblem(nameNode, MessagesPresentationUtil.prefixWithEa(messageMatches));
                            }
                        }
                    }
                }
            }
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) Field(com.jetbrains.php.lang.psi.elements.Field) PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) Method(com.jetbrains.php.lang.psi.elements.Method) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) PhpType(com.jetbrains.php.lang.psi.resolve.types.PhpType) 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