FIR checker: DSL_SCOPE_VIOLATION

This commit is contained in:
Tianyu Geng
2021-09-14 22:29:35 -07:00
committed by TeamCityServer
parent 7aaac2573c
commit 826ea122a9
53 changed files with 331 additions and 550 deletions
@@ -3292,6 +3292,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
token,
)
}
add(FirErrors.DSL_SCOPE_VIOLATION) { firDiagnostic ->
DslScopeViolationImpl(
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir),
firDiagnostic as FirPsiDiagnostic,
token,
)
}
add(FirErrors.TOPLEVEL_TYPEALIASES_ONLY) { firDiagnostic ->
ToplevelTypealiasesOnlyImpl(
firDiagnostic as FirPsiDiagnostic,
@@ -2298,6 +2298,11 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
abstract val property: KtVariableSymbol
}
abstract class DslScopeViolation : KtFirDiagnostic<PsiElement>() {
override val diagnosticClass get() = DslScopeViolation::class
abstract val calleeSymbol: KtSymbol
}
abstract class ToplevelTypealiasesOnly : KtFirDiagnostic<KtTypeAlias>() {
override val diagnosticClass get() = ToplevelTypealiasesOnly::class
}
@@ -2767,6 +2767,12 @@ internal class PropertyAsOperatorImpl(
override val token: ValidityToken,
) : KtFirDiagnostic.PropertyAsOperator(), KtAbstractFirDiagnostic<PsiElement>
internal class DslScopeViolationImpl(
override val calleeSymbol: KtSymbol,
override val firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
) : KtFirDiagnostic.DslScopeViolation(), KtAbstractFirDiagnostic<PsiElement>
internal class ToplevelTypealiasesOnlyImpl(
override val firDiagnostic: FirPsiDiagnostic,
override val token: ValidityToken,
@@ -24532,6 +24532,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/twoLanguages.kt");
}
@Test
@TestMetadata("typeAliasToBuiltinFunctionType.kt")
public void testTypeAliasToBuiltinFunctionType() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/typeAliasToBuiltinFunctionType.kt");
}
@Test
@TestMetadata("unsupportedFeature.kt")
public void testUnsupportedFeature() throws Exception {
@@ -24532,6 +24532,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/twoLanguages.kt");
}
@Test
@TestMetadata("typeAliasToBuiltinFunctionType.kt")
public void testTypeAliasToBuiltinFunctionType() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/typeAliasToBuiltinFunctionType.kt");
}
@Test
@TestMetadata("unsupportedFeature.kt")
public void testUnsupportedFeature() throws Exception {
@@ -24532,6 +24532,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/twoLanguages.kt");
}
@Test
@TestMetadata("typeAliasToBuiltinFunctionType.kt")
public void testTypeAliasToBuiltinFunctionType() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/typeAliasToBuiltinFunctionType.kt");
}
@Test
@TestMetadata("unsupportedFeature.kt")
public void testUnsupportedFeature() throws Exception {
@@ -1191,6 +1191,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
val PROPERTY_AS_OPERATOR by error<PsiElement>(PositioningStrategy.OPERATOR) {
parameter<FirPropertySymbol>("property")
}
val DSL_SCOPE_VIOLATION by error<PsiElement>(PositioningStrategy.REFERENCED_NAME_BY_QUALIFIED) {
parameter<FirBasedSymbol<*>>("calleeSymbol")
}
}
val TYPE_ALIAS by object : DiagnosticGroup("Type alias") {
@@ -623,6 +623,7 @@ object FirErrors {
val INC_DEC_SHOULD_NOT_RETURN_UNIT by error0<KtExpression>(SourceElementPositioningStrategies.OPERATOR)
val ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT by error2<KtExpression, FirNamedFunctionSymbol, String>(SourceElementPositioningStrategies.OPERATOR)
val PROPERTY_AS_OPERATOR by error1<PsiElement, FirPropertySymbol>(SourceElementPositioningStrategies.OPERATOR)
val DSL_SCOPE_VIOLATION by error1<PsiElement, FirBasedSymbol<*>>(SourceElementPositioningStrategies.REFERENCED_NAME_BY_QUALIFIED)
// Type alias
val TOPLEVEL_TYPEALIASES_ONLY by error0<KtTypeAlias>()
@@ -146,6 +146,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATED_TYPE_P
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATION_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DESERIALIZATION_ERROR
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DSL_SCOPE_VIOLATION
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DUPLICATE_LABEL_IN_WHEN
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DYNAMIC_UPPER_BOUND
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_RANGE
@@ -1611,6 +1612,12 @@ class FirDefaultErrorMessages {
"Property ''{0}'' cannot be used as an operator.",
SYMBOL
)
map.put(
DSL_SCOPE_VIOLATION,
"''{0}'' can''t be called in this context by implicit receiver. " +
"Use the explicit one if necessary",
SYMBOL
)
// Type alias
map.put(TOPLEVEL_TYPEALIASES_ONLY, "Nested and local type aliases are not supported")
@@ -225,6 +225,7 @@ private fun mapInapplicableCandidateError(
rootCause.argument.smartcastStability.description,
rootCause.isCastToNotNull
)
is DslScopeViolation -> FirErrors.DSL_SCOPE_VIOLATION.createOn(source, rootCause.calleeSymbol)
else -> genericDiagnostic
}
}.distinct()
@@ -16,6 +16,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
CollectTypeVariableUsagesInfo,
CheckDispatchReceiver,
CheckExtensionReceiver,
CheckDslScopeViolation,
CheckLowPriorityInOverloadResolution,
PostponedVariablesInitializerResolutionStage,
)
@@ -40,6 +41,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
CollectTypeVariableUsagesInfo,
CheckDispatchReceiver,
CheckExtensionReceiver,
CheckDslScopeViolation,
CheckArguments,
CheckCallModifiers,
EagerResolveOfCallableReferences,
@@ -57,6 +59,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
CollectTypeVariableUsagesInfo,
CheckDispatchReceiver,
CheckExtensionReceiver,
CheckDslScopeViolation,
CheckArguments,
EagerResolveOfCallableReferences,
)
@@ -70,6 +73,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
CollectTypeVariableUsagesInfo,
CheckDispatchReceiver,
CheckExtensionReceiver,
CheckDslScopeViolation,
CheckCallableReferenceExpectedType,
CheckLowPriorityInOverloadResolution,
)
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
import org.jetbrains.kotlin.fir.resolve.calls.tower.TowerGroup
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
import org.jetbrains.kotlin.resolve.calls.tower.shouldStopResolve
open class CandidateCollector(
val components: BodyResolveComponents,
@@ -48,7 +49,7 @@ open class CandidateCollector(
fun bestCandidates(): List<Candidate> = candidates
fun shouldStopAtTheLevel(group: TowerGroup): Boolean =
isSuccess() && bestGroup < group
currentApplicability.shouldStopResolve && bestGroup < group
fun isSuccess(): Boolean {
return currentApplicability.isSuccess
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter
import org.jetbrains.kotlin.fir.expressions.FirExpression
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
import org.jetbrains.kotlin.fir.symbols.FirBasedSymbol
import org.jetbrains.kotlin.fir.symbols.impl.FirNamedFunctionSymbol
import org.jetbrains.kotlin.fir.types.ConeKotlinType
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
@@ -102,4 +103,6 @@ class OperatorCallOfNonOperatorFunction(val function: FirNamedFunctionSymbol) :
class Unsupported(val message: String, val source: FirSourceElement? = null) : ResolutionDiagnostic(UNSUPPORTED)
object PropertyAsOperator : ResolutionDiagnostic(PROPERTY_AS_OPERATOR)
object PropertyAsOperator : ResolutionDiagnostic(PROPERTY_AS_OPERATOR)
class DslScopeViolation(val calleeSymbol: FirBasedSymbol<*>) : ResolutionDiagnostic(DSL_SCOPE_VIOLATION)
@@ -5,19 +5,19 @@
package org.jetbrains.kotlin.fir.resolve.calls
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
import org.jetbrains.kotlin.descriptors.Modality
import org.jetbrains.kotlin.fir.FirVisibilityChecker
import org.jetbrains.kotlin.fir.declarations.*
import org.jetbrains.kotlin.fir.declarations.utils.isInfix
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
import org.jetbrains.kotlin.fir.declarations.utils.modality
import org.jetbrains.kotlin.fir.declarations.utils.*
import org.jetbrains.kotlin.fir.expressions.*
import org.jetbrains.kotlin.fir.references.FirSuperReference
import org.jetbrains.kotlin.fir.resolve.directExpansionType
import org.jetbrains.kotlin.fir.resolve.fullyExpandedType
import org.jetbrains.kotlin.fir.resolve.inference.*
import org.jetbrains.kotlin.fir.resolve.isTypeMismatchDueToNullability
import org.jetbrains.kotlin.fir.resolve.toSymbol
import org.jetbrains.kotlin.fir.scopes.FirUnstableSmartcastTypeScope
import org.jetbrains.kotlin.fir.symbols.SymbolInternals
import org.jetbrains.kotlin.fir.symbols.SyntheticSymbol
import org.jetbrains.kotlin.fir.symbols.ensureResolved
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
@@ -32,8 +32,10 @@ import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
import org.jetbrains.kotlin.types.AbstractNullabilityChecker
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
import org.jetbrains.kotlin.util.OperatorNameConventions
abstract class ResolutionStage {
abstract suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext)
@@ -104,6 +106,7 @@ object CheckExtensionReceiver : ResolutionStage() {
}
object CheckDispatchReceiver : ResolutionStage() {
@OptIn(SymbolInternals::class)
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
val explicitReceiverExpression = callInfo.explicitReceiver
if (explicitReceiverExpression.isSuperCall()) {
@@ -144,6 +147,152 @@ object CheckDispatchReceiver : ResolutionStage() {
}
}
/**
* See https://kotlinlang.org/api/latest/jvm/stdlib/kotlin/-dsl-marker/ for more details and
* /compiler/testData/diagnostics/tests/resolve/dslMarker for the test files.
*/
object CheckDslScopeViolation : ResolutionStage() {
private val dslMarkerClassId = ClassId.fromString("kotlin/DslMarker")
@OptIn(ExperimentalStdlibApi::class)
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
fun checkReceiverValue(receiverValue: ReceiverValue?) {
if (receiverValue is ImplicitReceiverValue<*>) {
receiverValue.checkImpl(
candidate,
sink,
context,
{ receiverValue.getDslMarkersOfImplicitReceiver(context) }
) { a, b -> a == b }
}
}
checkReceiverValue(candidate.dispatchReceiverValue)
checkReceiverValue(candidate.extensionReceiverValue)
// For value of builtin functional type with implicit extension receiver, the receiver is passed as the first argument rather than
// an extension receiver of the `invoke` call. Hence, we need to specially handle this case.
// For example, consider the following
// ```
// @DslMarker
// annotation class MyDsl
//
// @MyDsl
// class X
// fun x(block: X.() -> Unit) {}
//
// @MyDsl
// class A
// fun a(block: A.() -> Unit) {}
//
// val useX: X.() -> Unit
//
// fun test() {
// x {
// a {
// useX() // DSL_SCOPE_VIOLATION because `useX` needs "extension receiver" `X`.
// }
// }
// }
// ```
// `useX()` is a call to `invoke` with `useX` as the dispatch receiver. In the FIR tree, extension receiver is represented as an
// implicit `this` expression passed as the first argument.
if (candidate.dispatchReceiverValue?.type?.fullyExpandedType(context.session)?.isBuiltinFunctionalType(context.session) == true &&
(candidate.symbol as? FirNamedFunctionSymbol)?.name == OperatorNameConventions.INVOKE
) {
val firstArg = candidate.argumentMapping?.keys?.firstOrNull() as? FirThisReceiverExpression ?: return
if (firstArg.source != null) return // Having no source means it's implicit.
firstArg.checkImpl(
candidate,
sink,
context,
{ firstArg.getDslMarkersOfThisReceiverExpression(context) }
) { receiver, thisExpression -> receiver.boundSymbol == thisExpression.calleeReference.boundSymbol }
}
}
/**
* Checks whether the implicit receiver (represented as an object of type `T`) violates DSL scope rules.
*/
private fun <T> T.checkImpl(
candidate: Candidate,
sink: CheckerSink,
context: ResolutionContext,
dslMarkersProvider: () -> Set<ClassId>,
isImplicitReceiverMatching: (ImplicitReceiverValue<*>, T) -> Boolean,
) {
val resolvedReceiverIndex = context.bodyResolveContext.implicitReceiverStack.indexOfFirst { isImplicitReceiverMatching(it, this) }
if (resolvedReceiverIndex == -1) return
val closerReceivers = context.bodyResolveContext.implicitReceiverStack.drop(resolvedReceiverIndex + 1)
if (closerReceivers.isEmpty()) return
val dslMarkers = dslMarkersProvider()
if (dslMarkers.isEmpty()) return
if (closerReceivers.any { receiver -> receiver.getDslMarkersOfImplicitReceiver(context).any { it in dslMarkers } }) {
sink.reportDiagnostic(DslScopeViolation(candidate.symbol))
}
}
@OptIn(ExperimentalStdlibApi::class)
private fun ImplicitReceiverValue<*>.getDslMarkersOfImplicitReceiver(context: ResolutionContext): Set<ClassId> {
return buildSet {
collectDslMarkerAnnotations(context, type)
}
}
@OptIn(ExperimentalStdlibApi::class)
private fun FirThisReceiverExpression.getDslMarkersOfThisReceiverExpression(context: ResolutionContext): Set<ClassId> {
return buildSet {
collectDslMarkerAnnotations(context, typeRef.coneType)
}
}
@OptIn(SymbolInternals::class)
private fun MutableSet<ClassId>.collectDslMarkerAnnotations(context: ResolutionContext, type: ConeKotlinType) {
collectDslMarkerAnnotations(context, type.attributes.customAnnotations)
when (type) {
is ConeFlexibleType -> {
collectDslMarkerAnnotations(context, type.lowerBound)
collectDslMarkerAnnotations(context, type.upperBound)
}
is ConeCapturedType -> {
if (type.constructor.projection.kind == ProjectionKind.OUT) {
type.constructor.supertypes?.forEach { collectDslMarkerAnnotations(context, it) }
}
}
is ConeDefinitelyNotNullType -> collectDslMarkerAnnotations(context, type.original)
is ConeIntersectionType -> type.intersectedTypes.forEach { collectDslMarkerAnnotations(context, it) }
is ConeLookupTagBasedType -> {
val classDeclaration = type.toSymbol(context.session)?.fir as? FirClassLikeDeclaration ?: return
collectDslMarkerAnnotations(context, classDeclaration.annotations)
when {
classDeclaration is FirClass -> {
for (superType in classDeclaration.superConeTypes) {
collectDslMarkerAnnotations(context, superType)
}
}
type is ConeClassLikeType -> {
type.directExpansionType(context.session)?.let {
collectDslMarkerAnnotations(context, it)
}
}
}
}
else -> return
}
}
@OptIn(SymbolInternals::class)
private fun MutableSet<ClassId>.collectDslMarkerAnnotations(context: ResolutionContext, annotations: Collection<FirAnnotation>) {
for (annotation in annotations) {
val annotationClass =
annotation.annotationTypeRef.coneType.fullyExpandedType(context.session).toSymbol(context.session)?.fir as? FirClass
?: continue
if (annotationClass.hasAnnotation(dslMarkerClassId)) {
add(annotationClass.classId)
}
}
}
}
private fun FirExpression?.isSuperCall(): Boolean {
if (this !is FirQualifiedAccessExpression) return false
return calleeReference is FirSuperReference
@@ -20,6 +20,11 @@ enum class CandidateApplicability {
UNSAFE_CALL, // receiver or argument nullability doesn't match
UNSTABLE_SMARTCAST, // unstable smart cast
CONVENTION_ERROR, // missing infix, operator etc
// Below has shouldStopResolve = true
DSL_SCOPE_VIOLATION, // Skip other levels for DSL_SCOPE_VIOLATION because if the candidate is marked DSL_SCOPE_VIOLATION with an inner receiver, one should not keep going to outer receivers.
// Below has isSuccess = true
RESOLVED_LOW_PRIORITY,
PROPERTY_AS_OPERATOR, // using property of functional type as an operator. From resolution perspective, this is considered successful.
RESOLVED_NEED_PRESERVE_COMPATIBILITY, // call resolved successfully, but using new features that changes resolve
@@ -29,3 +34,6 @@ enum class CandidateApplicability {
val CandidateApplicability.isSuccess: Boolean
get() = this >= CandidateApplicability.RESOLVED_LOW_PRIORITY
val CandidateApplicability.shouldStopResolve: Boolean
get() = this >= CandidateApplicability.DSL_SCOPE_VIOLATION
@@ -29,7 +29,7 @@ fun main() {
baz1 {
baz2 {
bar()
foo()
<!DSL_SCOPE_VIOLATION!>foo<!>()
}
}
@@ -29,7 +29,7 @@ fun main() {
baz1 {
baz2 {
bar()
foo()
<!DSL_SCOPE_VIOLATION!>foo<!>()
}
}
@@ -1,26 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
annotation class Ann
class A {
fun a() = 1
}
class B {
fun b() = 2
}
fun <T> foo(x: T.() -> Unit) {}
fun <E> bar(x: E.() -> Unit) {}
fun test() {
foo<@Ann A> {
a()
bar<@Ann B> {
a()
this@foo.a()
b()
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
@@ -1,28 +0,0 @@
@DslMarker
@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPEALIAS)
annotation class XMarker
@XMarker
class Foo
class Bar
@XMarker
typealias XBar = Bar
typealias XXBar = XBar
fun Foo.foo(body: Foo.() -> Unit) = body()
fun Foo.xbar(body: XBar.() -> Unit) = Bar().body()
fun Foo.xxbar(body: XXBar.() -> Unit) = Bar().body()
fun test() {
Foo().foo {
xbar {
foo {}
}
xxbar {
foo {}
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
@DslMarker
@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPEALIAS)
annotation class XMarker
@@ -1,30 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@Ann
interface Common
interface C : Common
interface D : C
class A : C {
fun a() = 1
}
class B : D {
fun b() = 2
}
fun foo(x: A.() -> Unit) {}
fun bar(x: B.() -> Unit) {}
fun test() {
foo {
a()
bar {
a()
this@foo.a()
b()
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@@ -1,23 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@Ann
class A {
fun a() = 1
}
@Ann
class B {
fun b() = 2
}
fun bar(x: B.() -> Unit) {}
fun A.test() {
bar {
a()
this@test.a()
b()
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@@ -1,22 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
annotation class Ann
class A {
fun a() = 1
}
class B {
fun b() = 2
}
fun bar(x: (@Ann B).() -> Unit) {}
fun @Ann A.test() {
bar {
a()
this@test.a()
b()
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
@@ -29,12 +29,12 @@ fun test() {
foo12 {
a()
bar1 {
a()
<!DSL_SCOPE_VIOLATION!>a<!>()
b()
}
bar2 {
a()
<!DSL_SCOPE_VIOLATION!>a<!>()
b()
}
}
@@ -43,7 +43,7 @@ fun test() {
b()
foo12 {
a()
b()
<!DSL_SCOPE_VIOLATION!>b<!>()
}
}
@@ -51,7 +51,7 @@ fun test() {
b()
foo12 {
a()
b()
<!DSL_SCOPE_VIOLATION!>b<!>()
}
}
@@ -64,7 +64,7 @@ fun test() {
}
bar2 {
a()
<!DSL_SCOPE_VIOLATION!>a<!>()
b()
}
}
@@ -85,7 +85,7 @@ fun test() {
foo2 {
bar1t(this) {
a()
b()
<!DSL_SCOPE_VIOLATION!>b<!>()
}
}
}
@@ -1,40 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
annotation class Ann
class A {
fun a() = 1
}
class B {
fun b() = 2
}
fun foo(x: (@Ann A).() -> Unit) {}
fun bar(x: (@Ann B).() -> Unit) {}
fun test() {
foo {
a()
foo l1@{
a()
bar l2@{
a()
this@l1.a()
b()
foo l3@{
a()
b()
this@l2.b()
bar {
a()
this@l3.a()
b()
}
}
}
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
@@ -34,13 +34,13 @@ fun test() {
a1++
bar {
a + 1
a += a + 1
a++
<!DSL_SCOPE_VIOLATION!>a<!> + 1
<!DSL_SCOPE_VIOLATION, VARIABLE_EXPECTED!>a<!> += <!DSL_SCOPE_VIOLATION!>a<!> + 1
<!DSL_SCOPE_VIOLATION, DSL_SCOPE_VIOLATION!>a<!>++
a1 + 1
a1 += a1 + 1
a1++
<!DSL_SCOPE_VIOLATION!>a1<!> + 1
<!DSL_SCOPE_VIOLATION, VARIABLE_EXPECTED!>a1<!> += <!DSL_SCOPE_VIOLATION!>a1<!> + 1
<!DSL_SCOPE_VIOLATION, DSL_SCOPE_VIOLATION!>a1<!>++
this@foo.a + 1
this@foo.a += this@foo.a + 1
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@@ -1,26 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
annotation class Ann
class A {
fun a() = 1
}
class B {
fun b() = 2
}
fun foo(x: (@Ann A).() -> Unit) {}
fun bar(x: (@Ann B).() -> Unit) {}
fun test() {
foo {
a()
bar {
a()
this@foo.a()
b()
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
@@ -1,27 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@Ann
class A {
fun a() = 1
}
@Ann
class B {
fun b() = 2
}
fun <T> foo(x: T.() -> Unit) {}
fun <E> bar(x: E.() -> Unit) {}
fun test() {
foo<A> {
a()
bar<B> {
a()
this@foo.a()
b()
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@@ -48,8 +48,8 @@ fun test() {
D().x()
foo1 {
x()
y()
<!DSL_SCOPE_VIOLATION!>x<!>()
<!DSL_SCOPE_VIOLATION!>y<!>()
with(A()) {
x()
@@ -57,19 +57,19 @@ fun test() {
}
with(D()) {
x()
<!DSL_SCOPE_VIOLATION!>x<!>()
}
D().x()
D().<!DSL_SCOPE_VIOLATION!>x<!>()
}
foo2 {
x()
y()
<!DSL_SCOPE_VIOLATION!>y<!>()
}
foo3 {
x()
y()
<!DSL_SCOPE_VIOLATION!>x<!>()
<!DSL_SCOPE_VIOLATION!>y<!>()
}
}
}
@@ -79,7 +79,7 @@ fun test() {
foo {
baz {
bar {
x()
<!DSL_SCOPE_VIOLATION!>x<!>()
y()
}
}
@@ -90,7 +90,7 @@ fun test() {
foo {
baz {
bar {
x()
<!DSL_SCOPE_VIOLATION!>x<!>()
y()
}
}
@@ -101,7 +101,7 @@ fun test() {
foo {
baz {
bar {
x()
<!DSL_SCOPE_VIOLATION!>x<!>()
y()
}
}
@@ -43,8 +43,8 @@ fun test() {
}
foo1 {
x()
y()
<!DSL_SCOPE_VIOLATION!>x<!>()
<!DSL_SCOPE_VIOLATION!>y<!>()
with(A()) {
x()
@@ -52,19 +52,19 @@ fun test() {
}
with(D()) {
x()
<!DSL_SCOPE_VIOLATION!>x<!>()
}
A().x()
}
foo2 {
x()
y()
<!DSL_SCOPE_VIOLATION!>y<!>()
}
foo3 {
x()
y()
<!DSL_SCOPE_VIOLATION!>x<!>()
<!DSL_SCOPE_VIOLATION!>y<!>()
}
}
}
@@ -74,7 +74,7 @@ fun test() {
foo {
baz {
bar {
x()
<!DSL_SCOPE_VIOLATION!>x<!>()
y()
}
}
@@ -85,7 +85,7 @@ fun test() {
foo {
baz {
bar {
x()
<!DSL_SCOPE_VIOLATION!>x<!>()
y()
}
}
@@ -96,7 +96,7 @@ fun test() {
foo {
baz {
bar {
x()
<!DSL_SCOPE_VIOLATION!>x<!>()
y()
}
}
@@ -1,102 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
annotation class Ann1
@DslMarker
@Target(AnnotationTarget.TYPE)
annotation class Ann2
class A {
fun D.extA() {}
}
class B {
fun D.extB() {}
}
class D
fun foo(x: (@Ann1 A).() -> Unit) {}
fun bar(x: (@Ann2 B).() -> Unit) {}
fun baz(x: (@Ann1 D).() -> Unit) {}
fun test() {
foo {
bar {
baz {
extA()
extB()
D().extA()
D().extB()
with(D()) {
extA()
extB()
}
}
}
}
foo {
baz {
extA()
D().extA()
bar {
extA()
extB()
D().extA()
D().extB()
with(D()) {
extA()
extB()
}
}
}
}
baz {
foo {
extA()
D().extA()
bar {
extA()
extB()
D().extA()
D().extB()
with(D()) {
extA()
extB()
}
}
}
}
baz {
bar {
extB()
D().extB()
foo {
extA()
extB()
D().extA()
D().extB()
with(D()) {
extA()
extB()
}
}
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
@@ -1,104 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
annotation class L1
@DslMarker
@Target(AnnotationTarget.TYPE)
annotation class L2
class A {
fun a() = 1
}
class B {
fun b() = 2
}
fun foo1(x: (@L1 A).() -> Unit) {}
fun foo2(x: (@L2 A).() -> Unit) {}
fun bar1(x: (@L1 B).() -> Unit) {}
fun bar2(x: (@L2 B).() -> Unit) {}
fun test() {
foo1 {
a()
foo2 {
a()
bar1 {
a()
b()
bar2 {
a()
b()
}
}
bar2 {
a()
b()
}
}
bar1 {
a()
b()
bar2 {
a()
b()
}
}
bar2 {
a()
b()
}
}
foo2 {
a()
bar1 {
a()
b()
bar2 {
a()
b()
}
}
bar2 {
a()
b()
}
}
bar1 {
b()
bar2 {
b()
}
}
bar2 {
b()
}
foo1 {
bar1 {
a()
b()
foo2 {
a()
b()
bar2 {
a()
b()
}
}
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
@@ -0,0 +1,28 @@
// FIR_IDENTICAL
@DslMarker
annotation class MyDsl
@MyDsl
class X
fun x(block: X.() -> Unit) {}
@MyDsl
class A
fun a(block: A.() -> Unit) {}
val useX1: X.() -> Unit = TODO()
typealias FunctionType = X.() -> Unit
val useX2: FunctionType = TODO()
fun test() {
x {
a {
<!DSL_SCOPE_VIOLATION!>useX1<!>()
<!DSL_SCOPE_VIOLATION!>useX2<!>()
}
}
}
@@ -0,0 +1,29 @@
package
public val useX1: X.() -> kotlin.Unit
public val useX2: FunctionType /* = X.() -> kotlin.Unit */
public fun a(/*0*/ block: A.() -> kotlin.Unit): kotlin.Unit
public fun test(): kotlin.Unit
public fun x(/*0*/ block: X.() -> kotlin.Unit): kotlin.Unit
@MyDsl public final class A {
public constructor A()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@kotlin.DslMarker public final annotation class MyDsl : kotlin.Annotation {
public constructor MyDsl()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@MyDsl public final class X {
public constructor X()
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
public typealias FunctionType = X.() -> kotlin.Unit
@@ -1,3 +1,4 @@
// !LANGUAGE: -DslMarkersSupport
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@@ -19,7 +20,7 @@ fun test() {
foo {
a()
bar {
a()
<!DSL_SCOPE_VIOLATION!>a<!>()
this@foo.a()
b()
}
@@ -1,4 +1,3 @@
// FIR_IDENTICAL
// !LANGUAGE: -DslMarkersSupport
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@@ -1,27 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@Ann
class A
fun A.a() = 1
@Ann
class B
fun B.b() = 2
fun foo(x: A.() -> Unit) {}
fun bar(x: B.() -> Unit) {}
fun test() {
foo {
a()
bar {
a()
this@foo.a()
b()
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@@ -1,24 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@Ann
class A {
fun a() = 1
}
@Ann
class B {
fun b() = 2
}
fun test(a: A, b: B) {
with(a) l1@{
a()
with(b) {
a()
this@l1.a()
b()
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
annotation class Ann
@@ -1,30 +0,0 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
annotation class Ann
class A {
fun a() = 1
}
class B {
fun b() = 2
}
fun foo(x: (@Ann A).() -> Unit) {}
fun bar(x: (@Ann B).() -> Unit) {}
fun test() {
foo {
with(this) l1@{
a()
bar {
with(this) {
a()
this@l1.a()
b()
}
}
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_PARAMETER
@DslMarker
@Target(AnnotationTarget.TYPE)
@@ -24544,6 +24544,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/twoLanguages.kt");
}
@Test
@TestMetadata("typeAliasToBuiltinFunctionType.kt")
public void testTypeAliasToBuiltinFunctionType() throws Exception {
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/typeAliasToBuiltinFunctionType.kt");
}
@Test
@TestMetadata("unsupportedFeature.kt")
public void testUnsupportedFeature() throws Exception {