-
Notifications
You must be signed in to change notification settings - Fork 57
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
53 changed files
with
701 additions
and
22 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
5 changes: 0 additions & 5 deletions
5
...fsharp/src/main/java/com/jetbrains/rider/ideaInterop/fileTypes/fsharp/FSharpAstFactory.kt
This file was deleted.
Oops, something went wrong.
115 changes: 115 additions & 0 deletions
115
...sharp/src/main/java/com/jetbrains/rider/ideaInterop/fileTypes/fsharp/FSharpDummyParser.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,115 @@ | ||
package com.jetbrains.rider.ideaInterop.fileTypes.fsharp | ||
|
||
import com.intellij.lang.ASTNode | ||
import com.intellij.lang.PsiBuilder | ||
import com.intellij.lang.PsiParser | ||
import com.intellij.psi.tree.IElementType | ||
import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.lexer.FSharpTokenType | ||
import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi.impl.FSharpElementTypes | ||
import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi.parse | ||
import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi.scanOrRollback | ||
import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi.whileMakingProgress | ||
|
||
class FSharpDummyParser : PsiParser { | ||
override fun parse(root: IElementType, builder: PsiBuilder): ASTNode { | ||
builder.setWhitespaceSkippedCallback { elementType, _, end -> | ||
if (elementType == FSharpTokenType.NEW_LINE) currentLineStart = end | ||
} | ||
builder.parseFile(root) | ||
return builder.treeBuilt | ||
} | ||
|
||
private fun PsiBuilder.parseFile(fileElementType: IElementType) { | ||
parse(fileElementType) { | ||
whileMakingProgress { | ||
if (!parseDummyExpression()) advanceLexerWithNewLineCounting() | ||
true | ||
} | ||
} | ||
} | ||
|
||
private fun PsiBuilder.getCurrentLineOffset() = currentOffset - currentLineStart | ||
private fun PsiBuilder.parseDummyExpression() = parseConcatenation() | ||
|
||
private fun PsiBuilder.parseConcatenation() = | ||
parse { | ||
val currentIndent = getCurrentLineOffset() | ||
|
||
if (!parseStringExpression()) null | ||
else if (!scanOrRollback { tryParseConcatenationPartAhead(currentIndent) }) null | ||
else { | ||
whileMakingProgress { | ||
scanOrRollback { tryParseConcatenationPartAhead(currentIndent) } | ||
} | ||
FSharpElementTypes.DUMMY_EXPRESSION | ||
} | ||
} | ||
|
||
private fun PsiBuilder.tryParseConcatenationPartAhead(requiredStringIndent: Int): Boolean { | ||
val hasSpaceBeforePlus = rawLookup(-1)?.let { isWhitespaceOrComment(it) } ?: false | ||
|
||
if (tokenType != FSharpTokenType.PLUS) return false | ||
val afterPlusTokenIndent = getCurrentLineOffset() + 1 | ||
advanceLexer() // eat plus token | ||
|
||
// since "123" +"123" is not allowed | ||
if (hasSpaceBeforePlus && currentOffset - afterPlusTokenIndent == 0) return false | ||
|
||
val secondStringOperandIndent = getCurrentLineOffset() | ||
// since | ||
// "123" | ||
// + "123" | ||
// is not allowed | ||
if (secondStringOperandIndent < requiredStringIndent) return false | ||
|
||
// since | ||
// "123" | ||
// more than one space after plus | ||
// + "123" | ||
// is not allowed | ||
if (secondStringOperandIndent == requiredStringIndent && | ||
secondStringOperandIndent - afterPlusTokenIndent > 1 | ||
) return false | ||
|
||
return 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.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.advanceLexerWithNewLineCounting() { | ||
when (tokenType) { | ||
in FSharpTokenType.STRINGS -> { | ||
val lastEndOfLineIndex = tokenText!!.lastIndexOf('\n') | ||
val stringStartIndent = currentOffset | ||
advanceLexer() | ||
if (lastEndOfLineIndex != -1) currentLineStart = stringStartIndent + lastEndOfLineIndex + 1 | ||
} | ||
|
||
else -> advanceLexer() | ||
} | ||
} | ||
|
||
private var currentLineStart = 0 | ||
} |
40 changes: 29 additions & 11 deletions
40
.../src/main/java/com/jetbrains/rider/ideaInterop/fileTypes/fsharp/FSharpParserDefinition.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,19 +1,37 @@ | ||
package com.jetbrains.rider.ideaInterop.fileTypes.fsharp | ||
|
||
import com.intellij.lexer.Lexer | ||
import com.intellij.lang.ASTNode | ||
import com.intellij.lang.ParserDefinition | ||
import com.intellij.lang.PsiParser | ||
import com.intellij.openapi.project.Project | ||
import com.intellij.psi.tree.IElementType | ||
import com.intellij.psi.FileViewProvider | ||
import com.intellij.psi.PsiElement | ||
import com.intellij.psi.tree.IFileElementType | ||
import com.jetbrains.rider.ideaInterop.fileTypes.RiderFileElementType | ||
import com.jetbrains.rider.ideaInterop.fileTypes.RiderParserDefinitionBase | ||
import com.intellij.psi.tree.TokenSet | ||
import com.intellij.psi.util.PsiUtilCore | ||
import com.jetbrains.rd.platform.util.getLogger | ||
import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.lexer.FSharpLexer | ||
import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.lexer.FSharpTokenType | ||
import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi.impl.FSharpElementTypes | ||
import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi.impl.FSharpFileImpl | ||
|
||
class FSharpParserDefinition : RiderParserDefinitionBase(FSharpFileElementType, FSharpFileType) { | ||
companion object { | ||
val FSharpElementType = IElementType("RIDER_FSHARP", FSharpLanguage) | ||
val FSharpFileElementType = RiderFileElementType("RIDER_FSHARP_FILE", FSharpLanguage, FSharpElementType) | ||
} | ||
class FSharpParserDefinition : ParserDefinition { | ||
private val logger = getLogger<FSharpParserDefinition>() | ||
override fun getWhitespaceTokens() = TokenSet.create(FSharpTokenType.NEW_LINE, FSharpTokenType.WHITESPACE) | ||
override fun createLexer(project: Project?) = FSharpLexer() | ||
override fun createParser(project: Project): PsiParser = FSharpDummyParser() | ||
override fun getCommentTokens(): TokenSet = FSharpTokenType.COMMENTS | ||
override fun getStringLiteralElements(): TokenSet = FSharpTokenType.ALL_STRINGS | ||
override fun createElement(node: ASTNode): PsiElement { | ||
if (node is PsiElement) { | ||
logger.error("Dummy blocks should be lazy and not parsed like this") | ||
return node | ||
} | ||
|
||
override fun createLexer(project: Project?): Lexer = FSharpLexer() | ||
override fun getFileNodeType(): IFileElementType = FSharpFileElementType | ||
logger.error("An attempt to parse unexpected element") | ||
return PsiUtilCore.NULL_PSI_ELEMENT | ||
} | ||
|
||
override fun createFile(viewProvider: FileViewProvider) = FSharpFileImpl(viewProvider) | ||
override fun getFileNodeType(): IFileElementType = FSharpElementTypes.FILE | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
17 changes: 17 additions & 0 deletions
17
.../src/main/java/com/jetbrains/rider/ideaInterop/fileTypes/fsharp/psi/FSharpElementTypes.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
package com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi | ||
|
||
import com.intellij.lang.ASTNode | ||
import com.intellij.psi.tree.ICompositeElementType | ||
import com.intellij.psi.tree.IElementType | ||
import com.intellij.psi.tree.IFileElementType | ||
import com.jetbrains.rider.ideaInterop.fileTypes.fsharp.FSharpLanguage | ||
|
||
class FSharpFileElementType : IFileElementType("FSharpFile", FSharpLanguage) | ||
|
||
open class FSharpElementType(debugName: String, val text: String = debugName) : IElementType(debugName, FSharpLanguage) | ||
abstract class FSharpCompositeElementType(debugName: String) : FSharpElementType(debugName), ICompositeElementType | ||
|
||
inline fun createCompositeElementType(debugName: String, crossinline elementFactory: (FSharpElementType) -> ASTNode) = | ||
object : FSharpCompositeElementType(debugName) { | ||
override fun createCompositeNode() = elementFactory(this) | ||
} |
16 changes: 16 additions & 0 deletions
16
...harp/src/main/java/com/jetbrains/rider/ideaInterop/fileTypes/fsharp/psi/FSharpElements.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
package com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi | ||
|
||
import com.intellij.psi.PsiElement | ||
import com.intellij.psi.PsiFile | ||
|
||
interface FSharpElement : PsiElement | ||
|
||
interface FSharpFile : FSharpElement, PsiFile | ||
|
||
interface FSharpExpression : FSharpElement | ||
|
||
interface FSharpStringLiteralExpression : FSharpElement | ||
|
||
interface FSharpInterpolatedStringLiteralExpressionPart : FSharpElement | ||
|
||
interface FSharpInterpolatedStringLiteralExpression : FSharpStringLiteralExpression |
24 changes: 24 additions & 0 deletions
24
...ain/java/com/jetbrains/rider/ideaInterop/fileTypes/fsharp/psi/FSharpStringLiteralTypes.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
package com.jetbrains.rider.ideaInterop.fileTypes.fsharp.psi | ||
|
||
enum class FSharpStringLiteralType { | ||
/** "{string representation}" */ | ||
RegularString, | ||
|
||
/** @"{string representation}" */ | ||
VerbatimString, | ||
|
||
/** """{string representation}""" */ | ||
TripleQuoteString, | ||
|
||
/** $"{string representation}" */ | ||
RegularInterpolatedString, | ||
|
||
/** $@"{string representation}" */ | ||
VerbatimInterpolatedString, | ||
|
||
/** $"""{string representation}""" */ | ||
TripleQuoteInterpolatedString, | ||
|
||
/** "{string representation}"B */ | ||
ByteArray | ||
} |
Oops, something went wrong.