From d6846bbf64d28753694eab81d2847406a6bdee7b Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Wed, 31 Oct 2012 20:30:00 +0400 Subject: [PATCH] Refactor JavaPropertyResolver --- .../java/resolver/JavaPropertyResolver.java | 410 ++++++++++-------- .../resolve/java/wrapper/PropertyPsiData.java | 16 + 2 files changed, 251 insertions(+), 175 deletions(-) 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 1d5cd3e4268..79ddc61790c 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 @@ -96,7 +96,7 @@ public final class JavaPropertyResolver { //noinspection ConstantConditions String qualifiedName = psiClass == null ? scopeData.getPsiPackage().getQualifiedName() : psiClass.getQualifiedName(); return resolveNamedGroupProperties(scopeData.getClassOrNamespaceDescriptor(), scopeData, namedMembers, fieldName, - "class or namespace " + qualifiedName); + "class or namespace " + qualifiedName); } @NotNull @@ -113,185 +113,253 @@ public final class JavaPropertyResolver { int regularPropertiesCount = getNumberOfNonExtensionProperties(psiDataCollection); - for (PropertyPsiData members : psiDataCollection) { + for (PropertyPsiData propertyPsiData : psiDataCollection) { // we cannot have more then one property with given name even if java code // has several fields, getters and setter of different types - if (!members.isExtension() && regularPropertiesCount > 1) { + if (!propertyPsiData.isExtension() && regularPropertiesCount > 1) { continue; } - boolean isFinal = isPropertyFinal(scopeData, members); - boolean isVar = members.isVar(); - - PropertyPsiDataElement characteristicMember = members.getCharacteristicMember(); - - Visibility visibility = DescriptorResolverUtils.resolveVisibility(members.getCharacteristicPsi(), null); - CallableMemberDescriptor.Kind kind = CallableMemberDescriptor.Kind.DECLARATION; - - PropertyPsiDataElement getter = members.getGetter(); - if (getter != null) { - JetMethodAnnotation jetMethod = ((PsiMethodWrapper) getter.getMember()).getJetMethodAnnotation(); - visibility = DescriptorResolverUtils.resolveVisibility(members.getCharacteristicPsi(), jetMethod); - kind = DescriptorKindUtils.flagsToKind(jetMethod.kind()); - } - - DeclarationDescriptor realOwner = getRealOwner(owner, scopeData, members.isStatic()); - boolean isEnumEntry = DescriptorUtils.isEnumClassObject(realOwner); - boolean isPropertyForNamedObject = members.getField() != null && JvmAbi.INSTANCE_FIELD.equals(members.getField().getMember().getName()); - PropertyDescriptor propertyDescriptor = new PropertyDescriptor( - realOwner, - annotationResolver.resolveAnnotations(characteristicMember.getMember().getPsiMember()), - DescriptorResolverUtils - .resolveModality(characteristicMember.getMember(), isFinal || isEnumEntry || isPropertyForNamedObject), - visibility, - isVar, - propertyName, - kind); - - //TODO: this is a hack to indicate that this enum entry is an object - // class descriptor for enum entries is not used by backends so for now this should be safe to use - // remove this when JavaDescriptorResolver gets rewritten - if (isEnumEntry) { - ClassDescriptorImpl dummyClassDescriptorForEnumEntryObject = - new ClassDescriptorImpl(realOwner, Collections.emptyList(), Modality.FINAL, propertyName); - dummyClassDescriptorForEnumEntryObject.initialize( - true, - Collections.emptyList(), - Collections.emptyList(), JetScope.EMPTY, - Collections.emptySet(), null); - trace.record(BindingContext.OBJECT_DECLARATION_CLASS, propertyDescriptor, dummyClassDescriptorForEnumEntryObject); - } - - PropertyGetterDescriptor getterDescriptor = null; - PropertySetterDescriptor setterDescriptor = null; - - if (getter != null) { - getterDescriptor = new PropertyGetterDescriptor( - propertyDescriptor, - annotationResolver.resolveAnnotations(getter.getMember().getPsiMember()), - Modality.OPEN, - visibility, - true, - false, - kind); - } - - PropertyPsiDataElement setter = members.getSetter(); - if (setter != null) { - Visibility setterVisibility = DescriptorResolverUtils.resolveVisibility(setter.getMember().getPsiMember(), null); - if (setter.getMember() instanceof PsiMethodWrapper) { - setterVisibility = DescriptorResolverUtils.resolveVisibility( - setter.getMember().getPsiMember(), - ((PsiMethodWrapper) setter.getMember()) - .getJetMethodAnnotation()); - } - setterDescriptor = new PropertySetterDescriptor( - propertyDescriptor, - annotationResolver.resolveAnnotations(setter.getMember().getPsiMember()), - Modality.OPEN, - setterVisibility, - true, - false, - kind); - } - - propertyDescriptor.initialize(getterDescriptor, setterDescriptor); - - List typeParameters = resolvePropertyTypeParameters(members, characteristicMember, propertyDescriptor); - - TypeVariableResolver typeVariableResolverForPropertyInternals = TypeVariableResolvers.typeVariableResolverFromTypeParameters( - typeParameters, propertyDescriptor, "property " + propertyName + " in " + context); - - JetType propertyType = getPropertyType(members, characteristicMember, typeVariableResolverForPropertyInternals); - JetType receiverType = getReceiverType(characteristicMember, typeVariableResolverForPropertyInternals); - - - if (characteristicMember.isField()) { - AlternativeFieldSignatureData signatureData = - new AlternativeFieldSignatureData((PsiFieldWrapper) characteristicMember.getMember(), propertyType, isVar); - if (!signatureData.hasErrors()) { - if (signatureData.isAnnotated()) { - propertyType = signatureData.getReturnType(); - } - } - else { - trace.record(BindingContext.ALTERNATIVE_SIGNATURE_DATA_ERROR, propertyDescriptor, signatureData.getError()); - } - } - - propertyDescriptor.setType( - propertyType, - typeParameters, - DescriptorUtils.getExpectedThisObjectIfNeeded(realOwner), - receiverType - ); - if (getterDescriptor != null) { - getterDescriptor.initialize(propertyType); - } - if (setterDescriptor != null) { - setterDescriptor.initialize(new ValueParameterDescriptorImpl( - setterDescriptor, - 0, - Collections.emptyList(), - Name.identifier("p0") /*TODO*/, - false, - propertyDescriptor.getType(), - false, - null)); - } - - if (kind == CallableMemberDescriptor.Kind.DECLARATION) { - trace.record(BindingContext.VARIABLE, characteristicMember.getMember().getPsiMember(), propertyDescriptor); - } - - if (isPropertyForNamedObject) { - ClassDescriptor objectDescriptor = (ClassDescriptor) propertyType.getConstructor().getDeclarationDescriptor(); - - assert objectDescriptor.getKind() == ClassKind.OBJECT; - assert objectDescriptor.getContainingDeclaration() == realOwner; - - trace.record(BindingContext.OBJECT_DECLARATION_CLASS, propertyDescriptor, objectDescriptor); - } - - if (!scopeData.isKotlin()) { - trace.record(BindingContext.IS_DECLARED_IN_JAVA, propertyDescriptor); - } - - propertiesFromCurrent.add(propertyDescriptor); + propertiesFromCurrent.add(resolveProperty(owner, scopeData, propertyName, context, propertyPsiData)); } Set propertiesFromSupertypes = getPropertiesFromSupertypes(scopeData, propertyName); + Set properties = Sets.newHashSet(); - final Set properties = Sets.newHashSet(); - - if (owner instanceof ClassDescriptor) { - ClassDescriptor classDescriptor = (ClassDescriptor) owner; - - OverrideResolver.generateOverridesInFunctionGroup( - propertyName, propertiesFromSupertypes, propertiesFromCurrent, classDescriptor, - new OverrideResolver.DescriptorSink() { - @Override - public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) { - properties.add((PropertyDescriptor) fakeOverride); - } - - @Override - public void conflict( - @NotNull CallableMemberDescriptor fromSuper, - @NotNull CallableMemberDescriptor fromCurrent - ) { - // nop - } - }); - } - + generateOverrides(owner, propertyName, propertiesFromCurrent, propertiesFromSupertypes, properties); OverrideResolver.resolveUnknownVisibilities(properties, trace); + properties.addAll(propertiesFromCurrent); return Sets.newHashSet(properties); } + private static void generateOverrides( + @NotNull ClassOrNamespaceDescriptor owner, + @NotNull Name propertyName, + @NotNull Set propertiesFromCurrent, + @NotNull Set propertiesFromSupertypes, + @NotNull final Set properties + ) { + if (!(owner instanceof ClassDescriptor)) { + return; + } + ClassDescriptor classDescriptor = (ClassDescriptor) owner; + + OverrideResolver.generateOverridesInFunctionGroup( + propertyName, propertiesFromSupertypes, propertiesFromCurrent, classDescriptor, + new OverrideResolver.DescriptorSink() { + @Override + public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) { + properties.add((PropertyDescriptor) fakeOverride); + } + + @Override + public void conflict( + @NotNull CallableMemberDescriptor fromSuper, + @NotNull CallableMemberDescriptor fromCurrent + ) { + // nop + } + }); + } + + @NotNull + private PropertyDescriptor resolveProperty( + @NotNull ClassOrNamespaceDescriptor owner, + @NotNull ResolverScopeData scopeData, + @NotNull Name propertyName, + @NotNull String context, + @NotNull PropertyPsiData psiData + ) { + boolean isFinal = isPropertyFinal(scopeData, psiData); + boolean isVar = psiData.isVar(); + + PropertyPsiDataElement characteristicMember = psiData.getCharacteristicMember(); + + Visibility visibility = DescriptorResolverUtils.resolveVisibility(psiData.getCharacteristicPsi(), null); + CallableMemberDescriptor.Kind kind = CallableMemberDescriptor.Kind.DECLARATION; + + PropertyPsiDataElement getter = psiData.getGetter(); + if (getter != null) { + JetMethodAnnotation methodAnnotation = ((PsiMethodWrapper) getter.getMember()).getJetMethodAnnotation(); + visibility = DescriptorResolverUtils.resolveVisibility(psiData.getCharacteristicPsi(), methodAnnotation); + kind = DescriptorKindUtils.flagsToKind(methodAnnotation.kind()); + } + + DeclarationDescriptor realOwner = getRealOwner(owner, scopeData, psiData.isStatic()); + boolean isEnumEntry = DescriptorUtils.isEnumClassObject(realOwner); + PropertyDescriptor propertyDescriptor = new PropertyDescriptor( + realOwner, + annotationResolver.resolveAnnotations(psiData.getCharacteristicPsi()), + DescriptorResolverUtils.resolveModality(characteristicMember.getMember(), + isFinal || isEnumEntry || psiData.isPropertyForNamedObject()), + visibility, + isVar, + propertyName, + kind); + + //TODO: this is a hack to indicate that this enum entry is an object + // class descriptor for enum entries is not used by backends so for now this should be safe to use + // remove this when JavaDescriptorResolver gets rewritten + if (isEnumEntry) { + ClassDescriptorImpl dummyClassDescriptorForEnumEntryObject = + new ClassDescriptorImpl(realOwner, Collections.emptyList(), Modality.FINAL, propertyName); + dummyClassDescriptorForEnumEntryObject.initialize( + true, + Collections.emptyList(), + Collections.emptyList(), JetScope.EMPTY, + Collections.emptySet(), null); + trace.record(BindingContext.OBJECT_DECLARATION_CLASS, propertyDescriptor, dummyClassDescriptorForEnumEntryObject); + } + + PropertyGetterDescriptor getterDescriptor = resolveGetter(visibility, kind, getter, propertyDescriptor); + PropertySetterDescriptor setterDescriptor = resolveSetter(psiData, kind, propertyDescriptor); + + propertyDescriptor.initialize(getterDescriptor, setterDescriptor); + + List typeParameters = resolvePropertyTypeParameters(psiData, characteristicMember, propertyDescriptor); + + TypeVariableResolver typeVariableResolverForPropertyInternals = TypeVariableResolvers.typeVariableResolverFromTypeParameters( + typeParameters, propertyDescriptor, "property " + propertyName + " in " + context); + + JetType propertyType = getPropertyType(psiData, characteristicMember, typeVariableResolverForPropertyInternals); + JetType receiverType = getReceiverType(characteristicMember, typeVariableResolverForPropertyInternals); + + + propertyType = getAlternativeSignatureData(isVar, characteristicMember, propertyDescriptor, propertyType); + + propertyDescriptor.setType( + propertyType, + typeParameters, + DescriptorUtils.getExpectedThisObjectIfNeeded(realOwner), + receiverType + ); + initializeSetterAndGetter(propertyDescriptor, getterDescriptor, setterDescriptor, propertyType); + + if (kind == CallableMemberDescriptor.Kind.DECLARATION) { + trace.record(BindingContext.VARIABLE, psiData.getCharacteristicPsi(), propertyDescriptor); + } + + recordObjectDeclarationClassIfNeeded(psiData, realOwner, propertyDescriptor, propertyType); + + if (!scopeData.isKotlin()) { + trace.record(BindingContext.IS_DECLARED_IN_JAVA, propertyDescriptor); + } + return propertyDescriptor; + } + + @NotNull + private JetType getAlternativeSignatureData( + boolean isVar, + PropertyPsiDataElement characteristicMember, + PropertyDescriptor propertyDescriptor, + JetType propertyType + ) { + if (!characteristicMember.isField()) { + return propertyType; + } + AlternativeFieldSignatureData signatureData = + new AlternativeFieldSignatureData((PsiFieldWrapper) characteristicMember.getMember(), propertyType, isVar); + if (!signatureData.hasErrors()) { + if (signatureData.isAnnotated()) { + return signatureData.getReturnType(); + } + } + else { + trace.record(BindingContext.ALTERNATIVE_SIGNATURE_DATA_ERROR, propertyDescriptor, signatureData.getError()); + } + return propertyType; + } + + private static void initializeSetterAndGetter( + PropertyDescriptor propertyDescriptor, + PropertyGetterDescriptor getterDescriptor, + PropertySetterDescriptor setterDescriptor, + JetType propertyType + ) { + if (getterDescriptor != null) { + getterDescriptor.initialize(propertyType); + } + if (setterDescriptor != null) { + setterDescriptor.initialize(new ValueParameterDescriptorImpl( + setterDescriptor, + 0, + Collections.emptyList(), + Name.identifier("p0") /*TODO*/, + false, + propertyDescriptor.getType(), + false, + null)); + } + } + + private void recordObjectDeclarationClassIfNeeded( + PropertyPsiData psiData, + DeclarationDescriptor realOwner, + PropertyDescriptor propertyDescriptor, + JetType propertyType + ) { + if (!psiData.isPropertyForNamedObject()) { + return; + } + ClassDescriptor objectDescriptor = (ClassDescriptor) propertyType.getConstructor().getDeclarationDescriptor(); + + assert objectDescriptor != null; + assert objectDescriptor.getKind() == ClassKind.OBJECT; + assert objectDescriptor.getContainingDeclaration() == realOwner; + + trace.record(BindingContext.OBJECT_DECLARATION_CLASS, propertyDescriptor, objectDescriptor); + } + + @Nullable + private PropertyGetterDescriptor resolveGetter( + Visibility visibility, + CallableMemberDescriptor.Kind kind, + PropertyPsiDataElement getter, + PropertyDescriptor propertyDescriptor + ) { + if (getter == null) { + return null; + } + return new PropertyGetterDescriptor( + propertyDescriptor, + annotationResolver.resolveAnnotations(getter.getMember().getPsiMember()), + Modality.OPEN, + visibility, + true, + false, + kind); + } + + @Nullable + private PropertySetterDescriptor resolveSetter( + PropertyPsiData psiData, + CallableMemberDescriptor.Kind kind, + PropertyDescriptor propertyDescriptor + ) { + PropertyPsiDataElement setter = psiData.getSetter(); + if (setter == null) { + return null; + } + Visibility setterVisibility = DescriptorResolverUtils.resolveVisibility(setter.getMember().getPsiMember(), null); + if (setter.getMember() instanceof PsiMethodWrapper) { + setterVisibility = DescriptorResolverUtils.resolveVisibility( + setter.getMember().getPsiMember(), + ((PsiMethodWrapper) setter.getMember()) + .getJetMethodAnnotation()); + } + return new PropertySetterDescriptor( + propertyDescriptor, + annotationResolver.resolveAnnotations(setter.getMember().getPsiMember()), + Modality.OPEN, + setterVisibility, + true, + false, + kind); + } + private List resolvePropertyTypeParameters( @NotNull PropertyPsiData members, @NotNull PropertyPsiDataElement characteristicMember, @@ -353,22 +421,14 @@ public final class JavaPropertyResolver { return regularPropertiesCount; } - private static boolean isPropertyFinal(ResolverScopeData scopeData, PropertyPsiData members) { + private static boolean isPropertyFinal(ResolverScopeData scopeData, PropertyPsiData psiData) { if (!scopeData.isKotlin()) { return true; } - - if (members.getGetter() != null) { - return members.getGetter().getMember().isFinal(); - } - - if (members.getSetter() != null) { - return members.getSetter().getMember().isFinal(); - } - - return false; + return psiData.isFinal(); } + @NotNull private static Set getPropertiesFromSupertypes(ResolverScopeData scopeData, Name propertyName) { Set r = new HashSet(); for (JetType supertype : DescriptorResolverUtils.getSupertypes(scopeData)) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/wrapper/PropertyPsiData.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/wrapper/PropertyPsiData.java index 07423f49e44..82c76011a99 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/wrapper/PropertyPsiData.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/wrapper/PropertyPsiData.java @@ -21,6 +21,7 @@ import com.intellij.openapi.util.Pair; import com.intellij.psi.PsiMember; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.TypeSource; import java.util.Collection; @@ -181,4 +182,19 @@ public final class PropertyPsiData { assert field != null; return field.getMember().isFinal() && field.getMember().isStatic(); } + + public boolean isPropertyForNamedObject() { + return field != null && JvmAbi.INSTANCE_FIELD.equals(field.getMember().getName()); + } + + public boolean isFinal() { + if (getter != null) { + return getter.getMember().isFinal(); + } + + if (setter != null) { + return setter.getMember().isFinal(); + } + return false; + } }