Compare commits

...

41 Commits

Author SHA1 Message Date
Simon Ogorodnik
75ae076c61 Partially implement invoke resolution 2019-05-24 19:47:02 +03:00
Mikhail Glukhikh
420f5c0c12 Preliminary: invokes 2019-05-24 17:14:17 +03:00
Mikhail Glukhikh
735c2a1c92 Add simple test for FIR invoke result (does not work) 2019-05-24 14:36:09 +03:00
Mikhail Glukhikh
7c617718a7 ++ correctly handle overridden Kotlin properties 2019-05-24 14:07:39 +03:00
Mikhail Glukhikh
70a852f072 FIR: fix exception in ConeKotlinType.returnType 2019-05-24 13:12:20 +03:00
Mikhail Glukhikh
bce20ea3e1 Use abstract 'createErrorType' in TypeApproximator 2019-05-24 13:06:39 +03:00
Mikhail Glukhikh
d90749709e FIR Java: correctly handle overridden Kotlin properties in use-site scope 2019-05-24 12:55:36 +03:00
Mikhail Glukhikh
106ab769dd FIR Java: add default constructors 2019-05-24 11:51:55 +03:00
Mikhail Glukhikh
02c90d0690 FIR resolve: check number of parameters when handling Java accessors 2019-05-24 11:13:00 +03:00
Mikhail Glukhikh
0458f94cdc FIR lambda resolve: handle case with expected resolved type properly 2019-05-23 17:17:45 +03:00
Mikhail Glukhikh
6888499081 FIR resolve: do not launch overload conflict resolve for erroneous 2019-05-23 17:17:41 +03:00
Mikhail Glukhikh
ee6da3964a FIR resolve: fix type refs for anonymous functions 2019-05-23 16:12:48 +03:00
Mikhail Glukhikh
b312edad09 FIR resolve test with cast to 'Any' 2019-05-23 16:12:48 +03:00
Mikhail Glukhikh
e73dd86472 FIR resolve bench: count implicit built-in type refs as resolved 2019-05-23 14:20:08 +03:00
Mikhail Glukhikh
d046c4f94d FIR resolve: set implicit Unit type for block without result expression
This fixes most of "implicit error types"
2019-05-23 14:20:08 +03:00
Mikhail Glukhikh
bff89230a5 FIR resolve: record & check implicit extension receiver type properly 2019-05-23 14:20:00 +03:00
Mikhail Glukhikh
b4d4f91255 ++ fix test compilation 2019-05-23 14:19:58 +03:00
Mikhail Glukhikh
81faf01672 FIR tower resolve: add level with implicit extension receiver 2019-05-23 14:19:58 +03:00
Mikhail Glukhikh
3eebe73291 Add FIR resolve test (call extension from extension) 2019-05-23 14:19:57 +03:00
Mikhail Glukhikh
fa0dcddff8 More top-level FIR resolve tests (map, with) 2019-05-23 14:19:56 +03:00
Simon Ogorodnik
58d3178bea Suspend resolution sequence on first inapplicability report 2019-05-23 14:19:56 +03:00
Simon Ogorodnik
997d73b1ce Abstract fir modularized tests 2019-05-23 14:19:55 +03:00
Simon Ogorodnik
d72f04455b Report percents in FirResolveBench 2019-05-23 14:19:55 +03:00
Mikhail Glukhikh
b63d9b03af Consider function calls wrapped into argument in FIR resolve 2019-05-23 14:19:54 +03:00
Mikhail Glukhikh
4fdff4fbd3 Make flexible type data class to improve constraint comparison 2019-05-23 14:19:53 +03:00
Mikhail Glukhikh
f4d00b6574 FIR resolve (by semoro): support correct type inference for generic args
This commit fixes e.g. resolve of listOf() + listOf()
2019-05-23 14:19:53 +03:00
Mikhail Glukhikh
df1460c93b Add FIR resolve test for top-level 'plus' 2019-05-23 14:19:52 +03:00
Simon Ogorodnik
309dd87567 Questionable: disable data class copy function body
This commit is possible but requires copy body generation in BE IR
2019-05-23 14:19:52 +03:00
Simon Ogorodnik
79b713cc75 Store type for already resolved FIR references properly 2019-05-23 14:19:51 +03:00
Simon Ogorodnik
1cf60b8c37 Preliminary: set setter value-parameter type in FIR 2019-05-23 14:19:50 +03:00
Simon Ogorodnik
d0358a57c0 FIR resolve: make companion scope available inside class 2019-05-23 14:19:50 +03:00
Simon Ogorodnik
332cdbf5a7 [FIR] Support withNullability for captured type 2019-05-23 14:19:49 +03:00
Mikhail Glukhikh
bdfa82b010 (by semoro) Set resolved type for lambdas during FIR resolve 2019-05-23 14:19:48 +03:00
Mikhail Glukhikh
8b4c1f6b57 Raw FIR: set enum entry types to kotlin.Enum to avoid their resolve 2019-05-23 14:19:47 +03:00
Mikhail Glukhikh
eed465ae03 (BREAKS tests) Raw FIR: set val setter to null instead of default one 2019-05-23 14:19:46 +03:00
Mikhail Glukhikh
809b8a95b7 Fix FIR Java enhancement of java.util.Map & similar supertypes 2019-05-23 14:19:45 +03:00
Simon Ogorodnik
70ef431227 WIP: Qualifier resolver 2019-05-23 14:19:45 +03:00
Mikhail Glukhikh
c3eea13f78 ~~~ Preliminary: introduce a FIR inspection #KT-29895 Fixed ~~~
Yet we do not take modifications into account
2019-05-23 14:19:44 +03:00
Mikhail Glukhikh
bdf7f65f13 ~~~ IDEA: introduce initial FIR resolution API (declarations only) ~~~ 2019-05-23 14:19:43 +03:00
Simon Ogorodnik
2e1a8741cd ~~~ Use intersection of star projection type-param bounds instead of type 2019-05-23 14:19:43 +03:00
Simon Ogorodnik
fee05d20fe ~~~ Fix test 2019-05-23 14:19:42 +03:00
232 changed files with 2170 additions and 465 deletions

View File

@@ -107,7 +107,7 @@ abstract class ConeTypeParameterType : ConeLookupTagBasedType() {
class ConeFlexibleType(val lowerBound: ConeKotlinType, val upperBound: ConeKotlinType) : ConeKotlinType(),
data class ConeFlexibleType(val lowerBound: ConeKotlinType, val upperBound: ConeKotlinType) : ConeKotlinType(),
FlexibleTypeMarker {
init {

View File

@@ -22,9 +22,7 @@ import org.jetbrains.kotlin.fir.expressions.impl.FirUncheckedNotNullCastImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirUnitExpression
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.directExpansionType
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.withNullability
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.FirTypePlaceholderProjection
@@ -851,7 +849,7 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
withIdentLevel {
generate(property.getter)
generate(property.setter)
property.setter?.let { generate(it) }
}
}
@@ -1167,6 +1165,20 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
keyword("class")
}
private fun FlowContent.generate(resolvedQualifier: FirResolvedQualifier) {
resolved {
val symbolProvider = session.service<FirSymbolProvider>()
val classId = resolvedQualifier.classId
if (classId != null) {
symbolRef(symbolProvider.getClassLikeSymbolByFqName(classId)) {
fqn(classId.relativeClassName)
}
} else {
fqn(resolvedQualifier.packageFqName)
}
}
}
private fun FlowContent.generate(expression: FirExpression) {
exprType(expression.typeRef) {
when (expression) {
@@ -1195,6 +1207,7 @@ class HtmlFirDump internal constructor(private var linkResolver: FirLinkResolver
is FirFunctionCall -> {
generate(expression)
}
is FirResolvedQualifier -> generate(expression)
is FirQualifiedAccessExpression -> generate(expression)
is FirNamedArgumentExpression -> {
simpleName(expression.name)

View File

@@ -494,7 +494,7 @@ internal class Fir2IrVisitor(
}
getter = property.getter.accept(this@Fir2IrVisitor, type) as IrSimpleFunction
if (property.isVar) {
setter = property.setter.accept(this@Fir2IrVisitor, type) as IrSimpleFunction
setter = property.setter!!.accept(this@Fir2IrVisitor, type) as IrSimpleFunction
}
property.annotations.forEach {
annotations += it.accept(this@Fir2IrVisitor, null) as IrConstructorCall

View File

@@ -7,6 +7,9 @@ package org.jetbrains.kotlin.fir.java
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.FirTypeParameter
@@ -206,14 +209,14 @@ class JavaSymbolProvider(
}
declarations += firJavaMethod
}
for (javaConstructor in javaClass.constructors) {
val constructorId = CallableId(classId.packageFqName, classId.relativeClassName, classId.shortClassName)
val javaClassDeclaredConstructors = javaClass.constructors
val constructorId = CallableId(classId.packageFqName, classId.relativeClassName, classId.shortClassName)
fun addJavaConstructor(visibility: Visibility = Visibilities.PUBLIC): FirJavaConstructor {
val constructorSymbol = FirFunctionSymbol(constructorId)
val classTypeParameters = javaClass.typeParameters.convertTypeParameters(javaTypeParameterStack)
val constructorTypeParameters = javaConstructor.typeParameters.convertTypeParameters(javaTypeParameterStack)
val typeParameters = classTypeParameters + constructorTypeParameters
val firJavaConstructor = FirJavaConstructor(
this@JavaSymbolProvider.session, constructorSymbol, javaConstructor.visibility,
this@JavaSymbolProvider.session, constructorSymbol, visibility,
FirResolvedTypeRefImpl(
this@JavaSymbolProvider.session, null,
firSymbol.constructType(
@@ -221,7 +224,18 @@ class JavaSymbolProvider(
)
)
).apply {
this.typeParameters += typeParameters
this.typeParameters += classTypeParameters
}
declarations += firJavaConstructor
return firJavaConstructor
}
if (javaClassDeclaredConstructors.isEmpty() && javaClass.classKind == ClassKind.CLASS) {
addJavaConstructor()
}
for (javaConstructor in javaClassDeclaredConstructors) {
addJavaConstructor(javaConstructor.visibility).apply {
this.typeParameters += javaConstructor.typeParameters.convertTypeParameters(javaTypeParameterStack)
addAnnotationsFrom(this@JavaSymbolProvider.session, javaConstructor, javaTypeParameterStack)
for (valueParameter in javaConstructor.valueParameters) {
valueParameters += valueParameter.toFirValueParameters(
@@ -229,7 +243,6 @@ class JavaSymbolProvider(
)
}
}
declarations += firJavaConstructor
}
}
}

View File

@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.expressions.FirArrayOfCall
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.java.declarations.FirJavaValueParameter
import org.jetbrains.kotlin.fir.java.enhancement.readOnlyToMutable
import org.jetbrains.kotlin.fir.java.types.FirJavaTypeRef
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
@@ -144,7 +145,8 @@ internal fun JavaClassifierType.toConeKotlinTypeWithNullability(
return when (val classifier = classifier) {
is JavaClass -> {
//val classId = classifier.classId!!
val classId = JavaToKotlinClassMap.mapJavaToKotlin(classifier.fqName!!) ?: classifier.classId!!
var classId = JavaToKotlinClassMap.mapJavaToKotlin(classifier.fqName!!) ?: classifier.classId!!
classId = classId.readOnlyToMutable() ?: classId
val lookupTag = ConeClassLikeLookupTagImpl(classId)
lookupTag.constructClassType(

View File

@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.fir.java.topLevelName
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.transformers.firSafeNullable
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.impl.FirClassDeclaredMemberScope
@@ -146,7 +147,7 @@ class KotlinDeserializedJvmSymbolsProvider(
): FirScope? {
val symbol = this.getClassLikeSymbolByFqName(classId) ?: return null
return symbol.firUnsafe<FirRegularClass>().buildDefaultUseSiteScope(session, scopeSession)
return symbol.firSafeNullable<FirRegularClass>()?.buildDefaultUseSiteScope(session, scopeSession)
}
override fun getClassLikeSymbolByFqName(classId: ClassId): ConeClassLikeSymbol? {

View File

@@ -114,7 +114,7 @@ private val KOTLIN_COLLECTIONS = FqName("kotlin.collections")
private val KOTLIN_COLLECTIONS_PREFIX_LENGTH = KOTLIN_COLLECTIONS.asString().length + 1
private fun ClassId.readOnlyToMutable(): ClassId? {
internal fun ClassId.readOnlyToMutable(): ClassId? {
val mutableFqName = JavaToKotlinClassMap.readOnlyToMutable(asSingleFqName().toUnsafe())
return mutableFqName?.let {
ClassId(KOTLIN_COLLECTIONS, FqName(it.asString().substring(KOTLIN_COLLECTIONS_PREFIX_LENGTH)), false)

View File

@@ -315,7 +315,7 @@ class JavaClassEnhancementScope(
return signatureParts.type
}
private val overrideBindCache = mutableMapOf<Name, Map<ConeFunctionSymbol?, List<ConeCallableSymbol>>>()
private val overrideBindCache = mutableMapOf<Name, Map<ConeCallableSymbol?, List<ConeCallableSymbol>>>()
private fun FirCallableMemberDeclaration.overriddenMembers(): List<FirCallableMemberDeclaration> {
val backMap = overrideBindCache.getOrPut(this.name) {

View File

@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutorByMap
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.ProcessorAction.*
import org.jetbrains.kotlin.fir.scopes.impl.FirAbstractProviderBasedScope
import org.jetbrains.kotlin.fir.symbols.ConeCallableSymbol
import org.jetbrains.kotlin.fir.symbols.ConeFunctionSymbol
@@ -32,7 +33,7 @@ import org.jetbrains.kotlin.name.Name
class JavaClassUseSiteScope(
klass: FirRegularClass,
session: FirSession,
internal val superTypesScope: FirScope,
private val superTypesScope: FirScope,
private val declaredMemberScope: FirScope
) : FirAbstractProviderBasedScope(session, lookupInFir = true) {
internal val symbol = klass.symbol
@@ -41,7 +42,7 @@ class JavaClassUseSiteScope(
if (klass is FirJavaClass) klass.javaTypeParameterStack else JavaTypeParameterStack.EMPTY
//base symbol as key, overridden as value
internal val overriddenByBase = mutableMapOf<ConeCallableSymbol, ConeFunctionSymbol?>()
internal val overriddenByBase = mutableMapOf<ConeCallableSymbol, ConeCallableSymbol?>()
private val context: ConeTypeContext = session.typeContext
@@ -99,21 +100,31 @@ class JavaClassUseSiteScope(
}
}
private fun isOverriddenPropertyCheck(overriddenInKotlin: FirProperty, base: FirProperty): Boolean {
val receiverTypeRef = base.receiverTypeRef
val overriddenReceiverTypeRef = overriddenInKotlin.receiverTypeRef
return when {
receiverTypeRef == null -> overriddenReceiverTypeRef == null
overriddenReceiverTypeRef == null -> false
else -> isEqualTypes(receiverTypeRef, overriddenReceiverTypeRef, ConeSubstitutor.Empty)
}
}
internal fun bindOverrides(name: Name) {
val overrideCandidates = mutableSetOf<ConeFunctionSymbol>()
declaredMemberScope.processFunctionsByName(name) {
overrideCandidates += it
ProcessorAction.NEXT
NEXT
}
superTypesScope.processFunctionsByName(name) {
it.getOverridden(overrideCandidates)
ProcessorAction.NEXT
NEXT
}
}
private fun ConeCallableSymbol.getOverridden(candidates: Set<ConeFunctionSymbol>): ConeCallableSymbol? {
private fun ConeCallableSymbol.getOverridden(candidates: Set<ConeCallableSymbol>): ConeCallableSymbol? {
if (overriddenByBase.containsKey(this)) return overriddenByBase[this]
val overriding = when (this) {
@@ -121,23 +132,32 @@ class JavaClassUseSiteScope(
val self = firUnsafe<FirFunction>()
self as FirCallableMemberDeclaration
candidates.firstOrNull {
val member = (it as FirFunctionSymbol).fir as FirFunction
self.modality != Modality.FINAL && isOverriddenFunCheck(member, self)
val overridden = (it as? FirFunctionSymbol)?.fir as? FirFunction
overridden != null && self.modality != Modality.FINAL && isOverriddenFunCheck(overridden, self)
}
}
is FirPropertySymbol -> {
val self = fir as? FirProperty ?: return null
candidates.firstOrNull {
val member = (it as FirFunctionSymbol).fir as FirNamedFunction
self.modality != Modality.FINAL && isOverriddenPropertyCheck(member, self)
when (it) {
is FirFunctionSymbol -> {
val overridden = it.fir as FirNamedFunction
self.modality != Modality.FINAL && isOverriddenPropertyCheck(overridden, self)
}
is FirPropertySymbol -> {
val overridden = it.fir
overridden is FirProperty && self.modality != Modality.FINAL && isOverriddenPropertyCheck(overridden, self)
}
else -> false
}
}
}
is FirAccessorSymbol -> {
val self = fir as FirNamedFunction
candidates.firstOrNull {
val member = (it as FirFunctionSymbol).fir as FirNamedFunction
self.modality != Modality.FINAL && isOverriddenFunCheck(member, self)
val overridden = (it as? FirFunctionSymbol)?.fir as? FirNamedFunction
overridden != null && self.modality != Modality.FINAL && isOverriddenFunCheck(overridden, self)
}
}
else -> error("Unexpected callable symbol: $this")
@@ -153,7 +173,7 @@ class JavaClassUseSiteScope(
overrideCandidates += it
processor(it)
}
) return ProcessorAction.STOP
) return STOP
return superTypesScope.processFunctionsByName(name) {
@@ -161,53 +181,73 @@ class JavaClassUseSiteScope(
if (overriddenBy == null) {
processor(it)
} else {
ProcessorAction.NEXT
NEXT
}
}
}
private fun processAccessorFunctionsByName(
private fun processAccessorFunctionsAndPropertiesByName(
propertyName: Name,
accessorName: Name,
processor: (ConePropertySymbol) -> ProcessorAction
isGetter: Boolean,
processor: (ConeVariableSymbol) -> ProcessorAction
): ProcessorAction {
val overrideCandidates = mutableSetOf<ConeFunctionSymbol>()
if (!declaredMemberScope.processFunctionsByName(accessorName) { functionSymbol ->
overrideCandidates += functionSymbol
val accessorSymbol = FirAccessorSymbol(
accessorId = functionSymbol.callableId,
callableId = CallableId(functionSymbol.callableId.packageName, functionSymbol.callableId.className, propertyName)
)
if (functionSymbol is FirBasedSymbol<*>) {
(functionSymbol.fir as? FirCallableMemberDeclaration)?.let { callableMember -> accessorSymbol.bind(callableMember) }
}
processor(accessorSymbol)
val overrideCandidates = mutableSetOf<ConeCallableSymbol>()
val klass = symbol.fir
if (!declaredMemberScope.processPropertiesByName(propertyName) { variableSymbol ->
overrideCandidates += variableSymbol
processor(variableSymbol)
}
) return ProcessorAction.STOP
) return STOP
if (klass is FirJavaClass) {
if (!declaredMemberScope.processFunctionsByName(accessorName) { functionSymbol ->
if (functionSymbol is FirFunctionSymbol) {
val fir = functionSymbol.fir
if (fir is FirNamedFunction) {
if (fir.isStatic) {
return@processFunctionsByName NEXT
}
when (isGetter) {
true -> if (fir.valueParameters.isNotEmpty()) {
return@processFunctionsByName NEXT
}
false -> if (fir.valueParameters.size != 1) {
return@processFunctionsByName NEXT
}
}
}
}
overrideCandidates += functionSymbol
val accessorSymbol = FirAccessorSymbol(
accessorId = functionSymbol.callableId,
callableId = CallableId(functionSymbol.callableId.packageName, functionSymbol.callableId.className, propertyName)
)
if (functionSymbol is FirBasedSymbol<*>) {
(functionSymbol.fir as? FirCallableMemberDeclaration)?.let { callableMember -> accessorSymbol.bind(callableMember) }
}
processor(accessorSymbol)
}
) return STOP
}
return superTypesScope.processPropertiesByName(propertyName) {
val firCallableMember = (it as FirBasedSymbol<*>).fir as? FirCallableMemberDeclaration
if (firCallableMember?.isStatic == true) {
ProcessorAction.NEXT
NEXT
} else {
val overriddenBy = it.getOverridden(overrideCandidates)
if (overriddenBy == null && it is ConePropertySymbol) {
processor(it)
} else {
ProcessorAction.NEXT
NEXT
}
}
}
}
override fun processPropertiesByName(name: Name, processor: (ConeVariableSymbol) -> ProcessorAction): ProcessorAction {
if (!declaredMemberScope.processPropertiesByName(name) {
processor(it)
}
) return ProcessorAction.STOP
val getterName = Name.identifier(getterPrefix + name.asString().capitalize())
return processAccessorFunctionsByName(name, getterName, processor)
return processAccessorFunctionsAndPropertiesByName(name, getterName, isGetter = true, processor = processor)
}
companion object {

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2010-2019 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
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import org.w3c.dom.Node
import org.w3c.dom.NodeList
import java.io.File
import javax.xml.parsers.DocumentBuilderFactory
data class ModuleData(
val name: String,
val qualifiedName: String,
val classpath: List<File>,
val sources: List<File>,
val javaSourceRoots: List<File>
)
private fun NodeList.toList(): List<Node> {
val list = mutableListOf<Node>()
for (index in 0 until this.length) {
list += item(index)
}
return list
}
private val Node.childNodesList get() = childNodes.toList()
abstract class AbstractModularizedTest : KtUsefulTestCase() {
private fun loadModule(file: File): ModuleData {
val factory = DocumentBuilderFactory.newInstance()
factory.isIgnoringComments = true
factory.isIgnoringElementContentWhitespace = true
val builder = factory.newDocumentBuilder()
val document = builder.parse(file)
val moduleElement = document.childNodes.item(0).childNodesList.first { it.nodeType == Node.ELEMENT_NODE }
val moduleName = moduleElement.attributes.getNamedItem("name").nodeValue
val outputDir = moduleElement.attributes.getNamedItem("outputDir").nodeValue
val qualifiedModuleName = outputDir.substringAfterLast("/")
val javaSourceRoots = mutableListOf<File>()
val classpath = mutableListOf<File>()
val sources = mutableListOf<File>()
for (index in 0 until moduleElement.childNodes.length) {
val item = moduleElement.childNodes.item(index)
if (item.nodeName == "classpath") {
val path = item.attributes.getNamedItem("path").nodeValue
if (path != outputDir) {
classpath += File(path)
}
}
if (item.nodeName == "javaSourceRoots") {
javaSourceRoots += File(item.attributes.getNamedItem("path").nodeValue)
}
if (item.nodeName == "sources") {
sources += File(item.attributes.getNamedItem("path").nodeValue)
}
}
return ModuleData(moduleName, qualifiedModuleName, classpath, sources, javaSourceRoots)
}
protected abstract fun beforePass()
protected abstract fun afterPass()
protected abstract fun processModule(moduleData: ModuleData): ProcessorAction
protected fun runTestOnce(pass: Int) {
beforePass()
val testDataPath = "/Users/jetbrains/jps"
val root = File(testDataPath)
println("BASE PATH: ${root.absolutePath}")
val modules =
root.listFiles().sortedBy { it.lastModified() }.map { loadModule(it) }
.filter { it.qualifiedName == "kotlin.idea.main" }
for (module in modules.progress(step = 0.0) { "Analyzing ${it.qualifiedName}" }) {
if (processModule(module).stop()) {
break
}
}
afterPass()
}
}

View File

@@ -21,30 +21,17 @@ import org.jetbrains.kotlin.fir.dump.MultiModuleHtmlFirDump
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.impl.FirProviderImpl
import org.jetbrains.kotlin.fir.resolve.transformers.FirTotalResolveTransformer
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import org.w3c.dom.Node
import org.w3c.dom.NodeList
import java.io.File
import java.io.PrintStream
import java.text.SimpleDateFormat
import java.util.*
import javax.xml.parsers.DocumentBuilderFactory
import kotlin.system.measureNanoTime
private fun NodeList.toList(): List<Node> {
val list = mutableListOf<Node>()
for (index in 0 until this.length) {
list += item(index)
}
return list
}
private val Node.childNodesList get() = childNodes.toList()
private const val FAIL_FAST = true
private const val DUMP_FIR = true
@@ -52,18 +39,9 @@ private const val FIR_DUMP_PATH = "tmp/firDump"
private const val FIR_HTML_DUMP_PATH = "tmp/firDump-html"
private const val FIR_LOGS_PATH = "tmp/fir-logs"
private data class ModuleData(
val name: String,
val qualifiedName: String,
val classpath: List<File>,
val sources: List<File>,
val javaSourceRoots: List<File>
)
private const val PASSES = 1
class FirResolveModularizedTotalKotlinTest : KtUsefulTestCase() {
class FirResolveModularizedTotalKotlinTest : AbstractModularizedTest() {
private lateinit var bench: FirResolveBench
private lateinit var dump: MultiModuleHtmlFirDump
@@ -115,7 +93,7 @@ class FirResolveModularizedTotalKotlinTest : KtUsefulTestCase() {
}
}
private fun processModule(moduleData: ModuleData) {
override fun processModule(moduleData: ModuleData): ProcessorAction {
val configurationKind = ConfigurationKind.ALL
val testJdkKind = TestJdkKind.FULL_JDK
@@ -138,63 +116,15 @@ class FirResolveModularizedTotalKotlinTest : KtUsefulTestCase() {
runAnalysis(moduleData, environment)
Disposer.dispose(disposable)
if (bench.hasFiles && FAIL_FAST) return ProcessorAction.STOP
return ProcessorAction.NEXT
}
private fun loadModule(file: File): ModuleData {
val factory = DocumentBuilderFactory.newInstance()
factory.isIgnoringComments = true
factory.isIgnoringElementContentWhitespace = true
val builder = factory.newDocumentBuilder()
val document = builder.parse(file)
val moduleElement = document.childNodes.item(0).childNodesList.first { it.nodeType == Node.ELEMENT_NODE }
val moduleName = moduleElement.attributes.getNamedItem("name").nodeValue
val outputDir = moduleElement.attributes.getNamedItem("outputDir").nodeValue
val qualifiedModuleName = outputDir.substringAfterLast("/")
val javaSourceRoots = mutableListOf<File>()
val classpath = mutableListOf<File>()
val sources = mutableListOf<File>()
for (index in 0 until moduleElement.childNodes.length) {
val item = moduleElement.childNodes.item(index)
if (item.nodeName == "classpath") {
val path = item.attributes.getNamedItem("path").nodeValue
if (path != outputDir) {
classpath += File(path)
}
}
if (item.nodeName == "javaSourceRoots") {
javaSourceRoots += File(item.attributes.getNamedItem("path").nodeValue)
}
if (item.nodeName == "sources") {
sources += File(item.attributes.getNamedItem("path").nodeValue)
}
}
return ModuleData(moduleName, qualifiedModuleName, classpath, sources, javaSourceRoots)
}
private fun runTestOnce(pass: Int) {
override fun beforePass() {
if (DUMP_FIR) dump = MultiModuleHtmlFirDump(File(FIR_HTML_DUMP_PATH))
val testDataPath = "/Users/jetbrains/jps"
val root = File(testDataPath)
println("BASE PATH: ${root.absolutePath}")
val modules =
root.listFiles().sortedBy { it.lastModified() }.map { loadModule(it) }
// .sortedByDescending { it.name == "idea" }
for (module in modules.progress(step = 0.0) { "Analyzing ${it.qualifiedName}" }) {
processModule(module)
if (bench.hasFiles && FAIL_FAST) {
break
}
}
}
override fun afterPass() {
bench.report(System.out, errorTypeReports = false)
saveReport()

View File

@@ -15,37 +15,21 @@ import org.jetbrains.kotlin.cli.common.messages.MessageCollector
import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment
import org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler
import org.jetbrains.kotlin.config.*
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.test.ConfigurationKind
import org.jetbrains.kotlin.test.KotlinTestUtils
import org.jetbrains.kotlin.test.TestJdkKind
import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase
import org.w3c.dom.Node
import org.w3c.dom.NodeList
import java.io.File
import javax.xml.parsers.DocumentBuilderFactory
import kotlin.system.measureNanoTime
private fun NodeList.toList(): List<Node> {
val list = mutableListOf<Node>()
for (index in 0 until this.length) {
list += item(index)
}
return list
}
private val Node.childNodesList get() = childNodes.toList()
private data class XModuleData(val name: String, val classpath: List<File>, val sources: List<File>, val javaSourceRoots: List<File>)
class NonFirResolveModularizedTotalKotlinTest : KtUsefulTestCase() {
class NonFirResolveModularizedTotalKotlinTest : AbstractModularizedTest() {
private var totalTime = 0L
private var files = 0
private fun runAnalysis(moduleData: XModuleData, environment: KotlinCoreEnvironment) {
private fun runAnalysis(moduleData: ModuleData, environment: KotlinCoreEnvironment) {
val project = environment.project
val time = measureNanoTime {
@@ -58,7 +42,7 @@ class NonFirResolveModularizedTotalKotlinTest : KtUsefulTestCase() {
}
private fun processModule(moduleData: XModuleData) {
override fun processModule(moduleData: ModuleData): ProcessorAction {
val configurationKind = ConfigurationKind.ALL
val testJdkKind = TestJdkKind.FULL_JDK
@@ -92,73 +76,19 @@ class NonFirResolveModularizedTotalKotlinTest : KtUsefulTestCase() {
})
val environment = KotlinCoreEnvironment.createForTests(disposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES)
// Extensions.getArea(environment.project)
// .getExtensionPoint(PsiElementFinder.EP_NAME)
// .unregisterExtension(JavaElementFinder::class.java)
println("Processing module: ${moduleData.name}")
runAnalysis(moduleData, environment)
Disposer.dispose(disposable)
}
private fun loadModule(file: File): XModuleData {
val factory = DocumentBuilderFactory.newInstance()
factory.isIgnoringComments = true
factory.isIgnoringElementContentWhitespace = true
val builder = factory.newDocumentBuilder()
val document = builder.parse(file)
val moduleElement = document.childNodes.item(0).childNodesList.first { it.nodeType == Node.ELEMENT_NODE }
val moduleName = moduleElement.attributes.getNamedItem("name").nodeValue
val javaSourceRoots = mutableListOf<File>()
val classpath = mutableListOf<File>()
val sources = mutableListOf<File>()
for (index in 0 until moduleElement.childNodes.length) {
val item = moduleElement.childNodes.item(index)
if (item.nodeName == "classpath") {
classpath += File(item.attributes.getNamedItem("path").nodeValue)
}
if (item.nodeName == "javaSourceRoots") {
javaSourceRoots += File(item.attributes.getNamedItem("path").nodeValue)
}
if (item.nodeName == "sources") {
sources += File(item.attributes.getNamedItem("path").nodeValue)
}
}
return XModuleData(moduleName, classpath, sources, javaSourceRoots)
return ProcessorAction.NEXT
}
private fun runTestLocal() {
val testDataPath = "/Users/jetbrains/jps"
val root = File(testDataPath)
println("BASE PATH: ${root.absolutePath}")
val modules =
root.listFiles().sortedBy { it.lastModified() }.map { loadModule(it) }
// .sortedBy { !it.sources.any { it.nameWithoutExtension == "KotlinSearchEverywhereClassifier" } }
for (module in modules.progress { "Analyzing ${it.name}" }) {
processModule(module)
}
println("Total time: ${totalTime * 1e-6} ms, ${(totalTime * 1e-6) / files} ms per file")
totalTime = 0
files = 0
}
override fun afterPass() {}
override fun beforePass() {}
fun testTotalKotlin() {
//Thread.sleep(5000)
for (i in 0..2) {
println("Pass $i")
runTestLocal()
runTestOnce(i)
}
}
}

View File

@@ -14,10 +14,7 @@ import org.jetbrains.kotlin.fir.declarations.FirProperty
import org.jetbrains.kotlin.fir.declarations.impl.FirClassImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirMemberFunctionImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirFunctionCallImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirReturnExpressionImpl
import org.jetbrains.kotlin.fir.expressions.impl.FirSingleExpressionBlock
import org.jetbrains.kotlin.fir.expressions.impl.*
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.symbols.CallableId
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
@@ -89,7 +86,7 @@ internal fun KtClassOrObject.generateCopyFunction(
isInfix = false, isInline = false,
isTailRec = false, isExternal = false,
isSuspend = false, receiverTypeRef = null,
returnTypeRef = FirImplicitTypeRefImpl(session, this)
returnTypeRef = firPrimaryConstructor.returnTypeRef//FirImplicitTypeRefImpl(session, this)
).apply {
val copyFunction = this
val zippedParameters =
@@ -105,29 +102,31 @@ internal fun KtClassOrObject.generateCopyFunction(
isCrossinline = false, isNoinline = false, isVararg = false
)
}
body = FirSingleExpressionBlock(
session,
FirReturnExpressionImpl(
session, this@generateCopyFunction,
FirFunctionCallImpl(session, this@generateCopyFunction).apply {
calleeReference = FirResolvedCallableReferenceImpl(
session, this@generateCopyFunction, firClass.name,
firPrimaryConstructor.symbol
)
}.apply {
for ((ktParameter, firParameter) in primaryConstructorParameters.zip(valueParameters)) {
this.arguments += FirQualifiedAccessExpressionImpl(session, ktParameter).apply {
calleeReference = FirResolvedCallableReferenceImpl(
session, ktParameter, firParameter.name, firParameter.symbol
)
}
}
}
).apply {
target = FirFunctionTarget(null)
target.bind(copyFunction)
}
)
body = FirEmptyExpressionBlock(session)
// body = FirSingleExpressionBlock(
// session,
// FirReturnExpressionImpl(
// session, this@generateCopyFunction,
// FirFunctionCallImpl(session, this@generateCopyFunction).apply {
// calleeReference = FirResolvedCallableReferenceImpl(
// session, this@generateCopyFunction, firClass.name,
// firPrimaryConstructor.symbol
// )
// }.apply {
// for ((ktParameter, firParameter) in primaryConstructorParameters.zip(valueParameters)) {
// this.arguments += FirQualifiedAccessExpressionImpl(session, ktParameter).apply {
// calleeReference = FirResolvedCallableReferenceImpl(
// session, ktParameter, firParameter.name, firParameter.symbol
// )
// }
// }
// }
// ).apply {
// target = FirFunctionTarget(null)
// target.bind(copyFunction)
// }
// )
}
)
}

View File

@@ -174,7 +174,7 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
} else {
FirSingleExpressionBlock(
session,
FirExpressionStub(session, this).toReturn()
FirExpressionStub(session, null).toReturn()
)
}
else -> {
@@ -281,7 +281,7 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
)
},
getter = FirDefaultPropertyGetter(session, this, type, visibility),
setter = FirDefaultPropertySetter(session, this, type, visibility),
setter = if (isMutable) FirDefaultPropertySetter(session, this, type, visibility) else null,
delegate = null
)
extractAnnotationsTo(firProperty)
@@ -796,7 +796,7 @@ class RawFirBuilder(val session: FirSession, val stubMode: Boolean) {
isVar,
initializer,
property.getter.toFirPropertyAccessor(property, propertyType, isGetter = true),
property.setter.toFirPropertyAccessor(property, propertyType, isGetter = false),
if (isVar) property.setter.toFirPropertyAccessor(property, propertyType, isGetter = false) else null,
if (property.hasDelegate()) {
{ property.delegate?.expression }.toFirExpression("Should have delegate")
} else null

View File

@@ -159,6 +159,7 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
val getterFlags = if (proto.hasGetterFlags()) proto.getterFlags else flags
val setterFlags = if (proto.hasSetterFlags()) proto.setterFlags else flags
val isVar = Flags.IS_VAR.get(flags)
return FirMemberPropertyImpl(
c.session,
@@ -174,10 +175,12 @@ class FirMemberDeserializer(private val c: FirDeserializationContext) {
isLateInit = Flags.IS_LATEINIT.get(flags),
receiverTypeRef = proto.receiverType(c.typeTable)?.toTypeRef(local),
returnTypeRef = returnTypeRef,
isVar = Flags.IS_VAR.get(flags),
isVar = isVar,
initializer = null,
getter = FirDefaultPropertyGetter(c.session, null, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(getterFlags))),
setter = FirDefaultPropertySetter(c.session, null, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags))),
setter = if (isVar) {
FirDefaultPropertySetter(c.session, null, returnTypeRef, ProtoEnumFlags.visibility(Flags.VISIBILITY.get(setterFlags)))
} else null,
delegate = null
).apply {
typeParameters += local.typeDeserializer.ownTypeParameters.map { it.firUnsafe() }

View File

@@ -6,14 +6,16 @@
package org.jetbrains.kotlin.fir.resolve
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.expandedConeType
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeAliasSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeAbbreviatedTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeClassTypeImpl
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.types.Variance
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
@@ -115,6 +117,7 @@ fun <T : ConeKotlinType> T.withNullability(nullability: ConeNullability): T {
is ConeTypeParameterTypeImpl -> ConeTypeParameterTypeImpl(lookupTag, nullability.isNullable) as T
is ConeFlexibleType -> ConeFlexibleType(lowerBound.withNullability(nullability), upperBound.withNullability(nullability)) as T
is ConeTypeVariableType -> ConeTypeVariableType(nullability, lookupTag) as T
is ConeCapturedType -> ConeCapturedType(captureStatus, lowerType, nullability, constructor) as T
else -> error("sealed: ${this::class}")
}
}
@@ -136,3 +139,22 @@ fun <T : ConeKotlinType> T.withArguments(arguments: Array<ConeKotlinTypeProjecti
else -> error("Not supported: $this: ${this.render()}")
}
}
fun FirFunction.constructFunctionalTypeRef(session: FirSession): FirResolvedTypeRef {
val receiverTypeRef = when (this) {
is FirNamedFunction -> receiverTypeRef
is FirAnonymousFunction -> receiverTypeRef
else -> null
}
val receiverType = receiverTypeRef?.coneTypeUnsafe<ConeKotlinType>()
val parameters = valueParameters.map {
it.returnTypeRef.coneTypeSafe<ConeKotlinType>() ?: ConeKotlinErrorType("No type for parameter")
}
val rawReturnType = (this as FirTypedDeclaration).returnTypeRef.coneTypeUnsafe<ConeKotlinType>()
val receiverAndParameterTypes = listOfNotNull(receiverType) + parameters + listOf(rawReturnType)
val functionalTypeId = StandardClassIds.byName("Function${receiverAndParameterTypes.size - 1}")
val functionalType = functionalTypeId(session.service()).constructType(receiverAndParameterTypes.toTypedArray(), isNullable = false)
return FirResolvedTypeRefImpl(session, psi, functionalType)
}

View File

@@ -29,10 +29,7 @@ fun ConeKotlinType.scope(useSiteSession: FirSession, scopeSession: ScopeSession)
// For ConeClassLikeType they might be a type alias instead of a regular class
// TODO: support that case and switch back to `firUnsafe` instead of `firSafeNullable`
val fir = this.lookupTag.toSymbol(useSiteSession)?.firSafeNullable<FirRegularClass>() ?: return null
val companionScope = fir.companionObject?.buildUseSiteScope(useSiteSession, scopeSession)
val ownScope = wrapSubstitutionScopeIfNeed(useSiteSession, fir.buildUseSiteScope(useSiteSession, scopeSession)!!, scopeSession)
if (companionScope != null) FirCompositeScope(mutableListOf(ownScope, companionScope)) else ownScope
wrapSubstitutionScopeIfNeed(useSiteSession, fir.buildUseSiteScope(useSiteSession, scopeSession)!!, scopeSession)
}
is ConeTypeParameterType -> {
// TODO: support LibraryTypeParameterSymbol or get rid of it

View File

@@ -10,6 +10,7 @@ import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.render
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
import org.jetbrains.kotlin.fir.resolve.withNullability
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.resolve.calls.inference.ConstraintSystemBuilder
@@ -37,7 +38,8 @@ fun resolveArgumentExpression(
typeProvider: (FirExpression) -> FirTypeRef?
) {
return when (argument) {
is FirQualifiedAccessExpression, is FirFunctionCall -> resolvePlainExpressionArgument(
is FirFunctionCall -> resolveSubCallArgument(csBuilder, argument, expectedType, sink, isReceiver, isSafeCall, typeProvider)
is FirQualifiedAccessExpression -> resolvePlainExpressionArgument(
csBuilder,
argument,
expectedType,
@@ -78,6 +80,21 @@ fun resolveArgumentExpression(
}
}
fun resolveSubCallArgument(
csBuilder: ConstraintSystemBuilder,
argument: FirFunctionCall,
expectedType: ConeKotlinType,
sink: CheckerSink,
isReceiver: Boolean,
isSafeCall: Boolean,
typeProvider: (FirExpression) -> FirTypeRef?
) {
val candidate = argument.candidate() ?: return resolvePlainExpressionArgument(csBuilder, argument, expectedType, sink, isReceiver, isSafeCall, typeProvider)
val type = sink.components.returnTypeCalculator.tryCalculateReturnType(candidate.symbol.firUnsafe()).coneTypeUnsafe<ConeKotlinType>()
val argumentType = candidate.substitutor.substituteOrSelf(type)
resolvePlainArgumentType(csBuilder, argumentType, expectedType, sink, isReceiver, isSafeCall)
}
fun resolvePlainExpressionArgument(
csBuilder: ConstraintSystemBuilder,
argument: FirExpression,

View File

@@ -8,16 +8,23 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirImportImpl
import org.jetbrains.kotlin.fir.declarations.impl.FirResolvedImportImpl
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.expressions.impl.FirQualifiedAccessExpressionImpl
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.resolve.FirSymbolProvider
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.scope
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculatorWithJump
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
import org.jetbrains.kotlin.fir.scopes.FirPosition
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.impl.FirExplicitSimpleImportingScope
import org.jetbrains.kotlin.fir.scopes.processClassifiersByNameWithAction
import org.jetbrains.kotlin.fir.service
import org.jetbrains.kotlin.fir.symbols.*
@@ -25,11 +32,14 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirFunctionSymbol
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
import org.jetbrains.kotlin.resolve.calls.model.PostponedResolvedAtomMarker
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
import org.jetbrains.kotlin.utils.addToStdlib.cast
import kotlin.coroutines.*
import kotlin.coroutines.intrinsics.createCoroutineUnintercepted
class CallInfo(
val callKind: CallKind,
@@ -49,24 +59,45 @@ class CallInfo(
interface CheckerSink {
fun reportApplicability(new: CandidateApplicability)
suspend fun yield()
suspend fun yieldApplicability(new: CandidateApplicability) {
reportApplicability(new)
yield()
}
val components: InferenceComponents
suspend fun yieldIfNeed()
}
class CheckerSinkImpl(override val components: InferenceComponents) : CheckerSink {
class CheckerSinkImpl(override val components: InferenceComponents, var continuation: Continuation<Unit>? = null) : CheckerSink {
var current = CandidateApplicability.RESOLVED
override fun reportApplicability(new: CandidateApplicability) {
if (new < current) current = new
}
override suspend fun yield() = kotlin.coroutines.intrinsics.suspendCoroutineUninterceptedOrReturn<Unit> {
continuation = it
kotlin.coroutines.intrinsics.COROUTINE_SUSPENDED
}
override suspend fun yieldIfNeed() {
if (current < CandidateApplicability.SYNTHETIC_RESOLVED) {
yield()
}
}
}
class Candidate(
val symbol: ConeSymbol,
val dispatchReceiverValue: ClassDispatchReceiverValue?,
val implicitExtensionReceiverValue: ImplicitReceiverValue?,
val explicitReceiverKind: ExplicitReceiverKind,
private val inferenceComponents: InferenceComponents,
private val baseSystem: ConstraintStorage
private val baseSystem: ConstraintStorage,
val callInfo: CallInfo
) {
val system by lazy {
val system = inferenceComponents.createConstraintSystem()
@@ -118,7 +149,11 @@ interface TowerScopeLevel {
): ProcessorAction
interface TowerScopeLevelProcessor<T : ConeSymbol> {
fun consumeCandidate(symbol: T, dispatchReceiverValue: ClassDispatchReceiverValue?): ProcessorAction
fun consumeCandidate(
symbol: T,
dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue?
): ProcessorAction
}
object Empty : TowerScopeLevel {
@@ -155,7 +190,7 @@ abstract class SessionBasedTowerLevel(val session: FirSession) : TowerScopeLevel
class MemberScopeTowerLevel(
session: FirSession,
val dispatchReceiver: ReceiverValue,
val implicitExtensionReceiver: ReceiverValue? = null
val implicitExtensionReceiver: ImplicitReceiverValue? = null
) : SessionBasedTowerLevel(session) {
private fun <T : ConeSymbol> processMembers(
@@ -170,9 +205,9 @@ class MemberScopeTowerLevel(
if (candidate is ConeCallableSymbol && candidate.hasConsistentExtensionReceiver(extensionReceiver)) {
// NB: we do not check dispatchReceiverValue != null here,
// because of objects & constructors (see comments in dispatchReceiverValue() implementation)
output.consumeCandidate(candidate, candidate.dispatchReceiverValue())
output.consumeCandidate(candidate, candidate.dispatchReceiverValue(), implicitExtensionReceiver)
} else if (candidate is ConeClassLikeSymbol) {
output.consumeCandidate(candidate, null)
output.consumeCandidate(candidate, null, implicitExtensionReceiver)
} else {
ProcessorAction.NEXT
}
@@ -180,7 +215,7 @@ class MemberScopeTowerLevel(
) return ProcessorAction.STOP
val withSynthetic = FirSyntheticPropertiesScope(session, scope, ReturnTypeCalculatorWithJump(session))
return withSynthetic.processScopeMembers { symbol ->
output.consumeCandidate(symbol, symbol.dispatchReceiverValue())
output.consumeCandidate(symbol, symbol.dispatchReceiverValue(), implicitExtensionReceiver)
}
}
@@ -217,7 +252,8 @@ private fun ConeCallableSymbol.hasExtensionReceiver(): Boolean = (this as? FirCa
// (if explicit receiver exists, it always *should* be an extension receiver)
class ScopeTowerLevel(
session: FirSession,
val scope: FirScope
val scope: FirScope,
val implicitExtensionReceiver: ImplicitReceiverValue? = null
) : SessionBasedTowerLevel(session) {
override fun <T : ConeSymbol> processElementsByName(
token: TowerScopeLevel.Token<T>,
@@ -225,27 +261,36 @@ class ScopeTowerLevel(
explicitReceiver: ExpressionReceiverValue?,
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
): ProcessorAction {
if (explicitReceiver != null && implicitExtensionReceiver != null) {
return ProcessorAction.NEXT
}
val extensionReceiver = explicitReceiver ?: implicitExtensionReceiver
return when (token) {
TowerScopeLevel.Token.Properties -> scope.processPropertiesByName(name) { candidate ->
if (candidate.hasConsistentExtensionReceiver(explicitReceiver) && candidate.dispatchReceiverValue() == null) {
processor.consumeCandidate(candidate as T, dispatchReceiverValue = null)
if (candidate.hasConsistentExtensionReceiver(extensionReceiver) && candidate.dispatchReceiverValue() == null) {
processor.consumeCandidate(
candidate as T, dispatchReceiverValue = null,
implicitExtensionReceiverValue = implicitExtensionReceiver
)
} else {
ProcessorAction.NEXT
}
}
TowerScopeLevel.Token.Functions -> scope.processFunctionsByName(name) { candidate ->
// TODO: fix implicit receiver
if (candidate.hasConsistentExtensionReceiver(explicitReceiver) && candidate.dispatchReceiverValue() == null) {
processor.consumeCandidate(candidate as T, dispatchReceiverValue = null)
if (candidate.hasConsistentExtensionReceiver(extensionReceiver) && candidate.dispatchReceiverValue() == null) {
processor.consumeCandidate(
candidate as T, dispatchReceiverValue = null,
implicitExtensionReceiverValue = implicitExtensionReceiver
)
} else {
ProcessorAction.NEXT
}
}
TowerScopeLevel.Token.Objects -> scope.processClassifiersByNameWithAction(name, FirPosition.OTHER) {
processor.consumeCandidate(
it as T,
dispatchReceiverValue = null
it as T, dispatchReceiverValue = null,
implicitExtensionReceiverValue = null
)
}
}
@@ -253,21 +298,112 @@ class ScopeTowerLevel(
}
/**
* Handles only statics and top-levels, DOES NOT handle objects/companions members
*/
class QualifiedReceiverTowerLevel(session: FirSession) : SessionBasedTowerLevel(session) {
override fun <T : ConeSymbol> processElementsByName(
token: TowerScopeLevel.Token<T>,
name: Name,
explicitReceiver: ExpressionReceiverValue?,
processor: TowerScopeLevel.TowerScopeLevelProcessor<T>
): ProcessorAction {
val qualifiedReceiver = explicitReceiver?.explicitReceiverExpression as FirResolvedQualifier
val scope = FirExplicitSimpleImportingScope(
listOf(
FirResolvedImportImpl(
session,
FirImportImpl(session, null, FqName.topLevel(name), false, null),
qualifiedReceiver.packageFqName,
qualifiedReceiver.relativeClassFqName
)
), session
)
return if (token == TowerScopeLevel.Token.Objects) {
scope.processClassifiersByNameWithAction(name, FirPosition.OTHER) {
processor.consumeCandidate(it as T, null, null)
}
} else {
scope.processCallables(name, token.cast()) {
val fir = it.firUnsafe<FirCallableMemberDeclaration>()
if (fir.isStatic || it.callableId.classId == null) {
processor.consumeCandidate(it as T, null, null)
} else {
ProcessorAction.NEXT
}
}
}
}
}
class QualifiedReceiverTowerDataConsumer<T : ConeSymbol>(
val session: FirSession,
val name: Name,
val token: TowerScopeLevel.Token<T>,
val explicitReceiver: ExpressionReceiverValue,
val candidateFactory: CandidateFactory,
val resultCollector: CandidateCollector
) : TowerDataConsumer() {
override fun consume(
kind: TowerDataKind,
towerScopeLevel: TowerScopeLevel,
group: Int
): ProcessorAction {
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
if (kind != TowerDataKind.EMPTY) return ProcessorAction.NEXT
return QualifiedReceiverTowerLevel(session).processElementsByName(
token,
name,
explicitReceiver,
processor = object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(
symbol: T,
dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue?
): ProcessorAction {
assert(dispatchReceiverValue == null)
resultCollector.consumeCandidate(
group,
candidateFactory.createCandidate(
symbol,
dispatchReceiverValue = null,
implicitExtensionReceiverValue = null,
explicitReceiverKind = ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
)
)
return ProcessorAction.NEXT
}
}
)
}
}
abstract class TowerDataConsumer {
abstract fun consume(
kind: TowerDataKind,
towerScopeLevel: TowerScopeLevel,
resultCollector: CandidateCollector,
// resultCollector: CandidateCollector,
group: Int
): ProcessorAction
private var processed = -1
private var stopGroup = Int.MAX_VALUE
fun checkSkip(group: Int, resultCollector: CandidateCollector): Boolean {
fun skipGroup(group: Int, resultCollector: CandidateCollector): Boolean {
if (resultCollector.isSuccess() && stopGroup == Int.MAX_VALUE) {
stopGroup = group
}
return group > stopGroup
if (group > processed) {
processed = group
}
if (group < processed) {
return true
}
if (group > stopGroup) return true
return false
}
}
@@ -276,39 +412,94 @@ fun createVariableAndObjectConsumer(
session: FirSession,
name: Name,
callInfo: CallInfo,
inferenceComponents: InferenceComponents
inferenceComponents: InferenceComponents,
resultCollector: CandidateCollector
): TowerDataConsumer {
return PrioritizedTowerDataConsumer(
resultCollector,
createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Properties,
callInfo,
inferenceComponents
inferenceComponents,
resultCollector
),
createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Objects,
callInfo,
inferenceComponents
inferenceComponents,
resultCollector
)
)
}
fun createFunctionConsumer(
fun createSimpleFunctionConsumer(
session: FirSession,
name: Name,
callInfo: CallInfo,
inferenceComponents: InferenceComponents
inferenceComponents: InferenceComponents,
resultCollector: CandidateCollector
): TowerDataConsumer {
return createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Functions,
callInfo,
inferenceComponents
inferenceComponents,
resultCollector
)
}
fun createFunctionConsumer(
session: FirSession,
name: Name,
callInfo: CallInfo,
inferenceComponents: InferenceComponents,
resultCollector: CandidateCollector,
callResolver: CallResolver
): TowerDataConsumer {
val varCallInfo = CallInfo(
CallKind.VariableAccess,
callInfo.explicitReceiver,
emptyList(),
callInfo.isSafeCall,
callInfo.typeArguments,
inferenceComponents.session,
callInfo.containingFile,
callInfo.container,
callInfo.typeProvider
)
return PrioritizedTowerDataConsumer(
resultCollector,
createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Functions,
callInfo,
inferenceComponents,
resultCollector
),
MultiplexerTowerDataConsumer(resultCollector).apply {
addConsumer(
createSimpleConsumer(
session,
name,
TowerScopeLevel.Token.Properties,
varCallInfo,
inferenceComponents,
InvokeCandidateCollector(
callResolver,
invokeCallInfo = callInfo,
components = inferenceComponents,
multiplexer = this
)
)
)
}
)
}
@@ -318,36 +509,49 @@ fun createSimpleConsumer(
name: Name,
token: TowerScopeLevel.Token<*>,
callInfo: CallInfo,
inferenceComponents: InferenceComponents
inferenceComponents: InferenceComponents,
resultCollector: CandidateCollector
): TowerDataConsumer {
val factory = CandidateFactory(inferenceComponents, callInfo)
return if (callInfo.explicitReceiver != null) {
ExplicitReceiverTowerDataConsumer(
session,
name,
token,
ExpressionReceiverValue(callInfo.explicitReceiver, callInfo.typeProvider),
factory
)
val explicitReceiver = callInfo.explicitReceiver
return if (explicitReceiver != null) {
val receiverValue = ExpressionReceiverValue(explicitReceiver, callInfo.typeProvider)
if (explicitReceiver is FirResolvedQualifier) {
val qualified =
QualifiedReceiverTowerDataConsumer(session, name, token, receiverValue, factory, resultCollector)
if (explicitReceiver.classId != null) {
PrioritizedTowerDataConsumer(
resultCollector,
qualified,
ExplicitReceiverTowerDataConsumer(session, name, token, receiverValue, factory, resultCollector)
)
} else {
qualified
}
} else {
ExplicitReceiverTowerDataConsumer(session, name, token, receiverValue, factory, resultCollector)
}
} else {
NoExplicitReceiverTowerDataConsumer(session, name, token, factory)
NoExplicitReceiverTowerDataConsumer(session, name, token, factory, resultCollector)
}
}
class PrioritizedTowerDataConsumer(
val resultCollector: CandidateCollector,
vararg val consumers: TowerDataConsumer
) : TowerDataConsumer() {
override fun consume(
kind: TowerDataKind,
towerScopeLevel: TowerScopeLevel,
resultCollector: CandidateCollector,
group: Int
): ProcessorAction {
if (checkSkip(group, resultCollector)) return ProcessorAction.NEXT
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
for ((index, consumer) in consumers.withIndex()) {
val action = consumer.consume(kind, towerScopeLevel, resultCollector, group * consumers.size + index)
val action = consumer.consume(kind, towerScopeLevel, group * consumers.size + index)
if (action.stop()) {
return ProcessorAction.STOP
}
@@ -356,22 +560,68 @@ class PrioritizedTowerDataConsumer(
}
}
class MultiplexerTowerDataConsumer(
val resultCollector: CandidateCollector
) : TowerDataConsumer() {
val consumers = mutableListOf<TowerDataConsumer>()
val newConsumers = mutableListOf<TowerDataConsumer>()
val kinds = mutableListOf<TowerDataKind>()
val groups = mutableListOf<Int>()
val levels = mutableListOf<TowerScopeLevel>()
override fun consume(
kind: TowerDataKind,
towerScopeLevel: TowerScopeLevel,
group: Int
): ProcessorAction {
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
consumers += newConsumers
newConsumers.clear()
kinds += kind
groups += group
levels += towerScopeLevel
for (consumer in consumers) {
val action = consumer.consume(kind, towerScopeLevel, group)
if (action.stop()) {
return ProcessorAction.STOP
}
}
return ProcessorAction.NEXT
}
fun addConsumer(consumer: TowerDataConsumer): ProcessorAction =
run {
for (index in kinds.indices) {
if (consumer.consume(kinds[index], levels[index], groups[index]).stop()) {
return@run ProcessorAction.STOP
}
}
return@run ProcessorAction.NEXT
}.also {
newConsumers += consumer
}
}
class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
val session: FirSession,
val name: Name,
val token: TowerScopeLevel.Token<T>,
val explicitReceiver: ExpressionReceiverValue,
val candidateFactory: CandidateFactory
val candidateFactory: CandidateFactory,
val resultCollector: CandidateCollector
) : TowerDataConsumer() {
override fun consume(
kind: TowerDataKind,
towerScopeLevel: TowerScopeLevel,
resultCollector: CandidateCollector,
group: Int
): ProcessorAction {
if (checkSkip(group, resultCollector)) return ProcessorAction.NEXT
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
return when (kind) {
TowerDataKind.EMPTY ->
MemberScopeTowerLevel(session, explicitReceiver).processElementsByName(
@@ -379,12 +629,17 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
name,
explicitReceiver = null,
processor = object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(symbol: T, dispatchReceiverValue: ClassDispatchReceiverValue?): ProcessorAction {
override fun consumeCandidate(
symbol: T,
dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue?
): ProcessorAction {
resultCollector.consumeCandidate(
group,
candidateFactory.createCandidate(
symbol,
dispatchReceiverValue,
implicitExtensionReceiverValue,
ExplicitReceiverKind.DISPATCH_RECEIVER
)
)
@@ -399,12 +654,17 @@ class ExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
name,
explicitReceiver = explicitReceiver,
processor = object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(symbol: T, dispatchReceiverValue: ClassDispatchReceiverValue?): ProcessorAction {
override fun consumeCandidate(
symbol: T,
dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue?
): ProcessorAction {
resultCollector.consumeCandidate(
group,
candidateFactory.createCandidate(
symbol,
dispatchReceiverValue,
implicitExtensionReceiverValue,
ExplicitReceiverKind.EXTENSION_RECEIVER
)
)
@@ -422,17 +682,17 @@ class NoExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
val session: FirSession,
val name: Name,
val token: TowerScopeLevel.Token<T>,
val candidateFactory: CandidateFactory
val candidateFactory: CandidateFactory,
val resultCollector: CandidateCollector
) : TowerDataConsumer() {
override fun consume(
kind: TowerDataKind,
towerScopeLevel: TowerScopeLevel,
resultCollector: CandidateCollector,
group: Int
): ProcessorAction {
if (checkSkip(group, resultCollector)) return ProcessorAction.NEXT
if (skipGroup(group, resultCollector)) return ProcessorAction.NEXT
return when (kind) {
TowerDataKind.TOWER_LEVEL -> {
@@ -441,12 +701,17 @@ class NoExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
name,
explicitReceiver = null,
processor = object : TowerScopeLevel.TowerScopeLevelProcessor<T> {
override fun consumeCandidate(symbol: T, dispatchReceiverValue: ClassDispatchReceiverValue?): ProcessorAction {
override fun consumeCandidate(
symbol: T,
dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue?
): ProcessorAction {
resultCollector.consumeCandidate(
group,
candidateFactory.createCandidate(
symbol,
dispatchReceiverValue,
implicitExtensionReceiverValue,
ExplicitReceiverKind.NO_EXPLICIT_RECEIVER
)
)
@@ -458,7 +723,6 @@ class NoExplicitReceiverTowerDataConsumer<T : ConeSymbol>(
else -> ProcessorAction.NEXT
}
}
}
class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: InferenceComponents) {
@@ -479,28 +743,41 @@ class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: Inf
towerDataConsumer.consume(
TowerDataKind.TOWER_LEVEL,
MemberScopeTowerLevel(session, implicitReceiverValue),
collector, group++
group++
)
// This is an equivalent to the old "BothTowerLevelAndImplicitReceiver"
towerDataConsumer.consume(
TowerDataKind.TOWER_LEVEL,
MemberScopeTowerLevel(session, implicitReceiverValue, implicitReceiverValue),
collector, group++
group++
)
for (scope in scopes!!) {
towerDataConsumer.consume(
TowerDataKind.TOWER_LEVEL,
ScopeTowerLevel(session, scope, implicitReceiverValue),
group++
)
}
return group
}
fun runTowerResolver(towerDataConsumer: TowerDataConsumer, implicitReceiverValues: List<ImplicitReceiverValue>): CandidateCollector {
val collector = CandidateCollector(callInfo!!, components)
val collector by lazy { CandidateCollector(components) }
lateinit var towerDataConsumer: TowerDataConsumer
private lateinit var implicitReceiverValues: List<ImplicitReceiverValue>
fun runTowerResolver(consumer: TowerDataConsumer, implicitReceiverValues: List<ImplicitReceiverValue>): CandidateCollector {
this.implicitReceiverValues = implicitReceiverValues
towerDataConsumer = consumer
var group = 0
towerDataConsumer.consume(TowerDataKind.EMPTY, TowerScopeLevel.Empty, collector, group++)
towerDataConsumer.consume(TowerDataKind.EMPTY, TowerScopeLevel.Empty, group++)
for (scope in scopes!!) {
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, scope), collector, group++)
towerDataConsumer.consume(TowerDataKind.TOWER_LEVEL, ScopeTowerLevel(session, scope), group++)
}
var blockDispatchReceivers = false
@@ -516,10 +793,11 @@ class CallResolver(val typeCalculator: ReturnTypeCalculator, val components: Inf
processImplicitReceiver(towerDataConsumer, implicitReceiverValue, collector, group)
}
return collector
}
}
@@ -532,7 +810,8 @@ enum class CandidateApplicability {
RESOLVED
}
class CandidateCollector(val callInfo: CallInfo, val components: InferenceComponents) {
open class CandidateCollector(val components: InferenceComponents) {
val groupNumbers = mutableListOf<Int>()
val candidates = mutableListOf<Candidate>()
@@ -553,16 +832,34 @@ class CandidateCollector(val callInfo: CallInfo, val components: InferenceCompon
): CandidateApplicability {
val sink = CheckerSinkImpl(components)
var finished = false
sink.continuation = suspend {
for (stage in candidate.callInfo.callKind.sequence()) {
stage.check(candidate, sink, candidate.callInfo)
}
}.createCoroutineUnintercepted(completion = object : Continuation<Unit> {
override val context: CoroutineContext
get() = EmptyCoroutineContext
override fun resumeWith(result: Result<Unit>) {
result.exceptionOrNull()?.let { throw it }
finished = true
}
})
callInfo.callKind.sequence().forEach {
it.check(candidate, sink, callInfo)
while (!finished) {
sink.continuation!!.resume(Unit)
if (sink.current < CandidateApplicability.SYNTHETIC_RESOLVED) {
break
}
}
return sink.current
}
fun consumeCandidate(group: Int, candidate: Candidate) {
open fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
val applicability = getApplicability(group, candidate)
if (applicability > currentApplicability) {
@@ -576,6 +873,8 @@ class CandidateCollector(val callInfo: CallInfo, val components: InferenceCompon
candidates.add(candidate)
groupNumbers.add(group)
}
return applicability
}
@@ -601,6 +900,47 @@ class CandidateCollector(val callInfo: CallInfo, val components: InferenceCompon
}
}
class InvokeCandidateCollector(
val callResolver: CallResolver,
val invokeCallInfo: CallInfo,
components: InferenceComponents,
val multiplexer: MultiplexerTowerDataConsumer
) : CandidateCollector(components) {
override fun consumeCandidate(group: Int, candidate: Candidate): CandidateApplicability {
val applicability = super.consumeCandidate(group, candidate)
if (applicability >= CandidateApplicability.SYNTHETIC_RESOLVED) {
val session = components.session
val boundInvokeCallInfo = CallInfo(
invokeCallInfo.callKind,
FirQualifiedAccessExpressionImpl(session, null, false).apply {
calleeReference = FirNamedReferenceWithCandidate(
session,
null,
(candidate.symbol as ConeCallableSymbol).callableId.callableName,
candidate
)
typeRef = callResolver.typeCalculator.tryCalculateReturnType(candidate.symbol.firUnsafe())
},
invokeCallInfo.arguments,
invokeCallInfo.isSafeCall,
invokeCallInfo.typeArguments,
session,
invokeCallInfo.containingFile,
invokeCallInfo.container,
invokeCallInfo.typeProvider
)
val invokeConsumer =
createSimpleFunctionConsumer(session, Name.identifier("invoke"), boundInvokeCallInfo, components, callResolver.collector)
multiplexer.addConsumer(invokeConsumer)
}
return applicability
}
}
fun FirCallableDeclaration.dispatchReceiverValue(session: FirSession): ClassDispatchReceiverValue? {
// TODO: this is not true at least for inner class constructors
if (this is FirConstructor) return null

View File

@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirWrappedArgumentExpression
import org.jetbrains.kotlin.fir.symbols.ConeSymbol
import org.jetbrains.kotlin.resolve.calls.components.PostponedArgumentsAnalyzer
import org.jetbrains.kotlin.resolve.calls.inference.model.ConstraintStorage
@@ -14,7 +15,7 @@ import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind
class CandidateFactory(
val inferenceComponents: InferenceComponents,
callInfo: CallInfo
val callInfo: CallInfo
) {
val baseSystem: ConstraintStorage
@@ -31,15 +32,20 @@ class CandidateFactory(
fun createCandidate(
symbol: ConeSymbol,
dispatchReceiverValue: ClassDispatchReceiverValue?,
implicitExtensionReceiverValue: ImplicitReceiverValue?,
explicitReceiverKind: ExplicitReceiverKind
): Candidate {
return Candidate(symbol, dispatchReceiverValue, explicitReceiverKind, inferenceComponents, baseSystem)
return Candidate(
symbol, dispatchReceiverValue, implicitExtensionReceiverValue,
explicitReceiverKind, inferenceComponents, baseSystem, callInfo
)
}
}
fun PostponedArgumentsAnalyzer.Context.addSubsystemFromExpression(expression: FirExpression) {
when (expression) {
is FirFunctionCall -> expression.candidate()?.let { addOtherSystem(it.system.asReadOnlyStorage()) }
is FirWrappedArgumentExpression -> addSubsystemFromExpression(expression.expression)
}
}

View File

@@ -22,7 +22,7 @@ import org.jetbrains.kotlin.resolve.calls.inference.model.SimpleConstraintSystem
internal object CreateFreshTypeVariableSubstitutorStage : ResolutionStage() {
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val declaration = candidate.symbol.firUnsafe<FirDeclaration>()
if (declaration !is FirCallableMemberDeclaration || declaration.typeParameters.isEmpty()) {
candidate.substitutor = ConeSubstitutor.Empty
@@ -35,7 +35,7 @@ internal object CreateFreshTypeVariableSubstitutorStage : ResolutionStage() {
// bad function -- error on declaration side
if (csBuilder.hasContradiction) {
sink.reportApplicability(CandidateApplicability.INAPPLICABLE) //TODO: auto report it
sink.yieldApplicability(CandidateApplicability.INAPPLICABLE) //TODO: auto report it
return
}

View File

@@ -24,7 +24,7 @@ class ClassDispatchReceiverValue(val klassSymbol: FirClassSymbol) : ReceiverValu
}
class ExpressionReceiverValue(
private val explicitReceiverExpression: FirExpression,
val explicitReceiverExpression: FirExpression,
val typeProvider: (FirExpression) -> FirTypeRef?
) : ReceiverValue {
override val type: ConeKotlinType

View File

@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirWrappedArgumentExpression
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.resolve.calls.inference.components.KotlinConstraintSystemCompleter
@@ -36,23 +37,41 @@ fun Candidate.computeCompletionMode(
return when {
// Consider call foo(bar(x)), if return type of bar is a proper one, then we can complete resolve for bar => full completion mode
// Otherwise, we shouldn't complete bar until we process call foo
system.getBuilder().isProperType(currentReturnType) -> KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL
csBuilder.isProperType(currentReturnType) -> KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL
// Nested call is connected with the outer one through the UPPER constraint (returnType <: expectedOuterType)
// This means that there will be no new LOWER constraints =>
// it's possible to complete call now if there are proper LOWER constraints
system.getBuilder().isTypeVariable(currentReturnType) ->
csBuilder.isTypeVariable(currentReturnType) ->
if (hasProperNonTrivialLowerConstraints(components, currentReturnType))
KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL
else
KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL
// Return type has proper equal constraints => there is no need in the outer call
containsTypeVariablesWithProperEqualConstraints(components, currentReturnType) -> KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.FULL
else -> KotlinConstraintSystemCompleter.ConstraintSystemCompletionMode.PARTIAL
}
}
val Candidate.csBuilder get() = system.getBuilder()
private fun Candidate.containsTypeVariablesWithProperEqualConstraints(components: InferenceComponents, type: ConeKotlinType): Boolean =
with(components.ctx){
for ((variableConstructor, variableWithConstraints) in csBuilder.currentStorage().notFixedTypeVariables) {
if (!type.contains { it.typeConstructor() == variableConstructor }) continue
val constraints = variableWithConstraints.constraints
val onlyProperEqualConstraints =
constraints.isNotEmpty() && constraints.all { it.kind.isEqual() && csBuilder.isProperType(it.type) }
if (!onlyProperEqualConstraints) return false
}
return true
}
private fun Candidate.hasProperNonTrivialLowerConstraints(components: InferenceComponents, typeVariable: ConeKotlinType): Boolean {
assert(csBuilder.isTypeVariable(typeVariable)) { "$typeVariable is not a type variable" }
@@ -162,6 +181,7 @@ class ConstraintSystemCompleter(val components: InferenceComponents) {
}
this.arguments.forEach { it.process(to) }
}
is FirWrappedArgumentExpression -> this.expression.process(to)
// TOOD: WTF?
}
// if (analyzed) {

View File

@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.resolve.*
import org.jetbrains.kotlin.fir.resolve.transformers.ReturnTypeCalculator
import org.jetbrains.kotlin.fir.symbols.*
import org.jetbrains.kotlin.fir.symbols.impl.FirTypeParameterSymbol
import org.jetbrains.kotlin.fir.types.*
@@ -45,7 +46,7 @@ open class ConeTypeVariable(name: String) : TypeVariableMarker {
val defaultType = ConeTypeVariableType(ConeNullability.NOT_NULL, typeConstructor)
}
class InferenceComponents(val ctx: TypeSystemInferenceExtensionContextDelegate, val session: FirSession) {
class InferenceComponents(val ctx: TypeSystemInferenceExtensionContextDelegate, val session: FirSession, val returnTypeCalculator: ReturnTypeCalculator) {
private val approximator = object : AbstractTypeApproximator(ctx) {
override fun createErrorType(message: String): SimpleTypeMarker {
return ConeClassErrorType(message)
@@ -59,5 +60,6 @@ class InferenceComponents(val ctx: TypeSystemInferenceExtensionContextDelegate,
fun createConstraintSystem(): NewConstraintSystemImpl {
return NewConstraintSystemImpl(injector, ctx)
}
}

View File

@@ -78,12 +78,11 @@ private fun isFunctionalTypeWithReceiver(typeRef: FirTypeRef) =
coneTypeSafe.lookupTag.classId.asString() == "kotlin/ExtensionFunctionType"
}
private val ConeKotlinType.returnType: ConeKotlinType
private val ConeKotlinType.returnType: ConeKotlinType?
get() {
require(this is ConeClassType)
val projection = typeArguments.last()
require(projection is ConeTypedProjection)
return projection.type
return (projection as? ConeTypedProjection)?.type
}
private val ConeKotlinType.valueParameterTypes: List<ConeKotlinType?>
@@ -130,7 +129,7 @@ private fun extraLambdaInfo(
return ResolvedLambdaAtom(argument, isSuspend, receiverType, parameters, returnType, typeVariable.takeIf { newTypeVariableUsed })
}
private fun extractLambdaInfoFromFunctionalType(
internal fun extractLambdaInfoFromFunctionalType(
expectedType: ConeKotlinType?,
expectedTypeRef: FirTypeRef,
argument: FirAnonymousFunction
@@ -139,8 +138,8 @@ private fun extractLambdaInfoFromFunctionalType(
val parameters = extractLambdaParameters(expectedType, argument)
val argumentAsFunctionExpression = argument//.safeAs<FunctionExpression>()
val receiverType = argumentAsFunctionExpression?.receiverType ?: expectedType.receiverType(expectedTypeRef)
val returnType = argumentAsFunctionExpression?.returnType ?: expectedType.returnType
val receiverType = argumentAsFunctionExpression.receiverType ?: expectedType.receiverType(expectedTypeRef)
val returnType = argumentAsFunctionExpression.returnType ?: expectedType.returnType ?: return null
return ResolvedLambdaAtom(
argument,

View File

@@ -27,6 +27,7 @@ interface LambdaAnalyzer {
receiverType: ConeKotlinType?,
parameters: List<ConeKotlinType>,
expectedReturnType: ConeKotlinType?, // null means, that return type is not proper i.e. it depends on some type variables
rawReturnType: ConeKotlinType,
stubsForPostponedVariables: Map<TypeVariableMarker, StubTypeMarker>
): Pair<List<FirExpression>, InferenceSession>
}
@@ -93,6 +94,7 @@ class PostponedArgumentsAnalyzer(
receiver,
parameters,
expectedTypeForReturnArguments,
rawReturnType,
stubsForPostponedVariables
)

View File

@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.declarations.FirFunction
import org.jetbrains.kotlin.fir.declarations.FirMemberDeclaration
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.fir.resolve.FirProvider
import org.jetbrains.kotlin.fir.resolve.transformers.firSafeNullable
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
@@ -27,25 +28,26 @@ import java.lang.IllegalStateException
abstract class ResolutionStage {
abstract fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo)
abstract suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo)
}
abstract class CheckerStage : ResolutionStage()
internal object CheckExplicitReceiverConsistency : ResolutionStage() {
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val receiverKind = candidate.explicitReceiverKind
val explicitReceiver = callInfo.explicitReceiver
// TODO: add invoke cases
when (receiverKind) {
NO_EXPLICIT_RECEIVER -> {
if (explicitReceiver != null) return sink.reportApplicability(CandidateApplicability.WRONG_RECEIVER)
if (explicitReceiver != null && explicitReceiver !is FirResolvedQualifier)
return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
}
EXTENSION_RECEIVER, DISPATCH_RECEIVER -> {
if (explicitReceiver == null) return sink.reportApplicability(CandidateApplicability.WRONG_RECEIVER)
if (explicitReceiver == null) return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
}
BOTH_RECEIVERS -> {
if (explicitReceiver == null) return sink.reportApplicability(CandidateApplicability.WRONG_RECEIVER)
if (explicitReceiver == null) return sink.yieldApplicability(CandidateApplicability.WRONG_RECEIVER)
// Here we should also check additional invoke receiver
}
}
@@ -95,45 +97,57 @@ internal sealed class CheckReceivers : ResolutionStage() {
abstract fun ExplicitReceiverKind.shouldBeResolvedAsImplicit(): Boolean
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val receiverParameterValue = candidate.getReceiverValue()
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val expectedReceiverParameterValue = candidate.getReceiverValue()
val explicitReceiverExpression = callInfo.explicitReceiver
val explicitReceiverKind = candidate.explicitReceiverKind
if (receiverParameterValue != null) {
if (expectedReceiverParameterValue != null) {
if (explicitReceiverExpression != null && explicitReceiverKind.shouldBeResolvedAsExplicit()) {
resolveArgumentExpression(
candidate.csBuilder,
explicitReceiverExpression,
candidate.substitutor.substituteOrSelf(receiverParameterValue.type),
explicitReceiverExpression.typeRef,
sink,
argument = explicitReceiverExpression,
expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverParameterValue.type),
expectedTypeRef = explicitReceiverExpression.typeRef,
sink = sink,
isReceiver = true,
isSafeCall = callInfo.isSafeCall,
typeProvider = callInfo.typeProvider,
acceptLambdaAtoms = { candidate.postponedAtoms += it }
)
} else {
val argumentExtensionReceiverValue = candidate.implicitExtensionReceiverValue
if (argumentExtensionReceiverValue != null && explicitReceiverKind.shouldBeResolvedAsImplicit()) {
resolvePlainArgumentType(
candidate.csBuilder,
argumentType = argumentExtensionReceiverValue.type,
expectedType = candidate.substitutor.substituteOrSelf(expectedReceiverParameterValue.type),
sink = sink,
isReceiver = true,
isSafeCall = callInfo.isSafeCall
)
}
}
}
}
}
internal object MapArguments : ResolutionStage() {
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val symbol = candidate.symbol as? FirFunctionSymbol ?: return sink.reportApplicability(CandidateApplicability.HIDDEN)
val function = symbol.firUnsafe<FirFunction>()
val processor = FirCallArgumentsProcessor(function, callInfo.arguments)
val mappingResult = processor.process()
candidate.argumentMapping = mappingResult.argumentMapping
if (!mappingResult.isSuccess) {
return sink.reportApplicability(CandidateApplicability.PARAMETER_MAPPING_ERROR)
return sink.yieldApplicability(CandidateApplicability.PARAMETER_MAPPING_ERROR)
}
}
}
internal object CheckArguments : CheckerStage() {
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val argumentMapping =
candidate.argumentMapping ?: throw IllegalStateException("Argument should be already mapped while checking arguments!")
for ((argument, parameter) in argumentMapping) {
@@ -145,16 +159,16 @@ internal object CheckArguments : CheckerStage() {
typeProvider = callInfo.typeProvider,
sink = sink
)
}
if (candidate.system.hasContradiction) {
sink.reportApplicability(CandidateApplicability.INAPPLICABLE)
if (candidate.system.hasContradiction) {
sink.yieldApplicability(CandidateApplicability.INAPPLICABLE)
}
sink.yield()
}
}
}
internal object DiscriminateSynthetics : CheckerStage() {
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
if (candidate.symbol is SyntheticSymbol) {
sink.reportApplicability(CandidateApplicability.SYNTHETIC_RESOLVED)
}
@@ -172,7 +186,7 @@ internal object CheckVisibility : CheckerStage() {
}
}
override fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
override suspend fun check(candidate: Candidate, sink: CheckerSink, callInfo: CallInfo) {
val symbol = candidate.symbol
val declaration = symbol.firSafeNullable<FirMemberDeclaration>()
if (declaration != null && !declaration.visibility.isPublicAPI) {
@@ -198,7 +212,7 @@ internal object CheckVisibility : CheckerStage() {
}
if (!visible) {
sink.reportApplicability(CandidateApplicability.HIDDEN)
sink.yieldApplicability(CandidateApplicability.HIDDEN)
}
}
}

View File

@@ -6,10 +6,12 @@
package org.jetbrains.kotlin.fir.resolve.transformers
import com.google.common.collect.LinkedHashMultimap
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.*
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.impl.FirValueParameterImpl
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.expressions.impl.FirResolvedQualifierImpl
import org.jetbrains.kotlin.fir.references.FirErrorNamedReference
import org.jetbrains.kotlin.fir.references.FirSimpleNamedReference
import org.jetbrains.kotlin.fir.resolve.*
@@ -123,6 +125,10 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
primaryConstructorParametersScope = null
val type = regularClass.defaultType()
scopes.addIfNotNull(type.scope(session, scopeSession))
val companionObject = regularClass.companionObject
if (companionObject != null) {
scopes.addIfNotNull(symbolProvider.getClassUseSiteMemberScope(companionObject.classId, session, scopeSession))
}
val result = withLabelAndReceiverType(regularClass.name, regularClass, type) {
super.transformRegularClass(regularClass, data)
}
@@ -159,10 +165,10 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
}
FirOperation.SAFE_AS -> {
resolved.resultType =
resolved.conversionTypeRef.withReplacedConeType(
session,
resolved.conversionTypeRef.coneTypeUnsafe<ConeKotlinType>().withNullability(ConeNullability.NULLABLE)
)
resolved.conversionTypeRef.withReplacedConeType(
session,
resolved.conversionTypeRef.coneTypeUnsafe<ConeKotlinType>().withNullability(ConeNullability.NULLABLE)
)
}
else -> error("Unknown type operator")
}
@@ -249,12 +255,81 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
override fun KotlinTypeMarker.removeExactAnnotation(): KotlinTypeMarker {
return this
}
}, session)
}, session, jump)
private fun <T : FirQualifiedAccess> transformCallee(qualifiedAccess: T): T {
private var qualifierStack = mutableListOf<Name>()
private var qualifierPartsToDrop = 0
private fun tryResolveAsQualifier(): FirStatement? {
val symbolProvider = session.service<FirSymbolProvider>()
var qualifierParts = qualifierStack.asReversed().map { it.asString() }
var resolved: PackageOrClass?
do {
resolved = resolveToPackageOrClass(
symbolProvider,
FqName.fromSegments(qualifierParts)
)
if (resolved == null)
qualifierParts = qualifierParts.dropLast(1)
} while (resolved == null && qualifierParts.isNotEmpty())
if (resolved != null) {
qualifierPartsToDrop = qualifierParts.size - 1
return FirResolvedQualifierImpl(session, null /* TODO */, resolved.packageFqName, resolved.relativeClassFqName)
.apply { resultType = typeForQualifier(this) }
}
return null
}
private fun typeForQualifier(resolvedQualifier: FirResolvedQualifier): FirTypeRef {
val classId = resolvedQualifier.classId
val resultType = resolvedQualifier.resultType
if (classId != null) {
val classSymbol = symbolProvider.getClassLikeSymbolByFqName(classId)!!
val declaration = classSymbol.firUnsafe<FirClassLikeDeclaration>()
if (declaration is FirClass) {
if (declaration.classKind == ClassKind.OBJECT) {
return resultType.resolvedTypeFromPrototype(
classSymbol.constructType(emptyArray(), false)
)
} else if (declaration.classKind == ClassKind.ENUM_ENTRY) {
val enumClassSymbol = symbolProvider.getClassLikeSymbolByFqName(classSymbol.classId.outerClassId!!)!!
return resultType.resolvedTypeFromPrototype(
enumClassSymbol.constructType(emptyArray(), false)
)
} else {
if (declaration is FirRegularClass) {
val companionObject = declaration.companionObject
if (companionObject != null) {
return resultType.resolvedTypeFromPrototype(
companionObject.symbol.constructType(emptyArray(), false)
)
}
}
}
}
}
// TODO: Handle no value type here
return resultType.resolvedTypeFromPrototype(
StandardClassIds.Unit(symbolProvider).constructType(emptyArray(), isNullable = false)
)
}
private fun <T : FirQualifiedAccess> transformCallee(qualifiedAccess: T): FirStatement {
val callee = qualifiedAccess.calleeReference as? FirSimpleNamedReference ?: return qualifiedAccess
if (qualifiedAccess.safe || callee.name.isSpecial) {
qualifierStack.clear()
} else {
qualifierStack.add(callee.name)
}
val qualifiedAccess = qualifiedAccess.transformExplicitReceiver(this, noExpectedType)
if (qualifierPartsToDrop > 0) {
qualifierPartsToDrop--
return qualifiedAccess.explicitReceiver!!
}
val info = CallInfo(
CallKind.VariableAccess,
@@ -273,16 +348,37 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
val consumer = createVariableAndObjectConsumer(
session,
callee.name,
info, inferenceComponents
info, inferenceComponents,
resolver.collector
)
val result = resolver.runTowerResolver(consumer, implicitReceiverStack.asReversed())
val candidates = result.bestCandidates()
val nameReference = createResolvedNamedReference(
callee,
result.bestCandidates(),
candidates,
result.currentApplicability
)
if (qualifiedAccess.explicitReceiver == null &&
(candidates.size <= 1 && result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED)
) {
tryResolveAsQualifier()?.let { return it }
}
if (nameReference is FirResolvedCallableReference) {
val symbol = nameReference.coneSymbol as? ConeClassLikeSymbol
if (symbol != null) {
return FirResolvedQualifierImpl(session, nameReference.psi, symbol.classId).apply {
resultType = typeForQualifier(this)
}
}
}
if (qualifiedAccess.explicitReceiver == null) {
qualifierStack.clear()
}
val resultExpression =
qualifiedAccess.transformCalleeReference(StoreNameReference, nameReference) as T
if (resultExpression is FirExpression) storeTypeFromCallee(resultExpression)
@@ -304,15 +400,14 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
}
is FirSuperReference -> {
qualifiedAccessExpression.resultType =
callee.superTypeRef as? FirResolvedTypeRef ?:
implicitReceiverStack.filterIsInstance<ImplicitDispatchReceiverValue>().lastOrNull()
callee.superTypeRef as? FirResolvedTypeRef
?: implicitReceiverStack.filterIsInstance<ImplicitDispatchReceiverValue>().lastOrNull()
?.boundSymbol?.fir?.superTypeRefs?.firstOrNull()
?: FirErrorTypeRefImpl(session, qualifiedAccessExpression.psi, "No super type")
?: FirErrorTypeRefImpl(session, qualifiedAccessExpression.psi, "No super type")
}
is FirResolvedCallableReference -> {
if (qualifiedAccessExpression.typeRef !is FirResolvedTypeRef) {
qualifiedAccessExpression.resultType =
jump.tryCalculateReturnType(callee.coneSymbol.firUnsafe<FirCallableDeclaration>())
storeTypeFromCallee(qualifiedAccessExpression)
}
}
}
@@ -328,12 +423,78 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
}
override fun transformAnonymousFunction(anonymousFunction: FirAnonymousFunction, data: Any?): CompositeTransformResult<FirDeclaration> {
if (data == null) return anonymousFunction.compose()
if (data is LambdaResolution) return transformAnonymousFunction(anonymousFunction, data).compose()
return super.transformAnonymousFunction(anonymousFunction, data)
return when (data) {
null -> {
anonymousFunction.compose()
}
is LambdaResolution -> {
transformAnonymousFunctionWithLambdaResolution(anonymousFunction, data).compose()
}
is FirTypeRef -> {
val resolvedLambdaAtom = (data as? FirResolvedTypeRef)?.let {
extractLambdaInfoFromFunctionalType(
it.type, it, anonymousFunction
)
}
var af = super.transformAnonymousFunction(anonymousFunction, data).single as FirAnonymousFunction
val valueParameters =
if (resolvedLambdaAtom == null) af.valueParameters
else {
val singleParameterType = resolvedLambdaAtom.parameters.singleOrNull()
val itParam = when {
af.valueParameters.isEmpty() && singleParameterType != null ->
FirValueParameterImpl(
session,
null,
Name.identifier("it"),
FirResolvedTypeRefImpl(session, null, singleParameterType, emptyList()),
defaultValue = null,
isCrossinline = false,
isNoinline = false,
isVararg = false
)
else -> null
}
if (itParam != null) {
listOf(itParam)
} else {
af.valueParameters.mapIndexed { index, param ->
if (param.returnTypeRef is FirResolvedTypeRef) {
param
} else {
param.transformReturnTypeRef(
StoreType,
param.returnTypeRef.resolvedTypeFromPrototype(
resolvedLambdaAtom.parameters[index]
)
)
param
}
}
}
}
af = af.copy(
receiverTypeRef = af.receiverTypeRef?.takeIf { it !is FirImplicitTypeRef }
?: resolvedLambdaAtom?.receiver?.let { af.receiverTypeRef?.resolvedTypeFromPrototype(it) },
valueParameters = valueParameters,
returnTypeRef = (af.returnTypeRef as? FirResolvedTypeRef)
?: resolvedLambdaAtom?.returnType?.let { af.returnTypeRef.resolvedTypeFromPrototype(it) }
?: af.body?.resultType?.takeIf { af.returnTypeRef is FirImplicitTypeRef }
?: FirErrorTypeRefImpl(session, af.psi, "No result type for lambda")
)
af.replaceTypeRef(af.constructFunctionalTypeRef(session))
af.compose()
}
else -> {
super.transformAnonymousFunction(anonymousFunction, data)
}
}
}
fun transformAnonymousFunction(anonymousFunction: FirAnonymousFunction, lambdaResolution: LambdaResolution): FirAnonymousFunction {
private fun transformAnonymousFunctionWithLambdaResolution(
anonymousFunction: FirAnonymousFunction, lambdaResolution: LambdaResolution
): FirAnonymousFunction {
val receiverTypeRef = anonymousFunction.receiverTypeRef
fun transform(): FirAnonymousFunction {
return withScopeCleanup(scopes) {
@@ -365,6 +526,8 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
private fun resolveCallAndSelectCandidate(functionCall: FirFunctionCall, expectedTypeRef: FirTypeRef?): FirFunctionCall {
qualifierStack.clear()
val functionCall =
(functionCall.transformExplicitReceiver(this, noExpectedType) as FirFunctionCall)
.transformArguments(this, null) as FirFunctionCall
@@ -389,11 +552,15 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
resolver.callInfo = info
resolver.scopes = (scopes + localScopes).asReversed()
val consumer = createFunctionConsumer(session, name, info, inferenceComponents)
val consumer = createFunctionConsumer(session, name, info, inferenceComponents, resolver.collector, resolver)
val result = resolver.runTowerResolver(consumer, implicitReceiverStack.asReversed())
val bestCandidates = result.bestCandidates()
val reducedCandidates = ConeOverloadConflictResolver(TypeSpecificityComparator.NONE, inferenceComponents)
.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = false)
val reducedCandidates = if (result.currentApplicability < CandidateApplicability.SYNTHETIC_RESOLVED) {
bestCandidates.toSet()
} else {
ConeOverloadConflictResolver(TypeSpecificityComparator.NONE, inferenceComponents)
.chooseMaximallySpecificCandidates(bestCandidates, discriminateGenerics = false)
}
// fun isInvoke()
@@ -462,6 +629,7 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
receiverType: ConeKotlinType?,
parameters: List<ConeKotlinType>,
expectedReturnType: ConeKotlinType?,
rawReturnType: ConeKotlinType,
stubsForPostponedVariables: Map<TypeVariableMarker, StubTypeMarker>
): Pair<List<FirExpression>, InferenceSession> {
@@ -485,10 +653,10 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
valueParameters = lambdaArgument.valueParameters.mapIndexed { index, parameter ->
parameter.transformReturnTypeRef(StoreType, parameter.returnTypeRef.resolvedTypeFromPrototype(parameters[index]))
parameter
} + listOfNotNull(itParam)
} + listOfNotNull(itParam),
returnTypeRef = lambdaArgument.returnTypeRef.resolvedTypeFromPrototype(rawReturnType)
)
val expectedReturnTypeRef = expectedReturnType?.let { newLambdaExpression.returnTypeRef.resolvedTypeFromPrototype(it) }
replacements[lambdaArgument] =
newLambdaExpression.transformSingle(this@FirBodyResolveTransformer, LambdaResolution(expectedReturnTypeRef))
@@ -609,7 +777,11 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
is FirExpression -> statement
else -> null
}
block.resultType = (resultExpression?.resultType as? FirResolvedTypeRef) ?: FirErrorTypeRefImpl(session, null, "No type for block")
block.resultType = if (resultExpression == null) {
FirImplicitUnitTypeRef(session, block.psi)
} else {
(resultExpression.resultType as? FirResolvedTypeRef) ?: FirErrorTypeRefImpl(session, null, "No type for block")
}
return block.compose()
}
@@ -774,7 +946,9 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
if (property.returnTypeRef !is FirImplicitTypeRef && implicitTypeOnly) return property.compose()
return withScopeCleanup(localScopes) {
localScopes.addIfNotNull(primaryConstructorParametersScope)
transformVariable(property, data)
(transformVariable(property, data).single as FirProperty).apply {
setter?.let { it.valueParameters[0].transformReturnTypeRef(StoreType, property.returnTypeRef) }
}.compose()
}
}
@@ -795,13 +969,33 @@ open class FirBodyResolveTransformer(val session: FirSession, val implicitTypeOn
override fun transformGetClassCall(getClassCall: FirGetClassCall, data: Any?): CompositeTransformResult<FirStatement> {
val transformedGetClassCall = super.transformGetClassCall(getClassCall, data).single as FirGetClassCall
val kClassSymbol = ClassId.fromString("kotlin/reflect/KClass")(session.service())
val typeOfExpression = when (val lhs = transformedGetClassCall.argument) {
is FirResolvedQualifier -> {
val classId = lhs.classId
if (classId != null) {
val symbol = symbolProvider.getClassLikeSymbolByFqName(classId)!!
// TODO: Unify logic?
symbol.constructType(
Array(symbol.firUnsafe<FirClassLikeDeclaration>().typeParameters.size) {
ConeStarProjection
},
isNullable = false
)
} else {
lhs.resultType.coneTypeUnsafe<ConeKotlinType>()
}
}
else -> lhs.resultType.coneTypeUnsafe<ConeKotlinType>()
}
transformedGetClassCall.resultType =
FirResolvedTypeRefImpl(
session,
null,
kClassSymbol.constructType(arrayOf(transformedGetClassCall.argument.resultType.coneTypeUnsafe()), false),
emptyList()
)
FirResolvedTypeRefImpl(
session,
null,
kClassSymbol.constructType(arrayOf(typeOfExpression), false),
emptyList()
)
return transformedGetClassCall.compose()
}
}

View File

@@ -7,16 +7,18 @@ package org.jetbrains.kotlin.fir.resolve.transformers
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.copy
import org.jetbrains.kotlin.fir.declarations.FirAnonymousFunction
import org.jetbrains.kotlin.fir.declarations.FirCallableMemberDeclaration
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.expressions.FirFunctionCall
import org.jetbrains.kotlin.fir.expressions.FirStatement
import org.jetbrains.kotlin.fir.references.FirResolvedCallableReferenceImpl
import org.jetbrains.kotlin.fir.resolve.calls.FirNamedReferenceWithCandidate
import org.jetbrains.kotlin.fir.resolve.constructFunctionalTypeRef
import org.jetbrains.kotlin.fir.resolve.substitution.ConeSubstitutor
import org.jetbrains.kotlin.fir.resolve.substitution.substituteOrNull
import org.jetbrains.kotlin.fir.scopes.impl.withReplacedConeType
import org.jetbrains.kotlin.fir.types.FirResolvedTypeRef
import org.jetbrains.kotlin.fir.types.FirTypeProjectionWithVariance
import org.jetbrains.kotlin.fir.types.*
import org.jetbrains.kotlin.fir.types.impl.ConeTypeParameterTypeImpl
import org.jetbrains.kotlin.fir.types.impl.FirResolvedTypeRefImpl
import org.jetbrains.kotlin.fir.types.impl.FirTypeProjectionWithVarianceImpl
@@ -82,4 +84,21 @@ class FirCallCompleterTransformer(
}
override fun transformAnonymousFunction(
anonymousFunction: FirAnonymousFunction,
data: Nothing?
): CompositeTransformResult<FirDeclaration> {
val initialType = anonymousFunction.returnTypeRef.coneTypeSafe<ConeKotlinType>()
if (initialType != null) {
val finalType = finalSubstitutor.substituteOrNull(initialType)
val resultType = anonymousFunction.returnTypeRef.withReplacedConeType(session, finalType)
anonymousFunction.transformReturnTypeRef(StoreType, resultType)
anonymousFunction.replaceTypeRef(anonymousFunction.constructFunctionalTypeRef(session))
}
return super.transformAnonymousFunction(anonymousFunction, data)
}
}

View File

@@ -49,32 +49,34 @@ class FirImportResolveTransformer() : FirAbstractTreeTransformer() {
}
private fun transformImportForFqName(fqName: FqName, delegate: FirImport): CompositeTransformResult<FirImport> {
val (packageFqName, relativeClassFqName) = resolveToPackageOrClass(fqName) ?: return delegate.compose()
val (packageFqName, relativeClassFqName) = resolveToPackageOrClass(symbolProvider, fqName) ?: return delegate.compose()
return FirResolvedImportImpl(session, delegate, packageFqName, relativeClassFqName).compose()
}
private fun resolveToPackageOrClass(fqName: FqName): PackageOrClass? {
var currentPackage = fqName
val pathSegments = fqName.pathSegments()
var prefixSize = pathSegments.size
while (!currentPackage.isRoot) {
if (symbolProvider.getPackage(currentPackage) != null) {
break
}
currentPackage = currentPackage.parent()
prefixSize--
}
fun resolveToPackageOrClass(symbolProvider: FirSymbolProvider, fqName: FqName): PackageOrClass? {
var currentPackage = fqName
val pathSegments = fqName.pathSegments()
var prefixSize = pathSegments.size
while (!currentPackage.isRoot && prefixSize > 0) {
if (symbolProvider.getPackage(currentPackage) != null) {
break
}
if (currentPackage == fqName) return PackageOrClass(currentPackage, null)
val relativeClassFqName =
FqName.fromSegments((prefixSize until pathSegments.size).map { pathSegments[it].asString() })
val classId = ClassId(currentPackage, relativeClassFqName, false)
if (symbolProvider.getClassLikeSymbolByFqName(classId) == null) return null
return PackageOrClass(currentPackage, relativeClassFqName)
currentPackage = currentPackage.parent()
prefixSize--
}
private data class PackageOrClass(val packageFqName: FqName, val relativeClassFqName: FqName?)
if (currentPackage == fqName) return PackageOrClass(currentPackage, null)
val relativeClassFqName =
FqName.fromSegments((prefixSize until pathSegments.size).map { pathSegments[it].asString() })
val classId = ClassId(currentPackage, relativeClassFqName, false)
if (symbolProvider.getClassLikeSymbolByFqName(classId) == null) return null
return PackageOrClass(currentPackage, relativeClassFqName)
}
data class PackageOrClass(val packageFqName: FqName, val relativeClassFqName: FqName?)

View File

@@ -43,7 +43,7 @@ class FirStatusResolveTransformer : FirAbstractTreeTransformer() {
Modality.FINAL
this is FirNamedFunction && body == null ->
Modality.ABSTRACT
this is FirProperty && initializer == null && getter.body == null && setter.body == null ->
this is FirProperty && initializer == null && getter.body == null && setter?.body == null ->
Modality.ABSTRACT
else ->
Modality.OPEN

View File

@@ -7,8 +7,13 @@ package org.jetbrains.kotlin.fir.scopes.impl
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.declarations.FirResolvedImport
import org.jetbrains.kotlin.fir.declarations.FirTypeAlias
import org.jetbrains.kotlin.fir.declarations.expandedConeType
import org.jetbrains.kotlin.fir.resolve.ScopeSession
import org.jetbrains.kotlin.fir.resolve.calls.TowerScopeLevel
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.resolve.transformers.firUnsafe
import org.jetbrains.kotlin.fir.scopes.FirScope
import org.jetbrains.kotlin.fir.scopes.ProcessorAction
import org.jetbrains.kotlin.fir.scopes.processConstructors
import org.jetbrains.kotlin.fir.symbols.*
@@ -21,7 +26,23 @@ abstract class FirAbstractImportingScope(session: FirSession, lookupInFir: Boole
protected val scopeCache = ScopeSession()
fun <T : ConeCallableSymbol> processCallables(
private fun getStaticsScope(classId: ClassId): FirScope? {
provider.getClassUseSiteMemberScope(classId, session, scopeCache)?.let { return it }
val symbol = provider.getClassLikeSymbolByFqName(classId) ?: error("No scope/symbol for $classId")
if (symbol is ConeTypeAliasSymbol) {
val expansionSymbol = symbol.firUnsafe<FirTypeAlias>().expandedConeType?.lookupTag?.toSymbol(session)
if (expansionSymbol as? ConeClassLikeSymbol != null) {
return getStaticsScope(expansionSymbol.classId)
}
}
return null
}
protected fun <T : ConeCallableSymbol> processCallables(
import: FirResolvedImport,
name: Name,
token: TowerScopeLevel.Token<T>,
@@ -31,9 +52,8 @@ abstract class FirAbstractImportingScope(session: FirSession, lookupInFir: Boole
val classId = import.resolvedClassId
if (classId != null) {
val scope = getStaticsScope(classId) ?: return ProcessorAction.NEXT
val scope =
provider.getClassUseSiteMemberScope(classId, session, scopeCache) ?: error("No scope for $classId")
val action = when (token) {
TowerScopeLevel.Token.Functions -> scope.processFunctionsByName(
@@ -75,7 +95,7 @@ abstract class FirAbstractImportingScope(session: FirSession, lookupInFir: Boole
return ProcessorAction.NEXT
}
protected abstract fun <T : ConeCallableSymbol> processCallables(
abstract fun <T : ConeCallableSymbol> processCallables(
name: Name,
token: TowerScopeLevel.Token<T>,
processor: (ConeCallableSymbol) -> ProcessorAction

View File

@@ -5,4 +5,6 @@ public open class NonNullNever : R|kotlin/Any| {
@R|MyNullable|() public open operator fun foo(@R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.NEVER|()) x: R|kotlin/String|?, @R|MyNullable|() y: R|kotlin/CharSequence|?): R|kotlin/String|?
public constructor(): R|NonNullNever|
}

View File

@@ -5,4 +5,6 @@ public open class Simple : R|kotlin/Any| {
@R|javax/annotation/Nonnull|() public open operator fun bar(): R|kotlin/String|
public constructor(): R|Simple|
}

View File

@@ -5,4 +5,6 @@ public open class Strange : R|kotlin/Any| {
@R|javax/annotation/Nonnull|() public open operator fun bar(): R|kotlin/String|
public constructor(): R|Strange|
}

View File

@@ -7,6 +7,8 @@
@R|javax/annotation/Nonnull|() public open operator fun bar(): R|kotlin/String|
public constructor(): R|A|
}
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class FieldsAreNullable : R|kotlin/Annotation| {
}

View File

@@ -3,6 +3,8 @@
@R|spr/ForceFlexibility|() public open operator fun bar(x: R|ft<kotlin/String, kotlin/String?>|!, @R|javax/annotation/Nonnull|() y: R|kotlin/CharSequence|): R|ft<kotlin/String, kotlin/String?>|!
public constructor(): R|A|
}
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|spr/UnknownNullability|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class ForceFlexibility : R|kotlin/Annotation| {
}

View File

@@ -7,6 +7,8 @@
public open operator fun foobar(@R|javax/annotation/Nonnull|(R|javax/annotation/meta/When.UNKNOWN|()) x: R|ft<kotlin/String, kotlin/String?>|!): R|kotlin/Unit|
public constructor(): R|A|
}
public abstract interface B : R|kotlin/Any| {
public abstract operator fun foo(@R|javax/annotation/Nonnull|() x: R|kotlin/String|): R|kotlin/Unit|

View File

@@ -11,6 +11,8 @@
public open operator fun baz(@R|javax/annotation/Nonnull|() x: R|kotlin/String|): R|kotlin/String|
public constructor(): R|A|
}
@R|NonNullApi|() public abstract interface AInt : R|kotlin/Any| {
public abstract operator fun foo1(x: R|kotlin/String|): R|kotlin/CharSequence|
@@ -35,6 +37,8 @@
public open operator fun baz(x: R|kotlin/String|): R|kotlin/String|
public constructor(): R|B|
}
@R|NonNullApi|() public open class C : R|A|, R|AInt| {
public open operator fun foo1(x: R|kotlin/String|): R|kotlin/String|
@@ -47,6 +51,8 @@
public open operator fun baz(x: R|kotlin/String|): R|kotlin/String|
public constructor(): R|C|
}
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|(), R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
}

View File

@@ -9,6 +9,8 @@
@R|javax/annotation/Nullable|() public open operator fun baz(): R|ft<kotlin/collections/MutableList<ft<kotlin/String, kotlin/String?>>?, kotlin/collections/List<ft<kotlin/String, kotlin/String?>>?>|?
public constructor(): R|A|
}
@R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/CheckForNull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.FIELD|())) public abstract annotation class FieldsAreNullable : R|kotlin/Annotation| {
}

View File

@@ -5,4 +5,6 @@
@R|javax/annotation/Nonnull|() public open operator fun bar(): R|kotlin/String|
public constructor(): R|A|
}

View File

@@ -5,6 +5,8 @@ public open class A : R|kotlin/Any| {
@R|javax/annotation/Nonnull|() public open operator fun bar(): R|kotlin/String|
public constructor(): R|test/A|
}
public open class A2 : R|kotlin/Any| {
@R|javax/annotation/Nullable|() public open field field: R|kotlin/String|?
@@ -13,4 +15,6 @@ public open class A2 : R|kotlin/Any| {
@R|javax/annotation/Nonnull|() public open operator fun bar(): R|kotlin/String|
public constructor(): R|test2/A2|
}

View File

@@ -7,6 +7,8 @@
@R|spr/Nullable|() public open operator fun baz(): R|ft<kotlin/collections/MutableList<ft<kotlin/String, kotlin/String?>>?, kotlin/collections/List<ft<kotlin/String, kotlin/String?>>?>|?
public constructor(): R|A|
}
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.TYPE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
}

View File

@@ -7,6 +7,8 @@ public open class A : R|kotlin/Any| {
@R|spr/Nullable|() public open operator fun baz(): R|ft<kotlin/collections/MutableList<ft<kotlin/String, kotlin/String?>>?, kotlin/collections/List<ft<kotlin/String, kotlin/String?>>?>|?
public constructor(): R|test/A|
}
@R|java/lang/annotation/Target|(R|java/lang/annotation/ElementType.PACKAGE|()) @R|java/lang/annotation/Retention|(R|java/lang/annotation/RetentionPolicy.RUNTIME|()) @R|java/lang/annotation/Documented|() @R|javax/annotation/Nonnull|() @R|javax/annotation/meta/TypeQualifierDefault|(<implicitArrayOf>(R|java/lang/annotation/ElementType.METHOD|(), R|java/lang/annotation/ElementType.PARAMETER|())) public abstract annotation class NonNullApi : R|kotlin/Annotation| {
}

View File

@@ -0,0 +1,4 @@
public abstract class AbstractMap : R|kotlin/Any|, R|kotlin/collections/MutableMap<kotlin/String, kotlin/String>| {
public constructor(): R|AbstractMap|
}

View File

@@ -0,0 +1,3 @@
public abstract class AbstractMap implements java.util.Map<String, String> {
}

View File

@@ -7,6 +7,8 @@ public/*package*/ open class A : R|kotlin/Any| {
public open operator fun bam(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(NOT_ENTRY_EITHER)) arg: R|ft<Mixed, Mixed?>|! = R|/Mixed.NOT_ENTRY_EITHER|): R|ft<Mixed, Mixed?>|!
public constructor(): R|A|
}
public final enum class Mixed : R|kotlin/Enum<Mixed>| {
public final static field NOT_ENTRY_EITHER: R|ft<Mixed, Mixed?>|!

View File

@@ -7,6 +7,8 @@ public open class A : R|kotlin/Any| {
public open operator fun fourth(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0B1010)) value: R|ft<kotlin/Long, kotlin/Long?>|! = Long(10)): R|kotlin/Unit|
public constructor(): R|A|
}
public open class B : R|kotlin/Any| {
public open operator fun first(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0x)) value: R|ft<kotlin/Long, kotlin/Long?>|!): R|kotlin/Unit|
@@ -17,4 +19,6 @@ public open class B : R|kotlin/Any| {
public open operator fun fourth(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(0B1234)) value: R|ft<kotlin/Long, kotlin/Long?>|!): R|kotlin/Unit|
public constructor(): R|B|
}

View File

@@ -3,8 +3,12 @@ public open class A : R|kotlin/Any| {
public open operator fun bar(@R|kotlin/annotations/jvm/internal/DefaultNull|() x: R|kotlin/Int| = Null(null)): R|kotlin/Unit|
public constructor(): R|A|
}
public open class B<T> : R|kotlin/Any| {
public open operator fun foo(@R|kotlin/annotations/jvm/internal/DefaultNull|() t: R|ft<T, T?>|! = Null(null)): R|kotlin/Unit|
public constructor<T>(): R|B<T>|
}

View File

@@ -7,6 +7,8 @@ public open class A : R|kotlin/Any| {
public open operator fun baz(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft<kotlin/Int, kotlin/Int?>|! = Int(42)): R|kotlin/Unit|
public constructor(): R|A|
}
public abstract interface AInt : R|kotlin/Any| {
public abstract operator fun foo(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) i: R|ft<kotlin/Int, kotlin/Int?>|! = Int(42)): R|kotlin/Unit|
@@ -21,6 +23,10 @@ public open class B : R|A| {
public open operator fun bam(@R|kotlin/annotations/jvm/internal/DefaultNull|() @R|kotlin/annotations/jvm/internal/DefaultValue|(String(42)) a: R|ft<kotlin/Int, kotlin/Int?>|! = Int(42)): R|kotlin/Unit|
public constructor(): R|B|
}
public open class C : R|A|, R|AInt| {
public constructor(): R|C|
}

View File

@@ -9,4 +9,6 @@ public/*package*/ open class A : R|kotlin/Any| {
public open operator fun wrong(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(hello)) i: R|ft<kotlin/Int, kotlin/Int?>|!): R|kotlin/Unit|
public constructor(): R|A|
}

View File

@@ -5,4 +5,6 @@ public/*package*/ open class A : R|kotlin/Any| {
public open operator fun numberName(@R|kotlin/annotations/jvm/internal/ParameterName|(Int(42)) first: R|ft<kotlin/String, kotlin/String?>|!): R|kotlin/Unit|
public constructor(): R|A|
}

View File

@@ -1,4 +1,6 @@
public open class A : R|kotlin/Any| {
public open operator fun connect(@R|kotlin/annotations/jvm/internal/ParameterName|(String(host)) host: R|ft<kotlin/String, kotlin/String?>|!, @R|kotlin/annotations/jvm/internal/ParameterName|(String(port)) port: R|kotlin/Int|): R|kotlin/Unit|
public constructor(): R|A|
}

View File

@@ -1,4 +1,6 @@
public open class A : R|kotlin/Any| {
public open operator fun same(@R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) first: R|ft<kotlin/String, kotlin/String?>|!, @R|kotlin/annotations/jvm/internal/ParameterName|(String(ok)) second: R|ft<kotlin/String, kotlin/String?>|!): R|kotlin/Unit|
public constructor(): R|A|
}

View File

@@ -3,4 +3,6 @@ public open class A : R|kotlin/Any| {
public open operator fun numberName(@R|kotlin/annotations/jvm/internal/ParameterName|(String(42)) field: R|ft<kotlin/String, kotlin/String?>|!): R|kotlin/Unit|
public constructor(): R|A|
}

View File

@@ -1,4 +1,6 @@
public/*package*/ open class A : R|kotlin/Any| {
public open static operator fun withDefault(@R|kotlin/annotations/jvm/internal/DefaultValue|(String(OK)) arg: R|ft<kotlin/String, kotlin/String?>|! = String(OK)): R|ft<kotlin/String, kotlin/String?>|!
public constructor(): R|A|
}

View File

@@ -0,0 +1,7 @@
val x = 1
val y = 2 as Any
val f = fun() = 3 as Any
val g = {}
val h: (String) -> Boolean = { _ -> false }
val hError = { _ -> true }

View File

@@ -0,0 +1,25 @@
FILE: cast.kt
public final val x: R|kotlin/Int| = Int(1)
public get(): R|kotlin/Int|
public final val y: R|kotlin/Any| = (Int(2) as R|kotlin/Any|)
public get(): R|kotlin/Any|
public final val f: R|kotlin/Function0<kotlin/Any>| = fun <anonymous>(): R|kotlin/Any| {
^ (Int(3) as R|kotlin/Any|)
}
public get(): R|kotlin/Function0<kotlin/Any>|
public final val g: R|kotlin/Function0<kotlin/Unit>| = fun <anonymous>(): R|kotlin/Unit| {
Unit
}
public get(): R|kotlin/Function0<kotlin/Unit>|
public final val h: R|kotlin/Function1<kotlin/String, kotlin/Boolean>| = fun R|kotlin/Function1<kotlin/String, kotlin/Boolean>|.<anonymous>(_: R|kotlin/String|): R|kotlin/Function1<kotlin/String, kotlin/Boolean>| {
Boolean(false)
}
public get(): R|kotlin/Function1<kotlin/String, kotlin/Boolean>|
public final val hError: R|kotlin/Function1<class error: No type for parameter, kotlin/Boolean>| = fun <anonymous>(_: R|class error: No type for parameter|): R|kotlin/Boolean| {
Boolean(true)
}
public get(): R|kotlin/Function1<class error: No type for parameter, kotlin/Boolean>|

View File

@@ -23,7 +23,7 @@ FILE: enum.kt
public final enum entry FIRST : R|SomeEnum| {
public constructor(): R|SomeEnum.FIRST| {
super<R|SomeEnum|>(R|/O1|)
super<R|SomeEnum|>(Q|O1|)
}
public final override fun check(y: R|Some|): R|kotlin/Boolean| {
@@ -34,11 +34,11 @@ FILE: enum.kt
public final enum entry SECOND : R|SomeEnum| {
public constructor(): R|SomeEnum.SECOND| {
super<R|SomeEnum|>(R|/O2|)
super<R|SomeEnum|>(Q|O2|)
}
public final override fun check(y: R|Some|): R|kotlin/Boolean| {
^check ==(R|<local>/y|, R|/O2|)
^check ==(R|<local>/y|, Q|O2|)
}
}

View File

@@ -42,10 +42,10 @@ FILE: companion.kt
}
public final fun test(): R|kotlin/Unit| {
R|/A|.R|/A.Companion.foo|()
R|/B|.<Inapplicable(WRONG_RECEIVER): [/A.bar]>#()
R|/B|.R|/B.Companion.baz|()
lval x: R|kotlin/String| = R|/A|.R|/A.Companion.D|
lval y: R|kotlin/String| = R|/B|.R|/B.Companion.C|
lval z: <ERROR TYPE REF: Unresolved name: D> = R|/B|.<Unresolved name: D>#
Q|A|.R|/A.Companion.foo|()
Q|B|.R|/A.bar|()
Q|B|.R|/B.Companion.baz|()
lval x: R|kotlin/String| = Q|A|.R|/A.Companion.D|
lval y: R|kotlin/String| = Q|B|.R|/B.Companion.C|
lval z: <ERROR TYPE REF: Unresolved name: D> = Q|B|.<Unresolved name: D>#
}

View File

@@ -13,8 +13,8 @@ FILE: explicitReceiver.kt
^invoke this#
}
public final fun bar(): R|kotlin/Unit| {
^bar R|/x|()
public final fun bar(): R|Foo| {
^bar R|/Foo.invoke|()
}
}

View File

@@ -23,8 +23,8 @@ FILE: explicitReceiver2.kt
public final val x: R|Bar| = R|/Bar.Bar|()
public get(): R|Bar|
public final fun bar(): R|kotlin/Unit| {
^bar R|/x|()
public final fun bar(): R|Foo| {
^bar R|/Bar.invoke|()
}
}

View File

@@ -7,5 +7,5 @@ class Foo {
val x = 0
fun foo() = x()
fun foo() = x() // should resolve to invoke
}

View File

@@ -8,5 +8,5 @@ class Foo {
val x = 0
fun foo() = x()
fun foo() = x() // should resolve to fun x
}

View File

@@ -1,6 +1,6 @@
class A {
fun bar() = foo()
fun bar() = foo() // should resolve to invoke
fun invoke() = this
}

View File

@@ -4,8 +4,8 @@ FILE: implicitTypeOrder.kt
super<R|kotlin/Any|>()
}
public final fun bar(): <ERROR TYPE REF: Unresolved name: foo> {
^bar <Unresolved name: foo>#()
public final fun bar(): R|A| {
^bar R|/A.invoke|()
}
public final fun invoke(): R|A| {

View File

@@ -0,0 +1,7 @@
class Simple {
operator fun invoke(): String = "invoke"
}
fun test(s: Simple) {
val result = s()
}

View File

@@ -0,0 +1,14 @@
FILE: simple.kt
public final class Simple : R|kotlin/Any| {
public constructor(): R|Simple| {
super<R|kotlin/Any|>()
}
public final operator fun invoke(): R|kotlin/String| {
^invoke String(invoke)
}
}
public final fun test(s: R|Simple|): R|kotlin/Unit| {
lval result: R|kotlin/String| = R|/Simple.invoke|()
}

View File

@@ -10,8 +10,8 @@ FILE: objects.kt
}
public final fun use(): R|A| {
^use R|/A|
^use Q|A|
}
public final fun bar(): R|A| {
^bar R|/A|.R|/A.foo|()
^bar Q|A|.R|/A.foo|()
}

View File

@@ -0,0 +1,33 @@
package a.b
class C {
object D {
fun foo() {}
}
companion object {
fun foo() {}
}
fun foo() {}
}
enum class E {
entry
}
fun foo() {}
val f = 10
fun main() {
a.b.foo()
a.b.C.foo()
a.b.C.D.foo()
val x = a.b.f
C.foo()
C().foo()
val e = a.b.E.entry
val e1 = E.entry
}

View File

@@ -0,0 +1,57 @@
FILE: qualifiedExpressions.kt
public final class C : R|kotlin/Any| {
public constructor(): R|a/b/C| {
super<R|kotlin/Any|>()
}
public final object D : R|kotlin/Any| {
private constructor(): R|a/b/C.D| {
super<R|kotlin/Any|>()
}
public final fun foo(): R|kotlin/Unit| {
}
}
public final companion object Companion : R|kotlin/Any| {
private constructor(): R|a/b/C.Companion| {
super<R|kotlin/Any|>()
}
public final fun foo(): R|kotlin/Unit| {
}
}
public final fun foo(): R|kotlin/Unit| {
}
}
public final enum class E : R|kotlin/Enum| {
private constructor(): R|a/b/E| {
super<R|kotlin/Enum|>()
}
public final enum entry entry : R|kotlin/Any| {
public constructor(): R|a/b/E.entry| {
super<R|kotlin/Any|>()
}
}
}
public final fun foo(): R|kotlin/Unit| {
}
public final val f: R|kotlin/Int| = Int(10)
public get(): R|kotlin/Int|
public final fun main(): R|kotlin/Unit| {
Q|a/b|.R|a/b/foo|()
Q|a/b/C|.R|a/b/C.Companion.foo|()
Q|a/b/C.D|.R|a/b/C.D.foo|()
lval x: R|kotlin/Int| = Q|a/b|.R|a/b/f|
Q|a/b/C|.R|a/b/C.Companion.foo|()
R|a/b/C.C|().R|a/b/C.foo|()
lval e: R|a/b/E| = Q|a/b/E.entry|
lval e1: R|a/b/E| = Q|a/b/E.entry|
}

View File

@@ -0,0 +1,13 @@
fun String.foo() {}
fun String.bar() {
foo()
}
class My {
fun bar() {
foo()
}
}
fun My.foo() {}

View File

@@ -0,0 +1,18 @@
FILE: extension.kt
public final fun R|kotlin/String|.foo(): R|kotlin/Unit| {
}
public final fun R|kotlin/String|.bar(): R|kotlin/Unit| {
R|/foo|()
}
public final class My : R|kotlin/Any| {
public constructor(): R|My| {
super<R|kotlin/Any|>()
}
public final fun bar(): R|kotlin/Unit| {
R|/foo|()
}
}
public final fun R|My|.foo(): R|kotlin/Unit| {
}

View File

@@ -1,4 +1,5 @@
class C
class D
open class A {
open fun foo(): A = this
@@ -9,12 +10,12 @@ open class A {
class B : A() {
override fun foo(): B = this
fun bar(): B = this // Ambiguity, no override here (really it's just "missing override" and no ambiguity)
override fun buz(p: B): B = this //No override as B <!:> A
override fun buz(p: C): B = this //No override as C <!:> A
fun test() {
foo()
bar()
buz()
buz(D())
}
}

View File

@@ -1,4 +1,16 @@
FILE: simple.kt
public final class C : R|kotlin/Any| {
public constructor(): R|C| {
super<R|kotlin/Any|>()
}
}
public final class D : R|kotlin/Any| {
public constructor(): R|D| {
super<R|kotlin/Any|>()
}
}
public open class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
@@ -30,14 +42,14 @@ FILE: simple.kt
^bar this#
}
public final override fun buz(p: R|B|): R|B| {
public final override fun buz(p: R|C|): R|B| {
^buz this#
}
public final fun test(): R|kotlin/Unit| {
R|/B.foo|()
R|/B.bar|()
<Inapplicable(PARAMETER_MAPPING_ERROR): [/B.buz, /A.buz]>#()
<Inapplicable(INAPPLICABLE): [/B.buz, /A.buz]>#(R|/D.D|())
}
}

View File

@@ -9,7 +9,7 @@ FILE: arrayFirstOrNull.kt
}
public final fun <T> R|kotlin/Array<out T>|.firstOrNullX(): R|T|? {
^firstOrNullX when () {
<Unresolved name: isEmpty>#() -> {
R|kotlin/collections/isEmpty|<R|T|>() -> {
Null(null)
}
else -> {

View File

@@ -1,4 +1,4 @@
FILE: companionLoad.kt
public final fun main(): R|kotlin/Unit| {
lval y: R|kotlin/Int| = R|kotlin/Int|.R|kotlin/Int.Companion.MAX_VALUE|
lval y: R|kotlin/Int| = Q|kotlin/Int|.R|kotlin/Int.Companion.MAX_VALUE|
}

View File

@@ -1,5 +1,5 @@
FILE: reflectionClass.kt
public final val javaClass: R|java/lang/Class<kotlin/String>| = <getClass>(R|kotlin/String|).R|kotlin/jvm/java|
public final val javaClass: R|java/lang/Class<kotlin/String>| = <getClass>(Q|kotlin/String|).R|kotlin/jvm/java|
public get(): R|java/lang/Class<kotlin/String>|
public final val kotlinClass: R|kotlin/reflect/KClass<kotlin/String>| = <getClass>(R|kotlin/String|)
public final val kotlinClass: R|kotlin/reflect/KClass<kotlin/String>| = <getClass>(Q|kotlin/String|)
public get(): R|kotlin/reflect/KClass<kotlin/String>|

View File

@@ -0,0 +1,34 @@
fun testPlus() {
val x = 1 + 2
val y = 3.0 + 4.0
val z = 5 + 6.0
val w = 7.0 + 8
val c = 'a' + 1
val s = "." + ".."
val ss = "" + 1
val list = listOf(1, 2, 3) + 4
val listAndList = listOf(4, 5, 6) + listOf(7, 8)
val mutableList = mutableListOf(9, 10) + listOf(11, 12, 13)
val setAndList = setOf(0) + listOf(1, 2)
val stringAndList = "" + emptyList<Boolean>()
val map = mapOf("" to 1, "." to 2) + (".." to 3)
val mapAndMap = mapOf("-" to 4) + mapOf("_" to 5)
}
fun <T> id(arg: T): T = arg
fun testMap() {
val first = listOf(1, 2, 3).map { it * 2 }
val second = intArrayOf(4, 5, 6).map { it * 2 }
val withId = listOf(1, 2, 3).map { id(it) }
val stringToInt = listOf("alpha", "omega").map { it.length }
val viaWith = with(listOf(42)) {
map { it * it }
}
}
fun testWith() {
val length = with("") { length }
val indices = with("") { indices }
val indicesNoWith = "".indices
}

View File

@@ -0,0 +1,56 @@
FILE: topLevelResolve.kt
public final fun testPlus(): R|kotlin/Unit| {
lval x: R|kotlin/Int| = Int(1).R|kotlin/Int.plus|(Int(2))
lval y: R|kotlin/Double| = Double(3.0).R|kotlin/Double.plus|(Double(4.0))
lval z: R|kotlin/Double| = Int(5).R|kotlin/Int.plus|(Double(6.0))
lval w: R|kotlin/Double| = Double(7.0).R|kotlin/Double.plus|(Int(8))
lval c: R|kotlin/Char| = Char(a).R|kotlin/Char.plus|(Int(1))
lval s: R|kotlin/String| = String(.).R|kotlin/String.plus|(String(..))
lval ss: R|kotlin/String| = String().R|kotlin/String.plus|(Int(1))
lval list: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(1), Int(2), Int(3)).R|kotlin/collections/plus|<R|kotlin/Int|>(Int(4))
lval listAndList: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(4), Int(5), Int(6)).R|kotlin/collections/plus|<R|kotlin/Int|>(R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(7), Int(8)))
lval mutableList: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/collections/mutableListOf|<R|kotlin/Int|>(Int(9), Int(10)).R|kotlin/collections/plus|<R|kotlin/Int|>(R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(11), Int(12), Int(13)))
lval setAndList: R|kotlin/collections/Set<kotlin/Int>| = R|kotlin/collections/setOf|<R|kotlin/Int|>(Int(0)).R|kotlin/collections/plus|<R|kotlin/Int|>(R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(1), Int(2)))
lval stringAndList: R|kotlin/String| = String().R|kotlin/String.plus|(R|kotlin/collections/emptyList|<R|kotlin/Boolean|>())
lval map: R|kotlin/collections/Map<kotlin/String, kotlin/Int>| = R|kotlin/collections/mapOf|<R|kotlin/String|, R|kotlin/Int|>(String().R|kotlin/to|<R|kotlin/String|, R|kotlin/Int|>(Int(1)), String(.).R|kotlin/to|<R|kotlin/String|, R|kotlin/Int|>(Int(2))).R|kotlin/collections/plus|<R|kotlin/String|, R|kotlin/Int|>(String(..).R|kotlin/to|<R|kotlin/String|, R|kotlin/Int|>(Int(3)))
lval mapAndMap: <ERROR TYPE REF: Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]> = <Ambiguity: mapOf, [kotlin/collections/mapOf, kotlin/collections/mapOf]>#(String(-).R|kotlin/to|(Int(4))).<Ambiguity: plus, [kotlin/plus, kotlin/plus, kotlin/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/collections/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/sequences/plus, kotlin/text/plus]>#(<Ambiguity: mapOf, [kotlin/collections/mapOf, kotlin/collections/mapOf]>#(String(_).R|kotlin/to|(Int(5))))
}
public final fun <T> id(arg: R|T|): R|T| {
^id R|<local>/arg|
}
public final fun testMap(): R|kotlin/Unit| {
lval first: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(1), Int(2), Int(3)).R|kotlin/collections/map|<R|kotlin/Int|, R|kotlin/Int|>(<L> = map@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Function1<kotlin/Int, kotlin/Int>| {
R|<local>/it|.R|kotlin/Int.times|(Int(2))
}
)
lval second: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/intArrayOf|(Int(4), Int(5), Int(6)).R|kotlin/collections/map|<R|kotlin/Int|>(<L> = map@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Function1<kotlin/Int, kotlin/Int>| {
R|<local>/it|.R|kotlin/Int.times|(Int(2))
}
)
lval withId: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(1), Int(2), Int(3)).R|kotlin/collections/map|<R|kotlin/Int|, R|kotlin/Int|>(<L> = map@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Function1<kotlin/Int, kotlin/Int>| {
R|/id|<R|kotlin/Int|>(R|<local>/it|)
}
)
lval stringToInt: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/collections/listOf|<R|kotlin/String|>(String(alpha), String(omega)).R|kotlin/collections/map|<R|kotlin/String|, R|kotlin/Int|>(<L> = map@fun <anonymous>(it: R|kotlin/String|): R|kotlin/Function1<kotlin/String, kotlin/Int>| {
R|<local>/it|.R|kotlin/String.length|
}
)
lval viaWith: R|kotlin/collections/List<kotlin/Int>| = R|kotlin/with|<R|kotlin/collections/List<kotlin/Int>|, R|kotlin/collections/List<kotlin/Int>|>(R|kotlin/collections/listOf|<R|kotlin/Int|>(Int(42)), <L> = with@fun R|kotlin/collections/List<kotlin/Int>|.<anonymous>(it: R|kotlin/collections/List<kotlin/Int>|): R|kotlin/Function2<kotlin/collections/List<kotlin/Int>, kotlin/collections/List<kotlin/Int>, kotlin/collections/List<kotlin/Int>>| {
R|kotlin/collections/map|<R|kotlin/Int|, R|kotlin/Int|>(<L> = map@fun <anonymous>(it: R|kotlin/Int|): R|kotlin/Function1<kotlin/Int, kotlin/Int>| {
R|<local>/it|.R|kotlin/Int.times|(R|<local>/it|)
}
)
}
)
}
public final fun testWith(): R|kotlin/Unit| {
lval length: R|kotlin/Int| = R|kotlin/with|<R|kotlin/String|, R|kotlin/Int|>(String(), <L> = with@fun R|kotlin/String|.<anonymous>(it: R|kotlin/String|): R|kotlin/Function2<kotlin/String, kotlin/String, kotlin/Int>| {
R|kotlin/String.length|
}
)
lval indices: R|kotlin/ranges/IntRange| = R|kotlin/with|<R|kotlin/String|, R|kotlin/ranges/IntRange|>(String(), <L> = with@fun R|kotlin/String|.<anonymous>(it: R|kotlin/String|): R|kotlin/Function2<kotlin/String, kotlin/String, kotlin/ranges/IntRange>| {
R|kotlin/text/indices|
}
)
lval indicesNoWith: R|kotlin/ranges/IntRange| = String().R|kotlin/text/indices|
}

View File

@@ -29,6 +29,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/resolve"), Pattern.compile("^([^.]+)\\.kt$"), TargetBackend.ANY, true, "stdlib");
}
@TestMetadata("cast.kt")
public void testCast() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/cast.kt");
}
@TestMetadata("companion.kt")
public void testCompanion() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/companion.kt");
@@ -49,6 +54,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/enum.kt");
}
@TestMetadata("extension.kt")
public void testExtension() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/extension.kt");
}
@TestMetadata("F.kt")
public void testF() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/F.kt");
@@ -257,6 +267,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/expresssions/objects.kt");
}
@TestMetadata("qualifiedExpressions.kt")
public void testQualifiedExpressions() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/qualifiedExpressions.kt");
}
@TestMetadata("receiverConsistency.kt")
public void testReceiverConsistency() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/receiverConsistency.kt");
@@ -352,6 +367,11 @@ public class FirResolveTestCaseGenerated extends AbstractFirResolveTestCase {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/implicitTypeOrder.kt");
}
@TestMetadata("simple.kt")
public void testSimple() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/simple.kt");
}
@TestMetadata("threeReceivers.kt")
public void testThreeReceivers() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/expresssions/invoke/threeReceivers.kt");

View File

@@ -79,6 +79,11 @@ public class FirResolveTestCaseWithStdlibGenerated extends AbstractFirResolveTes
runTest("compiler/fir/resolve/testData/resolve/stdlib/reflectionClass.kt");
}
@TestMetadata("topLevelResolve.kt")
public void testTopLevelResolve() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/topLevelResolve.kt");
}
@TestMetadata("typeAliasDeserialization.kt")
public void testTypeAliasDeserialization() throws Exception {
runTest("compiler/fir/resolve/testData/resolve/stdlib/typeAliasDeserialization.kt");

View File

@@ -115,6 +115,24 @@ public class OwnFirTypeEnhancementTestGenerated extends AbstractOwnFirTypeEnhanc
}
}
@TestMetadata("compiler/fir/resolve/testData/enhancement/mapping")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Mapping extends AbstractOwnFirTypeEnhancementTest {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, TargetBackend.ANY, testDataFilePath);
}
@TestMetadata("AbstractMap.java")
public void testAbstractMap() throws Exception {
runTest("compiler/fir/resolve/testData/enhancement/mapping/AbstractMap.java");
}
public void testAllFilesPresentInMapping() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/fir/resolve/testData/enhancement/mapping"), Pattern.compile("^(.+)\\.java$"), TargetBackend.ANY, true);
}
}
@TestMetadata("compiler/fir/resolve/testData/enhancement/signatureAnnotations")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)

View File

@@ -350,8 +350,8 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
println()
}
if (property.isVar) {
property.setter.accept(this)
if (property.setter.body == null) {
property.setter?.accept(this)
if (property.setter?.body == null) {
println()
}
}
@@ -930,4 +930,15 @@ class FirRenderer(builder: StringBuilder) : FirVisitorVoid() {
uncheckedNotNullCast.expression.accept(this)
print("!")
}
override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier) {
print("Q|")
val classId = resolvedQualifier.classId
if (classId != null) {
print(classId.asString())
} else {
print(resolvedQualifier.packageFqName.asString().replace(".", "/"))
}
print("|")
}
}

View File

@@ -22,7 +22,7 @@ interface FirProperty : @VisitedSupertype FirDeclaration, FirCallableMemberDecla
// Should it be nullable or have some default?
val getter: FirPropertyAccessor
val setter: FirPropertyAccessor
val setter: FirPropertyAccessor?
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R =
visitor.visitProperty(this, data)
@@ -32,6 +32,6 @@ interface FirProperty : @VisitedSupertype FirDeclaration, FirCallableMemberDecla
initializer?.accept(visitor, data)
delegate?.accept(visitor, data)
getter.accept(visitor, data)
setter.accept(visitor, data)
setter?.accept(visitor, data)
}
}

View File

@@ -18,6 +18,7 @@ import org.jetbrains.kotlin.fir.symbols.impl.FirClassSymbol
import org.jetbrains.kotlin.fir.transformInplace
import org.jetbrains.kotlin.fir.transformSingle
import org.jetbrains.kotlin.fir.types.FirTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitEnumTypeRef
import org.jetbrains.kotlin.fir.types.impl.FirImplicitTypeRefImpl
import org.jetbrains.kotlin.fir.visitors.FirTransformer
import org.jetbrains.kotlin.name.Name
@@ -42,7 +43,7 @@ class FirEnumEntryImpl(
isData = false,
isInline = false
), FirEnumEntry {
override var typeRef: FirTypeRef = FirImplicitTypeRefImpl(session, null)
override var typeRef: FirTypeRef = FirImplicitEnumTypeRef(session, null)
override val arguments = mutableListOf<FirExpression>()

View File

@@ -36,7 +36,7 @@ class FirMemberPropertyImpl(
override val isVar: Boolean,
override var initializer: FirExpression?,
override var getter: FirPropertyAccessor,
override var setter: FirPropertyAccessor,
override var setter: FirPropertyAccessor?,
override var delegate: FirExpression?
) : FirAbstractCallableMember(
session, psi, name, visibility, modality, isExpect, isActual, isOverride, receiverTypeRef, returnTypeRef
@@ -49,7 +49,7 @@ class FirMemberPropertyImpl(
override fun <D> transformChildren(transformer: FirTransformer<D>, data: D): FirElement {
getter = getter.transformSingle(transformer, data)
setter = setter.transformSingle(transformer, data)
setter = setter?.transformSingle(transformer, data)
initializer = initializer?.transformSingle(transformer, data)
delegate = delegate?.transformSingle(transformer, data)

View File

@@ -0,0 +1,22 @@
/*
* Copyright 2010-2019 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.expressions
import org.jetbrains.kotlin.fir.visitors.FirVisitor
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
interface FirResolvedQualifier : FirExpression {
override fun <R, D> accept(visitor: FirVisitor<R, D>, data: D): R = visitor.visitResolvedQualifier(this, data)
val packageFqName: FqName
val relativeClassFqName: FqName?
val classId
get() = relativeClassFqName?.let {
ClassId(packageFqName, it, false)
}
}

View File

@@ -0,0 +1,26 @@
/*
* Copyright 2010-2019 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.expressions.impl
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.fir.FirSession
import org.jetbrains.kotlin.fir.expressions.FirResolvedQualifier
import org.jetbrains.kotlin.name.ClassId
import org.jetbrains.kotlin.name.FqName
class FirResolvedQualifierImpl(
session: FirSession,
psi: PsiElement?,
override val packageFqName: FqName,
override val relativeClassFqName: FqName?
) : FirResolvedQualifier, FirAbstractExpression(session, psi) {
constructor(session: FirSession, psi: PsiElement?, classId: ClassId) : this(
session,
psi,
classId.packageFqName,
classId.relativeClassName
)
}

View File

@@ -268,6 +268,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
return transformJump(returnExpression, data)
}
open fun transformResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: D): CompositeTransformResult<FirStatement> {
return transformExpression(resolvedQualifier, data)
}
open fun transformThrowExpression(throwExpression: FirThrowExpression, data: D): CompositeTransformResult<FirStatement> {
return transformExpression(throwExpression, data)
}
@@ -664,6 +668,10 @@ abstract class FirTransformer<in D> : FirVisitor<CompositeTransformResult<FirEle
return transformResolvedImport(resolvedImport, data)
}
final override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: D): CompositeTransformResult<FirElement> {
return transformResolvedQualifier(resolvedQualifier, data)
}
final override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: D): CompositeTransformResult<FirElement> {
return transformResolvedTypeRef(resolvedTypeRef, data)
}

View File

@@ -268,6 +268,10 @@ abstract class FirVisitor<out R, in D> {
return visitJump(returnExpression, data)
}
open fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: D): R {
return visitExpression(resolvedQualifier, data)
}
open fun visitThrowExpression(throwExpression: FirThrowExpression, data: D): R {
return visitExpression(throwExpression, data)
}

View File

@@ -268,6 +268,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitJump(returnExpression, null)
}
open fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier) {
visitExpression(resolvedQualifier, null)
}
open fun visitThrowExpression(throwExpression: FirThrowExpression) {
visitExpression(throwExpression, null)
}
@@ -664,6 +668,10 @@ abstract class FirVisitorVoid : FirVisitor<Unit, Nothing?>() {
visitResolvedImport(resolvedImport)
}
final override fun visitResolvedQualifier(resolvedQualifier: FirResolvedQualifier, data: Nothing?) {
visitResolvedQualifier(resolvedQualifier)
}
final override fun visitResolvedTypeRef(resolvedTypeRef: FirResolvedTypeRef, data: Nothing?) {
visitResolvedTypeRef(resolvedTypeRef)
}

View File

@@ -179,8 +179,8 @@ class NewConstraintSystemImpl(
return !type.contains {
val capturedType = it.asSimpleType()?.asCapturedType()
// TODO: change NewCapturedType to markered one for FE-IR
val typeToCheck = if (capturedType is NewCapturedType && capturedType.captureStatus() == CaptureStatus.FROM_EXPRESSION)
capturedType.constructor.projection.type
val typeToCheck = if (capturedType is CapturedTypeMarker && capturedType.captureStatus() == CaptureStatus.FROM_EXPRESSION)
capturedType.typeConstructorProjection().getType()
else
it

View File

@@ -284,7 +284,11 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon
// Once NI will be more stabilized, we'll use more specific type
else -> type.typeConstructorProjection().getType()//.unwrap()
else -> {
val projection = type.typeConstructorProjection()
if (projection.isStarProjection()) intersectTypes(supertypes.toList())
else projection.getType()
}
}
val baseSubType = type.lowerType() ?: nothingType()
@@ -422,7 +426,7 @@ abstract class AbstractTypeApproximator(val ctx: TypeSystemInferenceExtensionCon
when (effectiveVariance) {
null -> {
return if (conf.errorType) {
ErrorUtils.createErrorType(
createErrorType(
"Inconsistent type: $type ($index parameter has declared variance: ${parameter.getVariance()}, " +
"but argument variance is ${argument.getVariance()})"
)

View File

@@ -1,4 +1,6 @@
public final class ArrayTypeVariance : R|kotlin/Any| {
public final operator fun toArray(p0: R|kotlin/Array<ft<kotlin/Any, kotlin/Any?>>|): R|kotlin/Array<ft<kotlin/Any, kotlin/Any?>>|
public constructor(): R|test/ArrayTypeVariance|
}

View File

@@ -1,2 +1,4 @@
public abstract class ClassDoesNotOverrideMethod : R|java/util/Date| {
public constructor(): R|test/ClassDoesNotOverrideMethod|
}

View File

@@ -3,4 +3,6 @@ public final class ClassWithConstVal : R|kotlin/Any| {
public final field f2: R|kotlin/Int|
public constructor(): R|test/ClassWithConstVal|
}

View File

@@ -1,2 +1,4 @@
public final class ClassWithTypeP<P> : R|kotlin/Any| {
public constructor<P>(): R|test/ClassWithTypeP<P>|
}

View File

@@ -1,2 +1,4 @@
public abstract class ClassWithTypePExtendsIterableP<P> : R|kotlin/Any|, R|kotlin/collections/Iterable<P>| {
public abstract class ClassWithTypePExtendsIterableP<P> : R|kotlin/Any|, R|kotlin/collections/MutableIterable<P>| {
public constructor<P>(): R|test/ClassWithTypePExtendsIterableP<P>|
}

View File

@@ -1,2 +1,4 @@
public final class ClassWithTypePP<P, Q : R|P|> : R|kotlin/Any| {
public final class ClassWithTypePP<P, Q : R|P|, R|P|> : R|kotlin/Any| {
public constructor<P, Q : R|P|, R|P|>(): R|test/ClassWithTypePP<P, Q>|
}

Some files were not shown because too many files have changed in this diff Show More