FIR checker: DSL_SCOPE_VIOLATION
This commit is contained in:
committed by
TeamCityServer
parent
7aaac2573c
commit
826ea122a9
+7
@@ -3292,6 +3292,13 @@ internal val KT_DIAGNOSTIC_CONVERTER = KtDiagnosticConverterBuilder.buildConvert
|
|||||||
token,
|
token,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
add(FirErrors.DSL_SCOPE_VIOLATION) { firDiagnostic ->
|
||||||
|
DslScopeViolationImpl(
|
||||||
|
firSymbolBuilder.buildSymbol(firDiagnostic.a.fir),
|
||||||
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
token,
|
||||||
|
)
|
||||||
|
}
|
||||||
add(FirErrors.TOPLEVEL_TYPEALIASES_ONLY) { firDiagnostic ->
|
add(FirErrors.TOPLEVEL_TYPEALIASES_ONLY) { firDiagnostic ->
|
||||||
ToplevelTypealiasesOnlyImpl(
|
ToplevelTypealiasesOnlyImpl(
|
||||||
firDiagnostic as FirPsiDiagnostic,
|
firDiagnostic as FirPsiDiagnostic,
|
||||||
|
|||||||
+5
@@ -2298,6 +2298,11 @@ sealed class KtFirDiagnostic<PSI : PsiElement> : KtDiagnosticWithPsi<PSI> {
|
|||||||
abstract val property: KtVariableSymbol
|
abstract val property: KtVariableSymbol
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract class DslScopeViolation : KtFirDiagnostic<PsiElement>() {
|
||||||
|
override val diagnosticClass get() = DslScopeViolation::class
|
||||||
|
abstract val calleeSymbol: KtSymbol
|
||||||
|
}
|
||||||
|
|
||||||
abstract class ToplevelTypealiasesOnly : KtFirDiagnostic<KtTypeAlias>() {
|
abstract class ToplevelTypealiasesOnly : KtFirDiagnostic<KtTypeAlias>() {
|
||||||
override val diagnosticClass get() = ToplevelTypealiasesOnly::class
|
override val diagnosticClass get() = ToplevelTypealiasesOnly::class
|
||||||
}
|
}
|
||||||
|
|||||||
+6
@@ -2767,6 +2767,12 @@ internal class PropertyAsOperatorImpl(
|
|||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
) : KtFirDiagnostic.PropertyAsOperator(), KtAbstractFirDiagnostic<PsiElement>
|
) : 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(
|
internal class ToplevelTypealiasesOnlyImpl(
|
||||||
override val firDiagnostic: FirPsiDiagnostic,
|
override val firDiagnostic: FirPsiDiagnostic,
|
||||||
override val token: ValidityToken,
|
override val token: ValidityToken,
|
||||||
|
|||||||
+6
@@ -24532,6 +24532,12 @@ public class DiagnosisCompilerTestFE10TestdataTestGenerated extends AbstractDiag
|
|||||||
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/twoLanguages.kt");
|
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
|
@Test
|
||||||
@TestMetadata("unsupportedFeature.kt")
|
@TestMetadata("unsupportedFeature.kt")
|
||||||
public void testUnsupportedFeature() throws Exception {
|
public void testUnsupportedFeature() throws Exception {
|
||||||
|
|||||||
+6
@@ -24532,6 +24532,12 @@ public class FirOldFrontendDiagnosticsTestGenerated extends AbstractFirDiagnosti
|
|||||||
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/twoLanguages.kt");
|
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
|
@Test
|
||||||
@TestMetadata("unsupportedFeature.kt")
|
@TestMetadata("unsupportedFeature.kt")
|
||||||
public void testUnsupportedFeature() throws Exception {
|
public void testUnsupportedFeature() throws Exception {
|
||||||
|
|||||||
+6
@@ -24532,6 +24532,12 @@ public class FirOldFrontendDiagnosticsWithLightTreeTestGenerated extends Abstrac
|
|||||||
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/twoLanguages.kt");
|
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
|
@Test
|
||||||
@TestMetadata("unsupportedFeature.kt")
|
@TestMetadata("unsupportedFeature.kt")
|
||||||
public void testUnsupportedFeature() throws Exception {
|
public void testUnsupportedFeature() throws Exception {
|
||||||
|
|||||||
+3
@@ -1191,6 +1191,9 @@ object DIAGNOSTICS_LIST : DiagnosticList("FirErrors") {
|
|||||||
val PROPERTY_AS_OPERATOR by error<PsiElement>(PositioningStrategy.OPERATOR) {
|
val PROPERTY_AS_OPERATOR by error<PsiElement>(PositioningStrategy.OPERATOR) {
|
||||||
parameter<FirPropertySymbol>("property")
|
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") {
|
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 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 ASSIGNMENT_OPERATOR_SHOULD_RETURN_UNIT by error2<KtExpression, FirNamedFunctionSymbol, String>(SourceElementPositioningStrategies.OPERATOR)
|
||||||
val PROPERTY_AS_OPERATOR by error1<PsiElement, FirPropertySymbol>(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
|
// Type alias
|
||||||
val TOPLEVEL_TYPEALIASES_ONLY by error0<KtTypeAlias>()
|
val TOPLEVEL_TYPEALIASES_ONLY by error0<KtTypeAlias>()
|
||||||
|
|||||||
+7
@@ -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
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DEPRECATION_ERROR
|
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.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.DUPLICATE_LABEL_IN_WHEN
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DYNAMIC_UPPER_BOUND
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.DYNAMIC_UPPER_BOUND
|
||||||
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_RANGE
|
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors.EMPTY_RANGE
|
||||||
@@ -1611,6 +1612,12 @@ class FirDefaultErrorMessages {
|
|||||||
"Property ''{0}'' cannot be used as an operator.",
|
"Property ''{0}'' cannot be used as an operator.",
|
||||||
SYMBOL
|
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
|
// Type alias
|
||||||
map.put(TOPLEVEL_TYPEALIASES_ONLY, "Nested and local type aliases are not supported")
|
map.put(TOPLEVEL_TYPEALIASES_ONLY, "Nested and local type aliases are not supported")
|
||||||
|
|||||||
+1
@@ -225,6 +225,7 @@ private fun mapInapplicableCandidateError(
|
|||||||
rootCause.argument.smartcastStability.description,
|
rootCause.argument.smartcastStability.description,
|
||||||
rootCause.isCastToNotNull
|
rootCause.isCastToNotNull
|
||||||
)
|
)
|
||||||
|
is DslScopeViolation -> FirErrors.DSL_SCOPE_VIOLATION.createOn(source, rootCause.calleeSymbol)
|
||||||
else -> genericDiagnostic
|
else -> genericDiagnostic
|
||||||
}
|
}
|
||||||
}.distinct()
|
}.distinct()
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
|
|||||||
CollectTypeVariableUsagesInfo,
|
CollectTypeVariableUsagesInfo,
|
||||||
CheckDispatchReceiver,
|
CheckDispatchReceiver,
|
||||||
CheckExtensionReceiver,
|
CheckExtensionReceiver,
|
||||||
|
CheckDslScopeViolation,
|
||||||
CheckLowPriorityInOverloadResolution,
|
CheckLowPriorityInOverloadResolution,
|
||||||
PostponedVariablesInitializerResolutionStage,
|
PostponedVariablesInitializerResolutionStage,
|
||||||
)
|
)
|
||||||
@@ -40,6 +41,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
|
|||||||
CollectTypeVariableUsagesInfo,
|
CollectTypeVariableUsagesInfo,
|
||||||
CheckDispatchReceiver,
|
CheckDispatchReceiver,
|
||||||
CheckExtensionReceiver,
|
CheckExtensionReceiver,
|
||||||
|
CheckDslScopeViolation,
|
||||||
CheckArguments,
|
CheckArguments,
|
||||||
CheckCallModifiers,
|
CheckCallModifiers,
|
||||||
EagerResolveOfCallableReferences,
|
EagerResolveOfCallableReferences,
|
||||||
@@ -57,6 +59,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
|
|||||||
CollectTypeVariableUsagesInfo,
|
CollectTypeVariableUsagesInfo,
|
||||||
CheckDispatchReceiver,
|
CheckDispatchReceiver,
|
||||||
CheckExtensionReceiver,
|
CheckExtensionReceiver,
|
||||||
|
CheckDslScopeViolation,
|
||||||
CheckArguments,
|
CheckArguments,
|
||||||
EagerResolveOfCallableReferences,
|
EagerResolveOfCallableReferences,
|
||||||
)
|
)
|
||||||
@@ -70,6 +73,7 @@ sealed class CallKind(vararg resolutionSequence: ResolutionStage) {
|
|||||||
CollectTypeVariableUsagesInfo,
|
CollectTypeVariableUsagesInfo,
|
||||||
CheckDispatchReceiver,
|
CheckDispatchReceiver,
|
||||||
CheckExtensionReceiver,
|
CheckExtensionReceiver,
|
||||||
|
CheckDslScopeViolation,
|
||||||
CheckCallableReferenceExpectedType,
|
CheckCallableReferenceExpectedType,
|
||||||
CheckLowPriorityInOverloadResolution,
|
CheckLowPriorityInOverloadResolution,
|
||||||
)
|
)
|
||||||
|
|||||||
+2
-1
@@ -9,6 +9,7 @@ import org.jetbrains.kotlin.fir.resolve.BodyResolveComponents
|
|||||||
import org.jetbrains.kotlin.fir.resolve.calls.tower.TowerGroup
|
import org.jetbrains.kotlin.fir.resolve.calls.tower.TowerGroup
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
import org.jetbrains.kotlin.resolve.calls.tower.isSuccess
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.tower.shouldStopResolve
|
||||||
|
|
||||||
open class CandidateCollector(
|
open class CandidateCollector(
|
||||||
val components: BodyResolveComponents,
|
val components: BodyResolveComponents,
|
||||||
@@ -48,7 +49,7 @@ open class CandidateCollector(
|
|||||||
fun bestCandidates(): List<Candidate> = candidates
|
fun bestCandidates(): List<Candidate> = candidates
|
||||||
|
|
||||||
fun shouldStopAtTheLevel(group: TowerGroup): Boolean =
|
fun shouldStopAtTheLevel(group: TowerGroup): Boolean =
|
||||||
isSuccess() && bestGroup < group
|
currentApplicability.shouldStopResolve && bestGroup < group
|
||||||
|
|
||||||
fun isSuccess(): Boolean {
|
fun isSuccess(): Boolean {
|
||||||
return currentApplicability.isSuccess
|
return currentApplicability.isSuccess
|
||||||
|
|||||||
+3
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.fir.declarations.FirValueParameter
|
|||||||
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
import org.jetbrains.kotlin.fir.expressions.FirExpression
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
import org.jetbrains.kotlin.fir.expressions.FirExpressionWithSmartcast
|
||||||
import org.jetbrains.kotlin.fir.expressions.FirNamedArgumentExpression
|
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.symbols.impl.FirNamedFunctionSymbol
|
||||||
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
import org.jetbrains.kotlin.fir.types.ConeKotlinType
|
||||||
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
import org.jetbrains.kotlin.resolve.ForbiddenNamedArgumentsTarget
|
||||||
@@ -103,3 +104,5 @@ class OperatorCallOfNonOperatorFunction(val function: FirNamedFunctionSymbol) :
|
|||||||
class Unsupported(val message: String, val source: FirSourceElement? = null) : ResolutionDiagnostic(UNSUPPORTED)
|
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)
|
||||||
+153
-4
@@ -5,19 +5,19 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.fir.resolve.calls
|
package org.jetbrains.kotlin.fir.resolve.calls
|
||||||
|
|
||||||
import org.jetbrains.kotlin.resolve.deprecation.DeprecationLevelValue
|
|
||||||
import org.jetbrains.kotlin.descriptors.Modality
|
import org.jetbrains.kotlin.descriptors.Modality
|
||||||
import org.jetbrains.kotlin.fir.FirVisibilityChecker
|
import org.jetbrains.kotlin.fir.FirVisibilityChecker
|
||||||
import org.jetbrains.kotlin.fir.declarations.*
|
import org.jetbrains.kotlin.fir.declarations.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isInfix
|
import org.jetbrains.kotlin.fir.declarations.utils.*
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.isOperator
|
|
||||||
import org.jetbrains.kotlin.fir.declarations.utils.modality
|
|
||||||
import org.jetbrains.kotlin.fir.expressions.*
|
import org.jetbrains.kotlin.fir.expressions.*
|
||||||
import org.jetbrains.kotlin.fir.references.FirSuperReference
|
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.inference.*
|
||||||
import org.jetbrains.kotlin.fir.resolve.isTypeMismatchDueToNullability
|
import org.jetbrains.kotlin.fir.resolve.isTypeMismatchDueToNullability
|
||||||
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
import org.jetbrains.kotlin.fir.resolve.toSymbol
|
||||||
import org.jetbrains.kotlin.fir.scopes.FirUnstableSmartcastTypeScope
|
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.SyntheticSymbol
|
||||||
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
import org.jetbrains.kotlin.fir.symbols.ensureResolved
|
||||||
import org.jetbrains.kotlin.fir.symbols.impl.FirCallableSymbol
|
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.name.Name
|
||||||
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
import org.jetbrains.kotlin.resolve.calls.tasks.ExplicitReceiverKind.*
|
||||||
import org.jetbrains.kotlin.resolve.calls.tower.CandidateApplicability
|
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.AbstractNullabilityChecker
|
||||||
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
import org.jetbrains.kotlin.types.TypeApproximatorConfiguration
|
||||||
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
|
|
||||||
abstract class ResolutionStage {
|
abstract class ResolutionStage {
|
||||||
abstract suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext)
|
abstract suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext)
|
||||||
@@ -104,6 +106,7 @@ object CheckExtensionReceiver : ResolutionStage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
object CheckDispatchReceiver : ResolutionStage() {
|
object CheckDispatchReceiver : ResolutionStage() {
|
||||||
|
@OptIn(SymbolInternals::class)
|
||||||
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
override suspend fun check(candidate: Candidate, callInfo: CallInfo, sink: CheckerSink, context: ResolutionContext) {
|
||||||
val explicitReceiverExpression = callInfo.explicitReceiver
|
val explicitReceiverExpression = callInfo.explicitReceiver
|
||||||
if (explicitReceiverExpression.isSuperCall()) {
|
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 {
|
private fun FirExpression?.isSuperCall(): Boolean {
|
||||||
if (this !is FirQualifiedAccessExpression) return false
|
if (this !is FirQualifiedAccessExpression) return false
|
||||||
return calleeReference is FirSuperReference
|
return calleeReference is FirSuperReference
|
||||||
|
|||||||
+8
@@ -20,6 +20,11 @@ enum class CandidateApplicability {
|
|||||||
UNSAFE_CALL, // receiver or argument nullability doesn't match
|
UNSAFE_CALL, // receiver or argument nullability doesn't match
|
||||||
UNSTABLE_SMARTCAST, // unstable smart cast
|
UNSTABLE_SMARTCAST, // unstable smart cast
|
||||||
CONVENTION_ERROR, // missing infix, operator etc
|
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,
|
RESOLVED_LOW_PRIORITY,
|
||||||
PROPERTY_AS_OPERATOR, // using property of functional type as an operator. From resolution perspective, this is considered successful.
|
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
|
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
|
val CandidateApplicability.isSuccess: Boolean
|
||||||
get() = this >= CandidateApplicability.RESOLVED_LOW_PRIORITY
|
get() = this >= CandidateApplicability.RESOLVED_LOW_PRIORITY
|
||||||
|
|
||||||
|
val CandidateApplicability.shouldStopResolve: Boolean
|
||||||
|
get() = this >= CandidateApplicability.DSL_SCOPE_VIOLATION
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ fun main() {
|
|||||||
baz1 {
|
baz1 {
|
||||||
baz2 {
|
baz2 {
|
||||||
bar()
|
bar()
|
||||||
foo()
|
<!DSL_SCOPE_VIOLATION!>foo<!>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -29,7 +29,7 @@ fun main() {
|
|||||||
baz1 {
|
baz1 {
|
||||||
baz2 {
|
baz2 {
|
||||||
bar()
|
bar()
|
||||||
foo()
|
<!DSL_SCOPE_VIOLATION!>foo<!>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
-26
@@ -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
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
@Target(AnnotationTarget.TYPE)
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
|||||||
-28
@@ -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
|
@DslMarker
|
||||||
@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPEALIAS)
|
@Target(AnnotationTarget.CLASS, AnnotationTarget.TYPEALIAS)
|
||||||
annotation class XMarker
|
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
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
annotation class Ann
|
annotation class Ann
|
||||||
|
|||||||
-23
@@ -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
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
annotation class Ann
|
annotation class Ann
|
||||||
|
|||||||
Vendored
-22
@@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
@Target(AnnotationTarget.TYPE)
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
|||||||
+6
-6
@@ -29,12 +29,12 @@ fun test() {
|
|||||||
foo12 {
|
foo12 {
|
||||||
a()
|
a()
|
||||||
bar1 {
|
bar1 {
|
||||||
a()
|
<!DSL_SCOPE_VIOLATION!>a<!>()
|
||||||
b()
|
b()
|
||||||
}
|
}
|
||||||
|
|
||||||
bar2 {
|
bar2 {
|
||||||
a()
|
<!DSL_SCOPE_VIOLATION!>a<!>()
|
||||||
b()
|
b()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ fun test() {
|
|||||||
b()
|
b()
|
||||||
foo12 {
|
foo12 {
|
||||||
a()
|
a()
|
||||||
b()
|
<!DSL_SCOPE_VIOLATION!>b<!>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ fun test() {
|
|||||||
b()
|
b()
|
||||||
foo12 {
|
foo12 {
|
||||||
a()
|
a()
|
||||||
b()
|
<!DSL_SCOPE_VIOLATION!>b<!>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +64,7 @@ fun test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bar2 {
|
bar2 {
|
||||||
a()
|
<!DSL_SCOPE_VIOLATION!>a<!>()
|
||||||
b()
|
b()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,7 +85,7 @@ fun test() {
|
|||||||
foo2 {
|
foo2 {
|
||||||
bar1t(this) {
|
bar1t(this) {
|
||||||
a()
|
a()
|
||||||
b()
|
<!DSL_SCOPE_VIOLATION!>b<!>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-40
@@ -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
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
@Target(AnnotationTarget.TYPE)
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
|||||||
@@ -34,13 +34,13 @@ fun test() {
|
|||||||
a1++
|
a1++
|
||||||
|
|
||||||
bar {
|
bar {
|
||||||
a + 1
|
<!DSL_SCOPE_VIOLATION!>a<!> + 1
|
||||||
a += a + 1
|
<!DSL_SCOPE_VIOLATION, VARIABLE_EXPECTED!>a<!> += <!DSL_SCOPE_VIOLATION!>a<!> + 1
|
||||||
a++
|
<!DSL_SCOPE_VIOLATION, DSL_SCOPE_VIOLATION!>a<!>++
|
||||||
|
|
||||||
a1 + 1
|
<!DSL_SCOPE_VIOLATION!>a1<!> + 1
|
||||||
a1 += a1 + 1
|
<!DSL_SCOPE_VIOLATION, VARIABLE_EXPECTED!>a1<!> += <!DSL_SCOPE_VIOLATION!>a1<!> + 1
|
||||||
a1++
|
<!DSL_SCOPE_VIOLATION, DSL_SCOPE_VIOLATION!>a1<!>++
|
||||||
|
|
||||||
this@foo.a + 1
|
this@foo.a + 1
|
||||||
this@foo.a += this@foo.a + 1
|
this@foo.a += this@foo.a + 1
|
||||||
|
|||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
annotation class Ann
|
annotation class Ann
|
||||||
|
|||||||
-26
@@ -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
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
@Target(AnnotationTarget.TYPE)
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
|||||||
Vendored
-27
@@ -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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Vendored
+1
@@ -1,3 +1,4 @@
|
|||||||
|
// FIR_IDENTICAL
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
annotation class Ann
|
annotation class Ann
|
||||||
|
|||||||
+10
-10
@@ -48,8 +48,8 @@ fun test() {
|
|||||||
D().x()
|
D().x()
|
||||||
|
|
||||||
foo1 {
|
foo1 {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
y()
|
<!DSL_SCOPE_VIOLATION!>y<!>()
|
||||||
|
|
||||||
with(A()) {
|
with(A()) {
|
||||||
x()
|
x()
|
||||||
@@ -57,19 +57,19 @@ fun test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
with(D()) {
|
with(D()) {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
}
|
}
|
||||||
D().x()
|
D().<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
}
|
}
|
||||||
|
|
||||||
foo2 {
|
foo2 {
|
||||||
x()
|
x()
|
||||||
y()
|
<!DSL_SCOPE_VIOLATION!>y<!>()
|
||||||
}
|
}
|
||||||
|
|
||||||
foo3 {
|
foo3 {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
y()
|
<!DSL_SCOPE_VIOLATION!>y<!>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ fun test() {
|
|||||||
foo {
|
foo {
|
||||||
baz {
|
baz {
|
||||||
bar {
|
bar {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
y()
|
y()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,7 +90,7 @@ fun test() {
|
|||||||
foo {
|
foo {
|
||||||
baz {
|
baz {
|
||||||
bar {
|
bar {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
y()
|
y()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -101,7 +101,7 @@ fun test() {
|
|||||||
foo {
|
foo {
|
||||||
baz {
|
baz {
|
||||||
bar {
|
bar {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
y()
|
y()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-9
@@ -43,8 +43,8 @@ fun test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
foo1 {
|
foo1 {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
y()
|
<!DSL_SCOPE_VIOLATION!>y<!>()
|
||||||
|
|
||||||
with(A()) {
|
with(A()) {
|
||||||
x()
|
x()
|
||||||
@@ -52,19 +52,19 @@ fun test() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
with(D()) {
|
with(D()) {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
}
|
}
|
||||||
A().x()
|
A().x()
|
||||||
}
|
}
|
||||||
|
|
||||||
foo2 {
|
foo2 {
|
||||||
x()
|
x()
|
||||||
y()
|
<!DSL_SCOPE_VIOLATION!>y<!>()
|
||||||
}
|
}
|
||||||
|
|
||||||
foo3 {
|
foo3 {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
y()
|
<!DSL_SCOPE_VIOLATION!>y<!>()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -74,7 +74,7 @@ fun test() {
|
|||||||
foo {
|
foo {
|
||||||
baz {
|
baz {
|
||||||
bar {
|
bar {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
y()
|
y()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -85,7 +85,7 @@ fun test() {
|
|||||||
foo {
|
foo {
|
||||||
baz {
|
baz {
|
||||||
bar {
|
bar {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
y()
|
y()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ fun test() {
|
|||||||
foo {
|
foo {
|
||||||
baz {
|
baz {
|
||||||
bar {
|
bar {
|
||||||
x()
|
<!DSL_SCOPE_VIOLATION!>x<!>()
|
||||||
y()
|
y()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
-102
@@ -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
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
@Target(AnnotationTarget.TYPE)
|
@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
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
@Target(AnnotationTarget.TYPE)
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
|||||||
+28
@@ -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<!>()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+29
@@ -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
|
||||||
+2
-1
@@ -1,3 +1,4 @@
|
|||||||
|
// !LANGUAGE: -DslMarkersSupport
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
annotation class Ann
|
annotation class Ann
|
||||||
@@ -19,7 +20,7 @@ fun test() {
|
|||||||
foo {
|
foo {
|
||||||
a()
|
a()
|
||||||
bar {
|
bar {
|
||||||
a()
|
<!DSL_SCOPE_VIOLATION!>a<!>()
|
||||||
this@foo.a()
|
this@foo.a()
|
||||||
b()
|
b()
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
// FIR_IDENTICAL
|
|
||||||
// !LANGUAGE: -DslMarkersSupport
|
// !LANGUAGE: -DslMarkersSupport
|
||||||
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@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
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
annotation class Ann
|
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
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
annotation class Ann
|
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
|
// !DIAGNOSTICS: -UNUSED_PARAMETER
|
||||||
@DslMarker
|
@DslMarker
|
||||||
@Target(AnnotationTarget.TYPE)
|
@Target(AnnotationTarget.TYPE)
|
||||||
|
|||||||
Generated
+6
@@ -24544,6 +24544,12 @@ public class DiagnosticTestGenerated extends AbstractDiagnosticTest {
|
|||||||
runTest("compiler/testData/diagnostics/tests/resolve/dslMarker/twoLanguages.kt");
|
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
|
@Test
|
||||||
@TestMetadata("unsupportedFeature.kt")
|
@TestMetadata("unsupportedFeature.kt")
|
||||||
public void testUnsupportedFeature() throws Exception {
|
public void testUnsupportedFeature() throws Exception {
|
||||||
|
|||||||
Reference in New Issue
Block a user