Search in sources :

Example 1 with ParameterList

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

the class FileFunctionMissUseInspector 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("file")) {
                return;
            }
            final PsiElement[] arguments = reference.getParameters();
            if (arguments.length != 1) {
                return;
            }
            /* function can be silenced, get parent for this case; validate parent structure */
            PsiElement parent = reference.getParent();
            if (parent instanceof UnaryExpression) {
                final PsiElement operation = ((UnaryExpression) parent).getOperation();
                if (OpenapiTypesUtil.is(operation, PhpTokenTypes.opSILENCE)) {
                    parent = parent.getParent();
                }
            }
            if (!(parent instanceof ParameterList) || !OpenapiTypesUtil.isFunctionReference(parent.getParent())) {
                return;
            }
            /* validate parent functions' name (implode or join) and amount of arguments */
            final FunctionReference parentReference = (FunctionReference) parent.getParent();
            final String parentName = parentReference.getName();
            if (parentName == null || (!parentName.equals("implode") && !parentName.equals("join"))) {
                return;
            }
            final PsiElement[] parentParams = parentReference.getParameters();
            if (parentParams.length != 2) {
                return;
            }
            /* validate if glue is not empty */
            final StringLiteralExpression glue = ExpressionSemanticUtil.resolveAsStringLiteral(parentParams[0]);
            if (glue != null && !glue.getContents().isEmpty()) {
                return;
            }
            final String message = String.format(messagePattern, arguments[0].getText());
            holder.registerProblem(parentReference, message, ProblemHighlightType.GENERIC_ERROR, new TheLocalFix());
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) StringLiteralExpression(com.jetbrains.php.lang.psi.elements.StringLiteralExpression) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) ParameterList(com.jetbrains.php.lang.psi.elements.ParameterList) UnaryExpression(com.jetbrains.php.lang.psi.elements.UnaryExpression) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with ParameterList

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

the class PrintfScanfArgumentsInspector 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.containsKey(functionName)) {
                return;
            }
            /* resolve needed parameter */
            final int neededPosition = functions.get(functionName);
            final int minimumArgumentsForAnalysis = neededPosition + 1;
            StringLiteralExpression pattern = null;
            final PsiElement[] params = reference.getParameters();
            if (params.length >= minimumArgumentsForAnalysis) {
                pattern = ExpressionSemanticUtil.resolveAsStringLiteral(params[neededPosition]);
            }
            /* not available */
            if (null == pattern) {
                return;
            }
            final String content = pattern.getContents().trim();
            if (!content.isEmpty()) {
                /* find valid placeholders and extract positions specifiers as well */
                int countWithoutPositionSpecifier = 0;
                int maxPositionSpecifier = 0;
                int countParsedAll = 0;
                /* do normalization: %%, inline variables */
                final String contentAdapted = content.replace("%%", "");
                final String contentNoVars = contentAdapted.replaceAll("\\$\\{?\\$?[a-zA-Z0-9]+\\}?", "");
                if (contentAdapted.length() != contentNoVars.length()) {
                    return;
                }
                final Matcher regexMatcher = regexPlaceHolders.matcher(contentAdapted);
                while (regexMatcher.find()) {
                    ++countParsedAll;
                    if (null != regexMatcher.group(2)) {
                        maxPositionSpecifier = Math.max(maxPositionSpecifier, Integer.parseInt(regexMatcher.group(2)));
                        continue;
                    }
                    ++countWithoutPositionSpecifier;
                }
                final int expectedParametersCount = minimumArgumentsForAnalysis + Math.max(countWithoutPositionSpecifier, maxPositionSpecifier);
                /* check for pattern validity */
                final int parametersInPattern = StringUtils.countMatches(content.replace("%%", ""), "%");
                if (countParsedAll != parametersInPattern) {
                    holder.registerProblem(params[neededPosition], messagePattern, ProblemHighlightType.GENERIC_ERROR);
                    return;
                }
                /* check for arguments matching */
                if (expectedParametersCount != params.length) {
                    /* fscanf/sscanf will also return parsed values as an array if no values containers provided */
                    if (2 == params.length) {
                        final boolean returnsArray = functionName.equals("fscanf") || functionName.equals("sscanf");
                        final PsiElement parent = returnsArray ? reference.getParent() : null;
                        final PsiElement grandParent = parent == null ? null : parent.getParent();
                        if (returnsArray && parent != null) {
                            /* false-positive: dispatching/deconstructing into containers */
                            if (parent instanceof AssignmentExpression || grandParent instanceof AssignmentExpression) {
                                return;
                            } else /* false-positive: dispatching into calls */
                            if (parent instanceof ParameterList && grandParent instanceof FunctionReference) {
                                return;
                            }
                        }
                    }
                    /* false-positives: variadic */
                    if (OpenapiTypesUtil.is(params[params.length - 1].getPrevSibling(), PhpTokenTypes.opVARIADIC)) {
                        return;
                    }
                    final String message = messageParameters.replace("%c%", String.valueOf(expectedParametersCount));
                    holder.registerProblem(reference, message, ProblemHighlightType.GENERIC_ERROR);
                }
            }
        }
    };
}
Also used : BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) AssignmentExpression(com.jetbrains.php.lang.psi.elements.AssignmentExpression) StringLiteralExpression(com.jetbrains.php.lang.psi.elements.StringLiteralExpression) Matcher(java.util.regex.Matcher) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) ParameterList(com.jetbrains.php.lang.psi.elements.ParameterList) NotNull(org.jetbrains.annotations.NotNull) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with ParameterList

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

the class CascadingDirnameCallsInspector 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("dirname")) {
                return;
            }
            final PsiElement[] arguments = reference.getParameters();
            if (arguments.length != 1 && arguments.length != 2) {
                return;
            }
            /* require PHP7+, where 2nd parameter has been added */
            PhpLanguageLevel php = PhpProjectConfigurationFacade.getInstance(holder.getProject()).getLanguageLevel();
            if (php.compareTo(PhpLanguageLevel.PHP700) < 0) {
                return;
            }
            /* don't report nested calls, we want to report the one on top level */
            final PsiElement parent = reference.getParent();
            if (parent instanceof ParameterList && parent.getParent() instanceof FunctionReference) {
                final FunctionReference parentReference = (FunctionReference) parent.getParent();
                final String parentName = parentReference.getName();
                if (parentName != null && parentName.equals("dirname")) {
                    final PsiElement[] parentArguments = parentReference.getParameters();
                    if (parentArguments.length == 1 || parentArguments.length == 2) {
                        return;
                    }
                }
            }
            int directoryLevel = 0;
            PsiElement argument = null;
            final List<PsiElement> levels = new ArrayList<>();
            FunctionReference current = reference;
            while (current instanceof FunctionReference) {
                final String currentName = current.getName();
                if (currentName == null || !currentName.equals("dirname")) {
                    break;
                }
                final PsiElement[] currentArguments = current.getParameters();
                if (currentArguments.length == 1) {
                    argument = currentArguments[0];
                    ++directoryLevel;
                } else if (currentArguments.length == 2) {
                    argument = currentArguments[0];
                    levels.add(currentArguments[1]);
                } else {
                    break;
                }
                if (!(currentArguments[0] instanceof FunctionReference)) {
                    break;
                }
                current = (FunctionReference) currentArguments[0];
            }
            /* if no nested dirname calls, stop analysis */
            if (current == reference) {
                levels.clear();
                return;
            }
            /* if we have 1+ nested call (top-level one is not considered) */
            if (argument != null && arguments[0] != argument) {
                /* process extracted level expressions: numbers to sum-up, expressions to stay */
                final List<String> reported = new ArrayList<>();
                for (PsiElement levelEntry : levels) {
                    try {
                        directoryLevel += Integer.parseInt(levelEntry.getText());
                    } catch (NumberFormatException fail) {
                        reported.add(levelEntry.getText());
                    }
                }
                levels.clear();
                /* do not report cases with one level extraction */
                if (1 == directoryLevel && 0 == reported.size()) {
                    reported.clear();
                    return;
                }
                /* generate the replacement expression */
                reported.add(0, String.valueOf(directoryLevel));
                final String replacement = "dirname(%a%, %l%)".replace("%a%", argument.getText()).replace("%l%", String.join(" + ", reported));
                reported.clear();
                final String message = messagePattern.replace("%e%", replacement);
                holder.registerProblem(reference, message, new TheLocalFix(replacement));
            }
        }
    };
}
Also used : ArrayList(java.util.ArrayList) NotNull(org.jetbrains.annotations.NotNull) PhpLanguageLevel(com.jetbrains.php.config.PhpLanguageLevel) BasePhpElementVisitor(com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor) FunctionReference(com.jetbrains.php.lang.psi.elements.FunctionReference) ParameterList(com.jetbrains.php.lang.psi.elements.ParameterList) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with ParameterList

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

the class MethodUtils method findParamRefByElement.

@Nullable
public static PsiElement findParamRefByElement(PsiElement element) {
    int limit = 10;
    PsiElement prevElement = element;
    PsiElement currElement = element.getParent();
    while (limit > 0) {
        if (currElement instanceof ParameterList)
            return prevElement;
        else {
            prevElement = currElement;
            currElement = currElement.getParent();
            limit--;
        }
    }
    return null;
}
Also used : ParameterList(com.jetbrains.php.lang.psi.elements.ParameterList) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable)

Example 5 with ParameterList

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

the class CompletionProvider method addCompletions.

@Override
protected void addCompletions(@NotNull CompletionParameters completionParameters, ProcessingContext processingContext, @NotNull CompletionResultSet completionResultSet) {
    final PsiElement psiElement = completionParameters.getPosition();
    final MethodReference method = PsiTreeUtil.getParentOfType(psiElement, MethodReference.class);
    if (method == null || method.getParameters().length == 0) {
        return;
    }
    if (!ViewUtil.isValidRenderMethod(method)) {
        return;
    }
    PsiElement viewParameter = psiElement;
    while (viewParameter != null && !(viewParameter.getParent() instanceof ParameterList)) {
        viewParameter = viewParameter.getParent();
    }
    if (viewParameter == null || !viewParameter.equals(method.getParameters()[0])) {
        return;
    }
    final ViewResolve resolve = ViewUtil.resolveView(viewParameter);
    if (resolve == null) {
        return;
    }
    final Project project = psiElement.getProject();
    final GlobalSearchScope scope = GlobalSearchScope.projectScope(project);
    final FileBasedIndex fileBasedIndex = FileBasedIndex.getInstance();
    int prefixLength = resolve.key.length();
    int lastSlashPosition = resolve.key.lastIndexOf('/');
    if (lastSlashPosition != -1 && !resolve.key.endsWith("/")) {
        prefixLength = lastSlashPosition + 1;
    }
    if (!completionParameters.isAutoPopup()) {
        if (completionResultSet.getPrefixMatcher().getPrefix().startsWith("@") && lastSlashPosition == -1) {
            final String prefix = completionResultSet.getPrefixMatcher().getPrefix();
            completionResultSet = completionResultSet.withPrefixMatcher(prefix.substring(1));
            prefixLength = 1;
        } else {
            completionResultSet = completionResultSet.withPrefixMatcher(resolve.key.substring(prefixLength));
        }
    }
    if (completionResultSet.getPrefixMatcher().getPrefix().equals("@")) {
        completionResultSet = completionResultSet.withPrefixMatcher("");
    }
    final String prefixFilter = resolve.key.substring(0, prefixLength);
    final Set<String> keys = new HashSet<>();
    fileBasedIndex.processAllKeys(ViewFileIndex.identity, key -> {
        if (key.startsWith(prefixFilter)) {
            keys.add(key);
        }
        return true;
    }, scope, null);
    final PsiManager psiManager = PsiManager.getInstance(project);
    boolean localViewSearch = false;
    if (resolve.from == ViewResolveFrom.View) {
        final String value = PhpUtil.getValue(viewParameter);
        localViewSearch = !value.startsWith("@") && !value.startsWith("//");
    }
    final String defaultViewExtension = '.' + Yii2SupportSettings.getInstance(psiElement.getProject()).defaultViewExtension;
    for (String key : keys) {
        Collection<ViewInfo> views = fileBasedIndex.getValues(ViewFileIndex.identity, key, scope);
        for (ViewInfo view : views) {
            if (!resolve.application.equals(view.application)) {
                continue;
            }
            if (localViewSearch && !resolve.theme.equals(view.theme)) {
                continue;
            }
            PsiFile psiFile = psiManager.findFile(view.getVirtualFile());
            if (psiFile != null) {
                String insertText = key.substring(prefixLength);
                if (insertText.endsWith(defaultViewExtension)) {
                    insertText = insertText.substring(0, insertText.length() - defaultViewExtension.length());
                }
                completionResultSet.addElement(new ViewLookupElement(psiFile, insertText));
                break;
            } else {
                System.out.println(view.fileUrl + " => not exists");
            }
        }
    }
}
Also used : ViewResolve(com.nvlad.yii2support.views.entities.ViewResolve) PsiManager(com.intellij.psi.PsiManager) ViewInfo(com.nvlad.yii2support.views.entities.ViewInfo) Project(com.intellij.openapi.project.Project) GlobalSearchScope(com.intellij.psi.search.GlobalSearchScope) ParameterList(com.jetbrains.php.lang.psi.elements.ParameterList) MethodReference(com.jetbrains.php.lang.psi.elements.MethodReference) PsiFile(com.intellij.psi.PsiFile) PsiElement(com.intellij.psi.PsiElement) FileBasedIndex(com.intellij.util.indexing.FileBasedIndex) HashSet(java.util.HashSet)

Aggregations

ParameterList (com.jetbrains.php.lang.psi.elements.ParameterList)10 PsiElement (com.intellij.psi.PsiElement)9 FunctionReference (com.jetbrains.php.lang.psi.elements.FunctionReference)6 NotNull (org.jetbrains.annotations.NotNull)5 MethodReference (com.jetbrains.php.lang.psi.elements.MethodReference)4 BasePhpElementVisitor (com.kalessil.phpStorm.phpInspectionsEA.openApi.BasePhpElementVisitor)4 StringLiteralExpression (com.jetbrains.php.lang.psi.elements.StringLiteralExpression)3 PsiWhiteSpace (com.intellij.psi.PsiWhiteSpace)2 ArrayCreationExpression (com.jetbrains.php.lang.psi.elements.ArrayCreationExpression)2 Template (com.intellij.codeInsight.template.Template)1 TemplateManager (com.intellij.codeInsight.template.TemplateManager)1 Editor (com.intellij.openapi.editor.Editor)1 Project (com.intellij.openapi.project.Project)1 PsiErrorElement (com.intellij.psi.PsiErrorElement)1 PsiFile (com.intellij.psi.PsiFile)1 PsiManager (com.intellij.psi.PsiManager)1 GlobalSearchScope (com.intellij.psi.search.GlobalSearchScope)1 FileBasedIndex (com.intellij.util.indexing.FileBasedIndex)1 PhpLanguageLevel (com.jetbrains.php.config.PhpLanguageLevel)1 AssignmentExpression (com.jetbrains.php.lang.psi.elements.AssignmentExpression)1