Search in sources :

Example 6 with PerlSubDefinitionElement

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

the class PerlCodeGeneratorImpl method getOverrideCodeText.

@Nullable
@Override
public String getOverrideCodeText(PsiElement subBase) {
    if (subBase instanceof PerlSubElement) {
        PerlSubElement perlSubBase = (PerlSubElement) subBase;
        StringBuilder code = new StringBuilder();
        code.append("#@override\n");
        PerlSubAnnotations annotations = perlSubBase.getAnnotations();
        if (annotations != null) {
            if (annotations.isDeprecated()) {
                code.append("#@deprecated\n");
            }
            if (annotations.isAbstract()) {
                code.append("#@abstract\n");
            }
            if (annotations.isMethod() || subBase instanceof PerlMethodDefinition) {
                code.append("#@method\n");
            }
            if (StringUtil.isNotEmpty(annotations.getReturns())) {
                code.append("#@returns ");
                code.append(annotations.getReturns());
                code.append("\n");
            }
        }
        code.append("sub ");
        code.append(perlSubBase.getSubName());
        code.append("{\n");
        List<String> superArgs = new ArrayList<>();
        List<PerlSubArgument> arguments = Collections.emptyList();
        if (perlSubBase instanceof PerlSubDefinitionElement) {
            // noinspection unchecked
            arguments = ((PerlSubDefinitionElement) perlSubBase).getSubArgumentsList();
            if (!arguments.isEmpty()) {
                boolean useShift = false;
                for (PerlSubArgument argument : arguments) {
                    if (StringUtil.isNotEmpty(argument.getVariableClass())) {
                        useShift = true;
                        break;
                    }
                }
                if (useShift) {
                    for (PerlSubArgument argument : arguments) {
                        if (!argument.isEmpty()) {
                            code.append("my ");
                            code.append(argument.getVariableClass());
                            code.append(" ");
                            String superArg = argument.toStringShort();
                            superArgs.add(superArg);
                            code.append(superArg);
                            code.append(" = ");
                        }
                        code.append("shift;\n");
                    }
                } else {
                    code.append("my ");
                    code.append('(');
                    boolean insertComma = false;
                    for (PerlSubArgument argument : arguments) {
                        if (insertComma) {
                            code.append(", ");
                        } else {
                            insertComma = true;
                        }
                        String superArg = argument.toStringShort();
                        superArgs.add(superArg);
                        code.append(superArg);
                    }
                    code.append(") = @_;\n");
                }
            } else {
                code.append("my ($self) = @_;\n");
            }
        }
        if (!superArgs.isEmpty()) {
            superArgs.remove(0);
        }
        if (!arguments.isEmpty() && !arguments.get(0).isEmpty()) {
            // noinspection StringConcatenationInsideStringBufferAppend
            code.append(arguments.get(0).toStringShort() + "->SUPER::" + perlSubBase.getSubName() + "(" + StringUtil.join(superArgs, ", ") + ");\n");
        }
        code.append("}");
        return code.toString();
    }
    return null;
}
Also used : PerlSubAnnotations(com.perl5.lang.perl.psi.utils.PerlSubAnnotations) PerlSubArgument(com.perl5.lang.perl.psi.utils.PerlSubArgument) PerlSubElement(com.perl5.lang.perl.psi.PerlSubElement) ArrayList(java.util.ArrayList) PerlMethodDefinition(com.perl5.lang.perl.psi.PerlMethodDefinition) PerlSubDefinitionElement(com.perl5.lang.perl.psi.PerlSubDefinitionElement) Nullable(org.jetbrains.annotations.Nullable)

Example 7 with PerlSubDefinitionElement

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

Example 8 with PerlSubDefinitionElement

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

the class PerlSubReferenceSimple method getResolveResults.

@NotNull
public List<ResolveResult> getResolveResults(List<PsiElement> relatedItems) {
    List<ResolveResult> result = new ArrayList<>();
    resetFlags();
    for (PsiElement element : relatedItems) {
        if (!isAutoloaded() && element instanceof PerlIdentifierOwner && PerlSubUtil.SUB_AUTOLOAD.equals(((PerlIdentifierOwner) element).getName())) {
            setAutoloaded();
        }
        if (!isConstant() && element instanceof PerlLightConstantDefinitionElement) {
            setConstant();
        }
        if (!isDeclared() && element instanceof PerlSubDeclarationElement) {
            setDeclared();
        }
        if (!isDefined() && element instanceof PerlSubDefinitionElement) {
            setDefined();
        }
        if (!isXSub() && element instanceof PerlSubElement && ((PerlSubElement) element).isXSub()) {
            setXSub();
        }
        if (!isAliased() && element instanceof PerlGlobVariable) {
            setAliased();
        }
        result.add(new PsiElementResolveResult(element));
    }
    return result;
}
Also used : PerlLightConstantDefinitionElement(com.perl5.lang.perl.parser.constant.psi.light.PerlLightConstantDefinitionElement) PerlSubElement(com.perl5.lang.perl.psi.PerlSubElement) ArrayList(java.util.ArrayList) PerlGlobVariable(com.perl5.lang.perl.psi.PerlGlobVariable) PerlSubDeclarationElement(com.perl5.lang.perl.psi.PerlSubDeclarationElement) PsiElementResolveResult(com.intellij.psi.PsiElementResolveResult) PsiElementResolveResult(com.intellij.psi.PsiElementResolveResult) ResolveResult(com.intellij.psi.ResolveResult) PerlSubDefinitionElement(com.perl5.lang.perl.psi.PerlSubDefinitionElement) PsiElement(com.intellij.psi.PsiElement) PerlIdentifierOwner(com.perl5.lang.perl.psi.properties.PerlIdentifierOwner) NotNull(org.jetbrains.annotations.NotNull)

Example 9 with PerlSubDefinitionElement

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

the class PerlAnnotator method annotate.

@Override
public void annotate(@NotNull final PsiElement element, @NotNull AnnotationHolder holder) {
    IElementType elementType = PsiUtilCore.getElementType(element);
    if (elementType == NYI_STATEMENT) {
        holder.createInfoAnnotation(element, "Unimplemented statement").setTextAttributes(CodeInsightColors.TODO_DEFAULT_ATTRIBUTES);
    } else if (element instanceof PerlGlobVariable && ((PerlGlobVariable) element).isBuiltIn()) {
        holder.createInfoAnnotation(element, null).setTextAttributes(PERL_GLOB_BUILTIN);
    } else if (element instanceof PerlVariable && ((PerlVariable) element).isBuiltIn()) {
        holder.createInfoAnnotation(element, null).setTextAttributes(VARIABLE_KEYS_MAP.get(element.getClass()));
    } else if (elementType == LABEL_DECLARATION || elementType == LABEL_EXPR) {
        holder.createInfoAnnotation(element.getFirstChild(), null).setTextAttributes(PerlSyntaxHighlighter.PERL_LABEL);
    } else if (elementType == PACKAGE) {
        assert element instanceof PerlNamespaceElement;
        PerlNamespaceElement namespaceElement = (PerlNamespaceElement) element;
        PsiElement parent = namespaceElement.getParent();
        if (parent instanceof PerlNamespaceDefinitionWithIdentifier) {
            decorateElement(namespaceElement, holder, PerlSyntaxHighlighter.PERL_PACKAGE_DEFINITION, false);
        } else {
            if (namespaceElement.isPragma()) {
                decorateElement(namespaceElement, holder, PerlSyntaxHighlighter.PERL_PACKAGE_PRAGMA, false);
            } else if (namespaceElement.isBuiltin()) {
                decorateElement(namespaceElement, holder, PerlSyntaxHighlighter.PERL_PACKAGE_CORE, false);
            }
        }
    } else if (element instanceof PerlPolyNamedElement) {
        TextAttributesKey subAttribute = PerlSyntaxHighlighter.PERL_SUB_DEFINITION;
        if (elementType == PerlConstantsWrapperElementType.CONSTANT_WRAPPER) {
            // fixme some interface?
            subAttribute = PerlSyntaxHighlighter.PERL_CONSTANT;
        }
        for (PerlDelegatingLightNamedElement lightNamedElement : ((PerlPolyNamedElement) element).getLightElements()) {
            TextAttributesKey currentKey = lightNamedElement instanceof PerlSubDefinition ? subAttribute : PerlSyntaxHighlighter.PERL_PACKAGE_DEFINITION;
            PsiElement navigationElement = lightNamedElement.getNavigationElement();
            holder.createInfoAnnotation(ElementManipulators.getValueTextRange(navigationElement).shiftRight(lightNamedElement.getTextOffset()), null).setEnforcedTextAttributes(adjustTextAttributes(currentScheme.getAttributes(currentKey), false));
        }
    } else if (// instanceof PerlSubNameElement
    elementType == SUB_NAME) {
        PsiElement parent = element.getParent();
        if (parent instanceof PsiPerlSubDeclaration) {
            holder.createInfoAnnotation(element, null).setTextAttributes(PerlSyntaxHighlighter.PERL_SUB_DECLARATION);
        } else if (parent instanceof PerlSubDefinitionElement) {
            if ("AUTOLOAD".equals(((PerlSubNameElement) element).getName())) {
                holder.createInfoAnnotation(element, null).setTextAttributes(PerlSyntaxHighlighter.PERL_AUTOLOAD);
            } else {
                holder.createInfoAnnotation(element, null).setTextAttributes(PerlSyntaxHighlighter.PERL_SUB_DEFINITION);
            }
        } else if (parent instanceof PerlMethod) {
            // fixme don't we need to take multiple references here?
            PsiElement grandParent = parent.getParent();
            PerlNamespaceElement methodNamespace = ((PerlMethod) parent).getNamespaceElement();
            if (// / not ...->method fixme shouldn't we use isObjectMethod here?
            !(grandParent instanceof PsiPerlNestedCall) && // no explicit NS or it's core
            (methodNamespace == null || methodNamespace.isCORE()) && ((PerlSubNameElement) element).isBuiltIn()) {
                decorateElement(element, holder, PerlSyntaxHighlighter.PERL_SUB_BUILTIN);
            } else {
                PsiReference reference = element.getReference();
                if (reference instanceof PerlSubReference) {
                    ((PerlSubReference) reference).multiResolve(false);
                    if (((PerlSubReference) reference).isConstant()) {
                        holder.createInfoAnnotation(element, "Constant").setTextAttributes(PerlSyntaxHighlighter.PERL_CONSTANT);
                    } else if (((PerlSubReference) reference).isAutoloaded()) {
                        holder.createInfoAnnotation(element, "Auto-loaded sub").setTextAttributes(PerlSyntaxHighlighter.PERL_AUTOLOAD);
                    } else if (((PerlSubReference) reference).isXSub()) {
                        holder.createInfoAnnotation(element, "XSub").setTextAttributes(PerlSyntaxHighlighter.PERL_XSUB);
                    }
                }
            }
        }
    }
}
Also used : PerlSubReference(com.perl5.lang.perl.psi.references.PerlSubReference) PsiReference(com.intellij.psi.PsiReference) TextAttributesKey(com.intellij.openapi.editor.colors.TextAttributesKey) IElementType(com.intellij.psi.tree.IElementType) PerlDelegatingLightNamedElement(com.perl5.lang.perl.psi.light.PerlDelegatingLightNamedElement) PsiElement(com.intellij.psi.PsiElement)

Example 10 with PerlSubDefinitionElement

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

the class SubSelectionHandler method handleInsert.

@Override
public void handleInsert(final InsertionContext context, LookupElement item) {
    final Editor editor = context.getEditor();
    int caretOffset = editor.getCaretModel().getOffset();
    PsiElement targetElement = context.getFile().findElementAt(caretOffset);
    if (targetElement != null && targetElement.getNode().getElementType() == LEFT_PAREN) {
        return;
    }
    PsiElement subDefitnition = item.getPsiElement();
    EditorModificationUtil.insertStringAtCaret(editor, "()");
    // todo we need hint with prototype here, but prototypes handling NYI
    if (!(subDefitnition instanceof PerlSubDefinitionElement && ((PerlSubDefinitionElement) subDefitnition).getSubArgumentsList().isEmpty())) {
        editor.getCaretModel().moveCaretRelatively(-1, 0, false, false, true);
    }
}
Also used : Editor(com.intellij.openapi.editor.Editor) PerlSubDefinitionElement(com.perl5.lang.perl.psi.PerlSubDefinitionElement) PsiElement(com.intellij.psi.PsiElement)

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