FIR: Expression typing and simple call resolver
This commit is contained in:
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.symbols
|
||||
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
object StandardClassIds {
|
||||
|
||||
private val BASE_KOTLIN_PACKAGE = FqName("kotlin")
|
||||
private fun String.baseId() = ClassId(BASE_KOTLIN_PACKAGE, Name.identifier(this))
|
||||
|
||||
val Nothing = "Nothing".baseId()
|
||||
val Any = "Any".baseId()
|
||||
|
||||
val Boolean = "Boolean".baseId()
|
||||
val Char = "Char".baseId()
|
||||
val Byte = "Byte".baseId()
|
||||
val Short = "Short".baseId()
|
||||
|
||||
val Int = "Int".baseId()
|
||||
val Long = "Long".baseId()
|
||||
|
||||
val String = "String".baseId()
|
||||
|
||||
val Float = "Float".baseId()
|
||||
val Double = "Double".baseId()
|
||||
|
||||
}
|
||||
+1
-1
@@ -109,7 +109,7 @@ class FirTypeResolverImpl(private val session: FirSession) : FirTypeResolver {
|
||||
is FirImplicitBuiltinTypeRef -> {
|
||||
resolveToSymbol(typeRef, scope, position)!!.constructType(emptyList(), isNullable = false)
|
||||
}
|
||||
is FirDynamicTypeRef, is FirImplicitTypeRef, is FirDelegatedTypeRef -> {
|
||||
is FirDynamicTypeRef, is FirDelegatedTypeRef -> {
|
||||
ConeKotlinErrorType("Not supported: ${typeRef::class.simpleName}")
|
||||
}
|
||||
else -> error("!")
|
||||
|
||||
+2
-103
@@ -14,7 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirRegularClass
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.buildUseSiteScope
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.NEXT
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.FirTopLevelDeclaredMemberScope
|
||||
@@ -24,105 +24,4 @@ import org.jetbrains.kotlin.fir.visitors.compose
|
||||
|
||||
class FirAccessResolveTransformer : FirAbstractTreeTransformerWithSuperTypes(reversedScopePriority = true) {
|
||||
|
||||
private lateinit var session: FirSession
|
||||
|
||||
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
|
||||
session = file.fileSession
|
||||
return withScopeCleanup {
|
||||
towerScope.scopes += FirTopLevelDeclaredMemberScope(file, session)
|
||||
super.transformFile(file, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformRegularClass(regularClass: FirRegularClass, data: Nothing?): CompositeTransformResult<FirDeclaration> {
|
||||
return withScopeCleanup {
|
||||
towerScope.scopes += regularClass.buildUseSiteScope(session)
|
||||
super.transformRegularClass(regularClass, data)
|
||||
}
|
||||
}
|
||||
|
||||
private var lookupFunctions = false
|
||||
private var lookupProperties = false
|
||||
|
||||
private inline fun <T> withNewSettings(block: () -> T): T {
|
||||
val prevFunctions = lookupFunctions
|
||||
val prevProperties = lookupProperties
|
||||
val result = block()
|
||||
|
||||
lookupFunctions = prevFunctions
|
||||
lookupProperties = prevProperties
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
override fun transformFunctionCall(functionCall: FirFunctionCall, data: Nothing?): CompositeTransformResult<FirStatement> {
|
||||
|
||||
return withNewSettings {
|
||||
lookupFunctions = true
|
||||
lookupProperties = false
|
||||
super.transformFunctionCall(functionCall, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun transformQualifiedAccessExpression(
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression,
|
||||
data: Nothing?
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return withNewSettings {
|
||||
lookupProperties = true
|
||||
lookupFunctions = false
|
||||
super.transformQualifiedAccessExpression(qualifiedAccessExpression, data)
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformCallableReferenceAccess(
|
||||
callableReferenceAccess: FirCallableReferenceAccess,
|
||||
data: Nothing?
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
return withNewSettings {
|
||||
lookupProperties = true
|
||||
lookupFunctions = true
|
||||
super.transformCallableReferenceAccess(callableReferenceAccess, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun transformAssignment(assignment: FirAssignment, data: Nothing?): CompositeTransformResult<FirStatement> {
|
||||
return withNewSettings {
|
||||
lookupProperties = true
|
||||
lookupFunctions = false
|
||||
super.transformAssignment(assignment, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun transformNamedReference(namedReference: FirNamedReference, data: Nothing?): CompositeTransformResult<FirNamedReference> {
|
||||
if (namedReference is FirResolvedCallableReference) return namedReference.compose()
|
||||
val name = namedReference.name
|
||||
val referents = mutableListOf<ConeCallableSymbol>()
|
||||
fun collect(it: ConeCallableSymbol): ProcessorAction {
|
||||
referents.add(it)
|
||||
return NEXT
|
||||
}
|
||||
|
||||
if (lookupFunctions)
|
||||
towerScope.processFunctionsByName(name, ::collect)
|
||||
if (lookupProperties)
|
||||
towerScope.processPropertiesByName(name, ::collect)
|
||||
|
||||
return when (referents.size) {
|
||||
0 -> FirErrorNamedReference(
|
||||
session, namedReference.psi, "Unresolved name: $name"
|
||||
).compose()
|
||||
1 -> FirResolvedCallableReferenceImpl(
|
||||
session, namedReference.psi,
|
||||
name, referents.single()
|
||||
).compose()
|
||||
else -> FirErrorNamedReference(
|
||||
session, namedReference.psi, "Ambiguity: $name, ${referents.map { it.callableId }}"
|
||||
).compose()
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
+392
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.*
|
||||
import org.jetbrains.kotlin.fir.declarations.*
|
||||
import org.jetbrains.kotlin.fir.expressions.*
|
||||
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
|
||||
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
import org.jetbrains.kotlin.fir.scopes.lookupSuperTypes
|
||||
import org.jetbrains.kotlin.fir.symbols.*
|
||||
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
|
||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.compose
|
||||
import org.jetbrains.kotlin.ir.expressions.IrConstKind
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirErrorTypeRefImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||
|
||||
class FirBodyResolveTransformer(val session: FirSession) : FirTransformer<Any?>() {
|
||||
|
||||
val symbolProvider = session.service<FirSymbolProvider>()
|
||||
|
||||
override fun <E : FirElement> transformElement(element: E, data: Any?): CompositeTransformResult<E> {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return (element.transformChildren(this, data) as E).compose()
|
||||
}
|
||||
|
||||
override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: Any?): CompositeTransformResult<FirTypeRef> {
|
||||
if (data == null)
|
||||
return implicitTypeRef.compose()
|
||||
require(data is FirTypeRef)
|
||||
return data.compose()
|
||||
}
|
||||
|
||||
|
||||
private fun ConeClassLikeType.buildSubstitutionScope(
|
||||
useSiteSession: FirSession,
|
||||
unsubstituted: FirScope,
|
||||
regularClass: FirRegularClass
|
||||
): FirClassSubstitutionScope? {
|
||||
if (this.typeArguments.isEmpty()) return null
|
||||
|
||||
val substitution = regularClass.typeParameters.zip(this.typeArguments) { typeParameter, typeArgument ->
|
||||
typeParameter.symbol to (typeArgument as? ConeTypedProjection)?.type
|
||||
}.filter { (_, type) -> type != null }.toMap() as Map<ConeTypeParameterSymbol, ConeKotlinType>
|
||||
|
||||
return FirClassSubstitutionScope(useSiteSession, unsubstituted, substitution, true)
|
||||
}
|
||||
|
||||
private fun FirRegularClass.buildUseSiteScope(useSiteSession: FirSession = session): FirClassUseSiteScope {
|
||||
val superTypeScope = FirCompositeScope(mutableListOf())
|
||||
val declaredScope = FirClassDeclaredMemberScope(this, useSiteSession)
|
||||
lookupSuperTypes(this, lookupInterfaces = true, deep = false, useSiteSession = useSiteSession)
|
||||
.mapNotNullTo(superTypeScope.scopes) { useSiteSuperType ->
|
||||
if (useSiteSuperType is ConeClassErrorType) return@mapNotNullTo null
|
||||
val symbol = useSiteSuperType.symbol
|
||||
if (symbol is FirClassSymbol) {
|
||||
val scope = symbol.fir.buildUseSiteScope(useSiteSession)
|
||||
useSiteSuperType.buildSubstitutionScope(useSiteSession, scope, symbol.fir) ?: scope
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
return FirClassUseSiteScope(useSiteSession, superTypeScope, declaredScope, true)
|
||||
}
|
||||
|
||||
fun ConeKotlinType.scope(useSiteSession: FirSession): FirScope {
|
||||
when (this) {
|
||||
is ConeClassTypeImpl -> return (this.symbol as FirBasedSymbol<FirRegularClass>).fir.buildUseSiteScope(useSiteSession)
|
||||
else -> error("Failed type ${this}")
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformRegularClass(regularClass: FirRegularClass, data: Any?): CompositeTransformResult<FirDeclaration> {
|
||||
return withScopeCleanup {
|
||||
scopes += regularClass.buildUseSiteScope()
|
||||
super.transformRegularClass(regularClass, data)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected inline fun <T> withScopeCleanup(crossinline l: () -> T): T {
|
||||
val sizeBefore = scopes.size
|
||||
val result = l()
|
||||
val size = scopes.size
|
||||
assert(size >= sizeBefore)
|
||||
repeat(size - sizeBefore) {
|
||||
scopes.let { it.removeAt(it.size - 1) }
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
val scopes = mutableListOf<FirScope>()
|
||||
|
||||
enum class CandidateApplicability {
|
||||
HIDDEN,
|
||||
PARAMETER_MAPPING_ERROR,
|
||||
SYNTHETIC_RESOLVED,
|
||||
RESOLVED
|
||||
}
|
||||
|
||||
inner class ApplicabilityChecker {
|
||||
|
||||
var groupCounter = 0
|
||||
val groupNumbers = mutableListOf<Int>()
|
||||
val candidates = mutableListOf<ConeCallableSymbol>()
|
||||
|
||||
|
||||
var currentApplicability = CandidateApplicability.HIDDEN
|
||||
|
||||
|
||||
var expectedType: FirTypeRef? = null
|
||||
var explicitReceiverType: FirTypeRef? = null
|
||||
|
||||
fun newDataSet() {
|
||||
groupNumbers.clear()
|
||||
candidates.clear()
|
||||
groupCounter = 0
|
||||
expectedType = null
|
||||
currentApplicability = CandidateApplicability.HIDDEN
|
||||
}
|
||||
|
||||
fun newGroup() {
|
||||
groupCounter++
|
||||
}
|
||||
|
||||
|
||||
fun isSubtypeOf(superType: FirTypeRef?, subType: FirTypeRef?): Boolean {
|
||||
if (superType == null && subType == null) return true
|
||||
if (superType != null && subType != null) return true
|
||||
return false
|
||||
}
|
||||
|
||||
|
||||
private fun getApplicability(symbol: ConeCallableSymbol): CandidateApplicability {
|
||||
val declaration = (symbol as? FirBasedSymbol<FirCallableMember>)?.fir
|
||||
?: return CandidateApplicability.HIDDEN
|
||||
|
||||
if (!isSubtypeOf(declaration.receiverTypeRef, explicitReceiverType)) return CandidateApplicability.PARAMETER_MAPPING_ERROR
|
||||
return CandidateApplicability.RESOLVED
|
||||
}
|
||||
|
||||
fun consumeCandidate(symbol: ConeCallableSymbol) {
|
||||
val applicability = getApplicability(symbol)
|
||||
|
||||
if (applicability > currentApplicability) {
|
||||
groupNumbers.clear()
|
||||
candidates.clear()
|
||||
currentApplicability = applicability
|
||||
}
|
||||
|
||||
|
||||
if (applicability == currentApplicability) {
|
||||
candidates.add(symbol)
|
||||
groupNumbers.add(groupCounter)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformQualifiedAccessExpression(
|
||||
qualifiedAccessExpression: FirQualifiedAccessExpression,
|
||||
data: Any?
|
||||
): CompositeTransformResult<FirStatement> {
|
||||
qualifiedAccessExpression.explicitReceiver?.visitNoTransform(this, null)
|
||||
val callee = qualifiedAccessExpression.calleeReference as? FirNamedReference ?: return qualifiedAccessExpression.compose()
|
||||
|
||||
with(ApplicabilityChecker()) {
|
||||
expectedType = data as FirTypeRef?
|
||||
explicitReceiverType = qualifiedAccessExpression.explicitReceiver?.resultType
|
||||
newDataSet()
|
||||
|
||||
for (scope in scopes.asReversed()) {
|
||||
newGroup()
|
||||
val name = callee.name
|
||||
scope.processPropertiesByName(name) {
|
||||
consumeCandidate(symbol = it)
|
||||
ProcessorAction.NEXT
|
||||
}
|
||||
if (currentApplicability == CandidateApplicability.RESOLVED) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
val result = candidates
|
||||
qualifiedAccessExpression.transformCalleeReference(this@FirBodyResolveTransformer, result)
|
||||
|
||||
bindingContext[qualifiedAccessExpression] =
|
||||
when (val newCallee = qualifiedAccessExpression.calleeReference) {
|
||||
is FirErrorNamedReference ->
|
||||
FirErrorTypeRefImpl(session, qualifiedAccessExpression.psi, newCallee.errorReason)
|
||||
is FirResolvedCallableReference ->
|
||||
(newCallee.callableSymbol as FirBasedSymbol<FirCallableMember>).fir.returnTypeRef
|
||||
else -> error("WTF!")
|
||||
}
|
||||
}
|
||||
return qualifiedAccessExpression.compose()
|
||||
}
|
||||
|
||||
override fun transformNamedReference(namedReference: FirNamedReference, data: Any?): CompositeTransformResult<FirNamedReference> {
|
||||
if (namedReference is FirResolvedCallableReference) return namedReference.compose()
|
||||
val name = namedReference.name
|
||||
val referents = data as? List<ConeCallableSymbol> ?: return namedReference.compose()
|
||||
return when (referents.size) {
|
||||
0 -> FirErrorNamedReference(
|
||||
namedReference.session, namedReference.psi, "Unresolved name: $name"
|
||||
).compose()
|
||||
1 -> FirResolvedCallableReferenceImpl(
|
||||
namedReference.session, namedReference.psi,
|
||||
name, referents.single()
|
||||
).compose()
|
||||
else -> FirErrorNamedReference(
|
||||
namedReference.session, namedReference.psi, "Ambiguity: $name, ${referents.map { it.callableId }}"
|
||||
).compose()
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// override fun transformAssignment(assignment: FirAssignment, data: Any?): CompositeTransformResult<FirStatement> {
|
||||
// return withNewSettings {
|
||||
// lookupProperties = true
|
||||
// lookupFunctions = false
|
||||
// super.transformAssignment(assignment, data)
|
||||
// }
|
||||
// }
|
||||
|
||||
//
|
||||
// override fun transformNamedReference(namedReference: FirNamedReference, data: Any?): CompositeTransformResult<FirNamedReference> {
|
||||
// if (namedReference is FirResolvedCallableReference) return namedReference.compose()
|
||||
// val name = namedReference.name
|
||||
// val referents = mutableListOf<ConeCallableSymbol>()
|
||||
// fun collect(it: ConeCallableSymbol): ProcessorAction {
|
||||
// referents.add(it)
|
||||
// return ProcessorAction.NEXT
|
||||
// }
|
||||
//
|
||||
// if (lookupFunctions)
|
||||
// towerScope.processFunctionsByName(name, ::collect)
|
||||
// if (lookupProperties)
|
||||
// towerScope.processPropertiesByName(name, ::collect)
|
||||
//
|
||||
// return when (referents.size) {
|
||||
// 0 -> FirErrorNamedReference(
|
||||
// namedReference.session, namedReference.psi, "Unresolved name: $name"
|
||||
// ).compose()
|
||||
// 1 -> FirResolvedCallableReferenceImpl(
|
||||
// namedReference.session, namedReference.psi,
|
||||
// name, referents.single()
|
||||
// ).compose()
|
||||
// else -> FirErrorNamedReference(
|
||||
// namedReference.session, namedReference.psi, "Ambiguity: $name, ${referents.map { it.callableId }}"
|
||||
// ).compose()
|
||||
// }
|
||||
//
|
||||
// }
|
||||
//
|
||||
// override fun transformQualifiedAccessExpression(
|
||||
// qualifiedAccessExpression: FirQualifiedAccessExpression,
|
||||
// data: Any?
|
||||
// ): CompositeTransformResult<FirStatement> {
|
||||
//
|
||||
//
|
||||
//
|
||||
// return super.transformQualifiedAccessExpression(qualifiedAccessExpression, data)
|
||||
// }
|
||||
|
||||
|
||||
override fun transformBlock(block: FirBlock, data: Any?): CompositeTransformResult<FirStatement> {
|
||||
|
||||
block.transformChildren(this, data)
|
||||
val statement = block.statements.lastOrNull()
|
||||
|
||||
val resultExpression = when (statement) {
|
||||
is FirReturnExpression -> statement.result
|
||||
is FirExpression -> statement
|
||||
else -> null
|
||||
}
|
||||
resultExpression?.resultType?.let { bindingContext[block] = it }
|
||||
return super.transformBlock(block, data)
|
||||
}
|
||||
|
||||
private fun commonSuperType(types: List<FirTypeRef>): FirTypeRef {
|
||||
return types.first()
|
||||
}
|
||||
|
||||
override fun transformWhenExpression(whenExpression: FirWhenExpression, data: Any?): CompositeTransformResult<FirStatement> {
|
||||
|
||||
val type = commonSuperType(whenExpression.branches.mapNotNull {
|
||||
it.result.visitNoTransform(this, data)
|
||||
it.result.resultType
|
||||
})
|
||||
bindingContext[whenExpression] = type
|
||||
return super.transformWhenExpression(whenExpression, data)
|
||||
}
|
||||
|
||||
override fun <T> transformConstExpression(constExpression: FirConstExpression<T>, data: Any?): CompositeTransformResult<FirStatement> {
|
||||
if (data == null) return constExpression.compose()
|
||||
val expectedType = data as FirTypeRef
|
||||
|
||||
if (expectedType is FirImplicitTypeRef) {
|
||||
|
||||
val symbol = when (constExpression.kind) {
|
||||
IrConstKind.Null -> StandardClassIds.Nothing(symbolProvider)
|
||||
IrConstKind.Boolean -> StandardClassIds.Boolean(symbolProvider)
|
||||
IrConstKind.Char -> StandardClassIds.Char(symbolProvider)
|
||||
IrConstKind.Byte -> StandardClassIds.Byte(symbolProvider)
|
||||
IrConstKind.Short -> StandardClassIds.Short(symbolProvider)
|
||||
IrConstKind.Int -> StandardClassIds.Int(symbolProvider)
|
||||
IrConstKind.Long -> StandardClassIds.Long(symbolProvider)
|
||||
IrConstKind.String -> StandardClassIds.String(symbolProvider)
|
||||
IrConstKind.Float -> StandardClassIds.Float(symbolProvider)
|
||||
IrConstKind.Double -> StandardClassIds.Double(symbolProvider)
|
||||
}
|
||||
|
||||
val type = ConeClassTypeImpl(symbol, emptyArray(), isNullable = constExpression.kind == IrConstKind.Null)
|
||||
|
||||
bindingContext[constExpression] = FirResolvedTypeRefImpl(session, null, type, false, emptyList())
|
||||
} else {
|
||||
bindingContext[constExpression] = expectedType
|
||||
}
|
||||
|
||||
|
||||
return super.transformConstExpression(constExpression, data)
|
||||
}
|
||||
|
||||
@Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")"))
|
||||
val bindingContext = mutableMapOf<FirExpression, FirTypeRef>()
|
||||
|
||||
val FirExpression.resultType: FirTypeRef? get() = bindingContext[this]
|
||||
|
||||
|
||||
override fun transformNamedFunction(namedFunction: FirNamedFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
|
||||
|
||||
return withScopeCleanup {
|
||||
scopes.addIfNotNull(namedFunction.receiverTypeRef?.coneTypeSafe()?.scope(session))
|
||||
val body = namedFunction.body
|
||||
if (namedFunction.returnTypeRef is FirImplicitTypeRef && body != null) {
|
||||
body.visitNoTransform(this, namedFunction.returnTypeRef)
|
||||
namedFunction.transformReturnTypeRef(this, body.resultType)
|
||||
}
|
||||
|
||||
super.transformNamedFunction(namedFunction, data)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
override fun transformVariable(variable: FirVariable, data: Any?): CompositeTransformResult<FirDeclaration> {
|
||||
val initializer = variable.initializer
|
||||
initializer?.visitNoTransform(this, variable.returnTypeRef)
|
||||
if (variable.returnTypeRef is FirImplicitTypeRef) {
|
||||
when {
|
||||
variable.delegate != null -> TODO("!?")
|
||||
initializer != null -> {
|
||||
variable.transformReturnTypeRef(this, initializer.resultType)
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.transformVariable(variable, data)
|
||||
}
|
||||
|
||||
override fun transformProperty(property: FirProperty, data: Any?): CompositeTransformResult<FirDeclaration> {
|
||||
return transformVariable(property, data)
|
||||
}
|
||||
|
||||
private fun <D> FirElement.visitNoTransform(transformer: FirTransformer<D>, data: D) {
|
||||
val result = this.transform(transformer, data)
|
||||
require(result.single === this)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Deprecated("It is temp", level = DeprecationLevel.WARNING, replaceWith = ReplaceWith("TODO(\"что-то нормальное\")"))
|
||||
class FirBodyResolveTransformerAdapter : FirTransformer<Nothing?>() {
|
||||
override fun <E : FirElement> transformElement(element: E, data: Nothing?): CompositeTransformResult<E> {
|
||||
return element.compose()
|
||||
}
|
||||
|
||||
override fun transformFile(file: FirFile, data: Nothing?): CompositeTransformResult<FirFile> {
|
||||
val transformer = FirBodyResolveTransformer(file.session)
|
||||
return file.transform(transformer, null)
|
||||
}
|
||||
}
|
||||
+5
-4
@@ -11,10 +11,7 @@ import org.jetbrains.kotlin.fir.expressions.FirAnnotationCall
|
||||
import org.jetbrains.kotlin.fir.resolve.FirTypeResolver
|
||||
import org.jetbrains.kotlin.fir.scopes.FirPosition
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||
import org.jetbrains.kotlin.fir.types.FirFunctionTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.*
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedFunctionTypeRefImpl
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
|
||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||
@@ -59,4 +56,8 @@ class FirSpecificTypeResolverTransformer(
|
||||
override fun transformResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
||||
return resolvedTypeRef.compose()
|
||||
}
|
||||
|
||||
override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
||||
return implicitTypeRef.compose()
|
||||
}
|
||||
}
|
||||
|
||||
+2
-1
@@ -15,7 +15,8 @@ class FirTotalResolveTransformer {
|
||||
FirSupertypeResolverTransformer(),
|
||||
FirTypeResolveTransformer(),
|
||||
FirStatusResolveTransformer(),
|
||||
FirAccessResolveTransformer()
|
||||
FirAccessResolveTransformer(),
|
||||
FirBodyResolveTransformerAdapter()
|
||||
)
|
||||
|
||||
fun processFiles(files: List<FirFile>) {
|
||||
|
||||
+8
@@ -13,8 +13,11 @@ import org.jetbrains.kotlin.fir.resolve.lookupSuperTypes
|
||||
import org.jetbrains.kotlin.fir.scopes.FirPosition
|
||||
import org.jetbrains.kotlin.fir.scopes.addImportingScopes
|
||||
import org.jetbrains.kotlin.fir.scopes.impl.*
|
||||
import org.jetbrains.kotlin.fir.types.FirImplicitTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.types.impl.FirImplicitBuiltinTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.CompositeTransformResult
|
||||
import org.jetbrains.kotlin.fir.visitors.compose
|
||||
|
||||
open class FirTypeResolveTransformer : FirAbstractTreeTransformerWithSuperTypes(reversedScopePriority = true) {
|
||||
private lateinit var session: FirSession
|
||||
@@ -76,6 +79,11 @@ open class FirTypeResolveTransformer : FirAbstractTreeTransformerWithSuperTypes(
|
||||
}
|
||||
}
|
||||
|
||||
override fun transformImplicitTypeRef(implicitTypeRef: FirImplicitTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
||||
if (implicitTypeRef is FirImplicitBuiltinTypeRef) return super.transformImplicitTypeRef(implicitTypeRef, data)
|
||||
return implicitTypeRef.compose()
|
||||
}
|
||||
|
||||
override fun transformTypeRef(typeRef: FirTypeRef, data: Nothing?): CompositeTransformResult<FirTypeRef> {
|
||||
return FirSpecificTypeResolverTransformer(towerScope, FirPosition.OTHER, session).transformTypeRef(typeRef, data)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.scopes.impl
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirSession
|
||||
import org.jetbrains.kotlin.fir.declarations.FirNamedDeclaration
|
||||
import org.jetbrains.kotlin.fir.declarations.FirNamedFunction
|
||||
import org.jetbrains.kotlin.fir.expressions.FirVariable
|
||||
import org.jetbrains.kotlin.fir.scopes.FirScope
|
||||
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
|
||||
import org.jetbrains.kotlin.fir.symbols.ConeFunctionSymbol
|
||||
import org.jetbrains.kotlin.fir.symbols.ConePropertySymbol
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
|
||||
//class FirLocalScope : FirScope {
|
||||
//
|
||||
// val properties = mutableMapOf<Name, FirVariable>()
|
||||
// val functions = mutableMapOf<Name, FirNamedFunction>()
|
||||
//
|
||||
// fun storeDeclaration(declaration: FirNamedDeclaration) {
|
||||
// when (declaration) {
|
||||
// is FirVariable -> properties[declaration.name] = declaration
|
||||
// is FirNamedFunction -> functions[declaration.name] = declaration
|
||||
//
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// override fun processFunctionsByName(name: Name, processor: (ConeFunctionSymbol) -> ProcessorAction): ProcessorAction {
|
||||
// return super.processFunctionsByName(name, processor)
|
||||
// }
|
||||
//
|
||||
// override fun processPropertiesByName(name: Name, processor: (ConePropertySymbol) -> ProcessorAction): ProcessorAction {
|
||||
// val prop = properties[name]
|
||||
// if (prop != null) {
|
||||
// return processor()
|
||||
// }
|
||||
// return ProcessorAction.NEXT
|
||||
// }
|
||||
//}
|
||||
@@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. 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.symbols
|
||||
|
||||
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
|
||||
import org.jetbrains.kotlin.name.ClassId
|
||||
|
||||
|
||||
val FirSymbolProvider.Any: ConeClassLikeSymbol get() = this.getClassLikeSymbolByFqName(StandardClassIds.Any)!!
|
||||
val FirSymbolProvider.Nothing: ConeClassLikeSymbol get() = this.getClassLikeSymbolByFqName(StandardClassIds.Nothing)!!
|
||||
|
||||
|
||||
operator fun ClassId.invoke(symbolProvider: FirSymbolProvider): ConeClassLikeSymbol {
|
||||
return symbolProvider.getClassLikeSymbolByFqName(this)!!
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
|
||||
class Foo {
|
||||
val x = 1
|
||||
|
||||
fun abc() = x
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
FILE: access.kt
|
||||
public final class Foo {
|
||||
public constructor(): super<R|kotlin/Any|>()
|
||||
|
||||
public final property x(val): R|kotlin/Int| = Int(1)
|
||||
public get(): <implicit>
|
||||
|
||||
public final function abc(): R|kotlin/Int| {
|
||||
return@@@abc R|/Foo.x|
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
fun foo() {
|
||||
val x = 1
|
||||
}
|
||||
|
||||
val bar = ""
|
||||
|
||||
val n = null
|
||||
|
||||
val g: String? = null
|
||||
@@ -0,0 +1,10 @@
|
||||
FILE: simple.kt
|
||||
public final function foo(): R|kotlin/Unit| {
|
||||
val x: R|kotlin/Int| = Int(1)
|
||||
}
|
||||
public final property bar(val): R|kotlin/String| = String()
|
||||
public get(): <implicit>
|
||||
public final property n(val): R|kotlin/Nothing|? = Null(null)
|
||||
public get(): <implicit>
|
||||
public final property g(val): R|kotlin/String|? = Null(null)
|
||||
public get(): R|kotlin/String|?
|
||||
@@ -0,0 +1 @@
|
||||
fun foo() = if (true) 1 else 0
|
||||
@@ -0,0 +1,12 @@
|
||||
FILE: when.kt
|
||||
public final function foo(): R|kotlin/Int| {
|
||||
return@@@foo when () {
|
||||
Boolean(true) -> {
|
||||
Int(1)
|
||||
}
|
||||
else -> {
|
||||
Int(0)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -62,8 +62,8 @@ FILE: enums.kt
|
||||
public final companion object Companion {
|
||||
public constructor(): super<R|kotlin/Any|>()
|
||||
|
||||
public final const property G(val): R|error: Not supported: FirImplicitTypeRefImpl| = Double(6.67E-11)
|
||||
public get(): R|error: Not supported: FirImplicitTypeRefImpl|
|
||||
public final const property G(val): R|kotlin/Double| = Double(6.67E-11)
|
||||
public get(): <implicit>
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ FILE: simpleClass.kt
|
||||
public final class SomeClass : R|SomeInterface| {
|
||||
public constructor(): super<R|kotlin/Any|>()
|
||||
|
||||
private final property baz(val): R|error: Not supported: FirImplicitTypeRefImpl| = Int(42)
|
||||
private get(): R|error: Not supported: FirImplicitTypeRefImpl|
|
||||
private final property baz(val): R|kotlin/Int| = Int(42)
|
||||
private get(): <implicit>
|
||||
|
||||
public final override function foo(x: R|kotlin/Int|, y: R|kotlin/String|): R|kotlin/String| {
|
||||
return@@@foo <Unresolved name: plus>#(<Unresolved name: plus>#(<Unresolved name: y>#, <Unresolved name: x>#), R|/SomeClass.baz|)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
FILE: simple.kt
|
||||
public final function foo(): R|error: Not supported: FirImplicitTypeRefImpl| {
|
||||
public final function foo(): R|kotlin/Int| {
|
||||
return@@@foo Int(1)
|
||||
}
|
||||
public final function bar(): R|error: Not supported: FirImplicitTypeRefImpl| {
|
||||
public final function bar(): <implicit> {
|
||||
return@@@bar R|/foo|()
|
||||
}
|
||||
|
||||
+2
-2
@@ -9,8 +9,8 @@ FILE: simpleClass.kt
|
||||
public final class SomeClass : R|SomeInterface| {
|
||||
public constructor(): super<R|kotlin/Any|>()
|
||||
|
||||
private final property baz(val): R|error: Not supported: FirImplicitTypeRefImpl| = Int(42)
|
||||
private get(): R|error: Not supported: FirImplicitTypeRefImpl|
|
||||
private final property baz(val): R|kotlin/Int| = Int(42)
|
||||
private get(): <implicit>
|
||||
|
||||
public final override function foo(x: R|kotlin/Int|, y: R|kotlin/String|): R|kotlin/String| {
|
||||
return@@@foo <Unresolved name: plus>#(<Unresolved name: plus>#(<Unresolved name: y>#, <Unresolved name: x>#), R|/SomeClass.baz|)
|
||||
|
||||
+28
@@ -142,6 +142,34 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/resolve/testData/resolve/expresssions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Expresssions extends AbstractFirResolveTestCase {
|
||||
private void runTest(String testDataFilePath) throws Exception {
|
||||
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
|
||||
}
|
||||
|
||||
@TestMetadata("access.kt")
|
||||
public void testAccess() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/access.kt");
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInExpresssions() throws Exception {
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/resolve/expresssions"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/simple.kt");
|
||||
}
|
||||
|
||||
@TestMetadata("when.kt")
|
||||
public void testWhen() throws Exception {
|
||||
runTest("compiler/fir/resolve/testData/resolve/expresssions/when.kt");
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/fir/resolve/testData/resolve/fromBuilder")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
@@ -7,11 +7,14 @@ package org.jetbrains.kotlin.fir.declarations
|
||||
|
||||
import org.jetbrains.kotlin.fir.expressions.FirAnnotationContainer
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeRef
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
|
||||
interface FirTypedDeclaration : FirDeclaration, FirAnnotationContainer {
|
||||
val returnTypeRef: FirTypeRef
|
||||
|
||||
fun <D> transformReturnTypeRef(transformer: FirTransformer<D>, data: D)
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
|
||||
visitor.visitTypedDeclaration(this, data)
|
||||
|
||||
|
||||
+4
@@ -23,6 +23,10 @@ abstract class FirAbstractCallableMember : FirAbstractMemberDeclaration, FirCall
|
||||
final override var receiverTypeRef: FirTypeRef?
|
||||
final override var returnTypeRef: FirTypeRef
|
||||
|
||||
override fun <D> transformReturnTypeRef(transformer: FirTransformer<D>, data: D) {
|
||||
returnTypeRef = returnTypeRef.transformSingle(transformer, data)
|
||||
}
|
||||
|
||||
constructor(
|
||||
session: FirSession,
|
||||
psi: PsiElement?,
|
||||
|
||||
+4
@@ -28,4 +28,8 @@ class FirAnonymousFunctionImpl(
|
||||
label = label?.transformSingle(transformer, data)
|
||||
return super<FirAbstractFunction>.transformChildren(transformer, data)
|
||||
}
|
||||
|
||||
override fun <D> transformReturnTypeRef(transformer: FirTransformer<D>, data: D) {
|
||||
returnTypeRef = returnTypeRef.transformSingle(transformer, data)
|
||||
}
|
||||
}
|
||||
+6
@@ -32,6 +32,12 @@ abstract class FirDefaultPropertyAccessor(
|
||||
|
||||
final override val annotations: List<FirAnnotationCall>
|
||||
get() = emptyList()
|
||||
|
||||
abstract override var returnTypeRef: FirTypeRef
|
||||
|
||||
override fun <D> transformReturnTypeRef(transformer: FirTransformer<D>, data: D) {
|
||||
returnTypeRef = returnTypeRef.transformSingle(transformer, data)
|
||||
}
|
||||
}
|
||||
|
||||
class FirDefaultPropertyGetter(
|
||||
|
||||
+4
@@ -34,6 +34,10 @@ class FirDefaultSetterValueParameter(
|
||||
return super<FirAbstractNamedAnnotatedDeclaration>.transformChildren(transformer, data)
|
||||
}
|
||||
|
||||
override fun <D> transformReturnTypeRef(transformer: FirTransformer<D>, data: D) {
|
||||
returnTypeRef = returnTypeRef.transformSingle(transformer, data)
|
||||
}
|
||||
|
||||
companion object {
|
||||
val name = Name.identifier("value")
|
||||
}
|
||||
|
||||
+4
@@ -32,4 +32,8 @@ class FirPropertyAccessorImpl(
|
||||
|
||||
return super<FirAbstractFunction>.transformChildren(transformer, data)
|
||||
}
|
||||
|
||||
override fun <D> transformReturnTypeRef(transformer: FirTransformer<D>, data: D) {
|
||||
returnTypeRef = returnTypeRef.transformSingle(transformer, data)
|
||||
}
|
||||
}
|
||||
+4
@@ -31,4 +31,8 @@ open class FirValueParameterImpl(
|
||||
|
||||
return super<FirAbstractNamedAnnotatedDeclaration>.transformChildren(transformer, data)
|
||||
}
|
||||
|
||||
override fun <D> transformReturnTypeRef(transformer: FirTransformer<D>, data: D) {
|
||||
returnTypeRef = returnTypeRef.transformSingle(transformer, data)
|
||||
}
|
||||
}
|
||||
@@ -31,4 +31,8 @@ class FirVariableImpl(
|
||||
|
||||
return super<FirAbstractNamedAnnotatedDeclaration>.transformChildren(transformer, data)
|
||||
}
|
||||
|
||||
override fun <D> transformReturnTypeRef(transformer: FirTransformer<D>, data: D) {
|
||||
returnTypeRef = returnTypeRef.transformSingle(transformer, data)
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
package org.jetbrains.kotlin.fir.expressions
|
||||
|
||||
import org.jetbrains.kotlin.fir.FirReference
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
import org.jetbrains.kotlin.fir.visitors.FirVisitor
|
||||
|
||||
interface FirQualifiedAccess : FirStatement {
|
||||
@@ -15,6 +16,8 @@ interface FirQualifiedAccess : FirStatement {
|
||||
|
||||
val explicitReceiver: FirExpression? get() = null
|
||||
|
||||
fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirQualifiedAccess
|
||||
|
||||
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
|
||||
visitor.visitQualifiedAccess(this, data)
|
||||
|
||||
|
||||
+6
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.expressions.impl
|
||||
import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
|
||||
abstract class FirAbstractQualifiedAccess(
|
||||
@@ -24,4 +25,9 @@ abstract class FirAbstractQualifiedAccess(
|
||||
explicitReceiver = explicitReceiver?.transformSingle(transformer, data)
|
||||
return super<FirAbstractStatement>.transformChildren(transformer, data)
|
||||
}
|
||||
|
||||
override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirQualifiedAccess {
|
||||
calleeReference = calleeReference.transformSingle(transformer, data)
|
||||
return this
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ import com.intellij.psi.PsiElement
|
||||
import org.jetbrains.kotlin.fir.*
|
||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
|
||||
import org.jetbrains.kotlin.fir.expressions.FirQualifiedAccess
|
||||
import org.jetbrains.kotlin.fir.types.FirTypeProjection
|
||||
import org.jetbrains.kotlin.fir.visitors.FirTransformer
|
||||
|
||||
@@ -29,4 +30,9 @@ class FirFunctionCallImpl(
|
||||
explicitReceiver = explicitReceiver?.transformSingle(transformer, data)
|
||||
return super<FirAbstractCall>.transformChildren(transformer, data)
|
||||
}
|
||||
|
||||
override fun <D> transformCalleeReference(transformer: FirTransformer<D>, data: D): FirQualifiedAccess {
|
||||
calleeReference = calleeReference.transformSingle(transformer, data)
|
||||
return this
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user