package org.elixir_lang.reference.callable;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiReference;
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
import org.apache.commons.lang.math.IntRange;
import org.elixir_lang.psi.ElixirIdentifier;
import org.elixir_lang.psi.call.Call;
import org.elixir_lang.structure_view.element.CallDefinitionClause;
import org.jetbrains.annotations.NotNull;
import static com.intellij.openapi.util.Pair.pair;
import static org.elixir_lang.structure_view.element.CallDefinitionClause.nameArityRange;
public class Issue480Test extends LightCodeInsightFixtureTestCase {
/*
* Tests
*/
public void testLocal() {
myFixture.configureByFiles("local.ex", "referenced.ex");
assertReferenceAndResolvedNameArityRange("changeset", 2);
}
public void testRemote() {
myFixture.configureByFiles("remote.ex", "referenced.ex");
assertUnresolvableReferenceNameArityRange("changeset", 1);
}
public void testDirectModuleQualifier() {
myFixture.configureByFiles("direct_module_qualifier.ex", "referenced.ex");
assertReferenceAndResolvedNameArityRange("changeset", 1);
}
public void testAliasedModuleQualifier() {
myFixture.configureByFiles("aliased_module_qualifier.ex", "referenced.ex");
assertReferenceAndResolvedNameArityRange("changeset", 1);
}
public void testDoubleAliasesModuleQualifier() {
myFixture.configureByFiles("double_aliased_module_qualifier.ex", "referenced.ex");
assertUnresolvableReferenceNameArityRange("changeset", 1);
}
public void testMapAccessQualifier() {
myFixture.configureByFiles("map_access_qualifier.ex", "referenced.ex");
assertUnresolvableReferenceNameArityRange("__struct__", 1);
}
public void testUnresolvedAliasQualifier() {
myFixture.configureByFiles("unresolved_alias_qualifier.ex", "referenced.ex");
assertUnresolvableReferenceNameArityRange("changeset", 1);
}
/*
* Protected Instance Methods
*/
@Override
protected String getTestDataPath() {
return "testData/org/elixir_lang/reference/callable/issue_480";
}
/*
* Private Instance Methods
*/
private void assertUnresolvableReferenceNameArityRange(@NotNull String name, int arity) {
PsiElement elementAtCaret = myFixture
.getFile()
.findElementAt(myFixture.getCaretOffset());
assertNotNull(elementAtCaret);
PsiElement grandParent = elementAtCaret.getParent().getParent();
assertNotNull(grandParent);
assertInstanceOf(grandParent, Call.class);
Call grandParentCall = (Call) grandParent;
assertEquals(name, grandParentCall.functionName());
assertEquals(arity, grandParentCall.resolvedFinalArity());
PsiReference reference = grandParent.getReference();
assertNotNull(reference);
PsiElement resolved = reference.resolve();
assertNull(resolved);
}
private void assertReferenceAndResolvedNameArityRange(@NotNull String name, int arity) {
PsiElement elementAtCaret = myFixture
.getFile()
.findElementAt(myFixture.getCaretOffset());
assertNotNull(elementAtCaret);
PsiElement grandParent = elementAtCaret.getParent().getParent();
assertNotNull(grandParent);
assertInstanceOf(grandParent, Call.class);
Call grandParentCall = (Call) grandParent;
assertEquals(name, grandParentCall.functionName());
assertEquals(arity, grandParentCall.resolvedFinalArity());
assertResolvedNameArityRange(grandParentCall, name, arity);
}
private void assertResolvedNameArityRange(@NotNull PsiElement element, @NotNull String name, int arity) {
PsiReference reference = element.getReference();
assertNotNull(reference);
PsiElement resolved = reference.resolve();
assertNotNull(resolved);
assertInstanceOf(resolved, ElixirIdentifier.class);
PsiElement maybeDefMaybeCall = resolved.getParent().getParent().getParent();
assertInstanceOf(maybeDefMaybeCall, Call.class);
Call maybeDefCall = (Call) maybeDefMaybeCall;
assertTrue(CallDefinitionClause.is(maybeDefCall));
assertEquals(pair(name, new IntRange(arity)), nameArityRange(maybeDefCall));
}
}