From 4ded2e79ad3709a051a856be6ed636049d242d9b Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 18 Jan 2012 12:01:00 +0400 Subject: [PATCH] refactor java descriptor resolver --- .../resolve/java/JavaClassMembersScope.java | 63 +- .../resolve/java/JavaDescriptorResolver.java | 554 ++++++------------ .../java/JavaDescriptorResolverHelper.java | 173 ++++++ .../lang/resolve/java/MembersForProperty.java | 15 + .../jet/lang/resolve/java/NamedMembers.java | 41 ++ .../lang/resolve/java/PsiClassWrapper.java | 59 ++ .../lang/resolve/java/PsiFieldWrapper.java | 10 + .../lang/resolve/java/PsiMethodWrapper.java | 11 + 8 files changed, 526 insertions(+), 400 deletions(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/NamedMembers.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassWrapper.java diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java index 80c8b72a9c9..636682c0838 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java @@ -2,15 +2,26 @@ package org.jetbrains.jet.lang.resolve.java; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.intellij.psi.*; +import com.intellij.psi.HierarchicalMethodSignature; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiModifier; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.TypeSubstitutor; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * @author abreslav @@ -20,8 +31,6 @@ public class JavaClassMembersScope implements JetScope { private final JavaSemanticServices semanticServices; private final boolean staticMembers; private final DeclarationDescriptor containingDeclaration; - private final Map> functionGroups = Maps.newHashMap(); - private final Map> variables = Maps.newHashMap(); private final Map classifiers = Maps.newHashMap(); private Collection allDescriptors; @@ -76,7 +85,7 @@ public class JavaClassMembersScope implements JetScope { if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) { continue; } - FunctionDescriptor functionDescriptor = semanticServices.getDescriptorResolver().resolveMethodToFunctionDescriptor(containingDeclaration, psiClass, substitutorForGenericSupertypes, method); + FunctionDescriptor functionDescriptor = semanticServices.getDescriptorResolver().resolveMethodToFunctionDescriptor(containingDeclaration, psiClass, substitutorForGenericSupertypes, new PsiMethodWrapper(method)); if (functionDescriptor != null) { allDescriptors.add(functionDescriptor); } @@ -117,14 +126,7 @@ public class JavaClassMembersScope implements JetScope { @NotNull @Override public Set getProperties(@NotNull String name) { - Set variableDescriptor = variables.get(name); - if (variableDescriptor == null) { - variableDescriptor = doGetVariable(name); - if (variableDescriptor != null) { - variables.put(name, variableDescriptor); - } - } - return variableDescriptor != null ? variableDescriptor : Collections.emptySet(); + return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDeclaration, psiClass, name, staticMembers); } @Override @@ -132,32 +134,15 @@ public class JavaClassMembersScope implements JetScope { return null; } - @Nullable - private Set doGetVariable(String name) { - PsiField field = psiClass.findFieldByName(name, true); - if (field == null) return null; - if (field.hasModifierProperty(PsiModifier.STATIC) != staticMembers) { - return null; - } - - //return semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDeclaration, field); - return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDeclaration, psiClass, name, staticMembers); - } - @NotNull @Override public Set getFunctions(@NotNull String name) { - Set functionGroup = functionGroups.get(name); - if (functionGroup == null) { - functionGroup = semanticServices.getDescriptorResolver().resolveFunctionGroup( - containingDeclaration, - psiClass, - staticMembers ? null : (ClassDescriptor) containingDeclaration, - name, - staticMembers); - functionGroups.put(name, functionGroup); - } - return functionGroup; + return semanticServices.getDescriptorResolver().resolveFunctionGroup( + containingDeclaration, + psiClass, + staticMembers ? null : (ClassDescriptor) containingDeclaration, + name, + staticMembers); } @Override 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 55480befad2..f5b85afcc20 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 @@ -4,15 +4,12 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; 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.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.PsiMethod; import com.intellij.psi.PsiModifier; @@ -63,6 +60,7 @@ import org.jetbrains.jet.rt.signature.JetSignatureVisitor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -128,11 +126,12 @@ public class JavaDescriptorResolver { this.lowerBoundsForKotlin = lowerBoundsForKotlin; } } - + + private static abstract class ResolverScopeData { - @Nullable - private Set properties; protected boolean kotlin; + + private Map namedMembersMap; } private static class ResolverClassData extends ResolverScopeData { @@ -159,7 +158,6 @@ public class JavaDescriptorResolver { private final Map typeParameterDescriptorCache = Maps.newHashMap(); protected final Map methodDescriptorCache = Maps.newHashMap(); - protected final Map fieldDescriptorCache = Maps.newHashMap(); protected final JavaPsiFacade javaFacade; protected final GlobalSearchScope javaSearchScope; protected final JavaSemanticServices semanticServices; @@ -781,217 +779,174 @@ public class JavaDescriptorResolver { } } - /* - public VariableDescriptor resolveFieldToVariableDescriptor(DeclarationDescriptor containingDeclaration, PsiField field) { - VariableDescriptor variableDescriptor = fieldDescriptorCache.get(field); - if (variableDescriptor != null) { - return variableDescriptor; - } - JetType type = semanticServices.getTypeTransformer().transformToType(field.getType()); - boolean isFinal = field.hasModifierProperty(PsiModifier.FINAL); - PropertyDescriptor propertyDescriptor = new PropertyDescriptor( - containingDeclaration, - Collections.emptyList(), - Modality.FINAL, - resolveVisibilityFromPsiModifiers(field), - !isFinal, - null, - DescriptorUtils.getExpectedThisObjectIfNeeded(containingDeclaration), - field.getName(), - type); - semanticServices.getTrace().record(BindingContext.VARIABLE, field, propertyDescriptor); - fieldDescriptorCache.put(field, propertyDescriptor); - return propertyDescriptor; - } - */ - - private static class PropertyKey { - @NotNull - private final String name; - //@NotNull - //private final PsiType type; - //@Nullable - //private final PsiType receiverType; - - 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) { - 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; - } - - @Override - public int hashCode() { - int result = name.hashCode(); - //result = 31 * result + type.hashCode(); - //result = 31 * result + (receiverType != null ? receiverType.hashCode() : 0); - return result; - } - } - - private static class MembersForProperty { - private PsiFieldWrapper field; - private PsiMethodWrapper setter; - private PsiMethodWrapper getter; - - private PsiType type; - private PsiType receiverType; - } - - private Map getMembersForProperties(@NotNull PsiClass clazz, boolean staticMembers, boolean kotlin) { - Map membersMap = Maps.newHashMap(); - if (!kotlin) { - for (PsiField field : clazz.getFields()) { - if (field.getModifierList().hasExplicitModifier(PsiModifier.STATIC) != staticMembers) { - continue; - } - - if (field.hasModifierProperty(PsiModifier.PRIVATE)) { - continue; - } - - MembersForProperty members = new MembersForProperty(); - members.field = new PsiFieldWrapper(field); - members.type = field.getType(); - membersMap.put(new PropertyKey(field.getName() /*, field.getType(), null*/), members); - } - } - - for (PsiMethod psiMethod : clazz.getMethods()) { - PsiMethodWrapper method = new PsiMethodWrapper(psiMethod); - - if (method.isStatic() != staticMembers) { - continue; - } - - if (method.isPrivate()) { - continue; - } - - // TODO: "is" prefix - // TODO: remove getJavaClass - if (psiMethod.getName().startsWith(JvmAbi.GETTER_PREFIX)) { - - // TODO: some java properties too - if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) { - - if (psiMethod.getName().equals(JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD)) { - continue; - } - - int i = 0; - - PsiType receiverType; - if (i < method.getParameters().size() && method.getParameter(i).getJetValueParameter().receiver()) { - receiverType = method.getParameter(i).getPsiParameter().getType(); - ++i; - } else { - receiverType = null; - } - - while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) { - // TODO: store is reified - ++i; - } - - if (i != method.getParameters().size()) { - // TODO: report error properly - throw new IllegalStateException(); - } - - 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 = new PsiMethodWrapper(psiMethod); - - // TODO: check conflicts with setter - members.type = psiMethod.getReturnType(); - members.receiverType = receiverType; - } - } else if (psiMethod.getName().startsWith(JvmAbi.SETTER_PREFIX)) { - - if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) { - if (psiMethod.getParameterList().getParametersCount() == 0) { - // TODO: report error properly - throw new IllegalStateException(); - } - - int i = 0; - - PsiType receiverType = null; - PsiParameterWrapper p1 = method.getParameter(0); - if (p1.getJetValueParameter().receiver()) { - receiverType = p1.getPsiParameter().getType(); - ++i; - } - - while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) { - ++i; - } - - if (i + 1 != psiMethod.getParameterList().getParametersCount()) { - throw new IllegalStateException(); - } - - PsiType propertyType = psiMethod.getParameterList().getParameters()[i].getType(); - - 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 = new PsiMethodWrapper(psiMethod); - - // TODO: check conflicts with getter - members.type = propertyType; - members.receiverType = receiverType; - } - } - } - - return membersMap; - } - public Set resolveFieldGroupByName(@NotNull DeclarationDescriptor owner, PsiClass psiClass, String fieldName, boolean staticMembers) { - Set r = Sets.newHashSet(); - // TODO: slow - Set variables = resolveFieldGroup(owner, psiClass, staticMembers); - for (VariableDescriptor variable : variables) { - if (variable.getName().equals(fieldName)) { - r.add(variable); - } - } - return r; - } + ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass)); + NamedMembers namedMembers = scopeData.namedMembersMap.get(fieldName); + if (namedMembers == null) { + return Collections.emptySet(); + } + + resolveNamedGroupProperties(owner, staticMembers, namedMembers, fieldName); + + return namedMembers.propertyDescriptors; + } + @NotNull public Set resolveFieldGroup(@NotNull DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) { + + ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass)); + Set descriptors = Sets.newHashSet(); + Map membersForProperties = scopeData.namedMembersMap; + for (Map.Entry entry : membersForProperties.entrySet()) { + NamedMembers namedMembers = entry.getValue(); + if (namedMembers.properties == null) { + continue; + } + + String propertyName = entry.getKey(); + + resolveNamedGroupProperties(owner, staticMembers, namedMembers, propertyName); + descriptors.addAll(namedMembers.propertyDescriptors); + } + return descriptors; + } + + private void resolveNamedGroupProperties(DeclarationDescriptor owner, boolean staticMembers, NamedMembers namedMembers, String propertyName) { + if (namedMembers.propertyDescriptors != null) { + return; + } + + if (namedMembers.properties == null) { + namedMembers.propertyDescriptors = Collections.emptySet(); + return; + } + + PsiType propertyType = namedMembers.properties.type; + PsiType receiverType = namedMembers.properties.receiverType; + MembersForProperty members = namedMembers.properties; + + boolean isFinal; + if (members.setter == null && members.getter == null) { + isFinal = false; + } else if (members.getter != null) { + isFinal = members.getter.isFinal(); + } else if (members.setter != null) { + isFinal = members.setter.isFinal(); + } else { + isFinal = false; + } + + PsiMemberWrapper anyMember; + if (members.getter != null) { + anyMember = members.getter; + } else if (members.field != null) { + anyMember = members.field; + } else if (members.setter != null) { + anyMember = members.setter; + } else { + throw new IllegalStateException(); + } + + boolean isVar; + if (members.getter == null && members.setter == null) { + isVar = !members.field.isFinal(); + } else { + isVar = members.setter != null; + } + + PropertyDescriptor propertyDescriptor = new PropertyDescriptor( + owner, + Collections.emptyList(), + isFinal && !staticMembers ? Modality.FINAL : Modality.OPEN, // TODO: abstract + resolveVisibilityFromPsiModifiers(anyMember.psiMember), + isVar, + false, + propertyName); + + PropertyGetterDescriptor getterDescriptor = null; + PropertySetterDescriptor setterDescriptor = null; + if (members.getter != null) { + getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false); + } + if (members.setter != null) { + setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false); + } + + propertyDescriptor.initialize(getterDescriptor, setterDescriptor); + + final List classTypeParameters; + if (anyMember instanceof PsiMethodWrapper && !anyMember.isStatic()) { + classTypeParameters = ((ClassDescriptor) owner).getTypeConstructor().getParameters(); + } else { + classTypeParameters = new ArrayList(0); + } + TypeParameterListTypeVariableResolver typeVariableResolver = new TypeParameterListTypeVariableResolver(classTypeParameters); + + List typeParameters = new ArrayList(0); + + if (members.setter != null) { + // call ugly code with side effects + typeParameters = resolveMethodTypeParameters(members.setter, propertyDescriptor.getSetter(), typeVariableResolver); + } + if (members.getter != null) { + // call ugly code with side effects + typeParameters = resolveMethodTypeParameters(members.getter, propertyDescriptor.getGetter(), typeVariableResolver); + } + + JetType receiverJetType; + if (receiverType == null) { + receiverJetType = null; + } else { + receiverJetType = semanticServices.getTypeTransformer().transformToType(receiverType); + } + + JetType type = semanticServices.getTypeTransformer().transformToType(propertyType); + + propertyDescriptor.setType( + type, + typeParameters, + DescriptorUtils.getExpectedThisObjectIfNeeded(owner), + receiverJetType + ); + if (getterDescriptor != null) { + getterDescriptor.initialize(type); + } + if (setterDescriptor != null) { + // TODO: initialize + } + + semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember.psiMember, propertyDescriptor); + namedMembers.propertyDescriptors = Collections.singleton(propertyDescriptor); + } + + private void resolveNamedGroupFunctions(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, boolean staticMembers, NamedMembers namedMembers, String functionName) { + if (namedMembers.functionDescriptors != null) { + return; + } + + if (namedMembers.methods == null) { + namedMembers.functionDescriptors = Collections.emptySet(); + return; + } + + Set functionDescriptors = new HashSet(namedMembers.methods.size()); + for (PsiMethodWrapper method : namedMembers.methods) { + functionDescriptors.add(resolveMethodToFunctionDescriptor(owner, psiClass, typeSubstitutorForGenericSuperclasses, method)); + } + namedMembers.functionDescriptors = functionDescriptors; + } + + private ResolverScopeData getResolverScopeData(DeclarationDescriptor owner, PsiClassWrapper psiClass) { ResolverScopeData scopeData; + boolean staticMembers; if (owner instanceof JavaNamespaceDescriptor) { scopeData = namespaceDescriptorCacheByFqn.get(((JavaNamespaceDescriptor) owner).getQualifiedName()); + staticMembers = true; } else if (owner instanceof ClassDescriptor) { scopeData = classDescriptorCache.get(psiClass.getQualifiedName()); + staticMembers = false; } else { throw new IllegalStateException(); } @@ -999,151 +954,29 @@ public class JavaDescriptorResolver { throw new IllegalStateException(); } - if (scopeData.properties != null) { - return scopeData.properties; + if (scopeData.namedMembersMap == null) { + scopeData.namedMembersMap = JavaDescriptorResolverHelper.getNamedMembers(psiClass, staticMembers, scopeData.kotlin); } - Set descriptors = Sets.newHashSet(); - Map membersForProperties = getMembersForProperties(psiClass, staticMembers, scopeData.kotlin); - for (Map.Entry entry : membersForProperties.entrySet()) { - //VariableDescriptor variableDescriptor = fieldDescriptorCache.get(field); - //if (variableDescriptor != null) { - // return variableDescriptor; - //} - String propertyName = entry.getKey().name; - PsiType propertyType = entry.getValue().type; - PsiType receiverType = entry.getValue().receiverType; - MembersForProperty members = entry.getValue(); - - boolean isFinal; - if (members.setter == null && members.getter == null) { - isFinal = false; - } else if (members.getter != null) { - isFinal = members.getter.isFinal(); - } else if (members.setter != null) { - isFinal = members.setter.isFinal(); - } else { - isFinal = false; - } - - PsiMemberWrapper anyMember; - if (members.getter != null) { - anyMember = members.getter; - } else if (members.field != null) { - anyMember = members.field; - } else if (members.setter != null) { - anyMember = members.setter; - } else { - throw new IllegalStateException(); - } - - boolean isVar; - if (members.getter == null && members.setter == null) { - isVar = !members.field.isFinal(); - } else { - isVar = members.setter != null; - } - - PropertyDescriptor propertyDescriptor = new PropertyDescriptor( - owner, - Collections.emptyList(), - isFinal && !staticMembers ? Modality.FINAL : Modality.OPEN, // TODO: abstract - resolveVisibilityFromPsiModifiers(anyMember.psiMember), - isVar, - false, - propertyName); - - PropertyGetterDescriptor getterDescriptor = null; - PropertySetterDescriptor setterDescriptor = null; - if (members.getter != null) { - getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false); - } - if (members.setter != null) { - setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false); - } - - propertyDescriptor.initialize(getterDescriptor, setterDescriptor); - - final List classTypeParameters; - if (anyMember instanceof PsiMethodWrapper && !anyMember.isStatic()) { - classTypeParameters = ((ClassDescriptor) owner).getTypeConstructor().getParameters(); - } else { - classTypeParameters = new ArrayList(0); - } - TypeParameterListTypeVariableResolver typeVariableResolver = new TypeParameterListTypeVariableResolver(classTypeParameters); - - List typeParameters = new ArrayList(0); - - if (members.setter != null) { - // call ugly code with side effects - typeParameters = resolveMethodTypeParameters(members.setter, propertyDescriptor.getSetter(), typeVariableResolver); - } - if (members.getter != null) { - // call ugly code with side effects - typeParameters = resolveMethodTypeParameters(members.getter, propertyDescriptor.getGetter(), typeVariableResolver); - } - - JetType receiverJetType; - if (receiverType == null) { - receiverJetType = null; - } else { - receiverJetType = semanticServices.getTypeTransformer().transformToType(receiverType); - } - - JetType type = semanticServices.getTypeTransformer().transformToType(propertyType); - - propertyDescriptor.setType( - type, - typeParameters, - DescriptorUtils.getExpectedThisObjectIfNeeded(owner), - receiverJetType - ); - if (getterDescriptor != null) { - getterDescriptor.initialize(type); - } - if (setterDescriptor != null) { - // TODO: initialize - } - - semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember.psiMember, propertyDescriptor); - //fieldDescriptorCache.put(field, propertyDescriptor); - descriptors.add(propertyDescriptor); - } - scopeData.properties = descriptors; - return descriptors; + return scopeData; } @NotNull public Set resolveFunctionGroup(@NotNull DeclarationDescriptor owner, @NotNull PsiClass psiClass, @Nullable ClassDescriptor classDescriptor, @NotNull String methodName, boolean staticMembers) { - Set writableFunctionGroup = Sets.newLinkedHashSet(); - final Collection signatures = psiClass.getVisibleSignatures(); + + ResolverScopeData resolverScopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass)); + + Map namedMembersMap = resolverScopeData.namedMembersMap; + + NamedMembers namedMembers = namedMembersMap.get(methodName); + if (namedMembers == null || namedMembers.methods == null) { + return Collections.emptySet(); + } + TypeSubstitutor typeSubstitutor = createSubstitutorForGenericSupertypes(classDescriptor); - for (HierarchicalMethodSignature signature: signatures) { - if (!methodName.equals(signature.getName())) { - continue; - } - - FunctionDescriptor substitutedFunctionDescriptor = resolveHierarchicalSignatureToFunction(owner, psiClass, staticMembers, typeSubstitutor, signature); - if (substitutedFunctionDescriptor != null) { - writableFunctionGroup.add(substitutedFunctionDescriptor); - } - } - return writableFunctionGroup; - } - - @Nullable - private FunctionDescriptor resolveHierarchicalSignatureToFunction(DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers, TypeSubstitutor typeSubstitutor, HierarchicalMethodSignature signature) { - PsiMethod method = signature.getMethod(); - if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) { - return null; - } - FunctionDescriptor functionDescriptor = resolveMethodToFunctionDescriptor(owner, psiClass, typeSubstitutor, method); -// if (functionDescriptor != null && !staticMembers) { -// for (HierarchicalMethodSignature superSignature : signature.getSuperSignatures()) { -// ((FunctionDescriptorImpl) functionDescriptor).addOverriddenFunction(resolveHierarchicalSignatureToFunction(owner, superSignature.getMethod().getContainingClass(), false, typeSubstitutor, superSignature)); -// } -// } - return functionDescriptor; + resolveNamedGroupFunctions(owner, psiClass, typeSubstitutor, staticMembers, namedMembers, methodName); + + return namedMembers.functionDescriptors; } public TypeSubstitutor createSubstitutorForGenericSupertypes(ClassDescriptor classDescriptor) { @@ -1178,16 +1011,15 @@ public class JavaDescriptorResolver { } @Nullable - public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethod psiMethod) { - PsiMethodWrapper method = new PsiMethodWrapper(psiMethod); + public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethodWrapper method) { - PsiType returnType = psiMethod.getReturnType(); + PsiType returnType = method.getReturnType(); if (returnType == null) { return null; } - FunctionDescriptor functionDescriptor = methodDescriptorCache.get(psiMethod); + FunctionDescriptor functionDescriptor = methodDescriptorCache.get(method.getPsiMethod()); if (functionDescriptor != null) { - if (psiMethod.getContainingClass() != psiClass) { + if (method.getPsiMethod().getContainingClass() != psiClass) { functionDescriptor = functionDescriptor.substitute(typeSubstitutorForGenericSuperclasses); } return functionDescriptor; @@ -1238,11 +1070,11 @@ public class JavaDescriptorResolver { DeclarationDescriptor classDescriptor; final List classTypeParameters; if (method.isStatic()) { - classDescriptor = resolveNamespace(psiMethod.getContainingClass()); + classDescriptor = resolveNamespace(method.getPsiMethod().getContainingClass()); classTypeParameters = Collections.emptyList(); } else { - ClassDescriptor classClassDescriptor = resolveClass(psiMethod.getContainingClass()); + ClassDescriptor classClassDescriptor = resolveClass(method.getPsiMethod().getContainingClass()); classDescriptor = classClassDescriptor; classTypeParameters = classClassDescriptor.getTypeConstructor().getParameters(); } @@ -1252,14 +1084,14 @@ public class JavaDescriptorResolver { NamedFunctionDescriptorImpl functionDescriptorImpl = new NamedFunctionDescriptorImpl( owner, Collections.emptyList(), // TODO - psiMethod.getName() + method.getName() ); - methodDescriptorCache.put(psiMethod, functionDescriptorImpl); + methodDescriptorCache.put(method.getPsiMethod(), functionDescriptorImpl); // TODO: add outer classes TypeParameterListTypeVariableResolver typeVariableResolverForParameters = new TypeParameterListTypeVariableResolver(classTypeParameters); - final List methodTypeParameters = resolveMethodTypeParameters(new PsiMethodWrapper(psiMethod), functionDescriptorImpl, typeVariableResolverForParameters); + final List methodTypeParameters = resolveMethodTypeParameters(method, functionDescriptorImpl, typeVariableResolverForParameters); class MethodTypeVariableResolver implements TypeVariableResolver { @@ -1288,12 +1120,12 @@ public class JavaDescriptorResolver { methodTypeParameters, valueParameterDescriptors.descriptors, makeReturnType(returnType, method, new MethodTypeVariableResolver()), - Modality.convertFromFlags(psiMethod.hasModifierProperty(PsiModifier.ABSTRACT), !psiMethod.hasModifierProperty(PsiModifier.FINAL)), - resolveVisibilityFromPsiModifiers(psiMethod) + Modality.convertFromFlags(method.getPsiMethod().hasModifierProperty(PsiModifier.ABSTRACT), !method.isFinal()), + resolveVisibilityFromPsiModifiers(method.getPsiMethod()) ); - semanticServices.getTrace().record(BindingContext.FUNCTION, psiMethod, functionDescriptorImpl); + semanticServices.getTrace().record(BindingContext.FUNCTION, method.getPsiMethod(), functionDescriptorImpl); FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl; - if (psiMethod.getContainingClass() != psiClass) { + if (method.getPsiMethod().getContainingClass() != psiClass) { substitutedFunctionDescriptor = functionDescriptorImpl.substitute(typeSubstitutorForGenericSuperclasses); } return substitutedFunctionDescriptor; @@ -1400,7 +1232,7 @@ public class JavaDescriptorResolver { ownerOwner = classDescriptor; substitutorForGenericSupertypes = semanticServices.getDescriptorResolver().createSubstitutorForGenericSupertypes(classDescriptor); } - FunctionDescriptor functionDescriptor = resolveMethodToFunctionDescriptor(ownerOwner, containingClass, substitutorForGenericSupertypes, psiMethod); + FunctionDescriptor functionDescriptor = resolveMethodToFunctionDescriptor(ownerOwner, containingClass, substitutorForGenericSupertypes, new PsiMethodWrapper(psiMethod)); return resolveTypeParameter(functionDescriptor, typeParameter); } throw new IllegalStateException("Unknown parent type: " + owner); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java new file mode 100644 index 00000000000..c56fb65b37c --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java @@ -0,0 +1,173 @@ +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.HierarchicalMethodSignature; +import com.intellij.psi.PsiType; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Stepan Koltsov + */ +class JavaDescriptorResolverHelper { + + + private static class Builder { + private final PsiClassWrapper psiClass; + private final boolean staticMembers; + private final boolean kotlin; + + private Map namedMembersMap = new HashMap(); + + private Builder(PsiClassWrapper psiClass, boolean staticMembers, boolean kotlin) { + this.psiClass = psiClass; + this.staticMembers = staticMembers; + this.kotlin = kotlin; + } + + public void run() { + processFields(); + processMethods(); + } + + private NamedMembers getNamedMembers(String name) { + NamedMembers r = namedMembersMap.get(name); + if (r == null) { + r = new NamedMembers(); + r.name = name; + namedMembersMap.put(name, r); + } + return r; + } + + private void processFields() { + if (!kotlin) { + for (PsiFieldWrapper field : psiClass.getFields()) { + if (field.isStatic() != staticMembers) { + continue; + } + + if (field.isPrivate()) { + continue; + } + + NamedMembers namedMembers = getNamedMembers(field.getName()); + + MembersForProperty members = new MembersForProperty(); + members.field = field; + members.type = field.getType(); + + namedMembers.properties = members; + } + } + } + + private void processMethods() { + for (HierarchicalMethodSignature method0 : psiClass.getPsiClass().getVisibleSignatures()) { + + PsiMethodWrapper method = new PsiMethodWrapper(method0.getMethod()); + + if (method.isStatic() != staticMembers) { + continue; + } + + if (method.isPrivate()) { + continue; + } + + // TODO: "is" prefix + // TODO: remove getJavaClass + if (method.getName().startsWith(JvmAbi.GETTER_PREFIX)) { + + // TODO: some java properties too + if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) { + + if (method.getName().equals(JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD)) { + continue; + } + + int i = 0; + + PsiType receiverType; + if (i < method.getParameters().size() && method.getParameter(i).getJetValueParameter().receiver()) { + receiverType = method.getParameter(i).getPsiParameter().getType(); + ++i; + } else { + receiverType = null; + } + + while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) { + // TODO: store is reified + ++i; + } + + if (i != method.getParameters().size()) { + // TODO: report error properly + throw new IllegalStateException(); + } + + String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.GETTER_PREFIX.length())); + NamedMembers members = getNamedMembers(propertyName); + members.getForProperty().getter = method; + + // TODO: check conflicts with setter + // TODO: what if returnType == null? + members.getForProperty().type = method.getReturnType(); + members.getForProperty().receiverType = receiverType; + } + } else if (method.getName().startsWith(JvmAbi.SETTER_PREFIX)) { + + if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) { + if (method.getParameters().size() == 0) { + // TODO: report error properly + throw new IllegalStateException(); + } + + int i = 0; + + PsiType receiverType = null; + PsiParameterWrapper p1 = method.getParameter(0); + if (p1.getJetValueParameter().receiver()) { + receiverType = p1.getPsiParameter().getType(); + ++i; + } + + while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) { + ++i; + } + + if (i + 1 != method.getParameters().size()) { + throw new IllegalStateException(); + } + + PsiType propertyType = method.getParameter(i).getPsiParameter().getType(); + + String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.SETTER_PREFIX.length())); + NamedMembers members = getNamedMembers(propertyName); + members.getForProperty().setter = method; + + // TODO: check conflicts with getter + members.getForProperty().type = propertyType; + members.getForProperty().receiverType = receiverType; + } + } + + if (method.getJetMethod().kind() != JvmStdlibNames.JET_METHOD_KIND_PROPERTY) { + NamedMembers namedMembers = getNamedMembers(method.getName()); + namedMembers.addMethod(method); + } + } + } + } + + + static Map getNamedMembers(@NotNull PsiClassWrapper psiClass, boolean staticMembers, boolean kotlin) { + Builder builder = new Builder(psiClass, staticMembers, kotlin); + builder.run(); + return builder.namedMembersMap; + } + + +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java new file mode 100644 index 00000000000..db363b87c82 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java @@ -0,0 +1,15 @@ +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.psi.PsiType; + +/** +* @author Stepan Koltsov +*/ +class MembersForProperty { + PsiFieldWrapper field; + PsiMethodWrapper setter; + PsiMethodWrapper getter; + + PsiType type; + PsiType receiverType; +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/NamedMembers.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/NamedMembers.java new file mode 100644 index 00000000000..7da0943b814 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/NamedMembers.java @@ -0,0 +1,41 @@ +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** +* @author Stepan Koltsov +*/ +class NamedMembers { + String name; + List methods; + @Nullable + MembersForProperty properties; + @Nullable + private PsiClass nestedClasses; + + Set propertyDescriptors; + Set functionDescriptors; + + MembersForProperty getForProperty() { + if (properties == null) { + properties = new MembersForProperty(); + } + return properties; + } + + void addMethod(PsiMethodWrapper method) { + if (methods == null) { + methods = new ArrayList(); + } + methods.add(method); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassWrapper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassWrapper.java new file mode 100644 index 00000000000..0eb52048fa3 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassWrapper.java @@ -0,0 +1,59 @@ +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiMethod; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Stepan Koltsov + */ +public class PsiClassWrapper { + + @NotNull + private final PsiClass psiClass; + + public PsiClassWrapper(@NotNull PsiClass psiClass) { + this.psiClass = psiClass; + } + + private List methods; + @NotNull + public List getMethods() { + if (methods == null) { + PsiMethod[] psiMethods = psiClass.getMethods(); + List methods = new ArrayList(psiMethods.length); + for (PsiMethod psiMethod : psiMethods) { + methods.add(new PsiMethodWrapper(psiMethod)); + } + this.methods = methods; + } + return methods; + } + + private List fields; + @NotNull + public List getFields() { + if (fields == null) { + PsiField[] psiFields = psiClass.getFields(); + List fields = new ArrayList(psiFields.length); + for (PsiField psiField : psiFields) { + fields.add(new PsiFieldWrapper(psiField)); + } + this.fields = fields; + } + return fields; + } + + public String getQualifiedName() { + return psiClass.getQualifiedName(); + } + + @NotNull + public PsiClass getPsiClass() { + return psiClass; + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiFieldWrapper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiFieldWrapper.java index 75ad3e13860..a896d42e1c7 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiFieldWrapper.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiFieldWrapper.java @@ -1,6 +1,8 @@ package org.jetbrains.jet.lang.resolve.java; +import com.intellij.psi.PsiField; import com.intellij.psi.PsiMember; +import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; /** @@ -10,4 +12,12 @@ public class PsiFieldWrapper extends PsiMemberWrapper { public PsiFieldWrapper(@NotNull PsiMember psiMember) { super(psiMember); } + + public PsiField getPsiField() { + return (PsiField) psiMember; + } + + public PsiType getType() { + return getPsiField().getType(); + } } 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 index 0f67274a018..66b1df1f991 100644 --- 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 @@ -3,7 +3,9 @@ package org.jetbrains.jet.lang.resolve.java; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiParameter; +import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.java.kt.JetConstructorAnnotation; import org.jetbrains.jet.lang.resolve.java.kt.JetMethodAnnotation; @@ -55,8 +57,17 @@ public class PsiMethodWrapper extends PsiMemberWrapper { return jetConstructor; } + public boolean isAbstract() { + return psiMember.hasModifierProperty(PsiModifier.ABSTRACT); + } + @NotNull public PsiMethod getPsiMethod() { return (PsiMethod) psiMember; } + + @Nullable + public PsiType getReturnType() { + return getPsiMethod().getReturnType(); + } }