Skip to content

Commit

Permalink
Intention "Add braces to blockless function" is now working with Reac…
Browse files Browse the repository at this point in the history
…t record fields (like render)
  • Loading branch information
giraud committed Sep 21, 2018
1 parent 26ad8cf commit f7c090d
Show file tree
Hide file tree
Showing 11 changed files with 77 additions and 38 deletions.
2 changes: 1 addition & 1 deletion src/main/java/com/reason/lang/ParserScopeEnum.java
Original file line number Diff line number Diff line change
Expand Up @@ -102,5 +102,5 @@ public enum ParserScopeEnum {
executable,
maybeLetFunction,
maybeLetFunctionParameters,
valNamedSymbol, struct, matchException, beginScope, ifElseStatement, bracketGt, moduleDeclaration, moduleInstanciation, tryWith, moduleNamedColonWith, moduleNamedWithType, doLoop, tryWithScope, letBinding, scope, moduleNamedSignatureEq, array, signature, objectScope, clazzDeclaration, clazz, clazzNamed, clazzNamedEq, clazzBody, clazzBodyScope, clazzConstructor, clazzField, clazzFieldNamed, clazzMethod, clazzMethodNamed, clazzNamedParameters, clazzNamedConstructor, name
valNamedSymbol, struct, matchException, beginScope, ifElseStatement, bracketGt, moduleDeclaration, moduleInstanciation, tryWith, moduleNamedColonWith, moduleNamedWithType, doLoop, tryWithScope, letBinding, scope, moduleNamedSignatureEq, array, signature, objectScope, clazzDeclaration, clazz, clazzNamed, clazzNamedEq, clazzBody, clazzBodyScope, clazzConstructor, clazzField, clazzFieldNamed, clazzMethod, clazzMethodNamed, clazzNamedParameters, clazzNamedConstructor, record, mixin, name
}
2 changes: 2 additions & 0 deletions src/main/java/com/reason/lang/PsiElementFactory.java
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ public static PsiElement createElement(MlTypes types, ASTNode node) {
return new PsiPatternMatch(node);
} else if (type == types.RECORD_EXPR) {
return new PsiRecord(node);
} else if (type == types.MIXIN_FIELD) {
return new PsiMixinField(node);
} else if (type == types.RECORD_FIELD) {
return new PsiRecordField(node);
} else if (type == types.INTERPOLATION_EXPR) {
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/com/reason/lang/core/psi/PsiMixinField.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.reason.lang.core.psi;

import com.intellij.extapi.psi.ASTWrapperPsiElement;
import com.intellij.lang.ASTNode;

public class PsiMixinField extends ASTWrapperPsiElement {

public PsiMixinField(ASTNode node) {
super(node);
}

@Override
public boolean canNavigate() {
return false;
}
}
4 changes: 1 addition & 3 deletions src/main/java/com/reason/lang/core/psi/type/MlTypes.java
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
package com.reason.lang.core.psi.type;

import com.intellij.lang.Language;
import com.intellij.psi.tree.IElementType;
import org.jetbrains.annotations.NotNull;

public abstract class MlTypes {

// Composite element types

public IElementType EXTERNAL_STMT;
Expand Down Expand Up @@ -92,6 +89,7 @@ public abstract class MlTypes {
public MlTokenElementType INITIALIZER;
public MlTokenElementType LAZY;
public MlTokenElementType LET;
public MlTokenElementType MIXIN_FIELD;
public MlTokenElementType MODULE;
public MlTokenElementType MUTABLE;
public MlTokenElementType NEW;
Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/reason/lang/ocaml/OclTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ private OclTypes() {
MATCH = new MlTokenElementType("MATCH", OclLanguage.INSTANCE);
MINUS = new MlTokenElementType("MINUS", OclLanguage.INSTANCE);
MINUSDOT = new MlTokenElementType("MINUSDOT", OclLanguage.INSTANCE);
MIXIN_FIELD = new MlTokenElementType("MIXIN_FIELD", OclLanguage.INSTANCE);
MODULE = new MlTokenElementType("MODULE", OclLanguage.INSTANCE);
MUTABLE = new MlTokenElementType("MUTABLE", OclLanguage.INSTANCE);
NONE = new MlTokenElementType("NONE", OclLanguage.INSTANCE);
Expand Down
30 changes: 21 additions & 9 deletions src/main/java/com/reason/lang/reason/RmlParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@ else if (tokenType == m_types.SEMI) {
parseAssert(builder, state);
} else if (tokenType == m_types.IF) {
parseIf(builder, state);
} else if (tokenType == m_types.DOTDOTDOT) {
parseDotDotDot(builder, state);
}
// ( ... )
else if (tokenType == m_types.LPAREN) {
Expand Down Expand Up @@ -174,6 +176,16 @@ private void parseIf(PsiBuilder builder, ParserState state) {
state.add(markComplete(builder, ifThenStatement, m_types.IF_STMT));
}

private void parseDotDotDot(PsiBuilder builder, ParserState state) {
if (state.previousTokenElementType == m_types.LBRACE) {
// Mixin: ... LBRACE <DOTDOTDOT> LIDENT ...
state.updateCurrentResolution(recordBinding);
state.updateCurrentContext(record);
state.updateCurrentCompositeElementType(m_types.RECORD_EXPR);
state.add(mark(builder, recordBinding, mixin, m_types.MIXIN_FIELD));
}
}

private void parseAssert(PsiBuilder builder, ParserState state) {
state.add(markComplete(builder, assert_, m_types.ASSERT_STMT));
state.dontMove = advance(builder);
Expand Down Expand Up @@ -210,6 +222,8 @@ private void parseComma(ParserState state) {
state.complete();
state.endUntilContext(recordField);
state.popEnd();
} else if (state.isCurrentResolution(mixin)) {
state.popEnd();
}
}

Expand Down Expand Up @@ -504,6 +518,8 @@ private void parseLIdent(PsiBuilder builder, ParserState state) {
});
} else if (state.isCurrentResolution(recordBinding)) {
state.add(mark(builder, recordField, m_types.RECORD_FIELD));
} else if (state.isCurrentResolution(mixin)) {
state.complete();
} else if (shouldStartExpression(state)) {
state.add(mark(builder, genericExpression, builder.getTokenType()));
} else {
Expand Down Expand Up @@ -562,16 +578,12 @@ private void parseLBrace(PsiBuilder builder, ParserState state) {
state.add(markScope(builder, scope, brace, m_types.SCOPED_EXPR, m_types.LBRACE));
} else if (state.isCurrentResolution(clazzNamedEq)) {
state.add(markScope(builder, clazzBodyScope, m_types.SCOPED_EXPR, m_types.LBRACE));
} else if (state.isCurrentResolution(switchBinaryCondition)) {
ParserScope switchScope = state.endUntilContext(switch_);
boolean isSwitch = switchScope != null && switchScope.isResolution(switch_);
state.add(markScope(builder, isSwitch ? switchBody : brace, m_types.SCOPED_EXPR, isSwitch ? m_types.SWITCH : m_types.LBRACE));
} else {
ParserScope switchScope;
if (state.isCurrentResolution(switchBinaryCondition)) {
switchScope = state.endUntilContext(switch_);
boolean isSwitch = switchScope != null && switchScope.isResolution(switch_);
state.add(markScope(builder, isSwitch ? switchBody : brace, m_types.SCOPED_EXPR, isSwitch ? m_types.SWITCH : m_types.LBRACE));
} else {
state.add(markScope(builder, scope, brace, m_types.SCOPED_EXPR, m_types.LBRACE));
}

state.add(markScope(builder, scope, brace, m_types.SCOPED_EXPR, m_types.LBRACE));
}
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/com/reason/lang/reason/RmlTypes.java
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ private RmlTypes() {
MATCH = new MlTokenElementType("MATCH", RmlLanguage.INSTANCE);
MINUS = new MlTokenElementType("MINUS", RmlLanguage.INSTANCE);
MINUSDOT = new MlTokenElementType("MINUSDOT", RmlLanguage.INSTANCE);
MIXIN_FIELD = new MlTokenElementType("MIXIN_FIELD", RmlLanguage.INSTANCE);
MODULE = new MlTokenElementType("MODULE", RmlLanguage.INSTANCE);
MUTABLE = new MlTokenElementType("MUTABLE", RmlLanguage.INSTANCE);
NONE = new MlTokenElementType("NONE", RmlLanguage.INSTANCE);
Expand Down
3 changes: 0 additions & 3 deletions testData/com/reason/ide/folding/TypeFolding.re

This file was deleted.

20 changes: 0 additions & 20 deletions tests/com/reason/ide/folding/TypeFoldingTest.java

This file was deleted.

15 changes: 13 additions & 2 deletions tests/com/reason/ide/intention/FunctionBracesIntention.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,30 @@
import com.intellij.testFramework.fixtures.LightPlatformCodeInsightFixtureTestCase;
import com.reason.ide.files.RmlFileType;

@SuppressWarnings("ConstantConditions")
public class FunctionBracesIntention extends LightPlatformCodeInsightFixtureTestCase {
public void testBasic() {
myFixture.configureByText(RmlFileType.INSTANCE, "let add = (x, y) => <caret>x + y;");
IntentionAction bracesAction = (IntentionAction) myFixture.getAvailableIntention("Add braces to blockless function");
IntentionAction bracesAction = myFixture.getAvailableIntention("Add braces to blockless function");
myFixture.launchAction(bracesAction);

myFixture.checkResult("let add = (x, y) => { x + y; };");
}

// https://github.com/reasonml-editor/reasonml-idea-plugin/issues/67
public void testInnerFunction() {
myFixture.configureByText(RmlFileType.INSTANCE, "Js.Promise.( Api.all() |> then_(result => <caret>Js.log(result)) );");
IntentionAction bracesAction = (IntentionAction) myFixture.getAvailableIntention("Add braces to blockless function");
IntentionAction bracesAction = myFixture.getAvailableIntention("Add braces to blockless function");
myFixture.launchAction(bracesAction);

myFixture.checkResult("Js.Promise.( Api.all() |> then_(result => { Js.log(result); }) );");
}

public void testReactComponentFunction() {
myFixture.configureByText(RmlFileType.INSTANCE, "let make = (children) => { ...component, render: self => <di<caret>v/>, };");
IntentionAction bracesAction = myFixture.getAvailableIntention("Add braces to blockless function");
myFixture.launchAction(bracesAction);

myFixture.checkResult("let make = (children) => { ...component, render: self => { <div/>; }, };");
}
}
21 changes: 21 additions & 0 deletions tests/com/reason/lang/reason/RecordParsingTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.reason.lang.reason;

import com.reason.lang.BaseParsingTestCase;
import com.reason.lang.core.psi.PsiLet;
import com.reason.lang.core.psi.PsiRecord;
import com.reason.lang.core.psi.PsiRecordField;

public class RecordParsingTest extends BaseParsingTestCase {
public RecordParsingTest() {
super("", "re", new RmlParserDefinition());
}

public void testMixin() {
PsiLet let = first(letExpressions(parseCode("let x = {...component, otherField: 1};", true)));

PsiRecord record = (PsiRecord) let.getBinding().getFirstChild();
PsiRecordField field = record.getFields().iterator().next();
assertEquals(field.getName(), "otherField");
}

}

0 comments on commit f7c090d

Please sign in to comment.