From 200fd78574baab2461979cb8e4e4ada4492b6132 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Thu, 12 Jan 2012 01:25:47 +0400 Subject: [PATCH] ReadClassDataTest: extension properties --- .../jet/codegen/FunctionCodegen.java | 27 ++-- .../resolve/java/JavaDescriptorResolver.java | 129 ++++++++++++------ .../lang/resolve/java/JavaPackageScope.java | 8 -- compiler/testData/readClass/prop/ExtVal.kt | 4 + .../testData/readClass/prop/ExtValInClass.kt | 6 + compiler/testData/readClass/prop/ExtVar.kt | 5 + .../testData/readClass/prop/ExtVarInClass.kt | 7 + .../org/jetbrains/jet/ReadClassDataTest.java | 4 + 8 files changed, 134 insertions(+), 56 deletions(-) create mode 100644 compiler/testData/readClass/prop/ExtVal.kt create mode 100644 compiler/testData/readClass/prop/ExtValInClass.kt create mode 100644 compiler/testData/readClass/prop/ExtVar.kt create mode 100644 compiler/testData/readClass/prop/ExtVarInClass.kt diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 83337012490..70d754e258e 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -91,17 +91,24 @@ public class FunctionCodegen { if(v.generateCode()) { int start = 0; if(kind != OwnerKind.TRAIT_IMPL) { - AnnotationVisitor av = mv.visitAnnotation(JvmStdlibNames.JET_METHOD.getDescriptor(), true); - if(functionDescriptor.getReturnType().isNullable()) { - av.visit(JvmStdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD, true); + if (functionDescriptor instanceof PropertyAccessorDescriptor) { + AnnotationVisitor av = mv.visitAnnotation(JvmStdlibNames.JET_PROPERTY.getDescriptor(), true); + av.visitEnd(); + } else if (functionDescriptor instanceof NamedFunctionDescriptor) { + AnnotationVisitor av = mv.visitAnnotation(JvmStdlibNames.JET_METHOD.getDescriptor(), true); + if(functionDescriptor.getReturnType().isNullable()) { + av.visit(JvmStdlibNames.JET_METHOD_NULLABLE_RETURN_TYPE_FIELD, true); + } + if (jvmSignature.getKotlinReturnType() != null) { + av.visit(JvmStdlibNames.JET_METHOD_RETURN_TYPE_FIELD, jvmSignature.getKotlinReturnType()); + } + if (jvmSignature.getKotlinTypeParameter() != null) { + av.visit(JvmStdlibNames.JET_METHOD_TYPE_PARAMETERS_FIELD, jvmSignature.getKotlinTypeParameter()); + } + av.visitEnd(); + } else { + throw new IllegalStateException(); } - if (jvmSignature.getKotlinReturnType() != null) { - av.visit(JvmStdlibNames.JET_METHOD_RETURN_TYPE_FIELD, jvmSignature.getKotlinReturnType()); - } - if (jvmSignature.getKotlinTypeParameter() != null) { - av.visit(JvmStdlibNames.JET_METHOD_TYPE_PARAMETERS_FIELD, jvmSignature.getKotlinTypeParameter()); - } - av.visitEnd(); } if(kind == OwnerKind.TRAIT_IMPL) { 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 1160483008f..85a67f77def 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 @@ -740,10 +740,7 @@ public class JavaDescriptorResolver { receiver = (Boolean) receiverExpression.getValue(); } - PsiLiteralExpression hasDefaultValueExpression = (PsiLiteralExpression) annotation.findAttributeValue(JvmStdlibNames.JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD); - if (hasDefaultValueExpression != null) { - hasDefaultValue = (Boolean) hasDefaultValueExpression.getValue(); - } + hasDefaultValue = getBooleanAnnotationAttributeValue(annotation, JvmStdlibNames.JET_VALUE_PARAMETER_HAS_DEFAULT_VALUE_FIELD, false); } else if (annotation.getQualifiedName().equals(JvmStdlibNames.JET_TYPE_PARAMETER.getFqName())) { @@ -773,6 +770,15 @@ public class JavaDescriptorResolver { } } + 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); @@ -802,21 +808,25 @@ public class JavaDescriptorResolver { private final String name; @NotNull private final PsiType type; + @Nullable + private final PsiType receiverType; - private PropertyKey(String name, PsiType type) { + private PropertyKey(@NotNull String name, @NotNull PsiType type, @Nullable PsiType receiverType) { this.name = name; this.type = type; + this.receiverType = receiverType; } @Override public boolean equals(Object o) { - // generated by Idea if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; PropertyKey that = (PropertyKey) o; if (!name.equals(that.name)) return false; + if (receiverType != null ? !receiverType.equals(that.receiverType) : that.receiverType != null) + return false; if (!type.equals(that.type)) return false; return true; @@ -826,6 +836,7 @@ public class JavaDescriptorResolver { public int hashCode() { int result = name.hashCode(); result = 31 * result + type.hashCode(); + result = 31 * result + (receiverType != null ? receiverType.hashCode() : 0); return result; } } @@ -850,7 +861,7 @@ public class JavaDescriptorResolver { MembersForProperty members = new MembersForProperty(); members.field = field; - membersMap.put(new PropertyKey(field.getName(), field.getType()), members); + membersMap.put(new PropertyKey(field.getName(), field.getType(), null), members); } } @@ -864,36 +875,77 @@ public class JavaDescriptorResolver { } // TODO: "is" prefix + // TODO: remove getJavaClass if (method.getName().startsWith(JvmAbi.GETTER_PREFIX)) { // TODO: some java properties too if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null) { + PsiType receiverType; if (method.getParameterList().getParametersCount() == 0) { - if (method.getName().equals(JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD)) { - continue; + receiverType = null; + } else if (method.getParameterList().getParametersCount() == 1) { + if (method.getParameterList().getParameters()[0].getModifierList().findAnnotation(JvmStdlibNames.JET_TYPE_PARAMETER.getFqName()) != null) { + receiverType = null; + } else { + receiverType = method.getParameterList().getParameters()[0].getType(); } - - String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.GETTER_PREFIX.length())); - PropertyKey key = new PropertyKey(propertyName, method.getReturnType()); - MembersForProperty members = membersMap.get(key); - if (members == null) { - members = new MembersForProperty(); - membersMap.put(key, members); + } else if (method.getParameterList().getParametersCount() == 2) { + if (method.getParameterList().getParameters()[1].getModifierList().findAnnotation(JvmStdlibNames.JET_TYPE_PARAMETER.getFqName()) == null) { + throw new IllegalStateException(); } - members.getter = method; + receiverType = method.getParameterList().getParameters()[0].getType(); + } else { + throw new IllegalStateException(); } + + if (method.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); + MembersForProperty members = membersMap.get(key); + if (members == null) { + members = new MembersForProperty(); + membersMap.put(key, members); + } + members.getter = method; } } else if (method.getName().startsWith(JvmAbi.SETTER_PREFIX)) { if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null) { - if (method.getParameterList().getParametersCount() == 1) { - String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.SETTER_PREFIX.length())); - PropertyKey key = new PropertyKey(propertyName, method.getParameterList().getParameters()[0].getType()); - MembersForProperty members = membersMap.get(key); - if (members == null) { - members = new MembersForProperty(); - membersMap.put(key, members); - } - members.setter = method; + if (method.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) { + ++i; + } + + if (i + 1 != method.getParameterList().getParametersCount()) { + throw new IllegalStateException(); + } + + PsiType propertyType = method.getParameterList().getParameters()[i].getType(); + + String propertyName = StringUtil.decapitalize(method.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; } } } @@ -940,6 +992,7 @@ public class JavaDescriptorResolver { //} String propertyName = entry.getKey().name; PsiType propertyType = entry.getKey().type; + PsiType receiverType = entry.getKey().receiverType; MembersForProperty members = entry.getValue(); JetType type = semanticServices.getTypeTransformer().transformToType(propertyType); @@ -972,6 +1025,13 @@ public class JavaDescriptorResolver { isVar = members.setter != null; } + JetType receiverJetType; + if (receiverType == null) { + receiverJetType = null; + } else { + receiverJetType = semanticServices.getTypeTransformer().transformToType(receiverType); + } + PropertyDescriptor propertyDescriptor = new PropertyDescriptor( owner, Collections.emptyList(), @@ -979,7 +1039,7 @@ public class JavaDescriptorResolver { resolveVisibilityFromPsiModifiers(anyMember), isVar, false, - null, + receiverJetType, DescriptorUtils.getExpectedThisObjectIfNeeded(owner), propertyName, type); @@ -1085,18 +1145,11 @@ public class JavaDescriptorResolver { kotlin = classData.kotlin; } - // TODO: hide getters and setters properly - if (kotlin) { - if (method.getName().startsWith(JvmAbi.GETTER_PREFIX) && method.getParameterList().getParametersCount() == 0) { - if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null) - return null; - } - if (method.getName().startsWith(JvmAbi.SETTER_PREFIX) && method.getParameterList().getParametersCount() == 1) { - if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null) - return null; - } + // TODO: ugly + if (method.getModifierList().findAnnotation(JvmStdlibNames.JET_PROPERTY.getFqName()) != null) { + return null; } - + DeclarationDescriptor classDescriptor; final List classTypeParameters; if (method.hasModifierProperty(PsiModifier.STATIC)) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java index 31bb50ad3db..cfd692ece93 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaPackageScope.java @@ -86,14 +86,6 @@ public class JavaPackageScope extends JetScopeImpl { return Collections.emptySet(); } - PsiField field = psiClassForPackage.findFieldByName(name, true); - if (field == null) { - return Collections.emptySet(); - } - if (!field.hasModifierProperty(PsiModifier.STATIC)) { - return Collections.emptySet(); - } - // TODO: cache return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDescriptor, psiClassForPackage, name, true); } diff --git a/compiler/testData/readClass/prop/ExtVal.kt b/compiler/testData/readClass/prop/ExtVal.kt new file mode 100644 index 00000000000..7a66f817fa2 --- /dev/null +++ b/compiler/testData/readClass/prop/ExtVal.kt @@ -0,0 +1,4 @@ +package test + +val Int.itIs: Int + get() = this diff --git a/compiler/testData/readClass/prop/ExtValInClass.kt b/compiler/testData/readClass/prop/ExtValInClass.kt new file mode 100644 index 00000000000..5bdd27596da --- /dev/null +++ b/compiler/testData/readClass/prop/ExtValInClass.kt @@ -0,0 +1,6 @@ +package test + +class ExtPropInClass { + val Int.itIs: Int + get() = this +} diff --git a/compiler/testData/readClass/prop/ExtVar.kt b/compiler/testData/readClass/prop/ExtVar.kt new file mode 100644 index 00000000000..229a26e8dc6 --- /dev/null +++ b/compiler/testData/readClass/prop/ExtVar.kt @@ -0,0 +1,5 @@ +package test + +var Int.ggg: Int + get() = throw Exception() + set(p) = throw Exception() diff --git a/compiler/testData/readClass/prop/ExtVarInClass.kt b/compiler/testData/readClass/prop/ExtVarInClass.kt new file mode 100644 index 00000000000..2e739bf5302 --- /dev/null +++ b/compiler/testData/readClass/prop/ExtVarInClass.kt @@ -0,0 +1,7 @@ +package test + +class ExtPropInClass { + var Int.itIs: Int + get() = throw Exception() + set(p: Int) = throw Exception() +} diff --git a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java index d6b191d143b..39ce1527cb2 100644 --- a/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java +++ b/compiler/tests/org/jetbrains/jet/ReadClassDataTest.java @@ -282,6 +282,10 @@ public class ReadClassDataTest extends TestCaseWithTmpdir { } else { sb.append("val "); } + if (prop.getReceiverParameter().exists()) { + serialize(prop.getReceiverParameter().getType()); + sb.append("."); + } sb.append(prop.getName()); sb.append(": "); serialize(prop.getOutType());