[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 { 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) return buildFirFile(code, file.name)
} }
@@ -21,12 +21,13 @@ import org.jetbrains.kotlin.lexer.KtTokens.*
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import kotlin.contracts.ExperimentalContracts import kotlin.contracts.ExperimentalContracts
open class BaseConverter( abstract class BaseConverter(
baseSession: FirSession, baseSession: FirSession,
val tree: FlyweightCapableTreeStructure<LighterASTNode>, val tree: FlyweightCapableTreeStructure<LighterASTNode>,
val offset: Int,
context: Context<LighterASTNode> = Context() context: Context<LighterASTNode> = Context()
) : BaseFirBuilder<LighterASTNode>(baseSession, context) { ) : BaseFirBuilder<LighterASTNode>(baseSession, context) {
abstract val offset: Int
protected val implicitType = buildImplicitTypeRef() protected val implicitType = buildImplicitTypeRef()
override fun LighterASTNode.toFirSourceElement(kind: FirFakeSourceElementKind?): FirLightSourceElement { override fun LighterASTNode.toFirSourceElement(kind: FirFakeSourceElementKind?): FirLightSourceElement {
@@ -175,4 +176,4 @@ open class BaseConverter(
return container return container
} }
} }
@@ -65,8 +65,22 @@ class DeclarationsConverter(
tree: FlyweightCapableTreeStructure<LighterASTNode>, tree: FlyweightCapableTreeStructure<LighterASTNode>,
offset: Int = 0, offset: Int = 0,
context: Context<LighterASTNode> = Context() context: Context<LighterASTNode> = Context()
) : BaseConverter(session, tree, offset, context) { ) : BaseConverter(session, tree, context) {
private val expressionConverter = ExpressionsConverter(session, stubMode, tree, this, offset + 1, 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] * [org.jetbrains.kotlin.parsing.KotlinParsing.parseFile]
@@ -50,9 +50,10 @@ class ExpressionsConverter(
private val stubMode: Boolean, private val stubMode: Boolean,
tree: FlyweightCapableTreeStructure<LighterASTNode>, tree: FlyweightCapableTreeStructure<LighterASTNode>,
private val declarationsConverter: DeclarationsConverter, private val declarationsConverter: DeclarationsConverter,
offset: Int,
context: Context<LighterASTNode> = Context() 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 { inline fun <reified R : FirElement> getAsFirExpression(expression: LighterASTNode?, errorReason: String = ""): R {
return expression?.let { return expression?.let {
@@ -68,8 +69,10 @@ class ExpressionsConverter(
return when (expression.tokenType) { return when (expression.tokenType) {
LAMBDA_EXPRESSION -> { LAMBDA_EXPRESSION -> {
val lambdaTree = LightTree2Fir.buildLightTreeLambdaExpression(expression.asText) val lambdaTree = LightTree2Fir.buildLightTreeLambdaExpression(expression.asText)
ExpressionsConverter(baseSession, stubMode, lambdaTree, declarationsConverter, offset, context) declarationsConverter.withOffset(offset + expression.startOffset) {
.convertLambdaExpression(lambdaTree.root) ExpressionsConverter(baseSession, stubMode, lambdaTree, declarationsConverter, context)
.convertLambdaExpression(lambdaTree.root)
}
} }
BINARY_EXPRESSION -> convertBinaryExpression(expression) BINARY_EXPRESSION -> convertBinaryExpression(expression)
BINARY_WITH_TYPE -> convertBinaryWithTypeRHSExpression(expression) { BINARY_WITH_TYPE -> convertBinaryWithTypeRHSExpression(expression) {
@@ -172,22 +175,24 @@ class ExpressionsConverter(
} }
body = if (block != null) { body = if (block != null) {
declarationsConverter.convertBlockExpressionWithoutBuilding(block!!).apply { declarationsConverter.withOffset(expressionSource.startOffset) {
if (statements.isEmpty()) { declarationsConverter.convertBlockExpressionWithoutBuilding(block!!).apply {
statements.add( if (statements.isEmpty()) {
buildReturnExpression { statements.add(
source = expressionSource buildReturnExpression {
this.target = target source = expressionSource
result = buildUnitExpression { source = expressionSource } this.target = target
} result = buildUnitExpression { source = expressionSource }
) }
} )
if (destructuringBlock is FirBlock) {
for ((index, statement) in destructuringBlock.statements.withIndex()) {
statements.add(index, statement)
} }
} if (destructuringBlock is FirBlock) {
}.build() for ((index, statement) in destructuringBlock.statements.withIndex()) {
statements.add(index, statement)
}
}
}.build()
}
} else { } else {
buildSingleExpressionBlock(buildErrorExpression(null, ConeSimpleDiagnostic("Lambda has no body", DiagnosticKind.Syntax))) buildSingleExpressionBlock(buildErrorExpression(null, ConeSimpleDiagnostic("Lambda has no body", DiagnosticKind.Syntax)))
} }