Search in sources :

Example 6 with ClassReference

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

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

the class InstanceOfTraitStrategy method apply.

public static boolean apply(@NotNull BinaryExpression expression, @NotNull ProblemsHolder holder) {
    /* general structure expectations */
    if (expression.getOperationType() != PhpTokenTypes.kwINSTANCEOF) {
        return false;
    }
    final PsiElement right = expression.getRightOperand();
    if (!(right instanceof ClassReference) && !(right instanceof ClassConstantReference)) {
        return false;
    }
    /* $this, self, static are referencing to host classes, skip the case */
    if (lateBindingSymbols.contains(right.getText())) {
        return false;
    }
    /* getting class from invariant constructs  */
    PsiElement resolved = null;
    if (right instanceof ClassReference) {
        resolved = OpenapiResolveUtil.resolveReference((ClassReference) right);
    }
    if (right instanceof ClassConstantReference) {
        final ClassConstantReference ref = (ClassConstantReference) right;
        final PsiElement classReference = ref.getClassReference();
        final String constantName = ref.getName();
        if (null != constantName && constantName.equals("class") && classReference instanceof ClassReference) {
            resolved = OpenapiResolveUtil.resolveReference((ClassReference) classReference);
        }
    }
    /* analysis itself */
    if (resolved instanceof PhpClass && ((PhpClass) resolved).isTrait()) {
        holder.registerProblem(expression, MessagesPresentationUtil.prefixWithEa(message));
        return true;
    }
    return false;
}
Also used : PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) ClassReference(com.jetbrains.php.lang.psi.elements.ClassReference) PsiElement(com.intellij.psi.PsiElement) ClassConstantReference(com.jetbrains.php.lang.psi.elements.ClassConstantReference)

Example 8 with ClassReference

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

the class ClassReImplementsParentInterfaceInspector method buildVisitor.

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

        @Override
        public void visitPhpClass(@NotNull PhpClass clazz) {
            final List<ClassReference> implemented = clazz.getImplementsList().getReferenceElements();
            if (!implemented.isEmpty()) {
                /* resolve own interfaces an maintain relation to original element */
                final Map<PsiElement, PhpClass> ownInterfaces = new LinkedHashMap<>(implemented.size());
                for (final ClassReference reference : implemented) {
                    final PsiElement resolved = OpenapiResolveUtil.resolveReference(reference);
                    if (resolved instanceof PhpClass) {
                        ownInterfaces.put(reference, (PhpClass) resolved);
                    }
                }
                implemented.clear();
                if (!ownInterfaces.isEmpty()) {
                    /* Case: indirect declaration duplication (parent already implements) */
                    final PhpClass parent = OpenapiResolveUtil.resolveSuperClass(clazz);
                    if (parent != null) {
                        final Set<PhpClass> inherited = InterfacesExtractUtil.getCrawlInheritanceTree(parent, false);
                        if (!inherited.isEmpty()) {
                            final Set<PsiElement> processed = new HashSet<>();
                            for (final Map.Entry<PsiElement, PhpClass> entry : ownInterfaces.entrySet()) {
                                final PhpClass ownInterface = entry.getValue();
                                if (inherited.contains(ownInterface) && processed.add(entry.getKey())) {
                                    holder.registerProblem(entry.getKey(), String.format(MessagesPresentationUtil.prefixWithEa(patternIndirectDuplication), ownInterface.getFQN(), parent.getFQN()), new TheLocalFix());
                                }
                            }
                            processed.clear();
                            inherited.clear();
                        }
                    }
                    ownInterfaces.clear();
                }
            }
        }
    };
}
Also used : PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) NotNull(org.jetbrains.annotations.NotNull) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) ClassReference(com.jetbrains.php.lang.psi.elements.ClassReference) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 9 with ClassReference

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

the class ImplicitMagicMethodCallInspector method buildVisitor.

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

        @Override
        public void visitPhpMethodReference(@NotNull MethodReference reference) {
            final String methodName = reference.getName();
            if (methodName != null && methods.contains(methodName)) {
                /* Pattern 1: direct calls ob objects */
                final String referenceObject = reference.getFirstChild().getText().trim();
                if (!referenceObject.equals("$this") && !this.isTestContext(reference)) {
                    if (!(reference.getFirstChild() instanceof ClassReference) && !referenceObject.equals("parent")) {
                        /* __toString is a special case */
                        if (SUGGEST_USING_STRING_CASTING && methodName.equals("__toString")) {
                            final String message = patternStringCasting.replace("%o%", referenceObject);
                            holder.registerProblem(reference, message, new UseStringCastingLocalFix());
                            return;
                        }
                        /* allow calling __toString, as a developer don't want hints on this */
                        if (!SUGGEST_USING_STRING_CASTING && methodName.equals("__toString")) {
                            return;
                        }
                        /* generally reported cases */
                        holder.registerProblem(reference, message);
                        return;
                    }
                    /* Pattern 2: internal calls inside class methods */
                    final Function method = ExpressionSemanticUtil.getScope(reference);
                    if (null != method && !method.getName().equals(methodName)) {
                        /* allow __construct inside unserialize */
                        if (methodName.equals("__construct") && method.getName().equals("unserialize")) {
                            return;
                        }
                        /* allow calling __toString, as a developer don't want hints on this */
                        if (!SUGGEST_USING_STRING_CASTING && methodName.equals("__toString")) {
                            return;
                        }
                        holder.registerProblem(reference, message);
                    }
                }
            }
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) Function(com.jetbrains.php.lang.psi.elements.Function) MethodReference(com.jetbrains.php.lang.psi.elements.MethodReference) ClassReference(com.jetbrains.php.lang.psi.elements.ClassReference) NotNull(org.jetbrains.annotations.NotNull) NotNull(org.jetbrains.annotations.NotNull)

Example 10 with ClassReference

use of com.jetbrains.php.lang.psi.elements.ClassReference in project idea-php-typo3-plugin by cedricziel.

the class LegacyClassesForIdeQuickFix method applyFix.

@Override
public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) {
    PsiElement psiElement = descriptor.getPsiElement();
    if (DumbService.isDumb(project)) {
        showIsInDumpModeMessage(project, psiElement);
        return;
    }
    if (psiElement instanceof ClassReference) {
        ClassReference classReference = (ClassReference) psiElement;
        String fqn = classReference.getFQN();
        if (fqn != null) {
            String replacementFQN = LegacyClassesForIDEIndex.findReplacementClass(project, fqn);
            if (replacementFQN != null) {
                try {
                    classReference.replace(PhpPsiElementFactory.createClassReference(project, replacementFQN));
                } catch (IncorrectOperationException e) {
                    showErrorMessage(project, "Could not replace class reference", psiElement);
                }
            }
        }
    }
}
Also used : ClassReference(com.jetbrains.php.lang.psi.elements.ClassReference) IncorrectOperationException(com.intellij.util.IncorrectOperationException) PsiElement(com.intellij.psi.PsiElement)

Aggregations

ClassReference (com.jetbrains.php.lang.psi.elements.ClassReference)10 PsiElement (com.intellij.psi.PsiElement)8 NotNull (org.jetbrains.annotations.NotNull)8 BasePhpElementVisitor (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor)7 PhpClass (com.jetbrains.php.lang.psi.elements.PhpClass)4 IElementType (com.intellij.psi.tree.IElementType)2 BinaryExpression (com.jetbrains.php.lang.psi.elements.BinaryExpression)2 FunctionReference (com.jetbrains.php.lang.psi.elements.FunctionReference)2 NewExpression (com.jetbrains.php.lang.psi.elements.NewExpression)2 ParenthesizedExpression (com.jetbrains.php.lang.psi.elements.ParenthesizedExpression)2 ArrayList (java.util.ArrayList)2 Objects (java.util.Objects)2 Nullable (org.jetbrains.annotations.Nullable)2 IncorrectOperationException (com.intellij.util.IncorrectOperationException)1 ClassConstantReference (com.jetbrains.php.lang.psi.elements.ClassConstantReference)1 Function (com.jetbrains.php.lang.psi.elements.Function)1 Method (com.jetbrains.php.lang.psi.elements.Method)1 MethodReference (com.jetbrains.php.lang.psi.elements.MethodReference)1 PhpPsiElement (com.jetbrains.php.lang.psi.elements.PhpPsiElement)1 StringLiteralExpression (com.jetbrains.php.lang.psi.elements.StringLiteralExpression)1