// 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()) } }