[FIR] Add diagnostics for object related problems

This commit is contained in:
Nick
2020-07-30 17:11:15 +03:00
committed by Mikhail Glukhikh
parent 694d3cad4e
commit 26e3a111d6
32 changed files with 419 additions and 77 deletions
@@ -0,0 +1,31 @@
object A {
object B {
object C
}
interface X
val a = object : Any() {
<!LOCAL_OBJECT_NOT_ALLOWED!>object D<!> {
<!LOCAL_OBJECT_NOT_ALLOWED!>object G<!>
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface Z<!>
}
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface Y<!>
}
fun b() {
<!LOCAL_OBJECT_NOT_ALLOWED!>object E<!> {
<!LOCAL_OBJECT_NOT_ALLOWED!>object F<!>
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface M<!>
}
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface N<!>
val c = object : Any() {
val t = "test"
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface U<!>
}
}
}
@@ -0,0 +1,89 @@
FILE: localEntitytNotAllowed.kt
public final object A : R|kotlin/Any| {
private constructor(): R|A| {
super<R|kotlin/Any|>()
}
public final object B : R|kotlin/Any| {
private constructor(): R|A.B| {
super<R|kotlin/Any|>()
}
public final object C : R|kotlin/Any| {
private constructor(): R|A.B.C| {
super<R|kotlin/Any|>()
}
}
}
public abstract interface X : R|kotlin/Any| {
}
public final val a: R|<anonymous>| = object : R|kotlin/Any| {
private constructor(): R|<anonymous>| {
super<R|kotlin/Any|>()
}
local final object D : R|kotlin/Any| {
private constructor(): R|A.<anonymous>.D| {
super<R|kotlin/Any|>()
}
local final object G : R|kotlin/Any| {
private constructor(): R|A.<anonymous>.D.G| {
super<R|kotlin/Any|>()
}
}
local abstract interface Z : R|kotlin/Any| {
}
}
local abstract interface Y : R|kotlin/Any| {
}
}
public get(): R|<anonymous>|
public final fun b(): R|kotlin/Unit| {
local final object E : R|kotlin/Any| {
private constructor(): R|A.E| {
super<R|kotlin/Any|>()
}
local final object F : R|kotlin/Any| {
private constructor(): R|A.E.F| {
super<R|kotlin/Any|>()
}
}
local abstract interface M : R|kotlin/Any| {
}
}
local abstract interface N : R|kotlin/Any| {
}
lval c: R|<anonymous>| = object : R|kotlin/Any| {
private constructor(): R|<anonymous>| {
super<R|kotlin/Any|>()
}
public final val t: R|kotlin/String| = String(test)
public get(): R|kotlin/String|
local abstract interface U : R|kotlin/Any| {
}
}
}
}
@@ -0,0 +1,19 @@
class A {
companion object {
}
companion <!MANY_COMPANION_OBJECTS!>object<!> {
}
}
class B {
companion object A {
}
companion <!MANY_COMPANION_OBJECTS!>object B<!> {
}
}
@@ -0,0 +1,41 @@
FILE: manyCompanionObjects.kt
public final class A : R|kotlin/Any| {
public constructor(): R|A| {
super<R|kotlin/Any|>()
}
public final companion object Companion : R|kotlin/Any| {
private constructor(): R|A.Companion| {
super<R|kotlin/Any|>()
}
}
public final companion object Companion : R|kotlin/Any| {
private constructor(): R|A.Companion| {
super<R|kotlin/Any|>()
}
}
}
public final class B : R|kotlin/Any| {
public constructor(): R|B| {
super<R|kotlin/Any|>()
}
public final companion object A : R|kotlin/Any| {
private constructor(): R|B.A| {
super<R|kotlin/Any|>()
}
}
public final companion object B : R|kotlin/Any| {
private constructor(): R|B.B| {
super<R|kotlin/Any|>()
}
}
}
@@ -0,0 +1,15 @@
<!TYPE_PARAMETERS_IN_OBJECT!>object A<!><T, K : T> {
<!TYPE_PARAMETERS_IN_OBJECT!>object B<!><L>
}
class N {
companion <!TYPE_PARAMETERS_IN_OBJECT!>object<!><T> {
}
}
fun test() {
<!LOCAL_OBJECT_NOT_ALLOWED, TYPE_PARAMETERS_IN_OBJECT!>object M<!><H> {
}
}
@@ -0,0 +1,36 @@
FILE: typeParametersInObject.kt
public final object A<T, K : R|T|> : R|kotlin/Any| {
private constructor<T, K : R|T|>(): R|A<T, K>| {
super<R|kotlin/Any|>()
}
public final object B<L> : R|kotlin/Any| {
private constructor<L>(): R|A.B<L>| {
super<R|kotlin/Any|>()
}
}
}
public final class N : R|kotlin/Any| {
public constructor(): R|N| {
super<R|kotlin/Any|>()
}
public final companion object Companion<T> : R|kotlin/Any| {
private constructor<T>(): R|N.Companion<T>| {
super<R|kotlin/Any|>()
}
}
}
public final fun test(): R|kotlin/Unit| {
local final object M<H> : R|kotlin/Any| {
private constructor<H>(): R|M<H>| {
super<R|kotlin/Any|>()
}
}
}
@@ -12,7 +12,7 @@ fun test() {
}
b.foo()
object B {
<!LOCAL_OBJECT_NOT_ALLOWED!>object B<!> {
fun foo() {}
}
B.foo()
@@ -916,6 +916,16 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/localAnnotationClass.kt");
}
@TestMetadata("localEntitytNotAllowed.kt")
public void testLocalEntitytNotAllowed() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/localEntitytNotAllowed.kt");
}
@TestMetadata("manyCompanionObjects.kt")
public void testManyCompanionObjects() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/manyCompanionObjects.kt");
}
@TestMetadata("notASupertype.kt")
public void testNotASupertype() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt");
@@ -961,6 +971,11 @@ public class FirDiagnosticsTestGenerated extends AbstractFirDiagnosticsTest {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/typeOfAnnotationMember.kt");
}
@TestMetadata("typeParametersInObject.kt")
public void testTypeParametersInObject() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/typeParametersInObject.kt");
}
@TestMetadata("upperBoundViolated.kt")
public void testUpperBoundViolated() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/upperBoundViolated.kt");
@@ -916,6 +916,16 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/localAnnotationClass.kt");
}
@TestMetadata("localEntitytNotAllowed.kt")
public void testLocalEntitytNotAllowed() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/localEntitytNotAllowed.kt");
}
@TestMetadata("manyCompanionObjects.kt")
public void testManyCompanionObjects() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/manyCompanionObjects.kt");
}
@TestMetadata("notASupertype.kt")
public void testNotASupertype() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/notASupertype.kt");
@@ -961,6 +971,11 @@ public class FirDiagnosticsWithLightTreeTestGenerated extends AbstractFirDiagnos
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/typeOfAnnotationMember.kt");
}
@TestMetadata("typeParametersInObject.kt")
public void testTypeParametersInObject() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/typeParametersInObject.kt");
}
@TestMetadata("upperBoundViolated.kt")
public void testUpperBoundViolated() throws Exception {
runTest("compiler/fir/analysis-tests/testData/resolve/diagnostics/upperBoundViolated.kt");
@@ -11,7 +11,10 @@ import org.jetbrains.kotlin.fir.analysis.checkers.cfa.FirControlFlowChecker
object CommonDeclarationCheckers : DeclarationCheckers() {
override val declarationCheckers: List<FirBasicDeclarationChecker> = listOf(
FirAnnotationClassDeclarationChecker,
FirModifierChecker
FirModifierChecker,
FirManyCompanionObjectsChecker,
FirLocalEntityNotAllowedChecker,
FirTypeParametersInObjectChecker,
)
override val memberDeclarationCheckers: List<FirMemberDeclarationChecker> = listOf(
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.*
object FirLocalEntityNotAllowedChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration !is FirRegularClass || declaration.visibility != Visibilities.LOCAL) {
return
}
when {
declaration.classKind == ClassKind.OBJECT && !declaration.isCompanion -> reporter.reportLocalObjectNotAllowed(declaration.source)
declaration.classKind == ClassKind.INTERFACE -> reporter.reportLocalInterfaceNotAllowed(declaration.source)
else -> {
}
}
}
private fun DiagnosticReporter.reportLocalObjectNotAllowed(source: FirSourceElement?) {
source?.let { report(FirErrors.LOCAL_OBJECT_NOT_ALLOWED.on(it)) }
}
private fun DiagnosticReporter.reportLocalInterfaceNotAllowed(source: FirSourceElement?) {
source?.let { report(FirErrors.LOCAL_INTERFACE_NOT_ALLOWED.on(it)) }
}
}
@@ -0,0 +1,38 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
import org.jetbrains.kotlin.fir.declarations.isCompanion
object FirManyCompanionObjectsChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration !is FirRegularClass) {
return
}
var hasCompanion = false
for (it in declaration.declarations) {
if (it is FirRegularClass && it.isCompanion) {
if (hasCompanion) {
reporter.report(it.source)
}
hasCompanion = true
}
}
}
private fun DiagnosticReporter.report(source: FirSourceElement?) {
source?.let { report(FirErrors.MANY_COMPANION_OBJECTS.on(it)) }
}
}
@@ -0,0 +1,30 @@
/*
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.fir.analysis.checkers.declaration
import org.jetbrains.kotlin.descriptors.ClassKind
import org.jetbrains.kotlin.fir.FirSourceElement
import org.jetbrains.kotlin.fir.analysis.checkers.context.CheckerContext
import org.jetbrains.kotlin.fir.analysis.diagnostics.DiagnosticReporter
import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import org.jetbrains.kotlin.fir.declarations.FirDeclaration
import org.jetbrains.kotlin.fir.declarations.FirRegularClass
object FirTypeParametersInObjectChecker : FirBasicDeclarationChecker() {
override fun check(declaration: FirDeclaration, context: CheckerContext, reporter: DiagnosticReporter) {
if (declaration !is FirRegularClass || declaration.classKind != ClassKind.OBJECT) {
return
}
if (declaration.typeParameters.isNotEmpty()) {
reporter.report(declaration.source)
}
}
private fun DiagnosticReporter.report(source: FirSourceElement?) {
source?.let { report(FirErrors.TYPE_PARAMETERS_IN_OBJECT.on(it)) }
}
}
@@ -81,6 +81,11 @@ object FirErrors {
val PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT by error0<FirSourceElement, PsiElement>()
val UPPER_BOUND_VIOLATED by error0<FirSourceElement, PsiElement>()
val MANY_COMPANION_OBJECTS by error0<FirSourceElement, PsiElement>()
val LOCAL_OBJECT_NOT_ALLOWED by error0<FirSourceElement, PsiElement>()
val LOCAL_INTERFACE_NOT_ALLOWED by error0<FirSourceElement, PsiElement>()
val TYPE_PARAMETERS_IN_OBJECT by error0<FirSourceElement, PsiElement>()
// Control flow diagnostics
val UNINITIALIZED_VARIABLE by error1<FirSourceElement, PsiElement, FirPropertySymbol>()
@@ -194,7 +194,7 @@ fun testFunctionLiterals() {
val endsWithObjectDeclaration : () -> Int = {
var x = 1
x = 333
object A {}
<!LOCAL_OBJECT_NOT_ALLOWED!>object A<!> {}
}
val expectedUnitReturnType1: () -> Unit = {
@@ -203,7 +203,7 @@ fun testFunctionLiterals() {
val expectedUnitReturnType2: () -> Unit = {
fun meow() : Unit {}
object A {}
<!LOCAL_OBJECT_NOT_ALLOWED!>object A<!> {}
}
}
@@ -5,7 +5,7 @@ class A {
companion object {
val x = 1
}
companion object {
companion <!MANY_COMPANION_OBJECTS!>object<!> {
val x = 1
}
}
@@ -14,10 +14,10 @@ class AA {
companion object {
val x = 1
}
companion object A {
companion <!MANY_COMPANION_OBJECTS!>object A<!> {
val x = 1
}
companion object AA {
companion <!MANY_COMPANION_OBJECTS!>object AA<!> {
val x = 1
}
}
@@ -2,16 +2,16 @@ class A {
inner class I {
companion object A
companion object B
companion <!MANY_COMPANION_OBJECTS!>object B<!>
companion object C
companion <!MANY_COMPANION_OBJECTS!>object C<!>
}
}
object O {
companion object A
companion object B
companion <!MANY_COMPANION_OBJECTS!>object B<!>
companion object C
companion <!MANY_COMPANION_OBJECTS!>object C<!>
}
@@ -1,21 +1,21 @@
object A<T>
object B<in T, out R>
object C<T : Comparable<T>>
<!TYPE_PARAMETERS_IN_OBJECT!>object A<!><T>
<!TYPE_PARAMETERS_IN_OBJECT!>object B<!><in T, out R>
<!TYPE_PARAMETERS_IN_OBJECT!>object C<!><T : Comparable<T>>
class D {
companion object<T>
companion <!TYPE_PARAMETERS_IN_OBJECT!>object<!><T>
}
class E {
companion object<in T, out R>
companion <!TYPE_PARAMETERS_IN_OBJECT!>object<!><in T, out R>
}
class F {
companion object C<T : Comparable<T>>
companion <!TYPE_PARAMETERS_IN_OBJECT!>object C<!><T : Comparable<T>>
}
class G {
companion object F<T>
companion <!TYPE_PARAMETERS_IN_OBJECT!>object F<!><T>
}
object H<T, R><!CONSTRUCTOR_IN_OBJECT!>()<!>
<!TYPE_PARAMETERS_IN_OBJECT!>object H<!><T, R><!CONSTRUCTOR_IN_OBJECT!>()<!>
@@ -4,9 +4,9 @@
override class A {
override companion object {}
open companion object {}
abstract companion object {}
final companion object {}
open companion <!MANY_COMPANION_OBJECTS!>object<!> {}
abstract companion <!MANY_COMPANION_OBJECTS!>object<!> {}
final companion <!MANY_COMPANION_OBJECTS!>object<!> {}
}
override object B1 {}
@@ -87,9 +87,9 @@ class WithNestedFun<K> {
}
fun <T> local() {
fun interface LocalFun {
<!LOCAL_INTERFACE_NOT_ALLOWED!>fun interface LocalFun {
fun invoke(element: T)
}
}<!>
}
fun interface WithDefaultValue {
@@ -9,8 +9,8 @@ inline val z: Int
}
}
object B{
object BInner {}
<!LOCAL_OBJECT_NOT_ALLOWED!>object B<!>{
<!LOCAL_OBJECT_NOT_ALLOWED!>object BInner<!> {}
}
fun local() {
@@ -9,8 +9,8 @@ inline fun unsupported() {
}
}
object B{
object BInner {}
<!LOCAL_OBJECT_NOT_ALLOWED!>object B<!>{
<!LOCAL_OBJECT_NOT_ALLOWED!>object BInner<!> {}
}
fun local() {
@@ -1,30 +0,0 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
// KT-4351 Cannot resolve reference to self in init of class local to function
fun f() {
class MyClass() {
init {
val x: MyClass = MyClass()
}
fun member() {
val x: MyClass = MyClass()
}
}
object MyObject {
init {
val obj: MyObject = MyObject
}
}
val x: MyClass = MyClass()
}
val closure = {
class MyClass {
init {
val x: MyClass = MyClass()
}
}
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
// !DIAGNOSTICS: -UNUSED_VARIABLE
// KT-4351 Cannot resolve reference to self in init of class local to function
+4 -4
View File
@@ -1,14 +1,14 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
fun foo() {
interface a {}
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface a {}<!>
val b = object {
interface c {}
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface c {}<!>
}
class A {
interface d {}
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface d {}<!>
}
val f = {
interface e {}
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface e {}<!>
}
}
@@ -16,7 +16,7 @@ fun test() {
}
b.foo()
object B {
<!LOCAL_OBJECT_NOT_ALLOWED!>object B<!> {
fun foo() {}
}
B.foo()
@@ -1,15 +1,15 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
fun foo() {
object a {}
<!LOCAL_OBJECT_NOT_ALLOWED!>object a<!> {}
val b = object {
object c {}
<!LOCAL_OBJECT_NOT_ALLOWED!>object c<!> {}
}
b.c
class A {
object d {}
<!LOCAL_OBJECT_NOT_ALLOWED!>object d<!> {}
}
val f = {
object e {}
<!LOCAL_OBJECT_NOT_ALLOWED!>object e<!> {}
}
}
@@ -1,4 +0,0 @@
fun foo(): Any {
object Bar
return Bar
}
@@ -1,3 +1,4 @@
// FIR_IDENTICAL
fun foo(): Any {
<!LOCAL_OBJECT_NOT_ALLOWED!>object Bar<!>
return Bar
@@ -8,10 +8,10 @@ fun withLocalClasses(param: Int): Interface {
get() = 100
}
interface LocalInterface : Interface {
<!LOCAL_INTERFACE_NOT_ALLOWED!>interface LocalInterface : Interface {
override fun foo(x: Int): Int =
x + param
}
}<!>
return object : LocalBase(), LocalInterface {
override fun foo(x: Int): Int =
@@ -227,12 +227,12 @@ public class YamlNewWizardProjectImportTestGenerated extends AbstractYamlNewWiza
}
@TestMetadata("singlePlatformJsBrowser")
public void testSingleplatformJsBrowser() throws Exception {
public void testSinglePlatformJsBrowser() throws Exception {
runTest("libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/singlePlatformJsBrowser/");
}
@TestMetadata("singlePlatformJsNode")
public void testSingleplatformJsNode() throws Exception {
public void testSinglePlatformJsNode() throws Exception {
runTest("libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/singlePlatformJsNode/");
}
}
@@ -79,12 +79,12 @@ public class YamlBuildFileGenerationTestGenerated extends AbstractYamlBuildFileG
}
@TestMetadata("singlePlatformJsBrowser")
public void testSingleplatformJsBrowser() throws Exception {
public void testSinglePlatformJsBrowser() throws Exception {
runTest("libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/singlePlatformJsBrowser/");
}
@TestMetadata("singlePlatformJsNode")
public void testSingleplatformJsNode() throws Exception {
public void testSinglePlatformJsNode() throws Exception {
runTest("libraries/tools/new-project-wizard/new-project-wizard-cli/testData/buildFileGeneration/singlePlatformJsNode/");
}
}