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();
}
Aggregations