package org.elixir_lang.structure_view.element.structure; 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.*; import org.elixir_lang.psi.call.Call; import org.elixir_lang.psi.impl.ElixirPsiImplUtil; import org.elixir_lang.structure_view.element.Element; import org.elixir_lang.structure_view.element.modular.Modular; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.List; import static org.elixir_lang.psi.call.name.Function.DEFSTRUCT; import static org.elixir_lang.psi.call.name.Module.KERNEL; import static org.elixir_lang.psi.impl.ElixirPsiImplUtil.stripAccessExpression; public class Structure extends Element<Call> { /* * Fields */ @NotNull private final Modular modular; /* * Static Methods */ public static String elementDescription(Call call, ElementDescriptionLocation location) { String elementDescription = null; if (location == UsageViewTypeLocation.INSTANCE) { elementDescription = "struct"; } return elementDescription; } public static boolean is(Call call) { return call.isCalling(KERNEL, DEFSTRUCT, 1); } /* * Constructors */ public Structure(@NotNull Modular modular, @NotNull Call call) { super(call); this.modular = modular; } /* * Instance Methods */ /** * Returns the list of children of the tree element. * * @return the list of children. */ @NotNull @Override public TreeElement[] getChildren() { PsiElement[] finalArguments = ElixirPsiImplUtil.finalArguments(navigationItem); List<TreeElement> childList = new ArrayList<TreeElement>(); assert finalArguments != null; assert finalArguments.length == 1; PsiElement finalArgument = finalArguments[0]; if (finalArgument instanceof QuotableKeywordList) { addDefaultValueByField(childList, (QuotableKeywordList) finalArgument); } else if (finalArgument instanceof ElixirAccessExpression) { PsiElement accessExpressionChild = stripAccessExpression(finalArgument); if (accessExpressionChild instanceof ElixirList) { ElixirList list = (ElixirList) accessExpressionChild; PsiElement[] listChildren = list.getChildren(); for (PsiElement listChild : listChildren) { if (listChild instanceof QuotableKeywordList) { addDefaultValueByField(childList, (QuotableKeywordList) listChild); } else if (listChild instanceof ElixirAccessExpression) { PsiElement listChildAccessExpressionChild = stripAccessExpression(listChild); if (listChildAccessExpressionChild instanceof ElixirAtom) { childList.add( new Field(this, (ElixirAtom) listChildAccessExpressionChild) ); } } } } } else { // TODO handle metaprogramming like {@code defstruct keys} } return childList.toArray(new TreeElement[childList.size()]); } /** * 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(); int lastIndex = location.lastIndexOf('.'); String parentLocation; String name; if (lastIndex != -1) { parentLocation = location.substring(0, lastIndex); name = location.substring(lastIndex + 1, location.length()); } else { parentLocation = null; name = location; } return new org.elixir_lang.navigation.item_presentation.structure.Structure(parentLocation, name); } /* * Private Instance Methods */ private void addDefaultValueByField(List<TreeElement> treeElementList, QuotableKeywordList defaultValueByField) { List<QuotableKeywordPair> fieldDefaultValuePairs = defaultValueByField.quotableKeywordPairList(); for (QuotableKeywordPair fieldDefaultValuePair : fieldDefaultValuePairs) { treeElementList.add(new FieldWithDefaultValue(this, fieldDefaultValuePair)); } } }