From 2873f74932de95da91049bc9c577942a53d054b3 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 8 Nov 2013 18:39:43 +0400 Subject: [PATCH] Generate @Nullable/@NotNull annotations on Kotlin declarations (for IDEA interop) --- .../jet/codegen/AnnotationCodegen.java | 47 ++++++++--- .../asJava/nullabilityAnnotations/Class.java | 74 +++++++++++++++++ .../asJava/nullabilityAnnotations/Class.kt | 32 ++++++++ .../ClassWithConstructor.java | 4 + .../ClassWithConstructor.kt | 4 + .../ClassWithConstructorAndProperties.java | 15 ++++ .../ClassWithConstructorAndProperties.kt | 4 + .../asJava/nullabilityAnnotations/Trait.java | 39 +++++++++ .../asJava/nullabilityAnnotations/Trait.kt | 18 +++++ .../_DefaultPackage.java | 62 ++++++++++++++ .../nullabilityAnnotations/_DefaultPackage.kt | 30 +++++++ .../jet/asJava/KotlinAsJavaTestBase.java | 6 ++ .../asJava/NullabilityAnnotationsTest.java | 81 +++++++++++++++++++ 13 files changed, 405 insertions(+), 11 deletions(-) create mode 100644 compiler/testData/asJava/nullabilityAnnotations/Class.java create mode 100644 compiler/testData/asJava/nullabilityAnnotations/Class.kt create mode 100644 compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructor.java create mode 100644 compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructor.kt create mode 100644 compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructorAndProperties.java create mode 100644 compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructorAndProperties.kt create mode 100644 compiler/testData/asJava/nullabilityAnnotations/Trait.java create mode 100644 compiler/testData/asJava/nullabilityAnnotations/Trait.kt create mode 100644 compiler/testData/asJava/nullabilityAnnotations/_DefaultPackage.java create mode 100644 compiler/testData/asJava/nullabilityAnnotations/_DefaultPackage.kt create mode 100644 compiler/tests/org/jetbrains/jet/asJava/NullabilityAnnotationsTest.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java index 889daf7ea91..139a2127618 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/AnnotationCodegen.java @@ -19,10 +19,7 @@ package org.jetbrains.jet.codegen; import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.asm4.AnnotationVisitor; -import org.jetbrains.asm4.ClassVisitor; -import org.jetbrains.asm4.FieldVisitor; -import org.jetbrains.asm4.MethodVisitor; +import org.jetbrains.asm4.*; import org.jetbrains.jet.codegen.state.JetTypeMapper; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.annotations.Annotated; @@ -36,11 +33,11 @@ import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.constants.*; import org.jetbrains.jet.lang.resolve.constants.StringValue; +import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import java.lang.annotation.RetentionPolicy; -import java.util.List; -import java.util.Map; +import java.util.*; import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDeclaration; @@ -73,9 +70,12 @@ public abstract class AnnotationCodegen { } if (modifierList == null) { + generateAdditionalAnnotations(annotated, Collections.emptySet()); return; } + Set annotationDescriptorsAlreadyPresent = new HashSet(); + List annotationEntries = modifierList.getAnnotationEntries(); for (JetAnnotationEntry annotationEntry : annotationEntries) { ResolvedCall resolvedCall = @@ -86,7 +86,29 @@ public abstract class AnnotationCodegen { if (annotationDescriptor == null) continue; // Skipping annotations if they are not resolved. Needed for JetLightClass generation if (isVolatile(annotationDescriptor)) continue; - genAnnotation(annotationDescriptor); + String descriptor = genAnnotation(annotationDescriptor); + if (descriptor != null) { + annotationDescriptorsAlreadyPresent.add(descriptor); + } + } + + generateAdditionalAnnotations(annotated, annotationDescriptorsAlreadyPresent); + } + + private void generateAdditionalAnnotations(@NotNull Annotated annotated, @NotNull Set annotationDescriptorsAlreadyPresent) { + if (annotated instanceof CallableDescriptor) { + generateNullabilityAnnotation(((CallableDescriptor) annotated).getReturnType(), annotationDescriptorsAlreadyPresent); + } + } + + private void generateNullabilityAnnotation(@Nullable JetType type, @NotNull Set annotationDescriptorsAlreadyPresent) { + if (type == null) return; + + Class annotationClass = CodegenUtil.isNullableType(type) ? Nullable.class : NotNull.class; + + String descriptor = Type.getType(annotationClass).getDescriptor(); + if (!annotationDescriptorsAlreadyPresent.contains(descriptor)) { + visitAnnotation(descriptor, false).visitEnd(); } } @@ -101,18 +123,21 @@ public abstract class AnnotationCodegen { visitor.visitEnd(); } - private void genAnnotation(AnnotationDescriptor annotationDescriptor) { + @Nullable + private String genAnnotation(AnnotationDescriptor annotationDescriptor) { ClassifierDescriptor classifierDescriptor = annotationDescriptor.getType().getConstructor().getDeclarationDescriptor(); RetentionPolicy rp = getRetentionPolicy(classifierDescriptor, typeMapper); if (rp == RetentionPolicy.SOURCE) { - return; + return null; } - String internalName = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor(); - AnnotationVisitor annotationVisitor = visitAnnotation(internalName, rp == RetentionPolicy.RUNTIME); + String descriptor = typeMapper.mapType(annotationDescriptor.getType()).getDescriptor(); + AnnotationVisitor annotationVisitor = visitAnnotation(descriptor, rp == RetentionPolicy.RUNTIME); genAnnotationArguments(annotationDescriptor, annotationVisitor); annotationVisitor.visitEnd(); + + return descriptor; } private void genAnnotationArguments(AnnotationDescriptor annotationDescriptor, AnnotationVisitor annotationVisitor) { diff --git a/compiler/testData/asJava/nullabilityAnnotations/Class.java b/compiler/testData/asJava/nullabilityAnnotations/Class.java new file mode 100644 index 00000000000..7c52678b9da --- /dev/null +++ b/compiler/testData/asJava/nullabilityAnnotations/Class.java @@ -0,0 +1,74 @@ +public final class Class implements jet.JetObject { + @org.jetbrains.annotations.Nullable + private final java.lang.String nullableVal = ""; + @org.jetbrains.annotations.Nullable + private java.lang.String nullableVar; + @org.jetbrains.annotations.NotNull + private final java.lang.String notNullVal = ""; + @org.jetbrains.annotations.NotNull + private java.lang.String notNullVar; + + @org.jetbrains.annotations.NotNull + public final java.lang.String notNull(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "a") java.lang.String p) { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + public final java.lang.String nullable(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "a", type = "?") java.lang.String p) { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public final java.lang.String notNullWithNN() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + @org.jetbrains.annotations.NotNull + public final java.lang.String notNullWithN() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + public final java.lang.String nullableWithN() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + @org.jetbrains.annotations.Nullable + public final java.lang.String nullableWithNN() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + public final java.lang.String getNullableVal() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + public final java.lang.String getNullableVar() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public final void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "", type = "?") java.lang.String p) { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public final java.lang.String getNotNullVal() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public final java.lang.String getNotNullVar() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public final void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "") java.lang.String p) { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + @org.jetbrains.annotations.NotNull + public final java.lang.String getNotNullValWithGet() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + @org.jetbrains.annotations.NotNull + public final java.lang.String getNotNullVarWithGetSet() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + @org.jetbrains.annotations.NotNull + public final void setNotNullVarWithGetSet(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "v") java.lang.String p) { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + @org.jetbrains.annotations.Nullable + public final java.lang.String getNullableValWithGet() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + @org.jetbrains.annotations.Nullable + public final java.lang.String getNullableVarWithGetSet() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public final void setNullableVarWithGetSet(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "v", type = "?") java.lang.String p) { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public Class() { /* compiled code */ } +} \ No newline at end of file diff --git a/compiler/testData/asJava/nullabilityAnnotations/Class.kt b/compiler/testData/asJava/nullabilityAnnotations/Class.kt new file mode 100644 index 00000000000..7f0e99b3d8f --- /dev/null +++ b/compiler/testData/asJava/nullabilityAnnotations/Class.kt @@ -0,0 +1,32 @@ +import org.jetbrains.annotations.NotNull +import org.jetbrains.annotations.Nullable + +class Class { + fun notNull(a: String): String = "" + fun nullable(a: String?): String? = "" + + NotNull fun notNullWithNN(): String = "" + Nullable fun notNullWithN(): String = "" + + Nullable fun nullableWithN(): String? = "" + NotNull fun nullableWithNN(): String? = "" + + val nullableVal: String? = "" + var nullableVar: String? = "" + val notNullVal: String = "" + var notNullVar: String = "" + + val notNullValWithGet: String + [Nullable] get() = "" + + var notNullVarWithGetSet: String + [Nullable] get() = "" + [Nullable] set(v) {} + + val nullableValWithGet: String? + [NotNull] get() = "" + + var nullableVarWithGetSet: String? + [NotNull] get() = "" + [NotNull] set(v) {} +} \ No newline at end of file diff --git a/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructor.java b/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructor.java new file mode 100644 index 00000000000..e65d0ed3a58 --- /dev/null +++ b/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructor.java @@ -0,0 +1,4 @@ +public final class ClassWithConstructor implements jet.JetObject { + @org.jetbrains.annotations.NotNull + public ClassWithConstructor(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "nullable", type = "?") java.lang.String p, @org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "notNull") java.lang.String p1) { /* compiled code */ } +} \ No newline at end of file diff --git a/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructor.kt b/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructor.kt new file mode 100644 index 00000000000..1d0b6fec0cc --- /dev/null +++ b/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructor.kt @@ -0,0 +1,4 @@ +class ClassWithConstructor( + nullable: String?, + notNull: String +) \ No newline at end of file diff --git a/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructorAndProperties.java b/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructorAndProperties.java new file mode 100644 index 00000000000..3de4644c2ea --- /dev/null +++ b/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructorAndProperties.java @@ -0,0 +1,15 @@ +public final class ClassWithConstructorAndProperties implements jet.JetObject { + @org.jetbrains.annotations.Nullable + private final java.lang.String nullable; + @org.jetbrains.annotations.NotNull + private final java.lang.String notNull; + + @org.jetbrains.annotations.Nullable + public final java.lang.String getNullable() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public final java.lang.String getNotNull() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public ClassWithConstructorAndProperties(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "nullable", type = "?") java.lang.String p, @org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "notNull") java.lang.String p1) { /* compiled code */ } +} \ No newline at end of file diff --git a/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructorAndProperties.kt b/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructorAndProperties.kt new file mode 100644 index 00000000000..b1ae17a6bca --- /dev/null +++ b/compiler/testData/asJava/nullabilityAnnotations/ClassWithConstructorAndProperties.kt @@ -0,0 +1,4 @@ +class ClassWithConstructorAndProperties( + val nullable: String?, + val notNull: String +) diff --git a/compiler/testData/asJava/nullabilityAnnotations/Trait.java b/compiler/testData/asJava/nullabilityAnnotations/Trait.java new file mode 100644 index 00000000000..329da257947 --- /dev/null +++ b/compiler/testData/asJava/nullabilityAnnotations/Trait.java @@ -0,0 +1,39 @@ +public interface Trait extends jet.JetObject { + @org.jetbrains.annotations.NotNull + java.lang.String notNull(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "a") java.lang.String p); + + @org.jetbrains.annotations.Nullable + java.lang.String nullable(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "a", type = "?") java.lang.String p); + + @org.jetbrains.annotations.NotNull + java.lang.String notNullWithNN(); + + @org.jetbrains.annotations.Nullable + @org.jetbrains.annotations.NotNull + java.lang.String notNullWithN(); + + @org.jetbrains.annotations.Nullable + java.lang.String nullableWithN(); + + @org.jetbrains.annotations.NotNull + @org.jetbrains.annotations.Nullable + java.lang.String nullableWithNN(); + + @org.jetbrains.annotations.Nullable + java.lang.String getNullableVal(); + + @org.jetbrains.annotations.Nullable + java.lang.String getNullableVar(); + + @org.jetbrains.annotations.NotNull + void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "", type = "?") java.lang.String p); + + @org.jetbrains.annotations.NotNull + java.lang.String getNotNullVal(); + + @org.jetbrains.annotations.NotNull + java.lang.String getNotNullVar(); + + @org.jetbrains.annotations.NotNull + void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "") java.lang.String p); +} \ No newline at end of file diff --git a/compiler/testData/asJava/nullabilityAnnotations/Trait.kt b/compiler/testData/asJava/nullabilityAnnotations/Trait.kt new file mode 100644 index 00000000000..a00d153a1f1 --- /dev/null +++ b/compiler/testData/asJava/nullabilityAnnotations/Trait.kt @@ -0,0 +1,18 @@ +import org.jetbrains.annotations.NotNull +import org.jetbrains.annotations.Nullable + +trait Trait { + fun notNull(a: String): String + fun nullable(a: String?): String? + + NotNull fun notNullWithNN(): String + Nullable fun notNullWithN(): String + + Nullable fun nullableWithN(): String? + NotNull fun nullableWithNN(): String? + + val nullableVal: String? + var nullableVar: String? + val notNullVal: String + var notNullVar: String +} \ No newline at end of file diff --git a/compiler/testData/asJava/nullabilityAnnotations/_DefaultPackage.java b/compiler/testData/asJava/nullabilityAnnotations/_DefaultPackage.java new file mode 100644 index 00000000000..80bb029cb7e --- /dev/null +++ b/compiler/testData/asJava/nullabilityAnnotations/_DefaultPackage.java @@ -0,0 +1,62 @@ +public final class _DefaultPackage { + @org.jetbrains.annotations.NotNull + public static final java.lang.String notNull(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "a") java.lang.String p) { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + public static final java.lang.String nullable(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "a", type = "?") java.lang.String p) { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public static final java.lang.String notNullWithNN() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + @org.jetbrains.annotations.NotNull + public static final java.lang.String notNullWithN() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + public static final java.lang.String nullableWithN() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + @org.jetbrains.annotations.Nullable + public static final java.lang.String nullableWithNN() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + public static final java.lang.String getNullableVal() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + public static final java.lang.String getNullableVar() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public static final void setNullableVar(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "", type = "?") java.lang.String p) { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public static final java.lang.String getNotNullVal() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public static final java.lang.String getNotNullVar() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public static final void setNotNullVar(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "") java.lang.String p) { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + @org.jetbrains.annotations.NotNull + public static final java.lang.String getNotNullValWithGet() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + @org.jetbrains.annotations.NotNull + public static final java.lang.String getNotNullVarWithGetSet() { /* compiled code */ } + + @org.jetbrains.annotations.Nullable + @org.jetbrains.annotations.NotNull + public static final void setNotNullVarWithGetSet(@org.jetbrains.annotations.NotNull @jet.runtime.typeinfo.JetValueParameter(name = "v") java.lang.String p) { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + @org.jetbrains.annotations.Nullable + public static final java.lang.String getNullableValWithGet() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + @org.jetbrains.annotations.Nullable + public static final java.lang.String getNullableVarWithGetSet() { /* compiled code */ } + + @org.jetbrains.annotations.NotNull + public static final void setNullableVarWithGetSet(@org.jetbrains.annotations.Nullable @jet.runtime.typeinfo.JetValueParameter(name = "v", type = "?") java.lang.String p) { /* compiled code */ } +} \ No newline at end of file diff --git a/compiler/testData/asJava/nullabilityAnnotations/_DefaultPackage.kt b/compiler/testData/asJava/nullabilityAnnotations/_DefaultPackage.kt new file mode 100644 index 00000000000..5fc0d180c2a --- /dev/null +++ b/compiler/testData/asJava/nullabilityAnnotations/_DefaultPackage.kt @@ -0,0 +1,30 @@ +import org.jetbrains.annotations.NotNull +import org.jetbrains.annotations.Nullable + +fun notNull(a: String): String = "" +fun nullable(a: String?): String? = "" + +NotNull fun notNullWithNN(): String = "" +Nullable fun notNullWithN(): String = "" + +Nullable fun nullableWithN(): String? = "" +NotNull fun nullableWithNN(): String? = "" + +val nullableVal: String? = "" +var nullableVar: String? = "" +val notNullVal: String = "" +var notNullVar: String = "" + +val notNullValWithGet: String + [Nullable] get() = "" + +var notNullVarWithGetSet: String + [Nullable] get() = "" + [Nullable] set(v) {} + +val nullableValWithGet: String? + [NotNull] get() = "" + +var nullableVarWithGetSet: String? + [NotNull] get() = "" + [NotNull] set(v) {} \ No newline at end of file diff --git a/compiler/tests/org/jetbrains/jet/asJava/KotlinAsJavaTestBase.java b/compiler/tests/org/jetbrains/jet/asJava/KotlinAsJavaTestBase.java index 82fd95fe121..90760819050 100644 --- a/compiler/tests/org/jetbrains/jet/asJava/KotlinAsJavaTestBase.java +++ b/compiler/tests/org/jetbrains/jet/asJava/KotlinAsJavaTestBase.java @@ -16,6 +16,7 @@ package org.jetbrains.jet.asJava; +import org.jetbrains.annotations.NotNull; import org.jetbrains.jet.JetTestUtils; import org.jetbrains.jet.cli.jvm.compiler.JetCoreEnvironment; import org.jetbrains.jet.config.CommonConfigurationKeys; @@ -36,9 +37,14 @@ public abstract class KotlinAsJavaTestBase extends KotlinTestWithEnvironment { configuration.add(CommonConfigurationKeys.SOURCE_ROOTS_KEY, root.getPath()); } + extraConfiguration(configuration); + return JetCoreEnvironment.createForTests(getTestRootDisposable(), configuration); } + protected void extraConfiguration(@NotNull CompilerConfiguration configuration) { + } + protected abstract List getKotlinSourceRoots(); @Override diff --git a/compiler/tests/org/jetbrains/jet/asJava/NullabilityAnnotationsTest.java b/compiler/tests/org/jetbrains/jet/asJava/NullabilityAnnotationsTest.java new file mode 100644 index 00000000000..e12f31a8869 --- /dev/null +++ b/compiler/tests/org/jetbrains/jet/asJava/NullabilityAnnotationsTest.java @@ -0,0 +1,81 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.asJava; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.impl.compiled.ClsElementImpl; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.JetTestUtils; +import org.jetbrains.jet.cli.jvm.JVMConfigurationKeys; +import org.jetbrains.jet.config.CompilerConfiguration; + +import java.io.File; +import java.util.Collections; +import java.util.List; + +public class NullabilityAnnotationsTest extends KotlinAsJavaTestBase { + private final File testDir = new File("compiler/testData/asJava/nullabilityAnnotations"); + + @Override + protected List getKotlinSourceRoots() { + return Collections.singletonList(new File(testDir, getTestName(false) + ".kt")); + } + + @Override + protected void extraConfiguration(@NotNull CompilerConfiguration configuration) { + configuration.add(JVMConfigurationKeys.CLASSPATH_KEY, JetTestUtils.getAnnotationsJar()); + } + + public void test_DefaultPackage() throws Exception { + doTest(getTestName(false)); + } + + public void testClass() throws Exception { + doTest(getTestName(false)); + } + + public void testTrait() throws Exception { + doTest(getTestName(false)); + } + + public void testClassWithConstructorAndProperties() throws Exception { + doTest(getTestName(false)); + } + + public void testClassWithConstructor() throws Exception { + doTest(getTestName(false)); + } + + private void doTest(@NotNull String fqName) { + PsiClass psiClass = finder.findClass(fqName, GlobalSearchScope.allScope(getProject())); + if (!(psiClass instanceof KotlinLightClass)) { + throw new IllegalStateException("Not a light class: " + psiClass); + } + + PsiClass delegate = ((KotlinLightClass) psiClass).getDelegate(); + if (!(delegate instanceof ClsElementImpl)) { + throw new IllegalStateException("Not a CLS element: " + delegate); + } + + StringBuilder buffer = new StringBuilder(); + ((ClsElementImpl) delegate).appendMirrorText(0, buffer); + String actual = buffer.toString(); + + JetTestUtils.assertEqualsToFile(new File(testDir, fqName + ".java"), actual); + } +}