JS: report errors on different external items:
* data classes
* val/var parameters of primary constructors
* enum entry with body
* anonymous `init {}` block in classes
This commit is contained in:
+5
@@ -0,0 +1,5 @@
|
||||
external class A {
|
||||
<!EXTERNAL_ANONYMOUS_INITIALIZER!>init {
|
||||
noImpl
|
||||
}<!>
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
package
|
||||
|
||||
public external final class A {
|
||||
public constructor A()
|
||||
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
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
external enum class E {
|
||||
X,
|
||||
Y <!EXTERNAL_ENUM_ENTRY_WITH_BODY!>{
|
||||
fun foo()
|
||||
}<!>,
|
||||
Z <!EXTERNAL_ENUM_ENTRY_WITH_BODY!>{}<!>
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
package
|
||||
|
||||
public external final enum class E : kotlin.Enum<E> {
|
||||
enum entry X
|
||||
|
||||
enum entry Y
|
||||
|
||||
enum entry Z
|
||||
|
||||
private constructor E()
|
||||
public final override /*1*/ /*fake_override*/ val name: kotlin.String
|
||||
public final override /*1*/ /*fake_override*/ val ordinal: kotlin.Int
|
||||
protected final override /*1*/ /*fake_override*/ fun clone(): kotlin.Any
|
||||
public final override /*1*/ /*fake_override*/ fun compareTo(/*0*/ other: E): kotlin.Int
|
||||
public final override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public final override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
|
||||
// Static members
|
||||
public final /*synthesized*/ fun valueOf(/*0*/ value: kotlin.String): E
|
||||
public final /*synthesized*/ fun values(): kotlin.Array<E>
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
external class C(x: Int, <!EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER!>val y: String<!>)
|
||||
@@ -0,0 +1,9 @@
|
||||
package
|
||||
|
||||
public external final class C {
|
||||
public constructor C(/*0*/ x: kotlin.Int, /*1*/ y: kotlin.String)
|
||||
public final val y: 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
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
external annotation class <!WRONG_EXTERNAL_DECLARATION!>A<!>
|
||||
external annotation class <!WRONG_EXTERNAL_DECLARATION!>A(val x: Int)<!>
|
||||
|
||||
val x: Int
|
||||
<!WRONG_EXTERNAL_DECLARATION!>external get()<!> = noImpl
|
||||
@@ -16,4 +16,6 @@ class C {
|
||||
external class D {
|
||||
val a: Int
|
||||
<!WRONG_EXTERNAL_DECLARATION!>external get()<!> = noImpl
|
||||
}
|
||||
}
|
||||
|
||||
external data class <!WRONG_EXTERNAL_DECLARATION!>E(val x: Int)<!>
|
||||
@@ -4,7 +4,8 @@ public val x: kotlin.Int
|
||||
public val B.x: kotlin.Int
|
||||
|
||||
public external final annotation class A : kotlin.Annotation {
|
||||
public constructor A()
|
||||
public constructor A(/*0*/ x: kotlin.Int)
|
||||
public final val x: kotlin.Int
|
||||
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
|
||||
@@ -32,3 +33,13 @@ public external final class D {
|
||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
public external final data class E {
|
||||
public constructor E(/*0*/ x: kotlin.Int)
|
||||
public final val x: kotlin.Int
|
||||
public final operator /*synthesized*/ fun component1(): kotlin.Int
|
||||
public final /*synthesized*/ fun copy(/*0*/ x: kotlin.Int = ...): E
|
||||
public open override /*1*/ /*synthesized*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||
public open override /*1*/ /*synthesized*/ fun hashCode(): kotlin.Int
|
||||
public open override /*1*/ /*synthesized*/ fun toString(): kotlin.String
|
||||
}
|
||||
|
||||
+18
@@ -569,6 +569,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/testsWithJsStdLib/native"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
|
||||
}
|
||||
|
||||
@TestMetadata("anonymousInitializer.kt")
|
||||
public void testAnonymousInitializer() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/native/anonymousInitializer.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("body.kt")
|
||||
public void testBody() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/native/body.kt");
|
||||
@@ -587,6 +593,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("enumEntry.kt")
|
||||
public void testEnumEntry() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/native/enumEntry.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("extensionFunctionAndProperty.kt")
|
||||
public void testExtensionFunctionAndProperty() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/native/extensionFunctionAndProperty.kt");
|
||||
@@ -635,6 +647,12 @@ public class DiagnosticsTestWithJsStdLibGenerated extends AbstractDiagnosticsTes
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyParameter.kt")
|
||||
public void testPropertyParameter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/native/propertyParameter.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("wrongTarget.kt")
|
||||
public void testWrongTarget() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/testsWithJsStdLib/native/wrongTarget.kt");
|
||||
|
||||
+5
-2
@@ -80,8 +80,11 @@ private val DIAGNOSTIC_FACTORY_TO_RENDERER by lazy {
|
||||
put(ErrorsJs.WRONG_INITIALIZER_OF_EXTERNAL_DECLARATION, "Wrong initializer of external declaration. Must be ' = noImpl'")
|
||||
put(ErrorsJs.WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER,
|
||||
"Wrong default value for parameter of external function. Must be ' = noImpl'")
|
||||
put(ErrorsJs.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL, "Delegated constructor call in external class")
|
||||
put(ErrorsJs.EXTERNAL_DELEGATION, "Using delegate on external declaration")
|
||||
put(ErrorsJs.EXTERNAL_DELEGATED_CONSTRUCTOR_CALL, "Delegated constructor call in external class is not allowed")
|
||||
put(ErrorsJs.EXTERNAL_DELEGATION, "Can't use delegate on external declaration")
|
||||
put(ErrorsJs.EXTERNAL_ANONYMOUS_INITIALIZER, "Anonymous initializer is not allowed in external classes")
|
||||
put(ErrorsJs.EXTERNAL_ENUM_ENTRY_WITH_BODY, "Entry of external enum class can't have body")
|
||||
put(ErrorsJs.EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER, "External class constructor cannot have a property parameter")
|
||||
|
||||
this
|
||||
}
|
||||
|
||||
@@ -20,10 +20,7 @@ import com.intellij.psi.PsiElement;
|
||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.kotlin.diagnostics.*;
|
||||
import org.jetbrains.kotlin.psi.KtClassOrObject;
|
||||
import org.jetbrains.kotlin.psi.KtDeclaration;
|
||||
import org.jetbrains.kotlin.psi.KtElement;
|
||||
import org.jetbrains.kotlin.psi.KtExpression;
|
||||
import org.jetbrains.kotlin.psi.*;
|
||||
import org.jetbrains.kotlin.types.KotlinType;
|
||||
|
||||
import static org.jetbrains.kotlin.diagnostics.PositioningStrategies.*;
|
||||
@@ -87,6 +84,9 @@ public interface ErrorsJs {
|
||||
DiagnosticFactory0<KtExpression> WRONG_DEFAULT_VALUE_FOR_EXTERNAL_FUN_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtElement> EXTERNAL_DELEGATED_CONSTRUCTOR_CALL = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtElement> EXTERNAL_DELEGATION = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtAnonymousInitializer> EXTERNAL_ANONYMOUS_INITIALIZER = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtClassBody> EXTERNAL_ENUM_ENTRY_WITH_BODY = DiagnosticFactory0.create(ERROR);
|
||||
DiagnosticFactory0<KtParameter> EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER = DiagnosticFactory0.create(ERROR);
|
||||
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
Object _initializer = new Object() {
|
||||
|
||||
@@ -51,6 +51,9 @@ object JsExternalChecker : SimpleDeclarationChecker {
|
||||
if (DescriptorUtils.isAnnotationClass(descriptor)) {
|
||||
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "annotation class"))
|
||||
}
|
||||
else if (descriptor is ClassDescriptor && descriptor.isData) {
|
||||
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "data class"))
|
||||
}
|
||||
else if (descriptor is PropertyAccessorDescriptor && isDirectlyExternal(declaration, descriptor)) {
|
||||
diagnosticHolder.report(ErrorsJs.WRONG_EXTERNAL_DECLARATION.on(declaration, "property accessor"))
|
||||
}
|
||||
@@ -92,6 +95,9 @@ object JsExternalChecker : SimpleDeclarationChecker {
|
||||
|
||||
checkBody(declaration, descriptor, diagnosticHolder, bindingContext)
|
||||
checkDelegation(declaration, descriptor, diagnosticHolder)
|
||||
checkAnonymousInitializer(declaration, diagnosticHolder)
|
||||
checkEnumEntry(declaration, diagnosticHolder)
|
||||
checkConstructorPropertyParam(declaration, descriptor, diagnosticHolder)
|
||||
}
|
||||
|
||||
private fun checkBody(
|
||||
@@ -143,6 +149,32 @@ object JsExternalChecker : SimpleDeclarationChecker {
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkAnonymousInitializer(declaration: KtDeclaration, diagnosticHolder: DiagnosticSink) {
|
||||
if (declaration !is KtClassOrObject) return
|
||||
|
||||
for (anonymousInitializer in declaration.getAnonymousInitializers()) {
|
||||
diagnosticHolder.report(ErrorsJs.EXTERNAL_ANONYMOUS_INITIALIZER.on(anonymousInitializer))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkEnumEntry(declaration: KtDeclaration, diagnosticHolder: DiagnosticSink) {
|
||||
if (declaration !is KtEnumEntry) return
|
||||
declaration.getBody()?.let {
|
||||
diagnosticHolder.report(ErrorsJs.EXTERNAL_ENUM_ENTRY_WITH_BODY.on(it))
|
||||
}
|
||||
}
|
||||
|
||||
private fun checkConstructorPropertyParam(
|
||||
declaration: KtDeclaration,
|
||||
descriptor: DeclarationDescriptor,
|
||||
diagnosticHolder: DiagnosticSink
|
||||
) {
|
||||
if (descriptor !is PropertyDescriptor || declaration !is KtParameter) return
|
||||
val containingClass = descriptor.containingDeclaration as ClassDescriptor
|
||||
if (containingClass.isData || DescriptorUtils.isAnnotationClass(containingClass)) return
|
||||
diagnosticHolder.report(ErrorsJs.EXTERNAL_CLASS_CONSTRUCTOR_PROPERTY_PARAMETER.on(declaration))
|
||||
}
|
||||
|
||||
private fun isDirectlyExternal(declaration: KtDeclaration, descriptor: DeclarationDescriptor): Boolean {
|
||||
if (declaration is KtProperty && descriptor is PropertyAccessorDescriptor) return false
|
||||
|
||||
|
||||
+3
-1
@@ -2,7 +2,9 @@
|
||||
package foo
|
||||
|
||||
@JsModule("lib")
|
||||
external class A(val x: Int = noImpl) {
|
||||
external class A(x: Int = noImpl) {
|
||||
val x: Int
|
||||
|
||||
fun foo(y: Int): Int = noImpl
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
@file:JsModule("lib")
|
||||
package foo
|
||||
|
||||
external class A(@native val x: Int = noImpl) {
|
||||
external class A(@native x: Int = noImpl) {
|
||||
val x: Int
|
||||
|
||||
fun foo(y: Int): Int = noImpl
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
@file:JsModule("lib")
|
||||
package foo
|
||||
|
||||
external class A(@native val x: Int = noImpl) {
|
||||
external class A(x: Int = noImpl) {
|
||||
val x: Int
|
||||
|
||||
fun foo(y: Int): Int = noImpl
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,9 @@
|
||||
@file:JsNonModule
|
||||
package foo
|
||||
|
||||
external class A(val x: Int = noImpl) {
|
||||
external class A(x: Int = noImpl) {
|
||||
val x: Int
|
||||
|
||||
fun foo(y: Int): Int = noImpl
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
@file:JsNonModule
|
||||
package foo
|
||||
|
||||
external class A(val x: Int = noImpl) {
|
||||
external class A(x: Int = noImpl) {
|
||||
val x: Int
|
||||
|
||||
fun foo(y: Int): Int = noImpl
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
package foo
|
||||
|
||||
@JsName("A")
|
||||
external open class B(val foo: String)
|
||||
external open class B(foo: String) {
|
||||
val foo: String
|
||||
}
|
||||
|
||||
class C(s: String) : B(s)
|
||||
|
||||
|
||||
+3
-1
@@ -4,7 +4,9 @@
|
||||
package foo
|
||||
|
||||
@JsName("A")
|
||||
external open class B(val foo: String)
|
||||
external open class B(foo: String) {
|
||||
val foo: String
|
||||
}
|
||||
|
||||
// MODULE: main(module1)
|
||||
// FILE: main.kt
|
||||
|
||||
@@ -4,7 +4,9 @@
|
||||
@file:JsModule("native-lib")
|
||||
package foo
|
||||
|
||||
external class A(val x: Int = noImpl) {
|
||||
external class A(x: Int = noImpl) {
|
||||
val x: Int
|
||||
|
||||
fun foo(y: Int): Int = noImpl
|
||||
}
|
||||
|
||||
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
package foo
|
||||
|
||||
external class A(val c: Int) {
|
||||
external class A(c: Int) {
|
||||
val c: Int
|
||||
|
||||
companion object {
|
||||
val g: Int
|
||||
val c: String = noImpl
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package foo
|
||||
|
||||
internal external open class A(val a: Int) {
|
||||
internal external open class A(a: Int) {
|
||||
val a: Int
|
||||
|
||||
fun g(): Int = noImpl
|
||||
fun m(): Int = noImpl
|
||||
|
||||
|
||||
+8
-4
@@ -87,7 +87,8 @@ external object Object {
|
||||
fun test(): Int = noImpl
|
||||
|
||||
@JsName("AnotherClass")
|
||||
class Class(val a: String) {
|
||||
class Class(a: String) {
|
||||
val a: String
|
||||
var b: String = noImpl
|
||||
fun test(): Int = noImpl
|
||||
|
||||
@@ -99,7 +100,8 @@ external object Object {
|
||||
}
|
||||
}
|
||||
|
||||
class Class(val a: String) {
|
||||
class Class(a: String) {
|
||||
val a: String
|
||||
var b: String = noImpl
|
||||
fun test(): Int = noImpl
|
||||
|
||||
@@ -135,7 +137,8 @@ external class Class {
|
||||
fun test(): Int = noImpl
|
||||
}
|
||||
|
||||
class Class(val a: String) {
|
||||
class Class(a: String) {
|
||||
val a: String
|
||||
var b: String = noImpl
|
||||
fun test(): Int = noImpl
|
||||
|
||||
@@ -174,7 +177,8 @@ external interface Trait {
|
||||
fun test(): Int = noImpl
|
||||
}
|
||||
|
||||
class Class(val a: String) {
|
||||
class Class(a: String) {
|
||||
val a: String
|
||||
var b: String = noImpl
|
||||
fun test(): Int = noImpl
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package foo
|
||||
|
||||
internal external class A(val v: String)
|
||||
internal external class A(v: String) {
|
||||
val v: String
|
||||
}
|
||||
|
||||
internal class B {
|
||||
fun bar(a: A, extLambda: A.(Int, String) -> String): String = a.extLambda(7, "_rr_")
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package foo
|
||||
|
||||
external class A(val v: String)
|
||||
external class A(v: String) {
|
||||
val v: String
|
||||
}
|
||||
|
||||
external fun bar(a: A, extLambda: A.(Int, String) -> String): String = noImpl
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package foo
|
||||
|
||||
external class A(val v: String) {
|
||||
external class A(v: String) {
|
||||
val v: String
|
||||
|
||||
fun m(i:Int, s:String): String = noImpl
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -16,7 +16,8 @@ fun anotherCount(vararg a: Int) = anotherParamCount(*a)
|
||||
|
||||
external fun test3(bar: Bar, dummy: Int, vararg args: Int): Boolean = noImpl
|
||||
|
||||
external class Bar(val size: Int, order: Int = noImpl) {
|
||||
external class Bar(size: Int, order: Int = noImpl) {
|
||||
val size: Int
|
||||
fun test(order: Int, dummy: Int, vararg args: Int): Boolean = noImpl
|
||||
companion object {
|
||||
fun startNewTest(): Boolean = noImpl
|
||||
|
||||
@@ -7,7 +7,9 @@ external class A(x: Int) {
|
||||
|
||||
fun foo(): Int = noImpl
|
||||
|
||||
class B(val value: Int) {
|
||||
class B(value: Int) {
|
||||
val value: Int
|
||||
|
||||
fun bar(): Int = noImpl
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user