提交 df9a4c77 编写于 作者: S Stepan Koltsov

allow two ext properties with same name in one package

上级 509e0189
......@@ -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();
final List<TypeParameterDescriptor> classTypeParameters;
if (!staticMembers) {
classTypeParameters = ((ClassDescriptor) owner).getTypeConstructor().getParameters();
} else {
isFinal = false;
classTypeParameters = new ArrayList<TypeParameterDescriptor>(0);
}
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();
TypeParameterListTypeVariableResolver typeVariableResolver = new TypeParameterListTypeVariableResolver(classTypeParameters);
class GroupingValue {
PropertyAccessorData getter;
PropertyAccessorData setter;
PropertyAccessorData field;
}
Map<Object, GroupingValue> map = new HashMap<Object, GroupingValue>();
boolean isVar;
if (members.getter == null && members.setter == null) {
isVar = !members.field.isFinal();
} else {
isVar = members.setter != null;
}
for (PropertyAccessorData propertyAccessor : namedMembers.propertyAccessors) {
PropertyDescriptor propertyDescriptor = new PropertyDescriptor(
owner,
Collections.<AnnotationDescriptor>emptyList(),
isFinal && !staticMembers ? Modality.FINAL : Modality.OPEN, // TODO: abstract
resolveVisibilityFromPsiModifiers(anyMember.psiMember),
isVar,
false,
propertyName);
Object key = propertyKeyForGrouping(propertyAccessor);
GroupingValue value = map.get(key);
if (value == null) {
value = new GroupingValue();
map.put(key, value);
}
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);
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();
}
}
propertyDescriptor.initialize(getterDescriptor, setterDescriptor);
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;
}
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);
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();
}
List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(0);
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);
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);
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);
}
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());
}
propertyDescriptor.initialize(getterDescriptor, setterDescriptor);
JetType type;
if (propertyType.getTypeString().length() > 0) {
type = semanticServices.getTypeTransformer().transformToType(propertyType.getTypeString(), typeVariableResolverForPropertyInternals);
} else {
type = semanticServices.getTypeTransformer().transformToType(propertyType.getPsiType());
}
List<TypeParameterDescriptor> typeParameters = new ArrayList<TypeParameterDescriptor>(0);
if (members.setter != null) {
PsiMethodWrapper method = (PsiMethodWrapper) members.setter.getMember();
propertyDescriptor.setType(
type,
typeParameters,
DescriptorUtils.getExpectedThisObjectIfNeeded(owner),
receiverJetType
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>();
......
......@@ -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));
}
}
......
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
PsiFieldWrapper field;
@Nullable
MembersForProperty properties;
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);
}
}
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;
}
}
......@@ -7,7 +7,7 @@ import org.jetbrains.annotations.NotNull;
/**
* @author Stepan Koltsov
*/
public class PsiMemberWrapper {
public abstract class PsiMemberWrapper {
@NotNull
protected final PsiMember psiMember;
......
......@@ -10,6 +10,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver;
import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeSubstitutor;
import org.jetbrains.jet.lang.types.Variance;
......@@ -37,6 +38,15 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
private List<TypeParameterDescriptor> typeParemeters;
private PropertyGetterDescriptor getter;
private PropertySetterDescriptor setter;
private PropertyDescriptor() {
super(ErrorUtils.getErrorClass(), Collections.<AnnotationDescriptor>emptyList(), "dummy");
this.modality = null;
this.visibility = null;
this.isVar = false;
this.isObject = false;
this.original = null;
}
private PropertyDescriptor(
@Nullable PropertyDescriptor original,
......@@ -243,4 +253,8 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
propertyDescriptor.initialize(newGetter, newSetter);
return propertyDescriptor;
}
public static PropertyDescriptor createDummy() {
return new PropertyDescriptor();
}
}
package test
var Int.junk: Short
get() = throw Exception()
set(p: Short) = throw Exception()
val String.junk: Int
get() = throw Exception()
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册