Show warnings for Java methods with external annotations when they called from Kotlin code
This commit is contained in:
+8
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.load.java.structure.impl;
|
package org.jetbrains.kotlin.load.java.structure.impl;
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.ExternalAnnotationsManager;
|
||||||
import com.intellij.psi.PsiAnnotation;
|
import com.intellij.psi.PsiAnnotation;
|
||||||
import com.intellij.psi.PsiClass;
|
import com.intellij.psi.PsiClass;
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiElement;
|
||||||
@@ -86,4 +87,11 @@ public class JavaAnnotationImpl extends JavaElementImpl<PsiAnnotation> implement
|
|||||||
PsiElement resolved = referenceElement.resolve();
|
PsiElement resolved = referenceElement.resolve();
|
||||||
return resolved instanceof PsiClass ? (PsiClass) resolved : null;
|
return resolved instanceof PsiClass ? (PsiClass) resolved : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isIdeExternalAnnotation() {
|
||||||
|
PsiAnnotation psi = getPsi();
|
||||||
|
ExternalAnnotationsManager externalAnnotationManager = ExternalAnnotationsManager.getInstance(psi.getProject());
|
||||||
|
return externalAnnotationManager.isExternalAnnotation(psi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+9
@@ -20,6 +20,7 @@ package org.jetbrains.kotlin.load.java.structure.impl
|
|||||||
|
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.search.GlobalSearchScope
|
import com.intellij.psi.search.GlobalSearchScope
|
||||||
|
import org.jetbrains.kotlin.load.java.NULLABILITY_ANNOTATIONS
|
||||||
import org.jetbrains.kotlin.load.java.structure.*
|
import org.jetbrains.kotlin.load.java.structure.*
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
|
|
||||||
@@ -67,6 +68,14 @@ internal fun classifierTypes(classTypes: Array<PsiClassType>): Collection<JavaCl
|
|||||||
internal fun annotations(annotations: Array<out PsiAnnotation>): Collection<JavaAnnotation> =
|
internal fun annotations(annotations: Array<out PsiAnnotation>): Collection<JavaAnnotation> =
|
||||||
annotations.convert(::JavaAnnotationImpl)
|
annotations.convert(::JavaAnnotationImpl)
|
||||||
|
|
||||||
|
internal fun nullabilityAnnotations(annotations: Array<out PsiAnnotation>): Collection<JavaAnnotation> =
|
||||||
|
annotations.convert(::JavaAnnotationImpl)
|
||||||
|
.filter { annotation ->
|
||||||
|
val fqName = annotation.classId?.asSingleFqName() ?: return@filter false
|
||||||
|
fqName in NULLABILITY_ANNOTATIONS
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
internal fun namedAnnotationArguments(nameValuePairs: Array<PsiNameValuePair>): Collection<JavaAnnotationArgument> =
|
internal fun namedAnnotationArguments(nameValuePairs: Array<PsiNameValuePair>): Collection<JavaAnnotationArgument> =
|
||||||
nameValuePairs.convert { psi ->
|
nameValuePairs.convert { psi ->
|
||||||
val name = psi.name?.let(Name::identifier)
|
val name = psi.name?.let(Name::identifier)
|
||||||
|
|||||||
+24
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.load.java.structure.impl;
|
package org.jetbrains.kotlin.load.java.structure.impl;
|
||||||
|
|
||||||
|
import com.intellij.codeInsight.ExternalAnnotationsManager;
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
@@ -25,10 +26,12 @@ import org.jetbrains.kotlin.load.java.JavaVisibilities;
|
|||||||
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation;
|
import org.jetbrains.kotlin.load.java.structure.JavaAnnotation;
|
||||||
import org.jetbrains.kotlin.name.FqName;
|
import org.jetbrains.kotlin.name.FqName;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.load.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.annotations;
|
import static org.jetbrains.kotlin.load.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.annotations;
|
||||||
|
import static org.jetbrains.kotlin.load.java.structure.impl.JavaElementCollectionFromPsiArrayUtil.nullabilityAnnotations;
|
||||||
|
|
||||||
/* package */ class JavaElementUtil {
|
/* package */ class JavaElementUtil {
|
||||||
private JavaElementUtil() {
|
private JavaElementUtil() {
|
||||||
@@ -70,6 +73,27 @@ import static org.jetbrains.kotlin.load.java.structure.impl.JavaElementCollectio
|
|||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private static PsiAnnotation[] getExternalAnnotations(@NotNull JavaModifierListOwnerImpl modifierListOwner) {
|
||||||
|
PsiModifierListOwner psiModifierListOwner = modifierListOwner.getPsi();
|
||||||
|
ExternalAnnotationsManager externalAnnotationManager = ExternalAnnotationsManager
|
||||||
|
.getInstance(psiModifierListOwner.getProject());
|
||||||
|
return externalAnnotationManager.findExternalAnnotations(psiModifierListOwner);
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
static <T extends JavaAnnotationOwnerImpl & JavaModifierListOwnerImpl>
|
||||||
|
Collection<JavaAnnotation> getRegularAndExternalAnnotations(@NotNull T owner) {
|
||||||
|
PsiAnnotation[] externalAnnotations = getExternalAnnotations(owner);
|
||||||
|
if (externalAnnotations == null) {
|
||||||
|
return getAnnotations(owner);
|
||||||
|
}
|
||||||
|
Collection<JavaAnnotation> annotations = new ArrayList<>(getAnnotations(owner));
|
||||||
|
annotations.addAll(nullabilityAnnotations(externalAnnotations));
|
||||||
|
return annotations;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static JavaAnnotation findAnnotation(@NotNull JavaAnnotationOwnerImpl owner, @NotNull FqName fqName) {
|
public static JavaAnnotation findAnnotation(@NotNull JavaAnnotationOwnerImpl owner, @NotNull FqName fqName) {
|
||||||
PsiAnnotationOwner annotationOwnerPsi = owner.getAnnotationOwnerPsi();
|
PsiAnnotationOwner annotationOwnerPsi = owner.getAnnotationOwnerPsi();
|
||||||
|
|||||||
+1
-1
@@ -83,7 +83,7 @@ public abstract class JavaMemberImpl<Psi extends PsiMember> extends JavaElementI
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<JavaAnnotation> getAnnotations() {
|
public Collection<JavaAnnotation> getAnnotations() {
|
||||||
return JavaElementUtil.getAnnotations(this);
|
return JavaElementUtil.getRegularAndExternalAnnotations(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
+1
-1
@@ -67,7 +67,7 @@ public class JavaValueParameterImpl extends JavaElementImpl<PsiParameter>
|
|||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Collection<JavaAnnotation> getAnnotations() {
|
public Collection<JavaAnnotation> getAnnotations() {
|
||||||
return JavaElementUtil.getAnnotations(this);
|
return JavaElementUtil.getRegularAndExternalAnnotations(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
|||||||
+4
-1
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.SourceElement
|
|||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinRetention
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
|
||||||
|
import org.jetbrains.kotlin.load.java.descriptors.PossiblyExternalAnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||||
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaAnnotationDescriptor
|
import org.jetbrains.kotlin.load.java.lazy.descriptors.LazyJavaAnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.structure.*
|
import org.jetbrains.kotlin.load.java.structure.*
|
||||||
@@ -103,7 +104,7 @@ open class JavaAnnotationDescriptor(
|
|||||||
c: LazyJavaResolverContext,
|
c: LazyJavaResolverContext,
|
||||||
annotation: JavaAnnotation?,
|
annotation: JavaAnnotation?,
|
||||||
override val fqName: FqName
|
override val fqName: FqName
|
||||||
) : AnnotationDescriptor {
|
) : AnnotationDescriptor, PossiblyExternalAnnotationDescriptor {
|
||||||
override val source: SourceElement = annotation?.let { c.components.sourceElementFactory.source(it) } ?: SourceElement.NO_SOURCE
|
override val source: SourceElement = annotation?.let { c.components.sourceElementFactory.source(it) } ?: SourceElement.NO_SOURCE
|
||||||
|
|
||||||
override val type: SimpleType by c.storageManager.createLazyValue { c.module.builtIns.getBuiltInClassByFqName(fqName).defaultType }
|
override val type: SimpleType by c.storageManager.createLazyValue { c.module.builtIns.getBuiltInClassByFqName(fqName).defaultType }
|
||||||
@@ -111,6 +112,8 @@ open class JavaAnnotationDescriptor(
|
|||||||
protected val firstArgument: JavaAnnotationArgument? = annotation?.arguments?.firstOrNull()
|
protected val firstArgument: JavaAnnotationArgument? = annotation?.arguments?.firstOrNull()
|
||||||
|
|
||||||
override val allValueArguments: Map<Name, ConstantValue<*>> get() = emptyMap()
|
override val allValueArguments: Map<Name, ConstantValue<*>> get() = emptyMap()
|
||||||
|
|
||||||
|
override val isIdeExternalAnnotation: Boolean = annotation?.isIdeExternalAnnotation == true
|
||||||
}
|
}
|
||||||
|
|
||||||
class JavaDeprecatedAnnotationDescriptor(
|
class JavaDeprecatedAnnotationDescriptor(
|
||||||
|
|||||||
+12
@@ -0,0 +1,12 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2019 JetBrains s.r.o. 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.load.java.descriptors
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
||||||
|
|
||||||
|
interface PossiblyExternalAnnotationDescriptor : AnnotationDescriptor {
|
||||||
|
val isIdeExternalAnnotation: Boolean
|
||||||
|
}
|
||||||
+4
-1
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.descriptors.findNonGenericClassAcrossDependencies
|
|||||||
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_ANNOTATION_MEMBER_NAME
|
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.DEFAULT_ANNOTATION_MEMBER_NAME
|
||||||
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
|
import org.jetbrains.kotlin.load.java.components.DescriptorResolverUtils
|
||||||
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
import org.jetbrains.kotlin.load.java.components.TypeUsage
|
||||||
|
import org.jetbrains.kotlin.load.java.descriptors.PossiblyExternalAnnotationDescriptor
|
||||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||||
import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
|
import org.jetbrains.kotlin.load.java.lazy.types.toAttributes
|
||||||
import org.jetbrains.kotlin.load.java.structure.*
|
import org.jetbrains.kotlin.load.java.structure.*
|
||||||
@@ -39,7 +40,7 @@ import org.jetbrains.kotlin.types.isError
|
|||||||
class LazyJavaAnnotationDescriptor(
|
class LazyJavaAnnotationDescriptor(
|
||||||
private val c: LazyJavaResolverContext,
|
private val c: LazyJavaResolverContext,
|
||||||
private val javaAnnotation: JavaAnnotation
|
private val javaAnnotation: JavaAnnotation
|
||||||
) : AnnotationDescriptor {
|
) : AnnotationDescriptor, PossiblyExternalAnnotationDescriptor {
|
||||||
override val fqName by c.storageManager.createNullableLazyValue {
|
override val fqName by c.storageManager.createNullableLazyValue {
|
||||||
javaAnnotation.classId?.asSingleFqName()
|
javaAnnotation.classId?.asSingleFqName()
|
||||||
}
|
}
|
||||||
@@ -112,4 +113,6 @@ class LazyJavaAnnotationDescriptor(
|
|||||||
ClassId.topLevel(fqName),
|
ClassId.topLevel(fqName),
|
||||||
c.components.deserializedDescriptorResolver.components.notFoundClasses
|
c.components.deserializedDescriptorResolver.components.notFoundClasses
|
||||||
)
|
)
|
||||||
|
|
||||||
|
override val isIdeExternalAnnotation: Boolean = javaAnnotation.isIdeExternalAnnotation
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ interface JavaTypeParameterListOwner : JavaElement {
|
|||||||
interface JavaAnnotation : JavaElement {
|
interface JavaAnnotation : JavaElement {
|
||||||
val arguments: Collection<JavaAnnotationArgument>
|
val arguments: Collection<JavaAnnotationArgument>
|
||||||
val classId: ClassId?
|
val classId: ClassId?
|
||||||
|
val isIdeExternalAnnotation: Boolean
|
||||||
|
get() = false
|
||||||
|
|
||||||
fun resolve(): JavaClass?
|
fun resolve(): JavaClass?
|
||||||
}
|
}
|
||||||
|
|||||||
+8
-4
@@ -18,10 +18,7 @@ package org.jetbrains.kotlin.load.java.typeEnhancement
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
import org.jetbrains.kotlin.builtins.jvm.JavaToKotlinClassMap
|
||||||
import org.jetbrains.kotlin.descriptors.*
|
import org.jetbrains.kotlin.descriptors.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotated
|
import org.jetbrains.kotlin.descriptors.annotations.*
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.Annotations
|
|
||||||
import org.jetbrains.kotlin.descriptors.annotations.composeAnnotations
|
|
||||||
import org.jetbrains.kotlin.load.java.*
|
import org.jetbrains.kotlin.load.java.*
|
||||||
import org.jetbrains.kotlin.load.java.descriptors.*
|
import org.jetbrains.kotlin.load.java.descriptors.*
|
||||||
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
import org.jetbrains.kotlin.load.java.lazy.LazyJavaResolverContext
|
||||||
@@ -34,6 +31,7 @@ import org.jetbrains.kotlin.resolve.constants.EnumValue
|
|||||||
import org.jetbrains.kotlin.resolve.deprecation.DEPRECATED_FUNCTION_KEY
|
import org.jetbrains.kotlin.resolve.deprecation.DEPRECATED_FUNCTION_KEY
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgument
|
import org.jetbrains.kotlin.resolve.descriptorUtil.firstArgument
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameOrNull
|
||||||
|
import org.jetbrains.kotlin.resolve.descriptorUtil.isSourceAnnotation
|
||||||
import org.jetbrains.kotlin.types.*
|
import org.jetbrains.kotlin.types.*
|
||||||
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
import org.jetbrains.kotlin.types.checker.KotlinTypeChecker
|
||||||
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
import org.jetbrains.kotlin.types.typeUtil.isTypeParameter
|
||||||
@@ -103,6 +101,12 @@ class SignatureEnhancement(
|
|||||||
isForWarningOnly = true
|
isForWarningOnly = true
|
||||||
)
|
)
|
||||||
else -> null
|
else -> null
|
||||||
|
}?.let { migrationStatus ->
|
||||||
|
if (!migrationStatus.isForWarningOnly
|
||||||
|
&& annotationDescriptor is PossiblyExternalAnnotationDescriptor
|
||||||
|
&& annotationDescriptor.isIdeExternalAnnotation)
|
||||||
|
migrationStatus.copy(isForWarningOnly = true)
|
||||||
|
else migrationStatus
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
public class ClassWithExternalAnnotatedMembers {
|
||||||
|
String nullableMethod() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
String notNullMethod() {
|
||||||
|
return "nya";
|
||||||
|
}
|
||||||
|
|
||||||
|
void methodWithNotNullParameter(Integer x) {
|
||||||
|
}
|
||||||
|
|
||||||
|
String nullableField = "nya";
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<root>
|
||||||
|
<item name='ClassWithExternalAnnotatedMembers java.lang.String notNullMethod()'>
|
||||||
|
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||||
|
</item>
|
||||||
|
<item name='ClassWithExternalAnnotatedMembers java.lang.String nullableMethod()'>
|
||||||
|
<annotation name='org.jetbrains.annotations.Nullable'/>
|
||||||
|
</item>
|
||||||
|
<item name='ClassWithExternalAnnotatedMembers nullableField'>
|
||||||
|
<annotation name='org.jetbrains.annotations.Nullable'/>
|
||||||
|
</item>
|
||||||
|
<item name='ClassWithExternalAnnotatedMembers void methodWithNotNullParameter(java.lang.Integer) 0'>
|
||||||
|
<annotation name='org.jetbrains.annotations.NotNull'/>
|
||||||
|
</item>
|
||||||
|
</root>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun test() {
|
||||||
|
val x = ClassWithExternalAnnotatedMembers()
|
||||||
|
x.notNullMethod()<warning descr="[UNNECESSARY_SAFE_CALL] Unnecessary safe call on a non-null receiver of type String!">?.</warning>toLowerCase()
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
@Suppress("UNUSED_VARIABLE")
|
||||||
|
fun test() {
|
||||||
|
val x = ClassWithExternalAnnotatedMembers()
|
||||||
|
val y: String = <warning descr="[NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS] Type mismatch: inferred type is String? but String was expected">x.nullableField</warning>
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
@Suppress("UNUSED_VARIABLE")
|
||||||
|
fun test() {
|
||||||
|
val x = ClassWithExternalAnnotatedMembers()
|
||||||
|
val y: String = <warning descr="[NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS] Type mismatch: inferred type is String? but String was expected">x.nullableMethod()</warning>
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
fun test() {
|
||||||
|
val x = ClassWithExternalAnnotatedMembers()
|
||||||
|
x.methodWithNotNullParameter(<warning descr="[NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS] Type mismatch: inferred type is Nothing? but Int was expected">null</warning>)
|
||||||
|
}
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
package org.jetbrains.kotlin.idea.externalAnnotations
|
||||||
|
|
||||||
|
import com.intellij.openapi.module.Module
|
||||||
|
import com.intellij.openapi.roots.JavaModuleExternalPaths
|
||||||
|
import com.intellij.openapi.roots.ModifiableRootModel
|
||||||
|
import com.intellij.openapi.util.io.FileUtil
|
||||||
|
import com.intellij.openapi.vfs.VfsUtilCore
|
||||||
|
import com.intellij.psi.codeStyle.JavaCodeStyleSettings
|
||||||
|
import com.intellij.testFramework.LightPlatformTestCase
|
||||||
|
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
|
||||||
|
import org.jetbrains.kotlin.idea.test.KotlinWithJdkAndRuntimeLightProjectDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
|
import org.jetbrains.kotlin.test.TargetBackend
|
||||||
|
import java.io.File
|
||||||
|
|
||||||
|
class ExternalAnnotationTest : KotlinLightCodeInsightFixtureTestCase() {
|
||||||
|
|
||||||
|
fun testNotNullMethod() {
|
||||||
|
KotlinTestUtils.runTest(::doTest, TargetBackend.ANY, "idea/testData/externalAnnotations/notNullMethod.kt")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNullableMethod() {
|
||||||
|
KotlinTestUtils.runTest(::doTest, TargetBackend.ANY, "idea/testData/externalAnnotations/nullableMethod.kt")
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fun testNullableField() {
|
||||||
|
KotlinTestUtils.runTest(::doTest, TargetBackend.ANY, "idea/testData/externalAnnotations/nullableField.kt")
|
||||||
|
}
|
||||||
|
|
||||||
|
fun testNullableMethodParameter() {
|
||||||
|
KotlinTestUtils.runTest(::doTest, TargetBackend.ANY, "idea/testData/externalAnnotations/nullableMethodParameter.kt")
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun setUp() {
|
||||||
|
super.setUp()
|
||||||
|
JavaCodeStyleSettings.getInstance(project).USE_EXTERNAL_ANNOTATIONS = true
|
||||||
|
addFile(classWithExternalAnnotatedMembers)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun tearDown() {
|
||||||
|
JavaCodeStyleSettings.getInstance(project).USE_EXTERNAL_ANNOTATIONS = false
|
||||||
|
super.tearDown()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun addFile(path: String) {
|
||||||
|
val file = File(path)
|
||||||
|
val root = LightPlatformTestCase.getSourceRoot()
|
||||||
|
runWriteAction {
|
||||||
|
val virtualFile = root.createChildData(null, file.name)
|
||||||
|
virtualFile.getOutputStream(null).writer().use { it.write(FileUtil.loadFile(file)) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun doTest(kotlinFilePath: String) {
|
||||||
|
myFixture.configureByFiles(kotlinFilePath, externalAnnotationsFile, classWithExternalAnnotatedMembers)
|
||||||
|
myFixture.checkHighlighting()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun getProjectDescriptor() = object : KotlinWithJdkAndRuntimeLightProjectDescriptor() {
|
||||||
|
override fun configureModule(module: Module, model: ModifiableRootModel) {
|
||||||
|
super.configureModule(module, model)
|
||||||
|
model.getModuleExtension(JavaModuleExternalPaths::class.java)
|
||||||
|
.setExternalAnnotationUrls(arrayOf(VfsUtilCore.pathToUrl(externalAnnotationsPath)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val externalAnnotationsPath = "idea/testData/externalAnnotations/annotations/"
|
||||||
|
private const val classWithExternalAnnotatedMembers = "idea/testData/externalAnnotations/ClassWithExternalAnnotatedMembers.java"
|
||||||
|
private const val externalAnnotationsFile = "$externalAnnotationsPath/annotations.xml"
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user