Search in sources :

Example 1 with PerlSubDefinitionElement

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

the class PerlBraceMatcher method getCodeConstructStart.

@Override
public int getCodeConstructStart(PsiFile file, int openingBraceOffset) {
    PsiElement element = file.findElementAt(openingBraceOffset);
    if (element == null || element instanceof PsiFile) {
        return openingBraceOffset;
    }
    PsiElement codeBlock = element.getParent();
    if (codeBlock != null && codeBlock instanceof PsiPerlBlock) {
        PsiElement blockContainer = codeBlock.getParent();
        if (blockContainer != null) {
            if (blockContainer instanceof PerlSubDefinitionElement || blockContainer instanceof PsiPerlForCompound) {
                return blockContainer.getTextOffset();
            } else if (blockContainer instanceof PsiPerlConditionalBlock || blockContainer instanceof PsiPerlIfCompoundImpl) {
                PsiElement keyword = blockContainer.getPrevSibling();
                while (keyword != null && (keyword instanceof PsiWhiteSpace || keyword instanceof PsiComment)) {
                    keyword = keyword.getPrevSibling();
                }
                if (keyword != null) {
                    return keyword.getTextOffset();
                }
            }
        }
    }
    return openingBraceOffset;
}
Also used : PsiPerlConditionalBlock(com.perl5.lang.perl.psi.PsiPerlConditionalBlock) PsiComment(com.intellij.psi.PsiComment) PsiPerlIfCompoundImpl(com.perl5.lang.perl.psi.impl.PsiPerlIfCompoundImpl) PsiPerlBlock(com.perl5.lang.perl.psi.PsiPerlBlock) PsiFile(com.intellij.psi.PsiFile) PerlSubDefinitionElement(com.perl5.lang.perl.psi.PerlSubDefinitionElement) PsiElement(com.intellij.psi.PsiElement) PsiPerlForCompound(com.perl5.lang.perl.psi.PsiPerlForCompound) PsiWhiteSpace(com.intellij.psi.PsiWhiteSpace)

Example 2 with PerlSubDefinitionElement

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

the class PerlMooseInnerReference method resolveInner.

@NotNull
@Override
protected ResolveResult[] resolveInner(boolean incompleteCode) {
    List<ResolveResult> result = new ArrayList<>();
    PsiElement element = getElement();
    String subName = null;
    PerlSubDefinitionElement subDefinitionBase = PsiTreeUtil.getParentOfType(element, PerlSubDefinitionElement.class);
    if (subDefinitionBase != null) {
        subName = subDefinitionBase.getSubName();
    }
    PerlMooseAugmentStatement augmentStatement = PsiTreeUtil.getParentOfType(element, PerlMooseAugmentStatement.class);
    if (augmentStatement != null) {
        subName = augmentStatement.getSubName();
    }
    if (subName != null) {
        PerlNamespaceDefinitionElement namespaceDefinition = PsiTreeUtil.getParentOfType(element, PerlNamespaceDefinitionElement.class);
        Set<PerlNamespaceDefinitionElement> recursionSet = new THashSet<>();
        if (StringUtil.isNotEmpty(subName) && namespaceDefinition != null) {
            collectNamespaceMethodsAugmentations(namespaceDefinition, subName, recursionSet, result);
        }
    }
    return result.toArray(new ResolveResult[result.size()]);
}
Also used : PerlNamespaceDefinitionElement(com.perl5.lang.perl.psi.PerlNamespaceDefinitionElement) ArrayList(java.util.ArrayList) PerlMooseAugmentStatement(com.perl5.lang.perl.parser.moose.psi.PerlMooseAugmentStatement) PsiElementResolveResult(com.intellij.psi.PsiElementResolveResult) ResolveResult(com.intellij.psi.ResolveResult) PerlSubDefinitionElement(com.perl5.lang.perl.psi.PerlSubDefinitionElement) PsiElement(com.intellij.psi.PsiElement) THashSet(gnu.trove.THashSet) NotNull(org.jetbrains.annotations.NotNull)

Example 3 with PerlSubDefinitionElement

use of com.perl5.lang.perl.psi.PerlSubDefinitionElement 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 PerlSubDefinitionElement

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

the class PerlMultipleSubDefinitionsInspection method buildVisitor.

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

        @Override
        public void visitPerlSubDefinitionElement(@NotNull PerlSubDefinitionElement o) {
            Project project = o.getProject();
            String name = "Sub";
            String canonicalName = o.getCanonicalName();
            if (PerlSubUtil.getSubDefinitions(project, canonicalName, GlobalSearchScope.projectScope(project)).size() > 1) {
                if (!PerlPackageUtil.isMain(o.getPackageName()) || !PerlSharedSettings.getInstance(project).SIMPLE_MAIN_RESOLUTION) {
                    registerProblem(holder, o.getNameIdentifier(), String.format("Multiple %ss definitions found", name.toLowerCase()));
                }
            }
            super.visitPerlSubDefinitionElement(o);
        }
    };
}
Also used : Project(com.intellij.openapi.project.Project) PerlVisitor(com.perl5.lang.perl.psi.PerlVisitor) NotNull(org.jetbrains.annotations.NotNull) PerlSubDefinitionElement(com.perl5.lang.perl.psi.PerlSubDefinitionElement) NotNull(org.jetbrains.annotations.NotNull)

Example 5 with PerlSubDefinitionElement

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

the class PerlStructureViewElement method getChildren.

@NotNull
@Override
public TreeElement[] getChildren() {
    List<TreeElement> result = new ArrayList<>();
    Set<String> implementedMethods = new HashSet<>();
    if (myElement instanceof PerlFile) {
        FileViewProvider viewProvider = ((PerlFile) myElement).getViewProvider();
        PsiFile podFile = viewProvider.getPsi(PodLanguage.INSTANCE);
        if (podFile != null && podFile.getChildren().length > 1) {
            result.add(new PodStructureViewElement(podFile));
        }
        Language targetLanguage = null;
        for (Language language : viewProvider.getLanguages()) {
            if (language == PerlLanguage.INSTANCE) {
                targetLanguage = language;
                break;
            } else if (targetLanguage == null && language.isKindOf(PerlLanguage.INSTANCE)) {
                targetLanguage = language;
            }
        }
        if (targetLanguage != null) {
            viewProvider.getPsi(targetLanguage).accept(new PerlRecursiveVisitor() {

                @Override
                public void visitNamespaceDefinitionElement(@NotNull PerlNamespaceDefinitionElement o) {
                    result.add(new PerlNamespaceStructureViewElement(o));
                    super.visitNamespaceDefinitionElement(o);
                }
            });
        }
    }
    if (myElement instanceof PerlNamespaceDefinitionElement) {
        // global variables
        for (PerlVariableDeclarationElement child : PsiTreeUtil.findChildrenOfType(myElement, PerlVariableDeclarationElement.class)) {
            if (child.isGlobalDeclaration() && myElement.isEquivalentTo(PerlPackageUtil.getNamespaceContainerForElement(child))) {
                result.add(new PerlVariableDeclarationStructureViewElement(child));
            }
        }
        Project project = myElement.getProject();
        GlobalSearchScope projectScope = GlobalSearchScope.projectScope(project);
        // imported scalars
        for (PerlExportDescriptor exportDescritptor : ((PerlNamespaceDefinitionElement) myElement).getImportedScalarDescriptors()) {
            String canonicalName = exportDescritptor.getTargetCanonicalName();
            Collection<PerlVariableDeclarationElement> variables = PerlScalarUtil.getGlobalScalarDefinitions(project, canonicalName);
            for (PerlVariableDeclarationElement variable : variables) {
                result.add(new PerlVariableDeclarationStructureViewElement(variable).setImported(exportDescritptor));
            }
            // globs
            Collection<PsiPerlGlobVariable> items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName, projectScope);
            if (items.isEmpty()) {
                items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName);
            }
            for (PerlGlobVariable item : items) {
                result.add(new PerlGlobStructureViewElement(item).setImported(exportDescritptor));
            }
        }
        // imported arrays
        for (PerlExportDescriptor exportDescritptor : ((PerlNamespaceDefinitionElement) myElement).getImportedArrayDescriptors()) {
            String canonicalName = exportDescritptor.getTargetCanonicalName();
            Collection<PerlVariableDeclarationElement> variables = PerlArrayUtil.getGlobalArrayDefinitions(project, canonicalName);
            for (PerlVariableDeclarationElement variable : variables) {
                result.add(new PerlVariableDeclarationStructureViewElement(variable).setImported(exportDescritptor));
            }
            // globs
            Collection<PsiPerlGlobVariable> items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName, projectScope);
            if (items.isEmpty()) {
                items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName);
            }
            for (PerlGlobVariable item : items) {
                result.add(new PerlGlobStructureViewElement(item).setImported(exportDescritptor));
            }
        }
        // imported hashes
        for (PerlExportDescriptor exportDescritptor : ((PerlNamespaceDefinitionElement) myElement).getImportedHashDescriptors()) {
            String canonicalName = exportDescritptor.getTargetCanonicalName();
            Collection<PerlVariableDeclarationElement> variables = PerlHashUtil.getGlobalHashDefinitions(project, canonicalName);
            for (PerlVariableDeclarationElement variable : variables) {
                result.add(new PerlVariableDeclarationStructureViewElement(variable).setImported(exportDescritptor));
            }
            // globs
            Collection<PsiPerlGlobVariable> items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName, projectScope);
            if (items.isEmpty()) {
                items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName);
            }
            for (PerlGlobVariable item : items) {
                result.add(new PerlGlobStructureViewElement(item).setImported(exportDescritptor));
            }
        }
        // Imported subs
        for (PerlExportDescriptor exportDescritptor : ((PerlNamespaceDefinitionElement) myElement).getImportedSubsDescriptors()) {
            String canonicalName = exportDescritptor.getTargetCanonicalName();
            // declarations
            Collection<PerlSubDeclarationElement> subDeclarations = PerlSubUtil.getSubDeclarations(project, canonicalName, projectScope);
            if (subDeclarations.isEmpty()) {
                subDeclarations = PerlSubUtil.getSubDeclarations(project, canonicalName);
            }
            for (PerlSubDeclarationElement item : subDeclarations) {
                result.add(new PerlSubStructureViewElement(item).setImported(exportDescritptor));
            }
            // definitions
            Collection<PerlSubDefinitionElement> subDefinitions = PerlSubUtil.getSubDefinitions(project, canonicalName, projectScope);
            if (subDefinitions.isEmpty()) {
                subDefinitions = PerlSubUtil.getSubDefinitions(project, canonicalName);
            }
            for (PerlSubDefinitionElement item : subDefinitions) {
                result.add(new PerlSubStructureViewElement(item).setImported(exportDescritptor));
            }
            // globs
            Collection<PsiPerlGlobVariable> items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName, projectScope);
            if (items.isEmpty()) {
                items = PerlGlobUtil.getGlobsDefinitions(project, canonicalName);
            }
            for (PerlGlobVariable item : items) {
                result.add(new PerlGlobStructureViewElement(item).setImported(exportDescritptor));
            }
        }
        myElement.accept(new PerlRecursiveVisitor() {

            @Override
            public void visitPerlSubDefinitionElement(@NotNull PerlSubDefinitionElement child) {
                if (myElement.isEquivalentTo(PerlPackageUtil.getNamespaceContainerForElement(child))) {
                    implementedMethods.add(child.getName());
                    result.add(new PerlSubStructureViewElement(child));
                }
                super.visitPerlSubDefinitionElement(child);
            }

            @Override
            public void visitSubDeclarationElement(@NotNull PerlSubDeclarationElement child) {
                if (myElement.isEquivalentTo(PerlPackageUtil.getNamespaceContainerForElement(child))) {
                    result.add(new PerlSubStructureViewElement(child));
                }
                super.visitSubDeclarationElement(child);
            }

            @Override
            public void visitGlobVariable(@NotNull PsiPerlGlobVariable child) {
                if (child.isLeftSideOfAssignment() && myElement.isEquivalentTo(PerlPackageUtil.getNamespaceContainerForElement(child))) {
                    implementedMethods.add(child.getName());
                    result.add(new PerlGlobStructureViewElement(child));
                }
                super.visitGlobVariable(child);
            }
        });
    }
    // inherited elements
    if (myElement instanceof PerlNamespaceDefinitionWithIdentifier) {
        List<TreeElement> inheritedResult = new ArrayList<>();
        String packageName = ((PerlNamespaceDefinitionElement) myElement).getPackageName();
        if (packageName != null) {
            for (PsiElement element : PerlMro.getVariants(myElement, packageName, true)) {
                if (element instanceof PerlIdentifierOwner && !implementedMethods.contains(((PerlIdentifierOwner) element).getName())) {
                    if (element instanceof PerlLightConstantDefinitionElement) {
                        inheritedResult.add(new PerlSubStructureViewElement((PerlSubDefinitionElement) element).setInherited());
                    } else if (element instanceof PerlSubDefinitionElement) {
                        inheritedResult.add(new PerlSubStructureViewElement((PerlSubDefinitionElement) element).setInherited());
                    } else if (element instanceof PerlSubDeclarationElement) {
                        inheritedResult.add(new PerlSubStructureViewElement((PerlSubDeclarationElement) element).setInherited());
                    } else if (element instanceof PerlGlobVariable && ((PerlGlobVariable) element).isLeftSideOfAssignment() && ((PerlGlobVariable) element).getName() != null) {
                        inheritedResult.add(new PerlGlobStructureViewElement((PerlGlobVariable) element).setInherited());
                    }
                }
            }
        }
        if (!inheritedResult.isEmpty()) {
            result.addAll(0, inheritedResult);
        }
    }
    return result.toArray(new TreeElement[result.size()]);
}
Also used : PerlExportDescriptor(com.perl5.lang.perl.extensions.packageprocessor.PerlExportDescriptor) FileViewProvider(com.intellij.psi.FileViewProvider) Language(com.intellij.lang.Language) PerlLanguage(com.perl5.lang.perl.PerlLanguage) PodLanguage(com.perl5.lang.pod.PodLanguage) GlobalSearchScope(com.intellij.psi.search.GlobalSearchScope) PsiFile(com.intellij.psi.PsiFile) PsiElement(com.intellij.psi.PsiElement) TreeElement(com.intellij.ide.util.treeView.smartTree.TreeElement) StructureViewTreeElement(com.intellij.ide.structureView.StructureViewTreeElement) SortableTreeElement(com.intellij.ide.util.treeView.smartTree.SortableTreeElement) Project(com.intellij.openapi.project.Project) PerlLightConstantDefinitionElement(com.perl5.lang.perl.parser.constant.psi.light.PerlLightConstantDefinitionElement) PodStructureViewElement(com.perl5.lang.pod.idea.structureView.PodStructureViewElement) PerlIdentifierOwner(com.perl5.lang.perl.psi.properties.PerlIdentifierOwner) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

PsiElement (com.intellij.psi.PsiElement)10 PerlSubDefinitionElement (com.perl5.lang.perl.psi.PerlSubDefinitionElement)10 NotNull (org.jetbrains.annotations.NotNull)8 PsiFile (com.intellij.psi.PsiFile)6 ArrayList (java.util.ArrayList)5 Project (com.intellij.openapi.project.Project)4 ResolveResult (com.intellij.psi.ResolveResult)4 PsiElementResolveResult (com.intellij.psi.PsiElementResolveResult)3 PerlExportDescriptor (com.perl5.lang.perl.extensions.packageprocessor.PerlExportDescriptor)3 PerlSubElement (com.perl5.lang.perl.psi.PerlSubElement)3 THashSet (gnu.trove.THashSet)3 StructureViewTreeElement (com.intellij.ide.structureView.StructureViewTreeElement)2 PerlSubDeclarationElement (com.perl5.lang.perl.psi.PerlSubDeclarationElement)2 PerlDelegatingLightNamedElement (com.perl5.lang.perl.psi.light.PerlDelegatingLightNamedElement)2 Nullable (org.jetbrains.annotations.Nullable)2 TargetElementUtil (com.intellij.codeInsight.TargetElementUtil)1 CompletionType (com.intellij.codeInsight.completion.CompletionType)1 SelectWordHandler (com.intellij.codeInsight.editorActions.SelectWordHandler)1 HighlightUsagesAction (com.intellij.codeInsight.highlighting.actions.HighlightUsagesAction)1 IntentionAction (com.intellij.codeInsight.intention.IntentionAction)1