Search in sources :

Example 6 with PerlSubCallElement

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

the class MojoHelperHandler method computeLightElementsFromPsi.

@Override
@NotNull
public List<? extends PerlDelegatingLightNamedElement<?>> computeLightElementsFromPsi(@NotNull PerlSubCallElement psiElement) {
    List<PsiElement> listElements = psiElement.getCallArgumentsList();
    if (listElements.size() != 2) {
        return Collections.emptyList();
    }
    PsiElement identifierElement = listElements.get(0);
    if (!psiElement.isAcceptableIdentifierElement(identifierElement)) {
        return Collections.emptyList();
    }
    PsiElement bodyElement = listElements.get(1);
    if (!(bodyElement instanceof PerlSubExpr)) {
        return Collections.emptyList();
    }
    String subName = ElementManipulators.getValueText(identifierElement);
    if (StringUtil.isEmpty(subName)) {
        return Collections.emptyList();
    }
    return Collections.singletonList(new MojoHelperDefinition(psiElement, subName, LIGHT_METHOD_DEFINITION, identifierElement, MOJO_CONTROLLER_NS, (PerlSubExpr) bodyElement));
}
Also used : PerlSubExpr(com.perl5.lang.perl.psi.PerlSubExpr) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 7 with PerlSubCallElement

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

the class PerlMooseAttributeHandler method createMooseAttributes.

@NotNull
private List<PerlDelegatingLightNamedElement<?>> createMooseAttributes(@NotNull PerlSubCallElement subCallElement, @NotNull List<PsiElement> identifiers, @NotNull List<PsiElement> listElements) {
    List<PerlDelegatingLightNamedElement<?>> result = new ArrayList<>();
    String packageName = PerlPackageUtil.getContextNamespaceName(subCallElement);
    Map<String, PerlHashEntry> parameters = PerlHashUtil.packToHash(listElements.subList(1, listElements.size()));
    // handling is
    PerlHashEntry isParameter = parameters.get(IS_KEY);
    boolean isWritableProtected = isParameter != null && StringUtil.equals(RWP_KEY, isParameter.getValueString());
    boolean isWritable = isParameter != null && (StringUtil.equals(RW_KEY, isParameter.getValueString()) || isWritableProtected);
    PsiElement forcedIdentifier = null;
    // handling isa and does
    PerlHashEntry isaEntry = parameters.get(ISA_KEY);
    String valueClass = null;
    if (isaEntry == null) {
        isaEntry = parameters.get(DOES_KEY);
    }
    if (isaEntry != null && subCallElement.isAcceptableIdentifierElement(isaEntry.valueElement)) {
        valueClass = isaEntry.getValueString();
        if (StringUtil.isEmpty(valueClass)) {
            valueClass = null;
        }
    }
    // handling accessor, reader, etc.
    boolean createMooClearer = false;
    boolean createMooPredicate = false;
    List<PerlLightMethodDefinitionElement<?>> secondaryResult = new ArrayList<>();
    for (String key : MOOSE_SUB_NAMES_KEYS) {
        PerlHashEntry entry = parameters.get(key);
        if (entry == null) {
            continue;
        }
        String methodName = entry.getValueString();
        if (StringUtil.isEmpty(methodName)) {
            if (entry.valueElement instanceof PsiPerlNumberConstant && "1".equals(entry.valueElement.getText())) {
                if (key.equals(CLEARER_KEY)) {
                    createMooClearer = true;
                } else if (key.equals(PREDICATE_KEY)) {
                    createMooPredicate = true;
                }
            }
            continue;
        }
        if (!isWritable && key.equals(WRITER_KEY)) {
            continue;
        }
        if (!isWritable && key.equals(READER_KEY) || key.equals(ACCESSOR_KEY)) {
            forcedIdentifier = entry.valueElement;
            continue;
        }
        if (!subCallElement.isAcceptableIdentifierElement(entry.valueElement)) {
            continue;
        }
        // fixme we could optimize new_value with subclassing and hardcoding of signature
        PsiElement identifier = entry.getNonNullValueElement();
        PerlLightMethodDefinitionElement<PerlSubCallElement> secondaryElement = new PerlLightMethodDefinitionElement<>(subCallElement, ElementManipulators.getValueText(identifier), LIGHT_METHOD_DEFINITION, identifier, packageName, key.equals(WRITER_KEY) ? Arrays.asList(PerlSubArgument.self(), PerlSubArgument.optionalScalar(PerlSubArgument.NEW_VALUE_VALUE, valueClass)) : Collections.emptyList(), PerlSubAnnotations.tryToFindAnnotations(identifier, entry.keyElement, subCallElement.getParent()));
        if (key.equals(READER_KEY) && valueClass != null) {
            secondaryElement.setReturnValueFromCode(PerlScalarValue.create(valueClass));
        }
        secondaryResult.add(secondaryElement);
    }
    // handle handles
    PerlHashEntry handlesEntry = parameters.get(HANDLES_KEY);
    if (handlesEntry != null) {
        // to show proper signatures, we need an access to delegates, what requires indexes; we should do this in runtime, not indexing, but store delegation target
        if (handlesEntry.valueElement instanceof PsiPerlAnonHash) {
            // handle handles HASH
            Map<String, PerlHashEntry> delegatesMap = PerlHashUtil.collectHashMap(handlesEntry.valueElement);
            for (PerlHashEntry delegateEntry : delegatesMap.values()) {
                if (!subCallElement.isAcceptableIdentifierElement(delegateEntry.keyElement)) {
                    continue;
                }
                secondaryResult.add(new PerlLightMethodDefinitionElement<>(subCallElement, ElementManipulators.getValueText(delegateEntry.keyElement), LIGHT_METHOD_DEFINITION, delegateEntry.keyElement, packageName, Collections.emptyList(), PerlSubAnnotations.tryToFindAnnotations(delegateEntry.keyElement, handlesEntry.keyElement, subCallElement.getParent())));
            }
        } else if (handlesEntry.valueElement instanceof PsiPerlAnonArray) {
            // handle handles ARRAY
            List<PsiElement> delegatesIdentifiers = PerlArrayUtil.collectListElements(((PsiPerlAnonArray) handlesEntry.valueElement).getExpr());
            for (PsiElement identifier : delegatesIdentifiers) {
                if (!subCallElement.isAcceptableIdentifierElement(identifier)) {
                    continue;
                }
                secondaryResult.add(new PerlLightMethodDefinitionElement<>(subCallElement, ElementManipulators.getValueText(identifier), LIGHT_METHOD_DEFINITION, identifier, packageName, Collections.emptyList(), PerlSubAnnotations.tryToFindAnnotations(identifier, handlesEntry.keyElement, subCallElement.getParent())));
            }
        }
    }
    for (PsiElement identifier : identifiers) {
        if (forcedIdentifier != null) {
            identifier = forcedIdentifier;
        }
        if (!subCallElement.isAcceptableIdentifierElement(identifier)) {
            continue;
        }
        List<PerlSubArgument> subArguments = isWritable && !isWritableProtected ? Arrays.asList(PerlSubArgument.self(), PerlSubArgument.optionalScalar(PerlSubArgument.NEW_VALUE_VALUE, valueClass)) : Collections.emptyList();
        var identifierText = ElementManipulators.getValueText(identifier);
        var identifierAnnotations = PerlSubAnnotations.tryToFindAnnotations(identifier, subCallElement.getParent());
        PerlAttributeDefinition newElement = new PerlAttributeDefinition(subCallElement, PerlAttributeDefinition.DEFAULT_NAME_COMPUTATION.fun(identifierText), LIGHT_ATTRIBUTE_DEFINITION, identifier, packageName, subArguments, identifierAnnotations);
        if (valueClass != null) {
            PerlValue returnValue = PerlScalarValue.create(valueClass);
            newElement.setReturnValueFromCode(returnValue);
        }
        result.add(newElement);
        if (isWritableProtected) {
            result.add(new PerlLightMethodDefinitionElement<>(subCallElement, PROTECTED_MUTATOR_PREFIX + identifierText, LIGHT_METHOD_DEFINITION, identifier, packageName, Arrays.asList(PerlSubArgument.self(), PerlSubArgument.mandatoryScalar(PerlSubArgument.NEW_VALUE_VALUE, StringUtil.notNullize(valueClass))), identifierAnnotations));
        }
        if (createMooClearer) {
            var clearerName = identifierText.startsWith("_") ? _MOO_CLEARER_PREFIX + identifierText.substring(1) : MOO_CLEARER_PREFIX + identifierText;
            result.add(new PerlLightMethodDefinitionElement<>(subCallElement, clearerName, LIGHT_METHOD_DEFINITION, identifier, packageName, Collections.emptyList(), identifierAnnotations));
        }
        if (createMooPredicate) {
            var predicateName = identifierText.startsWith("_") ? _MOO_PREDICATE_PREFIX + identifierText.substring(1) : MOO_PREDICATE_PREFIX + identifierText;
            result.add(new PerlLightMethodDefinitionElement<>(subCallElement, predicateName, LIGHT_METHOD_DEFINITION, identifier, packageName, Collections.emptyList(), identifierAnnotations));
        }
        result.addAll(secondaryResult);
        secondaryResult.clear();
    }
    return result;
}
Also used : PerlHashEntry(com.perl5.lang.perl.util.PerlHashEntry) PerlLightMethodDefinitionElement(com.perl5.lang.perl.psi.light.PerlLightMethodDefinitionElement) PerlSubArgument(com.perl5.lang.perl.psi.utils.PerlSubArgument) PerlDelegatingLightNamedElement(com.perl5.lang.perl.psi.light.PerlDelegatingLightNamedElement) PerlValue(com.perl5.lang.perl.idea.codeInsight.typeInference.value.PerlValue) PerlSubCallElement(com.perl5.lang.perl.psi.impl.PerlSubCallElement) PsiElement(com.intellij.psi.PsiElement) NotNull(org.jetbrains.annotations.NotNull)

Example 8 with PerlSubCallElement

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

the class PerlNameSuggestionProvider method suggestAndGetForDereference.

private String suggestAndGetForDereference(@NotNull PsiElement expression, @NotNull Set<String> result, String recommendation) {
    PsiElement[] children = expression.getChildren();
    PsiElement element = children[children.length - 1];
    PsiElement baseElement = children[children.length - 2];
    if (element instanceof PsiPerlHashIndex) {
        recommendation = Objects.requireNonNull(join(HASH, ELEMENT));
        result.add(recommendation);
        result.add(join(HASH, ITEM));
        recommendation = suggestNamesForElements(baseElement, true, ((PsiPerlHashIndex) element).getExpr(), result, recommendation);
    } else if (element instanceof PsiPerlArrayIndex) {
        recommendation = Objects.requireNonNull(join(ARRAY, ELEMENT));
        result.add(recommendation);
        result.add(join(ARRAY, ITEM));
        recommendation = suggestNamesForElements(baseElement, true, ((PsiPerlArrayIndex) element).getExpr(), result, recommendation);
    } else if (element instanceof PerlSubCallElement) {
        recommendation = suggestAndGetForCall((PerlSubCallElement) element, result, recommendation);
    } else if (element instanceof PsiPerlParenthesisedCallArguments) {
        recommendation = join(getBaseName(baseElement), RESULT);
    }
    return recommendation;
}
Also used : PerlSubCallElement(com.perl5.lang.perl.psi.impl.PerlSubCallElement) PsiElement(com.intellij.psi.PsiElement)

Example 9 with PerlSubCallElement

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

the class PerlNameSuggestionProvider method suggestAndGetForCall.

private static String suggestAndGetForCall(@NotNull PerlSubCallElement subCall, @NotNull Set<String> result, String recommendation) {
    PsiPerlMethod method = subCall.getMethod();
    if (method == null) {
        return recommendation;
    }
    PerlCallValue callValue = PerlCallValue.from(method);
    if (callValue == null) {
        return recommendation;
    }
    PerlValue subNameValue = callValue.getSubNameValue();
    if (subNameValue.canRepresentSubName("new")) {
        PerlValue namespaceNameValue = callValue.getNamespaceNameValue();
        Collection<String> variantsFromObjectClass = getVariantsFromPerlValueNamespaces(method, namespaceNameValue);
        result.addAll(variantsFromObjectClass);
        if (!variantsFromObjectClass.isEmpty()) {
            recommendation = variantsFromObjectClass.iterator().next();
        }
    } else {
        Ref<String> recommendationRef = Ref.create(recommendation);
        for (String subName : subNameValue.resolve(method).getSubNames()) {
            String normalizedName = join(subName.replaceAll("^(_+|get_*|set_*)", ""));
            if (StringUtil.isNotEmpty(normalizedName)) {
                result.add(normalizedName);
                recommendationRef.set(normalizedName);
            }
        }
        recommendation = recommendationRef.get();
        result.addAll(getVariantsFromEntityValueNamespaces(subCall));
    }
    return recommendation;
}
Also used : PerlValue(com.perl5.lang.perl.idea.codeInsight.typeInference.value.PerlValue) PerlCallValue(com.perl5.lang.perl.idea.codeInsight.typeInference.value.PerlCallValue)

Example 10 with PerlSubCallElement

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

the class PerlClassAccessorHandler method isFollowBestPractice.

static boolean isFollowBestPractice(@NotNull PerlSubCallElement psiElement) {
    PerlSubCallElementStub stub = psiElement.getGreenStub();
    if (stub != null) {
        PerlSubCallElementData callData = stub.getCallData();
        LOG.assertTrue(callData instanceof PerlClassAccessorCallData, "Got: " + callData);
        return ((PerlClassAccessorCallData) callData).isFBP();
    }
    return CachedValuesManager.getCachedValue(psiElement, () -> {
        Ref<Boolean> result = Ref.create(Boolean.FALSE);
        // fixme we need a smarter treewalkup here, scopes are not necessary here
        PerlResolveUtil.treeWalkUp(psiElement, (element, state) -> {
            if (element instanceof PsiPerlNamespaceContent) {
                return false;
            }
            if (element instanceof PerlSubCallElement && StringUtil.equals("follow_best_practice", ((PerlSubCallElement) element).getSubName())) {
                result.set(Boolean.TRUE);
                return false;
            }
            return true;
        });
        return CachedValueProvider.Result.create(result.get(), psiElement);
    }) == Boolean.TRUE;
}
Also used : PerlSubCallElementData(com.perl5.lang.perl.psi.stubs.calls.PerlSubCallElementData) Arrays(java.util.Arrays) PerlPackageUtil(com.perl5.lang.perl.util.PerlPackageUtil) CLASS_ACCESSOR_METHOD(com.perl5.lang.perl.parser.Class.Accessor.ClassAccessorElementTypes.CLASS_ACCESSOR_METHOD) PerlSubCallElementStub(com.perl5.lang.perl.psi.stubs.calls.PerlSubCallElementStub) PerlSubCallHandler(com.perl5.lang.perl.psi.PerlSubCallHandler) PerlSubCallElement(com.perl5.lang.perl.psi.impl.PerlSubCallElement) GETTER_COMPUTATION(com.perl5.lang.perl.parser.Class.Accessor.psi.impl.PerlClassAccessorMethod.GETTER_COMPUTATION) ArrayList(java.util.ArrayList) CachedValueProvider(com.intellij.psi.util.CachedValueProvider) SETTER_COMPUTATION(com.perl5.lang.perl.parser.Class.Accessor.psi.impl.PerlClassAccessorMethod.SETTER_COMPUTATION) StubInputStream(com.intellij.psi.stubs.StubInputStream) PsiElement(com.intellij.psi.PsiElement) Logger(com.intellij.openapi.diagnostic.Logger) PerlSubCallElementData(com.perl5.lang.perl.psi.stubs.calls.PerlSubCallElementData) ElementManipulators(com.intellij.psi.ElementManipulators) PerlDelegatingLightNamedElement(com.perl5.lang.perl.psi.light.PerlDelegatingLightNamedElement) StringUtil(com.intellij.openapi.util.text.StringUtil) PerlSubDefinitionStub(com.perl5.lang.perl.psi.stubs.subsdefinitions.PerlSubDefinitionStub) IOException(java.io.IOException) StubOutputStream(com.intellij.psi.stubs.StubOutputStream) PerlSubAnnotations(com.perl5.lang.perl.psi.utils.PerlSubAnnotations) Collectors(java.util.stream.Collectors) CachedValuesManager(com.intellij.psi.util.CachedValuesManager) PsiPerlNamespaceContent(com.perl5.lang.perl.psi.PsiPerlNamespaceContent) List(java.util.List) Function(com.intellij.util.Function) PerlResolveUtil(com.perl5.lang.perl.psi.utils.PerlResolveUtil) NotNull(org.jetbrains.annotations.NotNull) Ref(com.intellij.openapi.util.Ref) Collections(java.util.Collections) Ref(com.intellij.openapi.util.Ref) PerlSubCallElementStub(com.perl5.lang.perl.psi.stubs.calls.PerlSubCallElementStub) PerlSubCallElement(com.perl5.lang.perl.psi.impl.PerlSubCallElement) PsiPerlNamespaceContent(com.perl5.lang.perl.psi.PsiPerlNamespaceContent)

Aggregations

PsiElement (com.intellij.psi.PsiElement)10 PerlSubCallElement (com.perl5.lang.perl.psi.impl.PerlSubCallElement)9 NotNull (org.jetbrains.annotations.NotNull)8 PerlDelegatingLightNamedElement (com.perl5.lang.perl.psi.light.PerlDelegatingLightNamedElement)4 PerlValue (com.perl5.lang.perl.idea.codeInsight.typeInference.value.PerlValue)3 PerlLightMethodDefinitionElement (com.perl5.lang.perl.psi.light.PerlLightMethodDefinitionElement)3 IElementType (com.intellij.psi.tree.IElementType)2 PerlSubNameElement (com.perl5.lang.perl.psi.PerlSubNameElement)2 PerlSubAnnotations (com.perl5.lang.perl.psi.utils.PerlSubAnnotations)2 ArrayList (java.util.ArrayList)2 ASTNode (com.intellij.lang.ASTNode)1 Logger (com.intellij.openapi.diagnostic.Logger)1 Ref (com.intellij.openapi.util.Ref)1 StringUtil (com.intellij.openapi.util.text.StringUtil)1 ElementManipulators (com.intellij.psi.ElementManipulators)1 PsiReference (com.intellij.psi.PsiReference)1 StubInputStream (com.intellij.psi.stubs.StubInputStream)1 StubOutputStream (com.intellij.psi.stubs.StubOutputStream)1 CachedValueProvider (com.intellij.psi.util.CachedValueProvider)1 CachedValuesManager (com.intellij.psi.util.CachedValuesManager)1