Search in sources :

Example 6 with ArrayCreationExpression

use of com.jetbrains.php.lang.psi.elements.ArrayCreationExpression in project yii2support by nvlad.

the class ObjectFactoryReference method resolve.

@Nullable
@Override
public PsiElement resolve() {
    PsiElement possibleArrayCreation = myElement.getParent().getParent().getParent();
    if (possibleArrayCreation instanceof ArrayCreationExpression) {
        ArrayCreationExpression arrayCreation = (ArrayCreationExpression) possibleArrayCreation;
        PsiDirectory dir = myElement.getContainingFile().getContainingDirectory();
        PhpClass phpClass = ObjectFactoryUtils.findClassByArrayCreation(arrayCreation, dir);
        if (phpClass != null) {
            PsiElement field = ClassUtils.findWritableField(phpClass, myElement.getText());
            return field;
        }
    }
    return null;
}
Also used : ArrayCreationExpression(com.jetbrains.php.lang.psi.elements.ArrayCreationExpression) PsiDirectory(com.intellij.psi.PsiDirectory) PhpClass(com.jetbrains.php.lang.psi.elements.PhpClass) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable)

Example 7 with ArrayCreationExpression

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

the class TypeUnsafeArraySearchInspector 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 && targetFunctions.contains(functionName)) {
                final PsiElement[] arguments = reference.getParameters();
                if (arguments.length == 2) {
                    /* false-positives: array of string literals */
                    if (arguments[1] instanceof ArrayCreationExpression) {
                        final PsiElement[] elements = arguments[1].getChildren();
                        if (elements.length > 0) {
                            final long validElementsCount = Arrays.stream(elements).filter(element -> OpenapiTypesUtil.is(element, PhpElementTypes.ARRAY_VALUE)).map(PsiElement::getFirstChild).filter(element -> element instanceof StringLiteralExpression).map(literal -> ((StringLiteralExpression) literal).getContents().trim()).filter(content -> !content.isEmpty() && !content.matches("^\\d+$")).count();
                            if (validElementsCount == elements.length) {
                                return;
                            }
                        }
                    }
                    /* false-positives: array and item types are complimentary */
                    if (arguments[0] instanceof PhpTypedElement && arguments[1] instanceof PhpTypedElement) {
                        final Project project = holder.getProject();
                        final PhpType arrayType = OpenapiResolveUtil.resolveType((PhpTypedElement) arguments[1], project);
                        final Set<String> arrayTypes = arrayType == null ? null : arrayType.filterUnknown().getTypes();
                        if (arrayTypes != null && arrayTypes.size() == 1) {
                            final PhpType itemType = OpenapiResolveUtil.resolveType((PhpTypedElement) arguments[0], project);
                            final Set<String> itemTypes = itemType == null ? null : itemType.filterUnknown().getTypes();
                            if (itemTypes != null && itemTypes.size() == 1) {
                                final boolean matching = this.areTypesMatching(itemTypes.iterator().next(), arrayTypes.iterator().next());
                                if (matching) {
                                    return;
                                }
                            }
                        }
                    }
                    /* general case: we need the third argument */
                    final String replacement = String.format("%s%s(%s, %s, true)", reference.getImmediateNamespaceName(), functionName, arguments[0].getText(), arguments[1].getText());
                    holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(message), new MakeSearchTypeSensitiveFix(replacement));
                }
            }
        }

        private boolean areTypesMatching(@NotNull String itemType, @NotNull String arrayType) {
            boolean result = false;
            if (!itemType.isEmpty()) {
                result = arrayType.equals((itemType.charAt(0) == '\\' ? itemType : '\\' + itemType) + "[]");
            }
            return result;
        }
    };
}
Also used : Arrays(java.util.Arrays) BasePhpInspection(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpInspection) UseSuggestedReplacementFixer(com.kalessil.phpStorm.phpInspectionsEA.fixers.UseSuggestedReplacementFixer) Set(java.util.Set) PhpTypedElement(com.jetbrains.php.lang.psi.elements.PhpTypedElement) HashSet(java.util.HashSet) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) OpenapiTypesUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.OpenapiTypesUtil) OpenapiResolveUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.OpenapiResolveUtil) MessagesPresentationUtil(com.kalessil.phpStorm.phpInspectionsEA.utils.MessagesPresentationUtil) PsiElement(com.intellij.psi.PsiElement) Project(com.intellij.openapi.project.Project) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) StringLiteralExpression(com.jetbrains.php.lang.psi.elements.StringLiteralExpression) PhpType(com.jetbrains.php.lang.psi.resolve.types.PhpType) NotNull(org.jetbrains.annotations.NotNull) PsiElementVisitor(com.intellij.psi.PsiElementVisitor) PhpElementTypes(com.jetbrains.php.lang.parser.PhpElementTypes) ProblemsHolder(com.intellij.codeInspection.ProblemsHolder) ArrayCreationExpression(com.jetbrains.php.lang.psi.elements.ArrayCreationExpression) ArrayCreationExpression(com.jetbrains.php.lang.psi.elements.ArrayCreationExpression) StringLiteralExpression(com.jetbrains.php.lang.psi.elements.StringLiteralExpression) NotNull(org.jetbrains.annotations.NotNull) PhpType(com.jetbrains.php.lang.psi.resolve.types.PhpType) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) Project(com.intellij.openapi.project.Project) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) PhpTypedElement(com.jetbrains.php.lang.psi.elements.PhpTypedElement) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 8 with ArrayCreationExpression

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

the class PackedHashtableOptimizationInspector method buildVisitor.

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

        /* TODO: docs, http://blog.jpauli.tech/2016/04/08/hashtables.html#packed-hashtable-optimization */
        @Override
        public void visitPhpArrayCreationExpression(@NotNull ArrayCreationExpression expression) {
            /* requires PHP7 */
            if (PhpLanguageLevel.get(holder.getProject()).below(PhpLanguageLevel.PHP700)) {
                return;
            }
            /* requires at least 3 children - let array to grow enough */
            final PsiElement[] children = expression.getChildren();
            if (children.length < 3) {
                return;
            }
            /* false-positives: test classes */
            if (this.isTestContext(expression)) {
                return;
            }
            /* step 1: collect indexes and verify array structure */
            final List<PhpPsiElement> indexes = new ArrayList<>();
            for (final PsiElement pairCandidate : children) {
                if (pairCandidate instanceof ArrayHashElement) {
                    final PhpPsiElement key = ((ArrayHashElement) pairCandidate).getKey();
                    if ((key instanceof StringLiteralExpression && key.getFirstPsiChild() == null) || OpenapiTypesUtil.isNumber(key)) {
                        indexes.add(key);
                        continue;
                    }
                }
                break;
            }
            if (indexes.size() != children.length) {
                indexes.clear();
                return;
            }
            /* step 2: analyze collected indexes */
            // if string literal is not numeric => stop
            boolean hasStringIndexes = false;
            boolean hasIncreasingIndexes = true;
            int lastIndex = Integer.MIN_VALUE;
            for (PhpPsiElement index : indexes) {
                final String numericIndex;
                final int integerIndex;
                /* extract text representation of the index */
                if (index instanceof StringLiteralExpression) {
                    hasStringIndexes = true;
                    numericIndex = ((StringLiteralExpression) index).getContents();
                    /* '01' and etc cases can not be converted */
                    if (numericIndex.length() > 1 && '0' == numericIndex.charAt(0)) {
                        indexes.clear();
                        return;
                    }
                } else {
                    numericIndex = index.getText().replaceAll("\\s+", "");
                }
                /* try converting into integer */
                try {
                    integerIndex = Integer.parseInt(numericIndex);
                } catch (NumberFormatException error) {
                    indexes.clear();
                    return;
                }
                if (integerIndex < lastIndex) {
                    hasIncreasingIndexes = false;
                }
                lastIndex = integerIndex;
            }
            /* report if criteria are met */
            if (!hasIncreasingIndexes) {
                holder.registerProblem(expression.getFirstChild(), MessagesPresentationUtil.prefixWithEa(messageReorder));
            }
            if (hasIncreasingIndexes && hasStringIndexes) {
                holder.registerProblem(expression.getFirstChild(), MessagesPresentationUtil.prefixWithEa(messageUseNumericKeys));
            }
        }
    };
}
Also used : ArrayCreationExpression(com.jetbrains.php.lang.psi.elements.ArrayCreationExpression) StringLiteralExpression(com.jetbrains.php.lang.psi.elements.StringLiteralExpression) ArrayList(java.util.ArrayList) ArrayHashElement(com.jetbrains.php.lang.psi.elements.ArrayHashElement) NotNull(org.jetbrains.annotations.NotNull) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) PhpPsiElement(com.jetbrains.php.lang.psi.elements.PhpPsiElement) PhpPsiElement(com.jetbrains.php.lang.psi.elements.PhpPsiElement) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 9 with ArrayCreationExpression

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

the class DuplicateArrayKeysInspector method buildVisitor.

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

        @Override
        public void visitPhpArrayCreationExpression(@NotNull ArrayCreationExpression expression) {
            final Map<String, PsiElement> processed = new HashMap<>();
            for (final ArrayHashElement pair : expression.getHashElements()) {
                final PhpPsiElement key = pair.getKey();
                if (key instanceof StringLiteralExpression && key.getFirstPsiChild() == null) {
                    final PsiElement value = pair.getValue();
                    if (value != null) {
                        final String literal = ((StringLiteralExpression) key).getContents();
                        if (processed.containsKey(literal)) {
                            final boolean isPairDuplicated = !(value instanceof ArrayCreationExpression) && OpenapiEquivalenceUtil.areEqual(value, processed.get(literal));
                            if (isPairDuplicated) {
                                holder.registerProblem(pair, MessagesPresentationUtil.prefixWithEa(messageDuplicatePair), ProblemHighlightType.LIKE_UNUSED_SYMBOL);
                            } else {
                                holder.registerProblem(key, MessagesPresentationUtil.prefixWithEa(messageDuplicateKey));
                            }
                        }
                        processed.put(literal, value);
                    }
                }
            }
            processed.clear();
        }
    };
}
Also used : PhpElementVisitor(com.jetbrains.php.lang.psi.visitors.PhpElementVisitor) ArrayCreationExpression(com.jetbrains.php.lang.psi.elements.ArrayCreationExpression) HashMap(java.util.HashMap) StringLiteralExpression(com.jetbrains.php.lang.psi.elements.StringLiteralExpression) ArrayHashElement(com.jetbrains.php.lang.psi.elements.ArrayHashElement) NotNull(org.jetbrains.annotations.NotNull) PhpPsiElement(com.jetbrains.php.lang.psi.elements.PhpPsiElement) PhpPsiElement(com.jetbrains.php.lang.psi.elements.PhpPsiElement) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 10 with ArrayCreationExpression

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

the class UnserializeExploitsInspector 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("unserialize")) {
                final boolean supportsOptions = PhpLanguageLevel.get(holder.getProject()).atLeast(PhpLanguageLevel.PHP700);
                final PsiElement[] arguments = reference.getParameters();
                if (arguments.length == 1 && !this.isTestContext(reference)) {
                    /* pattern: use 2nd argument since PHP7 */
                    if (supportsOptions) {
                        holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messageUseSecondArgument));
                    }
                    /* pattern: exploitable calls */
                    this.inspectExploits(holder, arguments[0]);
                } else if (arguments.length == 2 && !this.isTestContext(reference)) {
                    if (arguments[1] instanceof ArrayCreationExpression) {
                        final boolean hasClassesListed = arguments[1].getChildren().length > 0;
                        if (!hasClassesListed) {
                            holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messageUseSecondArgument));
                        }
                    } else if (PhpLanguageUtil.isTrue(arguments[1])) {
                        holder.registerProblem(reference, MessagesPresentationUtil.prefixWithEa(messageUseSecondArgument));
                    }
                }
            }
        }

        private void inspectExploits(@NotNull ProblemsHolder holder, @NotNull PsiElement argument) {
            final Set<PsiElement> values = PossibleValuesDiscoveryUtil.discover(argument);
            if (!values.isEmpty()) {
                final List<String> reporting = new ArrayList<>();
                for (PsiElement value : values) {
                    if (OpenapiTypesUtil.isFunctionReference(value)) {
                        final FunctionReference call = (FunctionReference) value;
                        final String functionName = call.getName();
                        if (functionName != null && untrustedFunctions.contains(functionName)) {
                            reporting.add(functionName + "(...)");
                        }
                        continue;
                    }
                    /* extract array access variable */
                    if (value instanceof ArrayAccessExpression) {
                        PsiElement container = value;
                        while (container instanceof ArrayAccessExpression) {
                            container = ((ArrayAccessExpression) container).getValue();
                        }
                        if (container instanceof Variable) {
                            value = container;
                        }
                    }
                    if (value instanceof Variable && untrustedVars.contains(((Variable) value).getName())) {
                        reporting.add(value.getText());
                    // continue
                    }
                /* other expressions are not supported currently */
                }
                /* got something for reporting */
                if (!reporting.isEmpty()) {
                    /* sort reporting list to produce testable results */
                    Collections.sort(reporting);
                    holder.registerProblem(argument, MessagesPresentationUtil.prefixWithEa(messagePattern.replace("%e%", String.join(", ", reporting))), ProblemHighlightType.GENERIC_ERROR);
                    reporting.clear();
                }
            }
            values.clear();
        }
    };
}
Also used : Variable(com.jetbrains.php.lang.psi.elements.Variable) ArrayCreationExpression(com.jetbrains.php.lang.psi.elements.ArrayCreationExpression) NotNull(org.jetbrains.annotations.NotNull) ProblemsHolder(com.intellij.codeInspection.ProblemsHolder) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) ArrayAccessExpression(com.jetbrains.php.lang.psi.elements.ArrayAccessExpression) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

PsiElement (com.intellij.psi.PsiElement)13 ArrayCreationExpression (com.jetbrains.php.lang.psi.elements.ArrayCreationExpression)13 NotNull (org.jetbrains.annotations.NotNull)8 FunctionReference (com.jetbrains.php.lang.psi.elements.FunctionReference)6 StringLiteralExpression (com.jetbrains.php.lang.psi.elements.StringLiteralExpression)6 BasePhpElementVisitor (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor)6 PsiWhiteSpace (com.intellij.psi.PsiWhiteSpace)3 HashSet (java.util.HashSet)3 ProblemsHolder (com.intellij.codeInspection.ProblemsHolder)2 Project (com.intellij.openapi.project.Project)2 ArrayHashElement (com.jetbrains.php.lang.psi.elements.ArrayHashElement)2 MethodReference (com.jetbrains.php.lang.psi.elements.MethodReference)2 ParameterList (com.jetbrains.php.lang.psi.elements.ParameterList)2 PhpPsiElement (com.jetbrains.php.lang.psi.elements.PhpPsiElement)2 PhpTypedElement (com.jetbrains.php.lang.psi.elements.PhpTypedElement)2 Variable (com.jetbrains.php.lang.psi.elements.Variable)2 PhpType (com.jetbrains.php.lang.psi.resolve.types.PhpType)2 PhpElementVisitor (com.jetbrains.php.lang.psi.visitors.PhpElementVisitor)2 Template (com.intellij.codeInsight.template.Template)1 TemplateManager (com.intellij.codeInsight.template.TemplateManager)1