FIR: introduce element kind for source elements

It is needed for FIR IDE to determine if FIR element was built by PSI
or it is generated one
This commit is contained in:
Ilya Kirillov
2020-06-15 17:26:14 +03:00
parent f6e653b242
commit 94967bcd00
13 changed files with 305 additions and 127 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -21,10 +21,11 @@ import org.jetbrains.kotlin.fir.references.FirReference
import org.jetbrains.kotlin.fir.references.builder.*
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.lexer.KtTokens.CLOSING_QUOTE
import org.jetbrains.kotlin.lexer.KtTokens.OPEN_QUOTE
import org.jetbrains.kotlin.name.FqName
@@ -35,7 +36,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
//T can be either PsiElement, or LighterASTNode
abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Context<T> = Context()) {
abstract fun T.toFirSourceElement(): FirSourceElement
abstract fun T.toFirSourceElement(kind: FirSourceElementKind = FirRealSourceElementKind): FirSourceElement
protected val implicitUnitType = baseSession.builtinTypes.unitType
protected val implicitAnyType = baseSession.builtinTypes.anyType
@@ -168,7 +169,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
private fun T?.toDelegatedSelfType(firClass: FirClassBuilder, symbol: FirClassLikeSymbol<*>): FirResolvedTypeRef {
return buildResolvedTypeRef {
source = this@toDelegatedSelfType?.toFirSourceElement()
source = this@toDelegatedSelfType?.toFirSourceElement(FirFakeSourceElementKind.ClassSelfTypeRef)
type = ConeClassLikeTypeImpl(
symbol.toLookupTag(),
firClass.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(),
@@ -335,7 +336,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> {
hasExpressions = true
val firExpression = entry.convertTemplateEntry("Incorrect template argument")
val source = firExpression.source
val source = firExpression.source?.withKind(FirFakeSourceElementKind.GeneratedToStringCallOnTemplateEntry)
buildFunctionCall {
this.source = source
explicitReceiver = firExpression
@@ -402,22 +403,28 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
}
return buildBlock {
val baseSource = baseExpression?.toFirSourceElement()
source = baseSource
val desugaredSource = baseSource?.withKind(FirFakeSourceElementKind.DesugaredIncrementOrDecrement)
source = desugaredSource
val tempName = Name.special("<unary>")
val temporaryVariable = generateTemporaryVariable(this@BaseFirBuilder.baseSession, source, tempName, argument.convert())
val temporaryVariable = generateTemporaryVariable(
this@BaseFirBuilder.baseSession,
desugaredSource,
tempName,
argument.convert()
)
statements += temporaryVariable
val resultName = Name.special("<unary-result>")
val resultInitializer = buildFunctionCall {
source = baseSource
source = desugaredSource
calleeReference = buildSimpleNamedReference {
source = operationReference?.toFirSourceElement()
name = callName
}
explicitReceiver = generateResolvedAccessExpression(source, temporaryVariable)
explicitReceiver = generateResolvedAccessExpression(desugaredSource, temporaryVariable)
}
val resultVar = generateTemporaryVariable(this@BaseFirBuilder.baseSession, source, resultName, resultInitializer)
val resultVar = generateTemporaryVariable(this@BaseFirBuilder.baseSession, desugaredSource, resultName, resultInitializer)
val assignment = argument.generateAssignment(
source,
desugaredSource,
argument,
if (prefix && argument.elementType != REFERENCE_EXPRESSION)
generateResolvedAccessExpression(source, resultVar)
@@ -438,14 +445,14 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
if (argument.elementType != REFERENCE_EXPRESSION) {
statements += resultVar
appendAssignment()
statements += generateResolvedAccessExpression(source, resultVar)
statements += generateResolvedAccessExpression(desugaredSource, resultVar)
} else {
appendAssignment()
statements += generateAccessExpression(source, argument.getReferencedNameAsName())
statements += generateAccessExpression(desugaredSource, argument.getReferencedNameAsName())
}
} else {
appendAssignment()
statements += generateResolvedAccessExpression(source, temporaryVariable)
statements += generateResolvedAccessExpression(desugaredSource, temporaryVariable)
}
}
}
@@ -728,7 +735,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
componentIndex++
val parameterSource = sourceNode?.toFirSourceElement()
val componentFunction = buildSimpleFunction {
source = parameterSource
source = parameterSource?.withKind(FirFakeSourceElementKind.DataClassGeneratedMembers)
session = this@DataClassMembersGenerator.session
origin = FirDeclarationOrigin.Source
returnTypeRef = firProperty.returnTypeRef
@@ -762,7 +769,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
source = parameterSource
session = this@DataClassMembersGenerator.session
origin = FirDeclarationOrigin.Source
returnTypeRef = firProperty.returnTypeRef
returnTypeRef = propertyReturnTypeRef
name = propertyName
symbol = FirVariableSymbol(propertyName)
defaultValue = generateComponentAccess(parameterSource, firProperty)
@@ -1,11 +1,12 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.builder
import kotlinx.collections.immutable.persistentListOf
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirFunctionTarget
import org.jetbrains.kotlin.fir.FirLabel
import org.jetbrains.kotlin.fir.FirLoopTarget
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -33,10 +33,8 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirDelegateFieldSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.ConeStarProjection
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.*
import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name
@@ -146,12 +144,13 @@ fun FirExpression.generateNotNullOrOther(
session: FirSession, other: FirExpression, caseId: String, baseSource: FirSourceElement?,
): FirWhenExpression {
val subjectName = Name.special("<$caseId>")
val subjectVariable = generateTemporaryVariable(session, baseSource, subjectName, this)
val subjectSource = baseSource?.withKind(FirFakeSourceElementKind.WhenGeneratedSubject)
val subjectVariable = generateTemporaryVariable(session, subjectSource, subjectName, this)
@OptIn(FirContractViolation::class)
val ref = FirExpressionRef<FirWhenExpression>()
val subjectExpression = buildWhenSubjectExpression {
source = baseSource
source = subjectSource
whenRef = ref
}
@@ -160,22 +159,24 @@ fun FirExpression.generateNotNullOrOther(
this.subject = this@generateNotNullOrOther
this.subjectVariable = subjectVariable
branches += buildWhenBranch {
source = baseSource
val branchSource = baseSource?.withKind(FirFakeSourceElementKind.WhenCondition)
source = branchSource
condition = buildOperatorCall {
source = baseSource
source = branchSource
operation = FirOperation.EQ
argumentList = buildBinaryArgumentList(
subjectExpression, buildConstExpression(baseSource, FirConstKind.Null, null)
subjectExpression, buildConstExpression(branchSource, FirConstKind.Null, null)
)
}
result = buildSingleExpressionBlock(other)
}
branches += buildWhenBranch {
source = other.source
val otherSource = other.source?.withKind(FirFakeSourceElementKind.WhenCondition)
source = otherSource
condition = buildElseIfTrueCondition {
source = baseSource
source = otherSource
}
result = buildSingleExpressionBlock(generateResolvedAccessExpression(baseSource, subjectVariable))
result = buildSingleExpressionBlock(generateResolvedAccessExpression(otherSource, subjectVariable))
}
}.also {
ref.bind(it)
@@ -203,9 +204,9 @@ fun FirExpression.generateContainsOperation(
if (!inverted) return containsCall
return buildFunctionCall {
source = baseSource
source = baseSource?.withKind(FirFakeSourceElementKind.DesugaredInvertedContains)
calleeReference = buildSimpleNamedReference {
source = operationReferenceSource
source = operationReferenceSource?.withKind(FirFakeSourceElementKind.DesugaredInvertedContains)
name = OperatorNameConventions.NOT
}
explicitReceiver = containsCall
@@ -222,7 +223,12 @@ fun FirExpression.generateComparisonExpression(
"$operatorToken is not in ${OperatorConventions.COMPARISON_OPERATIONS}"
}
val compareToCall = createConventionCall(operationReferenceSource, baseSource, argument, OperatorNameConventions.COMPARE_TO)
val compareToCall = createConventionCall(
operationReferenceSource,
baseSource?.withKind(FirFakeSourceElementKind.GeneratedCompararisonExpression),
argument,
OperatorNameConventions.COMPARE_TO
)
val firOperation = when (operatorToken) {
KtTokens.LT -> FirOperation.LT
@@ -511,6 +517,6 @@ fun FirModifiableQualifiedAccess.wrapWithSafeCall(receiver: FirExpression): FirS
bind(checkedSafeCallSubject)
}
this.regularQualifiedAccess = this@wrapWithSafeCall
this.source = this@wrapWithSafeCall.source
this.source = this@wrapWithSafeCall.source?.withKind(FirFakeSourceElementKind.DesugaredSafeCallExpression)
}
}
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -12,6 +12,7 @@ import com.intellij.util.diff.FlyweightCapableTreeStructure
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.fir.FirLightSourceElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSourceElementKind
import org.jetbrains.kotlin.fir.builder.BaseFirBuilder
import org.jetbrains.kotlin.fir.builder.Context
import org.jetbrains.kotlin.fir.builder.escapedStringToCharacter
@@ -30,7 +31,7 @@ open class BaseConverter(
) : BaseFirBuilder<LighterASTNode>(baseSession, context) {
protected val implicitType = buildImplicitTypeRef()
override fun LighterASTNode.toFirSourceElement(): FirLightSourceElement {
override fun LighterASTNode.toFirSourceElement(kind: FirSourceElementKind): FirLightSourceElement {
val startOffset = offset + tree.getStartOffset(this)
val endOffset = offset + tree.getEndOffset(this)
return toFirLightSourceElement(startOffset, endOffset, tree)
@@ -7,9 +7,7 @@ package org.jetbrains.kotlin.fir.builder
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirExpressionRef
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty
@@ -19,7 +17,6 @@ import org.jetbrains.kotlin.fir.diagnostics.DiagnosticKind
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.toFirPsiSourceElement
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.psi.*
@@ -28,15 +25,15 @@ internal fun KtWhenCondition.toFirWhenCondition(
convert: KtExpression?.(String) -> FirExpression,
toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef,
): FirExpression {
val baseSource = this.toFirPsiSourceElement()
val firSubjectSource = this.toFirPsiSourceElement(FirFakeSourceElementKind.WhenGeneratedSubject)
val firSubjectExpression = buildWhenSubjectExpression {
source = baseSource
source = firSubjectSource
whenRef = whenRefWithSibject
}
return when (this) {
is KtWhenConditionWithExpression -> {
buildOperatorCall {
source = expression?.toFirPsiSourceElement()
source = expression?.toFirPsiSourceElement(FirFakeSourceElementKind.WhenCondition)
operation = FirOperation.EQ
argumentList = buildBinaryArgumentList(
firSubjectExpression, expression.convert("No expression in condition with expression")
@@ -48,26 +45,25 @@ internal fun KtWhenCondition.toFirWhenCondition(
firRange.generateContainsOperation(
firSubjectExpression,
isNegated,
rangeExpression?.toFirPsiSourceElement(),
rangeExpression?.toFirPsiSourceElement(FirFakeSourceElementKind.WhenCondition),
operationReference.toFirPsiSourceElement()
)
}
is KtWhenConditionIsPattern -> {
buildTypeOperatorCall {
source = typeReference?.toFirPsiSourceElement()
source = this@toFirWhenCondition.toFirPsiSourceElement()
operation = if (isNegated) FirOperation.NOT_IS else FirOperation.IS
conversionTypeRef = typeReference.toFirOrErrorTypeRef()
argumentList = buildUnaryArgumentList(firSubjectExpression)
}
}
else -> {
buildErrorExpression(baseSource, ConeSimpleDiagnostic("Unsupported when condition: ${this.javaClass}", DiagnosticKind.Syntax))
buildErrorExpression(firSubjectSource, ConeSimpleDiagnostic("Unsupported when condition: ${this.javaClass}", DiagnosticKind.Syntax))
}
}
}
internal fun Array<KtWhenCondition>.toFirWhenCondition(
baseSource: FirSourceElement?,
subject: FirExpressionRef<FirWhenExpression>,
convert: KtExpression?.(String) -> FirExpression,
toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef,
@@ -78,7 +74,7 @@ internal fun Array<KtWhenCondition>.toFirWhenCondition(
firCondition = when (firCondition) {
null -> firConditionElement
else -> firCondition.generateLazyLogicalOperation(
firConditionElement, false, baseSource,
firConditionElement, false, condition.toFirPsiSourceElement(FirFakeSourceElementKind.WhenCondition),
)
}
}
@@ -109,8 +105,9 @@ internal fun generateDestructuringBlock(
returnTypeRef = entry.typeReference.toFirOrImplicitTypeRef()
this.name = name
initializer = buildComponentCall {
source = entrySource
explicitReceiver = generateResolvedAccessExpression(entrySource, container)
val componentCallSource = entrySource.withKind(FirFakeSourceElementKind.DesugaredComponentFunctionCall)
source = componentCallSource
explicitReceiver = generateResolvedAccessExpression(componentCallSource, container)
componentIndex = index + 1
}
this.isVar = isVar
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.util.*
import org.jetbrains.kotlin.utils.addToStdlib.runIf
import kotlin.collections.contains
@@ -61,8 +62,8 @@ class RawFirBuilder(
return reference.accept(Visitor(), Unit) as FirTypeRef
}
override fun PsiElement.toFirSourceElement(): FirPsiSourceElement<*> {
return this.toFirPsiSourceElement()
override fun PsiElement.toFirSourceElement(kind: FirSourceElementKind): FirPsiSourceElement<*> {
return this.toFirPsiSourceElement(kind)
}
override val PsiElement.elementType: IElementType
@@ -128,7 +129,7 @@ class RawFirBuilder(
private fun KtTypeReference?.toFirOrImplicitType(): FirTypeRef =
convertSafe() ?: buildImplicitTypeRef {
source = this@toFirOrImplicitType?.toFirSourceElement()
source = this@toFirOrImplicitType?.toFirSourceElement(FirFakeSourceElementKind.ImplicitTypeRef)
}
private fun KtTypeReference?.toFirOrUnitType(): FirTypeRef =
@@ -272,7 +273,9 @@ class RawFirBuilder(
this@toFirPropertyAccessor?.hasModifier(EXTERNAL_KEYWORD) == true
}
if (this == null || !hasBody()) {
val propertySource = property.toFirSourceElement()
val propertySource =
if (this != null && hasBody()) property.toFirSourceElement()
else property.toFirPsiSourceElement(FirFakeSourceElementKind.DefaultAccessor)
return FirDefaultPropertyAccessor
.createGetterOrSetter(
propertySource,
@@ -307,7 +310,7 @@ class RawFirBuilder(
extractValueParametersTo(this, propertyTypeRef)
if (!isGetter && valueParameters.isEmpty()) {
valueParameters += buildDefaultSetterValueParameter {
this.source = source
this.source = source.withKind(FirFakeSourceElementKind.DefaultAccessor)
session = baseSession
origin = FirDeclarationOrigin.Source
returnTypeRef = propertyTypeRef
@@ -359,18 +362,17 @@ class RawFirBuilder(
isConst = false
isLateInit = false
}
val parameterSource = this.toFirSourceElement()
val propertySource = this@toFirProperty.toFirSourceElement()
val propertySource = toFirSourceElement(FirFakeSourceElementKind.PropertyFromParameter)
val propertyName = nameAsSafeName
return buildProperty {
source = parameterSource
source = propertySource
session = baseSession
origin = FirDeclarationOrigin.Source
returnTypeRef = type
receiverTypeRef = null
name = propertyName
initializer = buildQualifiedAccessExpression {
source = parameterSource
source = propertySource
calleeReference = buildPropertyFromParameterResolvedNamedReference {
source = propertySource
name = propertyName
@@ -381,9 +383,10 @@ class RawFirBuilder(
symbol = FirPropertySymbol(callableIdForName(propertyName))
isLocal = false
this.status = status
getter = FirDefaultPropertyGetter(propertySource, baseSession, FirDeclarationOrigin.Source, type, visibility)
val defaultAccessorSource = propertySource.withKind(FirFakeSourceElementKind.DefaultAccessor)
getter = FirDefaultPropertyGetter(defaultAccessorSource, baseSession, FirDeclarationOrigin.Source, type, visibility)
setter = if (isMutable) FirDefaultPropertySetter(
propertySource,
defaultAccessorSource,
baseSession,
FirDeclarationOrigin.Source,
type,
@@ -536,9 +539,10 @@ class RawFirBuilder(
ownerTypeParameters: List<FirTypeParameterRef>
): FirConstructor {
val constructorCallee = superTypeCallEntry?.calleeExpression?.toFirSourceElement()
val constructorSource = (this ?: owner).toFirSourceElement()
val constructorSource = this?.toFirSourceElement()
?: owner.toFirPsiSourceElement(FirFakeSourceElementKind.ImplicitConstructor)
val firDelegatedCall = buildDelegatedConstructorCall {
source = constructorCallee ?: constructorSource
source = constructorCallee ?: constructorSource.withKind(FirFakeSourceElementKind.DelegatingConstructorCall)
constructedTypeRef = delegatedSuperTypeRef
isThis = false
if (!stubMode) {
@@ -624,7 +628,7 @@ class RawFirBuilder(
}
initializer = withChildClassName(nameAsSafeName) {
buildAnonymousObject {
source = toFirSourceElement()
source = toFirSourceElement(FirFakeSourceElementKind.EnumInitializer)
session = baseSession
origin = FirDeclarationOrigin.Source
classKind = ClassKind.ENUM_ENTRY
@@ -897,11 +901,12 @@ class RawFirBuilder(
override fun visitLambdaExpression(expression: KtLambdaExpression, data: Unit): FirElement {
val literal = expression.functionLiteral
val literalSource = literal.toFirSourceElement()
val implicitTypeRefSource = literal.toFirSourceElement(FirFakeSourceElementKind.ImplicitTypeRef)
val returnType = buildImplicitTypeRef {
source = literalSource
source = implicitTypeRefSource
}
val receiverType = buildImplicitTypeRef {
source = literalSource
source = implicitTypeRefSource
}
val target: FirFunctionTarget
@@ -924,7 +929,7 @@ class RawFirBuilder(
session = baseSession
origin = FirDeclarationOrigin.Source
returnTypeRef = buildImplicitTypeRef {
source = multiDeclaration.toFirSourceElement()
source = multiDeclaration.toFirSourceElement(FirFakeSourceElementKind.ImplicitTypeRef)
}
this.name = name
symbol = FirVariableSymbol(name)
@@ -942,7 +947,7 @@ class RawFirBuilder(
multiParameter
} else {
val typeRef = buildImplicitTypeRef {
source = this@buildAnonymousFunction.source
source = implicitTypeRefSource
}
valueParameter.toFirValueParameter(typeRef)
}
@@ -950,7 +955,7 @@ class RawFirBuilder(
val expressionSource = expression.toFirSourceElement()
label = context.firLabels.pop() ?: context.calleeNamesForLambda.lastOrNull()?.let {
buildLabel {
source = expressionSource
source = expressionSource.withKind(FirFakeSourceElementKind.GeneratedLambdaLabel)
name = it.asString()
}
}
@@ -966,9 +971,11 @@ class RawFirBuilder(
if (statements.isEmpty()) {
statements.add(
buildReturnExpression {
source = expressionSource
source = expressionSource.withKind(FirFakeSourceElementKind.ImplicitReturn)
this.target = target
result = buildUnitExpression { source = expressionSource }
result = buildUnitExpression {
source = expressionSource.withKind(FirFakeSourceElementKind.ImplicitUnit)
}
}
)
}
@@ -1070,7 +1077,7 @@ class RawFirBuilder(
symbol = FirPropertySymbol(propertyName)
val delegateBuilder = delegateExpression?.let {
FirWrappedDelegateExpressionBuilder().apply {
source = it.toFirSourceElement()
source = it.toFirSourceElement(FirFakeSourceElementKind.WrappedDelegate)
expression = it.toFirExpression("Incorrect delegate expression")
}
}
@@ -1090,7 +1097,8 @@ class RawFirBuilder(
addCapturedTypeParameters(this.typeParameters)
val delegateBuilder = if (hasDelegate()) {
FirWrappedDelegateExpressionBuilder().apply {
source = if (stubMode) null else delegateExpression?.toFirSourceElement()
source =
if (stubMode) null else delegateExpression?.toFirSourceElement(FirFakeSourceElementKind.WrappedDelegate)
expression = { delegateExpression }.toFirExpression("Should have delegate")
}
} else null
@@ -1305,7 +1313,7 @@ class RawFirBuilder(
}
override fun visitReturnExpression(expression: KtReturnExpression, data: Unit): FirElement {
val source = expression.toFirSourceElement()
val source = expression.toFirSourceElement(FirFakeSourceElementKind.ImplicitUnit)
val result = expression.returnedExpression?.toFirExpression("Incorrect return expression")
?: buildUnitExpression { this.source = source }
return result.toReturn(source, expression.getTargetLabel()?.getReferencedName())
@@ -1332,7 +1340,7 @@ class RawFirBuilder(
source = expression.toFirSourceElement()
val ktCondition = expression.condition
branches += buildWhenBranch {
source = ktCondition?.toFirSourceElement()
source = ktCondition?.toFirSourceElement(FirFakeSourceElementKind.WhenCondition)
condition = ktCondition.toFirExpression("If statement should have condition")
result = expression.then.toFirBlock()
}
@@ -1388,7 +1396,6 @@ class RawFirBuilder(
buildWhenBranch {
source = entrySource
condition = entry.conditions.toFirWhenCondition(
entrySource,
ref,
{ toFirExpression(it) },
{ toFirOrErrorType() },
@@ -1435,16 +1442,16 @@ class RawFirBuilder(
override fun visitForExpression(expression: KtForExpression, data: Unit?): FirElement {
val rangeExpression = expression.loopRange.toFirExpression("No range in for loop")
val ktParameter = expression.loopParameter
val loopSource = expression.toFirSourceElement()
val fakeSource = expression.toFirPsiSourceElement(FirFakeSourceElementKind.DesugaredForLoop)
return buildBlock {
source = loopSource
val rangeSource = expression.loopRange?.toFirSourceElement()
source = fakeSource
val rangeSource = expression.loopRange?.toFirSourceElement(FirFakeSourceElementKind.DesugaredForLoop)
val iteratorVal = generateTemporaryVariable(
baseSession, rangeSource, Name.special("<iterator>"),
buildFunctionCall {
source = loopSource
source = fakeSource
calleeReference = buildSimpleNamedReference {
source = loopSource
source = fakeSource
name = Name.identifier("iterator")
}
explicitReceiver = rangeExpression
@@ -1452,14 +1459,14 @@ class RawFirBuilder(
)
statements += iteratorVal
statements += FirWhileLoopBuilder().apply {
source = loopSource
source = expression.toFirSourceElement()
condition = buildFunctionCall {
source = loopSource
source = fakeSource
calleeReference = buildSimpleNamedReference {
source = loopSource
source = fakeSource
name = Name.identifier("hasNext")
}
explicitReceiver = generateResolvedAccessExpression(loopSource, iteratorVal)
explicitReceiver = generateResolvedAccessExpression(fakeSource, iteratorVal)
}
}.configure {
// NB: just body.toFirBlock() isn't acceptable here because we need to add some statements
@@ -1467,7 +1474,7 @@ class RawFirBuilder(
is KtBlockExpression -> configureBlockWithoutBuilding(body)
null -> FirBlockBuilder()
else -> FirBlockBuilder().apply {
source = body.toFirSourceElement()
source = body.toFirSourceElement(FirFakeSourceElementKind.DesugaredForLoop)
statements += body.toFirStatement()
}
}
@@ -1477,12 +1484,12 @@ class RawFirBuilder(
session = baseSession, source = expression.loopParameter?.toFirSourceElement(),
name = if (multiDeclaration != null) Name.special("<destruct>") else ktParameter.nameAsSafeName,
initializer = buildFunctionCall {
source = loopSource
source = fakeSource
calleeReference = buildSimpleNamedReference {
source = loopSource
source = fakeSource
name = Name.identifier("next")
}
explicitReceiver = generateResolvedAccessExpression(loopSource, iteratorVal)
explicitReceiver = generateResolvedAccessExpression(fakeSource, iteratorVal)
},
typeRef = ktParameter.typeReference.toFirOrImplicitType(),
)
@@ -1659,7 +1666,7 @@ class RawFirBuilder(
else -> {
buildSimpleNamedReference {
source = defaultSource
source = defaultSource.withKind(FirFakeSourceElementKind.ImplicitInvokeCall)
name = OperatorNameConventions.INVOKE
} to calleeExpression.toFirExpression("Incorrect invoke receiver")
}
@@ -1746,7 +1753,7 @@ class RawFirBuilder(
val sourceElement = expression.toFirSourceElement()
source = sourceElement
calleeReference = buildExplicitThisReference {
source = sourceElement
source = sourceElement.withKind(FirFakeSourceElementKind.ExplicitThisOrSuperReference)
labelName = expression.getLabelName()
}
}
@@ -1758,7 +1765,7 @@ class RawFirBuilder(
return buildQualifiedAccessExpression {
this.source = source
calleeReference = buildExplicitSuperReference {
this.source
source.withKind(FirFakeSourceElementKind.ExplicitThisOrSuperReference)
labelName = expression.getLabelName()
superTypeRef = superType.toFirOrImplicitType()
}
@@ -1772,12 +1779,12 @@ class RawFirBuilder(
override fun visitLabeledExpression(expression: KtLabeledExpression, data: Unit): FirElement {
val sourceElement = expression.toFirSourceElement()
val labelName = expression.getLabelName()
val label = expression.getTargetLabel()
val size = context.firLabels.size
if (labelName != null) {
if (label != null) {
context.firLabels += buildLabel {
source = sourceElement
name = labelName
source = label.toFirPsiSourceElement()
name = label.getReferencedName()
}
}
val result = expression.baseExpression?.accept(this, data)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -8,8 +8,7 @@ package org.jetbrains.kotlin.fir.resolve
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
import org.jetbrains.kotlin.fir.expressions.*
@@ -31,7 +30,6 @@ import org.jetbrains.kotlin.fir.resolve.providers.bindSymbolToLookupTag
import org.jetbrains.kotlin.fir.resolve.providers.getSymbolByTypeRef
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.scopes.impl.FirDeclaredMemberScopeProvider
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.*
@@ -224,7 +222,7 @@ fun FirFunction<*>.constructFunctionalTypeRef(isSuspend: Boolean = false): FirRe
val functionalType = createFunctionalType(parameters, receiverTypeRef?.coneTypeSafe(), rawReturnType, isSuspend = isSuspend)
return buildResolvedTypeRef {
source = this@constructFunctionalTypeRef.source
source = this@constructFunctionalTypeRef.source?.withKind(FirFakeSourceElementKind.ImplicitTypeRef)
type = functionalType
this.isSuspend = isSuspend
}
@@ -327,7 +325,7 @@ fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirReso
return when (val newCallee = access.calleeReference) {
is FirErrorNamedReference ->
buildErrorTypeRef {
source = access.source
source = access.source?.withKind(FirFakeSourceElementKind.ErrorTypeRef)
diagnostic = ConeStubDiagnostic(newCallee.diagnostic)
}
is FirNamedReferenceWithCandidate -> {
@@ -392,7 +390,7 @@ fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(qualifiedAc
val intersectedType = ConeTypeIntersector.intersectTypes(inferenceComponents.ctx, allTypes)
// TODO: add check that intersectedType is not equal to original type
val intersectedTypeRef = buildResolvedTypeRef {
source = qualifiedAccessExpression.resultType.source
source = qualifiedAccessExpression.resultType.source?.withKind(FirFakeSourceElementKind.SmartCastedTypeRef)
type = intersectedType
annotations += qualifiedAccessExpression.resultType.annotations
}
@@ -1,11 +1,12 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.declarations.FirTypedDeclaration
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.*
@@ -99,7 +100,10 @@ internal fun FirTypedDeclaration.transformTypeToArrayType() {
val returnType = returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
transformReturnTypeRef(
StoreType,
returnTypeRef.withReplacedConeType(ConeKotlinTypeProjectionOut(returnType).createArrayOf())
returnTypeRef.withReplacedConeType(
ConeKotlinTypeProjectionOut(returnType).createArrayOf(),
FirFakeSourceElementKind.ArrayTypeFromVarargParameter
)
)
}
@@ -1,14 +1,12 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirElement
import org.jetbrains.kotlin.fir.FirFunctionTarget
import org.jetbrains.kotlin.fir.copy
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor
@@ -27,7 +25,6 @@ import org.jetbrains.kotlin.fir.resolve.inference.FirDelegatedPropertyInferenceS
import org.jetbrains.kotlin.fir.resolve.inference.extractLambdaInfoFromFunctionalType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.*
import org.jetbrains.kotlin.fir.resolvedTypeFromPrototype
import org.jetbrains.kotlin.fir.scopes.impl.FirLocalScope
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
import org.jetbrains.kotlin.fir.symbols.constructStarProjectedType
@@ -683,7 +680,7 @@ open class FirDeclarationsResolveTransformer(transformer: FirBodyResolveTransfor
override fun <E : FirElement> transformElement(element: E, data: FirExpression): CompositeTransformResult<E> {
if (element == lastStatement) {
val returnExpression = buildReturnExpression {
source = element.source
source = element.source?.withKind(FirFakeSourceElementKind.ImplicitReturn)
result = lastStatement
target = FirFunctionTarget(null, isLambda = this@addReturn.isLambda).also {
it.bind(this@addReturn)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -307,7 +307,7 @@ open class FirExpressionsResolveTransformer(transformer: FirBodyResolveTransform
val (leftArgument, rightArgument) = operatorCall.arguments
fun createFunctionCall(name: Name) = buildFunctionCall {
source = operatorCall.source
source = operatorCall.source?.withKind(FirFakeSourceElementKind.DesugaredCompoundAssignment)
explicitReceiver = leftArgument
argumentList = buildUnaryArgumentList(rightArgument)
calleeReference = buildSimpleNamedReference {
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirEffectiveVisibilityImpl
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.*
@@ -31,6 +32,7 @@ import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.withKind
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.Name
@@ -525,12 +527,12 @@ fun FirTypeRef.withReplacedReturnType(newType: ConeKotlinType?): FirTypeRef {
}
}
fun FirTypeRef.withReplacedConeType(newType: ConeKotlinType?): FirResolvedTypeRef {
fun FirTypeRef.withReplacedConeType(newType: ConeKotlinType?, sourceElementKind: FirFakeSourceElementKind? = null): FirResolvedTypeRef {
require(this is FirResolvedTypeRef)
if (newType == null) return this
return buildResolvedTypeRef {
source = this@withReplacedConeType.source
source = this@withReplacedConeType.source?.withKind(sourceElementKind)
type = newType
annotations += this@withReplacedConeType.annotations
}
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -32,12 +32,13 @@ private val VALUE = Name.identifier("value")
fun FirRegularClassBuilder.generateValuesFunction(
session: FirSession, packageFqName: FqName, classFqName: FqName, makeExpect: Boolean = false
) {
val sourceElement = source?.withKind(FirFakeSourceElementKind.EnumGeneratedDeclaration)
declarations += buildSimpleFunction {
source = this@generateValuesFunction.source
source = sourceElement
origin = FirDeclarationOrigin.Source
this.session = session
returnTypeRef = buildResolvedTypeRef {
source = this@generateValuesFunction.source
source = sourceElement
type = ConeClassLikeTypeImpl(
ConeClassLikeLookupTagImpl(StandardClassIds.Array),
arrayOf(
@@ -60,12 +61,13 @@ fun FirRegularClassBuilder.generateValuesFunction(
fun FirRegularClassBuilder.generateValueOfFunction(
session: FirSession, packageFqName: FqName, classFqName: FqName, makeExpect: Boolean = false
) {
val sourceElement = source?.withKind(FirFakeSourceElementKind.EnumGeneratedDeclaration)
declarations += buildSimpleFunction {
source = this@generateValueOfFunction.source
source = sourceElement
origin = FirDeclarationOrigin.Source
this.session = session
returnTypeRef = buildResolvedTypeRef {
source = this@generateValueOfFunction.source
source = sourceElement
type = ConeClassLikeTypeImpl(
this@generateValueOfFunction.symbol.toLookupTag(),
emptyArray(),
@@ -79,7 +81,7 @@ fun FirRegularClassBuilder.generateValueOfFunction(
}
symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, ENUM_VALUE_OF))
valueParameters += buildValueParameter vp@{
source = this@generateValueOfFunction.source
source = sourceElement
origin = FirDeclarationOrigin.Source
this@vp.session = session
returnTypeRef = FirImplicitStringTypeRef(source)
@@ -1,5 +1,5 @@
/*
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
@@ -10,13 +10,145 @@ import com.intellij.psi.PsiElement
import com.intellij.psi.tree.IElementType
import com.intellij.util.diff.FlyweightCapableTreeStructure
sealed class FirSourceElementKind
object FirRealSourceElementKind : FirSourceElementKind()
sealed class FirFakeSourceElementKind : FirSourceElementKind() {
// for some fir expression implicit return typeRef is generated
// some of them are: break, continue, return, throw, string concat,
// destruction parameters, function literals, explicitly boolean expressions
object ImplicitTypeRef : FirFakeSourceElementKind()
// for each class special class self type ref is created
// and have a fake source referencing it
object ClassSelfTypeRef : FirFakeSourceElementKind()
// FirErrorTypeRef may be built using unresolved firExpression
// and have a fake source referencing it
object ErrorTypeRef : FirFakeSourceElementKind()
// for properties without accessors default getter & setter are generated
// they have a fake source which refers to property
object DefaultAccessor : FirFakeSourceElementKind()
// for kt classes without implicit primary constructor one is generated
// with a fake source which refers to containing class
object ImplicitConstructor : FirFakeSourceElementKind()
// for constructors which do not have delegated constructor call the fake one is generated
// with a fake sources which refers to the original constructor
object DelegatingConstructorCall : FirFakeSourceElementKind()
// for enum entry with bodies the initializer in a form of anonymous object is generated
// with a fake sources which refers to the enum entry
object EnumInitializer : FirFakeSourceElementKind()
// for lambdas with implicit return the return statement is generated which is labeled
// with a fake sources which refers to the target expression
object GeneratedLambdaLabel : FirFakeSourceElementKind()
// for lambdas & functions with expression bodies the return statement is added
// with a fake sources which refers to the return target
object ImplicitReturn : FirFakeSourceElementKind()
// return expression in procedures -> return Unit
// with a fake sources which refers to the return statement
object ImplicitUnit : FirFakeSourceElementKind()
// delegates are wrapped into FirWrappedDelegateExpression
// with a fake sources which refers to delegated expression
object WrappedDelegate : FirFakeSourceElementKind()
// `for (i in list) { println(i) }` is converted to
// ```
// val <iterator>: = list.iterator()
// while(<iterator>.hasNext()) {
// val i = <iterator>.next()
// println(i)
// }
// ```
// where the generated WHILE loop has source element of initial FOR loop,
// other generated elements are marked as fake ones
object DesugaredForLoop : FirFakeSourceElementKind()
object ImplicitInvokeCall : FirFakeSourceElementKind()
// this/super expressions have FirThisReference/FirSuperReference
// with a fake sources which refers to this this/super expression
object ExplicitThisOrSuperReference : FirFakeSourceElementKind()
// for enum classes we have valueOf & values functions generated
// with a fake sources which refers to this the enum class
object EnumGeneratedDeclaration : FirFakeSourceElementKind()
// when (x) { "abc" -> 42 } --> when(val $subj = x) { $subj == "abc" -> 42 }
// where $subj == "42" has fake psi source which refers to "42" as inner expression
// and $subj fake source refers to "42" as KtWhenCondition
object WhenCondition : FirFakeSourceElementKind()
// for primary constructor parameter the corresponding class property is generated
// with a fake sources which refers to this the corresponding parameter
object PropertyFromParameter : FirFakeSourceElementKind()
// if (true) 1 --> if(true) { 1 }
// with a fake sources for the block which refers to the wrapped expression
object SingleExpressionBlock : FirFakeSourceElementKind()
// x++ -> x = x.inc()
// x = x++ -> x = { val <unary> = x; x = <unary>.inc(); <unary> }
object DesugaredIncrementOrDecrement : FirFakeSourceElementKind()
// x !in list --> !(x in list) where ! and !(x in list) will have a fake source
object DesugaredInvertedContains : FirFakeSourceElementKind()
// for data classes fir generates componentN() & copy() functions
// for componentN() functions the source will refer to the corresponding param and will be marked as a fake one
// for copy() functions the source will refer class to the param and will be marked as a fake one
object DataClassGeneratedMembers : FirFakeSourceElementKind()
// (vararg x: Int) --> (x: Array<out Int>) where array type ref has a fake source kind
object ArrayTypeFromVarargParameter : FirFakeSourceElementKind()
// val (a,b) = x --> val a = x.component1(); val b = x.component2()
// where componentN calls will have the fake source elements refer to the corresponding KtDestructuringDeclarationEntry
object DesugaredComponentFunctionCall : FirFakeSourceElementKind()
// when smart casts applied to the expression, its wrapped into FirExpressionWithSmartcast
// which type reference will have a fake source refer to a original source element of it
object SmartCastedTypeRef : FirFakeSourceElementKind()
// for safe call expressions like a?.foo() the FirSafeCallExpression is generated
// and it have a fake source
object DesugaredSafeCallExpression : FirFakeSourceElementKind()
// a += 2 --> a = a + 2
// where a + 2 will have a fake source
object DesugaredCompoundAssignment : FirFakeSourceElementKind()
//"$a" --> a.toString() where toString call source is marked as a fake one
object GeneratedToStringCallOnTemplateEntry : FirFakeSourceElementKind()
// `a > b` will be wrapped in FirComparisonExpression
// with real source which points to initial `a > b` expression
// and inner FirFunctionCall will refer to a fake source
object GeneratedCompararisonExpression : FirFakeSourceElementKind()
// a ?: b --> when(val $subj = a) { .... }
// where `val $subj = a` has a fake source
object WhenGeneratedSubject : FirFakeSourceElementKind()
}
sealed class FirSourceElement {
abstract val elementType: IElementType
abstract val startOffset: Int
abstract val endOffset: Int
abstract val kind: FirSourceElementKind
}
class FirPsiSourceElement<out P : PsiElement>(val psi: P) : FirSourceElement() {
sealed class FirPsiSourceElement<out P : PsiElement>(val psi: P) : FirSourceElement() {
override val elementType: IElementType
get() = psi.node.elementType
@@ -27,6 +159,24 @@ class FirPsiSourceElement<out P : PsiElement>(val psi: P) : FirSourceElement() {
get() = psi.textRange.endOffset
}
class FirRealPsiSourceElement<out P : PsiElement>(psi: P) : FirPsiSourceElement<P>(psi) {
override val kind: FirSourceElementKind get() = FirRealSourceElementKind
}
class FirFakeSourceElement<out P : PsiElement>(psi: P, override val kind: FirFakeSourceElementKind) : FirPsiSourceElement<P>(psi)
fun FirSourceElement.withKind(newKind: FirSourceElementKind?): FirSourceElement {
if (newKind == null) return this
return when (this) {
is FirLightSourceElement -> this
is FirPsiSourceElement<*> -> when (newKind) {
kind -> this
FirRealSourceElementKind -> FirRealPsiSourceElement(psi)
is FirFakeSourceElementKind -> FirFakeSourceElement(psi, newKind)
}
}
}
class FirLightSourceElement(
val element: LighterASTNode,
override val startOffset: Int,
@@ -35,14 +185,20 @@ class FirLightSourceElement(
) : FirSourceElement() {
override val elementType: IElementType
get() = element.tokenType
override val kind: FirSourceElementKind get() = FirRealSourceElementKind
}
val FirSourceElement?.psi: PsiElement? get() = (this as? FirPsiSourceElement<*>)?.psi
val FirElement.psi: PsiElement? get() = (source as? FirPsiSourceElement<*>)?.psi
val FirElement.realPsi: PsiElement? get() = (source as? FirRealPsiSourceElement<*>)?.psi
@Suppress("NOTHING_TO_INLINE")
inline fun PsiElement.toFirPsiSourceElement(): FirPsiSourceElement<*> = FirPsiSourceElement(this)
inline fun PsiElement.toFirPsiSourceElement(kind: FirSourceElementKind = FirRealSourceElementKind): FirPsiSourceElement<*> = when (kind) {
is FirRealSourceElementKind -> FirRealPsiSourceElement(this)
is FirFakeSourceElementKind -> FirFakeSourceElement(this, kind)
}
@Suppress("NOTHING_TO_INLINE")
inline fun LighterASTNode.toFirLightSourceElement(