Do not report "header with no impl" on incorrect header
Descriptor for a 'header' member in a non-'header' class now has isHeader = false #KT-18442 Fixed
This commit is contained in:
@@ -836,7 +836,7 @@ public class DescriptorResolver {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
private PropertyDescriptor resolveAsPropertyDescriptor(
|
private PropertyDescriptor resolveAsPropertyDescriptor(
|
||||||
@NotNull DeclarationDescriptor containingDeclaration,
|
@NotNull DeclarationDescriptor container,
|
||||||
@NotNull LexicalScope scopeForDeclarationResolution,
|
@NotNull LexicalScope scopeForDeclarationResolution,
|
||||||
@NotNull LexicalScope scopeForInitializerResolution,
|
@NotNull LexicalScope scopeForInitializerResolution,
|
||||||
@NotNull KtVariableDeclaration variableDeclaration,
|
@NotNull KtVariableDeclaration variableDeclaration,
|
||||||
@@ -847,11 +847,11 @@ public class DescriptorResolver {
|
|||||||
KtModifierList modifierList = variableDeclaration.getModifierList();
|
KtModifierList modifierList = variableDeclaration.getModifierList();
|
||||||
boolean isVar = variableDeclaration.isVar();
|
boolean isVar = variableDeclaration.isVar();
|
||||||
|
|
||||||
Visibility visibility = resolveVisibilityFromModifiers(variableDeclaration, getDefaultVisibility(variableDeclaration, containingDeclaration));
|
Visibility visibility = resolveVisibilityFromModifiers(variableDeclaration, getDefaultVisibility(variableDeclaration, container));
|
||||||
Modality modality = containingDeclaration instanceof ClassDescriptor
|
Modality modality = container instanceof ClassDescriptor
|
||||||
? resolveMemberModalityFromModifiers(variableDeclaration,
|
? resolveMemberModalityFromModifiers(variableDeclaration,
|
||||||
getDefaultModality(containingDeclaration, visibility, propertyInfo.getHasBody()),
|
getDefaultModality(container, visibility, propertyInfo.getHasBody()),
|
||||||
trace.getBindingContext(), containingDeclaration)
|
trace.getBindingContext(), container)
|
||||||
: Modality.FINAL;
|
: Modality.FINAL;
|
||||||
|
|
||||||
AnnotationSplitter.PropertyWrapper wrapper = new AnnotationSplitter.PropertyWrapper(variableDeclaration);
|
AnnotationSplitter.PropertyWrapper wrapper = new AnnotationSplitter.PropertyWrapper(variableDeclaration);
|
||||||
@@ -866,7 +866,7 @@ public class DescriptorResolver {
|
|||||||
annotationSplitter.getOtherAnnotations()));
|
annotationSplitter.getOtherAnnotations()));
|
||||||
|
|
||||||
PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create(
|
PropertyDescriptorImpl propertyDescriptor = PropertyDescriptorImpl.create(
|
||||||
containingDeclaration,
|
container,
|
||||||
propertyAnnotations,
|
propertyAnnotations,
|
||||||
modality,
|
modality,
|
||||||
visibility,
|
visibility,
|
||||||
@@ -876,8 +876,8 @@ public class DescriptorResolver {
|
|||||||
KotlinSourceElementKt.toSourceElement(variableDeclaration),
|
KotlinSourceElementKt.toSourceElement(variableDeclaration),
|
||||||
modifierList != null && modifierList.hasModifier(KtTokens.LATEINIT_KEYWORD),
|
modifierList != null && modifierList.hasModifier(KtTokens.LATEINIT_KEYWORD),
|
||||||
modifierList != null && modifierList.hasModifier(KtTokens.CONST_KEYWORD),
|
modifierList != null && modifierList.hasModifier(KtTokens.CONST_KEYWORD),
|
||||||
modifierList != null && modifierList.hasModifier(KtTokens.HEADER_KEYWORD) ||
|
modifierList != null && modifierList.hasModifier(KtTokens.HEADER_KEYWORD) && container instanceof PackageFragmentDescriptor ||
|
||||||
containingDeclaration instanceof ClassDescriptor && ((ClassDescriptor) containingDeclaration).isHeader(),
|
container instanceof ClassDescriptor && ((ClassDescriptor) container).isHeader(),
|
||||||
modifierList != null && modifierList.hasModifier(KtTokens.IMPL_KEYWORD),
|
modifierList != null && modifierList.hasModifier(KtTokens.IMPL_KEYWORD),
|
||||||
modifierList != null && modifierList.hasModifier(KtTokens.EXTERNAL_KEYWORD),
|
modifierList != null && modifierList.hasModifier(KtTokens.EXTERNAL_KEYWORD),
|
||||||
propertyInfo.getHasDelegate()
|
propertyInfo.getHasDelegate()
|
||||||
@@ -898,10 +898,10 @@ public class DescriptorResolver {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
LexicalWritableScope writableScopeForDeclarationResolution = new LexicalWritableScope(
|
LexicalWritableScope writableScopeForDeclarationResolution = new LexicalWritableScope(
|
||||||
scopeForDeclarationResolution, containingDeclaration, false, new TraceBasedLocalRedeclarationChecker(trace, overloadChecker),
|
scopeForDeclarationResolution, container, false, new TraceBasedLocalRedeclarationChecker(trace, overloadChecker),
|
||||||
LexicalScopeKind.PROPERTY_HEADER);
|
LexicalScopeKind.PROPERTY_HEADER);
|
||||||
LexicalWritableScope writableScopeForInitializerResolution = new LexicalWritableScope(
|
LexicalWritableScope writableScopeForInitializerResolution = new LexicalWritableScope(
|
||||||
scopeForInitializerResolution, containingDeclaration, false, LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
|
scopeForInitializerResolution, container, false, LocalRedeclarationChecker.DO_NOTHING.INSTANCE,
|
||||||
LexicalScopeKind.PROPERTY_HEADER);
|
LexicalScopeKind.PROPERTY_HEADER);
|
||||||
typeParameterDescriptors = resolveTypeParametersForDescriptor(
|
typeParameterDescriptors = resolveTypeParametersForDescriptor(
|
||||||
propertyDescriptor,
|
propertyDescriptor,
|
||||||
@@ -951,8 +951,7 @@ public class DescriptorResolver {
|
|||||||
propertyDescriptor, scopeForInitializer, variableDeclaration, dataFlowInfo, type, trace
|
propertyDescriptor, scopeForInitializer, variableDeclaration, dataFlowInfo, type, trace
|
||||||
);
|
);
|
||||||
|
|
||||||
propertyDescriptor.setType(type, typeParameterDescriptors, getDispatchReceiverParameterIfNeeded(containingDeclaration),
|
propertyDescriptor.setType(type, typeParameterDescriptors, getDispatchReceiverParameterIfNeeded(container), receiverDescriptor);
|
||||||
receiverDescriptor);
|
|
||||||
|
|
||||||
PropertySetterDescriptor setter = resolvePropertySetterDescriptor(
|
PropertySetterDescriptor setter = resolvePropertySetterDescriptor(
|
||||||
scopeForDeclarationResolutionWithTypeParameters,
|
scopeForDeclarationResolutionWithTypeParameters,
|
||||||
|
|||||||
@@ -134,7 +134,7 @@ class FunctionDescriptorResolver(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun initializeFunctionDescriptorAndExplicitReturnType(
|
fun initializeFunctionDescriptorAndExplicitReturnType(
|
||||||
containingDescriptor: DeclarationDescriptor,
|
container: DeclarationDescriptor,
|
||||||
scope: LexicalScope,
|
scope: LexicalScope,
|
||||||
function: KtFunction,
|
function: KtFunction,
|
||||||
functionDescriptor: SimpleFunctionDescriptorImpl,
|
functionDescriptor: SimpleFunctionDescriptorImpl,
|
||||||
@@ -164,12 +164,12 @@ class FunctionDescriptorResolver(
|
|||||||
|
|
||||||
val returnType = function.typeReference?.let { typeResolver.resolveType(headerScope, it, trace, true) }
|
val returnType = function.typeReference?.let { typeResolver.resolveType(headerScope, it, trace, true) }
|
||||||
|
|
||||||
val visibility = resolveVisibilityFromModifiers(function, getDefaultVisibility(function, containingDescriptor))
|
val visibility = resolveVisibilityFromModifiers(function, getDefaultVisibility(function, container))
|
||||||
val modality = resolveMemberModalityFromModifiers(function, getDefaultModality(containingDescriptor, visibility, function.hasBody()),
|
val modality = resolveMemberModalityFromModifiers(function, getDefaultModality(container, visibility, function.hasBody()),
|
||||||
trace.bindingContext, containingDescriptor)
|
trace.bindingContext, container)
|
||||||
functionDescriptor.initialize(
|
functionDescriptor.initialize(
|
||||||
receiverType,
|
receiverType,
|
||||||
getDispatchReceiverParameterIfNeeded(containingDescriptor),
|
getDispatchReceiverParameterIfNeeded(container),
|
||||||
typeParameterDescriptors,
|
typeParameterDescriptors,
|
||||||
valueParameterDescriptors,
|
valueParameterDescriptors,
|
||||||
returnType,
|
returnType,
|
||||||
@@ -182,8 +182,8 @@ class FunctionDescriptorResolver(
|
|||||||
functionDescriptor.isInline = function.hasModifier(KtTokens.INLINE_KEYWORD)
|
functionDescriptor.isInline = function.hasModifier(KtTokens.INLINE_KEYWORD)
|
||||||
functionDescriptor.isTailrec = function.hasModifier(KtTokens.TAILREC_KEYWORD)
|
functionDescriptor.isTailrec = function.hasModifier(KtTokens.TAILREC_KEYWORD)
|
||||||
functionDescriptor.isSuspend = function.hasModifier(KtTokens.SUSPEND_KEYWORD)
|
functionDescriptor.isSuspend = function.hasModifier(KtTokens.SUSPEND_KEYWORD)
|
||||||
functionDescriptor.isHeader = function.hasModifier(KtTokens.HEADER_KEYWORD) ||
|
functionDescriptor.isHeader = container is PackageFragmentDescriptor && function.hasModifier(KtTokens.HEADER_KEYWORD) ||
|
||||||
containingDescriptor is ClassDescriptor && containingDescriptor.isHeader
|
container is ClassDescriptor && container.isHeader
|
||||||
functionDescriptor.isImpl = function.hasModifier(KtTokens.IMPL_KEYWORD)
|
functionDescriptor.isImpl = function.hasModifier(KtTokens.IMPL_KEYWORD)
|
||||||
|
|
||||||
receiverType?.let { ForceResolveUtil.forceResolveAllContents(it.annotations) }
|
receiverType?.let { ForceResolveUtil.forceResolveAllContents(it.annotations) }
|
||||||
|
|||||||
+3
@@ -80,6 +80,9 @@ object HeaderImplDeclarationChecker : DeclarationChecker {
|
|||||||
platformModule: ModuleDescriptor,
|
platformModule: ModuleDescriptor,
|
||||||
checkImpl: Boolean
|
checkImpl: Boolean
|
||||||
) {
|
) {
|
||||||
|
// Only look for implementations of top level members; class members will be handled as a part of that header class
|
||||||
|
if (descriptor is CallableMemberDescriptor && descriptor.containingDeclaration !is PackageFragmentDescriptor) return
|
||||||
|
|
||||||
val compatibility = findImplForHeader(descriptor, platformModule, checkImpl) ?: return
|
val compatibility = findImplForHeader(descriptor, platformModule, checkImpl) ?: return
|
||||||
|
|
||||||
val shouldReportError =
|
val shouldReportError =
|
||||||
|
|||||||
+14
@@ -0,0 +1,14 @@
|
|||||||
|
// !LANGUAGE: +MultiPlatformProjects
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
|
||||||
|
header class H {
|
||||||
|
<!WRONG_MODIFIER_TARGET, JVM:WRONG_MODIFIER_TARGET!>header<!> fun foo()
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m1-jvm(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
|
|
||||||
|
impl class H {
|
||||||
|
impl fun foo() {}
|
||||||
|
}
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
// -- Module: <m1-common> --
|
||||||
|
package
|
||||||
|
|
||||||
|
public final header class H {
|
||||||
|
public constructor H()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final header fun foo(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- Module: <m1-jvm> --
|
||||||
|
package
|
||||||
|
|
||||||
|
public final impl class H {
|
||||||
|
public constructor H()
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public final impl fun foo(): kotlin.Unit
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
// !LANGUAGE: +MultiPlatformProjects
|
||||||
|
// MODULE: m1-common
|
||||||
|
// FILE: common.kt
|
||||||
|
|
||||||
|
class Foo {
|
||||||
|
<!NON_ABSTRACT_FUNCTION_WITH_NO_BODY, JVM:NON_ABSTRACT_FUNCTION_WITH_NO_BODY!><!WRONG_MODIFIER_TARGET, JVM:WRONG_MODIFIER_TARGET!>header<!> fun bar(): String<!>
|
||||||
|
}
|
||||||
|
|
||||||
|
// MODULE: m1-jvm(m1-common)
|
||||||
|
// FILE: jvm.kt
|
||||||
+22
@@ -0,0 +1,22 @@
|
|||||||
|
// -- Module: <m1-common> --
|
||||||
|
package
|
||||||
|
|
||||||
|
public final class Foo {
|
||||||
|
public constructor Foo()
|
||||||
|
public final fun bar(): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -- Module: <m1-jvm> --
|
||||||
|
package
|
||||||
|
|
||||||
|
public final class Foo {
|
||||||
|
public constructor Foo()
|
||||||
|
public final fun bar(): kotlin.String
|
||||||
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
}
|
||||||
@@ -10,11 +10,11 @@ class Outer <!WRONG_MODIFIER_TARGET!>header<!> constructor() {
|
|||||||
<!WRONG_MODIFIER_TARGET!>header<!> init {}
|
<!WRONG_MODIFIER_TARGET!>header<!> init {}
|
||||||
|
|
||||||
<!NON_ABSTRACT_FUNCTION_WITH_NO_BODY!><!WRONG_MODIFIER_TARGET!>header<!> fun foo()<!>
|
<!NON_ABSTRACT_FUNCTION_WITH_NO_BODY!><!WRONG_MODIFIER_TARGET!>header<!> fun foo()<!>
|
||||||
<!WRONG_MODIFIER_TARGET!>header<!> val bar: Int
|
<!MUST_BE_INITIALIZED_OR_BE_ABSTRACT!><!WRONG_MODIFIER_TARGET!>header<!> val bar: Int<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
fun foo() {
|
fun foo() {
|
||||||
<!WRONG_MODIFIER_TARGET!>header<!> fun localFun()
|
<!NON_MEMBER_FUNCTION_NO_BODY!><!WRONG_MODIFIER_TARGET!>header<!> fun localFun()<!>
|
||||||
<!WRONG_MODIFIER_TARGET!>header<!> var <!UNUSED_VARIABLE!>x<!> = 42
|
<!WRONG_MODIFIER_TARGET!>header<!> var <!UNUSED_VARIABLE!>x<!> = 42
|
||||||
<!WRONG_MODIFIER_TARGET!>header<!> class Bar
|
<!WRONG_MODIFIER_TARGET!>header<!> class Bar
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -5,9 +5,9 @@ public fun foo(): kotlin.Unit
|
|||||||
|
|
||||||
public final class Outer {
|
public final class Outer {
|
||||||
public constructor Outer()
|
public constructor Outer()
|
||||||
public header final val bar: kotlin.Int
|
public final val bar: kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
public final header fun foo(): kotlin.Unit
|
public final fun foo(): kotlin.Unit
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
|
|
||||||
|
|||||||
@@ -13630,6 +13630,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/multiplatform"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("headerFunInNonHeaderClass.kt")
|
||||||
|
public void testHeaderFunInNonHeaderClass() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerFunInNonHeaderClass.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("implDelegatedMember.kt")
|
@TestMetadata("implDelegatedMember.kt")
|
||||||
public void testImplDelegatedMember() throws Exception {
|
public void testImplDelegatedMember() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/implDelegatedMember.kt");
|
||||||
@@ -13734,6 +13740,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extraHeaderOnMembers.kt")
|
||||||
|
public void testExtraHeaderOnMembers() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/extraHeaderOnMembers.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("genericClassImplTypeAlias.kt")
|
@TestMetadata("genericClassImplTypeAlias.kt")
|
||||||
public void testGenericClassImplTypeAlias() throws Exception {
|
public void testGenericClassImplTypeAlias() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/multiplatform/headerClass/genericClassImplTypeAlias.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user