diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassifierImpl.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassifierImpl.java index 2d43b64ab63..5a93091e9ec 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassifierImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaClassifierImpl.java @@ -59,4 +59,9 @@ public abstract class JavaClassifierImpl extends JavaEleme public JavaAnnotation findAnnotation(@NotNull FqName fqName) { return JavaElementUtil.findAnnotation(this, fqName); } + + @Override + public boolean isDeprecatedInJavaDoc() { + return getPsi().isDeprecated(); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaMemberImpl.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaMemberImpl.java index f730d42fc57..2d057e4797e 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaMemberImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaMemberImpl.java @@ -18,6 +18,7 @@ package org.jetbrains.kotlin.load.java.structure.impl; import com.intellij.psi.PsiAnnotationOwner; import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiDocCommentOwner; import com.intellij.psi.PsiMember; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -90,4 +91,10 @@ public abstract class JavaMemberImpl extends JavaElementI public JavaAnnotation findAnnotation(@NotNull FqName fqName) { return JavaElementUtil.findAnnotation(this, fqName); } + + @Override + public boolean isDeprecatedInJavaDoc() { + PsiMember psi = getPsi(); + return psi instanceof PsiDocCommentOwner && ((PsiDocCommentOwner) psi).isDeprecated(); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaTypeImpl.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaTypeImpl.java index e2874bafc5a..153dae89544 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaTypeImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaTypeImpl.java @@ -97,6 +97,10 @@ public abstract class JavaTypeImpl implements JavaType, Jav return JavaElementUtil.findAnnotation(this, fqName); } + @Override + public boolean isDeprecatedInJavaDoc() { + return false; + } @Override public int hashCode() { diff --git a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaValueParameterImpl.java b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaValueParameterImpl.java index d8a03f5ad37..f064a9840ed 100644 --- a/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaValueParameterImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/kotlin/load/java/structure/impl/JavaValueParameterImpl.java @@ -76,6 +76,11 @@ public class JavaValueParameterImpl extends JavaElementImpl return JavaElementUtil.findAnnotation(this, fqName); } + @Override + public boolean isDeprecatedInJavaDoc() { + return false; + } + @Override @Nullable public Name getName() { diff --git a/compiler/testData/diagnostics/tests/deprecated/javaDocDeprecated.kt b/compiler/testData/diagnostics/tests/deprecated/javaDocDeprecated.kt new file mode 100644 index 00000000000..4397cee13f4 --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/javaDocDeprecated.kt @@ -0,0 +1,20 @@ +// !DIAGNOSTICS: -NO_VALUE_FOR_PARAMETER +// FILE: A.java + +/** + * @deprecated + */ +public class A { + /** + * @deprecated + */ + public String getFoo(String text) { + return text; + } +} + +// FILE: B.kt + +class B(private val foo: String) : A() { + override fun getFoo(text: String): String = super.getFoo(text + foo) +} diff --git a/compiler/testData/diagnostics/tests/deprecated/javaDocDeprecated.txt b/compiler/testData/diagnostics/tests/deprecated/javaDocDeprecated.txt new file mode 100644 index 00000000000..bbc598ed1df --- /dev/null +++ b/compiler/testData/diagnostics/tests/deprecated/javaDocDeprecated.txt @@ -0,0 +1,18 @@ +package + +kotlin.deprecated(value = "Deprecated in Java") public open class A { + public constructor A() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + kotlin.deprecated(value = "Deprecated in Java") public open fun getFoo(/*0*/ text: kotlin.String!): kotlin.String! + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +internal final class B : A { + public constructor B(/*0*/ foo: kotlin.String) + private final val foo: kotlin.String + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ fun getFoo(/*0*/ text: kotlin.String): kotlin.String + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/loadJava/compiledJava/annotations/JavaDocDeprecated.java b/compiler/testData/loadJava/compiledJava/annotations/JavaDocDeprecated.java new file mode 100644 index 00000000000..b7cd0889ef2 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/annotations/JavaDocDeprecated.java @@ -0,0 +1,16 @@ +// SKIP_IN_RUNTIME_TEST + +package test; + +/** + * @deprecated + */ +public class JavaDocDeprecated { + /** + * @deprecated + */ + public String getFoo(String text) { + return text; + } +} + diff --git a/compiler/testData/loadJava/compiledJava/annotations/JavaDocDeprecated.txt b/compiler/testData/loadJava/compiledJava/annotations/JavaDocDeprecated.txt new file mode 100644 index 00000000000..bb3c016390e --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/annotations/JavaDocDeprecated.txt @@ -0,0 +1,6 @@ +package test + +kotlin.deprecated(value = "Deprecated in Java") public open class JavaDocDeprecated { + public constructor JavaDocDeprecated() + kotlin.deprecated(value = "Deprecated in Java") public open fun getFoo(/*0*/ p0: kotlin.String!): kotlin.String! +} diff --git a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java index 73539995bae..ca63fe5a4f2 100644 --- a/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/checkers/JetDiagnosticsTestGenerated.java @@ -4524,6 +4524,12 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest { doTest(fileName); } + @TestMetadata("javaDocDeprecated.kt") + public void testJavaDocDeprecated() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/javaDocDeprecated.kt"); + doTest(fileName); + } + @TestMetadata("nestedTypesUsage.kt") public void testNestedTypesUsage() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/deprecated/nestedTypesUsage.kt"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java index 5f3d8ca1bee..ce3efb3fe99 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/compiler/LoadJavaTestGenerated.java @@ -417,6 +417,12 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestCompiledJava(fileName); } + @TestMetadata("JavaDocDeprecated.java") + public void testJavaDocDeprecated() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/annotations/JavaDocDeprecated.java"); + doTestCompiledJava(fileName); + } + @TestMetadata("NestedEnumArgument.java") public void testNestedEnumArgument() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/annotations/NestedEnumArgument.java"); diff --git a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java index 367ba6ae77f..a014c2941cd 100644 --- a/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/jvm/runtime/JvmRuntimeDescriptorLoaderTestGenerated.java @@ -3468,6 +3468,12 @@ public class JvmRuntimeDescriptorLoaderTestGenerated extends AbstractJvmRuntimeD doTest(fileName); } + @TestMetadata("JavaDocDeprecated.java") + public void testJavaDocDeprecated() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/annotations/JavaDocDeprecated.java"); + doTest(fileName); + } + @TestMetadata("NestedEnumArgument.java") public void testNestedEnumArgument() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/loadJava/compiledJava/annotations/NestedEnumArgument.java"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt index b5ff29246ac..4b081c735a0 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/components/JavaAnnotationMapper.kt @@ -48,8 +48,7 @@ public object JavaAnnotationMapper { public fun mapOrResolveJavaAnnotation(annotation: JavaAnnotation, c: LazyJavaResolverContext): AnnotationDescriptor? = when (annotation.classId) { ClassId.topLevel(javaTargetFqName) -> JavaTargetAnnotationDescriptor(annotation, c) - ClassId.topLevel(javaDeprecatedFqName) -> JavaDeprecatedAnnotationDescriptor(annotation, c) - ClassId.topLevel(javaRetentionFqName) -> null + ClassId.topLevel(javaRetentionFqName), ClassId.topLevel(javaDeprecatedFqName) -> null else -> c.resolveAnnotation(annotation) } @@ -70,6 +69,12 @@ public object JavaAnnotationMapper { null } } + if (kotlinName == KotlinBuiltIns.FQ_NAMES.deprecated) { + val javaAnnotation = annotationOwner.findAnnotation(javaDeprecatedFqName) + if (javaAnnotation != null || annotationOwner.isDeprecatedInJavaDoc) { + return JavaDeprecatedAnnotationDescriptor(javaAnnotation, c) + } + } return kotlinToJavaNameMap[kotlinName]?.let { annotationOwner.findAnnotation(it)?.let { mapOrResolveJavaAnnotation(it, c) @@ -79,8 +84,7 @@ public object JavaAnnotationMapper { // kotlin.annotation.annotation is treated separately private val kotlinToJavaNameMap: Map = - mapOf(KotlinBuiltIns.FQ_NAMES.target to javaTargetFqName, - KotlinBuiltIns.FQ_NAMES.deprecated to javaDeprecatedFqName) + mapOf(KotlinBuiltIns.FQ_NAMES.target to javaTargetFqName) public val javaToKotlinNameMap: Map = mapOf(javaTargetFqName to KotlinBuiltIns.FQ_NAMES.target, @@ -108,7 +112,7 @@ abstract class AbstractJavaAnnotationDescriptor( } class JavaDeprecatedAnnotationDescriptor( - annotation: JavaAnnotation, + annotation: JavaAnnotation?, c: LazyJavaResolverContext ): AbstractJavaAnnotationDescriptor(c, annotation, c.module.builtIns.deprecatedAnnotation) { diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt index bb913b1e115..97bc62f155e 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/lazy/LazyJavaAnnotations.kt @@ -19,11 +19,9 @@ package org.jetbrains.kotlin.load.java.lazy import org.jetbrains.kotlin.builtins.KotlinBuiltIns import org.jetbrains.kotlin.descriptors.annotations.Annotations import org.jetbrains.kotlin.load.java.components.JavaAnnotationMapper -import org.jetbrains.kotlin.load.java.lazy.descriptors.resolveAnnotation import org.jetbrains.kotlin.load.java.structure.JavaAnnotation import org.jetbrains.kotlin.load.java.structure.JavaAnnotationOwner import org.jetbrains.kotlin.name.FqName -import org.jetbrains.kotlin.resolve.DescriptorUtils class LazyJavaAnnotations( private val c: LazyJavaResolverContext, @@ -42,7 +40,8 @@ class LazyJavaAnnotations( override fun iterator() = (annotationOwner.annotations.asSequence().map(annotationDescriptors) - + JavaAnnotationMapper.findMappedJavaAnnotation(KotlinBuiltIns.FQ_NAMES.annotation, annotationOwner, c)).filterNotNull().iterator() + + JavaAnnotationMapper.findMappedJavaAnnotation(KotlinBuiltIns.FQ_NAMES.annotation, annotationOwner, c) + + JavaAnnotationMapper.findMappedJavaAnnotation(KotlinBuiltIns.FQ_NAMES.deprecated, annotationOwner, c)).filterNotNull().iterator() override fun isEmpty() = !iterator().hasNext() } diff --git a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaAnnotationOwner.java b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaAnnotationOwner.java index 3c0e420d2ff..1aced051933 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaAnnotationOwner.java +++ b/core/descriptor.loader.java/src/org/jetbrains/kotlin/load/java/structure/JavaAnnotationOwner.java @@ -28,4 +28,6 @@ public interface JavaAnnotationOwner extends JavaElement { @Nullable JavaAnnotation findAnnotation(@NotNull FqName fqName); + + boolean isDeprecatedInJavaDoc(); } diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaAnnotationOwner.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaAnnotationOwner.kt index 8fe2d034f30..02624dba5a8 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaAnnotationOwner.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaAnnotationOwner.kt @@ -26,6 +26,8 @@ public interface ReflectJavaAnnotationOwner : JavaAnnotationOwner { override fun getAnnotations() = getAnnotations(element.getDeclaredAnnotations()) override fun findAnnotation(fqName: FqName) = findAnnotation(element.getDeclaredAnnotations(), fqName) + + override fun isDeprecatedInJavaDoc() = false } fun getAnnotations(annotations: Array): List { diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClassifierType.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClassifierType.kt index f7e863fe164..2476e43c6e9 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClassifierType.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaClassifierType.kt @@ -54,4 +54,6 @@ public class ReflectJavaClassifierType(public override val type: Type) : Reflect override fun findAnnotation(fqName: FqName): JavaAnnotation? { return null // TODO } + + override fun isDeprecatedInJavaDoc() = false } diff --git a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaValueParameter.kt b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaValueParameter.kt index d5d9f2f555a..33d079608c9 100644 --- a/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaValueParameter.kt +++ b/core/descriptors.runtime/src/org/jetbrains/kotlin/load/java/structure/reflect/ReflectJavaValueParameter.kt @@ -28,6 +28,8 @@ public class ReflectJavaValueParameter( override fun findAnnotation(fqName: FqName) = findAnnotation(annotations, fqName) + override fun isDeprecatedInJavaDoc() = false + override fun getName() = null // TODO: use ParameterNames on JDK 8 override fun getType() = returnType override fun isVararg() = isVararg