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
@@ -6,6 +6,7 @@ import org.jetbrains.jet.lang.resolve.java.JetSignatureUtils;
import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.rt.signature.JetSignatureAdapter; import org.jetbrains.jet.rt.signature.JetSignatureAdapter;
import org.jetbrains.jet.rt.signature.JetSignatureReader; import org.jetbrains.jet.rt.signature.JetSignatureReader;
import org.jetbrains.jet.rt.signature.JetSignatureVariance;
import org.jetbrains.jet.rt.signature.JetSignatureWriter; import org.jetbrains.jet.rt.signature.JetSignatureWriter;
import org.objectweb.asm.Type; import org.objectweb.asm.Type;
import org.objectweb.asm.commons.Method; import org.objectweb.asm.commons.Method;
@@ -204,9 +205,19 @@ public class BothSignatureWriter {
pop(); pop();
} }
public void writeTypeArgument(char c) { private static JetSignatureVariance toJetSignatureVariance(Variance variance) {
push(signatureVisitor().visitTypeArgument(c)); switch (variance) {
jetSignatureWriter.visitTypeArgument(c); case INVARIANT: return JetSignatureVariance.INVARIANT;
case IN_VARIANCE: return JetSignatureVariance.IN;
case OUT_VARIANCE: return JetSignatureVariance.OUT;
default: throw new IllegalStateException();
}
}
public void writeTypeArgument(Variance variance) {
JetSignatureVariance jsVariance = toJetSignatureVariance(variance);
push(signatureVisitor().visitTypeArgument(jsVariance.getC()));
jetSignatureWriter.visitTypeArgument(jsVariance);
generic = true; generic = true;
} }
@@ -124,6 +124,9 @@ public class FunctionCodegen {
av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true); av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_NULLABLE_FIELD, true);
} }
av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_RECEIVER_FIELD, true); av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_RECEIVER_FIELD, true);
if (jvmSignature.getKotlinParameterTypes() != null && jvmSignature.getKotlinParameterTypes().get(0) != null) {
av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_TYPE_FIELD, jvmSignature.getKotlinParameterTypes().get(0).getKotlinSignature());
}
av.visitEnd(); av.visitEnd();
} }
for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) {
@@ -298,7 +298,7 @@ public class JetTypeMapper {
signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable()); signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable());
for (TypeProjection proj : jetType.getArguments()) { for (TypeProjection proj : jetType.getArguments()) {
// TODO: +- // TODO: +-
signatureVisitor.writeTypeArgument('='); signatureVisitor.writeTypeArgument(proj.getProjectionKind());
mapType(proj.getType(), kind, signatureVisitor, true); mapType(proj.getType(), kind, signatureVisitor, true);
signatureVisitor.writeTypeArgumentEnd(); signatureVisitor.writeTypeArgumentEnd();
} }
@@ -2,15 +2,26 @@ package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; 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.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; 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.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
import org.jetbrains.jet.lang.types.TypeSubstitutor; 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 * @author abreslav
@@ -20,8 +31,6 @@ public class JavaClassMembersScope implements JetScope {
private final JavaSemanticServices semanticServices; private final JavaSemanticServices semanticServices;
private final boolean staticMembers; private final boolean staticMembers;
private final DeclarationDescriptor containingDeclaration; 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 final Map<String, ClassifierDescriptor> classifiers = Maps.newHashMap();
private Collection<DeclarationDescriptor> allDescriptors; private Collection<DeclarationDescriptor> allDescriptors;
@@ -76,7 +85,7 @@ public class JavaClassMembersScope implements JetScope {
if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) { if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) {
continue; continue;
} }
FunctionDescriptor functionDescriptor = semanticServices.getDescriptorResolver().resolveMethodToFunctionDescriptor(containingDeclaration, psiClass, substitutorForGenericSupertypes, method); FunctionDescriptor functionDescriptor = semanticServices.getDescriptorResolver().resolveMethodToFunctionDescriptor(containingDeclaration, psiClass, substitutorForGenericSupertypes, new PsiMethodWrapper(method));
if (functionDescriptor != null) { if (functionDescriptor != null) {
allDescriptors.add(functionDescriptor); allDescriptors.add(functionDescriptor);
} }
@@ -117,14 +126,7 @@ public class JavaClassMembersScope implements JetScope {
@NotNull @NotNull
@Override @Override
public Set<VariableDescriptor> getProperties(@NotNull String name) { public Set<VariableDescriptor> getProperties(@NotNull String name) {
Set<VariableDescriptor> variableDescriptor = variables.get(name); return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDeclaration, psiClass, name, staticMembers);
if (variableDescriptor == null) {
variableDescriptor = doGetVariable(name);
if (variableDescriptor != null) {
variables.put(name, variableDescriptor);
}
}
return variableDescriptor != null ? variableDescriptor : Collections.<VariableDescriptor>emptySet();
} }
@Override @Override
@@ -132,32 +134,15 @@ public class JavaClassMembersScope implements JetScope {
return null; 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 @NotNull
@Override @Override
public Set<FunctionDescriptor> getFunctions(@NotNull String name) { public Set<FunctionDescriptor> getFunctions(@NotNull String name) {
Set<FunctionDescriptor> functionGroup = functionGroups.get(name); return semanticServices.getDescriptorResolver().resolveFunctionGroup(
if (functionGroup == null) { containingDeclaration,
functionGroup = semanticServices.getDescriptorResolver().resolveFunctionGroup( psiClass,
containingDeclaration, staticMembers ? null : (ClassDescriptor) containingDeclaration,
psiClass, name,
staticMembers ? null : (ClassDescriptor) containingDeclaration, staticMembers);
name,
staticMembers);
functionGroups.put(name, functionGroup);
}
return functionGroup;
} }
@Override @Override
@@ -4,15 +4,12 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import com.intellij.openapi.project.Project; import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile; import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.HierarchicalMethodSignature;
import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.JavaPsiFacade;
import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiClassType;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiEllipsisType; import com.intellij.psi.PsiEllipsisType;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiJavaFile; import com.intellij.psi.PsiJavaFile;
import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiModifier;
@@ -63,6 +60,7 @@ import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
@@ -129,10 +127,11 @@ public class JavaDescriptorResolver {
} }
} }
private static abstract class ResolverScopeData { private static abstract class ResolverScopeData {
@Nullable
private Set<VariableDescriptor> properties;
protected boolean kotlin; protected boolean kotlin;
private Map<String, NamedMembers> namedMembersMap;
} }
private static class ResolverClassData extends ResolverScopeData { private static class ResolverClassData extends ResolverScopeData {
@@ -159,7 +158,6 @@ public class JavaDescriptorResolver {
private final Map<PsiTypeParameter, TypeParameterDescriptorInitialization> typeParameterDescriptorCache = Maps.newHashMap(); private final Map<PsiTypeParameter, TypeParameterDescriptorInitialization> typeParameterDescriptorCache = Maps.newHashMap();
protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap(); protected final Map<PsiMethod, FunctionDescriptor> methodDescriptorCache = Maps.newHashMap();
protected final Map<PsiField, VariableDescriptor> fieldDescriptorCache = Maps.newHashMap();
protected final JavaPsiFacade javaFacade; protected final JavaPsiFacade javaFacade;
protected final GlobalSearchScope javaSearchScope; protected final GlobalSearchScope javaSearchScope;
protected final JavaSemanticServices semanticServices; protected final JavaSemanticServices semanticServices;
@@ -737,15 +735,6 @@ public class JavaDescriptorResolver {
PsiType psiType = parameter.getPsiParameter().getType(); 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(); boolean nullable = parameter.getJetValueParameter().nullable();
// TODO: must be very slow, make it lazy? // TODO: must be very slow, make it lazy?
@@ -765,6 +754,14 @@ public class JavaDescriptorResolver {
} else { } else {
outType = semanticServices.getTypeTransformer().transformToType(psiType); outType = semanticServices.getTypeTransformer().transformToType(psiType);
} }
JetType varargElementType;
if (psiType instanceof PsiEllipsisType) {
varargElementType = semanticServices.getJetSemanticServices().getStandardLibrary().getArrayElementType(outType);
} else {
varargElementType = null;
}
if (receiver) { if (receiver) {
return JvmMethodParameterMeaning.receiver(outType); return JvmMethodParameterMeaning.receiver(outType);
} else { } 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) { public Set<VariableDescriptor> resolveFieldGroupByName(@NotNull DeclarationDescriptor owner, PsiClass psiClass, String fieldName, boolean staticMembers) {
Set<VariableDescriptor> r = Sets.newHashSet(); ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass));
// TODO: slow
Set<VariableDescriptor> variables = resolveFieldGroup(owner, psiClass, staticMembers); NamedMembers namedMembers = scopeData.namedMembersMap.get(fieldName);
for (VariableDescriptor variable : variables) { if (namedMembers == null) {
if (variable.getName().equals(fieldName)) { return Collections.emptySet();
r.add(variable);
}
} }
return r;
resolveNamedGroupProperties(owner, staticMembers, namedMembers, fieldName);
return namedMembers.propertyDescriptors;
} }
@NotNull @NotNull
public Set<VariableDescriptor> resolveFieldGroup(@NotNull DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) { 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; ResolverScopeData scopeData;
boolean staticMembers;
if (owner instanceof JavaNamespaceDescriptor) { if (owner instanceof JavaNamespaceDescriptor) {
scopeData = namespaceDescriptorCacheByFqn.get(((JavaNamespaceDescriptor) owner).getQualifiedName()); scopeData = namespaceDescriptorCacheByFqn.get(((JavaNamespaceDescriptor) owner).getQualifiedName());
staticMembers = true;
} else if (owner instanceof ClassDescriptor) { } else if (owner instanceof ClassDescriptor) {
scopeData = classDescriptorCache.get(psiClass.getQualifiedName()); scopeData = classDescriptorCache.get(psiClass.getQualifiedName());
staticMembers = false;
} else { } else {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@@ -999,151 +966,29 @@ public class JavaDescriptorResolver {
throw new IllegalStateException(); throw new IllegalStateException();
} }
if (scopeData.properties != null) { if (scopeData.namedMembersMap == null) {
return scopeData.properties; scopeData.namedMembersMap = JavaDescriptorResolverHelper.getNamedMembers(psiClass, staticMembers, scopeData.kotlin);
} }
Set<VariableDescriptor> descriptors = Sets.newHashSet(); return scopeData;
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;
} }
@NotNull @NotNull
public Set<FunctionDescriptor> resolveFunctionGroup(@NotNull DeclarationDescriptor owner, @NotNull PsiClass psiClass, @Nullable ClassDescriptor classDescriptor, @NotNull String methodName, boolean staticMembers) { 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); TypeSubstitutor typeSubstitutor = createSubstitutorForGenericSupertypes(classDescriptor);
for (HierarchicalMethodSignature signature: signatures) { resolveNamedGroupFunctions(owner, psiClass, typeSubstitutor, staticMembers, namedMembers, methodName);
if (!methodName.equals(signature.getName())) {
continue;
}
FunctionDescriptor substitutedFunctionDescriptor = resolveHierarchicalSignatureToFunction(owner, psiClass, staticMembers, typeSubstitutor, signature); return namedMembers.functionDescriptors;
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;
} }
public TypeSubstitutor createSubstitutorForGenericSupertypes(ClassDescriptor classDescriptor) { public TypeSubstitutor createSubstitutorForGenericSupertypes(ClassDescriptor classDescriptor) {
@@ -1178,16 +1023,15 @@ public class JavaDescriptorResolver {
} }
@Nullable @Nullable
public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethod psiMethod) { public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethodWrapper method) {
PsiMethodWrapper method = new PsiMethodWrapper(psiMethod);
PsiType returnType = psiMethod.getReturnType(); PsiType returnType = method.getReturnType();
if (returnType == null) { if (returnType == null) {
return null; return null;
} }
FunctionDescriptor functionDescriptor = methodDescriptorCache.get(psiMethod); FunctionDescriptor functionDescriptor = methodDescriptorCache.get(method.getPsiMethod());
if (functionDescriptor != null) { if (functionDescriptor != null) {
if (psiMethod.getContainingClass() != psiClass) { if (method.getPsiMethod().getContainingClass() != psiClass) {
functionDescriptor = functionDescriptor.substitute(typeSubstitutorForGenericSuperclasses); functionDescriptor = functionDescriptor.substitute(typeSubstitutorForGenericSuperclasses);
} }
return functionDescriptor; return functionDescriptor;
@@ -1238,11 +1082,11 @@ public class JavaDescriptorResolver {
DeclarationDescriptor classDescriptor; DeclarationDescriptor classDescriptor;
final List<TypeParameterDescriptor> classTypeParameters; final List<TypeParameterDescriptor> classTypeParameters;
if (method.isStatic()) { if (method.isStatic()) {
classDescriptor = resolveNamespace(psiMethod.getContainingClass()); classDescriptor = resolveNamespace(method.getPsiMethod().getContainingClass());
classTypeParameters = Collections.emptyList(); classTypeParameters = Collections.emptyList();
} }
else { else {
ClassDescriptor classClassDescriptor = resolveClass(psiMethod.getContainingClass()); ClassDescriptor classClassDescriptor = resolveClass(method.getPsiMethod().getContainingClass());
classDescriptor = classClassDescriptor; classDescriptor = classClassDescriptor;
classTypeParameters = classClassDescriptor.getTypeConstructor().getParameters(); classTypeParameters = classClassDescriptor.getTypeConstructor().getParameters();
} }
@@ -1252,14 +1096,14 @@ public class JavaDescriptorResolver {
NamedFunctionDescriptorImpl functionDescriptorImpl = new NamedFunctionDescriptorImpl( NamedFunctionDescriptorImpl functionDescriptorImpl = new NamedFunctionDescriptorImpl(
owner, owner,
Collections.<AnnotationDescriptor>emptyList(), // TODO Collections.<AnnotationDescriptor>emptyList(), // TODO
psiMethod.getName() method.getName()
); );
methodDescriptorCache.put(psiMethod, functionDescriptorImpl); methodDescriptorCache.put(method.getPsiMethod(), functionDescriptorImpl);
// TODO: add outer classes // TODO: add outer classes
TypeParameterListTypeVariableResolver typeVariableResolverForParameters = new TypeParameterListTypeVariableResolver(classTypeParameters); 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 { class MethodTypeVariableResolver implements TypeVariableResolver {
@@ -1288,12 +1132,12 @@ public class JavaDescriptorResolver {
methodTypeParameters, methodTypeParameters,
valueParameterDescriptors.descriptors, valueParameterDescriptors.descriptors,
makeReturnType(returnType, method, new MethodTypeVariableResolver()), makeReturnType(returnType, method, new MethodTypeVariableResolver()),
Modality.convertFromFlags(psiMethod.hasModifierProperty(PsiModifier.ABSTRACT), !psiMethod.hasModifierProperty(PsiModifier.FINAL)), Modality.convertFromFlags(method.getPsiMethod().hasModifierProperty(PsiModifier.ABSTRACT), !method.isFinal()),
resolveVisibilityFromPsiModifiers(psiMethod) resolveVisibilityFromPsiModifiers(method.getPsiMethod())
); );
semanticServices.getTrace().record(BindingContext.FUNCTION, psiMethod, functionDescriptorImpl); semanticServices.getTrace().record(BindingContext.FUNCTION, method.getPsiMethod(), functionDescriptorImpl);
FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl; FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl;
if (psiMethod.getContainingClass() != psiClass) { if (method.getPsiMethod().getContainingClass() != psiClass) {
substitutedFunctionDescriptor = functionDescriptorImpl.substitute(typeSubstitutorForGenericSuperclasses); substitutedFunctionDescriptor = functionDescriptorImpl.substitute(typeSubstitutorForGenericSuperclasses);
} }
return substitutedFunctionDescriptor; return substitutedFunctionDescriptor;
@@ -1400,7 +1244,7 @@ public class JavaDescriptorResolver {
ownerOwner = classDescriptor; ownerOwner = classDescriptor;
substitutorForGenericSupertypes = semanticServices.getDescriptorResolver().createSubstitutorForGenericSupertypes(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); return resolveTypeParameter(functionDescriptor, typeParameter);
} }
throw new IllegalStateException("Unknown parent type: " + owner); 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(); PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType();
classDescriptorMap.put(jvmPrimitiveType.getWrapper().getFqName(), standardLibrary.getPrimitiveClassDescriptor(primitiveType)); classDescriptorMap.put(jvmPrimitiveType.getWrapper().getFqName(), standardLibrary.getPrimitiveClassDescriptor(primitiveType));
} }
//classDescriptorMap.put("java.lang.Object", standardLibrary.get
classDescriptorMap.put("java.lang.String", standardLibrary.getString()); classDescriptorMap.put("java.lang.String", standardLibrary.getString());
} }
return classDescriptorMap; 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.TypeUtils;
import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.lang.types.Variance;
import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter; import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter;
import org.jetbrains.jet.rt.signature.JetSignatureVariance;
import org.jetbrains.jet.rt.signature.JetSignatureVisitor; import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/** /**
* @author Stepan Koltsov * @author Stepan Koltsov
@@ -75,6 +78,26 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
this.classDescriptor = this.javaSemanticServices.getTypeTransformer().getPrimitiveWrappersClassDescriptorMap().get(ourName); 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) { if (this.classDescriptor == null) {
this.classDescriptor = javaDescriptorResolver.resolveClass(ourName); this.classDescriptor = javaDescriptorResolver.resolveClass(ourName);
} }
@@ -86,22 +109,22 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd
this.typeArguments = new ArrayList<TypeProjection>(); this.typeArguments = new ArrayList<TypeProjection>();
} }
private static Variance parseVariance(char wildcard) { private static Variance parseVariance(JetSignatureVariance variance) {
switch (wildcard) { switch (variance) {
case '=': return Variance.INVARIANT; case INVARIANT: return Variance.INVARIANT;
case '+': return Variance.OUT_VARIANCE; case OUT: return Variance.OUT_VARIANCE;
case '-': return Variance.IN_VARIANCE; case IN: return Variance.IN_VARIANCE;
default: throw new IllegalStateException(); default: throw new IllegalStateException();
} }
} }
@Override @Override
public JetSignatureVisitor visitTypeArgument(final char wildcard) { public JetSignatureVisitor visitTypeArgument(final JetSignatureVariance variance) {
return new JetTypeJetSignatureReader(javaSemanticServices, jetStandardLibrary, typeVariableResolver) { return new JetTypeJetSignatureReader(javaSemanticServices, jetStandardLibrary, typeVariableResolver) {
@Override @Override
protected void done(@NotNull JetType jetType) { 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; package org.jetbrains.jet.lang.resolve.java;
import com.intellij.psi.PsiField;
import com.intellij.psi.PsiMember; import com.intellij.psi.PsiMember;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
/** /**
@@ -10,4 +12,12 @@ public class PsiFieldWrapper extends PsiMemberWrapper {
public PsiFieldWrapper(@NotNull PsiMember psiMember) { public PsiFieldWrapper(@NotNull PsiMember psiMember) {
super(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.PsiMethod;
import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiModifier;
import com.intellij.psi.PsiParameter; import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull; 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.JetConstructorAnnotation;
import org.jetbrains.jet.lang.resolve.java.kt.JetMethodAnnotation; import org.jetbrains.jet.lang.resolve.java.kt.JetMethodAnnotation;
@@ -55,8 +57,17 @@ public class PsiMethodWrapper extends PsiMemberWrapper {
return jetConstructor; return jetConstructor;
} }
public boolean isAbstract() {
return psiMember.hasModifierProperty(PsiModifier.ABSTRACT);
}
@NotNull @NotNull
public PsiMethod getPsiMethod() { public PsiMethod getPsiMethod() {
return (PsiMethod) psiMember; 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;
}
}
@@ -78,6 +78,7 @@ public class JetStandardLibrary {
private EnumMap<PrimitiveType, JetType> primitiveTypeToArrayJetType; private EnumMap<PrimitiveType, JetType> primitiveTypeToArrayJetType;
private EnumMap<PrimitiveType, JetType> primitiveTypeToNullableArrayJetType; private EnumMap<PrimitiveType, JetType> primitiveTypeToNullableArrayJetType;
private Map<JetType, JetType> primitiveJetTypeToJetArrayType; private Map<JetType, JetType> primitiveJetTypeToJetArrayType;
private Map<JetType, JetType> jetArrayTypeToPrimitiveJetType;
private JetStandardLibrary(@NotNull Project project) { private JetStandardLibrary(@NotNull Project project) {
// TODO : review // TODO : review
@@ -147,6 +148,7 @@ public class JetStandardLibrary {
primitiveTypeToArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class); primitiveTypeToArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
primitiveTypeToNullableArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class); primitiveTypeToNullableArrayJetType = new EnumMap<PrimitiveType, JetType>(PrimitiveType.class);
primitiveJetTypeToJetArrayType = new HashMap<JetType, JetType>(); primitiveJetTypeToJetArrayType = new HashMap<JetType, JetType>();
jetArrayTypeToPrimitiveJetType = new HashMap<JetType, JetType>();
for (PrimitiveType primitive : PrimitiveType.values()) { for (PrimitiveType primitive : PrimitiveType.values()) {
makePrimitive(primitive); makePrimitive(primitive);
@@ -167,6 +169,7 @@ public class JetStandardLibrary {
primitiveTypeToArrayJetType.put(primitiveType, arrayType); primitiveTypeToArrayJetType.put(primitiveType, arrayType);
primitiveTypeToNullableArrayJetType.put(primitiveType, TypeUtils.makeNullable(arrayType)); primitiveTypeToNullableArrayJetType.put(primitiveType, TypeUtils.makeNullable(arrayType));
primitiveJetTypeToJetArrayType.put(type, arrayType); primitiveJetTypeToJetArrayType.put(type, arrayType);
jetArrayTypeToPrimitiveJetType.put(arrayType, type);
} }
@NotNull @NotNull
@@ -335,6 +338,22 @@ public class JetStandardLibrary {
); );
} }
@NotNull
public JetType getArrayElementType(@NotNull JetType arrayType) {
// make non-null?
if (arrayType.getConstructor().getDeclarationDescriptor() == getArray()) {
if (arrayType.getArguments().size() != 1) {
throw new IllegalStateException();
}
return arrayType.getArguments().get(0).getType();
}
JetType primitiveType = jetArrayTypeToPrimitiveJetType.get(arrayType);
if (primitiveType == null) {
throw new IllegalStateException("not array: " + arrayType);
}
return primitiveType;
}
@NotNull @NotNull
public JetType getIterableType(@NotNull JetType argument) { public JetType getIterableType(@NotNull JetType argument) {
return getIterableType(Variance.INVARIANT, argument); return getIterableType(Variance.INVARIANT, argument);
@@ -0,0 +1,6 @@
package test
import java.util.Collection
val Collection<*>.anotherSize : Int
get() = size()
@@ -0,0 +1,3 @@
package test
fun any(): Any = 1
@@ -0,0 +1,3 @@
package test
fun anyq(): Any? = 1
@@ -0,0 +1,3 @@
package test
fun fun1(): (String) -> Int = throw Exception()
@@ -0,0 +1,5 @@
package test
import java.util.List
fun listOfAny(): List<Any> = throw Exception()
@@ -0,0 +1,5 @@
package test
import java.util.List
fun listOfAnyQ(): List<Any?> = throw Exception()
@@ -0,0 +1,5 @@
package test
import java.util.List
fun listOfStar(): List<*> = throw Exception()
@@ -0,0 +1,8 @@
import java.util.List
fun listOfStar(): List<*> = throw Exception()
// method: namespace::listOfStar
// jvm signature: ()Ljava/util/List;
// generic signature: ()Ljava/util/List<+Ljava/lang/Object;>;
// kotlin signature: ()Ljava/util/List<+?Ljava/lang/Object;>;
@@ -15,6 +15,8 @@ import org.jetbrains.jet.lang.descriptors.PropertyDescriptor;
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JavaNamespaceDescriptor;
import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExtensionReceiver;
import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.JetType;
@@ -216,7 +218,13 @@ class NamespaceComparator {
} else { } else {
sb.append("val "); sb.append("val ");
} }
if (!prop.getTypeParameters().isEmpty()) {
sb.append(" <");
new Serializer(sb).serializeCommaSeparated(prop.getTypeParameters());
sb.append("> ");
}
if (prop.getReceiverParameter().exists()) { if (prop.getReceiverParameter().exists()) {
// TODO: print only name for type parameter
new Serializer(sb).serialize(prop.getReceiverParameter().getType()); new Serializer(sb).serialize(prop.getReceiverParameter().getType());
sb.append("."); sb.append(".");
} }
@@ -272,6 +280,9 @@ class NamespaceComparator {
} }
sb.append(">"); sb.append(">");
} }
if (type.isNullable()) {
sb.append("?");
}
} }
public void serializeCommaSeparated(List<?> list) { public void serializeCommaSeparated(List<?> list) {
@@ -290,6 +301,10 @@ class NamespaceComparator {
} }
private Method getMethodToSerialize(Object o) { private Method getMethodToSerialize(Object o) {
if (o == null) {
throw new IllegalStateException("won't serialize null");
}
// TODO: cache // TODO: cache
for (Method method : this.getClass().getMethods()) { for (Method method : this.getClass().getMethods()) {
if (!method.getName().equals("serialize")) { if (!method.getName().equals("serialize")) {
@@ -328,11 +343,12 @@ class NamespaceComparator {
} }
public void serialize(NamespaceDescriptor ns) { public void serialize(NamespaceDescriptor ns) {
if (ns.getContainingDeclaration() == null) { if (isRootNs(ns)) {
// root ns
return; return;
} }
new NamespacePrefixSerializer(sb).serialize(ns.getContainingDeclaration()); if (ns.getContainingDeclaration() != null) {
new NamespacePrefixSerializer(sb).serialize(ns.getContainingDeclaration());
}
sb.append(ns.getName()); sb.append(ns.getName());
} }
@@ -356,6 +372,11 @@ class NamespaceComparator {
} }
private static boolean isRootNs(DeclarationDescriptor ns) {
// upyachka
return ns instanceof JavaNamespaceDescriptor && JavaDescriptorResolver.JAVA_ROOT.equals(ns.getName());
}
private static class NamespacePrefixSerializer extends Serializer { private static class NamespacePrefixSerializer extends Serializer {
public NamespacePrefixSerializer(StringBuilder sb) { public NamespacePrefixSerializer(StringBuilder sb) {
@@ -364,11 +385,10 @@ class NamespaceComparator {
@Override @Override
public void serialize(NamespaceDescriptor ns) { public void serialize(NamespaceDescriptor ns) {
if (ns.getContainingDeclaration() == null) { super.serialize(ns);
// root ns if (isRootNs(ns)) {
return; return;
} }
super.serialize(ns);
sb.append("."); sb.append(".");
} }
@@ -1,17 +1,21 @@
package jet.typeinfo; package jet.typeinfo;
import org.jetbrains.jet.rt.signature.JetSignatureVariance;
/** /**
* @author alex.tkachman * @author alex.tkachman
*/ */
public enum TypeInfoVariance { public enum TypeInfoVariance {
INVARIANT("") , INVARIANT("", JetSignatureVariance.INVARIANT) ,
IN("in"), IN("in", JetSignatureVariance.IN),
OUT("out"); OUT("out", JetSignatureVariance.OUT);
private final String label; private final String label;
private final JetSignatureVariance variance;
TypeInfoVariance(String label) { TypeInfoVariance(String label, JetSignatureVariance variance) {
this.label = label; this.label = label;
this.variance = variance;
} }
@Override @Override
@@ -6,6 +6,7 @@ import jet.typeinfo.TypeInfoProjection;
import jet.typeinfo.TypeInfoVariance; import jet.typeinfo.TypeInfoVariance;
import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter; import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter;
import org.jetbrains.jet.rt.signature.JetSignatureReader; import org.jetbrains.jet.rt.signature.JetSignatureReader;
import org.jetbrains.jet.rt.signature.JetSignatureVariance;
import org.jetbrains.jet.rt.signature.JetSignatureVisitor; import org.jetbrains.jet.rt.signature.JetSignatureVisitor;
import java.lang.reflect.TypeVariable; import java.lang.reflect.TypeVariable;
@@ -176,17 +177,17 @@ class TypeInfoParser {
this.projections = new ArrayList<TypeInfoProjection>(); this.projections = new ArrayList<TypeInfoProjection>();
} }
private static TypeInfoVariance parseVariance(char wildcard) { private static TypeInfoVariance parseVariance(JetSignatureVariance variance) {
switch (wildcard) { switch (variance) {
case '=': return TypeInfoVariance.INVARIANT; case INVARIANT: return TypeInfoVariance.INVARIANT;
case '+': return TypeInfoVariance.OUT; case OUT: return TypeInfoVariance.OUT;
case '-': return TypeInfoVariance.IN; case IN: return TypeInfoVariance.IN;
default: throw new IllegalStateException(); default: throw new IllegalStateException();
} }
} }
@Override @Override
public JetSignatureVisitor visitTypeArgument(final char wildcard) { public JetSignatureVisitor visitTypeArgument(final JetSignatureVariance wildcard) {
final TypeInfoVariance variance = parseVariance(wildcard); final TypeInfoVariance variance = parseVariance(wildcard);
return new SignatureParserJetSignatureAdapter(classLoader, signature) { return new SignatureParserJetSignatureAdapter(classLoader, signature) {
@Override @Override
@@ -76,7 +76,7 @@ public class JetSignatureAdapter implements JetSignatureVisitor {
} }
@Override @Override
public JetSignatureVisitor visitTypeArgument(char wildcard) { public JetSignatureVisitor visitTypeArgument(JetSignatureVariance wildcard) {
return this; return this;
} }
@@ -82,7 +82,7 @@ public class JetSignatureExceptionsAdapter implements JetSignatureVisitor {
} }
@Override @Override
public JetSignatureVisitor visitTypeArgument(char wildcard) { public JetSignatureVisitor visitTypeArgument(JetSignatureVariance wildcard) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@@ -194,12 +194,12 @@ public class JetSignatureReader {
case '-': case '-':
pos = parseType(signature, pos = parseType(signature,
pos + 1, pos + 1,
v.visitTypeArgument(c)); v.visitTypeArgument(JetSignatureVariance.parseVariance(c)));
break; break;
default: default:
pos = parseType(signature, pos = parseType(signature,
pos, pos,
v.visitTypeArgument('=')); v.visitTypeArgument(JetSignatureVariance.INVARIANT));
break; break;
} }
} }
@@ -0,0 +1,30 @@
package org.jetbrains.jet.rt.signature;
/**
* @author Stepan Koltsov
*/
public enum JetSignatureVariance {
INVARIANT('='),
IN('-'),
OUT('+'),
;
private final char c;
private JetSignatureVariance(char c) {
this.c = c;
}
public char getC() {
return c;
}
public static JetSignatureVariance parseVariance(char c) {
switch (c) {
case '=': return INVARIANT;
case '+': return OUT;
case '-': return IN;
default: throw new IllegalStateException();
}
}
}
@@ -134,7 +134,7 @@ public interface JetSignatureVisitor {
* @param wildcard '+', '-' or '='. * @param wildcard '+', '-' or '='.
* @return a non null visitor to visit the signature of the type argument. * @return a non null visitor to visit the signature of the type argument.
*/ */
JetSignatureVisitor visitTypeArgument(char wildcard); JetSignatureVisitor visitTypeArgument(JetSignatureVariance wildcard);
/** /**
* Ends the visit of a signature corresponding to a class or interface type. * Ends the visit of a signature corresponding to a class or interface type.
@@ -171,13 +171,13 @@ public class JetSignatureWriter implements JetSignatureVisitor {
} }
@Override @Override
public JetSignatureWriter visitTypeArgument(final char wildcard) { public JetSignatureWriter visitTypeArgument(JetSignatureVariance variance) {
if (argumentStack % 2 == 0) { if (argumentStack % 2 == 0) {
++argumentStack; ++argumentStack;
buf.append('<'); buf.append('<');
} }
if (wildcard != '=') { if (variance.getC() != '=') {
buf.append(wildcard); buf.append(variance.getC());
} }
return this; return this;
} }