From 94967bcd00427d61ad6741f91d0e1d7bc2970897 Mon Sep 17 00:00:00 2001 From: Ilya Kirillov Date: Mon, 15 Jun 2020 17:26:14 +0300 Subject: [PATCH] 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 --- .../kotlin/fir/builder/BaseFirBuilder.kt | 41 +++-- .../jetbrains/kotlin/fir/builder/Context.kt | 3 +- .../kotlin/fir/builder/ConversionUtils.kt | 42 +++-- .../fir/lightTree/converter/BaseConverter.kt | 5 +- .../kotlin/fir/builder/PsiConversionUtils.kt | 25 ++- .../kotlin/fir/builder/RawFirBuilder.kt | 99 ++++++----- .../kotlin/fir/resolve/ResolveUtils.kt | 12 +- .../resolve/transformers/TransformUtils.kt | 8 +- .../FirDeclarationsResolveTransformer.kt | 9 +- .../FirExpressionsResolveTransformer.kt | 4 +- .../scopes/impl/FirClassSubstitutionScope.kt | 8 +- .../jetbrains/kotlin/fir/EnumClassUtils.kt | 14 +- .../jetbrains/kotlin/fir/FirSourceElement.kt | 162 +++++++++++++++++- 13 files changed, 305 insertions(+), 127 deletions(-) diff --git a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt index cf0391f00dd..d45265091b5 100644 --- a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt +++ b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/BaseFirBuilder.kt @@ -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(val baseSession: FirSession, val context: Context = 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(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(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(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("") - 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("") 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(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(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(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) diff --git a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/Context.kt b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/Context.kt index d1cd243ebb7..34a3ccdbc7c 100644 --- a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/Context.kt +++ b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/Context.kt @@ -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 diff --git a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt index 3f8f64854d6..64664e8248c 100644 --- a/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt +++ b/compiler/fir/raw-fir/fir-common/src/org/jetbrains/kotlin/fir/builder/ConversionUtils.kt @@ -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() 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) } -} +} \ No newline at end of file diff --git a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt index e2fb8ce2fff..f902e993034 100644 --- a/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt +++ b/compiler/fir/raw-fir/light-tree2fir/src/org/jetbrains/kotlin/fir/lightTree/converter/BaseConverter.kt @@ -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(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) diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt index 009128b582b..081321a06db 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/PsiConversionUtils.kt @@ -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.toFirWhenCondition( - baseSource: FirSourceElement?, subject: FirExpressionRef, convert: KtExpression?.(String) -> FirExpression, toFirOrErrorTypeRef: KtTypeReference?.() -> FirTypeRef, @@ -78,7 +74,7 @@ internal fun Array.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 diff --git a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt index 5c0f311c42c..dede28a0251 100644 --- a/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt +++ b/compiler/fir/raw-fir/psi2fir/src/org/jetbrains/kotlin/fir/builder/RawFirBuilder.kt @@ -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 ): 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(""), 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("") 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) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt index 77d5c2e1ffe..6fca6b13e53 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/ResolveUtils.kt @@ -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 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 } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/TransformUtils.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/TransformUtils.kt index 82bf24ea622..7151c9a40e0 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/TransformUtils.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/TransformUtils.kt @@ -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() transformReturnTypeRef( StoreType, - returnTypeRef.withReplacedConeType(ConeKotlinTypeProjectionOut(returnType).createArrayOf()) + returnTypeRef.withReplacedConeType( + ConeKotlinTypeProjectionOut(returnType).createArrayOf(), + FirFakeSourceElementKind.ArrayTypeFromVarargParameter + ) ) } diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt index 387db61ed40..b98dd492ea3 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirDeclarationsResolveTransformer.kt @@ -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 transformElement(element: E, data: FirExpression): CompositeTransformResult { 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) diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt index 47ef5f6bb7d..5d8f90c1bc0 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/resolve/transformers/body/resolve/FirExpressionsResolveTransformer.kt @@ -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 { diff --git a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt index 65a355ec544..67270703028 100644 --- a/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt +++ b/compiler/fir/resolve/src/org/jetbrains/kotlin/fir/scopes/impl/FirClassSubstitutionScope.kt @@ -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 } diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/EnumClassUtils.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/EnumClassUtils.kt index bf882edee41..0f2d0a1ca9e 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/EnumClassUtils.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/EnumClassUtils.kt @@ -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) diff --git a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt index fbfc966345b..151d2fbc2ba 100644 --- a/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt +++ b/compiler/fir/tree/src/org/jetbrains/kotlin/fir/FirSourceElement.kt @@ -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 : = list.iterator() + // while(.hasNext()) { + // val i = .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 = x; x = .inc(); } + 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) 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(val psi: P) : FirSourceElement() { + +sealed class FirPsiSourceElement(val psi: P) : FirSourceElement() { override val elementType: IElementType get() = psi.node.elementType @@ -27,6 +159,24 @@ class FirPsiSourceElement(val psi: P) : FirSourceElement() { get() = psi.textRange.endOffset } +class FirRealPsiSourceElement(psi: P) : FirPsiSourceElement

(psi) { + override val kind: FirSourceElementKind get() = FirRealSourceElementKind +} + +class FirFakeSourceElement(psi: P, override val kind: FirFakeSourceElementKind) : FirPsiSourceElement

(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(