use of org.apache.commons.lang.math.IntRange in project intellij-elixir by KronicDeth.
the class ElixirPsiImplUtil method exportedArity.
@Contract(pure = true)
public static int exportedArity(@NotNull final UnqualifiedNoParenthesesCall unqualifiedNoParenthesesCall) {
int arity = MaybeExported.UNEXPORTED_ARITY;
if (isExported(unqualifiedNoParenthesesCall)) {
Pair<String, IntRange> nameArityRange = CallDefinitionClause.nameArityRange(unqualifiedNoParenthesesCall);
if (nameArityRange != null) {
IntRange arityRange = nameArityRange.second;
if (arityRange != null) {
int minimumArity = arityRange.getMinimumInteger();
int maximumArity = arityRange.getMaximumInteger();
if (minimumArity == maximumArity) {
arity = minimumArity;
}
}
}
}
return arity;
}
use of org.apache.commons.lang.math.IntRange in project intellij-elixir by KronicDeth.
the class CallDefinitionClause method multiResolve.
/**
* Returns the results of resolving the reference.
*
* @param incompleteCode if true, the code in the context of which the reference is
* being resolved is considered incomplete, and the method may return additional
* invalid results.
* @return the array of results for resolving the reference.
*/
@NotNull
@Override
public ResolveResult[] multiResolve(boolean incompleteCode) {
Call enclosingModularMacroCall = enclosingModularMacroCall(moduleAttribute);
List<ResolveResult> resolveResultList = null;
if (enclosingModularMacroCall != null) {
Call[] siblings = macroChildCalls(enclosingModularMacroCall);
if (siblings != null && siblings.length > 0) {
Pair<String, Integer> nameArity = typeNameArity(myElement);
String name = nameArity.first;
int arity = nameArity.second;
for (Call call : siblings) {
if (org.elixir_lang.structure_view.element.CallDefinitionClause.is(call)) {
Pair<String, IntRange> callNameArityRange = org.elixir_lang.structure_view.element.CallDefinitionClause.nameArityRange(call);
if (callNameArityRange != null) {
String callName = callNameArityRange.first;
if (callName.equals(name)) {
IntRange callArityRange = callNameArityRange.second;
if (callArityRange.containsInteger(arity)) {
resolveResultList = add(resolveResultList, call, true);
} else if (arity < callArityRange.getMaximumInteger()) {
resolveResultList = add(resolveResultList, call, false);
}
} else if (incompleteCode && callName.startsWith(name)) {
IntRange callArityRange = callNameArityRange.second;
if (callArityRange.containsInteger(arity)) {
resolveResultList = add(resolveResultList, call, false);
} else if (arity < callArityRange.getMaximumInteger()) {
resolveResultList = add(resolveResultList, call, false);
}
}
}
}
}
}
}
ResolveResult[] resolveResults;
if (resolveResultList != null) {
resolveResults = resolveResultList.toArray(new ResolveResult[resolveResultList.size()]);
} else {
resolveResults = new ResolveResult[0];
}
return resolveResults;
}
use of org.apache.commons.lang.math.IntRange in project intellij-elixir by KronicDeth.
the class CallDefinitionClause method nameArityRange.
/**
* The name and arity range of the call definition this clause belongs to.
*
* @param call
* @return The name and arities of the {@link CallDefinition} this clause belongs. Multiple arities occur when
* default arguments are used, which produces an arity for each default argument that is turned on and off.
* @see Call#resolvedFinalArityRange()
*/
@Nullable
public static Pair<String, IntRange> nameArityRange(Call call) {
PsiElement head = head(call);
Pair<String, IntRange> pair = null;
if (head != null) {
pair = CallDefinitionHead.nameArityRange(head);
}
return pair;
}
use of org.apache.commons.lang.math.IntRange in project intellij-elixir by KronicDeth.
the class Used method provideNodesFromChild.
public static Collection<TreeElement> provideNodesFromChild(@NotNull TreeElement child) {
Collection<TreeElement> nodes = null;
if (child instanceof Use) {
Use use = (Use) child;
PsiElement[] finalArguments = ElixirPsiImplUtil.finalArguments(use.call());
assert finalArguments != null;
if (finalArguments.length > 0) {
PsiElement firstFinalArgument = finalArguments[0];
if (firstFinalArgument instanceof ElixirAccessExpression) {
PsiElement accessExpressionChild = stripAccessExpression(firstFinalArgument);
if (accessExpressionChild instanceof QualifiableAlias) {
PsiReference reference = accessExpressionChild.getReference();
if (reference != null) {
PsiElement ancestor = reference.resolve();
while (ancestor != null && !(ancestor instanceof PsiFile)) {
if (ancestor instanceof Call) {
Call call = (Call) ancestor;
if (Module.is(call)) {
Module module = new Module(call);
Call[] childCalls = ElixirPsiImplUtil.macroChildCalls(call);
if (childCalls != null) {
Map<Pair<String, Integer>, CallDefinition> macroByNameArity = new HashMap<Pair<String, Integer>, CallDefinition>(childCalls.length);
for (Call childCall : childCalls) {
/* portion of {@link org.elixir_lang.structure_view.element.enclosingModular.Module#childCallTreeElements}
dealing with macros, restricted to __using__/1 */
if (CallDefinitionClause.isMacro(childCall)) {
Pair<String, IntRange> nameArityRange = CallDefinitionClause.nameArityRange(childCall);
if (nameArityRange != null) {
String name = nameArityRange.first;
IntRange arityRange = nameArityRange.second;
if (name.equals(USING) && arityRange.containsInteger(1)) {
addClausesToCallDefinition(childCall, name, arityRange, macroByNameArity, module, Timed.Time.COMPILE, new Inserter<CallDefinition>() {
@Override
public void insert(CallDefinition element) {
}
});
}
}
}
}
if (macroByNameArity.size() > 0) {
PsiElement[] usingArguments;
CallDefinition macro;
CallDefinitionClause matchingClause = null;
if (finalArguments.length > 1) {
usingArguments = Arrays.copyOfRange(finalArguments, 1, finalArguments.length);
Pair<String, Integer> nameArity = pair(USING, usingArguments.length);
macro = macroByNameArity.get(nameArity);
if (macro != null) {
matchingClause = macro.matchingClause(usingArguments);
}
} else {
/* `use <ALIAS>` will calls `__using__/1` even though there is
no additional argument, but it obviously can't select a clause. */
Pair<String, Integer> nameArity = pair(USING, 1);
macro = macroByNameArity.get(nameArity);
List<CallDefinitionClause> macroClauseList = macro.clauseList();
if (macroClauseList.size() == 1) {
matchingClause = macroClauseList.get(0);
} else {
// TODO match default argument clause/head to non-default argument clause that would be executed.
}
}
if (matchingClause != null) {
TreeElement[] callDefinitionClauseChildren = matchingClause.getChildren();
int length = callDefinitionClauseChildren.length;
if (length > 0) {
TreeElement lastCallDefinitionClauseChild = callDefinitionClauseChildren[length - 1];
if (lastCallDefinitionClauseChild instanceof Quote) {
Quote quote = (Quote) lastCallDefinitionClauseChild;
Quote injectedQuote = quote.used(use);
TreeElement[] injectedQuoteChildren = injectedQuote.getChildren();
nodes = new ArrayList<TreeElement>(injectedQuoteChildren.length);
for (TreeElement injectedQuoteChild : injectedQuoteChildren) {
if (!(injectedQuoteChild instanceof Overridable)) {
nodes.add(injectedQuoteChild);
}
}
break;
}
}
}
}
}
} else {
break;
}
}
ancestor = ancestor.getParent();
}
}
}
}
}
}
if (nodes == null) {
nodes = Collections.emptyList();
}
return nodes;
}
use of org.apache.commons.lang.math.IntRange in project intellij-elixir by KronicDeth.
the class Module method addClausesToCallDefinition.
/*
*
* Static Methods
*
*/
/*
* Public Static Methods
*/
public static void addClausesToCallDefinition(@NotNull Call call, @NotNull Map<Pair<String, Integer>, CallDefinition> callDefinitionByNameArity, @NotNull Modular modular, @NotNull Timed.Time time, @NotNull Inserter<CallDefinition> callDefinitionInserter) {
Pair<String, IntRange> nameArityRange = CallDefinitionClause.nameArityRange(call);
if (nameArityRange != null) {
String name = nameArityRange.first;
IntRange arityRange = nameArityRange.second;
addClausesToCallDefinition(call, name, arityRange, callDefinitionByNameArity, modular, time, callDefinitionInserter);
}
}
Aggregations