Migrate JavaAnnotationResolver from PSI to JavaElement

Create a bunch of annotation argument classes, which serve as wrappers over
PsiAnnotationMemberValue class, but also have a Name
This commit is contained in:
Alexander Udalov
2013-08-01 15:45:41 +04:00
parent 7b945c2313
commit f98a949fdd
18 changed files with 412 additions and 158 deletions
@@ -78,20 +78,16 @@ public final class DescriptorResolverUtils {
}
@Nullable
public static ValueParameterDescriptor getValueParameterDescriptorForAnnotationParameter(
Name argumentName,
ClassDescriptor classDescriptor
) {
Collection<ConstructorDescriptor> constructors = classDescriptor.getConstructors();
public static ValueParameterDescriptor getAnnotationParameterByName(@NotNull Name name, @NotNull ClassDescriptor annotationClass) {
Collection<ConstructorDescriptor> constructors = annotationClass.getConstructors();
assert constructors.size() == 1 : "Annotation class descriptor must have only one constructor";
List<ValueParameterDescriptor> 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;
}
@@ -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);
@@ -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);
}
@@ -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;
@@ -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);
}
@@ -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<AnnotationDescriptor> resolveAnnotations(@NotNull PsiModifierListOwner owner, @NotNull PostponedTasks tasks) {
PsiAnnotation[] psiAnnotations = getAllAnnotations(owner);
List<AnnotationDescriptor> r = Lists.newArrayListWithCapacity(psiAnnotations.length);
for (PsiAnnotation psiAnnotation : psiAnnotations) {
AnnotationDescriptor annotation = resolveAnnotation(psiAnnotation, tasks);
public List<AnnotationDescriptor> resolveAnnotations(@NotNull JavaAnnotationOwner owner, @NotNull PostponedTasks tasks) {
Collection<JavaAnnotation> annotations = getAnnotationsWithExternal(owner);
List<AnnotationDescriptor> result = new ArrayList<AnnotationDescriptor>(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<AnnotationDescriptor> resolveAnnotations(@NotNull PsiModifierListOwner owner) {
public List<AnnotationDescriptor> resolveAnnotations(@NotNull JavaAnnotationOwner owner) {
PostponedTasks postponedTasks = new PostponedTasks();
List<AnnotationDescriptor> 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<PsiAnnotation> result = new ArrayList<PsiAnnotation>();
private static Collection<JavaAnnotation> getAnnotationsWithExternal(@NotNull JavaAnnotationOwner owner) {
List<JavaAnnotation> result = new ArrayList<JavaAnnotation>();
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) {
@@ -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));
@@ -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<JavaAnnotationArgument> elements,
@NotNull PostponedTasks taskList
) {
PsiAnnotationMemberValue[] initializers = value.getInitializers();
List<CompileTimeConstant<?>> 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<CompileTimeConstant<?>> getCompileTimeConstantForArrayValues(
FqName annotationQualifiedName,
Name valueName,
PostponedTasks taskList,
PsiAnnotationMemberValue[] initializers
) {
List<CompileTimeConstant<?>> values = new ArrayList<CompileTimeConstant<?>>();
for (PsiAnnotationMemberValue initializer : initializers) {
CompileTimeConstant<?> compileTimeConstant =
getCompileTimeConstFromExpression(annotationQualifiedName, valueName, initializer, taskList);
if (compileTimeConstant == null) {
compileTimeConstant = NullValue.NULL;
}
values.add(compileTimeConstant);
List<CompileTimeConstant<?>> values = new ArrayList<CompileTimeConstant<?>>(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<VariableDescriptor> 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;
}
}
}
@@ -118,7 +118,7 @@ public final class JavaFunctionResolver {
SimpleFunctionDescriptorImpl functionDescriptorImpl = new SimpleFunctionDescriptorImpl(
ownerDescriptor,
annotationResolver.resolveAnnotations(psiMethod),
annotationResolver.resolveAnnotations(method),
method.getName(),
CallableMemberDescriptor.Kind.DECLARATION
);
@@ -175,7 +175,7 @@ public final class JavaPropertyResolver {
@NotNull JavaField field,
boolean isVar
) {
List<AnnotationDescriptor> annotations = annotationResolver.resolveAnnotations(field.getPsi());
List<AnnotationDescriptor> annotations = annotationResolver.resolveAnnotations(field);
Visibility visibility = field.getVisibility();
if (field.isEnumEntry()) {
@@ -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<JavaAnnotationArgument> getArguments() {
return namedAnnotationArguments(getPsi().getParameterList().getAttributes());
}
@Nullable
public FqName getFqName() {
String qualifiedName = getPsi().getQualifiedName();
return qualifiedName == null ? null : new FqName(qualifiedName);
}
}
@@ -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;
}
}
@@ -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());
}
}
@@ -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<JavaAnnotationArgument> getElements() {
return namelessAnnotationArguments(getPsi().getInitializers());
}
}
@@ -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<JavaAnnotationArgument> namelessAnnotationArguments(@NotNull PsiAnnotationMemberValue[] memberValues) {
if (memberValues.length == 0) return Collections.emptyList();
List<JavaAnnotationArgument> result = new ArrayList<JavaAnnotationArgument>(memberValues.length);
for (PsiAnnotationMemberValue psiAnnotationMemberValue : memberValues) {
result.add(JavaAnnotationArgument.create(psiAnnotationMemberValue, null));
}
return result;
}
@NotNull
public static Collection<JavaAnnotationArgument> namedAnnotationArguments(@NotNull PsiNameValuePair[] nameValuePairs) {
if (nameValuePairs.length == 0) return Collections.emptyList();
List<JavaAnnotationArgument> result = new ArrayList<JavaAnnotationArgument>(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;
}
}
@@ -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();
}
}
@@ -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;
}
}