package org.elixir_lang.structure_view; import com.intellij.ide.structureView.StructureViewModel; import com.intellij.ide.structureView.StructureViewTreeElement; import com.intellij.ide.structureView.TextEditorBasedStructureViewModel; import com.intellij.ide.util.treeView.smartTree.NodeProvider; import com.intellij.ide.util.treeView.smartTree.Sorter; import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; import org.elixir_lang.psi.ElixirAtom; import org.elixir_lang.psi.ElixirFile; import org.elixir_lang.psi.QuotableKeywordPair; import org.elixir_lang.psi.call.Call; import org.elixir_lang.structure_view.element.*; import org.elixir_lang.structure_view.element.Exception; import org.elixir_lang.structure_view.element.modular.Implementation; import org.elixir_lang.structure_view.element.modular.Module; import org.elixir_lang.structure_view.element.modular.Protocol; import org.elixir_lang.structure_view.element.modular.Unknown; import org.elixir_lang.structure_view.element.structure.Field; import org.elixir_lang.structure_view.element.structure.FieldWithDefaultValue; import org.elixir_lang.structure_view.element.structure.Structure; import org.elixir_lang.structure_view.node_provider.Used; import org.elixir_lang.structure_view.sorter.Time; import org.elixir_lang.structure_view.sorter.Visibility; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.Arrays; import java.util.Collection; public class Model extends TextEditorBasedStructureViewModel implements StructureViewModel.ElementInfoProvider { /* * Static Fields */ private static final Collection<NodeProvider> NODE_PROVIDERS = Arrays.<NodeProvider>asList(new Used()); /* * Static Methods */ public static boolean isSuitable(Call call) { // everything in {@link Module#childCallTreeElements} return CallDefinitionClause.isFunction(call) || CallDefinitionClause.isMacro(call) || CallDefinitionHead.is(call) || CallDefinitionSpecification.is(call) || Callback.is(call) || Delegation.is(call) || Exception.is(call) || Implementation.is(call) || Module.is(call) || Overridable.is(call) || Protocol.is(call) || Quote.is(call) || Structure.is(call) || Type.is(call) || Use.is(call) || Unknown.is(call); } /* * Constructors */ public Model(@NotNull ElixirFile elixirFile, @Nullable Editor editor) { super(editor, elixirFile); } /* * Public Instance Methods */ @NotNull @Override public Collection<NodeProvider> getNodeProviders() { return NODE_PROVIDERS; } @Override public ElixirFile getPsiFile() { return (ElixirFile) super.getPsiFile(); } @NotNull @Override public Sorter[] getSorters() { return new Sorter[] { Time.INSTANCE, Visibility.INSTANCE, Sorter.ALPHA_SORTER, }; } /** * Returns the list of PSI element classes which are shown as structure view elements. * When determining the current editor element, the PSI tree is walked up until an element * matching one of these classes is found. * * @return the list of classes */ @NotNull @Override protected Class[] getSuitableClasses() { return new Class[]{ Call.class, ElixirAtom.class, QuotableKeywordPair.class }; } @Override public boolean isAlwaysShowsPlus(StructureViewTreeElement element) { return false; } @Override public boolean isAlwaysLeaf(StructureViewTreeElement element) { return element instanceof ElixirFile; } @Override protected boolean isSuitable(PsiElement element) { boolean suitable = false; // checks if the class is good if (super.isSuitable(element)) { // calls can be nested in calls, so need to check for sure if (element instanceof Call) { Call call = (Call) element; suitable = isSuitable(call); } else if (element instanceof ElixirAtom) { ElixirAtom atom = (ElixirAtom) element; suitable = Field.is(atom); } else if (element instanceof QuotableKeywordPair) { QuotableKeywordPair quotableKeywordPair = (QuotableKeywordPair) element; suitable = FieldWithDefaultValue.is(quotableKeywordPair); } } return suitable; } /** * Returns the root element of the structure view tree. * * @return the structure view root. */ @NotNull @Override public StructureViewTreeElement getRoot() { return new File(getPsiFile()); } }