Skip to content

Commit

Permalink
Flat tree structure, fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
pbroadbery committed Mar 3, 2018
1 parent 8e2ccfb commit bca53cf
Show file tree
Hide file tree
Showing 45 changed files with 1,165 additions and 201 deletions.
2 changes: 1 addition & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions .idea/shelf/Initial_attempt_at_psiSubs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
plugins {
id 'org.jetbrains.intellij' version "0.2.5"
id 'org.jetbrains.intellij' version "0.2.7"
id "de.undercouch.download" version "3.2.0"
}


allprojects {
apply plugin: 'java'
group = 'org.aldor.idea'
version = '1.0'
version = '1.1'

sourceSets {
main.java.srcDirs = ['src/main/java', 'src/gen/jflex', 'src/gen/grammar']
Expand All @@ -22,7 +22,7 @@ allprojects {

plugins = []

//updateSinceUntilBuild = false// Was in haskell, but..
updateSinceUntilBuild = false// Was in haskell, but..

sandboxDirectory = project.rootDir.canonicalPath + "/.sandbox"
}
Expand Down
32 changes: 27 additions & 5 deletions resources/META-INF/plugin.xml
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
<!--suppress XmlHighlighting -->
<idea-plugin version="2">
<idea-plugin>
<id>pab.aldor</id>
<name>Aldor Plugin</name>
<version>1.0</version>
<vendor email="nobody@example.com" url="http://www.notreally.org">Peter Broadbery</vendor>
<version>1.1</version>
<vendor email="p.broadbery@gmail.com" url="http://www.notreally.org">Peter Broadbery</vendor>

<description><![CDATA[
Aldor/Spad plugin.
]]></description>

<change-notes><![CDATA[
Version the first
Version the second
]]>
</change-notes>

<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->
<idea-version since-build="141.0"/>
<idea-version since-build="173"/>

<!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html
on how to target different products -->
Expand Down Expand Up @@ -84,6 +84,7 @@

<lang.psiStructureViewFactory language="Spad" implementationClass="aldor.structure.AldorPsiStructureViewFactory"/>
<typeHierarchyProvider implementationClass="aldor.hierarchy.AldorTypeHierarchyProvider" language="Spad"/>
<methodHierarchyProvider implementationClass="aldor.hierarchy.AldorMissingHierarchyProvider" language="Spad"/>

<configurationType implementation="aldor.spad.runconfiguration.SpadInputRunConfigurationType" />
<runConfigurationProducer implementation = "aldor.spad.runconfiguration.SpadInputRunConfigurationProducer"/>
Expand All @@ -108,6 +109,27 @@
text="Create New SPAD File" description="Creates a new SPAD file">
<add-to-group group-id="NewGroup" anchor="after" relative-to-action="NewFile"/>
</action>

<action id="AldorTypeHierarchy.BaseOnThisType" text="Base on this Type"
class="aldor.hierarchy.AldorTypeHierarchyBrowser$AldorBaseOnThisTypeAction"
use-shortcut-of="TypeHierarchy"/>
<group id="AldorTypeHierarchyPopupMenu">
<reference ref="AldorTypeHierarchy.BaseOnThisType"/>
<reference ref="TypeHierarchy.Class"/>
<reference ref="TypeHierarchy.Subtypes"/>
<reference ref="TypeHierarchy.Supertypes"/>
<separator/>
<reference ref="EditSource"/>
<separator/>
<reference ref="FindUsages"/>
<reference ref="RefactoringMenu"/>
<separator/>
<reference ref="AddToFavorites"/>
<separator/>
<reference ref="VersionControlsGroup"/>
<separator/>
</group>

</actions>

<application-components>
Expand Down
36 changes: 36 additions & 0 deletions src/main/java/aldor/build/module/AldorBuildLocationForm.form
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?xml version="1.0" encoding="UTF-8"?>
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="aldor.build.module.AldorBuildLocationForm">
<grid id="27dc6" layout-manager="GridLayoutManager" row-count="2" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<xy x="20" y="20" width="500" height="400"/>
</constraints>
<properties/>
<border type="none"/>
<children>
<component id="6433d" class="javax.swing.JLabel">
<constraints>
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text value="Build Directory"/>
</properties>
</component>
<vspacer id="1f79b">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<component id="c8720" class="javax.swing.JTextField" binding="buildDirectory">
<constraints>
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false">
<preferred-size width="150" height="-1"/>
</grid>
</constraints>
<properties>
<toolTipText value="Location of Build Directory"/>
</properties>
</component>
</children>
</grid>
</form>
8 changes: 8 additions & 0 deletions src/main/java/aldor/build/module/AldorBuildLocationForm.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package aldor.build.module;

import javax.swing.JComponent;
import javax.swing.JTextField;

public class AldorBuildLocationForm extends JComponent {
private JTextField buildDirectory;
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public static class OutputDirectoryEditor extends ModuleElementsEditor {

public OutputDirectoryEditor(ModuleConfigurationState state) {
super(state);
outputEditor = new AldorBuildElementsEditor(state);
outputEditor = new AldorBuildPathEditor(state);
}

@Override
Expand All @@ -73,13 +73,35 @@ public String getHelpTopic() {
}
}

private static class AldorBuildElementsEditor extends BuildElementsEditor {
private static class AldorBuildPathEditor extends BuildElementsEditor {

protected AldorBuildElementsEditor(ModuleConfigurationState state) {
protected AldorBuildPathEditor(ModuleConfigurationState state) {
super(state);
}
}

/* Giving up and using the output editor instead.
* Would be nice to have a custom editor
private static class LocalBuildElementsEditor extends ModuleElementsEditor {
AldorBuildLocationForm locationForm = new AldorBuildLocationForm();
protected LocalBuildElementsEditor(@NotNull ModuleConfigurationState state) {
super(state);
}
@Override
protected JComponent createComponentImpl() {
return locationForm;
}
@Nls
@Override
public String getDisplayName() {
return "Local Build Location";
}
}
*/
/**
* Classpath editor tweaked to hide class path boxes (keeps the module setting)
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;

import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
Expand Down Expand Up @@ -64,7 +65,7 @@ protected void addCompletions(@NotNull CompletionParameters parameters,
public List<LookupElement> allTypes(CompletionParameters parameters) {
PsiElement elt = parameters.getPosition();
SpadLibrary spadLibrary = SpadLibraryManager.instance().spadLibraryForElement(elt);
return allTypes(spadLibrary);
return (spadLibrary == null) ? Collections.emptyList() : allTypes(spadLibrary);
}

@VisibleForTesting
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package aldor.hierarchy;

import com.intellij.ide.hierarchy.TypeHierarchyBrowserBase;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.actionSystem.ToggleAction;
import com.intellij.openapi.application.ApplicationManager;
import org.jetbrains.annotations.NotNull;

import javax.swing.Icon;

public abstract class AbstractChangeHierarchyViewAction extends ToggleAction {

AbstractChangeHierarchyViewAction(final String shortDescription, final String longDescription, final Icon icon) {
super(shortDescription, longDescription, icon);
}

@Override
public final boolean isSelected(final AnActionEvent event) {
final AldorTypeHierarchyBrowser browser = (AldorTypeHierarchyBrowser) getTypeHierarchyBrowser(event.getDataContext());
return (browser != null) && getTypeName().equals(browser.typeName());
}

protected abstract String getTypeName();

@Override
public final void setSelected(final AnActionEvent event, final boolean flag) {
if (flag) {
final TypeHierarchyBrowserBase browser = getTypeHierarchyBrowser(event.getDataContext());
// setWaitCursor();
ApplicationManager.getApplication().invokeLater(() -> {
if (browser != null) {
browser.changeView(getTypeName());
}
});
}
}

@Override
public void update(@NotNull final AnActionEvent event) {
// its important to assign the myTypeHierarchyBrowser first
super.update(event);
final Presentation presentation = event.getPresentation();
presentation.setEnabled(true);
}

static TypeHierarchyBrowserBase getTypeHierarchyBrowser(final DataContext context) {
return TypeHierarchyBrowserBase.DATA_KEY.getData(context);
}


}
119 changes: 119 additions & 0 deletions src/main/java/aldor/hierarchy/AldorFlatHierarchyTreeStructure.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package aldor.hierarchy;

import aldor.spad.SpadLibrary;
import aldor.spad.SpadLibraryManager;
import aldor.syntax.Syntax;
import aldor.syntax.SyntaxPrinter;
import aldor.syntax.SyntaxUtils;
import com.intellij.ide.hierarchy.HierarchyNodeDescriptor;
import com.intellij.ide.hierarchy.HierarchyTreeStructure;
import com.intellij.ide.util.treeView.NodeDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Deque;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static aldor.syntax.SyntaxUtils.psiElementFromSyntax;

public class AldorFlatHierarchyTreeStructure extends HierarchyTreeStructure {
private static final Object[] EMPTY_ARRAY = new Object[0];
//private final SmartPsiElementPointer<PsiElement> smartPointer;

public AldorFlatHierarchyTreeStructure(Project project, @NotNull Syntax syntax) {
super(project, createBaseNodeDescriptor(project, syntax));
//this.smartPointer = SmartPointerManager.getInstance(project).createSmartPsiElementPointer(psiElementFromSyntax(syntax));
}

private static HierarchyNodeDescriptor createBaseNodeDescriptor(Project project, @NotNull Syntax syntax) {
return new AldorHierarchyNodeDescriptor(project, null, psiElementFromSyntax(syntax), syntax, true);
}

@Override
public boolean isAlwaysLeaf(Object element) {
if (!(element instanceof HierarchyNodeDescriptor)) {
return true;
}
HierarchyNodeDescriptor descriptor = (HierarchyNodeDescriptor) element;
if (descriptor instanceof ErrorNodeDescriptor) {
return true;
}
if (descriptor.getParentDescriptor() != null) {
return true;
}
return false;
}

@NotNull
@Override
protected Object[] buildChildren(@NotNull HierarchyNodeDescriptor descriptor) {
if (descriptor instanceof ErrorNodeDescriptor) {
return EMPTY_ARRAY;
}
if (descriptor.getParentDescriptor() != null) {
return EMPTY_ARRAY;
}

AldorHierarchyNodeDescriptor nodeDescriptor = (AldorHierarchyNodeDescriptor) descriptor;
SpadLibrary library = SpadLibraryManager.instance().spadLibraryForElement(descriptor.getPsiElement());
if (library == null) {
return new Object[] { "Missing library"};
}
Syntax syntax = nodeDescriptor.syntax();
List<Syntax> parents = this.parents(library, syntax);
//noinspection ObjectEquality
assert parents.get(0) == syntax;
List<SpadLibrary.Operation> operations = this.operations(library, parents);

Stream<Object> parentNodes = parents.subList(1, parents.size()-1).stream().map(psyntax -> createNodeDescriptorMaybe(nodeDescriptor, psyntax));
Stream<Object> operationNodes = operations.stream().map(op -> createOperationNodeDescriptorMaybe(nodeDescriptor, op));

return Stream.concat(parentNodes, operationNodes).toArray();
}


private Object createNodeDescriptorMaybe(AldorHierarchyNodeDescriptor parent, Syntax syntax) {
if (psiElementFromSyntax(syntax) == null) {
return new ErrorNodeDescriptor(parent, "Unknown element - " + SyntaxPrinter.instance().toString(syntax));
}
else {
return createNodeDescriptor(parent, syntax);
}
}

private HierarchyNodeDescriptor createNodeDescriptor(NodeDescriptor<PsiElement> parentDescriptor, Syntax syntax) {
return new AldorHierarchyNodeDescriptor(this.myProject, parentDescriptor, psiElementFromSyntax(syntax), syntax, false);
}

private Object createOperationNodeDescriptorMaybe(@NotNull AldorHierarchyNodeDescriptor parent, SpadLibrary.Operation operation) {
return new AldorHierarchyOperationDescriptor(this.myProject, parent, operation);
}



private List<Syntax> parents(SpadLibrary library, Syntax syntax) {
Deque<Syntax> candidates = new ArrayDeque<>();
candidates.add(syntax);
List<Syntax> allParents = new ArrayList<>();
while (!candidates.isEmpty()) {
Syntax candidate = candidates.pop();
if (allParents.stream().noneMatch(pp -> SyntaxUtils.match(pp, candidate))) {
allParents.add(candidate);
List<Syntax> parents = library.parentCategories(candidate);
candidates.addAll(parents);
}
}
return allParents;
}

private List<SpadLibrary.Operation> operations(SpadLibrary library, Collection<Syntax> allParents) {
return allParents.stream().flatMap(syntax -> library.operations(syntax).stream()).collect(Collectors.toList());
}

}
Loading

0 comments on commit bca53cf

Please sign in to comment.