package org.elixir_lang.psi.scope.module_attribute.implemetation; import com.intellij.openapi.util.Key; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementResolveResult; import com.intellij.psi.ResolveResult; import com.intellij.psi.ResolveState; import com.intellij.psi.scope.PsiScopeProcessor; import com.intellij.psi.util.PsiTreeUtil; import org.elixir_lang.psi.call.Call; import org.elixir_lang.structure_view.element.modular.Module; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Collections; import java.util.List; import static org.elixir_lang.psi.call.name.Function.DEFMODULE; import static org.elixir_lang.psi.call.name.Module.KERNEL; import static org.elixir_lang.psi.impl.ElixirPsiImplUtil.ENTRANCE; import static org.elixir_lang.structure_view.element.CallDefinitionClause.enclosingModularMacroCall; public class For implements PsiScopeProcessor { /* * * Static Methods * */ @Nullable public static List<ResolveResult> resolveResultList(boolean validResult, @NotNull PsiElement entrance) { For scopeProcessor = new For(validResult); PsiTreeUtil.treeWalkUp( scopeProcessor, entrance, entrance.getContainingFile(), ResolveState.initial().put(ENTRANCE, entrance) ); return scopeProcessor.getResolveResultList(); } /* * Fields */ private final boolean validResult; @Nullable private List<ResolveResult> resolveResultList = null; /* * Constructors */ public For(boolean validResult) { this.validResult = validResult; } /* * * Instance Methods * */ /* * Public Instance Methods */ @Override public boolean execute(@NotNull PsiElement element, @NotNull ResolveState state) { boolean keepProcessing = true; if (element instanceof Call) { keepProcessing = execute((Call) element, state); } return keepProcessing; } @Nullable @Override public <T> T getHint(@NotNull Key<T> hintKey) { return null; } @Nullable public List<ResolveResult> getResolveResultList() { return resolveResultList; } @Override public void handleEvent(@NotNull Event event, @Nullable Object associated) { } /* * Private Instance Methods */ private boolean execute(@NotNull Call call, @NotNull @SuppressWarnings("unused") ResolveState state) { boolean keepProcessing = true; if (org.elixir_lang.structure_view.element.modular.Implementation.is(call)) { PsiElement element = org.elixir_lang.structure_view.element.modular.Implementation.forNameElement(call); boolean validResult; if (element != null) { validResult = this.validResult; } else { Call enclosingModularMacroCall = enclosingModularMacroCall(call); if (enclosingModularMacroCall != null) { if (enclosingModularMacroCall.isCalling(KERNEL, DEFMODULE)) { element = Module.nameIdentifier(enclosingModularMacroCall); validResult = this.validResult; } else { element = enclosingModularMacroCall; validResult = false; } } else { element = call; validResult = false; } } resolveResultList = Collections.<ResolveResult>singletonList(new PsiElementResolveResult(element, validResult)); keepProcessing = false; } return keepProcessing; } }