Search in sources :

Example 1 with PerlSubNameElement

use of com.perl5.lang.perl.psi.PerlSubNameElement in project Perl5-IDEA by Camelcade.

the class PerlFancyMethodCallInspection method buildVisitor.

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

        @Override
        public void visitMethod(@NotNull PsiPerlMethod o) {
            if (o.isObjectMethod() && o.getLastChild() instanceof PerlNamespaceElement) {
                String packageName = o.getPackageName();
                if (packageName == null) {
                    return;
                }
                PerlSubNameElement subNameElement = o.getSubNameElement();
                if (subNameElement == null) {
                    return;
                }
                String properForm = String.format("%s->%s", packageName, subNameElement.getName());
                holder.registerProblem(o, PerlBundle.message("perl.inspection.fancy.call", properForm), ProblemHighlightType.GENERIC_ERROR_OR_WARNING, new PerlFancyMethodQuickFix(properForm));
            }
        }
    };
}
Also used : PerlSubNameElement(com.perl5.lang.perl.psi.PerlSubNameElement) PsiPerlMethod(com.perl5.lang.perl.psi.PsiPerlMethod) PerlFancyMethodQuickFix(com.perl5.lang.perl.idea.quickfixes.PerlFancyMethodQuickFix) PerlNamespaceElement(com.perl5.lang.perl.psi.PerlNamespaceElement) PerlVisitor(com.perl5.lang.perl.psi.PerlVisitor) NotNull(org.jetbrains.annotations.NotNull) NotNull(org.jetbrains.annotations.NotNull)

Example 2 with PerlSubNameElement

use of com.perl5.lang.perl.psi.PerlSubNameElement in project Perl5-IDEA by Camelcade.

the class PerlDocumentationProvider method getCustomDocumentationElement.

@Nullable
@Override
public PsiElement getCustomDocumentationElement(@NotNull Editor editor, @NotNull PsiFile file, @Nullable PsiElement contextElement) {
    if (contextElement == null || contextElement.getLanguage() != PerlLanguage.INSTANCE) {
        return null;
    }
    IElementType elementType = contextElement.getNode().getElementType();
    if (contextElement instanceof PerlVariable) {
        // fixme try to search doc in package or declaration
        return PerlDocUtil.getPerlVarDoc((PerlVariable) contextElement);
    } else if (elementType == REGEX_MODIFIER) {
        return PerlDocUtil.getRegexModifierDoc(contextElement);
    } else if (elementType == REGEX_TOKEN) {
        return PerlDocUtil.resolveDocLink("perlretut", contextElement);
    } else if (elementType == VERSION_ELEMENT) {
        return PerlDocUtil.resolveDocLink("perldata/\"Version Strings\"", contextElement);
    } else if (isFunc(contextElement)) {
        return PerlDocUtil.getPerlFuncDoc(contextElement);
    } else if (isOp(contextElement)) {
        return PerlDocUtil.getPerlOpDoc(contextElement);
    } else if (contextElement instanceof PerlSubNameElement) {
        String packageName = ((PerlSubNameElement) contextElement).getPackageName();
        String subName = ((PerlSubNameElement) contextElement).getName();
        if (StringUtil.isNotEmpty(subName)) {
            PsiElement result = null;
            // search by link
            if (StringUtil.isNotEmpty(packageName) && !StringUtil.equals(PerlPackageUtil.MAIN_PACKAGE, packageName)) {
                result = PerlDocUtil.resolveDocLink(packageName + "/" + ((PerlSubNameElement) contextElement).getName(), contextElement);
            }
            // not found or main::
            if (result == null) {
                PsiElement target = null;
                if (contextElement.getParent() instanceof PerlSubElement) {
                    target = contextElement.getParent();
                } else {
                    PsiReference reference = contextElement.getReference();
                    if (reference != null) {
                        target = reference.resolve();
                    }
                }
                if (target != null) {
                    PsiFile targetFile = target.getContainingFile();
                    if (targetFile != null) {
                        PsiFile podFile = targetFile.getViewProvider().getPsi(PodLanguage.INSTANCE);
                        if (podFile != null) {
                            result = PerlDocUtil.searchPodElement(targetFile, PodDocumentPattern.headingAndItemPattern(subName));
                        }
                    }
                }
            }
            if (result != null) {
                return result;
            }
        }
    } else if (contextElement instanceof PerlNamespaceElement) {
        String packageName = ((PerlNamespaceElement) contextElement).getCanonicalName();
        if (StringUtil.equals(PerlPackageUtil.SUPER_PACKAGE, packageName)) {
            return PerlDocUtil.resolveDocLink("perlobj/Inheritance", contextElement);
        } else if (StringUtil.isNotEmpty(packageName)) {
            return PerlDocUtil.resolveDocLink(packageName, contextElement);
        }
    }
    return super.getCustomDocumentationElement(editor, file, contextElement);
}
Also used : IElementType(com.intellij.psi.tree.IElementType) PerlSubNameElement(com.perl5.lang.perl.psi.PerlSubNameElement) PerlSubElement(com.perl5.lang.perl.psi.PerlSubElement) PsiReference(com.intellij.psi.PsiReference) PerlNamespaceElement(com.perl5.lang.perl.psi.PerlNamespaceElement) PsiFile(com.intellij.psi.PsiFile) PerlVariable(com.perl5.lang.perl.psi.PerlVariable) PsiElement(com.intellij.psi.PsiElement) Nullable(org.jetbrains.annotations.Nullable)

Example 3 with PerlSubNameElement

use of com.perl5.lang.perl.psi.PerlSubNameElement in project Perl5-IDEA by Camelcade.

the class PerlLoopControlInspection method buildVisitor.

@NotNull
@Override
public PsiElementVisitor buildVisitor(@NotNull ProblemsHolder holder, boolean isOnTheFly) {
    PerlSubDefinitionElement breakDefinition = PerlBuiltInSubsService.getInstance(holder.getProject()).findSub("break");
    return new PerlVisitor() {

        @Override
        public void visitNextExpr(@NotNull PsiPerlNextExpr o) {
            processLoopsControl(o);
        }

        @Override
        public void visitRedoExpr(@NotNull PsiPerlRedoExpr o) {
            processLoopsControl(o);
        }

        @Override
        public void visitLastExpr(@NotNull PsiPerlLastExpr o) {
            processLoopsControl(o);
        }

        @Override
        public void visitContinueExpr(@NotNull PsiPerlContinueExpr o) {
            PsiElement position = o;
            boolean isInsideTheLoop = false;
            while (true) {
                PsiElement closestBlockContainer = getClosestBlockContainer(position);
                if (closestBlockContainer == null) {
                    break;
                }
                IElementType blockContainerElementType = PsiUtilCore.getElementType(closestBlockContainer);
                if (blockContainerElementType == WHEN_COMPOUND || blockContainerElementType == DEFAULT_COMPOUND) {
                    return;
                } else if (LOOPS_CONTAINERS.contains(blockContainerElementType)) {
                    isInsideTheLoop = true;
                } else if (blockContainerElementType == NAMED_BLOCK) {
                    break;
                } else if (MAP_GREP.contains(blockContainerElementType)) {
                    break;
                } else if (BLOCKS_WITH_RETURN_VALUE.contains(blockContainerElementType)) {
                    break;
                } else if (blockContainerElementType == GIVEN_COMPOUND) {
                    break;
                }
                position = closestBlockContainer;
            }
            if (isInsideTheLoop) {
                holder.registerProblem(o, PerlBundle.message("perl.inspection.loop.control.continue.instead.of.next"), new ReplaceWithExpressionQuickFix("next"));
            } else {
                problem(o, "perl.inspection.loop.control.continue");
            }
        }

        @Override
        public void visitSubNameElement(@NotNull PerlSubNameElement o) {
            PsiReference reference = o.getReference();
            if (reference == null) {
                return;
            }
            if (reference.resolve() != breakDefinition) {
                return;
            }
            PsiElement position = o;
            boolean isInsideTheLoop = false;
            while (true) {
                PsiElement closestBlockContainer = getClosestBlockContainer(position);
                if (closestBlockContainer == null) {
                    break;
                }
                IElementType blockContainerElementType = PsiUtilCore.getElementType(closestBlockContainer);
                if (LOOPS_CONTAINERS.contains(blockContainerElementType)) {
                    isInsideTheLoop = true;
                } else if (blockContainerElementType == NAMED_BLOCK) {
                    break;
                } else if (MAP_GREP.contains(blockContainerElementType)) {
                    break;
                } else if (BLOCKS_WITH_RETURN_VALUE.contains(blockContainerElementType)) {
                    break;
                } else if (blockContainerElementType == GIVEN_COMPOUND) {
                    return;
                }
                position = closestBlockContainer;
            }
            if (isInsideTheLoop) {
                holder.registerProblem(o, PerlBundle.message("perl.inspection.loop.control.break.instead.of.last"), new ReplaceWithExpressionQuickFix("last"));
            } else {
                problem(o, "perl.inspection.loop.control.break");
            }
        }

        private void problem(@NotNull PsiElement anchor, @NotNull String key, @NotNull String... args) {
            registerProblem(holder, anchor, PerlBundle.message(key, (Object[]) args));
        }

        /**
         * @return parent psi element for closest parent block element
         */
        @Nullable
        private PsiElement getClosestBlockContainer(@NotNull PsiElement position) {
            PsiPerlBlock enclosingBlock = PsiTreeUtil.getParentOfType(position, PsiPerlBlock.class);
            if (enclosingBlock == null) {
                return null;
            }
            PsiElement blockContainer = enclosingBlock.getParent();
            return PsiUtilCore.getElementType(blockContainer) == LP_CODE_BLOCK ? blockContainer.getParent() : blockContainer;
        }

        /**
         * Traversing blocks up, trying to figure out if last/next/redo are in right place.
         *
         * @param expr last/next/redo expression
         */
        private void processLoopsControl(@NotNull PsiElement expr) {
            PsiElement keyword = expr.getFirstChild();
            if (keyword == null) {
                return;
            }
            String keywordText = keyword.getText();
            // checks modifier
            PsiPerlStatementImpl containingStatement = PsiTreeUtil.getParentOfType(expr, PsiPerlStatementImpl.class);
            PsiPerlStatementModifier modifier = containingStatement == null ? null : containingStatement.getModifier();
            if (modifier instanceof PsiPerlForStatementModifier) {
                return;
            }
            // traversing up
            PsiElement position = expr;
            boolean isInsideGiven = false;
            boolean isInsideWhenOrDefault = false;
            while (true) {
                PsiElement closestBlockContainer = getClosestBlockContainer(position);
                if (closestBlockContainer == null) {
                    break;
                }
                IElementType blockContainerType = PsiUtilCore.getElementType(closestBlockContainer);
                if (LOOPS_CONTAINERS.contains(blockContainerType)) {
                    return;
                } else if (blockContainerType == NAMED_BLOCK) {
                    problem(expr, "perl.inspection.loop.control.in.named.block", keywordText);
                    return;
                } else if (MAP_GREP.contains(blockContainerType)) {
                    problem(expr, "perl.inspection.loop.control.in.map", keywordText);
                    return;
                } else if (BLOCKS_WITH_RETURN_VALUE.contains(blockContainerType)) {
                    problem(expr, "perl.inspection.loop.control.in.do", keywordText);
                    return;
                } else if (blockContainerType == GIVEN_COMPOUND) {
                    isInsideGiven = true;
                } else if (blockContainerType == WHEN_COMPOUND || blockContainerType == DEFAULT_COMPOUND) {
                    isInsideWhenOrDefault = true;
                }
                position = closestBlockContainer;
            }
            if (expr instanceof PsiPerlNextExpr && isInsideWhenOrDefault) {
                holder.registerProblem(expr, PerlBundle.message("perl.inspection.loop.control.next.instead.of.continue"), new ReplaceWithExpressionQuickFix("continue"));
            } else if (expr instanceof PsiPerlLastExpr && isInsideGiven) {
                holder.registerProblem(expr, PerlBundle.message("perl.inspection.loop.control.last.instead.of.break"), new ReplaceWithExpressionQuickFix("break"));
            } else {
                problem(expr, "perl.inspection.loop.control.outside", keywordText);
            }
        }
    };
}
Also used : PsiReference(com.intellij.psi.PsiReference) PsiPerlStatementImpl(com.perl5.lang.perl.psi.impl.PsiPerlStatementImpl) NotNull(org.jetbrains.annotations.NotNull) IElementType(com.intellij.psi.tree.IElementType) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 4 with PerlSubNameElement

use of com.perl5.lang.perl.psi.PerlSubNameElement in project Perl5-IDEA by Camelcade.

the class PerlUnresolvedSubInspection method buildVisitor.

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

        @Override
        public void visitStringContentElement(@NotNull PerlStringContentElementImpl o) {
            if (EXPORT_ASSIGNED_STRING_CONTENT.accepts(o)) {
                if (!isResolvable(o.getReference())) {
                    registerProblem(holder, o, PerlBundle.message("perl.inspection.no.exported.entity"));
                }
            }
        }

        @Override
        public void visitPerlMethod(@NotNull PerlMethod o) {
            PerlNamespaceElement namespaceElement = o.getNamespaceElement();
            PerlSubNameElement subNameElement = o.getSubNameElement();
            // fixme adjust built in checking to the file; Remove second condition after implementing annotations
            if (subNameElement == null || namespaceElement != null && namespaceElement.isBuiltin() || subNameElement.isBuiltIn()) {
                return;
            }
            for (PsiReference reference : subNameElement.getReferences()) {
                if (isResolvable(reference)) {
                    return;
                }
            }
            registerProblem(holder, subNameElement, PerlBundle.message("perl.inspection.no.sub.definition"));
        }
    };
}
Also used : PerlMethod(com.perl5.lang.perl.psi.PerlMethod) PerlSubNameElement(com.perl5.lang.perl.psi.PerlSubNameElement) PerlNamespaceElement(com.perl5.lang.perl.psi.PerlNamespaceElement) PsiReference(com.intellij.psi.PsiReference) PerlVisitor(com.perl5.lang.perl.psi.PerlVisitor) NotNull(org.jetbrains.annotations.NotNull) PerlStringContentElementImpl(com.perl5.lang.perl.psi.impl.PerlStringContentElementImpl) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with PerlSubNameElement

use of com.perl5.lang.perl.psi.PerlSubNameElement in project Perl5-IDEA by Camelcade.

the class PerlSubReference method resolveInner.

@NotNull
@Override
protected ResolveResult[] resolveInner(boolean incompleteCode) {
    PsiElement myElement = getElement();
    assert myElement instanceof PerlSubNameElement;
    PsiElement parent = myElement.getParent();
    if (parent instanceof PerlSubDeclarationElement || parent instanceof PerlSubDefinitionElement) {
        return ResolveResult.EMPTY_ARRAY;
    }
    PerlSubNameElement subNameElement = (PerlSubNameElement) myElement;
    List<PsiElement> relatedItems = new ArrayList<>();
    String packageName = subNameElement.getPackageName();
    String subName = subNameElement.getName();
    Project project = subNameElement.getProject();
    PerlNamespaceElement expliclitPackageElement = null;
    if (parent instanceof PerlNamespaceElementContainer) {
        expliclitPackageElement = ((PerlNamespaceElementContainer) parent).getNamespaceElement();
    }
    if (!subName.isEmpty()) {
        if (parent instanceof PerlMethod && ((PerlMethod) parent).isObjectMethod()) {
            boolean isSuper = expliclitPackageElement != null && expliclitPackageElement.isSUPER();
            relatedItems.addAll(PerlMro.resolveSub(project, isSuper ? PerlPackageUtil.getContextPackageName(subNameElement) : packageName, subName, isSuper));
        } else // static resolution
        {
            if (PerlSharedSettings.getInstance(project).SIMPLE_MAIN_RESOLUTION && // fixme this is a dirty hack until proper names resolution implemented
            PerlPackageUtil.isMain(packageName)) {
                PsiFile file = subNameElement.getContainingFile();
                GlobalSearchScope fileScope = GlobalSearchScope.fileScope(file);
                collectRelatedItems(packageName + PerlPackageUtil.PACKAGE_SEPARATOR + subName, project, parent, relatedItems, fileScope);
            // if (file instanceof PerlFile)
            // ((PerlFile) file).getElementsResolveScope();
            // System.err.println("Checking for " + subName);
            }
            if (relatedItems.isEmpty()) {
                GlobalSearchScope globalSearchScope = GlobalSearchScope.allScope(project);
                // check indexes for defined subs
                collectRelatedItems(packageName + PerlPackageUtil.PACKAGE_SEPARATOR + subName, project, parent, relatedItems, globalSearchScope);
                if (expliclitPackageElement == null) {
                    // check for imports to the current file
                    PerlNamespaceDefinitionElement namespaceContainer = PerlPackageUtil.getNamespaceContainerForElement(subNameElement);
                    if (namespaceContainer != null) {
                        for (PerlExportDescriptor exportDescriptor : namespaceContainer.getImportedSubsDescriptors()) {
                            if (exportDescriptor.getImportedName().equals(subName)) {
                                int currentSize = relatedItems.size();
                                collectRelatedItems(exportDescriptor.getTargetCanonicalName(), project, parent, relatedItems, globalSearchScope);
                                if (// imported, but not found, attempting autoload
                                relatedItems.size() == currentSize) {
                                    collectRelatedItems(exportDescriptor.getRealPackage() + PerlSubUtil.SUB_AUTOLOAD_WITH_PREFIX, project, parent, relatedItems, globalSearchScope);
                                }
                            }
                        }
                    }
                } else // check imports to target namespace
                {
                    String targetPackageName = expliclitPackageElement.getCanonicalName();
                    if (targetPackageName != null) {
                        // fixme partially not DRY with previous block
                        for (PerlNamespaceDefinitionElement namespaceDefinition : PerlPackageUtil.getNamespaceDefinitions(project, targetPackageName)) {
                            for (PerlExportDescriptor exportDescriptor : namespaceDefinition.getImportedSubsDescriptors()) {
                                if (exportDescriptor.getImportedName().equals(subName)) {
                                    collectRelatedItems(exportDescriptor.getTargetCanonicalName(), project, parent, relatedItems, globalSearchScope);
                                }
                            }
                        }
                    }
                }
                // check for builtins
                if (relatedItems.isEmpty()) {
                    PerlSubDefinitionElement builtInSub = PerlBuiltInSubsService.getInstance(project).findSub(subName);
                    if (builtInSub != null) {
                        relatedItems.add(builtInSub);
                    }
                }
                // check for autoload
                if (relatedItems.isEmpty() && // don't check for UNIVERSAL::AUTOLOAD
                !PerlPackageUtil.isUNIVERSAL(packageName)) {
                    collectRelatedItems(packageName + PerlSubUtil.SUB_AUTOLOAD_WITH_PREFIX, project, parent, relatedItems, globalSearchScope);
                }
            }
        }
    }
    List<ResolveResult> result = getResolveResults(relatedItems);
    return result.toArray(new ResolveResult[result.size()]);
}
Also used : ArrayList(java.util.ArrayList) Project(com.intellij.openapi.project.Project) PerlExportDescriptor(com.perl5.lang.perl.extensions.packageprocessor.PerlExportDescriptor) GlobalSearchScope(com.intellij.psi.search.GlobalSearchScope) PerlNamespaceElementContainer(com.perl5.lang.perl.psi.properties.PerlNamespaceElementContainer) PsiFile(com.intellij.psi.PsiFile) ResolveResult(com.intellij.psi.ResolveResult) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

PsiElement (com.intellij.psi.PsiElement)7 PsiReference (com.intellij.psi.PsiReference)6 PerlSubNameElement (com.perl5.lang.perl.psi.PerlSubNameElement)5 PerlNamespaceElement (com.perl5.lang.perl.psi.PerlNamespaceElement)4 NotNull (org.jetbrains.annotations.NotNull)4 ResolveResult (com.intellij.psi.ResolveResult)3 IElementType (com.intellij.psi.tree.IElementType)3 Nullable (org.jetbrains.annotations.Nullable)3 PsiFile (com.intellij.psi.PsiFile)2 PerlMethod (com.perl5.lang.perl.psi.PerlMethod)2 PerlVisitor (com.perl5.lang.perl.psi.PerlVisitor)2 PerlSubReference (com.perl5.lang.perl.psi.references.PerlSubReference)2 TextAttributesKey (com.intellij.openapi.editor.colors.TextAttributesKey)1 Project (com.intellij.openapi.project.Project)1 PsiPolyVariantReference (com.intellij.psi.PsiPolyVariantReference)1 GlobalSearchScope (com.intellij.psi.search.GlobalSearchScope)1 PerlExportDescriptor (com.perl5.lang.perl.extensions.packageprocessor.PerlExportDescriptor)1 PerlFancyMethodQuickFix (com.perl5.lang.perl.idea.quickfixes.PerlFancyMethodQuickFix)1 PerlSubElement (com.perl5.lang.perl.psi.PerlSubElement)1 PerlVariable (com.perl5.lang.perl.psi.PerlVariable)1