Search in sources :

Example 1 with PhpIndex

use of com.jetbrains.php.PhpIndex in project phpinspectionsea by kalessil.

the class OffsetOperationsInspector method isContainerSupportsArrayAccess.

@SuppressWarnings("BooleanMethodIsAlwaysInverted")
private boolean isContainerSupportsArrayAccess(@NotNull ArrayAccessExpression expression, @NotNull Set<String> indexTypesSupported) {
    // ok JB parses `$var[]= ...` always as array, lets make it working properly and report them later
    final PsiElement container = expression.getValue();
    if (null == container) {
        return false;
    }
    final Set<String> containerTypes = new HashSet<>();
    if (container instanceof PhpTypedElement) {
        final PhpType type = OpenapiResolveUtil.resolveType((PhpTypedElement) container, container.getProject());
        if (type != null && !type.hasUnknown()) {
            type.getTypes().forEach(t -> containerTypes.add(Types.getType(t)));
        }
    }
    /* === cleanup resolved types === */
    if (containerTypes.contains(Types.strMixed)) {
        // mixed are not analyzable
        containerTypes.clear();
        return true;
    }
    if (containerTypes.size() == 2 && containerTypes.contains(Types.strString)) {
        final boolean isForeachKeyType = containerTypes.contains(Types.strInteger);
        final boolean isCoreApiStringType = containerTypes.contains(Types.strBoolean);
        if (isForeachKeyType || isCoreApiStringType) {
            containerTypes.clear();
            return true;
        }
    }
    if (containerTypes.contains(Types.strCallable)) {
        // treat callable as array
        containerTypes.remove(Types.strCallable);
        containerTypes.add(Types.strArray);
        containerTypes.add(Types.strString);
    }
    // don't process nulls
    containerTypes.remove(Types.strNull);
    // don't process generalized objects
    containerTypes.remove(Types.strObject);
    // don't process mysterious empty set type
    containerTypes.remove(Types.strEmptySet);
    /* === if we could not resolve container, do nothing === */
    if (containerTypes.isEmpty()) {
        return true;
    }
    final Project project = container.getProject();
    final PhpIndex index = PhpIndex.getInstance(project);
    boolean supportsOffsets = false;
    for (final String typeToCheck : containerTypes) {
        // commonly used case: string and array
        if (typeToCheck.equals(Types.strArray) || typeToCheck.equals(Types.strString)) {
            supportsOffsets = true;
            /* here we state which regular index types we want to promote */
            indexTypesSupported.add(Types.strString);
            indexTypesSupported.add(Types.strInteger);
            continue;
        }
        // some of possible types are scalars, what's wrong
        if (!typeToCheck.isEmpty() && typeToCheck.charAt(0) != '\\') {
            supportsOffsets = false;
            break;
        }
        // now we are at point when analyzing classes only
        final List<PhpClass> classes = OpenapiResolveUtil.resolveClassesAndInterfacesByFQN(typeToCheck, index);
        for (final PhpClass clazz : classes) {
            /* custom offsets management, follow annotated types */
            for (final String methodName : Arrays.asList("offsetGet", "offsetSet", "__get", "__set")) {
                final Method method = OpenapiResolveUtil.resolveMethod(clazz, methodName);
                if (method != null) {
                    /* regular array index types can be applied */
                    if (methodName.startsWith("__")) {
                        indexTypesSupported.add(Types.strString);
                        indexTypesSupported.add(Types.strInteger);
                    } else /* user-defined index types can be applied */
                    {
                        final Parameter[] parameters = method.getParameters();
                        if (parameters.length > 0) {
                            final PhpType type = OpenapiResolveUtil.resolveType(parameters[0], project);
                            if (type != null) {
                                type.filterUnknown().getTypes().forEach(t -> indexTypesSupported.add(Types.getType(t)));
                            }
                        }
                    }
                    supportsOffsets = true;
                }
            }
        }
        classes.clear();
    }
    // when might not support offset access, reuse types container to report back why
    if (!supportsOffsets) {
        indexTypesSupported.clear();
        indexTypesSupported.addAll(containerTypes);
    }
    containerTypes.clear();
    return supportsOffsets;
}
Also used : PhpIndex(com.jetbrains.php.PhpIndex) PhpType(com.jetbrains.php.lang.psi.resolve.types.PhpType) Project(com.intellij.openapi.project.Project) PsiElement(com.intellij.psi.PsiElement) HashSet(java.util.HashSet)

Example 2 with PhpIndex

use of com.jetbrains.php.PhpIndex in project phpinspectionsea by kalessil.

the class ComparableCoreClassesStrategy method isComparableObject.

private static boolean isComparableObject(@NotNull PsiElement operand, @NotNull PhpIndex index) {
    /* extract types of operand, check if classes are/inherited from \DateTime */
    final Set<String> operandTypes = new HashSet<>();
    if (operand instanceof PhpTypedElement) {
        final PhpType resolved = OpenapiResolveUtil.resolveType((PhpTypedElement) operand, operand.getProject());
        if (resolved != null) {
            resolved.filterUnknown().getTypes().forEach(t -> operandTypes.add(Types.getType(t)));
        }
    }
    if (!TypesSemanticsUtil.isNullableObjectInterface(operandTypes)) {
        operandTypes.clear();
        return false;
    }
    /* collect classes to check for \DateTime relationship */
    final List<PhpClass> operandClasses = new ArrayList<>();
    operandTypes.stream().filter(fqn -> fqn.charAt(0) == '\\').forEach(fqn -> operandClasses.addAll(OpenapiResolveUtil.resolveClassesAndInterfacesByFQN(fqn, index)));
    operandTypes.clear();
    /* inspect classes for being a/child of special once */
    for (final PhpClass clazz : operandClasses) {
        final HashSet<PhpClass> hierarchy = InterfacesExtractUtil.getCrawlInheritanceTree(clazz, true);
        for (final PhpClass oneClass : hierarchy) {
            if (comparableObjects.contains(oneClass.getFQN())) {
                return true;
            }
        }
        hierarchy.clear();
    }
    operandClasses.clear();
    return false;
}
Also used : PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) ExpressionSemanticUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.ExpressionSemanticUtil) Types(com.kalessil.phpStorm.phpInspectionsEA.utils.Types) TypesSemanticsUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.TypesSemanticsUtil) InterfacesExtractUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.hierarhy.InterfacesExtractUtil) Function(com.jetbrains.php.lang.psi.elements.Function) Set(java.util.Set) PhpIndex(com.jetbrains.php.PhpIndex) PhpTypedElement(com.jetbrains.php.lang.psi.elements.PhpTypedElement) ArrayList(java.util.ArrayList) HashSet(java.util.HashSet) Nullable(org.jetbrains.annotations.Nullable) List(java.util.List) OpenapiResolveUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.OpenapiResolveUtil) PsiElement(com.intellij.psi.PsiElement) PhpType(com.jetbrains.php.lang.psi.resolve.types.PhpType) NotNull(org.jetbrains.annotations.NotNull) ProblemsHolder(com.intellij.codeInspection.ProblemsHolder) PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) ArrayList(java.util.ArrayList) PhpTypedElement(com.jetbrains.php.lang.psi.elements.PhpTypedElement) PhpType(com.jetbrains.php.lang.psi.resolve.types.PhpType) HashSet(java.util.HashSet)

Example 3 with PhpIndex

use of com.jetbrains.php.PhpIndex in project yii2support by nvlad.

the class MissingActiveRecordInActiveQueryInspection method buildVisitor.

@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder problemsHolder, boolean isOnTheFly) {
    return new PhpElementVisitor() {

        @Override
        public void visitPhpClass(PhpClass clazz) {
            if (clazz.getSuperClass() != null && clazz.getSuperClass().getFQN().equals("\\yii\\db\\ActiveQuery")) {
                PhpIndex index = PhpIndex.getInstance(clazz.getProject());
                PhpClass activeRecordClass = ClassUtils.findClassInSeeTags(index, clazz, "\\yii\\db\\BaseActiveRecord");
                if (activeRecordClass == null) {
                    problemsHolder.registerProblem(clazz.getFirstChild(), "Can not find connected ActiveRecord class.\nYou should add @see tag with linked ActiveRecord", ProblemHighlightType.WEAK_WARNING);
                }
            }
            super.visitPhpClass(clazz);
        }
    };
}
Also used : PhpElementVisitor(com.jetbrains.php.lang.psi.visitors.PhpElementVisitor) PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) PhpIndex(com.jetbrains.php.PhpIndex) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with PhpIndex

use of com.jetbrains.php.PhpIndex in project yii2support by nvlad.

the class ViewUtil method isValidRenderMethod.

public static boolean isValidRenderMethod(MethodReference methodReference) {
    final PhpClass clazz = ClassUtils.getPhpClassByCallChain(methodReference);
    if (clazz == null) {
        return false;
    }
    final PhpIndex phpIndex = PhpIndex.getInstance(clazz.getProject());
    return ClassUtils.isClassInheritsOrEqual(clazz, "\\yii\\base\\Controller", phpIndex) || ClassUtils.isClassInheritsOrEqual(clazz, "\\yii\\base\\View", phpIndex) || ClassUtils.isClassInheritsOrEqual(clazz, "\\yii\\base\\Widget", phpIndex) || ClassUtils.isClassInheritsOrEqual(clazz, "\\yii\\mail\\BaseMailer", phpIndex);
}
Also used : PhpIndex(com.jetbrains.php.PhpIndex)

Example 5 with PhpIndex

use of com.jetbrains.php.PhpIndex in project idea-php-typo3-plugin by cedricziel.

the class TCAUtil method findAvailableRenderTypes.

private static Set<PsiElement> findAvailableRenderTypes(Project project) {
    PhpIndex phpIndex = PhpIndex.getInstance(project);
    PsiFile[] extLocalConfFiles = FilenameIndex.getFilesByName(project, EXT_LOCALCONF_FILENAME, GlobalSearchScope.allScope(project));
    Collection<PhpClass> nodeRegistries = phpIndex.getClassesByFQN(NODE_FACTORY_CLASS);
    Set<PsiElement> elements = new HashSet<>();
    for (PhpClass registry : nodeRegistries) {
        Collections.addAll(elements, PsiTreeUtil.collectElements(registry, element -> PlatformPatterns.psiElement(StringLiteralExpression.class).withParent(PlatformPatterns.psiElement(PhpElementTypes.ARRAY_KEY).withAncestor(3, PlatformPatterns.psiElement(PhpElementTypes.CLASS_FIELD).withName("nodeTypes"))).accepts(element)));
    }
    for (PsiFile file : extLocalConfFiles) {
        Collections.addAll(elements, PsiTreeUtil.collectElements(file, element -> PlatformPatterns.psiElement(StringLiteralExpression.class).withParent(PlatformPatterns.psiElement(PhpElementTypes.ARRAY_VALUE).withParent(PlatformPatterns.psiElement(PhpElementTypes.HASH_ARRAY_ELEMENT).withChild(PlatformPatterns.psiElement(PhpElementTypes.ARRAY_KEY).withText("'nodeName'")))).accepts(element)));
    }
    return elements;
}
Also used : java.util(java.util) PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) PhpElementsUtil.extractArrayIndexFromValue(com.cedricziel.idea.typo3.psi.PhpElementsUtil.extractArrayIndexFromValue) FilenameIndex(com.intellij.psi.search.FilenameIndex) GlobalSearchScope(com.intellij.psi.search.GlobalSearchScope) PhpIndex(com.jetbrains.php.PhpIndex) PlatformPatterns(com.intellij.patterns.PlatformPatterns) PsiTreeUtil(com.intellij.psi.util.PsiTreeUtil) PsiElement(com.intellij.psi.PsiElement) Project(com.intellij.openapi.project.Project) PsiFile(com.intellij.psi.PsiFile) StringLiteralExpression(com.jetbrains.php.lang.psi.elements.StringLiteralExpression) PhpElementTypes(com.jetbrains.php.lang.parser.PhpElementTypes) PhpIndex(com.jetbrains.php.PhpIndex) PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) PsiFile(com.intellij.psi.PsiFile) PsiElement(com.intellij.psi.PsiElement)

Aggregations

PhpIndex (com.jetbrains.php.PhpIndex)29 PsiElement (com.intellij.psi.PsiElement)19 NotNull (org.jetbrains.annotations.NotNull)18 PhpType (com.jetbrains.php.lang.psi.resolve.types.PhpType)11 BasePhpElementVisitor (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor)11 HashSet (java.util.HashSet)11 ProblemsHolder (com.intellij.codeInspection.ProblemsHolder)9 Project (com.intellij.openapi.project.Project)9 PhpClass (com.jetbrains.php.lang.psi.elements.PhpClass)8 Nullable (org.jetbrains.annotations.Nullable)7 PsiElementVisitor (com.intellij.psi.PsiElementVisitor)6 com.jetbrains.php.lang.psi.elements (com.jetbrains.php.lang.psi.elements)6 BasePhpInspection (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpInspection)6 OpenapiResolveUtil (com.kalessil.phpStorm.phpInspectionsEA.utils.OpenapiResolveUtil)6 InterfacesExtractUtil (com.kalessil.phpStorm.phpInspectionsEA.utils.hierarhy.InterfacesExtractUtil)6 Set (java.util.Set)6 PsiTreeUtil (com.intellij.psi.util.PsiTreeUtil)5 PhpTokenTypes (com.jetbrains.php.lang.lexer.PhpTokenTypes)4 MessagesPresentationUtil (com.kalessil.phpStorm.phpInspectionsEA.utils.MessagesPresentationUtil)4 Types (com.kalessil.phpStorm.phpInspectionsEA.utils.Types)4