Skip to content

Commit a87b40e

Browse files
committed
Frontend/Typing assists: handle enter inside single line brackets
1 parent 23d0d07 commit a87b40e

File tree

9 files changed

+108
-9
lines changed

9 files changed

+108
-9
lines changed

ReSharper.FSharp/test/data/features/service/typingAssist/Enter - Parens - Begin 01.fs.gold

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ${CHAR:Enter}
1+
// ${CHAR:Enter}
22
module Module
33

44
let _ =

ReSharper.FSharp/test/data/features/service/typingAssist/Enter - Parens - Begin 02.fs.gold

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ${CHAR:Enter}
1+
// ${CHAR:Enter}
22
module Module
33

44
let _ =

ReSharper.FSharp/test/data/features/service/typingAssist/Enter - Parens - Type 01.fs.gold

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ${CHAR:Enter}
1+
// ${CHAR:Enter}
22
module Module
33

44
type T() =

ReSharper.FSharp/test/data/features/service/typingAssist/Enter - Parens - Type 02.fs.gold

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ${CHAR:Enter}
1+
// ${CHAR:Enter}
22
module Module
33

44
type T() =

ReSharper.FSharp/test/data/features/service/typingAssist/Enter - Parens - Type 03.fs.gold

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ${CHAR:Enter}
1+
// ${CHAR:Enter}
22
module Module
33

44
type T() =

ReSharper.FSharp/test/data/features/service/typingAssist/Enter - Parens - Type 04.fs.gold

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// ${CHAR:Enter}
1+
// ${CHAR:Enter}
22
module Module
33

44
type T() =

rider-fsharp/src/main/java/com/jetbrains/rider/plugins/fsharp/editorActions/FSharpEnterHandlerDelegate.kt

Lines changed: 81 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,13 @@ class FSharpEnterHandlerDelegate : EnterHandlerDelegateAdapter() {
9292
FSharpTokenType.END
9393
)
9494

95+
private val bracketsAllowingDeindent: TokenSet = TokenSet.create(
96+
FSharpTokenType.LBRACE,
97+
FSharpTokenType.LBRACK,
98+
FSharpTokenType.LBRACK_BAR,
99+
FSharpTokenType.LPAREN
100+
)
101+
95102
private val emptyBracketsToAddSpace = setOf(
96103
Pair(FSharpTokenType.LBRACE, FSharpTokenType.RBRACE),
97104
Pair(FSharpTokenType.LBRACK, FSharpTokenType.RBRACK),
@@ -108,7 +115,13 @@ class FSharpEnterHandlerDelegate : EnterHandlerDelegateAdapter() {
108115
FSharpTokenType.LBRACK_BAR,
109116
FSharpTokenType.LBRACK_LESS,
110117
FSharpTokenType.LQUOTE_TYPED,
111-
FSharpTokenType.LQUOTE_UNTYPED
118+
FSharpTokenType.LQUOTE_UNTYPED,
119+
120+
FSharpTokenType.CLASS,
121+
FSharpTokenType.INTERFACE,
122+
FSharpTokenType.STRUCT,
123+
124+
FSharpTokenType.BEGIN
112125
)
113126

114127
private val rightBracketsToAddSpace = emptyBracketsToAddSpace.map { it.second }.toSet()
@@ -621,6 +634,8 @@ class FSharpEnterHandlerDelegate : EnterHandlerDelegateAdapter() {
621634
val document = editor.document
622635
val line = document.getLineNumber(tokenStart)
623636

637+
if (handleEnterInsideSingleLineBrackets(editor, iterator, line)) return true
638+
624639
if (leftBracketsToAddIndent.contains(tokenType) &&
625640
!isSingleLineBrackets(editor, tokenStart) &&
626641
!isLastTokenOnLine(editor, tokenStart) &&
@@ -705,6 +720,71 @@ class FSharpEnterHandlerDelegate : EnterHandlerDelegateAdapter() {
705720
return true
706721
}
707722

723+
fun handleEnterInsideSingleLineBrackets(editor: Editor, iterator: HighlighterIterator, line: Int): Boolean {
724+
val document = editor.document
725+
val iterator = editor.highlighter.createIterator(iterator.start)
726+
727+
val tokenType = iterator.tokenType
728+
val leftBracketStartOffset = iterator.start
729+
val leftBracketEndOffset = iterator.end
730+
val leftBracketLine = document.getLineNumber(leftBracketStartOffset)
731+
732+
if (!findRightBracket(iterator)) return false
733+
if (document.getLineNumber(iterator.start) != leftBracketLine) return false
734+
735+
val rightBracketStartOffset = iterator.start
736+
737+
iterator.retreat()
738+
while (iterator.tokenTypeSafe == FSharpTokenType.WHITESPACE)
739+
iterator.retreat()
740+
741+
val lastElementEndOffset = iterator.end
742+
743+
val deindentIter = editor.highlighter.createIterator(leftBracketStartOffset - 1)
744+
while (!deindentIter.atEnd() && isIgnored(iterator.tokenType))
745+
deindentIter.retreat()
746+
747+
val shouldDeindent =
748+
bracketsAllowingDeindent.contains(tokenType) && deindentIter.tokenType != FSharpTokenType.NEW_LINE
749+
750+
val baseIndentLength =
751+
if (!shouldDeindent)
752+
getOffsetInLine(document, line, leftBracketStartOffset)
753+
else {
754+
val line = getContinuedIndentLine(editor, leftBracketStartOffset, true)
755+
getLineWhitespaceIndent(editor, line)
756+
}
757+
758+
val indent = getIndentSettings(editor).indentSize
759+
val baseIndentString = "\n" + " ".repeat(baseIndentLength)
760+
val indentString = baseIndentString + " ".repeat(indent)
761+
762+
if (lastElementEndOffset == leftBracketEndOffset) {
763+
val newText = if (tokenType == FSharpTokenType.LPAREN) {
764+
indentString
765+
} else {
766+
indentString + baseIndentString
767+
}
768+
document.replaceString(lastElementEndOffset, rightBracketStartOffset, newText)
769+
} else {
770+
val firstElementIter = editor.highlighter.createIterator(leftBracketEndOffset)
771+
772+
while (!firstElementIter.atEnd() && isIgnored(firstElementIter.tokenTypeSafe))
773+
firstElementIter.advance()
774+
775+
val firstElementStartOffset = firstElementIter.start
776+
777+
if (tokenType != FSharpTokenType.LPAREN) {
778+
document.replaceString(lastElementEndOffset, rightBracketStartOffset, baseIndentString)
779+
}
780+
document.replaceString(leftBracketEndOffset, firstElementStartOffset, indentString)
781+
}
782+
783+
editor.caretModel.moveToOffset(leftBracketEndOffset + indentString.length)
784+
editor.scrollingModel.scrollToCaret(ScrollType.MAKE_VISIBLE)
785+
return true
786+
}
787+
708788
private fun handleEnter(
709789
editor: Editor,
710790
caretOffset: Int,

rider-fsharp/src/main/java/com/jetbrains/rider/plugins/fsharp/editorActions/FSharpTypingAssistUtils.kt

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,12 @@ class FSharpBracketMatcher : BracketMatcher(
4242
Pair(FSharpTokenType.LBRACE_BAR, FSharpTokenType.BAR_RBRACE),
4343
Pair(FSharpTokenType.LBRACK_LESS, FSharpTokenType.GREATER_RBRACK),
4444
Pair(FSharpTokenType.LQUOTE_TYPED, FSharpTokenType.RQUOTE_TYPED),
45-
Pair(FSharpTokenType.LQUOTE_UNTYPED, FSharpTokenType.RQUOTE_UNTYPED)
45+
Pair(FSharpTokenType.LQUOTE_UNTYPED, FSharpTokenType.RQUOTE_UNTYPED),
46+
47+
Pair(FSharpTokenType.CLASS, FSharpTokenType.END),
48+
Pair(FSharpTokenType.INTERFACE, FSharpTokenType.END),
49+
Pair(FSharpTokenType.STRUCT, FSharpTokenType.END),
50+
51+
Pair(FSharpTokenType.BEGIN, FSharpTokenType.END)
4652
)
4753
)

rider-fsharp/src/test/kotlin/com/jetbrains/rider/plugins/fsharp/test/cases/typingAssist/FSharpPatchEngineTypingAssists.kt

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,12 +185,19 @@ class FSharpEnterTypingAssistSyncTest : FSharpBackendSyncTypingAssistTestBase(Id
185185
"Enter 28 - No indent after else and new line",
186186
"Enter 29 - No indent before source",
187187
"Enter 30 - No indent before source 2",
188+
"Enter 31 - Inside empty ctor",
188189
"Enter 32 - Nested binding",
189190
"Enter 33 - After then on line with multiple parens in row",
190191
"Enter 34 - After line with multiple parens in row",
191192
"Enter 35 - Nested binding and indent",
192193
"Enter 36 - Indent after =, trim before source",
194+
"Enter 38 - Empty list",
195+
"Enter 39 - Empty list with spaces",
196+
"Enter 40 - Empty list continuing line",
197+
"Enter 41 - Empty array continuing line",
193198
"Enter 42 - Before first list element and new line",
199+
"Enter 43 - Before first list element",
200+
"Enter 44 - Before first list element and spaces",
194201
"Enter 45 - Before first list element in multiline list",
195202
"Enter 46 - Before first list element in multiline list",
196203
"Enter 47 - Before first list element in multiline list",
@@ -261,7 +268,13 @@ class FSharpEnterTypingAssistSyncTest : FSharpBackendSyncTypingAssistTestBase(Id
261268
"Enter - String 12",
262269
"Enter - String 13",
263270
"Enter - String 14",
264-
"Enter - String 15"
271+
"Enter - String 15",
272+
"Enter - Parens - Begin 01",
273+
"Enter - Parens - Begin 02",
274+
"Enter - Parens - Type 01",
275+
"Enter - Parens - Type 02",
276+
"Enter - Parens - Type 03",
277+
"Enter - Parens - Type 04"
265278
)
266279

267280
@DataProvider(name = SUPPORTED_BACKEND_CASES)

0 commit comments

Comments
 (0)