From 9e03fb94d0109a0643cf2a87ca64311e2f78e6e2 Mon Sep 17 00:00:00 2001 From: Johannes Mey <johannes.mey@tu-dresden.de> Date: Mon, 29 Nov 2021 02:03:10 +0100 Subject: [PATCH] work on the structure view. --- .../aspect/AspectStructureViewElement.java | 93 +++++++++++++++++++ .../aspect/AspectStructureViewFactory.java | 27 ++++++ .../aspect/AspectStructureViewModel.java | 48 ++++++++++ .../aspect/JastAddAspectAttributeFilter.java | 44 +++++++++ .../aspect/psi/AspectElementFactory.java | 9 ++ .../aspect/psi/JastAddAspectAttribute.java | 3 +- ...dAspectAspectDeclarationImplExtension.java | 67 +++++++++++++ ...JastAddAspectAstTypeNameImplExtension.java | 18 ++-- ...pectClassOrInterfaceTypeImplExtension.java | 19 ++-- .../impl/JastAddAspectCollAttributeImpl.java | 63 ++++++++++++- .../impl/JastAddAspectInhAttributeImpl.java | 63 ++++++++++++- .../impl/JastAddAspectSynAttributeImpl.java | 64 ++++++++++++- .../impl/GrammarTypeDeclImplExtension.java | 18 ++-- src/main/resources/META-INF/plugin.xml | 3 +- 14 files changed, 509 insertions(+), 30 deletions(-) create mode 100644 src/main/java/org/jastadd/tooling/aspect/AspectStructureViewElement.java create mode 100644 src/main/java/org/jastadd/tooling/aspect/AspectStructureViewFactory.java create mode 100644 src/main/java/org/jastadd/tooling/aspect/AspectStructureViewModel.java create mode 100644 src/main/java/org/jastadd/tooling/aspect/JastAddAspectAttributeFilter.java create mode 100644 src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectAspectDeclarationImplExtension.java diff --git a/src/main/java/org/jastadd/tooling/aspect/AspectStructureViewElement.java b/src/main/java/org/jastadd/tooling/aspect/AspectStructureViewElement.java new file mode 100644 index 0000000..e4e40a1 --- /dev/null +++ b/src/main/java/org/jastadd/tooling/aspect/AspectStructureViewElement.java @@ -0,0 +1,93 @@ +package org.jastadd.tooling.aspect; + +import com.intellij.ide.projectView.PresentationData; +import com.intellij.ide.structureView.StructureViewTreeElement; +import com.intellij.ide.util.treeView.smartTree.SortableTreeElement; +import com.intellij.ide.util.treeView.smartTree.TreeElement; +import com.intellij.navigation.ItemPresentation; +import com.intellij.psi.NavigatablePsiElement; +import com.intellij.psi.util.PsiTreeUtil; +import org.jastadd.tooling.aspect.psi.AspectFile; +import org.jastadd.tooling.aspect.psi.JastAddAspectAspectBodyDeclaration; +import org.jastadd.tooling.aspect.psi.JastAddAspectAspectDeclaration; +import org.jastadd.tooling.aspect.psi.JastAddAspectTypeDeclaration; +import org.jastadd.tooling.aspect.psi.impl.JastAddAspectAspectDeclarationImpl; +import org.jastadd.tooling.aspect.psi.impl.JastAddAspectAspectInhAttributeDeclarationImpl; +import org.jastadd.tooling.aspect.psi.impl.JastAddAspectAspectSynAttributeDeclarationImpl; +import org.jastadd.tooling.aspect.psi.impl.JastAddAspectCollectionAttributeImpl; +import org.jetbrains.annotations.NotNull; + +import java.util.Objects; + +public class AspectStructureViewElement implements StructureViewTreeElement, SortableTreeElement { + + private final NavigatablePsiElement myElement; + + public AspectStructureViewElement(NavigatablePsiElement element) { + this.myElement = element; + } + + @Override + public NavigatablePsiElement getValue() { + return myElement; + } + + @Override + public void navigate(boolean requestFocus) { + myElement.navigate(requestFocus); + } + + @Override + public boolean canNavigate() { + return myElement.canNavigate(); + } + + @Override + public boolean canNavigateToSource() { + return myElement.canNavigateToSource(); + } + + @NotNull + @Override + public String getAlphaSortKey() { + String name = myElement.getName(); + return name != null ? name : ""; + } + + @NotNull + @Override + public ItemPresentation getPresentation() { + ItemPresentation presentation = myElement.getPresentation(); + return presentation != null ? presentation : new PresentationData(); + } + + @Override + public TreeElement @NotNull [] getChildren() { + if (myElement instanceof AspectFile) { + return PsiTreeUtil.getChildrenOfTypeAsList(myElement, JastAddAspectTypeDeclaration.class) + .stream() + .map(JastAddAspectTypeDeclaration::getAspectDeclaration) + .filter(Objects::nonNull) + .map(decl -> new AspectStructureViewElement((JastAddAspectAspectDeclarationImpl) decl)) + .toArray(TreeElement[]::new); + } else if (myElement instanceof JastAddAspectAspectDeclaration) { + return PsiTreeUtil.getChildrenOfTypeAsList(((JastAddAspectAspectDeclaration) myElement).getAspectBody(), JastAddAspectAspectBodyDeclaration.class) + .stream() + .map(decl -> { + if (decl.getAspectSynAttributeDeclaration() != null) { + return new AspectStructureViewElement((JastAddAspectAspectSynAttributeDeclarationImpl) decl.getAspectSynAttributeDeclaration()); + } else if (decl.getAspectInhAttributeDeclaration() != null) { + return new AspectStructureViewElement((JastAddAspectAspectInhAttributeDeclarationImpl) decl.getAspectInhAttributeDeclaration()); + } else if (decl.getCollectionAttribute() != null) { + return new AspectStructureViewElement((JastAddAspectCollectionAttributeImpl) decl.getCollectionAttribute()); + } + return null; + }) + .filter(Objects::nonNull) + .toArray(TreeElement[]::new); + } + + return EMPTY_ARRAY; + } + +} diff --git a/src/main/java/org/jastadd/tooling/aspect/AspectStructureViewFactory.java b/src/main/java/org/jastadd/tooling/aspect/AspectStructureViewFactory.java new file mode 100644 index 0000000..c16c033 --- /dev/null +++ b/src/main/java/org/jastadd/tooling/aspect/AspectStructureViewFactory.java @@ -0,0 +1,27 @@ +package org.jastadd.tooling.aspect; + + +import com.intellij.ide.structureView.StructureViewBuilder; +import com.intellij.ide.structureView.StructureViewModel; +import com.intellij.ide.structureView.TreeBasedStructureViewBuilder; +import com.intellij.lang.PsiStructureViewFactory; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class AspectStructureViewFactory implements PsiStructureViewFactory { + + @Nullable + @Override + public StructureViewBuilder getStructureViewBuilder(@NotNull final PsiFile psiFile) { + return new TreeBasedStructureViewBuilder() { + @NotNull + @Override + public StructureViewModel createStructureViewModel(@Nullable Editor editor) { + return new AspectStructureViewModel(psiFile); + } + }; + } + +} diff --git a/src/main/java/org/jastadd/tooling/aspect/AspectStructureViewModel.java b/src/main/java/org/jastadd/tooling/aspect/AspectStructureViewModel.java new file mode 100644 index 0000000..d2af7e5 --- /dev/null +++ b/src/main/java/org/jastadd/tooling/aspect/AspectStructureViewModel.java @@ -0,0 +1,48 @@ +package org.jastadd.tooling.aspect; + + +import com.intellij.ide.structureView.StructureViewModel; +import com.intellij.ide.structureView.StructureViewModelBase; +import com.intellij.ide.structureView.StructureViewTreeElement; +import com.intellij.ide.util.treeView.smartTree.Filter; +import com.intellij.ide.util.treeView.smartTree.Grouper; +import com.intellij.ide.util.treeView.smartTree.Sorter; +import com.intellij.psi.PsiFile; +import org.jastadd.tooling.aspect.psi.JastAddAspectAspectDeclaration; +import org.jastadd.tooling.aspect.psi.JastAddAspectAttribute; +import org.jetbrains.annotations.NotNull; + +public class AspectStructureViewModel extends StructureViewModelBase implements + StructureViewModel.ElementInfoProvider { + + public AspectStructureViewModel(PsiFile psiFile) { + super(psiFile, new AspectStructureViewElement(psiFile)); + } + + @NotNull + public Sorter @NotNull [] getSorters() { + return new Sorter[]{Sorter.ALPHA_SORTER}; + } + + + @Override + public boolean isAlwaysShowsPlus(StructureViewTreeElement element) { + return element.getValue() instanceof JastAddAspectAspectDeclaration; + } + + @Override + public boolean isAlwaysLeaf(StructureViewTreeElement element) { + return element.getValue() instanceof JastAddAspectAttribute; + } + + @Override + public Grouper @NotNull [] getGroupers() { + // TODO group by member type + return new Grouper[]{}; + } + + @Override + public Filter @NotNull [] getFilters() { + return new Filter[]{new JastAddAspectAttributeFilter()}; + } +} diff --git a/src/main/java/org/jastadd/tooling/aspect/JastAddAspectAttributeFilter.java b/src/main/java/org/jastadd/tooling/aspect/JastAddAspectAttributeFilter.java new file mode 100644 index 0000000..974798a --- /dev/null +++ b/src/main/java/org/jastadd/tooling/aspect/JastAddAspectAttributeFilter.java @@ -0,0 +1,44 @@ +package org.jastadd.tooling.aspect; + +import com.intellij.ide.util.treeView.smartTree.ActionPresentation; +import com.intellij.ide.util.treeView.smartTree.ActionPresentationData; +import com.intellij.ide.util.treeView.smartTree.Filter; +import com.intellij.ide.util.treeView.smartTree.TreeElement; +import org.jastadd.tooling.aspect.psi.JastAddAspectAspectDeclaration; +import org.jastadd.tooling.aspect.psi.JastAddAspectAttribute; +import org.jastadd.tooling.util.JastAddIcons; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class JastAddAspectAttributeFilter implements Filter { + @NonNls + public static final String ID = "HIDE_ATTRIBUTE"; + + @Override + public boolean isVisible(TreeElement treeNode) { + if (treeNode instanceof AspectStructureViewElement) { + return !(((AspectStructureViewElement) treeNode).getValue() instanceof JastAddAspectAttribute); + } + else { + return true; + } + } + + @Override + @NotNull + public ActionPresentation getPresentation() { + // TODO use i18n and string bundle like JavaStructureViewBundle + return new ActionPresentationData("Hide Attributes", null, JastAddIcons.ATTRIBUTE); + } + + @Override + @NotNull + public String getName() { + return ID; + } + + @Override + public boolean isReverted() { + return false; + } +} diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/AspectElementFactory.java b/src/main/java/org/jastadd/tooling/aspect/psi/AspectElementFactory.java index 575b08a..1b0685d 100644 --- a/src/main/java/org/jastadd/tooling/aspect/psi/AspectElementFactory.java +++ b/src/main/java/org/jastadd/tooling/aspect/psi/AspectElementFactory.java @@ -34,4 +34,13 @@ public class AspectElementFactory { return (AspectFile) PsiFileFactory.getInstance(project). createFileFromText(name, AspectFileType.INSTANCE, text); } + + public static JastAddAspectAspectDeclaration createAspectDeclaration(Project project, String name) { + final AspectFile file = createFile(project, "aspect " + name + "{}"); + PsiElement result = file.getFirstChild().findElementAt(20); + if (result != null) { + return (JastAddAspectAspectDeclaration) result.getParent().getParent(); + } + return null; + } } diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/JastAddAspectAttribute.java b/src/main/java/org/jastadd/tooling/aspect/psi/JastAddAspectAttribute.java index 3641ed2..e3e4c7b 100644 --- a/src/main/java/org/jastadd/tooling/aspect/psi/JastAddAspectAttribute.java +++ b/src/main/java/org/jastadd/tooling/aspect/psi/JastAddAspectAttribute.java @@ -1,6 +1,7 @@ package org.jastadd.tooling.aspect.psi; import com.intellij.psi.PsiElement; +import org.jastadd.tooling.grammar.psi.GrammarNamedElement; -public interface JastAddAspectAttribute extends PsiElement { +public interface JastAddAspectAttribute extends PsiElement, GrammarNamedElement { } diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectAspectDeclarationImplExtension.java b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectAspectDeclarationImplExtension.java new file mode 100644 index 0000000..a077cbc --- /dev/null +++ b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectAspectDeclarationImplExtension.java @@ -0,0 +1,67 @@ +package org.jastadd.tooling.aspect.psi.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.navigation.ItemPresentation; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.psi.PsiElement; +import org.jastadd.tooling.aspect.psi.AspectElementFactory; +import org.jastadd.tooling.aspect.psi.JastAddAspectAspectDeclaration; +import org.jastadd.tooling.aspect.psi.JastAddAspectAspectName; +import org.jastadd.tooling.grammar.psi.GrammarNamedElement; +import org.jastadd.tooling.grammar.psi.impl.GrammarNamedElementImpl; +import org.jastadd.tooling.util.JastAddIcons; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +public class JastAddAspectAspectDeclarationImplExtension extends GrammarNamedElementImpl implements GrammarNamedElement { + + public JastAddAspectAspectDeclarationImplExtension(@NotNull ASTNode node) { + super(node); + } + + public String getName() { + return getNameIdentifier().getText(); + } + + public PsiElement setName(@NotNull String newName) { + ASTNode identifierNode = getNameIdentifier().getNode().getFirstChildNode(); + if (identifierNode != null) { + JastAddAspectAspectDeclaration name = AspectElementFactory.createAspectDeclaration(getProject(), newName); + assert name != null; // we know the name is not null because we always create the same one + ASTNode newNameIdentifierNode = name.getAspectName().getNode().getFirstChildNode(); + getNameIdentifier().getNode().replaceChild(identifierNode, newNameIdentifierNode); + } + return this; + } + + @Override + @NotNull + public JastAddAspectAspectName getNameIdentifier() { + return ((JastAddAspectAspectDeclaration) getNode().getPsi()).getAspectName(); + } + + @Override + public ItemPresentation getPresentation() { + return new ItemPresentation() { + @Nullable + @Override + public String getPresentableText() { + return "aspect " + getName(); + } + + @Override + public String getLocationString() { + Document document = FileDocumentManager.getInstance().getDocument(getNode().getPsi().getContainingFile().getVirtualFile()); + return document != null ? "l." + document.getLineNumber(getTextRange().getStartOffset() + 1) : ""; + } + + @Override + public Icon getIcon(boolean unused) { + return JastAddIcons.FILE; + } + }; + } +} diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectAstTypeNameImplExtension.java b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectAstTypeNameImplExtension.java index c83758e..50be78d 100644 --- a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectAstTypeNameImplExtension.java +++ b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectAstTypeNameImplExtension.java @@ -3,6 +3,7 @@ package org.jastadd.tooling.aspect.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import org.jastadd.tooling.aspect.psi.AspectElementFactory; +import org.jastadd.tooling.aspect.psi.AspectTypes; import org.jastadd.tooling.aspect.psi.JastAddAspectAstTypeName; import org.jastadd.tooling.grammar.psi.GrammarNamedElement; import org.jastadd.tooling.grammar.psi.impl.GrammarNamedElementImpl; @@ -15,18 +16,21 @@ public class JastAddAspectAstTypeNameImplExtension extends GrammarNamedElementIm } public String getName() { - // this finds the *first* ID, which is what we want - return getNode().getText(); + ASTNode nameNode = getNode().findChildByType(AspectTypes.AST_TYPE_NAME); + if (nameNode != null) { + return nameNode.getText(); + } else { + return null; + } } public PsiElement setName(@NotNull String newName) { - // FIXME this can break the grammar when the type is used in an unnamed component (and in many other cases probably) - ASTNode keyNode = getNode().getFirstChildNode(); - if (keyNode != null) { + ASTNode nameNode = getNode().findChildByType(AspectTypes.AST_TYPE_NAME); + if (nameNode != null) { JastAddAspectAstTypeName name = AspectElementFactory.createAstTypeName(getProject(), newName); assert name != null; // we know the name is not null because we always create the same one - ASTNode newKeyNode = name.getNode().getFirstChildNode(); - getNode().replaceChild(keyNode, newKeyNode); + ASTNode newNameNode = name.getNode().getFirstChildNode(); + getNode().replaceChild(nameNode, newNameNode); } return this; } diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectClassOrInterfaceTypeImplExtension.java b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectClassOrInterfaceTypeImplExtension.java index ca1542e..c483eff 100644 --- a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectClassOrInterfaceTypeImplExtension.java +++ b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectClassOrInterfaceTypeImplExtension.java @@ -3,6 +3,7 @@ package org.jastadd.tooling.aspect.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import org.jastadd.tooling.aspect.psi.AspectElementFactory; +import org.jastadd.tooling.aspect.psi.AspectTypes; import org.jastadd.tooling.aspect.psi.JastAddAspectClassOrInterfaceType; import org.jastadd.tooling.grammar.psi.GrammarNamedElement; import org.jastadd.tooling.grammar.psi.impl.GrammarNamedElementImpl; @@ -16,22 +17,28 @@ public class JastAddAspectClassOrInterfaceTypeImplExtension extends GrammarNamed public String getName() { // this finds the *first* ID, which is what we want - return getNode().getText(); + ASTNode nameNode = getNode().findChildByType(AspectTypes.JAVA_IDENTIFIER); + if (nameNode != null) { + return nameNode.getText(); + } else { + return null; + } } public PsiElement setName(@NotNull String newName) { - // FIXME this can break the grammar when the type is used in an unnamed component (and in many other cases probably) - ASTNode keyNode = getNode().getFirstChildNode(); - if (keyNode != null) { + ASTNode nameNode = getNode().findChildByType(AspectTypes.JAVA_IDENTIFIER); + if (nameNode != null) { JastAddAspectClassOrInterfaceType name = AspectElementFactory.createClassOrInterfaceType(getProject(), newName); assert name != null; // we know the name is not null because we always create the same one - ASTNode newKeyNode = name.getNode().getFirstChildNode(); - getNode().replaceChild(keyNode, newKeyNode); + assert !name.getJavaIdentifierList().isEmpty(); // we know there is always one name - the class name + ASTNode newKeyNode = name.getJavaIdentifierList().get(0).getNode().getFirstChildNode(); + getNode().replaceChild(nameNode, newKeyNode); } return this; } public PsiElement getNameIdentifier() { + // the entire thing is the identifier return getNode().getPsi(); } diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectCollAttributeImpl.java b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectCollAttributeImpl.java index 0381a57..931466e 100644 --- a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectCollAttributeImpl.java +++ b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectCollAttributeImpl.java @@ -1,12 +1,71 @@ package org.jastadd.tooling.aspect.psi.impl; -import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; +import com.intellij.navigation.ItemPresentation; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.util.NlsSafe; +import com.intellij.psi.PsiElement; +import com.intellij.util.IncorrectOperationException; +import org.jastadd.tooling.aspect.psi.AspectTypes; import org.jastadd.tooling.aspect.psi.JastAddAspectAttribute; +import org.jastadd.tooling.aspect.psi.JastAddAspectCollectionAttribute; +import org.jastadd.tooling.grammar.psi.impl.GrammarNamedElementImpl; +import org.jastadd.tooling.util.JastAddIcons; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -public abstract class JastAddAspectCollAttributeImpl extends ASTWrapperPsiElement implements JastAddAspectAttribute { +import javax.swing.*; + +public abstract class JastAddAspectCollAttributeImpl extends GrammarNamedElementImpl implements JastAddAspectAttribute { public JastAddAspectCollAttributeImpl(@NotNull ASTNode node) { super(node); } + + public String getName() { + // this finds the *first* ID, which is what we want + ASTNode nameNode = getNode().findChildByType(AspectTypes.ATTRIBUTE_NAME); + if (nameNode != null) { + return nameNode.getText(); + } else { + return null; + } + } + + @Override + public @Nullable PsiElement getNameIdentifier() { + return ((JastAddAspectCollectionAttribute) this).getAttributeName(); + } + + @Override + public PsiElement setName(@NlsSafe @NotNull String name) throws IncorrectOperationException { + throw new IncorrectOperationException("Renaming collection attributes is not supported."); + } + + @Override + public @Nullable PsiElement getIdentifyingElement() { + return this; + } + + @Override + public ItemPresentation getPresentation() { + return new ItemPresentation() { + @Nullable + @Override + public String getPresentableText() { + return "coll " + getName(); + } + + @Override + public String getLocationString() { + Document document = FileDocumentManager.getInstance().getDocument(getNode().getPsi().getContainingFile().getVirtualFile()); + return document != null ? "l." + document.getLineNumber(getTextRange().getStartOffset() + 1) : ""; + } + + @Override + public Icon getIcon(boolean unused) { + return JastAddIcons.COL_ATTRIBUTE; + } + }; + } } diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectInhAttributeImpl.java b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectInhAttributeImpl.java index 6bd54d1..5b2692b 100644 --- a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectInhAttributeImpl.java +++ b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectInhAttributeImpl.java @@ -1,12 +1,71 @@ package org.jastadd.tooling.aspect.psi.impl; -import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; +import com.intellij.navigation.ItemPresentation; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.util.NlsSafe; +import com.intellij.psi.PsiElement; +import com.intellij.util.IncorrectOperationException; +import org.jastadd.tooling.aspect.psi.AspectTypes; +import org.jastadd.tooling.aspect.psi.JastAddAspectAspectInhAttributeDeclaration; import org.jastadd.tooling.aspect.psi.JastAddAspectAttribute; +import org.jastadd.tooling.grammar.psi.impl.GrammarNamedElementImpl; +import org.jastadd.tooling.util.JastAddIcons; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -public abstract class JastAddAspectInhAttributeImpl extends ASTWrapperPsiElement implements JastAddAspectAttribute { +import javax.swing.*; + +public abstract class JastAddAspectInhAttributeImpl extends GrammarNamedElementImpl implements JastAddAspectAttribute { public JastAddAspectInhAttributeImpl(@NotNull ASTNode node) { super(node); } + + public String getName() { + // this finds the *first* ID, which is what we want + ASTNode nameNode = getNode().findChildByType(AspectTypes.ATTRIBUTE_NAME); + if (nameNode != null) { + return nameNode.getText(); + } else { + return null; + } + } + + @Override + public @Nullable PsiElement getNameIdentifier() { + return ((JastAddAspectAspectInhAttributeDeclaration) this).getAttributeName(); + } + + @Override + public PsiElement setName(@NlsSafe @NotNull String name) throws IncorrectOperationException { + throw new IncorrectOperationException("Renaming collection attributes is not supported."); + } + + @Override + public @Nullable PsiElement getIdentifyingElement() { + return this; + } + + @Override + public ItemPresentation getPresentation() { + return new ItemPresentation() { + @Nullable + @Override + public String getPresentableText() { + return "inh " + getName(); + } + + @Override + public String getLocationString() { + Document document = FileDocumentManager.getInstance().getDocument(getNode().getPsi().getContainingFile().getVirtualFile()); + return document != null ? "l." + document.getLineNumber(getTextRange().getStartOffset() + 1) : ""; + } + + @Override + public Icon getIcon(boolean unused) { + return JastAddIcons.INH_ATTRIBUTE; + } + }; + } } diff --git a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectSynAttributeImpl.java b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectSynAttributeImpl.java index 1b9443a..358e467 100644 --- a/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectSynAttributeImpl.java +++ b/src/main/java/org/jastadd/tooling/aspect/psi/impl/JastAddAspectSynAttributeImpl.java @@ -1,12 +1,72 @@ package org.jastadd.tooling.aspect.psi.impl; -import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; +import com.intellij.navigation.ItemPresentation; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.fileEditor.FileDocumentManager; +import com.intellij.openapi.util.NlsSafe; +import com.intellij.psi.PsiElement; +import com.intellij.util.IncorrectOperationException; +import org.jastadd.tooling.aspect.psi.AspectTypes; +import org.jastadd.tooling.aspect.psi.JastAddAspectAspectSynAttributeDeclaration; import org.jastadd.tooling.aspect.psi.JastAddAspectAttribute; +import org.jastadd.tooling.grammar.psi.impl.GrammarNamedElementImpl; +import org.jastadd.tooling.util.JastAddIcons; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -public abstract class JastAddAspectSynAttributeImpl extends ASTWrapperPsiElement implements JastAddAspectAttribute { +import javax.swing.*; + +public abstract class JastAddAspectSynAttributeImpl extends GrammarNamedElementImpl implements JastAddAspectAttribute { public JastAddAspectSynAttributeImpl(@NotNull ASTNode node) { super(node); } + + + public String getName() { + // this finds the *first* ID, which is what we want + ASTNode nameNode = getNode().findChildByType(AspectTypes.ATTRIBUTE_NAME); + if (nameNode != null) { + return nameNode.getText(); + } else { + return null; + } + } + + @Override + public @Nullable PsiElement getNameIdentifier() { + return ((JastAddAspectAspectSynAttributeDeclaration) this).getAttributeName(); + } + + @Override + public PsiElement setName(@NlsSafe @NotNull String name) throws IncorrectOperationException { + throw new IncorrectOperationException("Renaming collection attributes is not supported."); + } + + @Override + public @Nullable PsiElement getIdentifyingElement() { + return this; + } + + @Override + public ItemPresentation getPresentation() { + return new ItemPresentation() { + @Nullable + @Override + public String getPresentableText() { + return "syn " + getName(); + } + + @Override + public String getLocationString() { + Document document = FileDocumentManager.getInstance().getDocument(getNode().getPsi().getContainingFile().getVirtualFile()); + return document != null ? "l." + document.getLineNumber(getTextRange().getStartOffset() + 1) : ""; + } + + @Override + public Icon getIcon(boolean unused) { + return JastAddIcons.SYN_ATTRIBUTE; + } + }; + } } diff --git a/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java index 39bd24d..7be798b 100644 --- a/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java +++ b/src/main/java/org/jastadd/tooling/grammar/psi/impl/GrammarTypeDeclImplExtension.java @@ -16,28 +16,28 @@ public class GrammarTypeDeclImplExtension extends GrammarNamedElementImpl implem public String getName() { // this finds the *first* ID, which is what we want - ASTNode keyNode = getNode().findChildByType(GrammarTypes.TYPE_NAME); - if (keyNode != null) { - return keyNode.getText(); + ASTNode nameNode = getNode().findChildByType(GrammarTypes.TYPE_NAME); + if (nameNode != null) { + return nameNode.getText(); } else { return null; } } public PsiElement setName(@NotNull String newName) { - ASTNode keyNode = getNode().findChildByType(GrammarTypes.TYPE_NAME); - if (keyNode != null) { + ASTNode nameNode = getNode().findChildByType(GrammarTypes.TYPE_NAME); + if (nameNode != null) { GrammarTypeName name = GrammarElementFactory.createTypeName(getProject(), newName); ASTNode newKeyNode = name.getNode(); - getNode().replaceChild(keyNode, newKeyNode); + getNode().replaceChild(nameNode, newKeyNode); } return this; } public PsiElement getNameIdentifier() { - ASTNode keyNode = getNode().findChildByType(GrammarTypes.TYPE_NAME); - if (keyNode != null) { - return keyNode.getPsi(); + ASTNode nameNode = getNode().findChildByType(GrammarTypes.TYPE_NAME); + if (nameNode != null) { + return nameNode.getPsi(); } else { return null; } diff --git a/src/main/resources/META-INF/plugin.xml b/src/main/resources/META-INF/plugin.xml index a416248..d84dd36 100644 --- a/src/main/resources/META-INF/plugin.xml +++ b/src/main/resources/META-INF/plugin.xml @@ -91,7 +91,8 @@ <lang.formatter language="JastAddAspect" implementationClass="org.jastadd.tooling.aspect.AspectFormattingModelBuilder"/> <lang.foldingBuilder language="JastAddAspect" implementationClass="org.jastadd.tooling.aspect.AspectFoldingBuilder"/> - FoldingBuilder"/> + + <lang.psiStructureViewFactory language="JastAddAspect" implementationClass="org.jastadd.tooling.aspect.AspectStructureViewFactory"/> </extensions> <actions> -- GitLab