allow two ext properties with same name in one package
This commit is contained in:
+173
-98
@@ -4,6 +4,7 @@ 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.Pair;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.psi.JavaPsiFacade;
|
||||
import com.intellij.psi.PsiClass;
|
||||
@@ -15,9 +16,12 @@ import com.intellij.psi.PsiMethod;
|
||||
import com.intellij.psi.PsiModifier;
|
||||
import com.intellij.psi.PsiModifierListOwner;
|
||||
import com.intellij.psi.PsiPackage;
|
||||
import com.intellij.psi.PsiPrimitiveType;
|
||||
import com.intellij.psi.PsiType;
|
||||
import com.intellij.psi.PsiTypeParameter;
|
||||
import com.intellij.psi.PsiTypeParameterListOwner;
|
||||
import com.intellij.psi.PsiTypeVariable;
|
||||
import com.intellij.psi.impl.source.PsiClassReferenceType;
|
||||
import com.intellij.psi.search.DelegatingGlobalSearchScope;
|
||||
import com.intellij.psi.search.GlobalSearchScope;
|
||||
import jet.typeinfo.TypeInfoVariance;
|
||||
@@ -60,6 +64,7 @@ import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -800,7 +805,7 @@ public class JavaDescriptorResolver {
|
||||
Map<String, NamedMembers> membersForProperties = scopeData.namedMembersMap;
|
||||
for (Map.Entry<String, NamedMembers> entry : membersForProperties.entrySet()) {
|
||||
NamedMembers namedMembers = entry.getValue();
|
||||
if (namedMembers.properties == null) {
|
||||
if (namedMembers.propertyAccessors == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -811,126 +816,196 @@ public class JavaDescriptorResolver {
|
||||
}
|
||||
return descriptors;
|
||||
}
|
||||
|
||||
private Object key(TypeSource typeSource) {
|
||||
if (typeSource == null) {
|
||||
return "";
|
||||
} else if (typeSource.getTypeString().length() > 0) {
|
||||
return typeSource.getTypeString();
|
||||
} else {
|
||||
if (typeSource.getPsiType() instanceof PsiClassType) {
|
||||
return ((PsiClassType) typeSource.getPsiType()).getClassName();
|
||||
} else if (typeSource.getPsiType() instanceof PsiPrimitiveType) {
|
||||
return typeSource.getPsiType().getPresentableText();
|
||||
} else {
|
||||
throw new IllegalStateException("" + typeSource.getPsiType().getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Object propertyKeyForGrouping(PropertyAccessorData propertyAccessor) {
|
||||
Object type = key(propertyAccessor.getType());
|
||||
Object receiverType = key(propertyAccessor.getReceiverType());
|
||||
return Pair.create(type, receiverType);
|
||||
}
|
||||
|
||||
private void resolveNamedGroupProperties(DeclarationDescriptor owner, boolean staticMembers, NamedMembers namedMembers, String propertyName) {
|
||||
if (namedMembers.propertyDescriptors != null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (namedMembers.properties == null) {
|
||||
if (namedMembers.propertyAccessors == 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()) {
|
||||
if (!staticMembers) {
|
||||
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);
|
||||
|
||||
class GroupingValue {
|
||||
PropertyAccessorData getter;
|
||||
PropertyAccessorData setter;
|
||||
PropertyAccessorData field;
|
||||
}
|
||||
|
||||
List<TypeParameterDescriptor> typeParametersForReceiver = new ArrayList<TypeParameterDescriptor>();
|
||||
typeParametersForReceiver.addAll(classTypeParameters);
|
||||
typeParametersForReceiver.addAll(typeParameters);
|
||||
Map<Object, GroupingValue> map = new HashMap<Object, GroupingValue>();
|
||||
|
||||
for (PropertyAccessorData propertyAccessor : namedMembers.propertyAccessors) {
|
||||
|
||||
Object key = propertyKeyForGrouping(propertyAccessor);
|
||||
|
||||
GroupingValue value = map.get(key);
|
||||
if (value == null) {
|
||||
value = new GroupingValue();
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
if (propertyAccessor.isGetter()) {
|
||||
if (value.getter != null) {
|
||||
throw new IllegalStateException("oops, duplicate key");
|
||||
}
|
||||
value.getter = propertyAccessor;
|
||||
} else if (propertyAccessor.isSetter()) {
|
||||
if (value.setter != null) {
|
||||
throw new IllegalStateException("oops, duplicate key");
|
||||
}
|
||||
value.setter = propertyAccessor;
|
||||
} else if (propertyAccessor.isField()) {
|
||||
if (value.field != null) {
|
||||
throw new IllegalStateException("oops, duplicate key");
|
||||
}
|
||||
value.field = propertyAccessor;
|
||||
} else {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
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());
|
||||
}
|
||||
Set<VariableDescriptor> r = new HashSet<VariableDescriptor>();
|
||||
|
||||
for (GroupingValue members : map.values()) {
|
||||
boolean isFinal;
|
||||
if (members.setter == null && members.getter == null) {
|
||||
isFinal = false;
|
||||
} else if (members.getter != null) {
|
||||
isFinal = members.getter.getMember().isFinal();
|
||||
} else if (members.setter != null) {
|
||||
isFinal = members.setter.getMember().isFinal();
|
||||
} else {
|
||||
isFinal = false;
|
||||
}
|
||||
|
||||
JetType type;
|
||||
if (propertyType.getTypeString().length() > 0) {
|
||||
type = semanticServices.getTypeTransformer().transformToType(propertyType.getTypeString(), typeVariableResolverForPropertyInternals);
|
||||
} else {
|
||||
type = semanticServices.getTypeTransformer().transformToType(propertyType.getPsiType());
|
||||
}
|
||||
PropertyAccessorData 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();
|
||||
}
|
||||
|
||||
propertyDescriptor.setType(
|
||||
type,
|
||||
typeParameters,
|
||||
DescriptorUtils.getExpectedThisObjectIfNeeded(owner),
|
||||
receiverJetType
|
||||
boolean isVar;
|
||||
if (members.getter == null && members.setter == null) {
|
||||
isVar = !members.field.getMember().isFinal();
|
||||
} else {
|
||||
isVar = members.setter != null;
|
||||
}
|
||||
|
||||
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
|
||||
owner,
|
||||
Collections.<AnnotationDescriptor>emptyList(),
|
||||
isFinal && !staticMembers ? Modality.FINAL : Modality.OPEN, // TODO: abstract
|
||||
resolveVisibilityFromPsiModifiers(anyMember.getMember().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);
|
||||
|
||||
List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(0);
|
||||
|
||||
if (members.setter != null) {
|
||||
PsiMethodWrapper method = (PsiMethodWrapper) members.setter.getMember();
|
||||
|
||||
if (anyMember == members.setter) {
|
||||
typeParameters = resolveMethodTypeParameters(method, setterDescriptor, typeVariableResolver);
|
||||
}
|
||||
}
|
||||
if (members.getter != null) {
|
||||
PsiMethodWrapper method = (PsiMethodWrapper) members.getter.getMember();
|
||||
|
||||
if (anyMember == members.getter) {
|
||||
typeParameters = resolveMethodTypeParameters(method, getterDescriptor, typeVariableResolver);
|
||||
}
|
||||
}
|
||||
|
||||
List<TypeParameterDescriptor> typeParametersForReceiver = new ArrayList<TypeParameterDescriptor>();
|
||||
typeParametersForReceiver.addAll(classTypeParameters);
|
||||
typeParametersForReceiver.addAll(typeParameters);
|
||||
TypeVariableResolver typeVariableResolverForPropertyInternals = new TypeParameterListTypeVariableResolver(typeParametersForReceiver);
|
||||
|
||||
JetType propertyType;
|
||||
if (anyMember.getType().getTypeString().length() > 0) {
|
||||
propertyType = semanticServices.getTypeTransformer().transformToType(anyMember.getType().getTypeString(), typeVariableResolverForPropertyInternals);
|
||||
} else {
|
||||
propertyType = semanticServices.getTypeTransformer().transformToType(anyMember.getType().getPsiType());
|
||||
}
|
||||
|
||||
JetType receiverType;
|
||||
if (anyMember.getReceiverType() == null) {
|
||||
receiverType = null;
|
||||
} else if (anyMember.getReceiverType().getTypeString().length() > 0) {
|
||||
receiverType = semanticServices.getTypeTransformer().transformToType(anyMember.getReceiverType().getTypeString(), typeVariableResolverForPropertyInternals);
|
||||
} else {
|
||||
receiverType = semanticServices.getTypeTransformer().transformToType(anyMember.getReceiverType().getPsiType());
|
||||
}
|
||||
|
||||
propertyDescriptor.setType(
|
||||
propertyType,
|
||||
typeParameters,
|
||||
DescriptorUtils.getExpectedThisObjectIfNeeded(owner),
|
||||
receiverType
|
||||
);
|
||||
if (getterDescriptor != null) {
|
||||
getterDescriptor.initialize(type);
|
||||
}
|
||||
if (setterDescriptor != null) {
|
||||
// TODO: initialize
|
||||
if (getterDescriptor != null) {
|
||||
getterDescriptor.initialize(propertyType);
|
||||
}
|
||||
if (setterDescriptor != null) {
|
||||
// TODO: initialize
|
||||
}
|
||||
|
||||
semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember.getMember().psiMember, propertyDescriptor);
|
||||
|
||||
r.add(propertyDescriptor);
|
||||
}
|
||||
|
||||
semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember.psiMember, propertyDescriptor);
|
||||
namedMembers.propertyDescriptors = Collections.<VariableDescriptor>singleton(propertyDescriptor);
|
||||
namedMembers.propertyDescriptors = r;
|
||||
}
|
||||
|
||||
private void resolveNamedGroupFunctions(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, boolean staticMembers, NamedMembers namedMembers, String functionName) {
|
||||
@@ -1145,7 +1220,7 @@ public class JavaDescriptorResolver {
|
||||
|
||||
private List<TypeParameterDescriptor> resolveMethodTypeParameters(
|
||||
@NotNull PsiMethodWrapper method,
|
||||
@NotNull FunctionDescriptor functionDescriptor,
|
||||
@NotNull DeclarationDescriptor functionDescriptor,
|
||||
@NotNull TypeVariableResolver classTypeVariableResolver) {
|
||||
if (method.getJetMethod().typeParameters().length() > 0) {
|
||||
List<TypeParameterDescriptor> r = resolveMethodTypeParametersFromJetSignature(
|
||||
@@ -1163,7 +1238,7 @@ public class JavaDescriptorResolver {
|
||||
* @see #resolveClassTypeParametersFromJetSignature(String, com.intellij.psi.PsiClass, MutableClassDescriptorLite)
|
||||
*/
|
||||
private List<TypeParameterDescriptor> resolveMethodTypeParametersFromJetSignature(String jetSignature, final PsiMethod method,
|
||||
final FunctionDescriptor functionDescriptor, final TypeVariableResolver classTypeVariableResolver)
|
||||
final DeclarationDescriptor functionDescriptor, final TypeVariableResolver classTypeVariableResolver)
|
||||
{
|
||||
final List<TypeParameterDescriptor> r = new ArrayList<TypeParameterDescriptor>();
|
||||
|
||||
|
||||
+6
-13
@@ -54,11 +54,8 @@ class JavaDescriptorResolverHelper {
|
||||
|
||||
NamedMembers namedMembers = getNamedMembers(field.getName());
|
||||
|
||||
MembersForProperty members = new MembersForProperty();
|
||||
members.field = field;
|
||||
members.type = new TypeSource("", field.getType());
|
||||
|
||||
namedMembers.properties = members;
|
||||
TypeSource type = new TypeSource("", field.getType());
|
||||
namedMembers.addPropertyAccessor(new PropertyAccessorData(field, type, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -110,12 +107,11 @@ class JavaDescriptorResolverHelper {
|
||||
|
||||
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;
|
||||
TypeSource propertyType = new TypeSource(method.getJetMethod().propertyType(), method.getReturnType());
|
||||
|
||||
members.addPropertyAccessor(new PropertyAccessorData(method, true, propertyType, receiverType));
|
||||
}
|
||||
} else if (method.getName().startsWith(JvmAbi.SETTER_PREFIX)) {
|
||||
|
||||
@@ -147,11 +143,8 @@ class JavaDescriptorResolverHelper {
|
||||
|
||||
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;
|
||||
members.addPropertyAccessor(new PropertyAccessorData(method, false, propertyType, receiverType));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
class MembersForProperty {
|
||||
PsiFieldWrapper field;
|
||||
PsiMethodWrapper setter;
|
||||
PsiMethodWrapper getter;
|
||||
|
||||
TypeSource type;
|
||||
TypeSource receiverType;
|
||||
}
|
||||
@@ -17,25 +17,29 @@ import java.util.Set;
|
||||
class NamedMembers {
|
||||
String name;
|
||||
List<PsiMethodWrapper> methods;
|
||||
|
||||
@Nullable
|
||||
MembersForProperty properties;
|
||||
PsiFieldWrapper field;
|
||||
@Nullable
|
||||
List<PropertyAccessorData> propertyAccessors;
|
||||
|
||||
@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);
|
||||
}
|
||||
|
||||
void addPropertyAccessor(PropertyAccessorData propertyAccessorData) {
|
||||
if (propertyAccessors == null) {
|
||||
propertyAccessors = new ArrayList<PropertyAccessorData>();
|
||||
}
|
||||
propertyAccessors.add(propertyAccessorData);
|
||||
}
|
||||
}
|
||||
|
||||
+63
@@ -0,0 +1,63 @@
|
||||
package org.jetbrains.jet.lang.resolve.java;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.PropertyAccessorDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
class PropertyAccessorData {
|
||||
|
||||
@NotNull
|
||||
private final PsiMemberWrapper member;
|
||||
private final boolean getter;
|
||||
|
||||
@NotNull
|
||||
private final TypeSource type;
|
||||
@Nullable
|
||||
private final TypeSource receiverType;
|
||||
|
||||
|
||||
PropertyAccessorData(@NotNull PsiMethodWrapper method, boolean getter, @NotNull TypeSource type, @Nullable TypeSource receiverType) {
|
||||
this.member = method;
|
||||
this.type = type;
|
||||
this.receiverType = receiverType;
|
||||
this.getter = getter;
|
||||
}
|
||||
|
||||
PropertyAccessorData(@NotNull PsiFieldWrapper field, @NotNull TypeSource type, @Nullable TypeSource receiverType) {
|
||||
this.member = field;
|
||||
this.type = type;
|
||||
this.receiverType = receiverType;
|
||||
this.getter = false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public PsiMemberWrapper getMember() {
|
||||
return member;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public TypeSource getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public TypeSource getReceiverType() {
|
||||
return receiverType;
|
||||
}
|
||||
|
||||
public boolean isGetter() {
|
||||
return member instanceof PsiMethodWrapper && getter;
|
||||
}
|
||||
|
||||
public boolean isSetter() {
|
||||
return member instanceof PsiMethodWrapper && !getter;
|
||||
}
|
||||
|
||||
public boolean isField() {
|
||||
return member instanceof PsiFieldWrapper;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
/**
|
||||
* @author Stepan Koltsov
|
||||
*/
|
||||
public class PsiMemberWrapper {
|
||||
public abstract class PsiMemberWrapper {
|
||||
|
||||
@NotNull
|
||||
protected final PsiMember psiMember;
|
||||
|
||||
Reference in New Issue
Block a user