diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java index 01aff8833b1..573f8b2ae17 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/DescriptorResolverUtils.java @@ -78,20 +78,16 @@ public final class DescriptorResolverUtils { } @Nullable - public static ValueParameterDescriptor getValueParameterDescriptorForAnnotationParameter( - Name argumentName, - ClassDescriptor classDescriptor - ) { - Collection constructors = classDescriptor.getConstructors(); + public static ValueParameterDescriptor getAnnotationParameterByName(@NotNull Name name, @NotNull ClassDescriptor annotationClass) { + Collection constructors = annotationClass.getConstructors(); assert constructors.size() == 1 : "Annotation class descriptor must have only one constructor"; - List valueParameters = constructors.iterator().next().getValueParameters(); - for (ValueParameterDescriptor parameter : valueParameters) { - Name parameterName = parameter.getName(); - if (parameterName.equals(argumentName)) { + for (ValueParameterDescriptor parameter : constructors.iterator().next().getValueParameters()) { + if (parameter.getName().equals(name)) { return parameter; } } + return null; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java index f25ea13355f..148d2f8fd8d 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java @@ -20,6 +20,7 @@ import jet.KotlinClass; import jet.KotlinPackage; import jet.runtime.typeinfo.KotlinSignature; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.rt.annotation.AssertInvisibleInResolver; public final class JvmAnnotationNames { @@ -39,7 +40,7 @@ public final class JvmAnnotationNames { public static final JvmClassName KOTLIN_SIGNATURE = JvmClassName.byClass(KotlinSignature.class); - public static final String KOTLIN_SIGNATURE_VALUE_FIELD_NAME = "value"; + public static final Name KOTLIN_SIGNATURE_VALUE_FIELD_NAME = Name.identifier("value"); public static final JvmClassName JETBRAINS_NOT_NULL_ANNOTATION = JvmClassName.byClass(NotNull.class); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesUtil.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesUtil.java index 0064e58877d..a6b23f03300 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesUtil.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kotlinSignature/SignaturesUtil.java @@ -18,9 +18,6 @@ package org.jetbrains.jet.lang.resolve.java.kotlinSignature; import com.google.common.collect.Maps; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiAnnotation; -import com.intellij.psi.PsiAnnotationMemberValue; -import com.intellij.psi.PsiLiteralExpression; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; @@ -28,6 +25,9 @@ import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.impl.TypeParameterDescriptorImpl; import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationResolver; +import org.jetbrains.jet.lang.resolve.java.structure.JavaAnnotation; +import org.jetbrains.jet.lang.resolve.java.structure.JavaAnnotationArgument; +import org.jetbrains.jet.lang.resolve.java.structure.JavaLiteralAnnotationArgument; import org.jetbrains.jet.lang.resolve.java.structure.JavaMember; import org.jetbrains.jet.lang.types.TypeConstructor; import org.jetbrains.jet.lang.types.TypeProjection; @@ -72,12 +72,12 @@ public class SignaturesUtil { @Nullable public static String getKotlinSignature(@NotNull JavaMember member) { - PsiAnnotation annotation = JavaAnnotationResolver.findAnnotationWithExternal(member, JvmAnnotationNames.KOTLIN_SIGNATURE); + JavaAnnotation annotation = JavaAnnotationResolver.findAnnotationWithExternal(member, JvmAnnotationNames.KOTLIN_SIGNATURE); if (annotation != null) { - PsiAnnotationMemberValue attribute = annotation.findAttributeValue(JvmAnnotationNames.KOTLIN_SIGNATURE_VALUE_FIELD_NAME); - if (attribute instanceof PsiLiteralExpression) { - Object value = ((PsiLiteralExpression) attribute).getValue(); + JavaAnnotationArgument argument = annotation.findArgument(JvmAnnotationNames.KOTLIN_SIGNATURE_VALUE_FIELD_NAME); + if (argument instanceof JavaLiteralAnnotationArgument) { + Object value = ((JavaLiteralAnnotationArgument) argument).getValue(); if (value instanceof String) { return StringUtil.unescapeStringCharacters((String) value); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/mapping/JavaToKotlinClassMap.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/mapping/JavaToKotlinClassMap.java index ee492f5bbca..8ba3e679a44 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/mapping/JavaToKotlinClassMap.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/mapping/JavaToKotlinClassMap.java @@ -33,9 +33,9 @@ import org.jetbrains.jet.lang.resolve.constants.StringValue; import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils; import org.jetbrains.jet.lang.resolve.java.JvmPrimitiveType; import org.jetbrains.jet.lang.resolve.java.TypeUsage; +import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationResolver; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.FqNameUnsafe; -import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lang.types.lang.PrimitiveType; @@ -110,11 +110,11 @@ public class JavaToKotlinClassMap extends JavaToKotlinClassMapBuilder implements } @NotNull - private static AnnotationDescriptor getAnnotationDescriptorForJavaLangDeprecated(@NotNull ClassDescriptor classDescriptor) { + private static AnnotationDescriptor getAnnotationDescriptorForJavaLangDeprecated(@NotNull ClassDescriptor annotationClass) { AnnotationDescriptor annotation = new AnnotationDescriptor(); - annotation.setAnnotationType(classDescriptor.getDefaultType()); - ValueParameterDescriptor value = - DescriptorResolverUtils.getValueParameterDescriptorForAnnotationParameter(Name.identifier("value"), classDescriptor); + annotation.setAnnotationType(annotationClass.getDefaultType()); + ValueParameterDescriptor value = DescriptorResolverUtils.getAnnotationParameterByName( + JavaAnnotationResolver.DEFAULT_ANNOTATION_MEMBER_NAME, annotationClass); assert value != null : "jet.deprecated must have one parameter called value"; annotation.setValueArgument(value, new StringValue("Deprecated in Java")); return annotation; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java index c3a9269ea09..f762189b9c7 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/AnnotationDescriptorDeserializer.java @@ -217,7 +217,7 @@ public class AnnotationDescriptorDeserializer implements AnnotationDeserializer private void setArgumentValueByName(@NotNull String name, @NotNull CompileTimeConstant argumentValue) { ValueParameterDescriptor parameter = - DescriptorResolverUtils.getValueParameterDescriptorForAnnotationParameter(Name.identifier(name), annotationClass); + DescriptorResolverUtils.getAnnotationParameterByName(Name.identifier(name), annotationClass); if (parameter != null) { annotation.setValueArgument(parameter, argumentValue); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationResolver.java index c324a979ed2..3ecb5e9f974 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaAnnotationResolver.java @@ -16,9 +16,10 @@ package org.jetbrains.jet.lang.resolve.java.resolver; -import com.google.common.collect.Lists; import com.intellij.codeInsight.ExternalAnnotationsManager; -import com.intellij.psi.*; +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiModifierList; +import com.intellij.psi.PsiModifierListOwner; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; @@ -30,18 +31,21 @@ import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap; import org.jetbrains.jet.lang.resolve.java.structure.JavaAnnotation; +import org.jetbrains.jet.lang.resolve.java.structure.JavaAnnotationArgument; import org.jetbrains.jet.lang.resolve.java.structure.JavaAnnotationOwner; import org.jetbrains.jet.lang.resolve.name.FqName; import org.jetbrains.jet.lang.resolve.name.Name; import javax.inject.Inject; import java.util.ArrayList; -import java.util.Arrays; +import java.util.Collection; import java.util.List; import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES; public final class JavaAnnotationResolver { + public static final Name DEFAULT_ANNOTATION_MEMBER_NAME = Name.identifier("value"); + private JavaClassResolver classResolver; private JavaCompileTimeConstResolver compileTimeConstResolver; @@ -59,20 +63,20 @@ public final class JavaAnnotationResolver { } @NotNull - public List resolveAnnotations(@NotNull PsiModifierListOwner owner, @NotNull PostponedTasks tasks) { - PsiAnnotation[] psiAnnotations = getAllAnnotations(owner); - List r = Lists.newArrayListWithCapacity(psiAnnotations.length); - for (PsiAnnotation psiAnnotation : psiAnnotations) { - AnnotationDescriptor annotation = resolveAnnotation(psiAnnotation, tasks); + public List resolveAnnotations(@NotNull JavaAnnotationOwner owner, @NotNull PostponedTasks tasks) { + Collection annotations = getAnnotationsWithExternal(owner); + List result = new ArrayList(annotations.size()); + for (JavaAnnotation javaAnnotation : annotations) { + AnnotationDescriptor annotation = resolveAnnotation(javaAnnotation, tasks); if (annotation != null) { - r.add(annotation); + result.add(annotation); } } - return r; + return result; } @NotNull - public List resolveAnnotations(@NotNull PsiModifierListOwner owner) { + public List resolveAnnotations(@NotNull JavaAnnotationOwner owner) { PostponedTasks postponedTasks = new PostponedTasks(); List annotations = resolveAnnotations(owner, postponedTasks); postponedTasks.performTasks(); @@ -80,30 +84,28 @@ public final class JavaAnnotationResolver { } @Nullable - public AnnotationDescriptor resolveAnnotation(PsiAnnotation psiAnnotation, @NotNull PostponedTasks postponedTasks) { + public AnnotationDescriptor resolveAnnotation(@NotNull JavaAnnotation javaAnnotation, @NotNull PostponedTasks postponedTasks) { final AnnotationDescriptor annotation = new AnnotationDescriptor(); - String qname = psiAnnotation.getQualifiedName(); - if (qname == null) { + FqName fqName = javaAnnotation.getFqName(); + if (fqName == null) { return null; } // Don't process internal jet annotations and jetbrains NotNull annotations - if (qname.startsWith("jet.runtime.typeinfo.") - || qname.equals(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION.getFqName().asString()) - || qname.equals(JvmAnnotationNames.KOTLIN_CLASS.getFqName().asString()) - || qname.equals(JvmAnnotationNames.KOTLIN_PACKAGE.getFqName().asString()) + if (fqName.asString().startsWith("jet.runtime.typeinfo.") + || fqName.equals(JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION.getFqName()) + || fqName.equals(JvmAnnotationNames.KOTLIN_CLASS.getFqName()) + || fqName.equals(JvmAnnotationNames.KOTLIN_PACKAGE.getFqName()) ) { return null; } - FqName annotationFqName = new FqName(qname); - - AnnotationDescriptor mappedClassDescriptor = JavaToKotlinClassMap.getInstance().mapToAnnotationClass(annotationFqName); + AnnotationDescriptor mappedClassDescriptor = JavaToKotlinClassMap.getInstance().mapToAnnotationClass(fqName); if (mappedClassDescriptor != null) { return mappedClassDescriptor; } - final ClassDescriptor annotationClass = classResolver.resolveClass(annotationFqName, INCLUDE_KOTLIN_SOURCES, postponedTasks); + final ClassDescriptor annotationClass = classResolver.resolveClass(fqName, INCLUDE_KOTLIN_SOURCES, postponedTasks); if (annotationClass == null) { return null; } @@ -116,22 +118,15 @@ public final class JavaAnnotationResolver { }); - PsiAnnotationParameterList parameterList = psiAnnotation.getParameterList(); - for (PsiNameValuePair psiNameValuePair : parameterList.getAttributes()) { - PsiAnnotationMemberValue value = psiNameValuePair.getValue(); - String name = psiNameValuePair.getName(); - if (name == null) name = "value"; - Name identifier = Name.identifier(name); + for (JavaAnnotationArgument argument : javaAnnotation.getArguments()) { + CompileTimeConstant value = compileTimeConstResolver.resolveAnnotationArgument(fqName, argument, postponedTasks); + if (value == null) continue; - if (value == null) return null; - CompileTimeConstant compileTimeConst = - compileTimeConstResolver.getCompileTimeConstFromExpression(annotationFqName, identifier, value, postponedTasks); - if (compileTimeConst != null) { - ValueParameterDescriptor valueParameterDescriptor = - DescriptorResolverUtils.getValueParameterDescriptorForAnnotationParameter(identifier, annotationClass); - if (valueParameterDescriptor != null) { - annotation.setValueArgument(valueParameterDescriptor, compileTimeConst); - } + Name name = argument.getName(); + ValueParameterDescriptor descriptor = DescriptorResolverUtils.getAnnotationParameterByName( + name == null ? DEFAULT_ANNOTATION_MEMBER_NAME : name, annotationClass); + if (descriptor != null) { + annotation.setValueArgument(descriptor, value); } } @@ -139,30 +134,31 @@ public final class JavaAnnotationResolver { } @NotNull - private static PsiAnnotation[] getAllAnnotations(@NotNull PsiModifierListOwner owner) { - List result = new ArrayList(); + private static Collection getAnnotationsWithExternal(@NotNull JavaAnnotationOwner owner) { + List result = new ArrayList(); - PsiModifierList list = owner.getModifierList(); - if (list != null) { - result.addAll(Arrays.asList(list.getAnnotations())); - } + result.addAll(owner.getAnnotations()); - PsiAnnotation[] externalAnnotations = ExternalAnnotationsManager.getInstance(owner.getProject()).findExternalAnnotations(owner); + PsiAnnotation[] externalAnnotations = + ExternalAnnotationsManager.getInstance(owner.getPsi().getProject()).findExternalAnnotations(owner.getPsi()); if (externalAnnotations != null) { - result.addAll(Arrays.asList(externalAnnotations)); + for (PsiAnnotation annotation : externalAnnotations) { + result.add(new JavaAnnotation(annotation)); + } } - return result.toArray(new PsiAnnotation[result.size()]); + return result; } @Nullable - public static PsiAnnotation findAnnotationWithExternal(@NotNull JavaAnnotationOwner owner, @NotNull JvmClassName name) { + public static JavaAnnotation findAnnotationWithExternal(@NotNull JavaAnnotationOwner owner, @NotNull JvmClassName name) { JavaAnnotation annotation = owner.findAnnotation(name.getFqName()); if (annotation != null) { - return annotation.getPsi(); + return annotation; } - return findExternalAnnotation(owner.getPsi(), name); + PsiAnnotation externalAnnotation = findExternalAnnotation(owner.getPsi(), name); + return externalAnnotation == null ? null : new JavaAnnotation(externalAnnotation); } public static boolean hasNotNullAnnotation(@NotNull JavaAnnotationOwner owner) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java index 4ece3f77c14..cda7261a044 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaClassResolver.java @@ -22,7 +22,6 @@ import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.PsiClass; import gnu.trove.THashMap; import gnu.trove.TObjectHashingStrategy; import org.jetbrains.annotations.NotNull; @@ -327,12 +326,11 @@ public final class JavaClassResolver { classDescriptor.getBuilder().setClassObjectDescriptor(classObjectDescriptor); } - PsiClass psiClass = javaClass.getPsi(); - classDescriptor.setAnnotations(annotationResolver.resolveAnnotations(psiClass, taskList)); + classDescriptor.setAnnotations(annotationResolver.resolveAnnotations(javaClass, taskList)); - trace.record(BindingContext.CLASS, psiClass, classDescriptor); + trace.record(BindingContext.CLASS, javaClass.getPsi(), classDescriptor); - JavaMethod samInterfaceMethod = SingleAbstractMethodUtils.getSamInterfaceMethod(javaClass, psiClass.getProject()); + JavaMethod samInterfaceMethod = SingleAbstractMethodUtils.getSamInterfaceMethod(javaClass, javaClass.getPsi().getProject()); if (samInterfaceMethod != null) { SimpleFunctionDescriptor abstractMethod = resolveFunctionOfSamInterface(samInterfaceMethod, classDescriptor); classDescriptor.setFunctionTypeForSamInterface(SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(abstractMethod)); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaCompileTimeConstResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaCompileTimeConstResolver.java index 7cd038a7ae5..401d4e9d652 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaCompileTimeConstResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaCompileTimeConstResolver.java @@ -16,20 +16,19 @@ package org.jetbrains.jet.lang.resolve.java.resolver; -import com.intellij.psi.*; +import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor; import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; import org.jetbrains.jet.lang.resolve.constants.*; import org.jetbrains.jet.lang.resolve.constants.StringValue; import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils; +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.resolve.scopes.JetScope; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; @@ -38,6 +37,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import static org.jetbrains.jet.lang.resolve.DescriptorUtils.getEnumEntriesScope; import static org.jetbrains.jet.lang.resolve.java.DescriptorSearchRule.INCLUDE_KOTLIN_SOURCES; public final class JavaCompileTimeConstResolver { @@ -58,103 +58,87 @@ public final class JavaCompileTimeConstResolver { } @Nullable - public CompileTimeConstant getCompileTimeConstFromExpression( - FqName annotationFqName, Name parameterName, - PsiAnnotationMemberValue value, PostponedTasks postponedTasks + public CompileTimeConstant resolveAnnotationArgument( + @NotNull FqName annotationFqName, + @NotNull JavaAnnotationArgument argument, + @NotNull PostponedTasks postponedTasks ) { - if (value instanceof PsiLiteralExpression) { - return resolveCompileTimeConstantValue(((PsiLiteralExpression) value).getValue(), null); + if (argument instanceof JavaLiteralAnnotationArgument) { + return resolveCompileTimeConstantValue(((JavaLiteralAnnotationArgument) argument).getValue(), null); } // Enum - else if (value instanceof PsiReferenceExpression) { - return getCompileTimeConstFromReferenceExpression((PsiReferenceExpression) value, postponedTasks); + else if (argument instanceof JavaReferenceAnnotationArgument) { + return resolveFromReference(((JavaReferenceAnnotationArgument) argument).resolve(), postponedTasks); } // Array - else if (value instanceof PsiArrayInitializerMemberValue) { - return getCompileTimeConstFromArrayExpression(annotationFqName, parameterName, (PsiArrayInitializerMemberValue) value, - postponedTasks); + else if (argument instanceof JavaArrayAnnotationArgument) { + Name argumentName = argument.getName(); + return resolveFromArray( + annotationFqName, + argumentName == null ? JavaAnnotationResolver.DEFAULT_ANNOTATION_MEMBER_NAME : argumentName, + ((JavaArrayAnnotationArgument) argument).getElements(), + postponedTasks + ); } // Annotation - else if (value instanceof PsiAnnotation) { - return getCompileTimeConstFromAnnotation((PsiAnnotation) value, postponedTasks); + else if (argument instanceof JavaAnnotationAsAnnotationArgument) { + return resolveFromAnnotation(((JavaAnnotationAsAnnotationArgument) argument).getAnnotation(), postponedTasks); } + return null; } @Nullable - private CompileTimeConstant getCompileTimeConstFromAnnotation(PsiAnnotation value, PostponedTasks taskList) { - AnnotationDescriptor annotationDescriptor = annotationResolver.resolveAnnotation(value, taskList); - if (annotationDescriptor != null) { - return new AnnotationValue(annotationDescriptor); - } - return null; + private CompileTimeConstant resolveFromAnnotation(@NotNull JavaAnnotation value, @NotNull PostponedTasks taskList) { + AnnotationDescriptor descriptor = annotationResolver.resolveAnnotation(value, taskList); + return descriptor == null ? null : new AnnotationValue(descriptor); } @Nullable - private CompileTimeConstant getCompileTimeConstFromArrayExpression( - FqName annotationFqName, - Name valueName, PsiArrayInitializerMemberValue value, - PostponedTasks taskList + private CompileTimeConstant resolveFromArray( + @NotNull FqName annotationFqName, + @NotNull Name argumentName, + @NotNull Collection elements, + @NotNull PostponedTasks taskList ) { - PsiAnnotationMemberValue[] initializers = value.getInitializers(); - List> values = getCompileTimeConstantForArrayValues(annotationFqName, valueName, taskList, initializers); - - ClassDescriptor classDescriptor = classResolver.resolveClass(annotationFqName, INCLUDE_KOTLIN_SOURCES, taskList); + ClassDescriptor annotationClass = classResolver.resolveClass(annotationFqName, INCLUDE_KOTLIN_SOURCES, taskList); + if (annotationClass == null) return null; //TODO: nullability issues - ValueParameterDescriptor valueParameterDescriptor = - DescriptorResolverUtils.getValueParameterDescriptorForAnnotationParameter(valueName, classDescriptor); - if (valueParameterDescriptor == null) { - return null; - } - JetType expectedArrayType = valueParameterDescriptor.getType(); - return new ArrayValue(values, expectedArrayType); - } + ValueParameterDescriptor valueParameter = DescriptorResolverUtils.getAnnotationParameterByName(argumentName, annotationClass); + if (valueParameter == null) return null; - private List> getCompileTimeConstantForArrayValues( - FqName annotationQualifiedName, - Name valueName, - PostponedTasks taskList, - PsiAnnotationMemberValue[] initializers - ) { - List> values = new ArrayList>(); - for (PsiAnnotationMemberValue initializer : initializers) { - CompileTimeConstant compileTimeConstant = - getCompileTimeConstFromExpression(annotationQualifiedName, valueName, initializer, taskList); - if (compileTimeConstant == null) { - compileTimeConstant = NullValue.NULL; - } - values.add(compileTimeConstant); + List> values = new ArrayList>(elements.size()); + for (JavaAnnotationArgument argument : elements) { + CompileTimeConstant value = resolveAnnotationArgument(annotationFqName, argument, taskList); + values.add(value == null ? NullValue.NULL : value); } - return values; + + return new ArrayValue(values, valueParameter.getType()); } @Nullable - private CompileTimeConstant getCompileTimeConstFromReferenceExpression(PsiReferenceExpression value, PostponedTasks taskList) { - PsiElement resolveElement = value.resolve(); - if (resolveElement instanceof PsiEnumConstant) { - PsiElement psiElement = resolveElement.getParent(); - if (psiElement instanceof PsiClass) { - PsiClass psiClass = (PsiClass) psiElement; - String fqName = psiClass.getQualifiedName(); - if (fqName == null) { - return null; - } + private CompileTimeConstant resolveFromReference(@Nullable JavaElement element, @NotNull PostponedTasks taskList) { + if (!(element instanceof JavaField)) return null; - ClassDescriptor classDescriptor = classResolver.resolveClass(new FqName(fqName), INCLUDE_KOTLIN_SOURCES, taskList); - if (classDescriptor == null) return null; - JetScope scope = DescriptorUtils.getEnumEntriesScope(classDescriptor); + JavaField field = (JavaField) element; + if (!field.isEnumEntry()) return null; - Name identifier = Name.identifier(((PsiEnumConstant) resolveElement).getName()); - Collection properties = scope.getProperties(identifier); - for (VariableDescriptor variableDescriptor : properties) { - if (variableDescriptor.getReceiverParameter() == null) { - return new EnumValue((PropertyDescriptor) variableDescriptor); - } - } - return null; + JavaClass javaClass = field.getContainingClass(); + if (javaClass == null) return null; + + FqName fqName = javaClass.getFqName(); + if (fqName == null) return null; + + ClassDescriptor enumClass = classResolver.resolveClass(fqName, INCLUDE_KOTLIN_SOURCES, taskList); + if (enumClass == null) return null; + + for (VariableDescriptor variableDescriptor : getEnumEntriesScope(enumClass).getProperties(field.getName())) { + if (variableDescriptor.getReceiverParameter() == null) { + return new EnumValue((PropertyDescriptor) variableDescriptor); } } + return null; } @@ -203,4 +187,4 @@ public final class JavaCompileTimeConstResolver { } return null; } -} \ No newline at end of file +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java index fc75074096c..80760f7c513 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaFunctionResolver.java @@ -118,7 +118,7 @@ public final class JavaFunctionResolver { SimpleFunctionDescriptorImpl functionDescriptorImpl = new SimpleFunctionDescriptorImpl( ownerDescriptor, - annotationResolver.resolveAnnotations(psiMethod), + annotationResolver.resolveAnnotations(method), method.getName(), CallableMemberDescriptor.Kind.DECLARATION ); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java index 81fd13f4d5e..a4b953ef2ef 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/resolver/JavaPropertyResolver.java @@ -175,7 +175,7 @@ public final class JavaPropertyResolver { @NotNull JavaField field, boolean isVar ) { - List annotations = annotationResolver.resolveAnnotations(field.getPsi()); + List annotations = annotationResolver.resolveAnnotations(field); Visibility visibility = field.getVisibility(); if (field.isEnumEntry()) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaAnnotation.java index 68f38a880ca..2ea38c3d09a 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaAnnotation.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaAnnotation.java @@ -17,7 +17,15 @@ package org.jetbrains.jet.lang.resolve.java.structure; import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiAnnotationMemberValue; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.name.FqName; +import org.jetbrains.jet.lang.resolve.name.Name; + +import java.util.Collection; + +import static org.jetbrains.jet.lang.resolve.java.structure.JavaElementCollectionFromPsiArrayUtil.namedAnnotationArguments; public class JavaAnnotation extends JavaElementImpl { public JavaAnnotation(@NotNull PsiAnnotation psiAnnotation) { @@ -29,4 +37,21 @@ public class JavaAnnotation extends JavaElementImpl { public PsiAnnotation getPsi() { return (PsiAnnotation) super.getPsi(); } + + @Nullable + public JavaAnnotationArgument findArgument(@NotNull Name name) { + PsiAnnotationMemberValue attribute = getPsi().findAttributeValue(name.asString()); + return attribute == null ? null : JavaAnnotationArgument.create(attribute, name); + } + + @NotNull + public Collection getArguments() { + return namedAnnotationArguments(getPsi().getParameterList().getAttributes()); + } + + @Nullable + public FqName getFqName() { + String qualifiedName = getPsi().getQualifiedName(); + return qualifiedName == null ? null : new FqName(qualifiedName); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaAnnotationArgument.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaAnnotationArgument.java new file mode 100644 index 00000000000..b678aca8eeb --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaAnnotationArgument.java @@ -0,0 +1,61 @@ +/* + * 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 com.intellij.psi.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.name.Name; + +public abstract class JavaAnnotationArgument extends JavaElementImpl { + private final Name name; + + protected JavaAnnotationArgument(@NotNull PsiAnnotationMemberValue psiAnnotationMemberValue, @Nullable Name name) { + super(psiAnnotationMemberValue); + this.name = name; + } + + @NotNull + @Override + public PsiAnnotationMemberValue getPsi() { + return (PsiAnnotationMemberValue) super.getPsi(); + } + + @NotNull + public static JavaAnnotationArgument create(@NotNull PsiAnnotationMemberValue argument, @Nullable Name name) { + if (argument instanceof PsiLiteralExpression) { + return new JavaLiteralAnnotationArgument((PsiLiteralExpression) argument, name); + } + else if (argument instanceof PsiReferenceExpression) { + return new JavaReferenceAnnotationArgument((PsiReferenceExpression) argument, name); + } + else if (argument instanceof PsiArrayInitializerMemberValue) { + return new JavaArrayAnnotationArgument((PsiArrayInitializerMemberValue) argument, name); + } + else if (argument instanceof PsiAnnotation) { + return new JavaAnnotationAsAnnotationArgument((PsiAnnotation) argument, name); + } + else { + throw new UnsupportedOperationException("Unsupported annotation argument type: " + argument); + } + } + + @Nullable + public Name getName() { + return name; + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaAnnotationAsAnnotationArgument.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaAnnotationAsAnnotationArgument.java new file mode 100644 index 00000000000..eb2ab467fa8 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaAnnotationAsAnnotationArgument.java @@ -0,0 +1,39 @@ +/* + * 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 com.intellij.psi.PsiAnnotation; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.name.Name; + +public class JavaAnnotationAsAnnotationArgument extends JavaAnnotationArgument { + protected JavaAnnotationAsAnnotationArgument(@NotNull PsiAnnotation psiAnnotation, @Nullable Name name) { + super(psiAnnotation, name); + } + + @NotNull + @Override + public PsiAnnotation getPsi() { + return (PsiAnnotation) super.getPsi(); + } + + @NotNull + public JavaAnnotation getAnnotation() { + return new JavaAnnotation(getPsi()); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaArrayAnnotationArgument.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaArrayAnnotationArgument.java new file mode 100644 index 00000000000..995e97cd994 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaArrayAnnotationArgument.java @@ -0,0 +1,43 @@ +/* + * 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 com.intellij.psi.PsiArrayInitializerMemberValue; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.name.Name; + +import java.util.Collection; + +import static org.jetbrains.jet.lang.resolve.java.structure.JavaElementCollectionFromPsiArrayUtil.namelessAnnotationArguments; + +public class JavaArrayAnnotationArgument extends JavaAnnotationArgument { + protected JavaArrayAnnotationArgument(@NotNull PsiArrayInitializerMemberValue psiArrayInitializerMemberValue, @Nullable Name name) { + super(psiArrayInitializerMemberValue, name); + } + + @NotNull + @Override + public PsiArrayInitializerMemberValue getPsi() { + return (PsiArrayInitializerMemberValue) super.getPsi(); + } + + @NotNull + public Collection getElements() { + return namelessAnnotationArguments(getPsi().getInitializers()); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaElementCollectionFromPsiArrayUtil.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaElementCollectionFromPsiArrayUtil.java index 47e492b96d4..6fb52441ce8 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaElementCollectionFromPsiArrayUtil.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaElementCollectionFromPsiArrayUtil.java @@ -18,6 +18,7 @@ package org.jetbrains.jet.lang.resolve.java.structure; import com.intellij.psi.*; import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.resolve.name.Name; import java.util.ArrayList; import java.util.Collection; @@ -117,4 +118,27 @@ import java.util.List; } return result; } + + @NotNull + public static Collection namelessAnnotationArguments(@NotNull PsiAnnotationMemberValue[] memberValues) { + if (memberValues.length == 0) return Collections.emptyList(); + List result = new ArrayList(memberValues.length); + for (PsiAnnotationMemberValue psiAnnotationMemberValue : memberValues) { + result.add(JavaAnnotationArgument.create(psiAnnotationMemberValue, null)); + } + return result; + } + + @NotNull + public static Collection namedAnnotationArguments(@NotNull PsiNameValuePair[] nameValuePairs) { + if (nameValuePairs.length == 0) return Collections.emptyList(); + List result = new ArrayList(nameValuePairs.length); + for (PsiNameValuePair pair : nameValuePairs) { + String name = pair.getName(); + PsiAnnotationMemberValue value = pair.getValue(); + assert value != null : "Annotation argument value cannot be null: " + name; + result.add(JavaAnnotationArgument.create(value, name == null ? null : Name.identifier(name))); + } + return result; + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaLiteralAnnotationArgument.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaLiteralAnnotationArgument.java new file mode 100644 index 00000000000..fdb452d305b --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaLiteralAnnotationArgument.java @@ -0,0 +1,39 @@ +/* + * 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 com.intellij.psi.PsiLiteralExpression; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.name.Name; + +public class JavaLiteralAnnotationArgument extends JavaAnnotationArgument { + protected JavaLiteralAnnotationArgument(@NotNull PsiLiteralExpression psiLiteralExpression, @Nullable Name name) { + super(psiLiteralExpression, name); + } + + @NotNull + @Override + public PsiLiteralExpression getPsi() { + return (PsiLiteralExpression) super.getPsi(); + } + + @Nullable + public Object getValue() { + return getPsi().getValue(); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaReferenceAnnotationArgument.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaReferenceAnnotationArgument.java new file mode 100644 index 00000000000..e61c9191eac --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/structure/JavaReferenceAnnotationArgument.java @@ -0,0 +1,48 @@ +/* + * 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 com.intellij.psi.PsiElement; +import com.intellij.psi.PsiEnumConstant; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiReferenceExpression; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.name.Name; + +public class JavaReferenceAnnotationArgument extends JavaAnnotationArgument { + protected JavaReferenceAnnotationArgument(@NotNull PsiReferenceExpression psiReferenceExpression, @Nullable Name name) { + super(psiReferenceExpression, name); + } + + @NotNull + @Override + public PsiReferenceExpression getPsi() { + return (PsiReferenceExpression) super.getPsi(); + } + + @Nullable + public JavaElement resolve() { + PsiReferenceExpression expression = getPsi(); + PsiElement element = expression.resolve(); + if (element instanceof PsiEnumConstant) { + return new JavaField((PsiField) element); + } + // TODO: other types of references + return null; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/DeprecatedAnnotationVisitor.java b/idea/src/org/jetbrains/jet/plugin/highlighter/DeprecatedAnnotationVisitor.java index cc209359ffd..92047df71f8 100644 --- a/idea/src/org/jetbrains/jet/plugin/highlighter/DeprecatedAnnotationVisitor.java +++ b/idea/src/org/jetbrains/jet/plugin/highlighter/DeprecatedAnnotationVisitor.java @@ -34,7 +34,7 @@ import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant; import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils; -import org.jetbrains.jet.lang.resolve.name.Name; +import org.jetbrains.jet.lang.resolve.java.resolver.JavaAnnotationResolver; import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.lexer.JetTokens; @@ -237,10 +237,10 @@ public class DeprecatedAnnotationVisitor extends AfterAnalysisHighlightingVisito private static String getMessageFromAnnotationDescriptor(@NotNull AnnotationDescriptor descriptor) { ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(descriptor.getType()); assert classDescriptor != null : "ClassDescriptor for jet.deprecated mustn't be null"; - ValueParameterDescriptor parameterDescriptor = - DescriptorResolverUtils.getValueParameterDescriptorForAnnotationParameter(Name.identifier("value"), classDescriptor); - assert parameterDescriptor != null : "jet.deprecated must have one parameter called value"; - CompileTimeConstant valueArgument = descriptor.getValueArgument(parameterDescriptor); + ValueParameterDescriptor parameter = DescriptorResolverUtils.getAnnotationParameterByName( + JavaAnnotationResolver.DEFAULT_ANNOTATION_MEMBER_NAME, classDescriptor); + assert parameter != null : "jet.deprecated must have one parameter called value"; + CompileTimeConstant valueArgument = descriptor.getValueArgument(parameter); assert valueArgument != null : "jet.deprecated must have value argument"; return (String) valueArgument.getValue(); }