Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Structure View #243

Merged
merged 39 commits into from
Feb 25, 2016
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
00a10fa
Module structure view
KronicDeth Jan 21, 2016
c7525c9
Kernel.def/2 structure view
KronicDeth Jan 23, 2016
cacd8c6
Group function clauses together in Structure View
KronicDeth Jan 24, 2016
23adbcf
defdelegate structure view
KronicDeth Jan 26, 2016
20f0a57
Fix tests after removal of NoParenthesesExpression
KronicDeth Jan 27, 2016
6ff7cbd
Optimize imports
KronicDeth Jan 27, 2016
67c0e2a
Fix ambiguous_op quoting by skiping identifier element
KronicDeth Jan 27, 2016
62c12cd
Compress implements and methods for InfixOperation
KronicDeth Jan 28, 2016
4b6320b
Handle operations for `def/2` names
KronicDeth Jan 30, 2016
48547b5
Group callbacks under defexception
KronicDeth Jan 31, 2016
eb22a14
Always show default values for exception fields
KronicDeth Feb 1, 2016
7223cd1
defimpl structure view
KronicDeth Feb 2, 2016
ae8fda8
defmacro in structure
KronicDeth Feb 3, 2016
6b9fd78
Collapse Function and Macro structure view
KronicDeth Feb 5, 2016
0897759
Time sort
KronicDeth Feb 6, 2016
7a7f353
Fake new RowIcon(Icon... icon) with factory
KronicDeth Feb 6, 2016
0b5d686
defp and defmacrop structure
KronicDeth Feb 6, 2016
821f40e
Visibility sorter
KronicDeth Feb 6, 2016
cbcf038
Show structure inside of quote calls
KronicDeth Feb 7, 2016
c835a82
defoverridable structure
KronicDeth Feb 8, 2016
00a1bd8
Mark function CallDefinition as overridable
KronicDeth Feb 9, 2016
df5829d
`use` in Structure
KronicDeth Feb 9, 2016
41ff2c6
Default arguments generate entry for each arity
KronicDeth Feb 13, 2016
1a9415f
Provide __using__ quote's function to use location
KronicDeth Feb 15, 2016
5e5abb2
Show "use <ALIAS>" for location of injected functions
KronicDeth Feb 15, 2016
d5d3dde
Mark function overrides for use overriddable functions
KronicDeth Feb 17, 2016
202c156
Remove unused import that fails on travis-ci
KronicDeth Feb 17, 2016
3f7f02b
Callbacks using implemented method icon
KronicDeth Feb 20, 2016
6b892fc
@spec in structure view
KronicDeth Feb 20, 2016
8d8871a
Use NameArity for callback presentation
KronicDeth Feb 21, 2016
1d4b939
Callbacks split into name/arity and spec
KronicDeth Feb 21, 2016
6d62b16
Fix case-sensitive naming
KronicDeth Feb 22, 2016
b0731c6
@type, @typep and @opaque in Structure
KronicDeth Feb 22, 2016
6116b4b
defprotocol in Structure
KronicDeth Feb 22, 2016
935ba90
Structure with defstruct and its fields
KronicDeth Feb 23, 2016
5d2a393
Qualified alias support for defimpl
KronicDeth Feb 23, 2016
b236449
Fix Scroll From Source
KronicDeth Feb 24, 2016
ea00323
Better Scroll From Source
KronicDeth Feb 24, 2016
f693070
Show implicit Structure for Exception
KronicDeth Feb 24, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
@SPEC in structure view
@SPEC show up as sibling of call definition clauses because the mapping
of @SPEC to clause is not always one-to-one so it better to group
everything under the call definition.
  • Loading branch information
KronicDeth committed Feb 22, 2016
commit 6b892fc93d4c7c9e46a4c74917eacbf21921d3c2
Binary file added res/icons/type.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added res/icons/type@2x.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
133 changes: 91 additions & 42 deletions src/org/elixir_lang/icons/ElixirIcons.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,61 +5,110 @@
import com.intellij.ui.LayeredIcon;
import com.intellij.ui.RowIcon;
import com.intellij.util.PlatformIcons;
import org.elixir_lang.structure_view.element.Timed;
import org.elixir_lang.structure_view.element.Visible;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;

// RowIcon on travis-ci does not have RowIcon(Icon...) constructor, so fake it
class RowIconFactory {
public static RowIcon create(Icon... icons) {
RowIcon rowIcon = new RowIcon(icons.length);
public static RowIcon create(Icon... icons) {
RowIcon rowIcon = new RowIcon(icons.length);

for (int i = 0; i < icons.length; i++) {
rowIcon.setIcon(icons[i], i);
}
for (int i = 0; i < icons.length; i++) {
rowIcon.setIcon(icons[i], i);
}

return rowIcon;
}
return rowIcon;
}
}

/**
* Created by zyuyou on 15/7/6.
*/
public interface ElixirIcons {
class Time {
public static final Icon COMPILE = AllIcons.Actions.Compile;
public static final Icon RUN = AllIcons.General.Run;

@NotNull
public static Icon from(@NotNull Timed.Time time) {
Icon icon = null;

switch (time) {
case COMPILE:
icon = COMPILE;
break;
case RUN:
icon = RUN;
break;
}

assert icon != null;

return icon;
}
}

class Visibility {
public static final Icon PRIVATE = PlatformIcons.PRIVATE_ICON;
public static final Icon PUBLIC = PlatformIcons.PUBLIC_ICON;

@NotNull
public static Icon from(@Nullable Visible.Visibility visibility) {
Icon icon = null;


if (visibility != null) {
switch (visibility) {
case PRIVATE:
icon = PRIVATE;
break;
case PUBLIC:
icon = PUBLIC;
break;
}

assert icon != null;
} else {
icon = ElixirIcons.UNKNOWN;
}

return icon;
}
}

Icon CALLBACK = AllIcons.Gutter.ImplementedMethod;
Icon CALL_DEFINITION = PlatformIcons.FUNCTION_ICON;
Icon CALL_DEFINITION_CLAUSE = RowIconFactory.create(CALL_DEFINITION, PlatformIcons.PACKAGE_LOCAL_ICON);
Icon DELEGATION = RowIconFactory.create(AllIcons.General.Run, PlatformIcons.PACKAGE_LOCAL_ICON);
Icon EXCEPTION = PlatformIcons.EXCEPTION_CLASS_ICON;
Icon FILE = IconLoader.getIcon("/icons/elixir-16.png");
Icon IMPLEMENTATION = PlatformIcons.ANONYMOUS_CLASS_ICON;
Icon MIX_MODULE_CONFLICT = AllIcons.Actions.Cancel;
Icon MODULE = PlatformIcons.PACKAGE_ICON;
Icon OVERRIDABLE = AllIcons.General.OverridenMethod;
Icon OVERRIDE = AllIcons.General.OverridingMethod;
// same icon as intellij-erlang to match their look and feel
Icon TYPE = IconLoader.getIcon("/icons/type.png");
// MUST be after TYPE
Icon SPECIFICATION = RowIconFactory.create(CALL_DEFINITION, TYPE);


// it is the unknown that is only a question mark
Icon UNKNOWN = AllIcons.RunConfigurations.Unknown;

Icon ELIXIR_APPLICATION = IconLoader.getIcon("/icons/elixir-Application-16.png");
Icon ELIXIR_SUPERVISOR = IconLoader.getIcon("/icons/elixir-Supervisor-16.png");
Icon ELIXIR_GEN_EVENT = IconLoader.getIcon("/icons/elixir-GenEvent-16.png");
Icon ELIXIR_GEN_SERVER = IconLoader.getIcon("/icons/elixir-GenServer-16.png");

Icon ELIXIR_MARK = IconLoader.getIcon("/icons/elixir-mark.png");
Icon ELIXIR_MODULE_NODE = new LayeredIcon(PlatformIcons.FOLDER_ICON, ELIXIR_MARK);

interface Time {
Icon COMPILE = AllIcons.Actions.Compile;
Icon RUN = AllIcons.General.Run;
}

interface Visibility {
Icon PRIVATE = PlatformIcons.PRIVATE_ICON;
Icon PUBLIC = PlatformIcons.PUBLIC_ICON;
}

Icon CALLBACK = AllIcons.Gutter.ImplementedMethod;
Icon CALL_DEFINITION = PlatformIcons.FUNCTION_ICON;
Icon CALL_DEFINITION_CLAUSE = RowIconFactory.create(CALL_DEFINITION, PlatformIcons.PACKAGE_LOCAL_ICON);
Icon DELEGATION = RowIconFactory.create(AllIcons.General.Run, PlatformIcons.PACKAGE_LOCAL_ICON);
Icon EXCEPTION = PlatformIcons.EXCEPTION_CLASS_ICON;
Icon FILE = IconLoader.getIcon("/icons/elixir-16.png");
Icon IMPLEMENTATION = PlatformIcons.ANONYMOUS_CLASS_ICON;
Icon MIX_MODULE_CONFLICT = AllIcons.Actions.Cancel;
Icon MODULE = PlatformIcons.PACKAGE_ICON;
Icon OVERRIDABLE = AllIcons.General.OverridenMethod;
Icon OVERRIDE = AllIcons.General.OverridingMethod;

// it is the unknown that is only a question mark
Icon UNKNOWN = AllIcons.RunConfigurations.Unknown;

Icon ELIXIR_APPLICATION = IconLoader.getIcon("/icons/elixir-Application-16.png");
Icon ELIXIR_SUPERVISOR = IconLoader.getIcon("/icons/elixir-Supervisor-16.png");
Icon ELIXIR_GEN_EVENT = IconLoader.getIcon("/icons/elixir-GenEvent-16.png");
Icon ELIXIR_GEN_SERVER = IconLoader.getIcon("/icons/elixir-GenServer-16.png");

Icon ELIXIR_MARK = IconLoader.getIcon("/icons/elixir-mark.png");
Icon ELIXIR_MODULE_NODE = new LayeredIcon(PlatformIcons.FOLDER_ICON, ELIXIR_MARK);

Icon MIX = IconLoader.getIcon("/icons/mix-16.png");
Icon MIX_EX_UNIT = new LayeredIcon(MIX, AllIcons.Nodes.JunitTestMark);
Icon MIX = IconLoader.getIcon("/icons/mix-16.png");
Icon MIX_EX_UNIT = new LayeredIcon(MIX, AllIcons.Nodes.JunitTestMark);
}

Original file line number Diff line number Diff line change
Expand Up @@ -77,37 +77,18 @@ public String getLocationString() {
@Nullable
@Override
public Icon getIcon(boolean unused) {
RowIcon rowIcon = new RowIcon(3);
Icon timeIcon = null;
Icon[] icons = new Icon[]{
ElixirIcons.Time.from(callDefinition.time()),
ElixirIcons.Visibility.from(visibility),
ElixirIcons.CALL_DEFINITION_CLAUSE
};

switch (callDefinition.time()) {
case COMPILE:
timeIcon = ElixirIcons.Time.COMPILE;
break;
case RUN:
timeIcon = ElixirIcons.Time.RUN;
break;
}

assert timeIcon != null;

Icon visibilityIcon = null;
RowIcon rowIcon = new RowIcon(icons.length);

switch (visibility) {
case PRIVATE:
visibilityIcon = ElixirIcons.Visibility.PRIVATE;
break;
case PUBLIC:
visibilityIcon = ElixirIcons.Visibility.PUBLIC;
break;
for (int layer = 0; layer < icons.length; layer++) {
rowIcon.setIcon(icons[layer], layer);
}

assert visibilityIcon != null;

rowIcon.setIcon(timeIcon, 0);
rowIcon.setIcon(visibilityIcon, 1);
rowIcon.setIcon(ElixirIcons.CALL_DEFINITION_CLAUSE, 2);

return rowIcon;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
package org.elixir_lang.navigation.item_presentation;

import com.intellij.navigation.ItemPresentation;
import com.intellij.ui.RowIcon;
import org.elixir_lang.icons.ElixirIcons;
import org.elixir_lang.psi.call.Call;
import org.elixir_lang.structure_view.element.Timed;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;

public class CallDefinitionSpecification implements ItemPresentation {
/*
* Fields
*/

@Nullable
private final Call specification;
@NotNull
private final Timed.Time time;

/*
* Constructors
*/

/**
* @param specification should only be {@code null} when format is unrecognized because it is invalid or mid-editing
*/
public CallDefinitionSpecification(@Nullable Call specification, Timed.Time time) {
this.specification = specification;
this.time = time;
}

/**
* Returns the icon representing the object.
*
* @param unused Used to mean if open/close icons for tree renderer. No longer in use. The parameter is only there for API compatibility reason.
*/
@Nullable
@Override
public Icon getIcon(boolean unused) {
Icon[] icons = new Icon[]{
ElixirIcons.Time.from(time),
ElixirIcons.Visibility.PUBLIC,
ElixirIcons.SPECIFICATION
};

RowIcon rowIcon = new RowIcon(icons.length);

for (int layer = 0; layer < icons.length; layer++) {
rowIcon.setIcon(icons[layer], layer);
}

return rowIcon;
}

/**
* Returns the location of the object (for example, the package of a class). The location
* string is used by some renderers and usually displayed as grayed text next to the item name.
*
* @return the location description, or null if none is applicable.
*/
@Nullable
@Override
public String getLocationString() {
return null;
}

/**
* Returns the name of the object to be presented in most renderers across the program.
*
* @return the object name.
*/
@Nullable
@Override
public String getPresentableText() {
String presentableText = null;

if (specification != null) {
presentableText = specification.getText();
}

return presentableText;
}

}
32 changes: 30 additions & 2 deletions src/org/elixir_lang/structure_view/element/CallDefinition.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,12 @@
import com.intellij.ide.util.treeView.smartTree.TreeElement;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.Pair;
import com.intellij.util.containers.ContainerUtil;
import org.apache.commons.lang.math.IntRange;
import com.intellij.psi.PsiElement;
import org.elixir_lang.navigation.item_presentation.NameArity;
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.structure_view.element.modular.Modular;
import org.jetbrains.annotations.NotNull;
Expand All @@ -29,6 +31,9 @@ public class CallDefinition implements StructureViewTreeElement, Timed, Visible
*/

private final int arity;
// keeps track of total order of all children (clauses and specifications)
@NotNull
private final List<TreeElement> childList = new ArrayList<TreeElement>();
@NotNull
private final List<CallDefinitionClause> clauseList = new ArrayList<CallDefinitionClause>();
@NotNull
Expand All @@ -39,6 +44,7 @@ public class CallDefinition implements StructureViewTreeElement, Timed, Visible
private boolean overridable;
// overrides an overridable function
private boolean override;
private List<CallDefinitionSpecification> specificationList = new ArrayList<CallDefinitionSpecification>();
@NotNull
private final Time time;

Expand Down Expand Up @@ -72,7 +78,9 @@ public void clause(Call clause) {
assert nameArityRange.first.equals(name);
assert nameArityRange.second.getMinimumInteger() <= arity && nameArityRange.second.getMaximumInteger() >= arity;

clauseList.add(new CallDefinitionClause(this, clause));
CallDefinitionClause callDefinitionClause = new CallDefinitionClause(this, clause);
childList.add(callDefinitionClause);
clauseList.add(callDefinitionClause);
}

public List<CallDefinitionClause> clauseList() {
Expand All @@ -87,7 +95,7 @@ public List<CallDefinitionClause> clauseList() {
@NotNull
@Override
public TreeElement[] getChildren() {
return clauseList.toArray(new TreeElement[clauseList.size()]);
return childList.toArray(new TreeElement[childList.size()]);
}

/**
Expand Down Expand Up @@ -255,6 +263,26 @@ public void setOverridable(boolean overridable) {
this.overridable = overridable;
}

/**
*
* @param moduleAttributeDefinition
*/
public void specification(AtUnqualifiedNoParenthesesCall moduleAttributeDefinition) {
Pair<String, Integer> nameArity = CallDefinitionSpecification.moduleAttributeNameArity(
moduleAttributeDefinition
);

assert nameArity != null;
assert nameArity.first.equals(name);
assert nameArity.second == arity;

CallDefinitionSpecification callDefinitionSpecification = new CallDefinitionSpecification(
modular,
moduleAttributeDefinition
);
childList.add(callDefinitionSpecification);
specificationList.add(callDefinitionSpecification);
}
/**
* The visibility of the element.
*
Expand Down
Loading