package org.elixir_lang.psi;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.util.Function;
import org.apache.commons.lang.math.IntRange;
import org.elixir_lang.psi.call.Call;
import org.elixir_lang.psi.call.Named;
import org.elixir_lang.structure_view.element.CallDefinitionClause;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import static org.elixir_lang.psi.impl.ElixirPsiImplUtil.macroChildCalls;
import static org.elixir_lang.structure_view.element.CallDefinitionClause.nameArityRange;
public class Modular {
/*
* Public Static Methods
*/
public static boolean callDefinitionClauseCallWhile(@NotNull final Call modular,
@NotNull Function<Call, Boolean> function) {
Call[] childCalls = macroChildCalls(modular);
boolean keepProcessing = true;
if (childCalls != null) {
for (Call childCall : childCalls) {
if (CallDefinitionClause.is(childCall) && !function.fun(childCall)) {
keepProcessing = false;
break;
}
}
}
return keepProcessing;
}
public static void forEachCallDefinitionClauseNameIdentifier(
@NotNull Call modular,
@Nullable final String functionName,
final int resolvedFinalArity,
@NotNull final Function<PsiElement, Boolean> function
) {
callDefinitionClauseCallWhile(
modular,
functionName,
resolvedFinalArity,
new Function<Call, Boolean>() {
@Override
public Boolean fun(Call call) {
boolean keepProcessing = true;
if (call instanceof Named) {
Named named = (Named) call;
PsiElement nameIdentifier = named.getNameIdentifier();
if (nameIdentifier != null && !function.fun(nameIdentifier)) {
keepProcessing = false;
}
}
return keepProcessing;
}
}
);
}
/*
* Private Static Methods
*/
private static void callDefinitionClauseCallWhile(@NotNull Call modular,
@Nullable final String functionName,
final int resolvedFinalArity,
@NotNull final Function<Call, Boolean> function) {
if (functionName != null) {
callDefinitionClauseCallWhile(
modular,
new Function<Call, Boolean>() {
@Override
public Boolean fun(@NotNull Call callDefinitionClauseCall) {
Pair<String, IntRange> nameArityRange = nameArityRange(callDefinitionClauseCall);
boolean keepProcessing = true;
if (nameArityRange != null) {
String name = nameArityRange.first;
if (name != null && name.equals(functionName)) {
IntRange arityRange = nameArityRange.second;
if (arityRange.containsInteger(resolvedFinalArity) &&
!function.fun(callDefinitionClauseCall)) {
keepProcessing = false;
}
}
}
return keepProcessing;
}
}
);
}
}
}