Search in sources :

Example 1 with PerlMutationInstruction

use of com.perl5.lang.perl.idea.codeInsight.controlFlow.PerlMutationInstruction in project Perl5-IDEA by Camelcade.

the class PerlResolveUtil method getValueFromControlFlow.

/**
 * Building a control flow for the {@code element} and attempts to find a value of variable
 *
 * @param element            to build control flow for
 * @param namespaceName      namespace name of the variable if any
 * @param variableName       name of the variable
 * @param actualType         actual type of the variable
 * @param lexicalDeclaration variable declaration element
 * @param stopElement        stop element, lexical declaration or it's context for the light elements
 * @return a value of found variable or {@link PerlValues#UNKNOWN_VALUE}
 * @see PerlControlFlowBuilder#getControlFlowScope(com.intellij.psi.PsiElement)
 */
@NotNull
private static PerlValue getValueFromControlFlow(@NotNull PsiElement element, @Nullable String namespaceName, @NotNull String variableName, @NotNull PerlVariableType actualType, @Nullable PerlVariableDeclarationElement lexicalDeclaration, @Nullable PsiElement stopElement) {
    PsiElement controlFlowScope = PerlControlFlowBuilder.getControlFlowScope(element);
    if (controlFlowScope == null) {
        VirtualFile virtualFile = PsiUtilCore.getVirtualFile(element);
        if (!(element instanceof PsiFile) || !(virtualFile instanceof VirtualFileWindow)) {
            LOG.error("Unable to find control flow scope for:" + element.getClass() + " at " + element.getTextOffset() + " in " + virtualFile + "; " + PerlUtil.getParentsChain(element));
        }
        return UNKNOWN_VALUE;
    }
    Instruction[] instructions = PerlControlFlowBuilder.getFor(controlFlowScope);
    PsiElement elementToFind = element instanceof PerlFile ? element.getContext() : element;
    int elementInstructionIndex = findElementInstruction(elementToFind, instructions, element);
    if (elementInstructionIndex < 0) {
        String message = "Unable to find an instruction for " + element.getClass() + "; " + element.getText() + "; " + element.getTextRange() + "; " + PsiUtilCore.getVirtualFile(element) + "; " + controlFlowScope.getClass() + "; " + PerlUtil.getParentsChain(element);
        Application application = ApplicationManager.getApplication();
        if (!SUPPRESS_ERRORS && (application.isUnitTestMode() || application.isInternal())) {
            LOG.error(message);
        } else {
            LOG.warn(message);
        }
        return UNKNOWN_VALUE;
    }
    PerlOneOfValue.Builder valueBuilder = PerlOneOfValue.builder();
    ControlFlowUtil.iteratePrev(elementInstructionIndex, instructions, currentInstruction -> {
        if (!(currentInstruction instanceof PerlMutationInstruction)) {
            PsiElement instructionElement = currentInstruction.getElement();
            if ((instructionElement instanceof PerlSubDefinitionElement || instructionElement instanceof PerlSubExpr) && lexicalDeclaration instanceof PerlBuiltInVariable && "_".equals(variableName) && actualType == PerlVariableType.ARRAY) {
                valueBuilder.addVariant(PerlValues.ARGUMENTS_VALUE);
                return CONTINUE;
            }
            if (Objects.equals(stopElement, instructionElement)) {
                return CONTINUE;
            }
            if (currentInstruction.num() == 1 && instructionElement != null && instructionElement.getContext() != null) {
                valueBuilder.addVariant(getValueFromControlFlow(instructionElement, namespaceName, variableName, actualType, lexicalDeclaration, stopElement));
            }
            return NEXT;
        }
        if (currentInstruction.num() > elementInstructionIndex) {
            return NEXT;
        }
        // fixme pop instruction should be decomposed
        if (currentInstruction.num() == elementInstructionIndex && !(currentInstruction instanceof PerlAssignInstruction)) {
            return NEXT;
        }
        PsiElement assignee = ((PerlMutationInstruction) currentInstruction).getLeftSide();
        if (!(assignee instanceof PerlVariable) || ((PerlVariable) assignee).getActualType() != actualType) {
            return NEXT;
        }
        if (!Objects.equals(variableName, ((PerlVariable) assignee).getName())) {
            return NEXT;
        }
        String explicitNamespaceName = ((PerlVariable) assignee).getExplicitNamespaceName();
        if ((explicitNamespaceName != null || namespaceName != null) && !Objects.equals(namespaceName, explicitNamespaceName)) {
            return NEXT;
        }
        PerlVariableDeclarationElement assigneeDeclaration = getLexicalDeclaration((PerlVariable) assignee);
        if (element == assignee || lexicalDeclaration == null && assigneeDeclaration == null && !(assignee.getParent() instanceof PerlVariableDeclarationElement) || lexicalDeclaration != null && (Objects.equals(lexicalDeclaration, assigneeDeclaration) || Objects.equals(lexicalDeclaration, assignee.getParent()))) {
            valueBuilder.addVariant(((PerlMutationInstruction) currentInstruction).createValue());
        }
        return CONTINUE;
    });
    if (lexicalDeclaration != null) {
        PerlValue declaredValue = lexicalDeclaration.getDeclaredValue();
        if (!declaredValue.isUnknown()) {
            valueBuilder.addVariant(declaredValue);
        }
    }
    return valueBuilder.build();
}
Also used : VirtualFile(com.intellij.openapi.vfs.VirtualFile) PerlAssignInstruction(com.perl5.lang.perl.idea.codeInsight.controlFlow.PerlAssignInstruction) PerlBuiltInVariable(com.perl5.lang.perl.psi.impl.PerlBuiltInVariable) VirtualFileWindow(com.intellij.injected.editor.VirtualFileWindow) PerlOneOfValue(com.perl5.lang.perl.idea.codeInsight.typeInference.value.PerlOneOfValue) PerlAssignInstruction(com.perl5.lang.perl.idea.codeInsight.controlFlow.PerlAssignInstruction) Instruction(com.intellij.codeInsight.controlflow.Instruction) PerlMutationInstruction(com.perl5.lang.perl.idea.codeInsight.controlFlow.PerlMutationInstruction) PerlMutationInstruction(com.perl5.lang.perl.idea.codeInsight.controlFlow.PerlMutationInstruction) PerlValue(com.perl5.lang.perl.idea.codeInsight.typeInference.value.PerlValue) Application(com.intellij.openapi.application.Application) NotNull(org.jetbrains.annotations.NotNull)

Aggregations

Instruction (com.intellij.codeInsight.controlflow.Instruction)1 VirtualFileWindow (com.intellij.injected.editor.VirtualFileWindow)1 Application (com.intellij.openapi.application.Application)1 VirtualFile (com.intellij.openapi.vfs.VirtualFile)1 PerlAssignInstruction (com.perl5.lang.perl.idea.codeInsight.controlFlow.PerlAssignInstruction)1 PerlMutationInstruction (com.perl5.lang.perl.idea.codeInsight.controlFlow.PerlMutationInstruction)1 PerlOneOfValue (com.perl5.lang.perl.idea.codeInsight.typeInference.value.PerlOneOfValue)1 PerlValue (com.perl5.lang.perl.idea.codeInsight.typeInference.value.PerlValue)1 PerlBuiltInVariable (com.perl5.lang.perl.psi.impl.PerlBuiltInVariable)1 NotNull (org.jetbrains.annotations.NotNull)1