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:
Alexander Udalov
2017-07-21 15:47:57 +03:00
parent 6cb4916dee
commit 3a2d93f73e
10 changed files with 105 additions and 23 deletions
@@ -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) }
@@ -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 =
@@ -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() {}
}
@@ -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
}
@@ -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
@@ -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
} }
@@ -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");