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.usageView.UsageViewTypeLocation; import org.elixir_lang.navigation.item_presentation.Parent; import org.elixir_lang.psi.call.Call; import org.elixir_lang.structure_view.element.modular.Modular; import org.elixir_lang.structure_view.element.modular.Module; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import static org.elixir_lang.psi.call.name.Function.QUOTE; import static org.elixir_lang.psi.call.name.Module.KERNEL; /** * A `quote ... do ... end` block */ public class Quote extends Element<Call> { /* * Fields */ @Nullable private final Presentable parent; /* * Static Methods */ public static String elementDescription(Call call, ElementDescriptionLocation location) { String elementDescription = null; if (location == UsageViewTypeLocation.INSTANCE) { elementDescription = "quote"; } return elementDescription; } public static boolean is(@NotNull final Call call) { // TODO change Elixir.Kernel to Elixir.Kernel.SpecialForms when resolving works return call.isCallingMacro(KERNEL, QUOTE, 1) || // without keyword arguments call.isCallingMacro(KERNEL, QUOTE, 2); // with keyword arguments } /* * Constructors */ /** * Quote in top-level, outside of any Module */ public Quote(@NotNull Call call) { this((Modular) null, call); } /** * Quote in body of {@code defmodule} or another {@code quote}. * * @param modular Direct parent module or quote of {@code call} */ public Quote(@Nullable Modular modular, @NotNull Call call) { super(call); this.parent = modular; } /** * Quote in body of {@code CallDefinitionClause} as is common is `defmacro __using__(_) do ... end` * * @param callDefinitionClause function definition clause in which {@code call} is. */ public Quote(@NotNull CallDefinitionClause callDefinitionClause, Call call) { super(call); this.parent = callDefinitionClause; } /* * Methods */ /** * Returns the presentation of the tree element. * * @return the element presentation. */ @NotNull @Override public ItemPresentation getPresentation() { String location = null; if (parent != null) { ItemPresentation parentItemPresentation = parent.getPresentation(); if (parentItemPresentation instanceof Parent) { Parent parentParentPresentation = (Parent) parentItemPresentation; location = parentParentPresentation.getLocatedPresentableText(); } } return new org.elixir_lang.navigation.item_presentation.Quote(location, navigationItem); } /** * Returns the list of children of the tree element. * * @return the list of children. */ @NotNull @Override public TreeElement[] getChildren() { Modular modular = modular(); TreeElement[] children; if (modular != null) { children = Module.callChildren(modular, navigationItem); } else { children = new TreeElement[0]; } return children; } @Nullable public Modular modular() { Modular modular = null; if (parent instanceof CallDefinitionClause) { CallDefinitionClause callDefinitionClause = (CallDefinitionClause) parent; modular = new org.elixir_lang.structure_view.element.modular.Quote(callDefinitionClause); } else if (parent instanceof Modular) { modular = (Modular) parent; } return modular; } /** * Returns a new {@link Quote} with the {@link #parent} sent to {@code module}, so that the location is resolved * correctly for {@code use <ALIAS>}. * * @param module * @return */ public Quote used(Use use) { return new Quote(new org.elixir_lang.structure_view.element.modular.Use(use), navigationItem); } }