Skip to content

Commit

Permalink
#153 - Structure panel for let fn and let (..)
Browse files Browse the repository at this point in the history
  • Loading branch information
giraud committed Mar 25, 2019
1 parent c7eb53c commit 6fe63b2
Showing 8 changed files with 98 additions and 11 deletions.
26 changes: 24 additions & 2 deletions src/com/reason/ide/structure/StructureViewElement.java
Original file line number Diff line number Diff line change
@@ -18,7 +18,9 @@
import com.reason.lang.core.psi.ocamlyacc.OclYaccTrailer;
import com.reason.lang.ocamlyacc.OclYaccTypes;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.util.ArrayList;
import java.util.List;

@@ -70,7 +72,25 @@ public ItemPresentation getPresentation() {
return presentation;
}
}
throw new RuntimeException("Unknown presentation");
return new ItemPresentation() {
@Nullable
@Override
public String getPresentableText() {
return "Unknown presentation for element " + m_element.getText();
}

@Nullable
@Override
public String getLocationString() {
return null;
}

@Nullable
@Override
public Icon getIcon(boolean unused) {
return null;
}
};
}

@NotNull
@@ -182,7 +202,9 @@ static class ElementVisitor extends PsiElementVisitor {
@Override
public void visitElement(PsiElement element) {
if (element instanceof PsiStructuredElement) {
m_treeElements.add(new StructureViewElement(element));
if (((PsiStructuredElement) element).canBeDisplayed()) {
m_treeElements.add(new StructureViewElement(element));
}
}
}
}
2 changes: 1 addition & 1 deletion src/com/reason/lang/PsiElementFactory.java
Original file line number Diff line number Diff line change
@@ -67,7 +67,7 @@ public static PsiElement createElement(ORTypes types, ASTNode node) {
} else if (type == types.C_MACRO_RAW_BODY) {
return new PsiRawBody(types, node);
} else if (type == types.C_SCOPED_EXPR) {
return new PsiScopedExpr(node);
return new PsiScopedExpr(types, node);
} else if (type == types.LOCAL_OPEN) {
return new PsiLocalOpen(node, types);
} else if (type == types.C_PATTERN_MATCH_EXPR) {
21 changes: 20 additions & 1 deletion src/com/reason/lang/core/psi/PsiScopedExpr.java
Original file line number Diff line number Diff line change
@@ -2,12 +2,31 @@

import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import com.intellij.psi.tree.IElementType;
import com.reason.lang.core.type.ORTypes;
import org.jetbrains.annotations.NotNull;

public class PsiScopedExpr extends ASTWrapperPsiElement {

public PsiScopedExpr(@NotNull ASTNode node) {
private final ORTypes m_types;

public PsiScopedExpr(@NotNull ORTypes types, @NotNull ASTNode node) {
super(node);
m_types = types;
}

public boolean isEmpty() {
PsiElement firstChild = getFirstChild();
IElementType firstType = firstChild == null ? null : firstChild.getNode().getElementType();
if (firstType == m_types.LPAREN) {
assert firstChild != null;
PsiElement secondChild = firstChild.getNextSibling();
IElementType secondType = secondChild == null ? null : secondChild.getNode().getElementType();
return secondType == m_types.RPAREN;
}

return false;
}

@Override
3 changes: 3 additions & 0 deletions src/com/reason/lang/core/psi/PsiStructuredElement.java
Original file line number Diff line number Diff line change
@@ -6,4 +6,7 @@
* Indicates that the element can be displayed in the structure view
*/
public interface PsiStructuredElement extends PsiElement {
default boolean canBeDisplayed() {
return true;
}
}
18 changes: 17 additions & 1 deletion src/com/reason/lang/core/psi/impl/PsiLetImpl.java
Original file line number Diff line number Diff line change
@@ -168,16 +168,31 @@ public String getQualifiedName() {
return path + "." + getName();
}

//region PsiStructuredElement
@Override
public boolean canBeDisplayed() {
PsiElement nameIdentifier = getNameIdentifier();
if (nameIdentifier != null) {
return true;
}

PsiScopedExpr scope = ORUtil.findImmediateFirstChildOfClass(this, PsiScopedExpr.class);
return scope != null && !scope.isEmpty();
}

@Nullable
@Override
public ItemPresentation getPresentation() {
final PsiLet let = this;

return new ItemPresentation() {
@NotNull
@Override
public String getPresentableText() {
PsiElement letValueName = getNameIdentifier();
if (letValueName == null) {
return "_";
PsiScopedExpr scope = ORUtil.findImmediateFirstChildOfClass(let, PsiScopedExpr.class);
return scope == null || scope.isEmpty() ? "_" : scope.getText();
}

ORSignature signature = hasInferredType() ? getInferredType() : getORSignature();
@@ -204,6 +219,7 @@ public Icon getIcon(boolean unused) {
}
};
}
//endregion

@Nullable
@Override
8 changes: 4 additions & 4 deletions src/com/reason/lang/ocaml/OclParser.java
Original file line number Diff line number Diff line change
@@ -676,13 +676,13 @@ private void parseLIdent(@NotNull PsiBuilder builder, ParserState state) {
}

private void transitionToLetNamed(PsiBuilder builder, ParserState state) {
state.updateCurrentResolution(letNamed).complete();
IElementType nextTokenType = builder.getTokenType();
if (nextTokenType != m_types.EQ && nextTokenType != m_types.COLON) {
state.updateCurrentResolution(letNamed).complete().
wrapWith(m_types.C_LOWER_SYMBOL);
IElementType tokenType = builder.getTokenType();
if (tokenType != m_types.EQ && tokenType != m_types.COLON) {
state.add(mark(builder, letBinding, letNamedBinding, m_types.C_LET_BINDING).complete())
.add(mark(builder, function, m_types.C_FUN_EXPR).complete())
.add(mark(builder, function, functionParameters, m_types.C_FUN_PARAMS).complete());
// .add(mark(builder, function, functionParameter, m_types.C_FUN_PARAM).complete());
}

}
26 changes: 26 additions & 0 deletions tests/com/reason/lang/core/PsiScopedExprTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.reason.lang.core;

import com.reason.lang.BaseParsingTestCase;
import com.reason.lang.core.psi.PsiLet;
import com.reason.lang.core.psi.PsiScopedExpr;
import com.reason.lang.ocaml.OclParserDefinition;

@SuppressWarnings("ConstantConditions")
public class PsiScopedExprTest extends BaseParsingTestCase {
public PsiScopedExprTest() {
super("", "ml", new OclParserDefinition());
}

public void testEmptyScope() {
PsiLet e = (PsiLet) firstElement(parseCode("let () = x1"));

assertTrue(ORUtil.findImmediateFirstChildOfClass(e, PsiScopedExpr.class).isEmpty());
}

public void testNotEmptyScope() {
PsiLet e = (PsiLet) firstElement(parseCode("let (a, b) = x"));

assertFalse(ORUtil.findImmediateFirstChildOfClass(e, PsiScopedExpr.class).isEmpty());
}

}
5 changes: 3 additions & 2 deletions tests/com/reason/lang/ocaml/LetParsingTest.java
Original file line number Diff line number Diff line change
@@ -47,9 +47,10 @@ public void testScopeWithSome() {
}

public void testScopeWithLIdent() {
PsiLet let = first(letExpressions(parseCode("let l p = Js.log p; returnObj")));
PsiLet e = first(letExpressions(parseCode("let fn p = Js.log p; returnObj")));

assertTrue(let.isFunction());
assertTrue(e.isFunction());
assertEquals("fn", e.getName());
}

public void testRecord() {

0 comments on commit 6fe63b2

Please sign in to comment.