Search in sources :

Example 16 with PhpClass

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

the class MagicMethodsValidityInspector method buildVisitor.

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

        @Override
        public void visitPhpMethod(@NotNull Method method) {
            final PhpClass clazz = method.getContainingClass();
            final String methodName = method.getName();
            final PsiElement nameNode = NamedElementUtil.getNameIdentifier(method);
            if (clazz == null || nameNode == null || !methodName.startsWith("_") || method.isAbstract()) {
                return;
            }
            switch(methodName) {
                case "__construct":
                    CanNotBeStaticStrategy.apply(method, holder);
                    CanNotReturnTypeStrategy.apply(method, holder);
                    if (!this.isTestContext(clazz)) {
                        NormallyCallsParentMethodStrategy.apply(method, holder);
                    }
                    break;
                case "__destruct":
                case "__clone":
                    CanNotBeStaticStrategy.apply(method, holder);
                    CanNotReturnTypeStrategy.apply(method, holder);
                    CanNotTakeArgumentsStrategy.apply(method, holder);
                    NormallyCallsParentMethodStrategy.apply(method, holder);
                    break;
                case "__get":
                case "__isset":
                case "__unset":
                    TakesExactAmountOfArgumentsStrategy.apply(1, method, holder);
                    CanNotBeStaticStrategy.apply(method, holder);
                    MustBePublicStrategy.apply(method, holder);
                    CanNotTakeArgumentsByReferenceStrategy.apply(method, holder);
                    HasAlsoMethodStrategy.apply(method, "__set", holder);
                    break;
                case "__set":
                case "__call":
                    TakesExactAmountOfArgumentsStrategy.apply(2, method, holder);
                    CanNotBeStaticStrategy.apply(method, holder);
                    MustBePublicStrategy.apply(method, holder);
                    CanNotTakeArgumentsByReferenceStrategy.apply(method, holder);
                    if (methodName.equals("__set")) {
                        HasAlsoMethodStrategy.apply(method, "__isset", holder);
                        HasAlsoMethodStrategy.apply(method, "__get", holder);
                    }
                    break;
                case "__callStatic":
                    TakesExactAmountOfArgumentsStrategy.apply(2, method, holder);
                    MustBeStaticStrategy.apply(method, holder);
                    MustBePublicStrategy.apply(method, holder);
                    CanNotTakeArgumentsByReferenceStrategy.apply(method, holder);
                    break;
                case "__toString":
                    CanNotBeStaticStrategy.apply(method, holder);
                    CanNotTakeArgumentsStrategy.apply(method, holder);
                    MustBePublicStrategy.apply(method, holder);
                    MustReturnSpecifiedTypeStrategy.apply(stringType, method, holder);
                    break;
                case "__debugInfo":
                    CanNotBeStaticStrategy.apply(method, holder);
                    CanNotTakeArgumentsStrategy.apply(method, holder);
                    MustBePublicStrategy.apply(method, holder);
                    MustReturnSpecifiedTypeStrategy.apply(arrayOrNullType, method, holder);
                    MinimalPhpVersionStrategy.apply(method, holder, PhpLanguageLevel.PHP560);
                    break;
                case "__set_state":
                    TakesExactAmountOfArgumentsStrategy.apply(1, method, holder);
                    MustBeStaticStrategy.apply(method, holder);
                    MustBePublicStrategy.apply(method, holder);
                    final PhpType returnTypes = (new PhpType()).add(clazz.getFQN()).add(Types.strStatic);
                    MustReturnSpecifiedTypeStrategy.apply(returnTypes, method, holder);
                    break;
                case "__invoke":
                    CanNotBeStaticStrategy.apply(method, holder);
                    MustBePublicStrategy.apply(method, holder);
                    break;
                case "__wakeup":
                    CanNotBeStaticStrategy.apply(method, holder);
                    CanNotTakeArgumentsStrategy.apply(method, holder);
                    CanNotReturnTypeStrategy.apply(method, holder);
                    break;
                case "__unserialize":
                    CanNotBeStaticStrategy.apply(method, holder);
                    MustBePublicStrategy.apply(method, holder);
                    TakesExactAmountOfArgumentsStrategy.apply(1, method, holder);
                    CanNotReturnTypeStrategy.apply(method, holder);
                    break;
                case "__sleep":
                case "__serialize":
                    CanNotBeStaticStrategy.apply(method, holder);
                    MustBePublicStrategy.apply(method, holder);
                    CanNotTakeArgumentsStrategy.apply(method, holder);
                    MustReturnSpecifiedTypeStrategy.apply(arrayType, method, holder);
                    break;
                case "__autoload":
                    TakesExactAmountOfArgumentsStrategy.apply(1, method, holder);
                    CanNotReturnTypeStrategy.apply(method, holder);
                    holder.registerProblem(nameNode, MessagesPresentationUtil.prefixWithEa(messageUseSplAutoloading), ProblemHighlightType.LIKE_DEPRECATED);
                    break;
                default:
                    if (methodName.startsWith("__") && !knownNonMagic.contains(methodName)) {
                        holder.registerProblem(nameNode, MessagesPresentationUtil.prefixWithEa(messageNotMagic));
                    } else {
                        MissingUnderscoreStrategy.apply(method, holder);
                    }
                    break;
            }
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) 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)

Example 17 with PhpClass

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

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

Example 19 with PhpClass

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

the class DeprecatedConstructorStyleInspector method buildVisitor.

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

        @Override
        public void visitPhpMethod(@NotNull Method method) {
            if (!method.isStatic()) {
                final PhpClass clazz = method.getContainingClass();
                final PsiElement nameNode = NamedElementUtil.getNameIdentifier(method);
                if (clazz != null && nameNode != null && !clazz.isTrait() && !clazz.isInterface()) {
                    final String className = clazz.getName();
                    if (className.equals(method.getName()) && clazz.findOwnMethodByName("__construct") == null) {
                        holder.registerProblem(nameNode, MessagesPresentationUtil.prefixWithEa(String.format(messagePattern, className)), ProblemHighlightType.LIKE_DEPRECATED, new RenameConstructorFix());
                    }
                }
            }
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) Method(com.jetbrains.php.lang.psi.elements.Method) NotNull(org.jetbrains.annotations.NotNull) LeafPsiElement(com.intellij.psi.impl.source.tree.LeafPsiElement) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 20 with PhpClass

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

the class EmptyClassInspector method buildVisitor.

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

        @Override
        public void visitPhpClass(@NotNull PhpClass clazz) {
            if (!clazz.isInterface() && !clazz.isDeprecated() && !clazz.isAnonymous()) {
                final boolean isEmpty = clazz.getOwnFields().length == 0 && clazz.getOwnMethods().length == 0 && clazz.getTraits().length == 0;
                if (isEmpty) {
                    final PhpClass parent = OpenapiResolveUtil.resolveSuperClass(clazz);
                    if (parent != null) {
                        /* we can be forced to introduce an empty class: abstract parent, exception classes */
                        final boolean skip = parent.isAbstract() || InterfacesExtractUtil.getCrawlInheritanceTree(clazz, true).stream().anyMatch(c -> c.getFQN().equals("\\Exception"));
                        if (skip) {
                            return;
                        }
                    }
                    final PsiElement nameNode = NamedElementUtil.getNameIdentifier(clazz);
                    if (nameNode != null) {
                        holder.registerProblem(nameNode, MessagesPresentationUtil.prefixWithEa(message));
                    }
                }
            }
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) BasePhpInspection(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpInspection) OpenapiResolveUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.OpenapiResolveUtil) MessagesPresentationUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.MessagesPresentationUtil) InterfacesExtractUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.hierarhy.InterfacesExtractUtil) PsiElement(com.intellij.psi.PsiElement) NamedElementUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.NamedElementUtil) NotNull(org.jetbrains.annotations.NotNull) PsiElementVisitor(com.intellij.psi.PsiElementVisitor) ProblemsHolder(com.intellij.codeInspection.ProblemsHolder) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

PhpClass (com.jetbrains.php.lang.psi.elements.PhpClass)35 PsiElement (com.intellij.psi.PsiElement)26 NotNull (org.jetbrains.annotations.NotNull)19 BasePhpElementVisitor (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor)14 Method (com.jetbrains.php.lang.psi.elements.Method)11 PhpIndex (com.jetbrains.php.PhpIndex)8 ProblemsHolder (com.intellij.codeInspection.ProblemsHolder)7 PhpType (com.jetbrains.php.lang.psi.resolve.types.PhpType)7 MessagesPresentationUtil (com.kalessil.phpStorm.phpInspectionsEA.utils.MessagesPresentationUtil)6 OpenapiResolveUtil (com.kalessil.phpStorm.phpInspectionsEA.utils.OpenapiResolveUtil)6 PsiElementVisitor (com.intellij.psi.PsiElementVisitor)5 Field (com.jetbrains.php.lang.psi.elements.Field)5 BasePhpInspection (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpInspection)5 HashSet (java.util.HashSet)5 Project (com.intellij.openapi.project.Project)4 ClassReference (com.jetbrains.php.lang.psi.elements.ClassReference)4 ArrayList (java.util.ArrayList)4 List (java.util.List)4 ProblemHighlightType (com.intellij.codeInspection.ProblemHighlightType)3 Editor (com.intellij.openapi.editor.Editor)3