Merge remote branch 'origin/master'

This commit is contained in:
Andrey Breslav
2012-01-18 12:07:12 +04:00
32 changed files with 760 additions and 445 deletions
@@ -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
@@ -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;
@@ -737,15 +735,6 @@ public class JavaDescriptorResolver {
PsiType psiType = parameter.getPsiParameter().getType();
JetType varargElementType;
if (psiType instanceof PsiEllipsisType) {
PsiEllipsisType psiEllipsisType = (PsiEllipsisType) psiType;
varargElementType = semanticServices.getTypeTransformer().transformToType(psiEllipsisType.getComponentType());
}
else {
varargElementType = null;
}
boolean nullable = parameter.getJetValueParameter().nullable();
// TODO: must be very slow, make it lazy?
@@ -765,6 +754,14 @@ public class JavaDescriptorResolver {
} else {
outType = semanticServices.getTypeTransformer().transformToType(psiType);
}
JetType varargElementType;
if (psiType instanceof PsiEllipsisType) {
varargElementType = semanticServices.getJetSemanticServices().getStandardLibrary().getArrayElementType(outType);
} else {
varargElementType = null;
}
if (receiver) {
return JvmMethodParameterMeaning.receiver(outType);
} else {
@@ -781,217 +778,187 @@ 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;
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<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;
}
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<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);
}
}
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<VariableDescriptor> resolveFieldGroup(@NotNull DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) {
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();
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;
}
TypeSource propertyType = namedMembers.properties.type;
TypeSource receiver = 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.<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);
}
List<TypeParameterDescriptor> typeParametersForReceiver = new ArrayList<TypeParameterDescriptor>();
typeParametersForReceiver.addAll(classTypeParameters);
typeParametersForReceiver.addAll(typeParameters);
TypeParameterListTypeVariableResolver typeVariableResolverForPropertyInternals = new TypeParameterListTypeVariableResolver(typeParametersForReceiver);
JetType receiverJetType;
if (receiver == null) {
receiverJetType = null;
} else if (receiver.getTypeString().length() > 0) {
receiverJetType = semanticServices.getTypeTransformer().transformToType(receiver.getTypeString(), typeVariableResolverForPropertyInternals);
} else {
receiverJetType = semanticServices.getTypeTransformer().transformToType(receiver.getPsiType());
}
JetType type;
if (propertyType.getTypeString().length() > 0) {
type = semanticServices.getTypeTransformer().transformToType(propertyType.getTypeString(), typeVariableResolverForPropertyInternals);
} else {
type = semanticServices.getTypeTransformer().transformToType(propertyType.getPsiType());
}
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.<VariableDescriptor>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<FunctionDescriptor> functionDescriptors = new HashSet<FunctionDescriptor>(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 +966,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();
ResolverScopeData resolverScopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass));
Map<String, NamedMembers> 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 +1023,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 +1082,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 +1096,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 +1132,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 +1244,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);
@@ -0,0 +1,174 @@
package org.jetbrains.jet.lang.resolve.java;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.HierarchicalMethodSignature;
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 = new TypeSource("", 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;
TypeSource receiverType;
if (i < method.getParameters().size() && method.getParameter(i).getJetValueParameter().receiver()) {
PsiParameterWrapper receiverParameter = method.getParameter(i);
receiverType = new TypeSource(receiverParameter.getJetValueParameter().type(), receiverParameter.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 = new TypeSource(method.getJetMethod().propertyType(), 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;
TypeSource receiverType = null;
PsiParameterWrapper p1 = method.getParameter(0);
if (p1.getJetValueParameter().receiver()) {
receiverType = new TypeSource(p1.getJetValueParameter().type(), p1.getPsiParameter().getType());
++i;
}
while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) {
++i;
}
if (i + 1 != method.getParameters().size()) {
throw new IllegalStateException();
}
PsiParameterWrapper propertyTypeParameter = method.getParameter(i);
TypeSource propertyType = new TypeSource(method.getJetMethod().propertyType(), propertyTypeParameter.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;
}
}
@@ -190,7 +190,6 @@ public class JavaTypeTransformer {
PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
classDescriptorMap.put(jvmPrimitiveType.getWrapper().getFqName(), standardLibrary.getPrimitiveClassDescriptor(primitiveType));
}
//classDescriptorMap.put("java.lang.Object", standardLibrary.get
classDescriptorMap.put("java.lang.String", standardLibrary.getString());
}
return classDescriptorMap;
@@ -12,11 +12,14 @@ import org.jetbrains.jet.lang.types.TypeProjection;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter;
import org.jetbrains.jet.rt.signature.JetSignatureVariance;
import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author Stepan Koltsov
@@ -75,6 +78,26 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
this.classDescriptor = this.javaSemanticServices.getTypeTransformer().getPrimitiveWrappersClassDescriptorMap().get(ourName);
if (this.classDescriptor == null && ourName.equals("java.lang.Object")) {
this.classDescriptor = JetStandardClasses.getAny();
}
if (classDescriptor == null) {
// TODO: this is the worst code in Kotlin project
Matcher matcher = Pattern.compile("jet\\.Function(\\d+)").matcher(ourName);
if (matcher.matches()) {
classDescriptor = JetStandardClasses.getFunction(Integer.parseInt(matcher.group(1)));
}
}
if (classDescriptor == null) {
Matcher matcher = Pattern.compile("jet\\.Tuple(\\d+)").matcher(ourName);
if (matcher.matches()) {
classDescriptor = JetStandardClasses.getTuple(Integer.parseInt(matcher.group(1)));
}
}
if (this.classDescriptor == null) {
this.classDescriptor = javaDescriptorResolver.resolveClass(ourName);
}
@@ -86,22 +109,22 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
this.typeArguments = new ArrayList<TypeProjection>();
}
private static Variance parseVariance(char wildcard) {
switch (wildcard) {
case '=': return Variance.INVARIANT;
case '+': return Variance.OUT_VARIANCE;
case '-': return Variance.IN_VARIANCE;
private static Variance parseVariance(JetSignatureVariance variance) {
switch (variance) {
case INVARIANT: return Variance.INVARIANT;
case OUT: return Variance.OUT_VARIANCE;
case IN: return Variance.IN_VARIANCE;
default: throw new IllegalStateException();
}
}
@Override
public JetSignatureVisitor visitTypeArgument(final char wildcard) {
public JetSignatureVisitor visitTypeArgument(final JetSignatureVariance variance) {
return new JetTypeJetSignatureReader(javaSemanticServices, jetStandardLibrary, typeVariableResolver) {
@Override
protected void done(@NotNull JetType jetType) {
typeArguments.add(new TypeProjection(parseVariance(wildcard), jetType));
typeArguments.add(new TypeProjection(parseVariance(variance), jetType));
}
};
}
@@ -0,0 +1,13 @@
package org.jetbrains.jet.lang.resolve.java;
/**
* @author Stepan Koltsov
*/
class MembersForProperty {
PsiFieldWrapper field;
PsiMethodWrapper setter;
PsiMethodWrapper getter;
TypeSource type;
TypeSource receiverType;
}
@@ -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);
}
}
@@ -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;
}
}
@@ -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();
}
}
@@ -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();
}
}
@@ -0,0 +1,30 @@
package org.jetbrains.jet.lang.resolve.java;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
/**
* @author Stepan Koltsov
*/
class TypeSource {
@NotNull
private final String typeString;
@NotNull
private final PsiType psiType;
TypeSource(@NotNull String typeString, @NotNull PsiType psiType) {
this.typeString = typeString;
this.psiType = psiType;
}
@NotNull
public String getTypeString() {
return typeString;
}
@NotNull
public PsiType getPsiType() {
return psiType;
}
}