From 541fc8ec29a5561b6e8b202ee9596ee3338fb94c Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Thu, 12 Jan 2012 06:12:09 +0400 Subject: [PATCH] Psi* wrappers to work in jet-signature annotations refactoring to reduce amount of code in JavaDescriptorResolver --- .../resolve/java/JavaDescriptorResolver.java | 324 ++++++++---------- .../lang/resolve/java/PsiMethodWrapper.java | 77 +++++ .../resolve/java/PsiParameterWrapper.java | 38 ++ .../resolve/java/kt/JetClassAnnotation.java | 30 ++ .../java/kt/JetConstructorAnnotation.java | 31 ++ .../resolve/java/kt/JetMethodAnnotation.java | 50 +++ .../java/kt/JetPropertyAnnotation.java | 21 ++ .../java/kt/JetTypeParameterAnnotation.java | 22 ++ .../java/kt/JetValueParameterAnnotation.java | 70 ++++ .../resolve/java/kt/PsiAnnotationUtils.java | 35 ++ .../resolve/java/kt/PsiAnnotationWrapper.java | 36 ++ 11 files changed, 559 insertions(+), 175 deletions(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiMethodWrapper.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiParameterWrapper.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetClassAnnotation.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetConstructorAnnotation.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetMethodAnnotation.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetPropertyAnnotation.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetTypeParameterAnnotation.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetValueParameterAnnotation.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/PsiAnnotationUtils.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/PsiAnnotationWrapper.java diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 85a67f77def..794e85c57e9 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -6,24 +6,67 @@ import com.google.common.collect.Sets; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.*; +import com.intellij.psi.HierarchicalMethodSignature; +import com.intellij.psi.JavaPsiFacade; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiClassType; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiEllipsisType; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiJavaFile; +import com.intellij.psi.PsiMember; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.PsiModifierListOwner; +import com.intellij.psi.PsiPackage; +import com.intellij.psi.PsiType; +import com.intellij.psi.PsiTypeParameter; +import com.intellij.psi.PsiTypeParameterListOwner; import com.intellij.psi.search.DelegatingGlobalSearchScope; import com.intellij.psi.search.GlobalSearchScope; import jet.typeinfo.TypeInfoVariance; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.*; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassKind; +import org.jetbrains.jet.lang.descriptors.ConstructorDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptorVisitor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.Modality; +import org.jetbrains.jet.lang.descriptors.NamedFunctionDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; +import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptorImpl; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; +import org.jetbrains.jet.lang.descriptors.Visibility; import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor; import org.jetbrains.jet.lang.resolve.BindingContext; import org.jetbrains.jet.lang.resolve.DescriptorUtils; -import org.jetbrains.jet.lang.types.*; +import org.jetbrains.jet.lang.resolve.java.kt.JetClassAnnotation; +import org.jetbrains.jet.lang.resolve.java.kt.JetMethodAnnotation; +import org.jetbrains.jet.lang.types.JetStandardClasses; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeConstructorImpl; +import org.jetbrains.jet.lang.types.TypeSubstitutor; +import org.jetbrains.jet.lang.types.TypeUtils; +import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.plugin.JetFileType; import org.jetbrains.jet.rt.signature.JetSignatureAdapter; import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter; import org.jetbrains.jet.rt.signature.JetSignatureReader; import org.jetbrains.jet.rt.signature.JetSignatureVisitor; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * @author abreslav @@ -259,17 +302,11 @@ public class JavaDescriptorResolver { } } else { - for (PsiMethod constructor : psiConstructors) { - PsiAnnotation jetConstructorAnnotation = - constructor.getModifierList().findAnnotation(JvmStdlibNames.JET_CONSTRUCTOR.getFqName()); - if (jetConstructorAnnotation != null) { - PsiLiteralExpression hiddenExpresson = (PsiLiteralExpression) jetConstructorAnnotation.findAttributeValue(JvmStdlibNames.JET_CONSTRUCTOR_HIDDEN_FIELD); - if (hiddenExpresson != null) { - boolean hidden = (Boolean) hiddenExpresson.getValue(); - if (hidden) { - continue; - } - } + for (PsiMethod psiConstructor : psiConstructors) { + PsiMethodWrapper constructor = new PsiMethodWrapper(psiConstructor); + + if (constructor.getJetConstructor().hidden()) { + continue; } ConstructorDescriptorImpl constructorDescriptor = new ConstructorDescriptorImpl( @@ -277,17 +314,17 @@ public class JavaDescriptorResolver { Collections.emptyList(), // TODO false); ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(constructorDescriptor, - constructor.getParameterList().getParameters(), + constructor.getParameters(), new TypeParameterListTypeVariableResolver(typeParameters) // TODO: outer too ); if (valueParameterDescriptors.receiverType != null) { throw new IllegalStateException(); } constructorDescriptor.initialize(typeParameters, valueParameterDescriptors.descriptors, Modality.FINAL, - resolveVisibilityFromPsiModifiers(constructor)); + resolveVisibilityFromPsiModifiers(psiConstructor)); constructorDescriptor.setReturnType(classData.classDescriptor.getDefaultType()); classData.classDescriptor.addConstructor(constructorDescriptor); - semanticServices.getTrace().record(BindingContext.CONSTRUCTOR, constructor, constructorDescriptor); + semanticServices.getTrace().record(BindingContext.CONSTRUCTOR, psiConstructor, constructorDescriptor); } } @@ -297,18 +334,14 @@ public class JavaDescriptorResolver { } private List resolveClassTypeParameters(PsiClass psiClass, ResolverClassData classData, TypeVariableResolver typeVariableResolver) { - for (PsiAnnotation annotation : psiClass.getModifierList().getAnnotations()) { - if (annotation.getQualifiedName().equals(JvmStdlibNames.JET_CLASS.getFqName())) { - classData.kotlin = true; - PsiLiteralExpression attributeValue = (PsiLiteralExpression) annotation.findAttributeValue(JvmStdlibNames.JET_CLASS_SIGNATURE); - if (attributeValue != null) { - String typeParametersString = (String) attributeValue.getValue(); - if (typeParametersString != null) { - return resolveClassTypeParametersFromJetSignature(typeParametersString, psiClass, classData.classDescriptor, typeVariableResolver); - } - } - } + JetClassAnnotation jetClassAnnotation = JetClassAnnotation.get(psiClass); + classData.kotlin = jetClassAnnotation.isDefined(); + + if (jetClassAnnotation.signature().length() > 0) { + return resolveClassTypeParametersFromJetSignature( + jetClassAnnotation.signature(), psiClass, classData.classDescriptor, typeVariableResolver); } + return makeUninitializedTypeParameters(classData.classDescriptor, psiClass.getTypeParameters()); } @@ -633,13 +666,13 @@ public class JavaDescriptorResolver { } } - public ValueParameterDescriptors resolveParameterDescriptors(DeclarationDescriptor containingDeclaration, - PsiParameter[] parameters, TypeVariableResolver typeVariableResolver) { + private ValueParameterDescriptors resolveParameterDescriptors(DeclarationDescriptor containingDeclaration, + List parameters, TypeVariableResolver typeVariableResolver) { List result = new ArrayList(); JetType receiverType = null; int indexDelta = 0; - for (int i = 0, parametersLength = parameters.length; i < parametersLength; i++) { - PsiParameter parameter = parameters[i]; + for (int i = 0, parametersLength = parameters.size(); i < parametersLength; i++) { + PsiParameterWrapper parameter = parameters.get(i); JvmMethodParameterMeaning meaning = resolveParameterDescriptor(containingDeclaration, i + indexDelta, parameter, typeVariableResolver); if (meaning.kind == JvmMethodParameterKind.TYPE_INFO) { // TODO @@ -691,8 +724,13 @@ public class JavaDescriptorResolver { @NotNull private JvmMethodParameterMeaning resolveParameterDescriptor(DeclarationDescriptor containingDeclaration, int i, - PsiParameter parameter, TypeVariableResolver typeVariableResolver) { - PsiType psiType = parameter.getType(); + PsiParameterWrapper parameter, TypeVariableResolver typeVariableResolver) { + + if (parameter.getJetTypeParameter().isDefined()) { + return JvmMethodParameterMeaning.typeInfo(new Object()); + } + + PsiType psiType = parameter.getPsiParameter().getType(); JetType varargElementType; if (psiType instanceof PsiEllipsisType) { @@ -703,53 +741,21 @@ public class JavaDescriptorResolver { varargElementType = null; } - boolean changeNullable = false; - boolean nullable = true; - String typeFromAnnotation = null; - - boolean receiver = false; - boolean hasDefaultValue = false; - + boolean nullable = parameter.getJetValueParameter().nullable(); + // TODO: must be very slow, make it lazy? - String name = parameter.getName() != null ? parameter.getName() : "p" + i; - for (PsiAnnotation annotation : parameter.getModifierList().getAnnotations()) { + String name = parameter.getPsiParameter().getName() != null ? parameter.getPsiParameter().getName() : "p" + i; - if (annotation.getQualifiedName().equals(JvmStdlibNames.JET_VALUE_PARAMETER.getFqName())) { - PsiLiteralExpression nameExpression = (PsiLiteralExpression) annotation.findAttributeValue(JvmStdlibNames.JET_VALUE_PARAMETER_NAME_FIELD); - if (nameExpression != null) { - name = (String) nameExpression.getValue(); - } - - PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue(JvmStdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD); - if (nullableExpression != null) { - nullable = (Boolean) nullableExpression.getValue(); - } else { - // default value of parameter - nullable = false; - changeNullable = true; - } - - PsiLiteralExpression signatureExpression = (PsiLiteralExpression) annotation.findAttributeValue(JvmStdlibNames.JET_VALUE_PARAMETER_TYPE_FIELD); - if (signatureExpression != null) { - typeFromAnnotation = (String) signatureExpression.getValue(); - } - - - PsiLiteralExpression receiverExpression = (PsiLiteralExpression) annotation.findAttributeValue(JvmStdlibNames.JET_VALUE_PARAMETER_RECEIVER_FIELD); - if (receiverExpression != null) { - receiver = (Boolean) receiverExpression.getValue(); - } - - hasDefaultValue = getBooleanAnnotationAttributeValue(annotation, JvmStdlibNames.JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD, false); - - - } else if (annotation.getQualifiedName().equals(JvmStdlibNames.JET_TYPE_PARAMETER.getFqName())) { - return JvmMethodParameterMeaning.typeInfo(new Object()); - } + if (parameter.getJetValueParameter().name().length() > 0) { + name = parameter.getJetValueParameter().name(); } + String typeFromAnnotation = parameter.getJetValueParameter().type(); + boolean receiver = parameter.getJetValueParameter().receiver(); + boolean hasDefaultValue = parameter.getJetValueParameter().hasDefaultValue(); + JetType outType; - if (typeFromAnnotation != null && typeFromAnnotation.length() > 0) { + if (typeFromAnnotation.length() > 0) { outType = semanticServices.getTypeTransformer().transformToType(typeFromAnnotation, typeVariableResolver); } else { outType = semanticServices.getTypeTransformer().transformToType(psiType); @@ -763,22 +769,13 @@ public class JavaDescriptorResolver { Collections.emptyList(), // TODO name, false, - changeNullable ? TypeUtils.makeNullableAsSpecified(outType, nullable) : outType, + nullable ? TypeUtils.makeNullableAsSpecified(outType, nullable) : outType, hasDefaultValue, varargElementType )); } } - private static boolean getBooleanAnnotationAttributeValue(PsiAnnotation annotation, String parameterName, boolean defaultValue) { - PsiLiteralExpression receiverExpression = (PsiLiteralExpression) annotation.findAttributeValue(parameterName); - if (receiverExpression != null) { - return (Boolean) receiverExpression.getValue(); - } else { - return defaultValue; - } - } - /* public VariableDescriptor resolveFieldToVariableDescriptor(DeclarationDescriptor containingDeclaration, PsiField field) { VariableDescriptor variableDescriptor = fieldDescriptorCache.get(field); @@ -865,87 +862,88 @@ public class JavaDescriptorResolver { } } - for (PsiMethod method : clazz.getMethods()) { - if (method.getModifierList().hasExplicitModifier(PsiModifier.STATIC) != staticMembers) { + for (PsiMethod psiMethod : clazz.getMethods()) { + PsiMethodWrapper method = new PsiMethodWrapper(psiMethod); + + if (method.isStatic() != staticMembers) { continue; } - if (method.hasModifierProperty(PsiModifier.PRIVATE)) { + if (method.isPrivate()) { continue; } // TODO: "is" prefix // TODO: remove getJavaClass - if (method.getName().startsWith(JvmAbi.GETTER_PREFIX)) { + if (psiMethod.getName().startsWith(JvmAbi.GETTER_PREFIX)) { + // TODO: some java properties too - if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null) { + if (method.getJetProperty().isDefined()) { PsiType receiverType; - if (method.getParameterList().getParametersCount() == 0) { + if (method.getParameters().size() == 0) { receiverType = null; - } else if (method.getParameterList().getParametersCount() == 1) { - if (method.getParameterList().getParameters()[0].getModifierList().findAnnotation(JvmStdlibNames.JET_TYPE_PARAMETER.getFqName()) != null) { + } else if (method.getParameters().size() == 1) { + if (method.getParameter(0).getJetTypeParameter().isDefined()) { receiverType = null; } else { - receiverType = method.getParameterList().getParameters()[0].getType(); + receiverType = method.getParameter(0).getPsiParameter().getType(); } - } else if (method.getParameterList().getParametersCount() == 2) { - if (method.getParameterList().getParameters()[1].getModifierList().findAnnotation(JvmStdlibNames.JET_TYPE_PARAMETER.getFqName()) == null) { + } else if (method.getParameters().size() == 2) { + if (!method.getParameter(1).getJetTypeParameter().isDefined()) { throw new IllegalStateException(); } - receiverType = method.getParameterList().getParameters()[0].getType(); + receiverType = psiMethod.getParameterList().getParameters()[0].getType(); } else { throw new IllegalStateException(); } - if (method.getName().equals(JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD)) { + if (psiMethod.getName().equals(JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD)) { continue; } - String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.GETTER_PREFIX.length())); - PropertyKey key = new PropertyKey(propertyName, method.getReturnType(), receiverType); + String propertyName = StringUtil.decapitalize(psiMethod.getName().substring(JvmAbi.GETTER_PREFIX.length())); + PropertyKey key = new PropertyKey(propertyName, psiMethod.getReturnType(), receiverType); MembersForProperty members = membersMap.get(key); if (members == null) { members = new MembersForProperty(); membersMap.put(key, members); } - members.getter = method; + members.getter = psiMethod; } - } else if (method.getName().startsWith(JvmAbi.SETTER_PREFIX)) { - if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null) { - if (method.getParameterList().getParametersCount() == 0) { + } else if (psiMethod.getName().startsWith(JvmAbi.SETTER_PREFIX)) { + + if (method.getJetProperty().isDefined()) { + if (psiMethod.getParameterList().getParametersCount() == 0) { throw new IllegalStateException(); } int i = 0; PsiType receiverType = null; - PsiParameter p1 = method.getParameterList().getParameters()[0]; - PsiAnnotation p1a = p1.getModifierList().findAnnotation(JvmStdlibNames.JET_VALUE_PARAMETER.getFqName()); - if (p1a != null) { - if (getBooleanAnnotationAttributeValue(p1a, JvmStdlibNames.JET_VALUE_PARAMETER_RECEIVER_FIELD, false)) { - receiverType = p1.getType(); - ++i; - } - } - - while (i < method.getParameterList().getParametersCount() && method.getParameterList().getParameters()[i].getModifierList().findAnnotation(JvmStdlibNames.JET_TYPE_PARAMETER.getFqName()) != null) { + PsiParameterWrapper p1 = method.getParameter(0); + if (p1.getJetValueParameter().receiver()) { + receiverType = p1.getPsiParameter().getType(); ++i; } - if (i + 1 != method.getParameterList().getParametersCount()) { + while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) { + ++i; + } + + if (i + 1 != psiMethod.getParameterList().getParametersCount()) { throw new IllegalStateException(); } - PsiType propertyType = method.getParameterList().getParameters()[i].getType(); + PsiType propertyType = psiMethod.getParameterList().getParameters()[i].getType(); - String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.SETTER_PREFIX.length())); + String propertyName = StringUtil.decapitalize(psiMethod.getName().substring(JvmAbi.SETTER_PREFIX.length())); PropertyKey key = new PropertyKey(propertyName, propertyType, receiverType); MembersForProperty members = membersMap.get(key); if (members == null) { members = new MembersForProperty(); membersMap.put(key, members); } - members.setter = method; + members.setter = psiMethod; } } } @@ -1116,14 +1114,16 @@ public class JavaDescriptorResolver { } @Nullable - public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethod method) { - PsiType returnType = method.getReturnType(); + public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethod psiMethod) { + PsiMethodWrapper method = new PsiMethodWrapper(psiMethod); + + PsiType returnType = psiMethod.getReturnType(); if (returnType == null) { return null; } - FunctionDescriptor functionDescriptor = methodDescriptorCache.get(method); + FunctionDescriptor functionDescriptor = methodDescriptorCache.get(psiMethod); if (functionDescriptor != null) { - if (method.getContainingClass() != psiClass) { + if (psiMethod.getContainingClass() != psiClass) { functionDescriptor = functionDescriptor.substitute(typeSubstitutorForGenericSuperclasses); } return functionDescriptor; @@ -1146,36 +1146,35 @@ public class JavaDescriptorResolver { } // TODO: ugly - if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null) { + if (method.getJetProperty().isDefined()) { return null; } DeclarationDescriptor classDescriptor; final List classTypeParameters; - if (method.hasModifierProperty(PsiModifier.STATIC)) { - classDescriptor = resolveNamespace(method.getContainingClass()); + if (method.isStatic()) { + classDescriptor = resolveNamespace(psiMethod.getContainingClass()); classTypeParameters = Collections.emptyList(); } else { - ClassDescriptor classClassDescriptor = resolveClass(method.getContainingClass()); + ClassDescriptor classClassDescriptor = resolveClass(psiMethod.getContainingClass()); classDescriptor = classClassDescriptor; classTypeParameters = classClassDescriptor.getTypeConstructor().getParameters(); } if (classDescriptor == null) { return null; } - PsiParameter[] parameters = method.getParameterList().getParameters(); NamedFunctionDescriptorImpl functionDescriptorImpl = new NamedFunctionDescriptorImpl( owner, Collections.emptyList(), // TODO - method.getName() + psiMethod.getName() ); - methodDescriptorCache.put(method, functionDescriptorImpl); + methodDescriptorCache.put(psiMethod, functionDescriptorImpl); // TODO: add outer classes TypeParameterListTypeVariableResolver typeVariableResolverForParameters = new TypeParameterListTypeVariableResolver(classTypeParameters); - final List methodTypeParameters = resolveMethodTypeParameters(method, functionDescriptorImpl, typeVariableResolverForParameters); + final List methodTypeParameters = resolveMethodTypeParameters(psiMethod, functionDescriptorImpl, typeVariableResolverForParameters); class MethodTypeVariableResolver implements TypeVariableResolver { @@ -1197,39 +1196,33 @@ public class JavaDescriptorResolver { } - ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(functionDescriptorImpl, parameters, new MethodTypeVariableResolver()); + ValueParameterDescriptors valueParameterDescriptors = resolveParameterDescriptors(functionDescriptorImpl, method.getParameters(), new MethodTypeVariableResolver()); functionDescriptorImpl.initialize( valueParameterDescriptors.receiverType, DescriptorUtils.getExpectedThisObjectIfNeeded(classDescriptor), methodTypeParameters, valueParameterDescriptors.descriptors, makeReturnType(returnType, method, new MethodTypeVariableResolver()), - Modality.convertFromFlags(method.hasModifierProperty(PsiModifier.ABSTRACT), !method.hasModifierProperty(PsiModifier.FINAL)), - resolveVisibilityFromPsiModifiers(method) + Modality.convertFromFlags(psiMethod.hasModifierProperty(PsiModifier.ABSTRACT), !psiMethod.hasModifierProperty(PsiModifier.FINAL)), + resolveVisibilityFromPsiModifiers(psiMethod) ); - semanticServices.getTrace().record(BindingContext.FUNCTION, method, functionDescriptorImpl); + semanticServices.getTrace().record(BindingContext.FUNCTION, psiMethod, functionDescriptorImpl); FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl; - if (method.getContainingClass() != psiClass) { + if (psiMethod.getContainingClass() != psiClass) { substitutedFunctionDescriptor = functionDescriptorImpl.substitute(typeSubstitutorForGenericSuperclasses); } return substitutedFunctionDescriptor; } private List resolveMethodTypeParameters(PsiMethod method, FunctionDescriptorImpl functionDescriptorImpl, TypeVariableResolver classTypeVariableResolver) { - for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) { - if (annotation.getQualifiedName().equals(JvmStdlibNames.JET_METHOD.getFqName())) { - PsiLiteralExpression attributeValue = (PsiLiteralExpression) annotation.findAttributeValue(JvmStdlibNames.JET_METHOD_TYPE_PARAMETERS_FIELD); - if (attributeValue != null) { - String typeParametersString = (String) attributeValue.getValue(); - if (typeParametersString != null) { - List r = resolveMethodTypeParametersFromJetSignature(typeParametersString, method, functionDescriptorImpl, classTypeVariableResolver); - initializeTypeParameters(method); - return r; - } - } - } + JetMethodAnnotation jetMethodAnnotation = JetMethodAnnotation.get(method); + if (jetMethodAnnotation.typeParameters().length() > 0) { + List r = resolveMethodTypeParametersFromJetSignature( + jetMethodAnnotation.typeParameters(), method, functionDescriptorImpl, classTypeVariableResolver); + initializeTypeParameters(method); + return r; } - + List typeParameters = makeUninitializedTypeParameters(functionDescriptorImpl, method.getTypeParameters()); initializeTypeParameters(method); return typeParameters; @@ -1273,37 +1266,18 @@ public class JavaDescriptorResolver { return r; } - private JetType makeReturnType(PsiType returnType, PsiMethod method, TypeVariableResolver typeVariableResolver) { - boolean changeNullable = false; - boolean nullable = true; - - String returnTypeFromAnnotation = null; + private JetType makeReturnType(PsiType returnType, PsiMethodWrapper method, TypeVariableResolver typeVariableResolver) { + + String returnTypeFromAnnotation = method.getJetMethod().returnType(); - for (PsiAnnotation annotation : method.getModifierList().getAnnotations()) { - if (annotation.getQualifiedName().equals(JvmStdlibNames.JET_METHOD.getFqName())) { - PsiLiteralExpression nullableExpression = (PsiLiteralExpression) annotation.findAttributeValue(JvmStdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD); - if (nullableExpression != null) { - nullable = (Boolean) nullableExpression.getValue(); - } else { - // default value of parameter - nullable = false; - changeNullable = true; - } - - PsiLiteralExpression returnTypeExpression = (PsiLiteralExpression) annotation.findAttributeValue(JvmStdlibNames.JET_METHOD_RETURN_TYPE_FIELD); - if (returnTypeExpression != null) { - returnTypeFromAnnotation = (String) returnTypeExpression.getValue(); - } - } - } JetType transformedType; - if (returnTypeFromAnnotation != null && returnTypeFromAnnotation.length() > 0) { + if (returnTypeFromAnnotation.length() > 0) { transformedType = semanticServices.getTypeTransformer().transformToType(returnTypeFromAnnotation, typeVariableResolver); } else { transformedType = semanticServices.getTypeTransformer().transformToType(returnType); } - if (changeNullable) { - return TypeUtils.makeNullableAsSpecified(transformedType, nullable); + if (method.getJetMethod().returnTypeNullable()) { + return TypeUtils.makeNullableAsSpecified(transformedType, true); } else { return transformedType; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiMethodWrapper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiMethodWrapper.java new file mode 100644 index 00000000000..c0d5c8c82c0 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiMethodWrapper.java @@ -0,0 +1,77 @@ +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiModifier; +import com.intellij.psi.PsiParameter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.resolve.java.kt.JetConstructorAnnotation; +import org.jetbrains.jet.lang.resolve.java.kt.JetMethodAnnotation; +import org.jetbrains.jet.lang.resolve.java.kt.JetPropertyAnnotation; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Stepan Koltsov + */ +public class PsiMethodWrapper { + @NotNull + private final PsiMethod psiMethod; + + public PsiMethodWrapper(@NotNull PsiMethod psiMethod) { + this.psiMethod = psiMethod; + } + + private List parameters; + @NotNull + public List getParameters() { + if (parameters == null) { + PsiParameter[] psiParameters = psiMethod.getParameterList().getParameters(); + parameters = new ArrayList(psiParameters.length); + for (int i = 0; i < psiParameters.length; ++i) { + parameters.add(new PsiParameterWrapper(psiParameters[i])); + } + } + return parameters; + } + + @NotNull + public PsiParameterWrapper getParameter(int i) { + return getParameters().get(i); + } + + public boolean isStatic() { + return psiMethod.getModifierList().hasExplicitModifier(PsiModifier.STATIC); + } + + public boolean isPrivate() { + return psiMethod.hasModifierProperty(PsiModifier.PRIVATE); + } + + private JetMethodAnnotation jetMethod; + @NotNull + public JetMethodAnnotation getJetMethod() { + if (jetMethod == null) { + jetMethod = JetMethodAnnotation.get(psiMethod); + } + return jetMethod; + } + + private JetConstructorAnnotation jetConstructor; + @NotNull + public JetConstructorAnnotation getJetConstructor() { + if (jetConstructor == null) { + jetConstructor = JetConstructorAnnotation.get(psiMethod); + } + return jetConstructor; + } + + private JetPropertyAnnotation jetProperty; + @NotNull + public JetPropertyAnnotation getJetProperty() { + if (jetProperty == null) { + jetProperty = JetPropertyAnnotation.get(psiMethod); + } + return jetProperty; + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiParameterWrapper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiParameterWrapper.java new file mode 100644 index 00000000000..56f03009847 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiParameterWrapper.java @@ -0,0 +1,38 @@ +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.psi.PsiParameter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.jet.lang.resolve.java.kt.JetTypeParameterAnnotation; +import org.jetbrains.jet.lang.resolve.java.kt.JetValueParameterAnnotation; + +/** + * @author Stepan Koltsov + */ +public class PsiParameterWrapper { + private final PsiParameter psiParameter; + + public PsiParameterWrapper(@NotNull PsiParameter psiParameter) { + this.psiParameter = psiParameter; + + this.jetValueParameter = JetValueParameterAnnotation.get(psiParameter); + this.jetTypeParameter = JetTypeParameterAnnotation.get(psiParameter); + } + + private JetValueParameterAnnotation jetValueParameter; + private JetTypeParameterAnnotation jetTypeParameter; + + @NotNull + public PsiParameter getPsiParameter() { + return psiParameter; + } + + @NotNull + public JetValueParameterAnnotation getJetValueParameter() { + return jetValueParameter; + } + + @NotNull + public JetTypeParameterAnnotation getJetTypeParameter() { + return jetTypeParameter; + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetClassAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetClassAnnotation.java new file mode 100644 index 00000000000..65ed9874a6c --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetClassAnnotation.java @@ -0,0 +1,30 @@ +package org.jetbrains.jet.lang.resolve.java.kt; + +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiClass; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; + +/** + * @author Stepan Koltsov + */ +public class JetClassAnnotation extends PsiAnnotationWrapper { + + public JetClassAnnotation(@Nullable PsiAnnotation psiAnnotation) { + super(psiAnnotation); + } + + private String signature; + public String signature() { + if (signature == null) { + signature = getStringAttribute(JvmStdlibNames.JET_CLASS_SIGNATURE, ""); + } + return signature; + } + + @NotNull + public static JetClassAnnotation get(PsiClass psiClass) { + return new JetClassAnnotation(psiClass.getModifierList().findAnnotation(JvmStdlibNames.JET_CLASS.getFqName())); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetConstructorAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetConstructorAnnotation.java new file mode 100644 index 00000000000..400c73e3f84 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetConstructorAnnotation.java @@ -0,0 +1,31 @@ +package org.jetbrains.jet.lang.resolve.java.kt; + +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiMethod; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; + +/** + * @author Stepan Koltsov + */ +public class JetConstructorAnnotation extends PsiAnnotationWrapper { + + public JetConstructorAnnotation(@Nullable PsiAnnotation psiAnnotation) { + super(psiAnnotation); + } + + private boolean hidden; + private boolean hiddenInitialized = false; + /** @deprecated */ + public boolean hidden() { + if (!hiddenInitialized) { + hidden = getBooleanAttribute(JvmStdlibNames.JET_CONSTRUCTOR_HIDDEN_FIELD, false); + hiddenInitialized = true; + } + return hidden; + } + + public static JetConstructorAnnotation get(PsiMethod constructor) { + return new JetConstructorAnnotation(constructor.getModifierList().findAnnotation(JvmStdlibNames.JET_CONSTRUCTOR.getFqName())); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetMethodAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetMethodAnnotation.java new file mode 100644 index 00000000000..189a744258b --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetMethodAnnotation.java @@ -0,0 +1,50 @@ +package org.jetbrains.jet.lang.resolve.java.kt; + +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiMethod; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; + +/** + * @author Stepan Koltsov + */ +public class JetMethodAnnotation extends PsiAnnotationWrapper { + + public JetMethodAnnotation(@Nullable PsiAnnotation psiAnnotation) { + super(psiAnnotation); + } + + private String typeParameters; + @NotNull + public String typeParameters() { + if (typeParameters == null) { + typeParameters = getStringAttribute(JvmStdlibNames.JET_METHOD_TYPE_PARAMETERS_FIELD, ""); + } + return typeParameters; + } + + private String returnType; + @NotNull + public String returnType() { + if (returnType == null) { + returnType = getStringAttribute(JvmStdlibNames.JET_METHOD_RETURN_TYPE_FIELD, ""); + } + return returnType; + } + + private boolean returnTypeNullable; + private boolean returnTypeNullableInitialized; + @NotNull + public boolean returnTypeNullable() { + if (!returnTypeNullableInitialized) { + returnTypeNullable = getBooleanAttribute(JvmStdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD, false); + returnTypeNullableInitialized = true; + } + return returnTypeNullable; + } + + public static JetMethodAnnotation get(PsiMethod psiMethod) { + return new JetMethodAnnotation(psiMethod.getModifierList().findAnnotation(JvmStdlibNames.JET_METHOD.getFqName())); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetPropertyAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetPropertyAnnotation.java new file mode 100644 index 00000000000..945051bbf94 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetPropertyAnnotation.java @@ -0,0 +1,21 @@ +package org.jetbrains.jet.lang.resolve.java.kt; + +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiMethod; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; + +/** + * @author Stepan Koltsov + */ +public class JetPropertyAnnotation extends PsiAnnotationWrapper { + protected JetPropertyAnnotation(@Nullable PsiAnnotation psiAnnotation) { + super(psiAnnotation); + } + + @NotNull + public static JetPropertyAnnotation get(@NotNull PsiMethod psiMethod) { + return new JetPropertyAnnotation(psiMethod.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName())); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetTypeParameterAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetTypeParameterAnnotation.java new file mode 100644 index 00000000000..e7ad45cc60b --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetTypeParameterAnnotation.java @@ -0,0 +1,22 @@ +package org.jetbrains.jet.lang.resolve.java.kt; + +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiParameter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; + +/** + * @author Stepan Koltsov + */ +public class JetTypeParameterAnnotation extends PsiAnnotationWrapper { + + protected JetTypeParameterAnnotation(@Nullable PsiAnnotation psiAnnotation) { + super(psiAnnotation); + } + + @NotNull + public static JetTypeParameterAnnotation get(@NotNull PsiParameter psiParameter) { + return new JetTypeParameterAnnotation(psiParameter.getModifierList().findAnnotation(JvmStdlibNames.JET_TYPE_PARAMETER.getFqName())); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetValueParameterAnnotation.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetValueParameterAnnotation.java new file mode 100644 index 00000000000..174d047b9f1 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/JetValueParameterAnnotation.java @@ -0,0 +1,70 @@ +package org.jetbrains.jet.lang.resolve.java.kt; + +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiParameter; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.java.JvmStdlibNames; + +/** + * @author Stepan Koltsov + */ +public class JetValueParameterAnnotation extends PsiAnnotationWrapper { + + public JetValueParameterAnnotation(@Nullable PsiAnnotation psiAnnotation) { + super(psiAnnotation); + } + + private String name; + @NotNull + public String name() { + if (name == null) { + name = getStringAttribute(JvmStdlibNames.JET_VALUE_PARAMETER_NAME_FIELD, ""); + } + return name; + } + + private String type; + @NotNull + public String type() { + if (type == null) { + type = getStringAttribute(JvmStdlibNames.JET_VALUE_PARAMETER_TYPE_FIELD, ""); + } + return type; + } + + private boolean nullable; + private boolean nullableInitialized = false; + public boolean nullable() { + if (!nullableInitialized) { + nullable = getBooleanAttribute(JvmStdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, false); + nullableInitialized = true; + } + return nullable; + } + + private boolean receiver; + private boolean receiverInitialized = false; + public boolean receiver() { + if (!receiverInitialized) { + receiver = getBooleanAttribute(JvmStdlibNames.JET_VALUE_PARAMETER_RECEIVER_FIELD, false); + receiverInitialized = true; + } + return receiver; + } + + private boolean hasDefaultValue; + private boolean hasDefaultValueInitialized = false; + public boolean hasDefaultValue() { + if (!hasDefaultValueInitialized) { + hasDefaultValue = getBooleanAttribute(JvmStdlibNames.JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD, false); + hasDefaultValueInitialized = true; + } + return hasDefaultValue; + } + + public static JetValueParameterAnnotation get(PsiParameter psiParameter) { + return new JetValueParameterAnnotation(psiParameter.getModifierList().findAnnotation(JvmStdlibNames.JET_VALUE_PARAMETER.getFqName())); + } + +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/PsiAnnotationUtils.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/PsiAnnotationUtils.java new file mode 100644 index 00000000000..ec611685b02 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/PsiAnnotationUtils.java @@ -0,0 +1,35 @@ +package org.jetbrains.jet.lang.resolve.java.kt; + +import com.intellij.psi.PsiAnnotation; +import com.intellij.psi.PsiLiteralExpression; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Stepan Koltsov + */ +public class PsiAnnotationUtils { + + @NotNull + public static String getStringAttribute(@Nullable PsiAnnotation annotation, @NotNull String field, @NotNull String defaultValue) { + return getAttribute(annotation, field, defaultValue); + } + + public static boolean getBooleanAttribute(@Nullable PsiAnnotation annotation, @NotNull String field, boolean defaultValue) { + return getAttribute(annotation, field, defaultValue); + } + + private static T getAttribute(@Nullable PsiAnnotation annotation, @NotNull String field, @NotNull T defaultValue) { + if (annotation == null) { + return defaultValue; + } else { + PsiLiteralExpression attributeValue = (PsiLiteralExpression) annotation.findAttributeValue(field); + if (attributeValue != null) { + return (T) attributeValue.getValue(); + } else { + return defaultValue; + } + } + } + +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/PsiAnnotationWrapper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/PsiAnnotationWrapper.java new file mode 100644 index 00000000000..005b49c587f --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/kt/PsiAnnotationWrapper.java @@ -0,0 +1,36 @@ +package org.jetbrains.jet.lang.resolve.java.kt; + +import com.intellij.psi.PsiAnnotation; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Stepan Koltsov + */ +public abstract class PsiAnnotationWrapper { + + @Nullable + private PsiAnnotation psiAnnotation; + + protected PsiAnnotationWrapper(@Nullable PsiAnnotation psiAnnotation) { + this.psiAnnotation = psiAnnotation; + } + + @Nullable + public PsiAnnotation getPsiAnnotation() { + return psiAnnotation; + } + + public boolean isDefined() { + return psiAnnotation != null; + } + + @NotNull + protected String getStringAttribute(String name, String defaultValue) { + return PsiAnnotationUtils.getStringAttribute(psiAnnotation, name, defaultValue); + } + + protected boolean getBooleanAttribute(String name, boolean defaultValue) { + return PsiAnnotationUtils.getBooleanAttribute(psiAnnotation, name, defaultValue); + } +}