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. * 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.references.builder.*
import org.jetbrains.kotlin.fir.symbols.CallableId import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.* import org.jetbrains.kotlin.fir.symbols.impl.*
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef import org.jetbrains.kotlin.fir.types.builder.*
import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl import org.jetbrains.kotlin.fir.types.impl.ConeClassLikeTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl 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.CLOSING_QUOTE
import org.jetbrains.kotlin.lexer.KtTokens.OPEN_QUOTE import org.jetbrains.kotlin.lexer.KtTokens.OPEN_QUOTE
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
@@ -35,7 +36,7 @@ import org.jetbrains.kotlin.util.OperatorNameConventions
//T can be either PsiElement, or LighterASTNode //T can be either PsiElement, or LighterASTNode
abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Context<T> = Context()) { 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 implicitUnitType = baseSession.builtinTypes.unitType
protected val implicitAnyType = baseSession.builtinTypes.anyType 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 { private fun T?.toDelegatedSelfType(firClass: FirClassBuilder, symbol: FirClassLikeSymbol<*>): FirResolvedTypeRef {
return buildResolvedTypeRef { return buildResolvedTypeRef {
source = this@toDelegatedSelfType?.toFirSourceElement() source = this@toDelegatedSelfType?.toFirSourceElement(FirFakeSourceElementKind.ClassSelfTypeRef)
type = ConeClassLikeTypeImpl( type = ConeClassLikeTypeImpl(
symbol.toLookupTag(), symbol.toLookupTag(),
firClass.typeParameters.map { ConeTypeParameterTypeImpl(it.symbol.toLookupTag(), false) }.toTypedArray(), 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 -> { SHORT_STRING_TEMPLATE_ENTRY, LONG_STRING_TEMPLATE_ENTRY -> {
hasExpressions = true hasExpressions = true
val firExpression = entry.convertTemplateEntry("Incorrect template argument") val firExpression = entry.convertTemplateEntry("Incorrect template argument")
val source = firExpression.source val source = firExpression.source?.withKind(FirFakeSourceElementKind.GeneratedToStringCallOnTemplateEntry)
buildFunctionCall { buildFunctionCall {
this.source = source this.source = source
explicitReceiver = firExpression explicitReceiver = firExpression
@@ -402,22 +403,28 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
} }
return buildBlock { return buildBlock {
val baseSource = baseExpression?.toFirSourceElement() val baseSource = baseExpression?.toFirSourceElement()
source = baseSource val desugaredSource = baseSource?.withKind(FirFakeSourceElementKind.DesugaredIncrementOrDecrement)
source = desugaredSource
val tempName = Name.special("<unary>") 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 statements += temporaryVariable
val resultName = Name.special("<unary-result>") val resultName = Name.special("<unary-result>")
val resultInitializer = buildFunctionCall { val resultInitializer = buildFunctionCall {
source = baseSource source = desugaredSource
calleeReference = buildSimpleNamedReference { calleeReference = buildSimpleNamedReference {
source = operationReference?.toFirSourceElement() source = operationReference?.toFirSourceElement()
name = callName 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( val assignment = argument.generateAssignment(
source, desugaredSource,
argument, argument,
if (prefix && argument.elementType != REFERENCE_EXPRESSION) if (prefix && argument.elementType != REFERENCE_EXPRESSION)
generateResolvedAccessExpression(source, resultVar) generateResolvedAccessExpression(source, resultVar)
@@ -438,14 +445,14 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
if (argument.elementType != REFERENCE_EXPRESSION) { if (argument.elementType != REFERENCE_EXPRESSION) {
statements += resultVar statements += resultVar
appendAssignment() appendAssignment()
statements += generateResolvedAccessExpression(source, resultVar) statements += generateResolvedAccessExpression(desugaredSource, resultVar)
} else { } else {
appendAssignment() appendAssignment()
statements += generateAccessExpression(source, argument.getReferencedNameAsName()) statements += generateAccessExpression(desugaredSource, argument.getReferencedNameAsName())
} }
} else { } else {
appendAssignment() appendAssignment()
statements += generateResolvedAccessExpression(source, temporaryVariable) statements += generateResolvedAccessExpression(desugaredSource, temporaryVariable)
} }
} }
} }
@@ -728,7 +735,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
componentIndex++ componentIndex++
val parameterSource = sourceNode?.toFirSourceElement() val parameterSource = sourceNode?.toFirSourceElement()
val componentFunction = buildSimpleFunction { val componentFunction = buildSimpleFunction {
source = parameterSource source = parameterSource?.withKind(FirFakeSourceElementKind.DataClassGeneratedMembers)
session = this@DataClassMembersGenerator.session session = this@DataClassMembersGenerator.session
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
returnTypeRef = firProperty.returnTypeRef returnTypeRef = firProperty.returnTypeRef
@@ -762,7 +769,7 @@ abstract class BaseFirBuilder<T>(val baseSession: FirSession, val context: Conte
source = parameterSource source = parameterSource
session = this@DataClassMembersGenerator.session session = this@DataClassMembersGenerator.session
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
returnTypeRef = firProperty.returnTypeRef returnTypeRef = propertyReturnTypeRef
name = propertyName name = propertyName
symbol = FirVariableSymbol(propertyName) symbol = FirVariableSymbol(propertyName)
defaultValue = generateComponentAccess(parameterSource, firProperty) 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. * 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 package org.jetbrains.kotlin.fir.builder
import kotlinx.collections.immutable.persistentListOf import kotlinx.collections.immutable.persistentListOf
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirFunctionTarget import org.jetbrains.kotlin.fir.FirFunctionTarget
import org.jetbrains.kotlin.fir.FirLabel import org.jetbrains.kotlin.fir.FirLabel
import org.jetbrains.kotlin.fir.FirLoopTarget 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. * 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.FirPropertyAccessorSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol import org.jetbrains.kotlin.fir.symbols.impl.FirVariableSymbol
import org.jetbrains.kotlin.fir.types.ConeStarProjection import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.FirTypeRef import org.jetbrains.kotlin.fir.types.builder.*
import org.jetbrains.kotlin.fir.types.builder.buildImplicitTypeRef
import org.jetbrains.kotlin.fir.types.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.impl.* import org.jetbrains.kotlin.fir.types.impl.*
import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
@@ -146,12 +144,13 @@ fun FirExpression.generateNotNullOrOther(
session: FirSession, other: FirExpression, caseId: String, baseSource: FirSourceElement?, session: FirSession, other: FirExpression, caseId: String, baseSource: FirSourceElement?,
): FirWhenExpression { ): FirWhenExpression {
val subjectName = Name.special("<$caseId>") 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) @OptIn(FirContractViolation::class)
val ref = FirExpressionRef<FirWhenExpression>() val ref = FirExpressionRef<FirWhenExpression>()
val subjectExpression = buildWhenSubjectExpression { val subjectExpression = buildWhenSubjectExpression {
source = baseSource source = subjectSource
whenRef = ref whenRef = ref
} }
@@ -160,22 +159,24 @@ fun FirExpression.generateNotNullOrOther(
this.subject = this@generateNotNullOrOther this.subject = this@generateNotNullOrOther
this.subjectVariable = subjectVariable this.subjectVariable = subjectVariable
branches += buildWhenBranch { branches += buildWhenBranch {
source = baseSource val branchSource = baseSource?.withKind(FirFakeSourceElementKind.WhenCondition)
source = branchSource
condition = buildOperatorCall { condition = buildOperatorCall {
source = baseSource source = branchSource
operation = FirOperation.EQ operation = FirOperation.EQ
argumentList = buildBinaryArgumentList( argumentList = buildBinaryArgumentList(
subjectExpression, buildConstExpression(baseSource, FirConstKind.Null, null) subjectExpression, buildConstExpression(branchSource, FirConstKind.Null, null)
) )
} }
result = buildSingleExpressionBlock(other) result = buildSingleExpressionBlock(other)
} }
branches += buildWhenBranch { branches += buildWhenBranch {
source = other.source val otherSource = other.source?.withKind(FirFakeSourceElementKind.WhenCondition)
source = otherSource
condition = buildElseIfTrueCondition { condition = buildElseIfTrueCondition {
source = baseSource source = otherSource
} }
result = buildSingleExpressionBlock(generateResolvedAccessExpression(baseSource, subjectVariable)) result = buildSingleExpressionBlock(generateResolvedAccessExpression(otherSource, subjectVariable))
} }
}.also { }.also {
ref.bind(it) ref.bind(it)
@@ -203,9 +204,9 @@ fun FirExpression.generateContainsOperation(
if (!inverted) return containsCall if (!inverted) return containsCall
return buildFunctionCall { return buildFunctionCall {
source = baseSource source = baseSource?.withKind(FirFakeSourceElementKind.DesugaredInvertedContains)
calleeReference = buildSimpleNamedReference { calleeReference = buildSimpleNamedReference {
source = operationReferenceSource source = operationReferenceSource?.withKind(FirFakeSourceElementKind.DesugaredInvertedContains)
name = OperatorNameConventions.NOT name = OperatorNameConventions.NOT
} }
explicitReceiver = containsCall explicitReceiver = containsCall
@@ -222,7 +223,12 @@ fun FirExpression.generateComparisonExpression(
"$operatorToken is not in ${OperatorConventions.COMPARISON_OPERATIONS}" "$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) { val firOperation = when (operatorToken) {
KtTokens.LT -> FirOperation.LT KtTokens.LT -> FirOperation.LT
@@ -511,6 +517,6 @@ fun FirModifiableQualifiedAccess.wrapWithSafeCall(receiver: FirExpression): FirS
bind(checkedSafeCallSubject) bind(checkedSafeCallSubject)
} }
this.regularQualifiedAccess = this@wrapWithSafeCall 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. * 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.KtNodeTypes
import org.jetbrains.kotlin.fir.FirLightSourceElement import org.jetbrains.kotlin.fir.FirLightSourceElement
import org.jetbrains.kotlin.fir.FirSession 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.BaseFirBuilder
import org.jetbrains.kotlin.fir.builder.Context import org.jetbrains.kotlin.fir.builder.Context
import org.jetbrains.kotlin.fir.builder.escapedStringToCharacter import org.jetbrains.kotlin.fir.builder.escapedStringToCharacter
@@ -30,7 +31,7 @@ open class BaseConverter(
) : BaseFirBuilder<LighterASTNode>(baseSession, context) { ) : BaseFirBuilder<LighterASTNode>(baseSession, context) {
protected val implicitType = buildImplicitTypeRef() protected val implicitType = buildImplicitTypeRef()
override fun LighterASTNode.toFirSourceElement(): FirLightSourceElement { override fun LighterASTNode.toFirSourceElement(kind: FirSourceElementKind): FirLightSourceElement {
val startOffset = offset + tree.getStartOffset(this) val startOffset = offset + tree.getStartOffset(this)
val endOffset = offset + tree.getEndOffset(this) val endOffset = offset + tree.getEndOffset(this)
return toFirLightSourceElement(startOffset, endOffset, tree) 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.Modality
import org.jetbrains.kotlin.descriptors.Visibilities import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirExpressionRef import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin import org.jetbrains.kotlin.fir.declarations.FirDeclarationOrigin
import org.jetbrains.kotlin.fir.declarations.FirVariable import org.jetbrains.kotlin.fir.declarations.FirVariable
import org.jetbrains.kotlin.fir.declarations.builder.buildProperty 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.*
import org.jetbrains.kotlin.fir.expressions.builder.* import org.jetbrains.kotlin.fir.expressions.builder.*
import org.jetbrains.kotlin.fir.symbols.impl.FirPropertySymbol 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.fir.types.FirTypeRef
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
@@ -28,15 +25,15 @@ internal fun KtWhenCondition.toFirWhenCondition(
convert: KtExpression?.(String) -> FirExpression, convert: KtExpression?.(String) -> FirExpression,
toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef, toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef,
): FirExpression { ): FirExpression {
val baseSource = this.toFirPsiSourceElement() val firSubjectSource = this.toFirPsiSourceElement(FirFakeSourceElementKind.WhenGeneratedSubject)
val firSubjectExpression = buildWhenSubjectExpression { val firSubjectExpression = buildWhenSubjectExpression {
source = baseSource source = firSubjectSource
whenRef = whenRefWithSibject whenRef = whenRefWithSibject
} }
return when (this) { return when (this) {
is KtWhenConditionWithExpression -> { is KtWhenConditionWithExpression -> {
buildOperatorCall { buildOperatorCall {
source = expression?.toFirPsiSourceElement() source = expression?.toFirPsiSourceElement(FirFakeSourceElementKind.WhenCondition)
operation = FirOperation.EQ operation = FirOperation.EQ
argumentList = buildBinaryArgumentList( argumentList = buildBinaryArgumentList(
firSubjectExpression, expression.convert("No expression in condition with expression") firSubjectExpression, expression.convert("No expression in condition with expression")
@@ -48,26 +45,25 @@ internal fun KtWhenCondition.toFirWhenCondition(
firRange.generateContainsOperation( firRange.generateContainsOperation(
firSubjectExpression, firSubjectExpression,
isNegated, isNegated,
rangeExpression?.toFirPsiSourceElement(), rangeExpression?.toFirPsiSourceElement(FirFakeSourceElementKind.WhenCondition),
operationReference.toFirPsiSourceElement() operationReference.toFirPsiSourceElement()
) )
} }
is KtWhenConditionIsPattern -> { is KtWhenConditionIsPattern -> {
buildTypeOperatorCall { buildTypeOperatorCall {
source = typeReference?.toFirPsiSourceElement() source = this@toFirWhenCondition.toFirPsiSourceElement()
operation = if (isNegated) FirOperation.NOT_IS else FirOperation.IS operation = if (isNegated) FirOperation.NOT_IS else FirOperation.IS
conversionTypeRef = typeReference.toFirOrErrorTypeRef() conversionTypeRef = typeReference.toFirOrErrorTypeRef()
argumentList = buildUnaryArgumentList(firSubjectExpression) argumentList = buildUnaryArgumentList(firSubjectExpression)
} }
} }
else -> { 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( internal fun Array<KtWhenCondition>.toFirWhenCondition(
baseSource: FirSourceElement?,
subject: FirExpressionRef<FirWhenExpression>, subject: FirExpressionRef<FirWhenExpression>,
convert: KtExpression?.(String) -> FirExpression, convert: KtExpression?.(String) -> FirExpression,
toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef, toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef,
@@ -78,7 +74,7 @@ internal fun Array<KtWhenCondition>.toFirWhenCondition(
firCondition = when (firCondition) { firCondition = when (firCondition) {
null -> firConditionElement null -> firConditionElement
else -> firCondition.generateLazyLogicalOperation( else -> firCondition.generateLazyLogicalOperation(
firConditionElement, false, baseSource, firConditionElement, false, condition.toFirPsiSourceElement(FirFakeSourceElementKind.WhenCondition),
) )
} }
} }
@@ -109,8 +105,9 @@ internal fun generateDestructuringBlock(
returnTypeRef = entry.typeReference.toFirOrImplicitTypeRef() returnTypeRef = entry.typeReference.toFirOrImplicitTypeRef()
this.name = name this.name = name
initializer = buildComponentCall { initializer = buildComponentCall {
source = entrySource val componentCallSource = entrySource.withKind(FirFakeSourceElementKind.DesugaredComponentFunctionCall)
explicitReceiver = generateResolvedAccessExpression(entrySource, container) source = componentCallSource
explicitReceiver = generateResolvedAccessExpression(componentCallSource, container)
componentIndex = index + 1 componentIndex = index + 1
} }
this.isVar = isVar this.isVar = isVar
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.types.expressions.OperatorConventions import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.util.OperatorNameConventions import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
import java.util.*
import org.jetbrains.kotlin.utils.addToStdlib.runIf import org.jetbrains.kotlin.utils.addToStdlib.runIf
import kotlin.collections.contains import kotlin.collections.contains
@@ -61,8 +62,8 @@ class RawFirBuilder(
return reference.accept(Visitor(), Unit) as FirTypeRef return reference.accept(Visitor(), Unit) as FirTypeRef
} }
override fun PsiElement.toFirSourceElement(): FirPsiSourceElement<*> { override fun PsiElement.toFirSourceElement(kind: FirSourceElementKind): FirPsiSourceElement<*> {
return this.toFirPsiSourceElement() return this.toFirPsiSourceElement(kind)
} }
override val PsiElement.elementType: IElementType override val PsiElement.elementType: IElementType
@@ -128,7 +129,7 @@ class RawFirBuilder(
private fun KtTypeReference?.toFirOrImplicitType(): FirTypeRef = private fun KtTypeReference?.toFirOrImplicitType(): FirTypeRef =
convertSafe() ?: buildImplicitTypeRef { convertSafe() ?: buildImplicitTypeRef {
source = this@toFirOrImplicitType?.toFirSourceElement() source = this@toFirOrImplicitType?.toFirSourceElement(FirFakeSourceElementKind.ImplicitTypeRef)
} }
private fun KtTypeReference?.toFirOrUnitType(): FirTypeRef = private fun KtTypeReference?.toFirOrUnitType(): FirTypeRef =
@@ -272,7 +273,9 @@ class RawFirBuilder(
this@toFirPropertyAccessor?.hasModifier(EXTERNAL_KEYWORD) == true this@toFirPropertyAccessor?.hasModifier(EXTERNAL_KEYWORD) == true
} }
if (this == null || !hasBody()) { if (this == null || !hasBody()) {
val propertySource = property.toFirSourceElement() val propertySource =
if (this != null && hasBody()) property.toFirSourceElement()
else property.toFirPsiSourceElement(FirFakeSourceElementKind.DefaultAccessor)
return FirDefaultPropertyAccessor return FirDefaultPropertyAccessor
.createGetterOrSetter( .createGetterOrSetter(
propertySource, propertySource,
@@ -307,7 +310,7 @@ class RawFirBuilder(
extractValueParametersTo(this, propertyTypeRef) extractValueParametersTo(this, propertyTypeRef)
if (!isGetter && valueParameters.isEmpty()) { if (!isGetter && valueParameters.isEmpty()) {
valueParameters += buildDefaultSetterValueParameter { valueParameters += buildDefaultSetterValueParameter {
this.source = source this.source = source.withKind(FirFakeSourceElementKind.DefaultAccessor)
session = baseSession session = baseSession
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
returnTypeRef = propertyTypeRef returnTypeRef = propertyTypeRef
@@ -359,18 +362,17 @@ class RawFirBuilder(
isConst = false isConst = false
isLateInit = false isLateInit = false
} }
val parameterSource = this.toFirSourceElement() val propertySource = toFirSourceElement(FirFakeSourceElementKind.PropertyFromParameter)
val propertySource = this@toFirProperty.toFirSourceElement()
val propertyName = nameAsSafeName val propertyName = nameAsSafeName
return buildProperty { return buildProperty {
source = parameterSource source = propertySource
session = baseSession session = baseSession
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
returnTypeRef = type returnTypeRef = type
receiverTypeRef = null receiverTypeRef = null
name = propertyName name = propertyName
initializer = buildQualifiedAccessExpression { initializer = buildQualifiedAccessExpression {
source = parameterSource source = propertySource
calleeReference = buildPropertyFromParameterResolvedNamedReference { calleeReference = buildPropertyFromParameterResolvedNamedReference {
source = propertySource source = propertySource
name = propertyName name = propertyName
@@ -381,9 +383,10 @@ class RawFirBuilder(
symbol = FirPropertySymbol(callableIdForName(propertyName)) symbol = FirPropertySymbol(callableIdForName(propertyName))
isLocal = false isLocal = false
this.status = status 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( setter = if (isMutable) FirDefaultPropertySetter(
propertySource, defaultAccessorSource,
baseSession, baseSession,
FirDeclarationOrigin.Source, FirDeclarationOrigin.Source,
type, type,
@@ -536,9 +539,10 @@ class RawFirBuilder(
ownerTypeParameters: List<FirTypeParameterRef> ownerTypeParameters: List<FirTypeParameterRef>
): FirConstructor { ): FirConstructor {
val constructorCallee = superTypeCallEntry?.calleeExpression?.toFirSourceElement() val constructorCallee = superTypeCallEntry?.calleeExpression?.toFirSourceElement()
val constructorSource = (this ?: owner).toFirSourceElement() val constructorSource = this?.toFirSourceElement()
?: owner.toFirPsiSourceElement(FirFakeSourceElementKind.ImplicitConstructor)
val firDelegatedCall = buildDelegatedConstructorCall { val firDelegatedCall = buildDelegatedConstructorCall {
source = constructorCallee ?: constructorSource source = constructorCallee ?: constructorSource.withKind(FirFakeSourceElementKind.DelegatingConstructorCall)
constructedTypeRef = delegatedSuperTypeRef constructedTypeRef = delegatedSuperTypeRef
isThis = false isThis = false
if (!stubMode) { if (!stubMode) {
@@ -624,7 +628,7 @@ class RawFirBuilder(
} }
initializer = withChildClassName(nameAsSafeName) { initializer = withChildClassName(nameAsSafeName) {
buildAnonymousObject { buildAnonymousObject {
source = toFirSourceElement() source = toFirSourceElement(FirFakeSourceElementKind.EnumInitializer)
session = baseSession session = baseSession
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
classKind = ClassKind.ENUM_ENTRY classKind = ClassKind.ENUM_ENTRY
@@ -897,11 +901,12 @@ class RawFirBuilder(
override fun visitLambdaExpression(expression: KtLambdaExpression, data: Unit): FirElement { override fun visitLambdaExpression(expression: KtLambdaExpression, data: Unit): FirElement {
val literal = expression.functionLiteral val literal = expression.functionLiteral
val literalSource = literal.toFirSourceElement() val literalSource = literal.toFirSourceElement()
val implicitTypeRefSource = literal.toFirSourceElement(FirFakeSourceElementKind.ImplicitTypeRef)
val returnType = buildImplicitTypeRef { val returnType = buildImplicitTypeRef {
source = literalSource source = implicitTypeRefSource
} }
val receiverType = buildImplicitTypeRef { val receiverType = buildImplicitTypeRef {
source = literalSource source = implicitTypeRefSource
} }
val target: FirFunctionTarget val target: FirFunctionTarget
@@ -924,7 +929,7 @@ class RawFirBuilder(
session = baseSession session = baseSession
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
returnTypeRef = buildImplicitTypeRef { returnTypeRef = buildImplicitTypeRef {
source = multiDeclaration.toFirSourceElement() source = multiDeclaration.toFirSourceElement(FirFakeSourceElementKind.ImplicitTypeRef)
} }
this.name = name this.name = name
symbol = FirVariableSymbol(name) symbol = FirVariableSymbol(name)
@@ -942,7 +947,7 @@ class RawFirBuilder(
multiParameter multiParameter
} else { } else {
val typeRef = buildImplicitTypeRef { val typeRef = buildImplicitTypeRef {
source = this@buildAnonymousFunction.source source = implicitTypeRefSource
} }
valueParameter.toFirValueParameter(typeRef) valueParameter.toFirValueParameter(typeRef)
} }
@@ -950,7 +955,7 @@ class RawFirBuilder(
val expressionSource = expression.toFirSourceElement() val expressionSource = expression.toFirSourceElement()
label = context.firLabels.pop() ?: context.calleeNamesForLambda.lastOrNull()?.let { label = context.firLabels.pop() ?: context.calleeNamesForLambda.lastOrNull()?.let {
buildLabel { buildLabel {
source = expressionSource source = expressionSource.withKind(FirFakeSourceElementKind.GeneratedLambdaLabel)
name = it.asString() name = it.asString()
} }
} }
@@ -966,9 +971,11 @@ class RawFirBuilder(
if (statements.isEmpty()) { if (statements.isEmpty()) {
statements.add( statements.add(
buildReturnExpression { buildReturnExpression {
source = expressionSource source = expressionSource.withKind(FirFakeSourceElementKind.ImplicitReturn)
this.target = target this.target = target
result = buildUnitExpression { source = expressionSource } result = buildUnitExpression {
source = expressionSource.withKind(FirFakeSourceElementKind.ImplicitUnit)
}
} }
) )
} }
@@ -1070,7 +1077,7 @@ class RawFirBuilder(
symbol = FirPropertySymbol(propertyName) symbol = FirPropertySymbol(propertyName)
val delegateBuilder = delegateExpression?.let { val delegateBuilder = delegateExpression?.let {
FirWrappedDelegateExpressionBuilder().apply { FirWrappedDelegateExpressionBuilder().apply {
source = it.toFirSourceElement() source = it.toFirSourceElement(FirFakeSourceElementKind.WrappedDelegate)
expression = it.toFirExpression("Incorrect delegate expression") expression = it.toFirExpression("Incorrect delegate expression")
} }
} }
@@ -1090,7 +1097,8 @@ class RawFirBuilder(
addCapturedTypeParameters(this.typeParameters) addCapturedTypeParameters(this.typeParameters)
val delegateBuilder = if (hasDelegate()) { val delegateBuilder = if (hasDelegate()) {
FirWrappedDelegateExpressionBuilder().apply { FirWrappedDelegateExpressionBuilder().apply {
source = if (stubMode) null else delegateExpression?.toFirSourceElement() source =
if (stubMode) null else delegateExpression?.toFirSourceElement(FirFakeSourceElementKind.WrappedDelegate)
expression = { delegateExpression }.toFirExpression("Should have delegate") expression = { delegateExpression }.toFirExpression("Should have delegate")
} }
} else null } else null
@@ -1305,7 +1313,7 @@ class RawFirBuilder(
} }
override fun visitReturnExpression(expression: KtReturnExpression, data: Unit): FirElement { 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") val result = expression.returnedExpression?.toFirExpression("Incorrect return expression")
?: buildUnitExpression { this.source = source } ?: buildUnitExpression { this.source = source }
return result.toReturn(source, expression.getTargetLabel()?.getReferencedName()) return result.toReturn(source, expression.getTargetLabel()?.getReferencedName())
@@ -1332,7 +1340,7 @@ class RawFirBuilder(
source = expression.toFirSourceElement() source = expression.toFirSourceElement()
val ktCondition = expression.condition val ktCondition = expression.condition
branches += buildWhenBranch { branches += buildWhenBranch {
source = ktCondition?.toFirSourceElement() source = ktCondition?.toFirSourceElement(FirFakeSourceElementKind.WhenCondition)
condition = ktCondition.toFirExpression("If statement should have condition") condition = ktCondition.toFirExpression("If statement should have condition")
result = expression.then.toFirBlock() result = expression.then.toFirBlock()
} }
@@ -1388,7 +1396,6 @@ class RawFirBuilder(
buildWhenBranch { buildWhenBranch {
source = entrySource source = entrySource
condition = entry.conditions.toFirWhenCondition( condition = entry.conditions.toFirWhenCondition(
entrySource,
ref, ref,
{ toFirExpression(it) }, { toFirExpression(it) },
{ toFirOrErrorType() }, { toFirOrErrorType() },
@@ -1435,16 +1442,16 @@ class RawFirBuilder(
override fun visitForExpression(expression: KtForExpression, data: Unit?): FirElement { override fun visitForExpression(expression: KtForExpression, data: Unit?): FirElement {
val rangeExpression = expression.loopRange.toFirExpression("No range in for loop") val rangeExpression = expression.loopRange.toFirExpression("No range in for loop")
val ktParameter = expression.loopParameter val ktParameter = expression.loopParameter
val loopSource = expression.toFirSourceElement() val fakeSource = expression.toFirPsiSourceElement(FirFakeSourceElementKind.DesugaredForLoop)
return buildBlock { return buildBlock {
source = loopSource source = fakeSource
val rangeSource = expression.loopRange?.toFirSourceElement() val rangeSource = expression.loopRange?.toFirSourceElement(FirFakeSourceElementKind.DesugaredForLoop)
val iteratorVal = generateTemporaryVariable( val iteratorVal = generateTemporaryVariable(
baseSession, rangeSource, Name.special("<iterator>"), baseSession, rangeSource, Name.special("<iterator>"),
buildFunctionCall { buildFunctionCall {
source = loopSource source = fakeSource
calleeReference = buildSimpleNamedReference { calleeReference = buildSimpleNamedReference {
source = loopSource source = fakeSource
name = Name.identifier("iterator") name = Name.identifier("iterator")
} }
explicitReceiver = rangeExpression explicitReceiver = rangeExpression
@@ -1452,14 +1459,14 @@ class RawFirBuilder(
) )
statements += iteratorVal statements += iteratorVal
statements += FirWhileLoopBuilder().apply { statements += FirWhileLoopBuilder().apply {
source = loopSource source = expression.toFirSourceElement()
condition = buildFunctionCall { condition = buildFunctionCall {
source = loopSource source = fakeSource
calleeReference = buildSimpleNamedReference { calleeReference = buildSimpleNamedReference {
source = loopSource source = fakeSource
name = Name.identifier("hasNext") name = Name.identifier("hasNext")
} }
explicitReceiver = generateResolvedAccessExpression(loopSource, iteratorVal) explicitReceiver = generateResolvedAccessExpression(fakeSource, iteratorVal)
} }
}.configure { }.configure {
// NB: just body.toFirBlock() isn't acceptable here because we need to add some statements // 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) is KtBlockExpression -> configureBlockWithoutBuilding(body)
null -> FirBlockBuilder() null -> FirBlockBuilder()
else -> FirBlockBuilder().apply { else -> FirBlockBuilder().apply {
source = body.toFirSourceElement() source = body.toFirSourceElement(FirFakeSourceElementKind.DesugaredForLoop)
statements += body.toFirStatement() statements += body.toFirStatement()
} }
} }
@@ -1477,12 +1484,12 @@ class RawFirBuilder(
session = baseSession, source = expression.loopParameter?.toFirSourceElement(), session = baseSession, source = expression.loopParameter?.toFirSourceElement(),
name = if (multiDeclaration != null) Name.special("<destruct>") else ktParameter.nameAsSafeName, name = if (multiDeclaration != null) Name.special("<destruct>") else ktParameter.nameAsSafeName,
initializer = buildFunctionCall { initializer = buildFunctionCall {
source = loopSource source = fakeSource
calleeReference = buildSimpleNamedReference { calleeReference = buildSimpleNamedReference {
source = loopSource source = fakeSource
name = Name.identifier("next") name = Name.identifier("next")
} }
explicitReceiver = generateResolvedAccessExpression(loopSource, iteratorVal) explicitReceiver = generateResolvedAccessExpression(fakeSource, iteratorVal)
}, },
typeRef = ktParameter.typeReference.toFirOrImplicitType(), typeRef = ktParameter.typeReference.toFirOrImplicitType(),
) )
@@ -1659,7 +1666,7 @@ class RawFirBuilder(
else -> { else -> {
buildSimpleNamedReference { buildSimpleNamedReference {
source = defaultSource source = defaultSource.withKind(FirFakeSourceElementKind.ImplicitInvokeCall)
name = OperatorNameConventions.INVOKE name = OperatorNameConventions.INVOKE
} to calleeExpression.toFirExpression("Incorrect invoke receiver") } to calleeExpression.toFirExpression("Incorrect invoke receiver")
} }
@@ -1746,7 +1753,7 @@ class RawFirBuilder(
val sourceElement = expression.toFirSourceElement() val sourceElement = expression.toFirSourceElement()
source = sourceElement source = sourceElement
calleeReference = buildExplicitThisReference { calleeReference = buildExplicitThisReference {
source = sourceElement source = sourceElement.withKind(FirFakeSourceElementKind.ExplicitThisOrSuperReference)
labelName = expression.getLabelName() labelName = expression.getLabelName()
} }
} }
@@ -1758,7 +1765,7 @@ class RawFirBuilder(
return buildQualifiedAccessExpression { return buildQualifiedAccessExpression {
this.source = source this.source = source
calleeReference = buildExplicitSuperReference { calleeReference = buildExplicitSuperReference {
this.source source.withKind(FirFakeSourceElementKind.ExplicitThisOrSuperReference)
labelName = expression.getLabelName() labelName = expression.getLabelName()
superTypeRef = superType.toFirOrImplicitType() superTypeRef = superType.toFirOrImplicitType()
} }
@@ -1772,12 +1779,12 @@ class RawFirBuilder(
override fun visitLabeledExpression(expression: KtLabeledExpression, data: Unit): FirElement { override fun visitLabeledExpression(expression: KtLabeledExpression, data: Unit): FirElement {
val sourceElement = expression.toFirSourceElement() val sourceElement = expression.toFirSourceElement()
val labelName = expression.getLabelName() val label = expression.getTargetLabel()
val size = context.firLabels.size val size = context.firLabels.size
if (labelName != null) { if (label != null) {
context.firLabels += buildLabel { context.firLabels += buildLabel {
source = sourceElement source = label.toFirPsiSourceElement()
name = labelName name = label.getReferencedName()
} }
} }
val result = expression.baseExpression?.accept(this, data) 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. * 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.KotlinBuiltIns
import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor import org.jetbrains.kotlin.builtins.functions.FunctionClassDescriptor
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic import org.jetbrains.kotlin.fir.diagnostics.ConeStubDiagnostic
import org.jetbrains.kotlin.fir.expressions.* 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.providers.getSymbolByTypeRef
import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.AbstractConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.body.resolve.resultType 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.FirDeclaredMemberScopeProvider
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.symbols.* 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) val functionalType = createFunctionalType(parameters, receiverTypeRef?.coneTypeSafe(), rawReturnType, isSuspend = isSuspend)
return buildResolvedTypeRef { return buildResolvedTypeRef {
source = this@constructFunctionalTypeRef.source source = this@constructFunctionalTypeRef.source?.withKind(FirFakeSourceElementKind.ImplicitTypeRef)
type = functionalType type = functionalType
this.isSuspend = isSuspend this.isSuspend = isSuspend
} }
@@ -327,7 +325,7 @@ fun <T : FirResolvable> BodyResolveComponents.typeFromCallee(access: T): FirReso
return when (val newCallee = access.calleeReference) { return when (val newCallee = access.calleeReference) {
is FirErrorNamedReference -> is FirErrorNamedReference ->
buildErrorTypeRef { buildErrorTypeRef {
source = access.source source = access.source?.withKind(FirFakeSourceElementKind.ErrorTypeRef)
diagnostic = ConeStubDiagnostic(newCallee.diagnostic) diagnostic = ConeStubDiagnostic(newCallee.diagnostic)
} }
is FirNamedReferenceWithCandidate -> { is FirNamedReferenceWithCandidate -> {
@@ -392,7 +390,7 @@ fun BodyResolveComponents.transformQualifiedAccessUsingSmartcastInfo(qualifiedAc
val intersectedType = ConeTypeIntersector.intersectTypes(inferenceComponents.ctx, allTypes) val intersectedType = ConeTypeIntersector.intersectTypes(inferenceComponents.ctx, allTypes)
// TODO: add check that intersectedType is not equal to original type // TODO: add check that intersectedType is not equal to original type
val intersectedTypeRef = buildResolvedTypeRef { val intersectedTypeRef = buildResolvedTypeRef {
source = qualifiedAccessExpression.resultType.source source = qualifiedAccessExpression.resultType.source?.withKind(FirFakeSourceElementKind.SmartCastedTypeRef)
type = intersectedType type = intersectedType
annotations += qualifiedAccessExpression.resultType.annotations 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. * 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 package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.FirElement 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.FirTypedDeclaration
import org.jetbrains.kotlin.fir.declarations.FirValueParameter import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.* import org.jetbrains.kotlin.fir.expressions.*
@@ -99,7 +100,10 @@ internal fun FirTypedDeclaration.transformTypeToArrayType() {
val returnType = returnTypeRef.coneTypeUnsafe<ConeKotlinType>() val returnType = returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
transformReturnTypeRef( transformReturnTypeRef(
StoreType, 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. * 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 package org.jetbrains.kotlin.fir.resolve.transformers.body.resolve
import org.jetbrains.kotlin.descriptors.ClassKind import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirElement import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.FirFunctionTarget
import org.jetbrains.kotlin.fir.copy
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter import org.jetbrains.kotlin.fir.declarations.builder.buildValueParameter
import org.jetbrains.kotlin.fir.declarations.impl.FirDefaultPropertyAccessor 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.inference.extractLambdaInfoFromFunctionalType
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.* 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.FirLocalScope
import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope import org.jetbrains.kotlin.fir.scopes.impl.FirMemberTypeParameterScope
import org.jetbrains.kotlin.fir.symbols.constructStarProjectedType 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> { override fun <E : FirElement> transformElement(element: E, data: FirExpression): CompositeTransformResult<E> {
if (element == lastStatement) { if (element == lastStatement) {
val returnExpression = buildReturnExpression { val returnExpression = buildReturnExpression {
source = element.source source = element.source?.withKind(FirFakeSourceElementKind.ImplicitReturn)
result = lastStatement result = lastStatement
target = FirFunctionTarget(null, isLambda = this@addReturn.isLambda).also { target = FirFunctionTarget(null, isLambda = this@addReturn.isLambda).also {
it.bind(this@addReturn) 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. * 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 val (leftArgument, rightArgument) = operatorCall.arguments
fun createFunctionCall(name: Name) = buildFunctionCall { fun createFunctionCall(name: Name) = buildFunctionCall {
source = operatorCall.source source = operatorCall.source?.withKind(FirFakeSourceElementKind.DesugaredCompoundAssignment)
explicitReceiver = leftArgument explicitReceiver = leftArgument
argumentList = buildUnaryArgumentList(rightArgument) argumentList = buildUnaryArgumentList(rightArgument)
calleeReference = buildSimpleNamedReference { 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. * 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.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirEffectiveVisibilityImpl import org.jetbrains.kotlin.fir.FirEffectiveVisibilityImpl
import org.jetbrains.kotlin.fir.FirFakeSourceElementKind
import org.jetbrains.kotlin.fir.FirSession import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.* import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.builder.* 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.builder.buildResolvedTypeRef
import org.jetbrains.kotlin.fir.types.coneTypeUnsafe import org.jetbrains.kotlin.fir.types.coneTypeUnsafe
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl 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.ClassId
import org.jetbrains.kotlin.name.Name 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) require(this is FirResolvedTypeRef)
if (newType == null) return this if (newType == null) return this
return buildResolvedTypeRef { return buildResolvedTypeRef {
source = this@withReplacedConeType.source source = this@withReplacedConeType.source?.withKind(sourceElementKind)
type = newType type = newType
annotations += this@withReplacedConeType.annotations 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. * 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( fun FirRegularClassBuilder.generateValuesFunction(
session: FirSession, packageFqName: FqName, classFqName: FqName, makeExpect: Boolean = false session: FirSession, packageFqName: FqName, classFqName: FqName, makeExpect: Boolean = false
) { ) {
val sourceElement = source?.withKind(FirFakeSourceElementKind.EnumGeneratedDeclaration)
declarations += buildSimpleFunction { declarations += buildSimpleFunction {
source = this@generateValuesFunction.source source = sourceElement
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
this.session = session this.session = session
returnTypeRef = buildResolvedTypeRef { returnTypeRef = buildResolvedTypeRef {
source = this@generateValuesFunction.source source = sourceElement
type = ConeClassLikeTypeImpl( type = ConeClassLikeTypeImpl(
ConeClassLikeLookupTagImpl(StandardClassIds.Array), ConeClassLikeLookupTagImpl(StandardClassIds.Array),
arrayOf( arrayOf(
@@ -60,12 +61,13 @@ fun FirRegularClassBuilder.generateValuesFunction(
fun FirRegularClassBuilder.generateValueOfFunction( fun FirRegularClassBuilder.generateValueOfFunction(
session: FirSession, packageFqName: FqName, classFqName: FqName, makeExpect: Boolean = false session: FirSession, packageFqName: FqName, classFqName: FqName, makeExpect: Boolean = false
) { ) {
val sourceElement = source?.withKind(FirFakeSourceElementKind.EnumGeneratedDeclaration)
declarations += buildSimpleFunction { declarations += buildSimpleFunction {
source = this@generateValueOfFunction.source source = sourceElement
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
this.session = session this.session = session
returnTypeRef = buildResolvedTypeRef { returnTypeRef = buildResolvedTypeRef {
source = this@generateValueOfFunction.source source = sourceElement
type = ConeClassLikeTypeImpl( type = ConeClassLikeTypeImpl(
this@generateValueOfFunction.symbol.toLookupTag(), this@generateValueOfFunction.symbol.toLookupTag(),
emptyArray(), emptyArray(),
@@ -79,7 +81,7 @@ fun FirRegularClassBuilder.generateValueOfFunction(
} }
symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, ENUM_VALUE_OF)) symbol = FirNamedFunctionSymbol(CallableId(packageFqName, classFqName, ENUM_VALUE_OF))
valueParameters += buildValueParameter vp@{ valueParameters += buildValueParameter vp@{
source = this@generateValueOfFunction.source source = sourceElement
origin = FirDeclarationOrigin.Source origin = FirDeclarationOrigin.Source
this@vp.session = session this@vp.session = session
returnTypeRef = FirImplicitStringTypeRef(source) 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. * 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.psi.tree.IElementType
import com.intellij.util.diff.FlyweightCapableTreeStructure 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 { sealed class FirSourceElement {
abstract val elementType: IElementType abstract val elementType: IElementType
abstract val startOffset: Int abstract val startOffset: Int
abstract val endOffset: 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 override val elementType: IElementType
get() = psi.node.elementType get() = psi.node.elementType
@@ -27,6 +159,24 @@ class FirPsiSourceElement<out P : PsiElement>(val psi: P) : FirSourceElement() {
get() = psi.textRange.endOffset 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( class FirLightSourceElement(
val element: LighterASTNode, val element: LighterASTNode,
override val startOffset: Int, override val startOffset: Int,
@@ -35,14 +185,20 @@ class FirLightSourceElement(
) : FirSourceElement() { ) : FirSourceElement() {
override val elementType: IElementType override val elementType: IElementType
get() = element.tokenType get() = element.tokenType
override val kind: FirSourceElementKind get() = FirRealSourceElementKind
} }
val FirSourceElement?.psi: PsiElement? get() = (this as? FirPsiSourceElement<*>)?.psi val FirSourceElement?.psi: PsiElement? get() = (this as? FirPsiSourceElement<*>)?.psi
val FirElement.psi: PsiElement? get() = (source 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") @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") @Suppress("NOTHING_TO_INLINE")
inline fun LighterASTNode.toFirLightSourceElement( inline fun LighterASTNode.toFirLightSourceElement(