// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInspection.tests.kotlin
import com.intellij.jvm.analysis.internal.testFramework.UnstableApiUsageInspectionTestBase
import com.intellij.jvm.analysis.testFramework.JvmLanguage
class KotlinUnstableApiUsageInspectionTest : UnstableApiUsageInspectionTestBase() {
fun `test kotlin unstable api usages`() {
inspection.myIgnoreInsideImports = false
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
@file:Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE", "UNUSED_VALUE", "UNUSED_PARAMETER", "UNUSED_VARIABLE")
import experimental.pkg.AnnotatedClass
import experimental.pkg.ClassWithExperimentalTypeInSignature
import experimental.pkg.OwnerOfMembersWithExperimentalTypesInSignature
import experimental.pkg.AnnotatedClass.NON_ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
import experimental.pkg.AnnotatedClass.staticNonAnnotatedMethodInAnnotatedClass
import experimental.pkg.AnnotatedClass.ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
import experimental.pkg.AnnotatedClass.staticAnnotatedMethodInAnnotatedClass
import experimental.pkg.NonAnnotatedClass
import experimental.pkg.NonAnnotatedClass.NON_ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
import experimental.pkg.NonAnnotatedClass.staticNonAnnotatedMethodInNonAnnotatedClass
import experimental.pkg.NonAnnotatedClass.ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
import experimental.pkg.NonAnnotatedClass.staticAnnotatedMethodInNonAnnotatedClass
import experimental.pkg.AnnotatedEnum
import experimental.pkg.NonAnnotatedEnum
import experimental.pkg.AnnotatedEnum.NON_ANNOTATED_VALUE_IN_ANNOTATED_ENUM
import experimental.pkg.AnnotatedEnum.ANNOTATED_VALUE_IN_ANNOTATED_ENUM
import experimental.pkg.NonAnnotatedEnum.NON_ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
import experimental.pkg.NonAnnotatedEnum.ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
import experimental.pkg.AnnotatedAnnotation
import experimental.pkg.NonAnnotatedAnnotation
import experimental.annotatedPkg.ClassInAnnotatedPkg
class UnstableElementsTest {
fun test() {
var s = AnnotatedClass.NON_ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
AnnotatedClass.staticNonAnnotatedMethodInAnnotatedClass()
val annotatedClassInstanceViaNonAnnotatedConstructor : AnnotatedClass = AnnotatedClass()
s = annotatedClassInstanceViaNonAnnotatedConstructor.nonAnnotatedFieldInAnnotatedClass
annotatedClassInstanceViaNonAnnotatedConstructor.nonAnnotatedMethodInAnnotatedClass()
s = NON_ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
staticNonAnnotatedMethodInAnnotatedClass()
s = AnnotatedClass.ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
AnnotatedClass.staticAnnotatedMethodInAnnotatedClass()
val annotatedClassInstanceViaAnnotatedConstructor : AnnotatedClass = AnnotatedClass("")
s = annotatedClassInstanceViaAnnotatedConstructor.annotatedFieldInAnnotatedClass
annotatedClassInstanceViaAnnotatedConstructor.annotatedMethodInAnnotatedClass()
s = ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
staticAnnotatedMethodInAnnotatedClass()
// ---------------------------------
s = NonAnnotatedClass.NON_ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
NonAnnotatedClass.staticNonAnnotatedMethodInNonAnnotatedClass()
val nonAnnotatedClassInstanceViaNonAnnotatedConstructor = NonAnnotatedClass()
s = nonAnnotatedClassInstanceViaNonAnnotatedConstructor.nonAnnotatedFieldInNonAnnotatedClass
nonAnnotatedClassInstanceViaNonAnnotatedConstructor.nonAnnotatedMethodInNonAnnotatedClass()
s = NON_ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
staticNonAnnotatedMethodInNonAnnotatedClass()
s = NonAnnotatedClass.ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
NonAnnotatedClass.staticAnnotatedMethodInNonAnnotatedClass()
val nonAnnotatedClassInstanceViaAnnotatedConstructor = NonAnnotatedClass("")
s = nonAnnotatedClassInstanceViaAnnotatedConstructor.annotatedFieldInNonAnnotatedClass
nonAnnotatedClassInstanceViaAnnotatedConstructor.annotatedMethodInNonAnnotatedClass()
s = ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
staticAnnotatedMethodInNonAnnotatedClass()
// ---------------------------------
var nonAnnotatedValueInAnnotatedEnum : AnnotatedEnum = AnnotatedEnum.NON_ANNOTATED_VALUE_IN_ANNOTATED_ENUM
nonAnnotatedValueInAnnotatedEnum = NON_ANNOTATED_VALUE_IN_ANNOTATED_ENUM
var annotatedValueInAnnotatedEnum : AnnotatedEnum = AnnotatedEnum.ANNOTATED_VALUE_IN_ANNOTATED_ENUM
annotatedValueInAnnotatedEnum = ANNOTATED_VALUE_IN_ANNOTATED_ENUM
var nonAnnotatedValueInNonAnnotatedEnum = NonAnnotatedEnum.NON_ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
nonAnnotatedValueInNonAnnotatedEnum = NON_ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
var annotatedValueInNonAnnotatedEnum = NonAnnotatedEnum.ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
annotatedValueInNonAnnotatedEnum = ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
// ---------------------------------
@AnnotatedAnnotation class C1
@AnnotatedAnnotation(nonAnnotatedAttributeInAnnotatedAnnotation = "123") class C2
@AnnotatedAnnotation(annotatedAttributeInAnnotatedAnnotation = "123") class C3
@NonAnnotatedAnnotation class C4
@NonAnnotatedAnnotation(nonAnnotatedAttributeInNonAnnotatedAnnotation = "123") class C5
@NonAnnotatedAnnotation(annotatedAttributeInNonAnnotatedAnnotation = "123") class C6
}
}
open class DirectOverrideAnnotatedMethod : NonAnnotatedClass() {
override fun annotatedMethodInNonAnnotatedClass() {}
}
//No warning should be produced.
class IndirectOverrideAnnotatedMethod : DirectOverrideAnnotatedMethod() {
override fun annotatedMethodInNonAnnotatedClass() {}
}
class DirectOverrideNonAnnotatedMethodInAnnotatedClass : AnnotatedClass() {
override fun nonAnnotatedMethodInAnnotatedClass() {}
}
class DirectOverrideAnnotatedMethodInAnnotatedClass : AnnotatedClass() {
override fun annotatedMethodInAnnotatedClass() {}
}
class WarningsOfExperimentalTypesInSignature {
fun classUsage() {
experimental.pkg.ClassWithExperimentalTypeInSignature<AnnotatedClass>()
}
fun membersUsages(owner: OwnerOfMembersWithExperimentalTypesInSignature) {
val field = owner.field
owner.parameterType(null)
owner.returnType()
val fieldPkg = owner.field
owner.parameterTypePkg(null)
owner.returnTypePkg()
}
}
""".trimIndent())
}
fun `test kotlin no warnings on access to members of the same file`() {
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
@file:Suppress("UNUSED_PARAMETER")
package test;
import experimental.pkg.AnnotatedClass;
class NoWarningsMembersOfTheSameFile {
companion object {
private var staticField: AnnotatedClass? = null;
private fun staticReturnType(): AnnotatedClass? { return null; }
private fun staticParamType(param: AnnotatedClass?) { }
}
private var field: AnnotatedClass? = null;
private fun returnType(): AnnotatedClass? { return null; }
private fun paramType(param: AnnotatedClass?) { }
fun testNoWarningsProducedForMembersOfTheSameClass() {
field?.toString();
staticField?.toString();
returnType();
paramType(null);
staticReturnType();
staticParamType(null)
}
private inner class InnerClass {
fun testNoWarningsProducedForMembersEnclosingClass() {
field.toString();
staticField.toString();
returnType();
paramType(null);
staticReturnType();
staticParamType(null)
}
}
}
""".trimIndent())
}
fun `test kotlin do not report unstable api usages inside import statements`() {
inspection.myIgnoreInsideImports = true
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
import experimental.pkg.AnnotatedClass
import experimental.pkg.AnnotatedClass.NON_ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
import experimental.pkg.AnnotatedClass.staticNonAnnotatedMethodInAnnotatedClass
import experimental.pkg.AnnotatedClass.ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
import experimental.pkg.AnnotatedClass.staticAnnotatedMethodInAnnotatedClass
import experimental.pkg.NonAnnotatedClass
import experimental.pkg.NonAnnotatedClass.NON_ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
import experimental.pkg.NonAnnotatedClass.staticNonAnnotatedMethodInNonAnnotatedClass
import experimental.pkg.NonAnnotatedClass.ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
import experimental.pkg.NonAnnotatedClass.staticAnnotatedMethodInNonAnnotatedClass
import experimental.pkg.AnnotatedEnum
import experimental.pkg.NonAnnotatedEnum
import experimental.pkg.AnnotatedEnum.NON_ANNOTATED_VALUE_IN_ANNOTATED_ENUM
import experimental.pkg.AnnotatedEnum.ANNOTATED_VALUE_IN_ANNOTATED_ENUM
import experimental.pkg.NonAnnotatedEnum.NON_ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
import experimental.pkg.NonAnnotatedEnum.ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
import experimental.pkg.AnnotatedAnnotation
import experimental.pkg.NonAnnotatedAnnotation
import experimental.annotatedPkg.ClassInAnnotatedPkg
""".trimIndent())
}
fun `test Kotlin scheduled for removal`() {
inspection.myIgnoreInsideImports = false
myFixture.testHighlighting(JvmLanguage.KOTLIN, """
@file:Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE", "UNUSED_VALUE", "UNUSED_PARAMETER", "UNUSED_VARIABLE")
import scheduledForRemoval.pkg.AnnotatedClass
import scheduledForRemoval.pkg.ClassWithScheduledForRemovalTypeInSignature
import scheduledForRemoval.pkg.OwnerOfMembersWithScheduledForRemovalTypesInSignature
import scheduledForRemoval.pkg.AnnotatedClass.NON_ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
import scheduledForRemoval.pkg.AnnotatedClass.staticNonAnnotatedMethodInAnnotatedClass
import scheduledForRemoval.pkg.AnnotatedClass.ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
import scheduledForRemoval.pkg.AnnotatedClass.staticAnnotatedMethodInAnnotatedClass
import scheduledForRemoval.pkg.NonAnnotatedClass
import scheduledForRemoval.pkg.NonAnnotatedClass.NON_ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
import scheduledForRemoval.pkg.NonAnnotatedClass.staticNonAnnotatedMethodInNonAnnotatedClass
import scheduledForRemoval.pkg.NonAnnotatedClass.ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
import scheduledForRemoval.pkg.NonAnnotatedClass.staticAnnotatedMethodInNonAnnotatedClass
import scheduledForRemoval.pkg.AnnotatedEnum
import scheduledForRemoval.pkg.NonAnnotatedEnum
import scheduledForRemoval.pkg.AnnotatedEnum.NON_ANNOTATED_VALUE_IN_ANNOTATED_ENUM
import scheduledForRemoval.pkg.AnnotatedEnum.ANNOTATED_VALUE_IN_ANNOTATED_ENUM
import scheduledForRemoval.pkg.NonAnnotatedEnum.NON_ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
import scheduledForRemoval.pkg.NonAnnotatedEnum.ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
import scheduledForRemoval.pkg.AnnotatedAnnotation
import scheduledForRemoval.pkg.NonAnnotatedAnnotation
import scheduledForRemoval.annotatedPkg.ClassInAnnotatedPkg
@Suppress("ASSIGNED_BUT_NEVER_ACCESSED_VARIABLE", "UNUSED_VALUE")
class ScheduledForRemovalElementsTest {
fun test() {
var s = AnnotatedClass.NON_ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
AnnotatedClass.staticNonAnnotatedMethodInAnnotatedClass()
val annotatedClassInstanceViaNonAnnotatedConstructor : AnnotatedClass = AnnotatedClass()
s = annotatedClassInstanceViaNonAnnotatedConstructor.nonAnnotatedFieldInAnnotatedClass
annotatedClassInstanceViaNonAnnotatedConstructor.nonAnnotatedMethodInAnnotatedClass()
s = NON_ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
staticNonAnnotatedMethodInAnnotatedClass()
s = AnnotatedClass.ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
AnnotatedClass.staticAnnotatedMethodInAnnotatedClass()
val annotatedClassInstanceViaAnnotatedConstructor : AnnotatedClass = AnnotatedClass("")
s = annotatedClassInstanceViaAnnotatedConstructor.annotatedFieldInAnnotatedClass
annotatedClassInstanceViaAnnotatedConstructor.annotatedMethodInAnnotatedClass()
s = ANNOTATED_CONSTANT_IN_ANNOTATED_CLASS
staticAnnotatedMethodInAnnotatedClass()
// ---------------------------------
s = NonAnnotatedClass.NON_ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
NonAnnotatedClass.staticNonAnnotatedMethodInNonAnnotatedClass()
val nonAnnotatedClassInstanceViaNonAnnotatedConstructor = NonAnnotatedClass()
s = nonAnnotatedClassInstanceViaNonAnnotatedConstructor.nonAnnotatedFieldInNonAnnotatedClass
nonAnnotatedClassInstanceViaNonAnnotatedConstructor.nonAnnotatedMethodInNonAnnotatedClass()
s = NON_ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
staticNonAnnotatedMethodInNonAnnotatedClass()
s = NonAnnotatedClass.ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
NonAnnotatedClass.staticAnnotatedMethodInNonAnnotatedClass()
val nonAnnotatedClassInstanceViaAnnotatedConstructor = NonAnnotatedClass("")
s = nonAnnotatedClassInstanceViaAnnotatedConstructor.annotatedFieldInNonAnnotatedClass
nonAnnotatedClassInstanceViaAnnotatedConstructor.annotatedMethodInNonAnnotatedClass()
s = ANNOTATED_CONSTANT_IN_NON_ANNOTATED_CLASS
staticAnnotatedMethodInNonAnnotatedClass()
// ---------------------------------
var nonAnnotatedValueInAnnotatedEnum : AnnotatedEnum = AnnotatedEnum.NON_ANNOTATED_VALUE_IN_ANNOTATED_ENUM
nonAnnotatedValueInAnnotatedEnum = NON_ANNOTATED_VALUE_IN_ANNOTATED_ENUM
var annotatedValueInAnnotatedEnum : AnnotatedEnum = AnnotatedEnum.ANNOTATED_VALUE_IN_ANNOTATED_ENUM
annotatedValueInAnnotatedEnum = ANNOTATED_VALUE_IN_ANNOTATED_ENUM
var nonAnnotatedValueInNonAnnotatedEnum = NonAnnotatedEnum.NON_ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
nonAnnotatedValueInNonAnnotatedEnum = NON_ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
var annotatedValueInNonAnnotatedEnum = NonAnnotatedEnum.ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
annotatedValueInNonAnnotatedEnum = ANNOTATED_VALUE_IN_NON_ANNOTATED_ENUM
// ---------------------------------
@AnnotatedAnnotation class C1
@AnnotatedAnnotation(nonAnnotatedAttributeInAnnotatedAnnotation = "123") class C2
@AnnotatedAnnotation(annotatedAttributeInAnnotatedAnnotation = "123") class C3
@NonAnnotatedAnnotation class C4
@NonAnnotatedAnnotation(nonAnnotatedAttributeInNonAnnotatedAnnotation = "123") class C5
@NonAnnotatedAnnotation(annotatedAttributeInNonAnnotatedAnnotation = "123") class C6
}
}
open class DirectOverrideAnnotatedMethod : NonAnnotatedClass() {
override fun annotatedMethodInNonAnnotatedClass() {}
}
//No warning should be produced.
class IndirectOverrideAnnotatedMethod : DirectOverrideAnnotatedMethod() {
override fun annotatedMethodInNonAnnotatedClass() {}
}
class WarningsOfScheduledForRemovalTypesInSignature {
fun classUsage() {
ClassWithScheduledForRemovalTypeInSignature<AnnotatedClass>()
}
fun membersUsages(owner: OwnerOfMembersWithScheduledForRemovalTypesInSignature) {
val field = owner.field
owner.parameterType(null)
owner.returnType()
val fieldPkg = owner.field
owner.parameterTypePkg(null)
owner.returnTypePkg()
}
}
""".trimIndent())
}
}