Skip to content

Instantly share code, notes, and snippets.

@stepancheg
Created January 17, 2012 18:58
Show Gist options
  • Save stepancheg/1628144 to your computer and use it in GitHub Desktop.
Save stepancheg/1628144 to your computer and use it in GitHub Desktop.
commit 41b6b4ef0ec11fdd9adec8fde73f176b938e865d
Author: Stepan Koltsov <[email protected]>
Date: Mon Jan 16 16:55:00 2012 +0400
refactor java descriptor resolver
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 80c8b72..636682c 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<String, Set<FunctionDescriptor>> functionGroups = Maps.newHashMap();
- private final Map<String, Set<VariableDescriptor>> variables = Maps.newHashMap();
private final Map<String, ClassifierDescriptor> classifiers = Maps.newHashMap();
private Collection<DeclarationDescriptor> 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<VariableDescriptor> getProperties(@NotNull String name) {
- Set<VariableDescriptor> variableDescriptor = variables.get(name);
- if (variableDescriptor == null) {
- variableDescriptor = doGetVariable(name);
- if (variableDescriptor != null) {
- variables.put(name, variableDescriptor);
- }
- }
- return variableDescriptor != null ? variableDescriptor : Collections.<VariableDescriptor>emptySet();
+ return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDeclaration, psiClass, name, staticMembers);
}
@Override
@@ -132,32 +134,15 @@ public class JavaClassMembersScope implements JetScope {
return null;
}
- @Nullable
- private Set<VariableDescriptor> 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<FunctionDescriptor> getFunctions(@NotNull String name) {
- Set<FunctionDescriptor> 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 55480be..f5b85af 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<VariableDescriptor> properties;
protected boolean kotlin;
+
+ private Map<String, NamedMembers> namedMembersMap;
}
private static class ResolverClassData extends ResolverScopeData {
@@ -159,7 +158,6 @@ public class JavaDescriptorResolver {
private final Map<PsiTypeParameter, TypeParameterDescriptorInitialization> typeParameterDescriptorCache = Maps.newHashMap();
protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap();
- protected final Map<PsiField, VariableDescriptor> 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.<AnnotationDescriptor>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;
+ public Set<VariableDescriptor> resolveFieldGroupByName(@NotNull DeclarationDescriptor owner, PsiClass psiClass, String fieldName, boolean staticMembers) {
+ ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass));
- private PropertyKey(@NotNull String name /*, @NotNull PsiType type, @Nullable PsiType receiverType */) {
- this.name = name;
- //this.type = type;
- //this.receiverType = receiverType;
+ NamedMembers namedMembers = scopeData.namedMembersMap.get(fieldName);
+ if (namedMembers == null) {
+ return Collections.emptySet();
}
- @Override
- public boolean equals(Object o) {
- if (this == o) return true;
- if (o == null || getClass() != o.getClass()) return false;
-
- PropertyKey that = (PropertyKey) o;
+ resolveNamedGroupProperties(owner, staticMembers, namedMembers, fieldName);
- 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 namedMembers.propertyDescriptors;
+ }
+
+ @NotNull
+ public Set<VariableDescriptor> resolveFieldGroup(@NotNull DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) {
- return true;
- }
+ ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass));
+
+ Set<VariableDescriptor> descriptors = Sets.newHashSet();
+ Map<String, NamedMembers> membersForProperties = scopeData.namedMembersMap;
+ for (Map.Entry<String, NamedMembers> entry : membersForProperties.entrySet()) {
+ NamedMembers namedMembers = entry.getValue();
+ if (namedMembers.properties == null) {
+ continue;
+ }
+
+ String propertyName = entry.getKey();
- @Override
- public int hashCode() {
- int result = name.hashCode();
- //result = 31 * result + type.hashCode();
- //result = 31 * result + (receiverType != null ? receiverType.hashCode() : 0);
- return result;
+ resolveNamedGroupProperties(owner, staticMembers, namedMembers, propertyName);
+ descriptors.addAll(namedMembers.propertyDescriptors);
}
+ return descriptors;
}
- private static class MembersForProperty {
- private PsiFieldWrapper field;
- private PsiMethodWrapper setter;
- private PsiMethodWrapper getter;
-
- private PsiType type;
- private PsiType receiverType;
- }
-
- private Map<PropertyKey, MembersForProperty> getMembersForProperties(@NotNull PsiClass clazz, boolean staticMembers, boolean kotlin) {
- Map<PropertyKey, MembersForProperty> membersMap = Maps.newHashMap();
- if (!kotlin) {
- for (PsiField field : clazz.getFields()) {
- if (field.getModifierList().hasExplicitModifier(PsiModifier.STATIC) != staticMembers) {
- continue;
- }
+ 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;
+ }
- if (field.hasModifierProperty(PsiModifier.PRIVATE)) {
- continue;
- }
+ 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();
+ }
- MembersForProperty members = new MembersForProperty();
- members.field = new PsiFieldWrapper(field);
- members.type = field.getType();
- membersMap.put(new PropertyKey(field.getName() /*, field.getType(), null*/), members);
- }
+ boolean isVar;
+ if (members.getter == null && members.setter == null) {
+ isVar = !members.field.isFinal();
+ } else {
+ isVar = members.setter != null;
}
-
- for (PsiMethod psiMethod : clazz.getMethods()) {
- PsiMethodWrapper method = new PsiMethodWrapper(psiMethod);
- if (method.isStatic() != staticMembers) {
- continue;
- }
+ PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
+ owner,
+ Collections.<AnnotationDescriptor>emptyList(),
+ isFinal && !staticMembers ? Modality.FINAL : Modality.OPEN, // TODO: abstract
+ resolveVisibilityFromPsiModifiers(anyMember.psiMember),
+ isVar,
+ false,
+ propertyName);
- if (method.isPrivate()) {
- continue;
- }
+ PropertyGetterDescriptor getterDescriptor = null;
+ PropertySetterDescriptor setterDescriptor = null;
+ if (members.getter != null) {
+ getterDescriptor = new PropertyGetterDescriptor(propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false);
+ }
+ if (members.setter != null) {
+ setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false);
+ }
- // TODO: "is" prefix
- // TODO: remove getJavaClass
- if (psiMethod.getName().startsWith(JvmAbi.GETTER_PREFIX)) {
+ propertyDescriptor.initialize(getterDescriptor, setterDescriptor);
- // TODO: some java properties too
- if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) {
+ final List<TypeParameterDescriptor> classTypeParameters;
+ if (anyMember instanceof PsiMethodWrapper && !anyMember.isStatic()) {
+ classTypeParameters = ((ClassDescriptor) owner).getTypeConstructor().getParameters();
+ } else {
+ classTypeParameters = new ArrayList<TypeParameterDescriptor>(0);
+ }
+ TypeParameterListTypeVariableResolver typeVariableResolver = new TypeParameterListTypeVariableResolver(classTypeParameters);
- if (psiMethod.getName().equals(JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD)) {
- continue;
- }
+ List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(0);
- int i = 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);
+ }
- 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);
+ JetType receiverJetType;
+ if (receiverType == null) {
+ receiverJetType = null;
+ } else {
+ receiverJetType = semanticServices.getTypeTransformer().transformToType(receiverType);
+ }
- // TODO: check conflicts with setter
- members.type = psiMethod.getReturnType();
- members.receiverType = receiverType;
- }
- } else if (psiMethod.getName().startsWith(JvmAbi.SETTER_PREFIX)) {
+ JetType type = semanticServices.getTypeTransformer().transformToType(propertyType);
- if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) {
- if (psiMethod.getParameterList().getParametersCount() == 0) {
- // TODO: report error properly
- throw new IllegalStateException();
- }
+ propertyDescriptor.setType(
+ type,
+ typeParameters,
+ DescriptorUtils.getExpectedThisObjectIfNeeded(owner),
+ receiverJetType
+ );
+ if (getterDescriptor != null) {
+ getterDescriptor.initialize(type);
+ }
+ if (setterDescriptor != null) {
+ // TODO: initialize
+ }
- int i = 0;
+ semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember.psiMember, propertyDescriptor);
+ namedMembers.propertyDescriptors = Collections.<VariableDescriptor>singleton(propertyDescriptor);
+ }
- 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);
+ private void resolveNamedGroupFunctions(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, boolean staticMembers, NamedMembers namedMembers, String functionName) {
+ if (namedMembers.functionDescriptors != null) {
+ return;
+ }
- // TODO: check conflicts with getter
- members.type = propertyType;
- members.receiverType = receiverType;
- }
- }
+ if (namedMembers.methods == null) {
+ namedMembers.functionDescriptors = Collections.emptySet();
+ return;
}
-
- return membersMap;
- }
-
- public Set<VariableDescriptor> resolveFieldGroupByName(@NotNull DeclarationDescriptor owner, PsiClass psiClass, String fieldName, boolean staticMembers) {
- Set<VariableDescriptor> r = Sets.newHashSet();
- // TODO: slow
- Set<VariableDescriptor> variables = resolveFieldGroup(owner, psiClass, staticMembers);
- for (VariableDescriptor variable : variables) {
- if (variable.getName().equals(fieldName)) {
- r.add(variable);
- }
+
+ Set<FunctionDescriptor> functionDescriptors = new HashSet<FunctionDescriptor>(namedMembers.methods.size());
+ for (PsiMethodWrapper method : namedMembers.methods) {
+ functionDescriptors.add(resolveMethodToFunctionDescriptor(owner, psiClass, typeSubstitutorForGenericSuperclasses, method));
}
- return r;
+ namedMembers.functionDescriptors = functionDescriptors;
}
- @NotNull
- public Set<VariableDescriptor> resolveFieldGroup(@NotNull DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) {
-
+ 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<VariableDescriptor> descriptors = Sets.newHashSet();
- Map<PropertyKey, MembersForProperty> membersForProperties = getMembersForProperties(psiClass, staticMembers, scopeData.kotlin);
- for (Map.Entry<PropertyKey, MembersForProperty> 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.<AnnotationDescriptor>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.<AnnotationDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false);
- }
- if (members.setter != null) {
- setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, Collections.<AnnotationDescriptor>emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false);
- }
-
- propertyDescriptor.initialize(getterDescriptor, setterDescriptor);
-
- final List<TypeParameterDescriptor> classTypeParameters;
- if (anyMember instanceof PsiMethodWrapper && !anyMember.isStatic()) {
- classTypeParameters = ((ClassDescriptor) owner).getTypeConstructor().getParameters();
- } else {
- classTypeParameters = new ArrayList<TypeParameterDescriptor>(0);
- }
- TypeParameterListTypeVariableResolver typeVariableResolver = new TypeParameterListTypeVariableResolver(classTypeParameters);
-
- List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(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<FunctionDescriptor> resolveFunctionGroup(@NotNull DeclarationDescriptor owner, @NotNull PsiClass psiClass, @Nullable ClassDescriptor classDescriptor, @NotNull String methodName, boolean staticMembers) {
- Set<FunctionDescriptor> writableFunctionGroup = Sets.newLinkedHashSet();
- final Collection<HierarchicalMethodSignature> signatures = psiClass.getVisibleSignatures();
- 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;
- }
+ ResolverScopeData resolverScopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass));
- @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;
+ Map<String, NamedMembers> namedMembersMap = resolverScopeData.namedMembersMap;
+
+ NamedMembers namedMembers = namedMembersMap.get(methodName);
+ if (namedMembers == null || namedMembers.methods == null) {
+ return Collections.emptySet();
}
- 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;
+
+ TypeSubstitutor typeSubstitutor = createSubstitutorForGenericSupertypes(classDescriptor);
+ 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<TypeParameterDescriptor> 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.<AnnotationDescriptor>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<TypeParameterDescriptor> methodTypeParameters = resolveMethodTypeParameters(new PsiMethodWrapper(psiMethod), functionDescriptorImpl, typeVariableResolverForParameters);
+ final List<TypeParameterDescriptor> 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 0000000..c56fb65
--- /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<String, NamedMembers> namedMembersMap = new HashMap<String, NamedMembers>();
+
+ 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<String, NamedMembers> 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 0000000..db363b8
--- /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 0000000..7da0943
--- /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<PsiMethodWrapper> methods;
+ @Nullable
+ MembersForProperty properties;
+ @Nullable
+ private PsiClass nestedClasses;
+
+ Set<VariableDescriptor> propertyDescriptors;
+ Set<FunctionDescriptor> functionDescriptors;
+
+ MembersForProperty getForProperty() {
+ if (properties == null) {
+ properties = new MembersForProperty();
+ }
+ return properties;
+ }
+
+ void addMethod(PsiMethodWrapper method) {
+ if (methods == null) {
+ methods = new ArrayList<PsiMethodWrapper>();
+ }
+ 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 0000000..0eb5204
--- /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<PsiMethodWrapper> methods;
+ @NotNull
+ public List<PsiMethodWrapper> getMethods() {
+ if (methods == null) {
+ PsiMethod[] psiMethods = psiClass.getMethods();
+ List<PsiMethodWrapper> methods = new ArrayList<PsiMethodWrapper>(psiMethods.length);
+ for (PsiMethod psiMethod : psiMethods) {
+ methods.add(new PsiMethodWrapper(psiMethod));
+ }
+ this.methods = methods;
+ }
+ return methods;
+ }
+
+ private List<PsiFieldWrapper> fields;
+ @NotNull
+ public List<PsiFieldWrapper> getFields() {
+ if (fields == null) {
+ PsiField[] psiFields = psiClass.getFields();
+ List<PsiFieldWrapper> fields = new ArrayList<PsiFieldWrapper>(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 75ad3e1..a896d42 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 0f67274..66b1df1 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();
+ }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment