Report @JvmOverloads errors on annotation, not on entire declaration (KT-12701)

This commit is contained in:
Dmitry Jemerov
2016-11-17 12:02:47 +01:00
parent d3ccbe8172
commit 12e4cf9a4f
7 changed files with 24 additions and 28 deletions
@@ -25,7 +25,7 @@ import org.jetbrains.kotlin.psi.KtClassOrObject
import org.jetbrains.kotlin.psi.KtElement import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue import org.jetbrains.kotlin.resolve.descriptorUtil.hasDefaultValue
import org.jetbrains.kotlin.resolve.jvm.AsmTypes import org.jetbrains.kotlin.resolve.jvm.AsmTypes
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmOverloadsAnnotation import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin import org.jetbrains.kotlin.resolve.jvm.diagnostics.OtherOrigin
import org.jetbrains.org.objectweb.asm.Label import org.jetbrains.org.objectweb.asm.Label
import org.jetbrains.org.objectweb.asm.Opcodes import org.jetbrains.org.objectweb.asm.Opcodes
@@ -83,9 +83,7 @@ class DefaultParameterValueSubstitutor(val state: GenerationState) {
classBuilder: ClassBuilder, classBuilder: ClassBuilder,
memberCodegen: MemberCodegen<*> memberCodegen: MemberCodegen<*>
): Boolean { ): Boolean {
if (!functionDescriptor.hasJvmOverloadsAnnotation()) { functionDescriptor.findJvmOverloadsAnnotation() ?: return false
return false
}
val count = functionDescriptor.countDefaultParameters() val count = functionDescriptor.countDefaultParameters()
@@ -16,16 +16,11 @@
package org.jetbrains.kotlin.resolve.jvm.annotations package org.jetbrains.kotlin.resolve.jvm.annotations
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor
import org.jetbrains.kotlin.descriptors.annotations.AnnotationUseSiteTarget
import org.jetbrains.kotlin.name.FqName import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
fun DeclarationDescriptor.hasJvmOverloadsAnnotation(): Boolean { fun DeclarationDescriptor.findJvmOverloadsAnnotation() = annotations.findAnnotation(FqName("kotlin.jvm.JvmOverloads"))
return annotations.findAnnotation(FqName("kotlin.jvm.JvmOverloads")) != null
}
fun DeclarationDescriptor.findJvmFieldAnnotation() = DescriptorUtils.getAnnotationByFqName(annotations, FqName("kotlin.jvm.JvmField")) fun DeclarationDescriptor.findJvmFieldAnnotation() = DescriptorUtils.getAnnotationByFqName(annotations, FqName("kotlin.jvm.JvmField"))
@@ -25,13 +25,13 @@ import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation import org.jetbrains.kotlin.resolve.annotations.hasJvmStaticAnnotation
import org.jetbrains.kotlin.resolve.checkers.SimpleDeclarationChecker
import org.jetbrains.kotlin.resolve.inline.InlineUtil import org.jetbrains.kotlin.resolve.inline.InlineUtil
import org.jetbrains.kotlin.resolve.jvm.annotations.findJvmOverloadsAnnotation
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmFieldAnnotation
import org.jetbrains.kotlin.resolve.jvm.annotations.hasJvmOverloadsAnnotation
import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm import org.jetbrains.kotlin.resolve.jvm.diagnostics.ErrorsJvm
class LocalFunInlineChecker : SimpleDeclarationChecker { class LocalFunInlineChecker : SimpleDeclarationChecker {
@@ -183,24 +183,27 @@ class OverloadsAnnotationChecker: SimpleDeclarationChecker {
diagnosticHolder: DiagnosticSink, diagnosticHolder: DiagnosticSink,
bindingContext: BindingContext bindingContext: BindingContext
) { ) {
if (descriptor.hasJvmOverloadsAnnotation()) { descriptor.findJvmOverloadsAnnotation()?.let { annotation ->
checkDeclaration(declaration, descriptor, diagnosticHolder) val annotationEntry = DescriptorToSourceUtils.getSourceFromAnnotation(annotation)
if (annotationEntry != null) {
checkDeclaration(annotationEntry, descriptor, diagnosticHolder)
}
} }
} }
private fun checkDeclaration(declaration: KtDeclaration, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) { private fun checkDeclaration(annotationEntry: KtAnnotationEntry, descriptor: DeclarationDescriptor, diagnosticHolder: DiagnosticSink) {
if (descriptor !is CallableDescriptor) { if (descriptor !is CallableDescriptor) {
return return
} }
if (descriptor is FunctionDescriptor && descriptor.modality == Modality.ABSTRACT) { if (descriptor is FunctionDescriptor && descriptor.modality == Modality.ABSTRACT) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_ABSTRACT.on(declaration)) diagnosticHolder.report(ErrorsJvm.OVERLOADS_ABSTRACT.on(annotationEntry))
} }
else if ((!descriptor.visibility.isPublicAPI && descriptor.visibility != Visibilities.INTERNAL) || else if ((!descriptor.visibility.isPublicAPI && descriptor.visibility != Visibilities.INTERNAL) ||
DescriptorUtils.isLocal(descriptor)) { DescriptorUtils.isLocal(descriptor)) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_PRIVATE.on(declaration)) diagnosticHolder.report(ErrorsJvm.OVERLOADS_PRIVATE.on(annotationEntry))
} }
else if (descriptor.valueParameters.none { it.declaresDefaultValue() }) { else if (descriptor.valueParameters.none { it.declaresDefaultValue() }) {
diagnosticHolder.report(ErrorsJvm.OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS.on(declaration)) diagnosticHolder.report(ErrorsJvm.OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS.on(annotationEntry))
} }
} }
} }
@@ -57,9 +57,9 @@ public interface ErrorsJvm {
DiagnosticFactory0<KtAnnotationEntry> VOLATILE_ON_DELEGATE = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<KtAnnotationEntry> VOLATILE_ON_DELEGATE = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtAnnotationEntry> SYNCHRONIZED_ON_ABSTRACT = DiagnosticFactory0.create(ERROR); DiagnosticFactory0<KtAnnotationEntry> SYNCHRONIZED_ON_ABSTRACT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtDeclaration> OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE); DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtDeclaration> OVERLOADS_ABSTRACT = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_ABSTRACT = DiagnosticFactory0.create(ERROR);
DiagnosticFactory0<KtDeclaration> OVERLOADS_PRIVATE = DiagnosticFactory0.create(WARNING, DECLARATION_SIGNATURE); DiagnosticFactory0<KtAnnotationEntry> OVERLOADS_PRIVATE = DiagnosticFactory0.create(WARNING);
DiagnosticFactory0<KtDeclaration> EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT = DiagnosticFactory0.create(ERROR, ABSTRACT_MODIFIER); DiagnosticFactory0<KtDeclaration> EXTERNAL_DECLARATION_CANNOT_BE_ABSTRACT = DiagnosticFactory0.create(ERROR, ABSTRACT_MODIFIER);
DiagnosticFactory0<KtDeclaration> EXTERNAL_DECLARATION_CANNOT_HAVE_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE); DiagnosticFactory0<KtDeclaration> EXTERNAL_DECLARATION_CANNOT_HAVE_BODY = DiagnosticFactory0.create(ERROR, DECLARATION_SIGNATURE);
@@ -1,7 +1,7 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
class C { class C {
@kotlin.jvm.JvmOverloads <!OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS!>constructor()<!> { <!OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS!>@kotlin.jvm.JvmOverloads<!> constructor() {
} }
<!OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS!>@kotlin.jvm.JvmOverloads fun foo(s: String)<!> {} <!OVERLOADS_WITHOUT_DEFAULT_ARGUMENTS!>@kotlin.jvm.JvmOverloads<!>1 fun foo(s: String) {}
} }
@@ -1,8 +1,8 @@
interface T { interface T {
<!OVERLOADS_ABSTRACT!>@kotlin.jvm.JvmOverloads fun foo(s: String = "OK")<!> <!OVERLOADS_ABSTRACT!>@kotlin.jvm.JvmOverloads<!> fun foo(s: String = "OK")
} }
abstract class C { abstract class C {
<!OVERLOADS_ABSTRACT!>@kotlin.jvm.JvmOverloads abstract fun foo(s: String = "OK")<!> <!OVERLOADS_ABSTRACT!>@kotlin.jvm.JvmOverloads<!> abstract fun foo(s: String = "OK")
} }
@@ -1,6 +1,6 @@
// !DIAGNOSTICS: -UNUSED_PARAMETER // !DIAGNOSTICS: -UNUSED_PARAMETER
class C { class C {
<!OVERLOADS_PRIVATE!>@kotlin.jvm.JvmOverloads private fun foo(s: String = "OK")<!> { <!OVERLOADS_PRIVATE!>@kotlin.jvm.JvmOverloads<!> private fun foo(s: String = "OK") {
} }
@kotlin.jvm.JvmOverloads fun bar(s: String = "OK") { @kotlin.jvm.JvmOverloads fun bar(s: String = "OK") {
@@ -9,12 +9,12 @@ class C {
fun foo() { fun foo() {
class D { class D {
<!OVERLOADS_PRIVATE!>@kotlin.jvm.JvmOverloads fun foo(s: String = "OK")<!> { <!OVERLOADS_PRIVATE!>@kotlin.jvm.JvmOverloads<!> fun foo(s: String = "OK") {
} }
} }
val <!UNUSED_VARIABLE!>x<!> = object { val <!UNUSED_VARIABLE!>x<!> = object {
<!OVERLOADS_PRIVATE!>@kotlin.jvm.JvmOverloads fun foo(s: String = "OK")<!> { <!OVERLOADS_PRIVATE!>@kotlin.jvm.JvmOverloads<!> fun foo(s: String = "OK") {
} }
} }
} }