[FIR] Fix calculating offsets for light tree source elements

This commit is contained in:
Dmitriy Novozhilov
2020-12-15 12:58:14 +03:00
parent acbc468fdd
commit b048296dca
4 changed files with 45 additions and 25 deletions
@@ -52,7 +52,7 @@ class LightTree2Fir(
}
fun buildFirFile(file: File): FirFile {
val code = FileUtil.loadFile(file, CharsetToolkit.UTF8, true).trim()
val code = FileUtil.loadFile(file, CharsetToolkit.UTF8, true)
return buildFirFile(code, file.name)
}
@@ -21,12 +21,13 @@ import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.Name
import kotlin.contracts.ExperimentalContracts
open class BaseConverter(
abstract class BaseConverter(
baseSession: FirSession,
val tree: FlyweightCapableTreeStructure<LighterASTNode>,
val offset: Int,
context: Context<LighterASTNode> = Context()
) : BaseFirBuilder<LighterASTNode>(baseSession, context) {
abstract val offset: Int
protected val implicitType = buildImplicitTypeRef()
override fun LighterASTNode.toFirSourceElement(kind: FirFakeSourceElementKind?): FirLightSourceElement {
@@ -175,4 +176,4 @@ open class BaseConverter(
return container
}
}
}
@@ -65,8 +65,22 @@ class DeclarationsConverter(
tree: FlyweightCapableTreeStructure<LighterASTNode>,
offset: Int = 0,
context: Context<LighterASTNode> = Context()
) : BaseConverter(session, tree, offset, context) {
private val expressionConverter = ExpressionsConverter(session, stubMode, tree, this, offset + 1, context)
) : BaseConverter(session, tree, context) {
@set:PrivateForInline
override var offset: Int = offset
@OptIn(PrivateForInline::class)
inline fun <R> withOffset(newOffset: Int, block: () -> R): R {
val oldOffset = offset
offset = newOffset
return try {
block()
} finally {
offset = oldOffset
}
}
private val expressionConverter = ExpressionsConverter(session, stubMode, tree, this, context)
/**
* [org.jetbrains.kotlin.parsing.KotlinParsing.parseFile]
@@ -50,9 +50,10 @@ class ExpressionsConverter(
private val stubMode: Boolean,
tree: FlyweightCapableTreeStructure<LighterASTNode>,
private val declarationsConverter: DeclarationsConverter,
offset: Int,
context: Context<LighterASTNode> = Context()
) : BaseConverter(session, tree, offset, context) {
) : BaseConverter(session, tree, context) {
override val offset: Int
get() = declarationsConverter.offset
inline fun <reified R : FirElement> getAsFirExpression(expression: LighterASTNode?, errorReason: String = ""): R {
return expression?.let {
@@ -68,8 +69,10 @@ class ExpressionsConverter(
return when (expression.tokenType) {
LAMBDA_EXPRESSION -> {
val lambdaTree = LightTree2Fir.buildLightTreeLambdaExpression(expression.asText)
ExpressionsConverter(baseSession, stubMode, lambdaTree, declarationsConverter, offset, context)
.convertLambdaExpression(lambdaTree.root)
declarationsConverter.withOffset(offset + expression.startOffset) {
ExpressionsConverter(baseSession, stubMode, lambdaTree, declarationsConverter, context)
.convertLambdaExpression(lambdaTree.root)
}
}
BINARY_EXPRESSION -> convertBinaryExpression(expression)
BINARY_WITH_TYPE -> convertBinaryWithTypeRHSExpression(expression) {
@@ -172,22 +175,24 @@ class ExpressionsConverter(
}
body = if (block != null) {
declarationsConverter.convertBlockExpressionWithoutBuilding(block!!).apply {
if (statements.isEmpty()) {
statements.add(
buildReturnExpression {
source = expressionSource
this.target = target
result = buildUnitExpression { source = expressionSource }
}
)
}
if (destructuringBlock is FirBlock) {
for ((index, statement) in destructuringBlock.statements.withIndex()) {
statements.add(index, statement)
declarationsConverter.withOffset(expressionSource.startOffset) {
declarationsConverter.convertBlockExpressionWithoutBuilding(block!!).apply {
if (statements.isEmpty()) {
statements.add(
buildReturnExpression {
source = expressionSource
this.target = target
result = buildUnitExpression { source = expressionSource }
}
)
}
}
}.build()
if (destructuringBlock is FirBlock) {
for ((index, statement) in destructuringBlock.statements.withIndex()) {
statements.add(index, statement)
}
}
}.build()
}
} else {
buildSingleExpressionBlock(buildErrorExpression(null, ConeSimpleDiagnostic("Lambda has no body", DiagnosticKind.Syntax)))
}