Diagnostics: add diagnostic for reporting contract description blocks in old frontend

This commit is contained in:
Arsen Nagdalian
2020-08-16 00:08:50 +03:00
parent 80d7f6b688
commit 8b4e8a2c0c
17 changed files with 299 additions and 1 deletions
@@ -1370,6 +1370,39 @@ public class FirOldFrontendDiagnosticsTestWithStdlibGenerated extends AbstractFi
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NewSyntax extends AbstractFirOldFrontendDiagnosticsTestWithStdlib {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInNewSyntax() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("complexContractDescription.kt")
public void testComplexContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/complexContractDescription.kt");
}
@TestMetadata("onelineFunctionsContractDescription.kt")
public void testOnelineFunctionsContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/onelineFunctionsContractDescription.kt");
}
@TestMetadata("propertyAccessorsContractDescription.kt")
public void testPropertyAccessorsContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/propertyAccessorsContractDescription.kt");
}
@TestMetadata("simpleFunctionsContractDescription.kt")
public void testSimpleFunctionsContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/simpleFunctionsContractDescription.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -37,7 +37,8 @@ private val DEFAULT_DECLARATION_CHECKERS = listOf(
TrailingCommaDeclarationChecker,
MissingDependencySupertypeChecker.ForDeclarations,
FunInterfaceDeclarationChecker(),
DeprecatedSinceKotlinAnnotationChecker
DeprecatedSinceKotlinAnnotationChecker,
ContractDescriptionBlockChecker
)
private val DEFAULT_CALL_CHECKERS = listOf(
@@ -0,0 +1,25 @@
/*
* Copyright 2010-2020 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.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtNamedFunction
import org.jetbrains.kotlin.psi.KtPropertyAccessor
object ContractDescriptionBlockChecker: DeclarationChecker {
override fun check(declaration: KtDeclaration, descriptor: DeclarationDescriptor, context: DeclarationCheckerContext) {
val contractDescription = when (declaration) {
is KtNamedFunction -> declaration.contractDescription
is KtPropertyAccessor -> declaration.contractDescription
else -> null
}
if (contractDescription != null) {
context.trace.report(Errors.UNSUPPORTED.on(contractDescription, "Contract description blocks are not supported"))
}
}
}
@@ -0,0 +1,24 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
import kotlin.contracts.*
fun foo(arg: Any?, num: Int?, block: () -> Unit) contract [
returns() implies (arg is String),
returns() implies (num != null),
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
] {
require(arg is String)
require(num != null)
block()
}
fun bar(arg: Any?, block: () -> Int): Boolean contract [
returns(true) implies (arg != null),
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
] {
val num = block()
if (arg != null) {
return true
}
return false
}
@@ -0,0 +1,24 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
import kotlin.contracts.*
fun foo(arg: Any?, num: Int?, block: () -> Unit) contract <!UNSUPPORTED!>[
returns() implies (arg is String),
returns() implies (num != null),
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
]<!> {
require(arg is String)
require(num != null)
block()
}
fun bar(arg: Any?, block: () -> Int): Boolean contract <!UNSUPPORTED!>[
returns(true) implies (arg != null),
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
]<!> {
val num = block()
if (arg != null) {
return true
}
return false
}
@@ -0,0 +1,4 @@
package
public fun bar(/*0*/ arg: kotlin.Any?, /*1*/ block: () -> kotlin.Int): kotlin.Boolean
public fun foo(/*0*/ arg: kotlin.Any?, /*1*/ num: kotlin.Int?, /*2*/ block: () -> kotlin.Unit): kotlin.Unit
@@ -0,0 +1,10 @@
import kotlin.contracts.*
fun calculateNumber(block: () -> Int): Int contract [
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
] = block()
fun <R> calculateResult(num: Int?, calculate: (Int?) -> R): R contract [
callsInPlace(calculate, InvocationKind.EXACTLY_ONCE),
returns() implies (num != null)
] = calculate(num)
@@ -0,0 +1,10 @@
import kotlin.contracts.*
fun calculateNumber(block: () -> Int): Int contract <!UNSUPPORTED!>[
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
]<!> = block()
fun <R> calculateResult(num: Int?, calculate: (Int?) -> R): R contract <!UNSUPPORTED!>[
callsInPlace(calculate, InvocationKind.EXACTLY_ONCE),
returns() implies (num != null)
]<!> = calculate(num)
@@ -0,0 +1,4 @@
package
public fun calculateNumber(/*0*/ block: () -> kotlin.Int): kotlin.Int
public fun </*0*/ R> calculateResult(/*0*/ num: kotlin.Int?, /*1*/ calculate: (kotlin.Int?) -> R): R
@@ -0,0 +1,18 @@
import kotlin.contracts.*
class A {
var x: Int = 0
get() = f(x)
set(value) contract [returns() implies (value != null)] {
field = value + 1
}
var y: Double = 0.0
get() = g(y)
set(value) contract [returns() implies (value != null)] {
field = value * 2
}
fun f(arg: Int) = arg * arg
fun g(arg: Double) = arg / 2
}
@@ -0,0 +1,18 @@
import kotlin.contracts.*
class A {
var x: Int = 0
get() = f(x)
set(value) contract <!UNSUPPORTED!>[returns() implies (value != null)]<!> {
field = value + 1
}
var y: Double = 0.0
get() = g(y)
set(value) contract <!UNSUPPORTED!>[returns() implies (value != null)]<!> {
field = value * 2
}
fun f(arg: Int) = arg * arg
fun g(arg: Double) = arg / 2
}
@@ -0,0 +1,12 @@
package
public final class A {
public constructor A()
public final var x: kotlin.Int
public final var y: kotlin.Double
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public final fun f(/*0*/ arg: kotlin.Int): kotlin.Int
public final fun g(/*0*/ arg: kotlin.Double): kotlin.Double
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
}
@@ -0,0 +1,22 @@
import kotlin.contracts.*
fun printStr(str: String?) contract [
returns() implies (str != null)
] {
require(str != null)
println(str)
}
fun callExactlyOnce(block: () -> Int) contract [
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
] {
val num = block()
println(num)
}
fun calculateNumber(block: () -> Int): Int contract [
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
] {
val num = block()
return num
}
@@ -0,0 +1,22 @@
import kotlin.contracts.*
fun printStr(str: String?) contract <!UNSUPPORTED!>[
returns() implies (str != null)
]<!> {
require(str != null)
println(str)
}
fun callExactlyOnce(block: () -> Int) contract <!UNSUPPORTED!>[
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
]<!> {
val num = block()
println(num)
}
fun calculateNumber(block: () -> Int): Int contract <!UNSUPPORTED!>[
callsInPlace(block, InvocationKind.EXACTLY_ONCE)
]<!> {
val num = block()
return num
}
@@ -0,0 +1,5 @@
package
public fun calculateNumber(/*0*/ block: () -> kotlin.Int): kotlin.Int
public fun callExactlyOnce(/*0*/ block: () -> kotlin.Int): kotlin.Unit
public fun printStr(/*0*/ str: kotlin.String?): kotlin.Unit
@@ -1370,6 +1370,39 @@ public class DiagnosticsTestWithStdLibGenerated extends AbstractDiagnosticsTestW
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NewSyntax extends AbstractDiagnosticsTestWithStdLib {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInNewSyntax() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("complexContractDescription.kt")
public void testComplexContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/complexContractDescription.kt");
}
@TestMetadata("onelineFunctionsContractDescription.kt")
public void testOnelineFunctionsContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/onelineFunctionsContractDescription.kt");
}
@TestMetadata("propertyAccessorsContractDescription.kt")
public void testPropertyAccessorsContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/propertyAccessorsContractDescription.kt");
}
@TestMetadata("simpleFunctionsContractDescription.kt")
public void testSimpleFunctionsContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/simpleFunctionsContractDescription.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
@@ -1370,6 +1370,39 @@ public class DiagnosticsTestWithStdLibUsingJavacGenerated extends AbstractDiagno
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class NewSyntax extends AbstractDiagnosticsTestWithStdLibUsingJavac {
private void runTest(String testDataFilePath) throws Exception {
KotlinTestUtils.runTest(this::doTest, this, testDataFilePath);
}
public void testAllFilesPresentInNewSyntax() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadataWithExcluded(this.getClass(), new File("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax"), Pattern.compile("^(.+)\\.kt$"), Pattern.compile("^(.+)\\.fir\\.kts?$"), true);
}
@TestMetadata("complexContractDescription.kt")
public void testComplexContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/complexContractDescription.kt");
}
@TestMetadata("onelineFunctionsContractDescription.kt")
public void testOnelineFunctionsContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/onelineFunctionsContractDescription.kt");
}
@TestMetadata("propertyAccessorsContractDescription.kt")
public void testPropertyAccessorsContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/propertyAccessorsContractDescription.kt");
}
@TestMetadata("simpleFunctionsContractDescription.kt")
public void testSimpleFunctionsContractDescription() throws Exception {
runTest("compiler/testData/diagnostics/testsWithStdLib/contracts/newSyntax/simpleFunctionsContractDescription.kt");
}
}
@TestMetadata("compiler/testData/diagnostics/testsWithStdLib/contracts/smartcasts")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)