for (ErlangQVar v : vars) {
if (inLeftPartOfAssignment(v, true)) {
ErlangAssignmentExpression assign = PsiTreeUtil.getParentOfType(v, ErlangAssignmentExpression.class);
ErlangExpression right = assign != null ? assign.getRight() : null;
ErlangExpressionType varType = ErlangExpressionType.create(right);
if (contains(expectedTypes, varType)) {
result.addElement(LookupElementBuilder.create(v).withIcon(ErlangIcons.VARIABLE));
}
}
}
if (clause == null) return;
List<LookupElement> functionLookupElements = getFunctionLookupElements(clause.getContainingFile(), false, null);
for (LookupElement lookupElement : functionLookupElements) {
PsiElement psiElement = lookupElement.getPsiElement();
if (psiElement instanceof ErlangFunction) {
ErlangExpressionType erlangExpressionType = ErlangExpressionType.calculateFunctionType((ErlangFunction) psiElement);
if (contains(expectedTypes, erlangExpressionType)) result.addElement(lookupElement);
}
}
}
private boolean contains(Set<ErlangExpressionType> expectedTypes, ErlangExpressionType varType) {
for (ErlangExpressionType type : expectedTypes) {
if (type.accept(varType)) return true;
}
return false;
}
@NotNull
private Set<ErlangExpressionType> getExpectedTypes(@NotNull PsiElement argList, int pos) {
Set<ErlangExpressionType> expectedTypes = ContainerUtil.newHashSet();
PsiElement call = argList.getParent();
if (!(call instanceof ErlangFunctionCallExpression)) return expectedTypes;
try {
PsiReference callReference = call.getReference();
//noinspection ConstantConditions
ResolveResult[] resolveResults = ((PsiPolyVariantReference) callReference).multiResolve(true);
for (ResolveResult r : resolveResults) {
PsiElement element = r.getElement();
if (element instanceof ErlangFunction) {
ErlangSpecification spec = getSpecification((ErlangFunction) element);
if (spec == null) return expectedTypes;
ErlangFunTypeSigs signature = getSignature(spec);
List<ErlangTypeSig> typeSigList = signature != null ? signature.getTypeSigList() : ContainerUtil.<ErlangTypeSig>emptyList();
for (ErlangTypeSig sig : typeSigList) {
ErlangFunTypeArguments arguments = sig.getFunType().getFunTypeArguments();
ErlangType type = arguments.getTopTypeList().get(pos).getType();
processType(type, expectedTypes);
}
}
}
} catch (Exception ignored) {
}
return expectedTypes;
}
private void processType(@NotNull ErlangType type, @NotNull Set<ErlangExpressionType> expectedTypes) {
for (PsiElement childType : type.getChildren()) {
if (childType instanceof ErlangType) processType((ErlangType) childType, expectedTypes);
}
ErlangTypeRef typeRef = type.getTypeRef();
String key = typeRef != null ? typeRef.getText() : type.getFirstChild().getText();
ErlangExpressionType et = ErlangExpressionType.TYPE_MAP.get(key);
ContainerUtil.addIfNotNull(expectedTypes, et);
}
});
}