'open' + 'private' and 'abstract' + 'private' are now incompatible for functions and properties #KT-9324 Fixed

This commit is contained in:
Mikhail Glukhikh
2015-09-28 13:29:06 +03:00
parent 7cf2840fe5
commit 4e91f2ffb7
7 changed files with 30 additions and 36 deletions
@@ -17,6 +17,7 @@
package org.jetbrains.kotlin.resolve
import com.intellij.lang.ASTNode
import com.intellij.psi.PsiElement
import com.intellij.psi.tree.TokenSet
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.annotations.KotlinTarget
@@ -30,12 +31,20 @@ import org.jetbrains.kotlin.psi.*
public object ModifierCheckerCore {
private enum class Compatibility {
// modifier pair is compatible: ok (default)
COMPATIBLE,
// second is redundant to first: warning
REDUNDANT,
// first is redundant to second: warning
REVERSE_REDUNDANT,
// error
REPEATED,
// pair is deprecated, will become incompatible: warning
DEPRECATED,
INCOMPATIBLE
// pair is incompatible: error
INCOMPATIBLE,
// same but only for functions / properties: error
COMPATIBLE_FOR_CLASSES_ONLY
}
private val possibleTargetMap = mapOf<JetModifierKeywordToken, Set<KotlinTarget>>(
@@ -121,6 +130,9 @@ public object ModifierCheckerCore {
// private is incompatible with override
result += incompatibilityRegister(PRIVATE_KEYWORD, OVERRIDE_KEYWORD)
// private is compatible with open / abstract only for classes
result += compatibilityForClassesRegister(PRIVATE_KEYWORD, OPEN_KEYWORD)
result += compatibilityForClassesRegister(PRIVATE_KEYWORD, ABSTRACT_KEYWORD)
return result
}
@@ -146,6 +158,9 @@ public object ModifierCheckerCore {
return result
}
private fun compatibilityForClassesRegister(vararg list: JetModifierKeywordToken) =
compatibilityRegister(Compatibility.COMPATIBLE_FOR_CLASSES_ONLY, *list)
private fun incompatibilityRegister(vararg list: JetModifierKeywordToken) = compatibilityRegister(Compatibility.INCOMPATIBLE, *list)
private fun deprecationRegister(vararg list: JetModifierKeywordToken) = compatibilityRegister(Compatibility.DEPRECATED, *list)
@@ -159,7 +174,11 @@ public object ModifierCheckerCore {
}
}
private fun checkCompatibility(trace: BindingTrace, firstNode: ASTNode, secondNode: ASTNode, incorrectNodes: MutableSet<ASTNode>) {
private fun checkCompatibility(trace: BindingTrace,
firstNode: ASTNode,
secondNode: ASTNode,
owner: PsiElement,
incorrectNodes: MutableSet<ASTNode>) {
val first = firstNode.elementType as JetModifierKeywordToken
val second = secondNode.elementType as JetModifierKeywordToken
val compatibility = compatibility(first, second)
@@ -176,7 +195,10 @@ public object ModifierCheckerCore {
trace.report(Errors.DEPRECATED_MODIFIER_PAIR.on(firstNode.psi, first, second))
trace.report(Errors.DEPRECATED_MODIFIER_PAIR.on(secondNode.psi, second, first))
}
Compatibility.INCOMPATIBLE -> {
Compatibility.COMPATIBLE_FOR_CLASSES_ONLY, Compatibility.INCOMPATIBLE -> {
if (compatibility == Compatibility.COMPATIBLE_FOR_CLASSES_ONLY) {
if (owner is JetClassOrObject) return
}
if (incorrectNodes.add(firstNode)) {
trace.report(Errors.INCOMPATIBLE_MODIFIERS.on(firstNode.psi, first, second))
}
@@ -234,7 +256,7 @@ public object ModifierCheckerCore {
if (first == second) {
break;
}
checkCompatibility(trace, first, second, incorrectNodes)
checkCompatibility(trace, first, second, list.owner, incorrectNodes)
}
if (second !in incorrectNodes) {
if (!checkTarget(trace, second, actualTargets)) {
@@ -40,7 +40,7 @@ class IllegalModifiers1(
<!UNUSED_PARAMETER!>a<!>: Int)
//Check multiple illegal modifiers in constructor
class IllegalModifiers2(<!WRONG_MODIFIER_TARGET!>private<!> <!WRONG_MODIFIER_TARGET!>abstract<!> <!UNUSED_PARAMETER!>a<!>: Int)
class IllegalModifiers2(<!WRONG_MODIFIER_TARGET!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> <!UNUSED_PARAMETER!>a<!>: Int)
//Check annotations with illegal modifiers in constructor
@@ -131,7 +131,7 @@ class IllegalModifiers8 {
<!INCOMPATIBLE_MODIFIERS!>const<!>
constructor() {}
constructor(<!WRONG_MODIFIER_TARGET!>private<!> <!WRONG_MODIFIER_TARGET!>enum<!> <!WRONG_MODIFIER_TARGET!>abstract<!> <!UNUSED_PARAMETER!>x<!>: Int) {}
constructor(<!WRONG_MODIFIER_TARGET!>private<!> <!WRONG_MODIFIER_TARGET!>enum<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> <!UNUSED_PARAMETER!>x<!>: Int) {}
}
class IllegalModifiers9 {
@@ -11,7 +11,7 @@ public abstract class TestBug1() {
position(m1().second)
}
private abstract fun m1(): Pair<Int, Int>
<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>abstract<!> fun m1(): Pair<Int, Int>
private fun position(<!UNUSED_PARAMETER!>p<!>: Int) {}
@@ -14,7 +14,7 @@ class C : A() {
//------------
open class D {
private open fun self() : D = this
<!INCOMPATIBLE_MODIFIERS!>private<!> <!INCOMPATIBLE_MODIFIERS!>open<!> fun self() : D = this
}
class E : D() {
@@ -1,7 +0,0 @@
open class A<out T> {
private open fun foo(t: T) {}
}
class B : A<String>() {
<caret>
}
@@ -1,17 +0,0 @@
open class A<out T> {
private open fun foo(t: T) {}
}
class B : A<String>() {
override fun equals(other: Any?): Boolean {
<selection><caret>return super.equals(other)</selection>
}
override fun hashCode(): Int {
return super.hashCode()
}
override fun toString(): String {
return super.toString()
}
}
@@ -152,10 +152,6 @@ public class OverrideImplementTest : AbstractOverrideImplementTest() {
doMultiOverrideDirectoryTest()
}
public fun testPrivateToThis() {
doMultiOverrideFileTest()
}
public fun testInheritVisibilities() {
doMultiOverrideFileTest()
}