Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
DedSec256 committed Apr 6, 2023
1 parent 1000b12 commit c3c00cd
Show file tree
Hide file tree
Showing 59 changed files with 654 additions and 618 deletions.
11 changes: 11 additions & 0 deletions ReSharper.FSharp/ReSharper.FSharp.sln.DotSettings.user
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/Environment/AssemblyExplorer/XmlDocument/@EntryValue">&lt;AssemblyExplorer&gt;&#xD;
&lt;Assembly Path="C:\Users\berej\.nuget\packages\jetbrains.psi.features.src\231.0.20230211.4307-eap05d\DotFiles\JetBrains.ReSharper.Daemon.dll" /&gt;&#xD;
&lt;/AssemblyExplorer&gt;</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=0be7263c_002Dfde2_002D498d_002Dba85_002D4b5092a44991/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" Name="XmlDoc 02" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;Solution /&gt;&#xD;
&lt;/SessionState&gt;</s:String>
<s:String x:Key="/Default/Environment/UnitTesting/UnitTestSessionStore/Sessions/=137685b7_002D91ce_002D48e8_002Db21f_002Db50efed1d8db/@EntryIndexedValue">&lt;SessionState ContinuousTestingMode="0" IsActive="True" Name="XmlDocSyntaxHighlightingTest" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"&gt;&#xD;
&lt;Solution /&gt;&#xD;
&lt;/SessionState&gt;</s:String>
</wpf:ResourceDictionary>
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using System.Collections.Concurrent;
using System.Linq;
using JetBrains.ReSharper.Plugins.FSharp.Psi.Impl.Tree;
using JetBrains.ReSharper.Plugins.FSharp.Psi.Parsing;
using JetBrains.ReSharper.Plugins.FSharp.Services.Formatter;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,120 +12,123 @@ import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi.tryParse
import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi.whileMakingProgress

class FSharpDummyParser : PsiParser {
override fun parse(root: IElementType, builder: PsiBuilder): ASTNode {
builder.setWhitespaceSkippedCallback { elementType, _, _ ->
if (elementType == FSharpTokenType.NEW_LINE) ++currentLineIndex
}
builder.parseFile(root)
return builder.treeBuilt
override fun parse(root: IElementType, builder: PsiBuilder): ASTNode {
builder.setWhitespaceSkippedCallback { elementType, _, end ->
if (elementType == FSharpTokenType.NEW_LINE) {
++currentLineIndex
currentLineStart = end
}
}

private fun PsiBuilder.parseFile(fileElementType: IElementType) {
parse(fileElementType) {
whileMakingProgress {
if (!parseDummyExpression()) advanceLexerWithNewLineCounting()
true
}
}
builder.parseFile(root)
return builder.treeBuilt
}

private fun PsiBuilder.parseFile(fileElementType: IElementType) {
parse(fileElementType) {
whileMakingProgress {
if (!parseDummyExpression()) advanceLexerWithNewLineCounting()
true
}
}
}

private fun PsiBuilder.getCurrentIndentation() =
currentOffset - currentLineIndent
private fun PsiBuilder.getCurrentIndentation() =
currentOffset - currentLineStart

private fun PsiBuilder.parseDummyExpression() = parseConcatenation()
private fun PsiBuilder.parseDummyExpression() = parseConcatenation()

private fun PsiBuilder.parseConcatenation() =
tryParse(FSharpElementTypes.DUMMY_EXPRESSION) {
val currentIndent = getCurrentIndentation()
private fun PsiBuilder.parseConcatenation() =
tryParse(FSharpElementTypes.DUMMY_EXPRESSION) {
val currentIndent = getCurrentIndentation()

if (!parseStringExpression()) false
else if (!scanOrRollback { tryParseConcatenationPartAhead(currentIndent) }) false
else {
whileMakingProgress {
scanOrRollback { tryParseConcatenationPartAhead(currentIndent) }
}
true
}
if (!parseStringExpression()) false
else if (tryParseConcatenationPartAhead(currentIndent)) false
else {
whileMakingProgress {
scanOrRollback { tryParseConcatenationPartAhead(currentIndent) }
}

private fun PsiBuilder.tryParseConcatenationPartAhead(requiredStringIndent: Int): Boolean {
val oldLineIndex = currentLineIndex
val hasSpaceBeforePlus = eatFilteredTokens()
val movedToNewLine = currentLineIndex != oldLineIndex

if (tokenType != FSharpTokenType.PLUS) return false
advanceLexer() // eat plus token
val afterPlusTokenIndent = getCurrentIndentation()

// since "123" +"123" is not allowed
if (hasSpaceBeforePlus && !eatFilteredTokens()) return false

// since
// "123"
// more than one space after plus
// + "123"
// is not allowed
val secondStringOperandIndent = getCurrentIndentation()
if (movedToNewLine &&
afterPlusTokenIndent < requiredStringIndent &&
secondStringOperandIndent - afterPlusTokenIndent != 1
) return false

// since
// "123"
// + "123"
// is not allowed
return secondStringOperandIndent >= requiredStringIndent && parseStringExpression()
true
}
}

private fun PsiBuilder.parseStringExpression() =
parseInterpolatedStringExpression() || parseAnyStringExpression()

private fun PsiBuilder.parseAnyStringExpression() =
if (tokenType !in FSharpTokenType.ALL_STRINGS) false
else parse {
val interpolated = tokenType in FSharpTokenType.INTERPOLATED_STRINGS
advanceLexerWithNewLineCounting()
if (interpolated) FSharpElementTypes.INTERPOLATED_STRING_LITERAL_EXPRESSION_PART
else FSharpElementTypes.STRING_LITERAL_EXPRESSION
}

private fun PsiBuilder.parseInterpolatedStringExpression() =
if (tokenType !in FSharpTokenType.INTERPOLATED_STRINGS) false
else parse(FSharpElementTypes.INTERPOLATED_STRING_LITERAL_EXPRESSION) {
var nestingDepth = 0
whileMakingProgress {
if (tokenType in FSharpTokenType.INTERPOLATED_STRING_STARTS) nestingDepth += 1
if (tokenType in FSharpTokenType.INTERPOLATED_STRING_ENDS) nestingDepth -= 1
if (!parseAnyStringExpression()) advanceLexerWithNewLineCounting()
nestingDepth != 0
}
}
private fun PsiBuilder.tryParseConcatenationPartAhead(requiredStringIndent: Int): Boolean {
val oldLineIndex = currentLineIndex
val hasSpaceBeforePlus = eatFilteredTokens()
val movedToNewLine = currentLineIndex != oldLineIndex

if (tokenType != FSharpTokenType.PLUS) return false
advanceLexer() // eat plus token
val afterPlusTokenIndent = getCurrentIndentation()

// since "123" +"123" is not allowed
if (hasSpaceBeforePlus && !eatFilteredTokens()) return false

// since
// "123"
// more than one space after plus
// + "123"
// is not allowed
val secondStringOperandIndent = getCurrentIndentation()
if (movedToNewLine &&
afterPlusTokenIndent < requiredStringIndent &&
secondStringOperandIndent - afterPlusTokenIndent != 1
) return false

// since
// "123"
// + "123"
// is not allowed
return secondStringOperandIndent >= requiredStringIndent && parseStringExpression()
}

private fun PsiBuilder.parseStringExpression() =
parseInterpolatedStringExpression() || parseAnyStringExpression()

private fun PsiBuilder.parseAnyStringExpression() =
if (tokenType !in FSharpTokenType.ALL_STRINGS) false
else parse {
val interpolated = tokenType in FSharpTokenType.INTERPOLATED_STRINGS
advanceLexerWithNewLineCounting()
if (interpolated) FSharpElementTypes.INTERPOLATED_STRING_LITERAL_EXPRESSION_PART
else FSharpElementTypes.STRING_LITERAL_EXPRESSION
}

private fun PsiBuilder.eatFilteredTokens(): Boolean {
val offset = currentOffset
eof()
return currentOffset > offset
private fun PsiBuilder.parseInterpolatedStringExpression() =
if (tokenType !in FSharpTokenType.INTERPOLATED_STRINGS) false
else parse(FSharpElementTypes.INTERPOLATED_STRING_LITERAL_EXPRESSION) {
var nestingDepth = 0
whileMakingProgress {
if (tokenType in FSharpTokenType.INTERPOLATED_STRING_STARTS) nestingDepth += 1
if (tokenType in FSharpTokenType.INTERPOLATED_STRING_ENDS) nestingDepth -= 1
if (!parseAnyStringExpression()) advanceLexer()
nestingDepth != 0
}
}

private fun PsiBuilder.advanceLexerWithNewLineCounting() {
if (eof()) return

when (tokenType) {
in FSharpTokenType.STRINGS -> {
val lastEndOfLineIndex = tokenText!!.lastIndexOf('\n')
val stringStartIndent = currentOffset
advanceLexer()
if (lastEndOfLineIndex != -1) {
currentLineIndent = stringStartIndent + lastEndOfLineIndex + 1
++currentLineIndex
}
}

else -> advanceLexer()
private fun PsiBuilder.eatFilteredTokens(): Boolean {
val offset = currentOffset
eof() //skips whitespaces and comment tokens
return currentOffset > offset
}

private fun PsiBuilder.advanceLexerWithNewLineCounting() {
if (eof()) return

when (tokenType) {
in FSharpTokenType.STRINGS -> {
val lastEndOfLineIndex = tokenText!!.lastIndexOf('\n')
val stringStartIndent = currentOffset
advanceLexer()
if (lastEndOfLineIndex != -1) {
currentLineStart = stringStartIndent + lastEndOfLineIndex + 1
++currentLineIndex
}
}

else -> advanceLexer()
}
}

private var currentLineIndent = 0
private var currentLineIndex = 0
private var currentLineStart = 0
private var currentLineIndex = 0
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi.impl.FSharpFileImpl

class FSharpParserDefinition : ParserDefinition {
private val logger = getLogger<FSharpParserDefinition>()
override fun getWhitespaceTokens(): TokenSet = TokenSet.create(FSharpTokenType.NEW_LINE, TokenType.WHITE_SPACE)
override fun getWhitespaceTokens() = TokenSet.create(FSharpTokenType.NEW_LINE, TokenType.WHITE_SPACE)
override fun createLexer(project: Project?) = FSharpLexer()
override fun createParser(project: Project): PsiParser = FSharpDummyParser()
override fun getCommentTokens(): TokenSet = FSharpTokenType.COMMENTS
Expand Down
Loading

0 comments on commit c3c00cd

Please sign in to comment.