package org.elixir_lang.structure_view.element;
import com.intellij.ide.util.treeView.smartTree.TreeElement;
import com.intellij.navigation.ItemPresentation;
import com.intellij.psi.ElementDescriptionLocation;
import com.intellij.psi.PsiElement;
import com.intellij.usageView.UsageViewTypeLocation;
import org.elixir_lang.navigation.item_presentation.Parent;
import org.elixir_lang.psi.AtUnqualifiedNoParenthesesCall;
import org.elixir_lang.psi.call.Call;
import org.elixir_lang.psi.impl.ElixirPsiImplUtil;
import org.elixir_lang.structure_view.element.modular.Modular;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class Type extends Element<AtUnqualifiedNoParenthesesCall> implements Visible {
/*
* Fields
*/
private final boolean opaque;
@NotNull
private final Modular modular;
@NotNull
private final Visible.Visibility visibility;
/*
* Static Methods
*/
public static String elementDescription(Call call, ElementDescriptionLocation location) {
String elementDescription = null;
if (location == UsageViewTypeLocation.INSTANCE) {
elementDescription = "type";
}
return elementDescription;
}
@NotNull
public static Type fromCall(@NotNull Modular modular, Call call) {
return fromAtUnqualifiedNoParenthesesCall(modular, (AtUnqualifiedNoParenthesesCall) call);
}
@NotNull
public static Type fromAtUnqualifiedNoParenthesesCall(
@NotNull Modular modular,
@NotNull AtUnqualifiedNoParenthesesCall moduleAttributeDefinition) {
String moduleAttributeName = ElixirPsiImplUtil.moduleAttributeName(moduleAttributeDefinition);
boolean opaque = isOpaque(moduleAttributeName);
Visibility visibility = visibility(moduleAttributeName);
return new Type(modular, moduleAttributeDefinition, opaque, visibility);
}
public static boolean is(@NotNull Call call) {
boolean is = false;
if (call instanceof AtUnqualifiedNoParenthesesCall) {
AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall = (AtUnqualifiedNoParenthesesCall) call;
String moduleAttributeName = ElixirPsiImplUtil.moduleAttributeName(atUnqualifiedNoParenthesesCall);
is = moduleAttributeName.equals("@opaque") ||
moduleAttributeName.equals("@type") ||
moduleAttributeName.equals("@typep");
}
return is;
}
public static boolean isOpaque(@NotNull String moduleAttributeName) {
return moduleAttributeName.equals("@opaque");
}
@Nullable
public static Call type(AtUnqualifiedNoParenthesesCall atUnqualifiedNoParenthesesCall) {
PsiElement[] arguments = atUnqualifiedNoParenthesesCall.getNoParenthesesOneArgument().arguments();
Call type = null;
if (arguments.length == 1) {
PsiElement argument = arguments[0];
if (argument instanceof Call) {
type = (Call) argument;
}
}
return type;
}
@NotNull
public static Visibility visibility(@NotNull String moduleAttributeName) {
Visibility visibility = null;
if (moduleAttributeName.equals("@opaque") || moduleAttributeName.equals("@type")) {
visibility = Visibility.PUBLIC;
} else if (moduleAttributeName.equals("@typep")) {
visibility = Visibility.PRIVATE;
}
assert visibility != null;
return visibility;
}
/*
* Constructors
*/
public Type(@NotNull Modular modular,
@NotNull AtUnqualifiedNoParenthesesCall moduleAttributeDefinition,
boolean opaque,
@NotNull Visibility visibility) {
super(moduleAttributeDefinition);
this.modular = modular;
this.opaque = opaque;
this.visibility = visibility;
}
/*
* Instance Methods
*/
/**
* No children.
*
* @return empty array.
*/
@NotNull
@Override
public TreeElement[] getChildren() {
return new TreeElement[0];
}
/**
* Returns the presentation of the tree element.
*
* @return the element presentation.
*/
@NotNull
@Override
public ItemPresentation getPresentation() {
Parent parentPresentation = (Parent) modular.getPresentation();
String location = parentPresentation.getLocatedPresentableText();
return new org.elixir_lang.navigation.item_presentation.Type(
location,
type(navigationItem),
opaque,
visibility
);
}
/**
* The visibility of the element.
*
* @return {@link Visibility#PUBLIC} for {@code @type} and {@code @opaque}; {@link Visibility#PRIVATE} for
* {@code @typep}
*/
@Nullable
@Override
public Visibility visibility() {
return visibility;
}
}