diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java index 101935aaba6..e6ce342492f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForJavaDescriptorResolver.java @@ -131,6 +131,7 @@ public class InjectorForJavaDescriptorResolver { javaAnnotationArgumentResolver.setAnnotationResolver(javaAnnotationResolver); javaAnnotationArgumentResolver.setClassResolver(javaClassResolver); + javaAnnotationArgumentResolver.setTypeTransformer(javaTypeTransformer); javaClassResolver.setAnnotationResolver(javaAnnotationResolver); javaClassResolver.setCache(traceBasedJavaResolverCache); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java index 7946bdc86ae..61b42381f47 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/di/InjectorForTopDownAnalyzerForJvm.java @@ -59,12 +59,12 @@ import org.jetbrains.jet.lang.resolve.ScriptBodyResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaClassResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationArgumentResolver; +import org.jetbrains.jet.lang.resolve.java.resolver.JavaTypeTransformer; import org.jetbrains.jet.lang.resolve.java.resolver.DeserializedDescriptorResolver; import org.jetbrains.jet.lang.resolve.java.resolver.AnnotationDescriptorDeserializer; import org.jetbrains.jet.lang.resolve.java.resolver.JavaNamespaceResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaMemberResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaConstructorResolver; -import org.jetbrains.jet.lang.resolve.java.resolver.JavaTypeTransformer; import org.jetbrains.jet.lang.resolve.java.resolver.JavaValueParameterResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaFunctionResolver; import org.jetbrains.jet.lang.resolve.java.resolver.JavaTypeParameterResolver; @@ -119,12 +119,12 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly private final JavaClassResolver javaClassResolver; private final JavaAnnotationResolver javaAnnotationResolver; private final JavaAnnotationArgumentResolver javaAnnotationArgumentResolver; + private final JavaTypeTransformer javaTypeTransformer; private final DeserializedDescriptorResolver deserializedDescriptorResolver; private final AnnotationDescriptorDeserializer annotationDescriptorDeserializer; private final JavaNamespaceResolver javaNamespaceResolver; private final JavaMemberResolver javaMemberResolver; private final JavaConstructorResolver javaConstructorResolver; - private final JavaTypeTransformer javaTypeTransformer; private final JavaValueParameterResolver javaValueParameterResolver; private final JavaFunctionResolver javaFunctionResolver; private final JavaTypeParameterResolver javaTypeParameterResolver; @@ -180,12 +180,12 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly this.javaClassResolver = new JavaClassResolver(); this.javaAnnotationResolver = new JavaAnnotationResolver(); this.javaAnnotationArgumentResolver = new JavaAnnotationArgumentResolver(); + this.javaTypeTransformer = new JavaTypeTransformer(); this.deserializedDescriptorResolver = new DeserializedDescriptorResolver(); this.annotationDescriptorDeserializer = new AnnotationDescriptorDeserializer(); this.javaNamespaceResolver = new JavaNamespaceResolver(); this.javaMemberResolver = new JavaMemberResolver(); this.javaConstructorResolver = new JavaConstructorResolver(); - this.javaTypeTransformer = new JavaTypeTransformer(); this.javaValueParameterResolver = new JavaValueParameterResolver(); this.javaFunctionResolver = new JavaFunctionResolver(); this.javaTypeParameterResolver = new JavaTypeParameterResolver(); @@ -333,6 +333,9 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly javaAnnotationArgumentResolver.setAnnotationResolver(javaAnnotationResolver); javaAnnotationArgumentResolver.setClassResolver(javaClassResolver); + javaAnnotationArgumentResolver.setTypeTransformer(javaTypeTransformer); + + javaTypeTransformer.setClassResolver(javaClassResolver); deserializedDescriptorResolver.setAnnotationDeserializer(annotationDescriptorDeserializer); deserializedDescriptorResolver.setErrorReporter(traceBasedErrorReporter); @@ -359,8 +362,6 @@ public class InjectorForTopDownAnalyzerForJvm implements InjectorForTopDownAnaly javaConstructorResolver.setTypeTransformer(javaTypeTransformer); javaConstructorResolver.setValueParameterResolver(javaValueParameterResolver); - javaTypeTransformer.setClassResolver(javaClassResolver); - javaValueParameterResolver.setAnnotationResolver(javaAnnotationResolver); javaValueParameterResolver.setTypeTransformer(javaTypeTransformer); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaAnnotationArgumentImpl.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaAnnotationArgumentImpl.java index a70658a0c9f..2c67cc202ab 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaAnnotationArgumentImpl.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/impl/JavaAnnotationArgumentImpl.java @@ -47,6 +47,9 @@ public abstract class JavaAnnotationArgumentImpl + implements JavaClassObjectAnnotationArgument { + public JavaClassObjectAnnotationArgumentImpl(@NotNull PsiClassObjectAccessExpression expression, @Nullable Name name) { + super(expression, name); + } + + @NotNull + @Override + public JavaType getReferencedType() { + return JavaTypeImpl.create(getPsi().getOperand().getType()); + } +} diff --git a/compiler/testData/loadJava/compiledJava/annotations/ClassObjectArrayInParam.java b/compiler/testData/loadJava/compiledJava/annotations/ClassObjectArrayInParam.java new file mode 100644 index 00000000000..b7ec6e97925 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/annotations/ClassObjectArrayInParam.java @@ -0,0 +1,10 @@ +package test; + +public class ClassObjectArrayInParam { + public @interface Anno { + Class[] value(); + } + + @Anno({ClassObjectArrayInParam.class, Nested.class, String.class}) + public static class Nested {} +} diff --git a/compiler/testData/loadJava/compiledJava/annotations/ClassObjectArrayInParam.txt b/compiler/testData/loadJava/compiledJava/annotations/ClassObjectArrayInParam.txt new file mode 100644 index 00000000000..b472980868b --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/annotations/ClassObjectArrayInParam.txt @@ -0,0 +1,14 @@ +package test + +public open class ClassObjectArrayInParam : java.lang.Object { + public constructor ClassObjectArrayInParam() + + public final annotation class Anno : jet.Annotation { + public constructor Anno(/*0*/ vararg value: java.lang.Class? /*jet.Array>?*/) + public abstract fun value(): jet.Array>? + } + + test.ClassObjectArrayInParam.Anno(value = [ClassObjectArrayInParam?.class, Nested?.class, String?.class]: jet.Array>?) public open class Nested : java.lang.Object { + public constructor Nested() + } +} diff --git a/compiler/testData/loadJava/compiledJava/annotations/ClassObjectInParam.java b/compiler/testData/loadJava/compiledJava/annotations/ClassObjectInParam.java new file mode 100644 index 00000000000..ebcd76f4221 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/annotations/ClassObjectInParam.java @@ -0,0 +1,10 @@ +package test; + +public class ClassObjectInParam { + public @interface Anno { + Class value(); + } + + @Anno(ClassObjectInParam.class) + public static class Nested {} +} diff --git a/compiler/testData/loadJava/compiledJava/annotations/ClassObjectInParam.txt b/compiler/testData/loadJava/compiledJava/annotations/ClassObjectInParam.txt new file mode 100644 index 00000000000..8573aad22b1 --- /dev/null +++ b/compiler/testData/loadJava/compiledJava/annotations/ClassObjectInParam.txt @@ -0,0 +1,14 @@ +package test + +public open class ClassObjectInParam : java.lang.Object { + public constructor ClassObjectInParam() + + public final annotation class Anno : jet.Annotation { + public constructor Anno(/*0*/ value: java.lang.Class?) + public abstract fun value(): java.lang.Class? + } + + test.ClassObjectInParam.Anno(value = ClassObjectInParam?.class: java.lang.Class) public open class Nested : java.lang.Object { + public constructor Nested() + } +} diff --git a/compiler/testData/loadJava/sourceJava/ErrorTypes.txt b/compiler/testData/loadJava/sourceJava/ErrorTypes.txt index 65e61c84783..1e90a206970 100644 --- a/compiler/testData/loadJava/sourceJava/ErrorTypes.txt +++ b/compiler/testData/loadJava/sourceJava/ErrorTypes.txt @@ -3,13 +3,13 @@ package test public trait ErrorTypes : java.lang.Object { public trait Sub : test.ErrorTypes.Super { - public abstract fun errorTypeInParameter(/*0*/ list: jet.List?>?): jet.Unit - public abstract override /*1*/ /*fake_override*/ fun errorTypeInParameter(/*0*/ list: jet.List?>?): jet.Unit - public abstract override /*1*/ fun returnErrorType(): [ERROR : Unresolved java class: T] + public abstract fun errorTypeInParameter(/*0*/ list: jet.List?>?): jet.Unit + public abstract override /*1*/ /*fake_override*/ fun errorTypeInParameter(/*0*/ list: jet.List?>?): jet.Unit + public abstract override /*1*/ fun returnErrorType(): [ERROR : Unresolved java classifier: T] } public trait Super : java.lang.Object { - public abstract fun errorTypeInParameter(/*0*/ list: jet.List?>?): jet.Unit - public abstract fun returnErrorType(): [ERROR : Unresolved java class: T] + public abstract fun errorTypeInParameter(/*0*/ list: jet.List?>?): jet.Unit + public abstract fun returnErrorType(): [ERROR : Unresolved java classifier: T] } } diff --git a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java index 4ca403c6bc1..bd433a30974 100644 --- a/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java +++ b/compiler/tests/org/jetbrains/jet/jvm/compiler/LoadJavaTestGenerated.java @@ -1080,6 +1080,16 @@ public class LoadJavaTestGenerated extends AbstractLoadJavaTest { doTestCompiledJava("compiler/testData/loadJava/compiledJava/annotations/ArrayOfStringInParam.java"); } + @TestMetadata("ClassObjectArrayInParam.java") + public void testClassObjectArrayInParam() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/annotations/ClassObjectArrayInParam.java"); + } + + @TestMetadata("ClassObjectInParam.java") + public void testClassObjectInParam() throws Exception { + doTestCompiledJava("compiler/testData/loadJava/compiledJava/annotations/ClassObjectInParam.java"); + } + @TestMetadata("CustomAnnotation.java") public void testCustomAnnotation() throws Exception { doTestCompiledJava("compiler/testData/loadJava/compiledJava/annotations/CustomAnnotation.java"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java index 8e85fded0fb..6a90b595ede 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java @@ -168,7 +168,7 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer annotation.setAnnotationType(annotationClass.getDefaultType()); return new AnnotationVisitor(Opcodes.ASM4) { - // TODO: arrays, annotations + // TODO: arrays, annotations, java.lang.Class @Override public void visit(String name, Object value) { CompileTimeConstant argument = JavaAnnotationArgumentResolver.resolveCompileTimeConstantValue(value, null); diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationArgumentResolver.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationArgumentResolver.java index 2e45fb6d0b4..cfd0ef9dc25 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationArgumentResolver.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationArgumentResolver.java @@ -29,19 +29,26 @@ import org.jetbrains.jet.lang.resolve.java.structure.*; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.JetTypeImpl; +import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import javax.inject.Inject; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.List; import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getEnumEntriesScope; +import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.IGNORE_KOTLIN_SOURCES; import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES; public final class JavaAnnotationArgumentResolver { + public static final FqName JL_CLASS_FQ_NAME = new FqName("java.lang.Class"); + private JavaAnnotationResolver annotationResolver; private JavaClassResolver classResolver; + private JavaTypeTransformer typeTransformer; @Inject public void setAnnotationResolver(JavaAnnotationResolver annotationResolver) { @@ -53,6 +60,11 @@ public final class JavaAnnotationArgumentResolver { this.classResolver = classResolver; } + @Inject + public void setTypeTransformer(JavaTypeTransformer typeTransformer) { + this.typeTransformer = typeTransformer; + } + @Nullable public CompileTimeConstant resolveAnnotationArgument( @NotNull FqName annotationFqName, @@ -80,6 +92,10 @@ public final class JavaAnnotationArgumentResolver { else if (argument instanceof JavaAnnotationAsAnnotationArgument) { return resolveFromAnnotation(((JavaAnnotationAsAnnotationArgument) argument).getAnnotation(), postponedTasks); } + // Class + else if (argument instanceof JavaClassObjectAnnotationArgument) { + return resolveFromJavaClassObjectType(((JavaClassObjectAnnotationArgument) argument).getReferencedType()); + } return null; } @@ -135,6 +151,25 @@ public final class JavaAnnotationArgumentResolver { return null; } + @Nullable + private CompileTimeConstant resolveFromJavaClassObjectType(@NotNull JavaType javaType) { + JetType type = typeTransformer.transformToType(javaType, TypeVariableResolver.EMPTY); + + ClassDescriptor jlClass = classResolver.resolveClass(JL_CLASS_FQ_NAME, IGNORE_KOTLIN_SOURCES); + if (jlClass == null) return null; + + List arguments = Collections.singletonList(new TypeProjection(type)); + JetTypeImpl javaClassType = new JetTypeImpl( + jlClass.getAnnotations(), + jlClass.getTypeConstructor(), + false, + arguments, + jlClass.getMemberScope(arguments) + ); + + return new JavaClassValue(javaClassType); + } + @Nullable public static CompileTimeConstant resolveCompileTimeConstantValue(@Nullable Object value, @Nullable JetType expectedType) { if (value instanceof String) { diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClassObjectAnnotationArgument.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClassObjectAnnotationArgument.java new file mode 100644 index 00000000000..691f84e5537 --- /dev/null +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaClassObjectAnnotationArgument.java @@ -0,0 +1,24 @@ +/* + * 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.lang.resolve.java.structure; + +import org.jetbrains.annotations.NotNull; + +public interface JavaClassObjectAnnotationArgument extends JavaAnnotationArgument { + @NotNull + JavaType getReferencedType(); +}