[FE] Add language feature for context receivers

This commit is contained in:
Anastasiya Shadrina
2021-09-16 17:13:13 +07:00
committed by TeamCityServer
parent 369c86ebb0
commit 910660a083
91 changed files with 222 additions and 3 deletions
@@ -376,6 +376,12 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
)
var selfUpperBoundInference: Boolean by FreezableVar(false)
@Argument(
value = "-Xcontext-receivers",
description = "Enable experimental context receivers"
)
var contextReceivers: Boolean by FreezableVar(false)
open fun configureAnalysisFlags(collector: MessageCollector, languageVersion: LanguageVersion): MutableMap<AnalysisFlag<*>, Any> {
return HashMap<AnalysisFlag<*>, Any>().apply {
put(AnalysisFlags.skipMetadataVersionCheck, skipMetadataVersionCheck)
@@ -433,6 +439,10 @@ abstract class CommonCompilerArguments : CommonToolArguments() {
put(LanguageFeature.DisableCompatibilityModeForNewInference, LanguageFeature.State.ENABLED)
}
if (contextReceivers) {
put(LanguageFeature.ContextReceivers, LanguageFeature.State.ENABLED)
}
if (inlineClasses) {
put(LanguageFeature.InlineClasses, LanguageFeature.State.ENABLED)
}
@@ -47,6 +47,7 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
SealedInterfaceAllowedChecker,
SuspendFunctionAsSupertypeChecker,
EnumCompanionInEnumConstructorCallChecker,
ContextualDeclarationChecker,
)
private val DEFAULT_CALL_CHECKERS = listOf(
@@ -0,0 +1,62 @@
/*
* Copyright 2010-2021 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.resolve.checkers
import org.jetbrains.kotlin.config.LanguageFeature
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.findDescendantOfType
import org.jetbrains.kotlin.psi.psiUtil.isContextualDeclaration
object ContextualDeclarationChecker : DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
if (context.languageVersionSettings.supportsFeature(LanguageFeature.ContextReceivers)) {
return
}
if (declaration.isContextualDeclaration()) {
val contextReceiverList = declaration.findDescendantOfType<KtContextReceiverList>() ?: return
context.trace.report(
Errors.UNSUPPORTED_FEATURE.on(
contextReceiverList, LanguageFeature.ContextReceivers to context.languageVersionSettings
)
)
return
}
val types = mutableListOf<KtTypeReference?>()
when (declaration) {
is KtFunction -> {
types.addAll(declaration.valueParameters.mapNotNull { it.typeReference })
types.add(declaration.receiverTypeReference)
types.add(declaration.typeReference)
}
is KtProperty -> {
types.add(declaration.receiverTypeReference)
types.add(declaration.typeReference)
}
is KtClass -> {
types.addAll(declaration.primaryConstructor?.valueParameters?.map { it.typeReference } ?: emptyList())
}
is KtTypeAlias -> {
types.add(declaration.getTypeReference())
}
}
fun KtTypeReference.isOrHasContextualType(): Boolean {
val typeElement = typeElement as? KtFunctionType ?: return false
return !typeElement.contextReceiversTypeReferences.isNullOrEmpty()
|| typeElement.typeArgumentsAsTypes.any(KtTypeReference::isOrHasContextualType)
}
types.filterNotNull().filter { it.isOrHasContextualType() }.forEach {
context.trace.report(
Errors.UNSUPPORTED_FEATURE.on(
it, LanguageFeature.ContextReceivers to context.languageVersionSettings
)
)
}
}
}
@@ -333,6 +333,15 @@ fun PsiElement.isExtensionDeclaration(): Boolean {
return callable?.receiverTypeReference != null
}
fun KtElement.isContextualDeclaration(): Boolean {
val contextReceivers = when (this) {
is KtCallableDeclaration -> contextReceivers
is KtClassOrObject -> contextReceivers
else -> emptyList()
}
return contextReceivers.isNotEmpty()
}
fun KtClassOrObject.isObjectLiteral(): Boolean = this is KtObjectDeclaration && isObjectLiteral()
//TODO: strange method, and not only Kotlin specific (also Java)
+1
View File
@@ -49,6 +49,7 @@ where advanced options include:
Run sticky condition checks on subsequent phases as well. Implies -Xcheck-phase-conditions
-Xcommon-sources=<path> Sources of the common module that need to be compiled together with this module in the multi-platform mode.
Should be a subset of sources passed as free arguments
-Xcontext-receivers Enable experimental context receivers
-Xdisable-default-scripting-plugin
Do not enable scripting plugin by default
-Xdisable-phases Disable backend phases
+1
View File
@@ -152,6 +152,7 @@ where advanced options include:
Run sticky condition checks on subsequent phases as well. Implies -Xcheck-phase-conditions
-Xcommon-sources=<path> Sources of the common module that need to be compiled together with this module in the multi-platform mode.
Should be a subset of sources passed as free arguments
-Xcontext-receivers Enable experimental context receivers
-Xdisable-default-scripting-plugin
Do not enable scripting plugin by default
-Xdisable-phases Disable backend phases
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
class A {
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
// WITH_RUNTIME
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
// IGNORE_BACKEND_FIR: JVM_IR
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// TARGET_BACKEND: JVM_IR
package test
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface Common {
fun supertypeMember() {}
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface Common {
fun supertypeMember() {}
}
@@ -1,4 +1,6 @@
// !LANGUAGE: +ContextReceivers
// FIR_IDENTICAL
class File(name: String)
interface InputStream
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// FIR_IDENTICAL
interface Canvas
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// FIR_IDENTICAL
class Button
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
data class Pair<A, B>(val first: A, val second: B)
context(Comparator<T>)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
data class Pair<A, B>(val first: A, val second: B)
context(Comparator<T>)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class View
context(View) val Int.dp get() = 42 * this
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class View
context(View) val Int.dp get() = 42 * this
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// !DIAGNOSTICS: -ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE
class Context
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
typealias IterableClass<C, T> = (C) -> Iterator<T>
context(IterableClass<C, T>)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
typealias IterableClass<C, T> = (C) -> Iterator<T>
context(IterableClass<C, T>)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class JSONObject {
fun build(): JSONObject = TODO()
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class JSONObject {
fun build(): JSONObject = TODO()
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface Params
interface Logger {
fun info(message: String)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface Params
interface Logger {
fun info(message: String)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface Semigroup<T> {
infix fun T.combine(other: T): T
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface Semigroup<T> {
infix fun T.combine(other: T): T
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class Session(var lastAccess: Any?)
interface Transaction {
fun loadSession(): Session
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class Session(var lastAccess: Any?)
interface Transaction {
fun loadSession(): Session
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class Storage<T> {
inner class Info
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class Storage<T> {
inner class Info
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class Param
class C {
val c = 42
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class Param
class C {
val c = 42
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
context(T) class A<T>
context(Collection<P>) class B<P>
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
context(T) class A<T>
context(Collection<P>) class B<P>
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A {
fun h1() {}
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A {
fun h1() {}
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface Lazy<T>
context(Lazy<Int>, Lazy<CharSequence>)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface Lazy<T>
context(Lazy<Int>, Lazy<CharSequence>)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface A {
fun f() {}
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface A {
fun f() {}
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A {
val a = 1
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A {
val a = 1
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface A {
fun a(): Int
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface A {
fun a(): Int
}
@@ -1,4 +1,4 @@
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses, +ContextReceivers
class A
@@ -1,4 +1,4 @@
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses
// !LANGUAGE: +InlineClasses, -JvmInlineValueClasses, +ContextReceivers
class A
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// FIR_IDENTICAL
class A
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// !DIAGNOSTICS: -UNUSED_PARAMETER
class Outer {
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// !DIAGNOSTICS: -UNUSED_PARAMETER
class Outer {
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class Context
<!CONFLICTING_OVERLOADS!>context(Context)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class Context
context(Context)
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface Context {
fun h() {}
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
interface Context {
fun h() {}
}
@@ -1,4 +1,6 @@
// FIR_IDENTICAL
// !LANGUAGE: +ContextReceivers
context(
<!SYNTAX!><!>fun foo() {
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A(val a: String?)
context(A) fun f() {
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A(val a: String?)
context(A) fun f() {
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A<T>(val a: T)
class B(val b: Any)
class C(val c: Any)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A<T>(val a: T)
class B(val b: Any)
class C(val c: Any)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A {
val x = 1
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A {
val x = 1
}
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A<T>(val a: T)
class B(val b: Any)
class C(val c: Any)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A<T>(val a: T)
class B(val b: Any)
class C(val c: Any)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A<T>(val a: T)
class B(val b: Any)
class C(val c: Any)
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A<T>(val a: T)
class B(val b: Any)
class C(val c: Any)
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// !DIAGNOSTICS: -UNUSED_PARAMETER
class A
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun <T> listOf(vararg e: T): List<T> = null!!
@@ -1,3 +1,4 @@
// !LANGUAGE: +ContextReceivers
// !DIAGNOSTICS: -UNUSED_PARAMETER
fun <T> listOf(vararg e: T): List<T> = null!!
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
open class A
class B
class C: A()
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
open class A
class B
class C: A()
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A
class B
class C
@@ -1,3 +1,5 @@
// !LANGUAGE: +ContextReceivers
class A
class B
class C
@@ -268,7 +268,8 @@ enum class LanguageFeature(
ExplicitBackingFields(sinceVersion = null, defaultState = State.DISABLED, kind = UNSTABLE_FEATURE),
FunctionalTypeWithExtensionAsSupertype(sinceVersion = KOTLIN_1_6, defaultState = State.DISABLED),
JsAllowInvalidCharsIdentifiersEscaping(sinceVersion = null, defaultState = State.DISABLED, kind = UNSTABLE_FEATURE),
JsAllowValueClassesInExternals(sinceVersion = null, defaultState = State.DISABLED, kind = UNSTABLE_FEATURE)
JsAllowValueClassesInExternals(sinceVersion = null, defaultState = State.DISABLED, kind = UNSTABLE_FEATURE),
ContextReceivers(sinceVersion = null, defaultState = State.DISABLED, kind = UNSTABLE_FEATURE),
;