diff --git a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt old mode 100644 new mode 100755 index 700169f3ced..5ea357c4aea --- a/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt +++ b/generators/src/org/jetbrains/kotlin/generators/tests/GenerateTests.kt @@ -23,6 +23,8 @@ import org.jetbrains.kotlin.addImport.AbstractAddImportTest import org.jetbrains.kotlin.android.* import org.jetbrains.kotlin.android.configure.AbstractConfigureProjectTest import org.jetbrains.kotlin.annotation.AbstractAnnotationProcessorBoxTest +import org.jetbrains.kotlin.annotation.processing.test.wrappers.AbstractJavaModelWrappersTest +import org.jetbrains.kotlin.annotation.processing.test.wrappers.AbstractKotlinModelWrappersTest import org.jetbrains.kotlin.asJava.AbstractCompilerLightClassTest import org.jetbrains.kotlin.cfg.AbstractControlFlowTest import org.jetbrains.kotlin.cfg.AbstractDataFlowTest @@ -1055,6 +1057,16 @@ fun main(args: Array) { model("collectToFile", recursive = false, extension = null) } } + + testGroup("plugins/plugins-tests/tests", "plugins/annotation-processing/testData") { + testClass() { + model("javaWrappers", extension = null) + } + + testClass() { + model("kotlinWrappers", extension = "kt") + } + } testGroup("plugins/android-extensions/android-extensions-idea/tests", "plugins/android-extensions/android-extensions-idea/testData") { testClass() { diff --git a/plugins/annotation-processing/annotation-processing.iml b/plugins/annotation-processing/annotation-processing.iml index 81a78835658..8bc37eae375 100644 --- a/plugins/annotation-processing/annotation-processing.iml +++ b/plugins/annotation-processing/annotation-processing.iml @@ -4,6 +4,7 @@ + diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt old mode 100644 new mode 100755 index 1f8bf80cdab..c2f2a9187e7 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingExtension.kt @@ -35,10 +35,21 @@ import java.net.URLClassLoader import java.util.* import javax.annotation.processing.Processor -class AnnotationProcessingExtension( +class ClasspathBasedAnnotationProcessingExtension( + val annotationProcessingClasspath: List, + generatedSourcesOutputDir: File, + classesOutputDir: File, + javaSourceRoots: List +) : AbstractAnnotationProcessingExtension(generatedSourcesOutputDir, classesOutputDir, javaSourceRoots) { + override fun loadAnnotationProcessors(): List { + val classLoader = URLClassLoader(annotationProcessingClasspath.map { File(it).toURI().toURL() }.toTypedArray()) + return ServiceLoader.load(Processor::class.java, classLoader).toList() + } +} + +abstract class AbstractAnnotationProcessingExtension( val generatedSourcesOutputDir: File, val classesOutputDir: File, - val annotationProcessingClasspath: List, val javaSourceRoots: List ) : AnalysisCompletedHandlerExtension { private var annotationProcessingComplete = false @@ -53,7 +64,7 @@ class AnnotationProcessingExtension( return null } - val processors = loadAnnotationProcessors(annotationProcessingClasspath) + val processors = loadAnnotationProcessors() if (processors.isEmpty()) return null val analysisContext = AnalysisContext(hashMapOf()) @@ -114,11 +125,8 @@ class AnnotationProcessingExtension( annotationProcessingComplete = true return AnalysisResult.RetryWithAdditionalJavaRoots(bindingContext, module, listOf(generatedSourcesOutputDir)) } - - private fun loadAnnotationProcessors(classpath: List): List { - val classLoader = URLClassLoader(classpath.map { File(it).toURI().toURL() }.toTypedArray()) - return ServiceLoader.load(Processor::class.java, classLoader).toList() - } + + protected abstract fun loadAnnotationProcessors(): List } internal class AnalysisContext(annotationsMap: MutableMap>) { diff --git a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt old mode 100644 new mode 100755 index 4016615d7b9..80823dbc538 --- a/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt +++ b/plugins/annotation-processing/src/org/jetbrains/kotlin/annotation/processing/AnnotationProcessingPlugin.kt @@ -17,7 +17,7 @@ package org.jetbrains.kotlin.annotation.processing import com.intellij.mock.MockProject -import org.jetbrains.kotlin.annotation.AnnotationProcessingExtension +import org.jetbrains.kotlin.annotation.ClasspathBasedAnnotationProcessingExtension import org.jetbrains.kotlin.compiler.plugin.CliOption import org.jetbrains.kotlin.compiler.plugin.CliOptionProcessingException import org.jetbrains.kotlin.compiler.plugin.CommandLineProcessor @@ -88,7 +88,8 @@ class AnnotationProcessingComponentRegistrar : ComponentRegistrar { val classesOutputDir = File(configuration.get(AnnotationProcessingConfigurationKeys.CLASS_FILES_OUTPUT_DIR) ?: configuration[JVMConfigurationKeys.MODULES]!!.first().getOutputDirectory()) - val annotationProcessingExtension = AnnotationProcessingExtension(generatedOutputDirFile, classesOutputDir, classpath, javaRoots) + val annotationProcessingExtension = ClasspathBasedAnnotationProcessingExtension( + classpath, generatedOutputDirFile, classesOutputDir, javaRoots) AnalysisCompletedHandlerExtension.registerExtension(project, annotationProcessingExtension) } } \ No newline at end of file diff --git a/plugins/annotation-processing/testData/elements/GetAllMembers.kt b/plugins/annotation-processing/testData/elements/GetAllMembers.kt new file mode 100644 index 00000000000..0ef9208ed64 --- /dev/null +++ b/plugins/annotation-processing/testData/elements/GetAllMembers.kt @@ -0,0 +1,8 @@ +@Deprecated("") +class MyClass { + var myProperty: String = "A" + + fun myFunction() = object : java.lang.Runnable { + override fun run() {} + } +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/elements/GetElementValuesWithDefaults.kt b/plugins/annotation-processing/testData/elements/GetElementValuesWithDefaults.kt new file mode 100644 index 00000000000..8392d49f6ba --- /dev/null +++ b/plugins/annotation-processing/testData/elements/GetElementValuesWithDefaults.kt @@ -0,0 +1,13 @@ +annotation class Anno(val name: String = "Mary", val age: Int = 20) + +@Anno("Tom", 10) +class A + +@Anno(name = "Tom") +class B + +@Anno(age = 10) +class C + +@Anno +class D \ No newline at end of file diff --git a/plugins/annotation-processing/testData/elements/GetPackageOf.kt b/plugins/annotation-processing/testData/elements/GetPackageOf.kt new file mode 100644 index 00000000000..2c5f13cf013 --- /dev/null +++ b/plugins/annotation-processing/testData/elements/GetPackageOf.kt @@ -0,0 +1,6 @@ +package test + +@Deprecated("") +class MyClass + +interface MyInterface \ No newline at end of file diff --git a/plugins/annotation-processing/testData/elements/IsDeprecated.kt b/plugins/annotation-processing/testData/elements/IsDeprecated.kt new file mode 100644 index 00000000000..9bec4cb4ab3 --- /dev/null +++ b/plugins/annotation-processing/testData/elements/IsDeprecated.kt @@ -0,0 +1,7 @@ +@Deprecated("") +class Depr + +class NoDepr + +@java.lang.Deprecated +class JavaDepr \ No newline at end of file diff --git a/plugins/annotation-processing/testData/elements/IsFunctionalInterface.kt b/plugins/annotation-processing/testData/elements/IsFunctionalInterface.kt new file mode 100644 index 00000000000..78b59ba86ae --- /dev/null +++ b/plugins/annotation-processing/testData/elements/IsFunctionalInterface.kt @@ -0,0 +1,22 @@ +class A { + interface AA { + fun onClick(o: Any) + } +} + +enum class B { RED } + +interface C { + fun onClick() +} + +interface D { + fun onClick() + fun onDoubleClick() +} + +interface E : C + +interface F : C { + fun onDoubleClick() +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/elements/Overrides.kt b/plugins/annotation-processing/testData/elements/Overrides.kt new file mode 100644 index 00000000000..a3a8b7cab9b --- /dev/null +++ b/plugins/annotation-processing/testData/elements/Overrides.kt @@ -0,0 +1,16 @@ +@Deprecated("") +open class Parent { + open fun a() {} +} + +open class Child : Parent() { + override fun a() {} + fun a(name: String) {} + open fun b() = "A" +} + +class ChildOfChild : Child() { + override fun a() {} + override fun b() = "B" + fun a(name: CharSequence) {} +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/elements/Overrides2.kt b/plugins/annotation-processing/testData/elements/Overrides2.kt new file mode 100644 index 00000000000..c3c62e5f232 --- /dev/null +++ b/plugins/annotation-processing/testData/elements/Overrides2.kt @@ -0,0 +1,12 @@ +@Deprecated("") +interface Intf { + fun a() +} + +open class A { + open fun a() {} +} + +class B : A(), Intf { + override fun a() {} +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/javaWrappers/EnumClass/EnumClass.java b/plugins/annotation-processing/testData/javaWrappers/EnumClass/EnumClass.java new file mode 100644 index 00000000000..e4c6008c13d --- /dev/null +++ b/plugins/annotation-processing/testData/javaWrappers/EnumClass/EnumClass.java @@ -0,0 +1,13 @@ +// EnumClass + +enum EnumClass { + RED, GREEN, BLUE; + + void someMethod() { + System.out.println("Hello, world!") + } + + String getStringRepresentation() { + return this.toString(); + } +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/javaWrappers/EnumClass/EnumClass.txt b/plugins/annotation-processing/testData/javaWrappers/EnumClass/EnumClass.txt new file mode 100644 index 00000000000..75d4b9ef917 --- /dev/null +++ b/plugins/annotation-processing/testData/javaWrappers/EnumClass/EnumClass.txt @@ -0,0 +1,11 @@ +final enum EnumClass { + public static final EnumClass RED + + public static final EnumClass GREEN + + public static final EnumClass BLUE + + void someMethod() + + java.lang.String getStringRepresentation() +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/javaWrappers/MetaAnnotation/MetaAnnotation.java b/plugins/annotation-processing/testData/javaWrappers/MetaAnnotation/MetaAnnotation.java new file mode 100644 index 00000000000..a97b15eab44 --- /dev/null +++ b/plugins/annotation-processing/testData/javaWrappers/MetaAnnotation/MetaAnnotation.java @@ -0,0 +1,13 @@ +// MetaAnnotation + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Deprecated +@Target({ ElementType.CONSTRUCTOR, ElementType.FIELD }) +@Retention(RetentionPolicy.RUNTIME) +public @interface MetaAnnotation { + String strValue(); +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/javaWrappers/MetaAnnotation/MetaAnnotation.txt b/plugins/annotation-processing/testData/javaWrappers/MetaAnnotation/MetaAnnotation.txt new file mode 100644 index 00000000000..653e513877d --- /dev/null +++ b/plugins/annotation-processing/testData/javaWrappers/MetaAnnotation/MetaAnnotation.txt @@ -0,0 +1,6 @@ +@java.lang.Deprecated +@java.lang.annotation.Target(value = { CONSTRUCTOR, FIELD }) +@java.lang.annotation.Retention(value = RUNTIME) +public abstract @interface MetaAnnotation { + public abstract java.lang.String strValue() +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/javaWrappers/Simple/Simple.java b/plugins/annotation-processing/testData/javaWrappers/Simple/Simple.java new file mode 100644 index 00000000000..81d1343dee8 --- /dev/null +++ b/plugins/annotation-processing/testData/javaWrappers/Simple/Simple.java @@ -0,0 +1,20 @@ +// Simple + +@KotlinAnnotation(a = "A", b = 5) +public abstract class Simple { + final String field = "A"; + + abstract void voidMethod(); + + static { + System.out.println("A"); + } + + { + System.out.println("b"); + } + + protected String strMethod(int param) { + return "A"; + } +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/javaWrappers/Simple/Simple.txt b/plugins/annotation-processing/testData/javaWrappers/Simple/Simple.txt new file mode 100644 index 00000000000..bdb1f5d399f --- /dev/null +++ b/plugins/annotation-processing/testData/javaWrappers/Simple/Simple.txt @@ -0,0 +1,12 @@ +@KotlinAnnotation(a = "A", b = 5) +public abstract class Simple { + static {} + + {} + + final java.lang.String field + + abstract void voidMethod() + + protected java.lang.String strMethod(int param) +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/javaWrappers/WithNested/WithNested.java b/plugins/annotation-processing/testData/javaWrappers/WithNested/WithNested.java new file mode 100644 index 00000000000..52089063e52 --- /dev/null +++ b/plugins/annotation-processing/testData/javaWrappers/WithNested/WithNested.java @@ -0,0 +1,21 @@ +// WithNested + +class WithNested { + void myClassFun() {} + + static class NestedClass { + void nestedClassFun() {} + } + + class InnerClass { + void innerClassFun() {} + + class InnerInnerClass { + void innerInnerClassFun() {} + } + } + + interface NestedInterface { + void nestedInterfaceFun() {} + } +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/javaWrappers/WithNested/WithNested.txt b/plugins/annotation-processing/testData/javaWrappers/WithNested/WithNested.txt new file mode 100644 index 00000000000..4701d212eb0 --- /dev/null +++ b/plugins/annotation-processing/testData/javaWrappers/WithNested/WithNested.txt @@ -0,0 +1,19 @@ +class WithNested { + void myClassFun() + + static class NestedClass { + void nestedClassFun() + } + + class InnerClass { + void innerClassFun() + + class InnerInnerClass { + void innerInnerClassFun() + } + } + + static abstract interface NestedInterface { + public abstract void nestedInterfaceFun() + } +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/javaWrappers/common.kt b/plugins/annotation-processing/testData/javaWrappers/common.kt new file mode 100644 index 00000000000..811fd455b8d --- /dev/null +++ b/plugins/annotation-processing/testData/javaWrappers/common.kt @@ -0,0 +1 @@ +annotation class KotlinAnnotation(val a: String, val b: Int) \ No newline at end of file diff --git a/plugins/annotation-processing/testData/kotlinWrappers/annotations.kt b/plugins/annotation-processing/testData/kotlinWrappers/annotations.kt new file mode 100644 index 00000000000..bfa54ceee0a --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/annotations.kt @@ -0,0 +1,31 @@ +// test.Main + +package test + +@MainAnno("A", 5) +class Main { + @field:XAnno(color = Color.GREEN) + val x: String + + @get:YAnno(arrayOf("Mary", "Tom"), intArrayOf(1, 3, 5), arrayOf(Color.GREEN, Color.RED)) + val y: String + + @set:ZAnno(String::class, arrayOf(String::class, Long::class, Main::class)) + var z: String + + // Property annotations are lost here (we don't create Elements (javac API) for the synthetic propertyName$annotations() methods) + @MainAnno("B", 6) + val zz: String +} + +enum class Color { + RED, GREEN, BLUE +} + +annotation class MainAnno(val a: String, val b: Int) + +annotation class XAnno(val color: Color) + +annotation class YAnno(val names: Array, val ints: Array, val colors: Array) + +annotation class ZAnno(val clazz: Class<*>, val classes = Array>) \ No newline at end of file diff --git a/plugins/annotation-processing/testData/kotlinWrappers/annotations.txt b/plugins/annotation-processing/testData/kotlinWrappers/annotations.txt new file mode 100644 index 00000000000..f8eb0aa57f6 --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/annotations.txt @@ -0,0 +1,33 @@ +@test.MainAnno(a = "A", b = 5) +public final class Main { + @test.XAnno(color = GREEN) + @org.jetbrains.annotations.NotNull + private final java.lang.String x + + @org.jetbrains.annotations.NotNull + private final java.lang.String y + + @org.jetbrains.annotations.NotNull + private java.lang.String z + + @org.jetbrains.annotations.NotNull + private final java.lang.String zz + + @org.jetbrains.annotations.NotNull + public final java.lang.String getX() + + @test.YAnno(names = { "Mary", "Tom" }, ints = { 1, 3, 5 }, colors = { GREEN, RED }) + @org.jetbrains.annotations.NotNull + public final java.lang.String getY() + + @org.jetbrains.annotations.NotNull + public final java.lang.String getZ() + + @test.ZAnno(clazz = java.lang.String.class, classes = { java.lang.String.class, long.class, test.Main.class }) + public final void setZ(java.lang.String p) + + @org.jetbrains.annotations.NotNull + public final java.lang.String getZz() + + public void () +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/kotlinWrappers/enum.kt b/plugins/annotation-processing/testData/kotlinWrappers/enum.kt new file mode 100644 index 00000000000..a9bfad046ed --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/enum.kt @@ -0,0 +1,11 @@ +// EnumClass + +enum class EnumClass { + RED, GREEN, BLUE; + + fun someFun() { + System.out.println("Hello, world!") + } + + fun stringRepresentation() = this.toString() +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/kotlinWrappers/enum.txt b/plugins/annotation-processing/testData/kotlinWrappers/enum.txt new file mode 100644 index 00000000000..449b5b0641b --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/enum.txt @@ -0,0 +1,14 @@ +public enum EnumClass { + public static final EnumClass RED + + public static final EnumClass GREEN + + public static final EnumClass BLUE + + public final void someFun() + + @org.jetbrains.annotations.NotNull + public final java.lang.String stringRepresentation() + + protected void () +} diff --git a/plugins/annotation-processing/testData/kotlinWrappers/metaAnnotations.kt b/plugins/annotation-processing/testData/kotlinWrappers/metaAnnotations.kt new file mode 100644 index 00000000000..67dd760f843 --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/metaAnnotations.kt @@ -0,0 +1,7 @@ +// Anno + +@Repeatable +@Deprecated +@Retention(AnnotationRetention.RUNTIME) +@Target(AnnotationTarget.CLASS, AnnotationTarget.CONSTRUCTOR, AnnotationTarget.EXPRESSION) +annotation class Anno \ No newline at end of file diff --git a/plugins/annotation-processing/testData/kotlinWrappers/metaAnnotations.txt b/plugins/annotation-processing/testData/kotlinWrappers/metaAnnotations.txt new file mode 100644 index 00000000000..cdf362487e2 --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/metaAnnotations.txt @@ -0,0 +1,9 @@ +@kotlin.annotation.Repeatable +@kotlin.Deprecated +@kotlin.annotation.Retention(value = RUNTIME) +@kotlin.annotation.Target(allowedTargets = { CLASS, CONSTRUCTOR, EXPRESSION }) +@java.lang.annotation.Retention(value = RUNTIME) +@java.lang.annotation.Target(value = { TYPE, CONSTRUCTOR }) +public abstract @interface Anno { + +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/kotlinWrappers/nestedClasses.kt b/plugins/annotation-processing/testData/kotlinWrappers/nestedClasses.kt new file mode 100644 index 00000000000..80bca69fc9d --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/nestedClasses.kt @@ -0,0 +1,30 @@ +// MyClass + +class MyClass { + companion object { + val CONST = 2 + } + + fun myClassFun() {} + + class NestedClass { + companion object A { + val CONSTA = 3 + } + + fun nestedClassFun() {} + + class NestedNestedClass { + fun nestedNestedClassFun() {} + } + } + + inner class InnerClass { + fun innerClassFun() {} + } + + interface InnerInterface { + fun innerInterfaceFun() + fun innerInterfaceFunWithImpl() = 5 + } +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/kotlinWrappers/nestedClasses.txt b/plugins/annotation-processing/testData/kotlinWrappers/nestedClasses.txt new file mode 100644 index 00000000000..0f0ce5534cd --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/nestedClasses.txt @@ -0,0 +1,53 @@ +public final class MyClass { + private static final int CONST + + public static final MyClass.Companion Companion + + public final void myClassFun() + + public void () + + public static final class Companion { + public final int getCONST() + + private void () + } + + public static final class NestedClass { + private static final int CONSTA + + public static final MyClass.NestedClass.A A + + public final void nestedClassFun() + + public void () + + public static final class A { + public final int getCONSTA() + + private void () + } + + public static final class NestedNestedClass { + public final void nestedNestedClassFun() + + public void () + } + } + + public final class InnerClass { + public final void innerClassFun() + + public void () + } + + public static abstract interface InnerInterface { + public abstract void innerInterfaceFun() + + public abstract int innerInterfaceFunWithImpl() + + public static final class DefaultImpls { + public static int innerInterfaceFunWithImpl(MyClass.InnerInterface $this) + } + } +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/kotlinWrappers/repeatableAnnotations.kt b/plugins/annotation-processing/testData/kotlinWrappers/repeatableAnnotations.kt new file mode 100644 index 00000000000..0fa9291edb5 --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/repeatableAnnotations.kt @@ -0,0 +1,8 @@ +// MyClass + +@Repeatable +annotation class Anno(val name: String) + +@Anno("Mary") +@Anno("Tom") +class MyClass \ No newline at end of file diff --git a/plugins/annotation-processing/testData/kotlinWrappers/repeatableAnnotations.txt b/plugins/annotation-processing/testData/kotlinWrappers/repeatableAnnotations.txt new file mode 100644 index 00000000000..b2614274855 --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/repeatableAnnotations.txt @@ -0,0 +1,5 @@ +@Anno(name = "Mary") +@Anno(name = "Tom") +public final class MyClass { + public void () +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/kotlinWrappers/simple.kt b/plugins/annotation-processing/testData/kotlinWrappers/simple.kt new file mode 100644 index 00000000000..959cbb2ccde --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/simple.kt @@ -0,0 +1,10 @@ +// test.Simple + +package test + +abstract class Simple(private val prop: String) { + protected val anotherProp: Int = 5 + + abstract fun strFun(val x: Long): String + fun voidFun() {} +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/kotlinWrappers/simple.txt b/plugins/annotation-processing/testData/kotlinWrappers/simple.txt new file mode 100644 index 00000000000..2625f57ea62 --- /dev/null +++ b/plugins/annotation-processing/testData/kotlinWrappers/simple.txt @@ -0,0 +1,14 @@ +public abstract class Simple { + private final int anotherProp + + private final java.lang.String prop + + protected final int getAnotherProp() + + @org.jetbrains.annotations.NotNull + public abstract java.lang.String strFun(long x) + + public final void voidFun() + + public void (java.lang.String prop) +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/processors/DoesNotRun.kt b/plugins/annotation-processing/testData/processors/DoesNotRun.kt new file mode 100644 index 00000000000..f7e70c7b871 --- /dev/null +++ b/plugins/annotation-processing/testData/processors/DoesNotRun.kt @@ -0,0 +1 @@ +class Test \ No newline at end of file diff --git a/plugins/annotation-processing/testData/processors/DoesNotRun2.kt b/plugins/annotation-processing/testData/processors/DoesNotRun2.kt new file mode 100644 index 00000000000..0eced4f6f64 --- /dev/null +++ b/plugins/annotation-processing/testData/processors/DoesNotRun2.kt @@ -0,0 +1,3 @@ +class Test + +annotation class Anno \ No newline at end of file diff --git a/plugins/annotation-processing/testData/processors/SeveralAnnotations.kt b/plugins/annotation-processing/testData/processors/SeveralAnnotations.kt new file mode 100644 index 00000000000..d7649390ebd --- /dev/null +++ b/plugins/annotation-processing/testData/processors/SeveralAnnotations.kt @@ -0,0 +1,11 @@ + +@Name("Mary") +@Age(18) +class Mary + +@Name("Kate") +@Age(22) +class Kate + +annotation class Name(val name: String) +annotation class Age(val age: Int) \ No newline at end of file diff --git a/plugins/annotation-processing/testData/processors/Simple.kt b/plugins/annotation-processing/testData/processors/Simple.kt new file mode 100644 index 00000000000..19a6070bf17 --- /dev/null +++ b/plugins/annotation-processing/testData/processors/Simple.kt @@ -0,0 +1,10 @@ +annotation class Anno(val name: String) + +@Anno("MyClassAnno") +class MyClass { + @Anno("myFuncAnno") + fun myFunc(): String = "Mary" + + @field:Anno("myFieldAnno") + val myField: String = "Tom" +} \ No newline at end of file diff --git a/plugins/annotation-processing/testData/processors/Star.kt b/plugins/annotation-processing/testData/processors/Star.kt new file mode 100644 index 00000000000..8a3e7756f0b --- /dev/null +++ b/plugins/annotation-processing/testData/processors/Star.kt @@ -0,0 +1,4 @@ +@Anno +class MyClass + +annotation class Anno \ No newline at end of file diff --git a/plugins/annotation-processing/testData/processors/Star3.kt b/plugins/annotation-processing/testData/processors/Star3.kt new file mode 100644 index 00000000000..3fdcd9aa6e9 --- /dev/null +++ b/plugins/annotation-processing/testData/processors/Star3.kt @@ -0,0 +1,5 @@ +@Anno2 +class MyClass + +annotation class Anno +annotation class Anno2 \ No newline at end of file diff --git a/plugins/plugins-tests/plugins-tests.iml b/plugins/plugins-tests/plugins-tests.iml old mode 100644 new mode 100755 index a8854bd30a0..b4f442f1860 --- a/plugins/plugins-tests/plugins-tests.iml +++ b/plugins/plugins-tests/plugins-tests.iml @@ -30,5 +30,10 @@ + + + + + \ No newline at end of file diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt new file mode 100755 index 00000000000..1399dfec5b5 --- /dev/null +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/AbstractProcessorTest.kt @@ -0,0 +1,152 @@ +/* + * Copyright 2010-2016 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.kotlin.annotation.processing.test.processor + +import org.jetbrains.kotlin.annotation.AbstractAnnotationProcessingExtension +import org.jetbrains.kotlin.cli.jvm.compiler.EnvironmentConfigFiles +import org.jetbrains.kotlin.cli.jvm.compiler.KotlinCoreEnvironment +import org.jetbrains.kotlin.codegen.AbstractBytecodeTextTest +import org.jetbrains.kotlin.codegen.CodegenTestUtil +import org.jetbrains.kotlin.java.model.JeName +import org.jetbrains.kotlin.java.model.elements.JeAnnotationMirror +import org.jetbrains.kotlin.java.model.elements.JeMethodExecutableElement +import org.jetbrains.kotlin.java.model.elements.JeTypeElement +import org.jetbrains.kotlin.resolve.jvm.extensions.AnalysisCompletedHandlerExtension +import org.jetbrains.kotlin.test.ConfigurationKind +import org.jetbrains.kotlin.test.KotlinTestUtils +import org.jetbrains.kotlin.test.TestJdkKind +import java.io.File +import java.nio.file.Files +import javax.annotation.processing.Completion +import javax.annotation.processing.ProcessingEnvironment +import javax.annotation.processing.Processor +import javax.annotation.processing.RoundEnvironment +import javax.lang.model.SourceVersion +import javax.lang.model.element.* + +class AnnotationProcessingExtensionForTests( + val processors: List +) : AbstractAnnotationProcessingExtension(createTempDir(), createTempDir(), listOf()) { + override fun loadAnnotationProcessors() = processors + + private companion object { + fun createTempDir(): File = Files.createTempDirectory("ap-test").toFile().apply { + deleteOnExit() + } + } +} + +abstract class AbstractProcessorTest : AbstractBytecodeTextTest() { + abstract val testDataDir: String + + private fun createTestEnvironment(processors: List): KotlinCoreEnvironment { + val configuration = KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.MOCK_JDK) + val environment = KotlinCoreEnvironment.createForTests(testRootDisposable, configuration, EnvironmentConfigFiles.JVM_CONFIG_FILES) + val project = environment.project + + val apExtension = AnnotationProcessingExtensionForTests(processors) + AnalysisCompletedHandlerExtension.registerExtension(project, apExtension) + + return environment + } + + fun doTest(path: String, processors: List) { + myEnvironment = createTestEnvironment(processors) + + loadFileByFullPath(path) + CodegenTestUtil.generateFiles(myEnvironment, myFiles) + } + + protected fun Element.assertHasAnnotation(fqName: String, vararg parameterValues: Any?) { + val annotation = annotationMirrors.first { it is JeAnnotationMirror && it.psi.qualifiedName == fqName } + val actualValues = annotation.elementValues.values + assertEquals(parameterValues.size, actualValues.size) + + for ((expected, actual) in parameterValues.zip(actualValues)) { + assertEquals(expected, actual.value) + } + } + + protected fun test( + name: String, + vararg supportedAnnotations: String, + process: (Set, RoundEnvironment, ProcessingEnvironment) -> Unit + ) = testAP(true, name, process, *supportedAnnotations) + + protected fun testShouldNotRun( + name: String, + vararg supportedAnnotations: String + ) = testAP(false, name, { set, roundEnv, env -> fail("Should not run") }, *supportedAnnotations) + + private fun testAP( + shouldRun: Boolean, + name: String, + process: (Set, RoundEnvironment, ProcessingEnvironment) -> Unit, + vararg supportedAnnotations: String + ) { + val ktFileName = File(testDataDir, name + ".kt") + var started = false + val processor = object : Processor { + lateinit var processingEnv: ProcessingEnvironment + + override fun getSupportedOptions() = setOf() + + override fun process(annotations: Set, roundEnv: RoundEnvironment): Boolean { + if (!roundEnv.processingOver()) { + started = true + process(annotations, roundEnv, processingEnv) + } + return true + } + + override fun init(env: ProcessingEnvironment) { + processingEnv = env + } + + override fun getCompletions( + element: Element?, + annotation: AnnotationMirror?, + member: ExecutableElement?, + userText: String? + ): Iterable? { + return emptyList() + } + + override fun getSupportedSourceVersion() = SourceVersion.RELEASE_6 + override fun getSupportedAnnotationTypes() = supportedAnnotations.toSet() + } + + doTest(ktFileName.canonicalPath, listOf(processor)) + + if (started != shouldRun) { + fail("Annotation processor " + (if (shouldRun) "was not started" else "was started")) + } + } + + protected fun TypeElement.findMethod(name: String, vararg parameterTypes: String): JeMethodExecutableElement { + return enclosedElements.first { + if (it !is JeMethodExecutableElement + || it.simpleName.toString() != name + || parameterTypes.size != it.parameters.size) return@first false + parameterTypes.zip(it.parameters).all { it.first == it.second.asType().toString() } + } as JeMethodExecutableElement + } + + protected fun ProcessingEnvironment.findClass(fqName: String) = elementUtils.getTypeElement(fqName) as JeTypeElement + + protected fun assertEquals(expected: String, actual: Name) = assertEquals(expected, actual.toString()) +} \ No newline at end of file diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ElementsTests.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ElementsTests.kt new file mode 100644 index 00000000000..bb91074e813 --- /dev/null +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ElementsTests.kt @@ -0,0 +1,131 @@ +/* + * Copyright 2010-2016 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.kotlin.annotation.processing.test.processor + +import org.jetbrains.kotlin.annotation.processing.impl.KotlinElements +import org.jetbrains.kotlin.java.model.elements.JeTypeElement +import javax.lang.model.element.ExecutableElement +import javax.lang.model.element.TypeElement + +class ElementsTests : AbstractProcessorTest() { + override val testDataDir = "plugins/annotation-processing/testData/elements" + + fun testOverrides() = test("Overrides", "*") { set, roundEnv, env -> + val (parent, child, childChild) = Triple(env.findClass("Parent"), env.findClass("Child"), env.findClass("ChildOfChild")) + + val parentA = parent.findMethod("a") + + val childA = child.findMethod("a") + val childAString = child.findMethod("a", "java.lang.String") + val childB = child.findMethod("b") + + val childChildA = childChild.findMethod("a") + val childChildACharSequence = childChild.findMethod("a", "java.lang.CharSequence") + val childChildB = childChild.findMethod("b") + + fun ExecutableElement.assertOverrides(overridden: ExecutableElement, result: Boolean) { + assertEquals(result, env.elementUtils.overrides(this, overridden, enclosingElement as JeTypeElement)) + } + + parentA.assertOverrides(parentA, false) + childA.assertOverrides(parentA, true) + childAString.assertOverrides(childA, false) + childB.assertOverrides(parentA, false) + childChildA.assertOverrides(parentA, true) + childChildA.assertOverrides(childA, true) + childChildB.assertOverrides(childB, true) + childChildACharSequence.assertOverrides(childA, false) + } + + fun testOverrides2() = test("Overrides2", "*") { set, roundEnv, env -> + val classes = listOf(env.findClass("Intf"), env.findClass("A"), env.findClass("B")) + val (intf, a, b) = classes.map { it.findMethod("a") } + + fun ExecutableElement.assertOverrides(overridden: ExecutableElement, context: TypeElement, result: Boolean) { + assertEquals(result, env.elementUtils.overrides(this, overridden, context)) + } + + a.assertOverrides(intf, classes[1], false) + b.assertOverrides(a, classes[2], true) + b.assertOverrides(intf, classes[2], true) + a.assertOverrides(intf, classes[2], true) + } + + fun testIsFunctionalInterface() = test("IsFunctionalInterface", "*") { set, roundEnv, env -> + with (env.elementUtils as KotlinElements) { + fun assertIsFunctionalInterface(fqName: String, isIntf: Boolean) { + assertEquals(isIntf, isFunctionalInterface(env.findClass(fqName))) + } + + assertIsFunctionalInterface("A", false) + assertIsFunctionalInterface("A.AA", true) + assertIsFunctionalInterface("B", false) + assertIsFunctionalInterface("C", true) + assertIsFunctionalInterface("D", false) + assertIsFunctionalInterface("E", true) + assertIsFunctionalInterface("F", false) + } + } + + fun testIsDeprecated() = test("IsDeprecated", "*") { set, roundEnv, env -> + with (env.elementUtils) { + assertEquals(true, isDeprecated(env.findClass("Depr"))) + assertEquals(false, isDeprecated(env.findClass("NoDepr"))) + assertEquals(true, isDeprecated(env.findClass("JavaDepr"))) + } + } + + fun testGetElementValuesWithDefaults() = test("GetElementValuesWithDefaults", "Anno") { set, roundEnv, env -> + val (a, b, c, d) = listOf(env.findClass("A"), env.findClass("B"), env.findClass("C"), env.findClass("D")) + fun getValues(e: JeTypeElement) = env.elementUtils + .getElementValuesWithDefaults(e.annotationMirrors.first { it.psi.qualifiedName == "Anno" }) + .values.map { it.value } + + assertEquals(listOf("Tom", 10), getValues(a)) + assertEquals(listOf("Tom", 20), getValues(b)) + assertEquals(listOf("Mary", 10), getValues(c)) + assertEquals(listOf("Mary", 20), getValues(d)) + } + + fun testGetAllMembers() = test("GetAllMembers", "*") { set, roundEnv, env -> + val clazz = env.findClass("MyClass") + val members = clazz.enclosedElements + assertEquals(5, members.size) // constructor, field, getter/setter, arbitrary method + + val allMembers = env.elementUtils.getAllMembers(clazz) + assertEquals(17, allMembers.size) + assertEquals(", clone, equals, finalize, getClass, getMyProperty, hashCode, myFunction, myProperty, " + + "notify, notifyAll, registerNatives, setMyProperty, toString, wait, wait, wait", + allMembers.sortedBy { it.simpleName.toString() }.joinToString { it.simpleName }) + } + + fun testGetPackageOf() = test("GetPackageOf", "*") { set, roundEnv, env -> + val e = env.elementUtils + + val myClass = env.findClass("test.MyClass") + val packageElement = e.getPackageOf(myClass) + assertEquals("test", packageElement.qualifiedName) + assertEquals(packageElement, e.getPackageOf(packageElement)) + + assertNull(e.getPackageElement("SomethingStrange")) + val testPackageElement = e.getPackageElement("test") + assertEquals(packageElement, testPackageElement) + assertFalse(packageElement.isUnnamed) + val classes = packageElement.enclosedElements.filterIsInstance() + assertEquals(2, classes.size) + } +} \ No newline at end of file diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt new file mode 100644 index 00000000000..b5d4ea1d366 --- /dev/null +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/processor/ProcessorTests.kt @@ -0,0 +1,75 @@ +/* + * Copyright 2010-2016 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.kotlin.annotation.processing.test.processor + +import org.jetbrains.kotlin.java.model.elements.JeMethodExecutableElement +import org.jetbrains.kotlin.java.model.elements.JeTypeElement +import org.jetbrains.kotlin.java.model.elements.JeVariableElement +import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance + +class ProcessorTests : AbstractProcessorTest() { + override val testDataDir = "plugins/annotation-processing/testData/processors" + + fun testSimple() = test("Simple", "Anno") { set, roundEnv, env -> + assertEquals(1, set.size) + val annotated = roundEnv.getElementsAnnotatedWith(set.first()) + assertEquals(3, annotated.size) + + val clazz = annotated.firstIsInstance() + val method = annotated.firstIsInstance() + val field = annotated.firstIsInstance() + + listOf(clazz, method, field).forEach { + it.assertHasAnnotation("Anno", it.simpleName.toString() + "Anno") + } + } + + fun testSeveralAnnotations() = test("SeveralAnnotations", "Name", "Age") { set, roundEnv, env -> + val annos = set.toList() + + assertEquals(2, annos.size) + val annotated1 = roundEnv.getElementsAnnotatedWith(annos[0]).sortedBy { it.simpleName.toString() } + val annotated2 = roundEnv.getElementsAnnotatedWith(annos[1]).sortedBy { it.simpleName.toString() } + assertEquals(2, annotated1.size) + assertEquals(annotated1, annotated2) + + val (kate, mary) = Pair(annotated1[0] as JeTypeElement, annotated1[1] as JeTypeElement) + assertEquals("Mary", mary.simpleName) + with (kate) { + assertEquals("Kate", simpleName) + assertHasAnnotation("Name", "Kate") + assertHasAnnotation("Age", 22) + } + } + + fun testStar() = test("Star", "*") { set, roundEnv, env -> + assertEquals(true, set.any { it.qualifiedName.toString() == "Anno" }) + } + + fun testStar2() = test("Star", "Anno", "*") { set, roundEnv, env -> + assertEquals(true, set.any { it.qualifiedName.toString() == "Anno" }) + } + + fun testStar3() = test("Star3", "Anno", "*") { set, roundEnv, env -> + assertEquals(true, set.any { it.qualifiedName.toString() == "Anno2" }) + } + + fun testDoesNotRun() = testShouldNotRun("DoesNotRun", "Anno") + fun testDoesNotRun2() = testShouldNotRun("DoesNotRun2", "Anno") +} + + diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractJavaAnnotationProcessingTest.java b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractJavaAnnotationProcessingTest.java new file mode 100755 index 00000000000..42165b9c270 --- /dev/null +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractJavaAnnotationProcessingTest.java @@ -0,0 +1,66 @@ +/* + * Copyright 2010-2016 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.kotlin.annotation.processing.test.wrappers; + +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; +import com.intellij.psi.search.GlobalSearchScope; +import junit.framework.TestCase; +import org.jetbrains.kotlin.asJava.AbstractCompilerLightClassTest; +import org.jetbrains.kotlin.cli.jvm.config.JavaSourceRoot; +import org.jetbrains.kotlin.test.KotlinTestUtils; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public abstract class AbstractJavaAnnotationProcessingTest extends AbstractCompilerLightClassTest { + private final static Pattern SUBJECT_FQ_NAME_PATTERN = Pattern.compile("^//\\s*(.*)$", Pattern.MULTILINE); + + @Override + protected void doTest(String testDirPath) throws Exception { + File testDir = new File(testDirPath); + File javaFile = new File(testDirPath, testDir.getName() + ".java"); + + String text = FileUtil.loadFile(javaFile, true); + Matcher matcher = SUBJECT_FQ_NAME_PATTERN.matcher(text); + TestCase.assertTrue("No FqName specified. First line of the form '// f.q.Name' expected", matcher.find()); + String fqName = matcher.group(1); + + getEnvironment().updateClasspath(Collections.singletonList(testDir)); + + super.doTest(new File(testDir.getParentFile(), "common.kt").getCanonicalPath()); + + KotlinTestUtils.resolveAllKotlinFiles(getEnvironment()); + Project project = getEnvironment().getProject(); + + PsiClass javaClass = JavaPsiFacade.getInstance(project).findClass(fqName, GlobalSearchScope.allScope(project)); + TestCase.assertNotNull("Class $fqName was not found.", javaClass != null); + doTest(javaFile, javaClass); + } + + @Override + protected void doMultiFileTest(File testDataFile, Map modules, List files) throws IOException {} + + protected abstract void doTest(File testDataFile, PsiClass lightClass); +} \ No newline at end of file diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractKotlinAnnotationProcessingTest.java b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractKotlinAnnotationProcessingTest.java new file mode 100755 index 00000000000..2a1108e87fe --- /dev/null +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractKotlinAnnotationProcessingTest.java @@ -0,0 +1,56 @@ +/* + * Copyright 2010-2016 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.kotlin.annotation.processing.test.wrappers; + +import com.intellij.openapi.util.io.FileUtil; +import com.intellij.psi.PsiClass; +import com.intellij.psi.search.GlobalSearchScope; +import org.jetbrains.kotlin.asJava.AbstractCompilerLightClassTest; +import org.jetbrains.kotlin.utils.ExceptionUtilsKt; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public abstract class AbstractKotlinAnnotationProcessingTest extends AbstractCompilerLightClassTest { + private final static Pattern SUBJECT_FQ_NAME_PATTERN = Pattern.compile("^//\\s*(.*)$", Pattern.MULTILINE); + + @Override + protected void doMultiFileTest(File testDataFile, Map modules, List files) throws IOException { + String text = FileUtil.loadFile(testDataFile, true); + Matcher matcher = SUBJECT_FQ_NAME_PATTERN.matcher(text); + assertTrue("No FqName specified. First line of the form '// f.q.Name' expected", matcher.find()); + String fqName = matcher.group(1); + + PsiClass lightClass = findLightClass(fqName); + doTest(testDataFile, lightClass); + } + + protected abstract void doTest(File testDataFile, PsiClass lightClass); + + private PsiClass findLightClass(String fqName) { + try { + return createFinder(getEnvironment()).findClass(fqName, GlobalSearchScope.allScope(getEnvironment().getProject())); + } + catch (IOException e) { + throw ExceptionUtilsKt.rethrow(e); + } + } +} diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractKotlinModelWrappersTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractKotlinModelWrappersTest.kt new file mode 100755 index 00000000000..facffd53854 --- /dev/null +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/AbstractKotlinModelWrappersTest.kt @@ -0,0 +1,39 @@ +/* + * Copyright 2010-2016 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.kotlin.annotation.processing.test.wrappers + +import com.intellij.psi.PsiClass +import org.jetbrains.kotlin.java.model.elements.DefaultJeElementRenderer +import org.jetbrains.kotlin.java.model.toJeElement +import org.jetbrains.kotlin.test.KotlinTestUtils +import java.io.File + +private val RENDERER = DefaultJeElementRenderer() + +private fun runTest(testDataFile: File, lightClass: PsiClass) { + val modelFile = File(testDataFile.parent, testDataFile.nameWithoutExtension + ".txt") + val jeElement = lightClass.toJeElement() ?: error("JeElement is null") + KotlinTestUtils.assertEqualsToFile(modelFile, RENDERER.render(jeElement)) +} + +abstract class AbstractKotlinModelWrappersTest : AbstractKotlinAnnotationProcessingTest() { + override fun doTest(testDataFile: File, lightClass: PsiClass) = runTest(testDataFile, lightClass) +} + +abstract class AbstractJavaModelWrappersTest : AbstractJavaAnnotationProcessingTest() { + override fun doTest(testDataFile: File, lightClass: PsiClass) = runTest(testDataFile, lightClass) +} \ No newline at end of file diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/JavaModelWrappersTestGenerated.java b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/JavaModelWrappersTestGenerated.java new file mode 100644 index 00000000000..bc2ce9790d0 --- /dev/null +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/JavaModelWrappersTestGenerated.java @@ -0,0 +1,62 @@ +/* + * Copyright 2010-2016 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.kotlin.annotation.processing.test.wrappers; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("plugins/annotation-processing/testData/javaWrappers") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class JavaModelWrappersTestGenerated extends AbstractJavaModelWrappersTest { + public void testAllFilesPresentInJavaWrappers() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("plugins/annotation-processing/testData/javaWrappers"), Pattern.compile("^([^\\.]+)$"), true); + } + + @TestMetadata("EnumClass") + public void testEnumClass() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/annotation-processing/testData/javaWrappers/EnumClass/"); + doTest(fileName); + } + + @TestMetadata("MetaAnnotation") + public void testMetaAnnotation() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/annotation-processing/testData/javaWrappers/MetaAnnotation/"); + doTest(fileName); + } + + @TestMetadata("Simple") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/annotation-processing/testData/javaWrappers/Simple/"); + doTest(fileName); + } + + @TestMetadata("WithNested") + public void testWithNested() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/annotation-processing/testData/javaWrappers/WithNested/"); + doTest(fileName); + } + +} diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/KotlinModelWrappersTestGenerated.java b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/KotlinModelWrappersTestGenerated.java new file mode 100644 index 00000000000..56440ca9519 --- /dev/null +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/annotation/processing/test/wrappers/KotlinModelWrappersTestGenerated.java @@ -0,0 +1,73 @@ +/* + * Copyright 2010-2016 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.kotlin.annotation.processing.test.wrappers; + +import com.intellij.testFramework.TestDataPath; +import org.jetbrains.kotlin.test.JUnit3RunnerWithInners; +import org.jetbrains.kotlin.test.KotlinTestUtils; +import org.jetbrains.kotlin.test.TestMetadata; +import org.junit.runner.RunWith; + +import java.io.File; +import java.util.regex.Pattern; + +/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */ +@SuppressWarnings("all") +@TestMetadata("plugins/annotation-processing/testData/kotlinWrappers") +@TestDataPath("$PROJECT_ROOT") +@RunWith(JUnit3RunnerWithInners.class) +public class KotlinModelWrappersTestGenerated extends AbstractKotlinModelWrappersTest { + public void testAllFilesPresentInKotlinWrappers() throws Exception { + KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("plugins/annotation-processing/testData/kotlinWrappers"), Pattern.compile("^(.+)\\.kt$"), true); + } + + @TestMetadata("annotations.kt") + public void testAnnotations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/annotation-processing/testData/kotlinWrappers/annotations.kt"); + doTest(fileName); + } + + @TestMetadata("enum.kt") + public void testEnum() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/annotation-processing/testData/kotlinWrappers/enum.kt"); + doTest(fileName); + } + + @TestMetadata("metaAnnotations.kt") + public void testMetaAnnotations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/annotation-processing/testData/kotlinWrappers/metaAnnotations.kt"); + doTest(fileName); + } + + @TestMetadata("nestedClasses.kt") + public void testNestedClasses() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/annotation-processing/testData/kotlinWrappers/nestedClasses.kt"); + doTest(fileName); + } + + @TestMetadata("repeatableAnnotations.kt") + public void testRepeatableAnnotations() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/annotation-processing/testData/kotlinWrappers/repeatableAnnotations.kt"); + doTest(fileName); + } + + @TestMetadata("simple.kt") + public void testSimple() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("plugins/annotation-processing/testData/kotlinWrappers/simple.kt"); + doTest(fileName); + } +} diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidBoxTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidBoxTest.kt old mode 100644 new mode 100755 index 461049cfc4e..6fe96740402 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidBoxTest.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidBoxTest.kt @@ -41,7 +41,7 @@ abstract class AbstractAndroidBoxTest : AbstractBlackBoxCodegenTest() { private fun createEnvironmentForConfiguration(configuration: CompilerConfiguration, path: String) { val layoutPaths = File(path).listFiles { it -> it.name.startsWith("layout") && it.isDirectory }!!.map { "$path${it.name}/" } - myEnvironment = createAndroidTestEnvironment(configuration, layoutPaths) + myEnvironment = createTestEnvironment(configuration, layoutPaths) } fun doCompileAgainstAndroidSdkTest(path: String) { diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidBytecodeShapeTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidBytecodeShapeTest.kt old mode 100644 new mode 100755 index 16ae189e318..fa432986322 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidBytecodeShapeTest.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidBytecodeShapeTest.kt @@ -30,7 +30,7 @@ abstract class AbstractAndroidBytecodeShapeTest : AbstractBytecodeTextTest() { private fun createEnvironmentForConfiguration(configuration: CompilerConfiguration, path: String) { val layoutPaths = getResPaths(path) - myEnvironment = createAndroidTestEnvironment(configuration, layoutPaths) + myEnvironment = createTestEnvironment(configuration, layoutPaths) } override fun doTest(path: String) { diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidSyntheticPropertyDescriptorTest.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidSyntheticPropertyDescriptorTest.kt old mode 100644 new mode 100755 index ef962577989..43607563ab8 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidSyntheticPropertyDescriptorTest.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/AbstractAndroidSyntheticPropertyDescriptorTest.kt @@ -32,7 +32,7 @@ import java.io.File abstract class AbstractAndroidSyntheticPropertyDescriptorTest : KtUsefulTestCase() { fun doTest(path: String) { val config = KotlinTestUtils.newConfiguration(ConfigurationKind.ALL, TestJdkKind.ANDROID_API) - val env = createAndroidTestEnvironment(config, getResPaths(path)) + val env = createTestEnvironment(config, getResPaths(path)) val project = env.project val ext = PackageFragmentProviderExtension.getInstances(project).first { it is AndroidPackageFragmentProviderExtension } diff --git a/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/CompilerTestUtils.kt b/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/CompilerTestUtils.kt old mode 100644 new mode 100755 index d1649ee2973..742836d6905 --- a/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/CompilerTestUtils.kt +++ b/plugins/plugins-tests/tests/org/jetbrains/kotlin/lang/resolve/android/test/CompilerTestUtils.kt @@ -35,7 +35,7 @@ import org.jetbrains.kotlin.resolve.jvm.extensions.PackageFragmentProviderExtens import org.jetbrains.kotlin.test.testFramework.KtUsefulTestCase import java.io.File -fun KtUsefulTestCase.createAndroidTestEnvironment(configuration: CompilerConfiguration, resDirectories: List): KotlinCoreEnvironment { +fun KtUsefulTestCase.createTestEnvironment(configuration: CompilerConfiguration, resDirectories: List): KotlinCoreEnvironment { configuration.put(AndroidConfigurationKeys.VARIANT, resDirectories) configuration.put(AndroidConfigurationKeys.PACKAGE, "test")