From 5c6823a094d94612647029b51b31cc46884c3fa3 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 18 Jan 2012 11:56:14 +0400 Subject: [PATCH 1/7] ReadJavaBinaryClassTest: Any --- .../jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java | 1 - .../jet/lang/resolve/java/JetTypeJetSignatureReader.java | 4 ++++ compiler/testData/readKotlinBinaryClass/type/Any.kt | 3 +++ compiler/testData/readKotlinBinaryClass/type/AnyQ.kt | 3 +++ compiler/testData/readKotlinBinaryClass/type/ListOfAny.kt | 5 +++++ compiler/testData/readKotlinBinaryClass/type/ListOfAnyQ.kt | 5 +++++ 6 files changed, 20 insertions(+), 1 deletion(-) create mode 100644 compiler/testData/readKotlinBinaryClass/type/Any.kt create mode 100644 compiler/testData/readKotlinBinaryClass/type/AnyQ.kt create mode 100644 compiler/testData/readKotlinBinaryClass/type/ListOfAny.kt create mode 100644 compiler/testData/readKotlinBinaryClass/type/ListOfAnyQ.kt diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java index dc5bbf755a2..1e568b6a993 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaTypeTransformer.java @@ -187,7 +187,6 @@ public class JavaTypeTransformer { PrimitiveType primitiveType = jvmPrimitiveType.getPrimitiveType(); classDescriptorMap.put(jvmPrimitiveType.getWrapper().getFqName(), standardLibrary.getPrimitiveClassDescriptor(primitiveType)); } - //classDescriptorMap.put("java.lang.Object", standardLibrary.get classDescriptorMap.put("java.lang.String", standardLibrary.getString()); } return classDescriptorMap; diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java index 3e1d1918651..d45e3db6c8f 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java @@ -74,6 +74,10 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd String ourName = name.replace('/', '.'); this.classDescriptor = this.javaSemanticServices.getTypeTransformer().getPrimitiveWrappersClassDescriptorMap().get(ourName); + + if (this.classDescriptor == null && ourName.equals("java.lang.Object")) { + this.classDescriptor = JetStandardClasses.getAny(); + } if (this.classDescriptor == null) { this.classDescriptor = javaDescriptorResolver.resolveClass(ourName); diff --git a/compiler/testData/readKotlinBinaryClass/type/Any.kt b/compiler/testData/readKotlinBinaryClass/type/Any.kt new file mode 100644 index 00000000000..9f1e3eaa6ca --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/type/Any.kt @@ -0,0 +1,3 @@ +package test + +fun any(): Any = 1 diff --git a/compiler/testData/readKotlinBinaryClass/type/AnyQ.kt b/compiler/testData/readKotlinBinaryClass/type/AnyQ.kt new file mode 100644 index 00000000000..a59092e1372 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/type/AnyQ.kt @@ -0,0 +1,3 @@ +package test + +fun anyq(): Any? = 1 diff --git a/compiler/testData/readKotlinBinaryClass/type/ListOfAny.kt b/compiler/testData/readKotlinBinaryClass/type/ListOfAny.kt new file mode 100644 index 00000000000..74df70f27c7 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/type/ListOfAny.kt @@ -0,0 +1,5 @@ +package test + +import java.util.List + +fun listOfAny(): List = throw Exception() diff --git a/compiler/testData/readKotlinBinaryClass/type/ListOfAnyQ.kt b/compiler/testData/readKotlinBinaryClass/type/ListOfAnyQ.kt new file mode 100644 index 00000000000..618cb4023d6 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/type/ListOfAnyQ.kt @@ -0,0 +1,5 @@ +package test + +import java.util.List + +fun listOfAnyQ(): List = throw Exception() From c18a5009a4a63f51e5f19e42c5498493efa6f1e4 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 18 Jan 2012 11:56:27 +0400 Subject: [PATCH 2/7] test for function type --- .../type/Function1IntString.kt | 3 +++ .../jetbrains/jet/NamespaceComparator.java | 23 ++++++++++++++----- 2 files changed, 20 insertions(+), 6 deletions(-) create mode 100644 compiler/testData/readKotlinBinaryClass/type/Function1IntString.kt diff --git a/compiler/testData/readKotlinBinaryClass/type/Function1IntString.kt b/compiler/testData/readKotlinBinaryClass/type/Function1IntString.kt new file mode 100644 index 00000000000..ce8b87d4a66 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/type/Function1IntString.kt @@ -0,0 +1,3 @@ +package test + +fun fun1(): (String) -> Int = throw Exception() diff --git a/compiler/tests/org/jetbrains/jet/NamespaceComparator.java b/compiler/tests/org/jetbrains/jet/NamespaceComparator.java index 196f8a587e0..7a7dfb7daf5 100644 --- a/compiler/tests/org/jetbrains/jet/NamespaceComparator.java +++ b/compiler/tests/org/jetbrains/jet/NamespaceComparator.java @@ -15,6 +15,8 @@ import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor; import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor; 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.receivers.ExtensionReceiver; import org.jetbrains.jet.lang.types.JetType; @@ -290,6 +292,10 @@ class NamespaceComparator { } private Method getMethodToSerialize(Object o) { + if (o == null) { + throw new IllegalStateException("won't serialize null"); + } + // TODO: cache for (Method method : this.getClass().getMethods()) { if (!method.getName().equals("serialize")) { @@ -328,11 +334,12 @@ class NamespaceComparator { } public void serialize(NamespaceDescriptor ns) { - if (ns.getContainingDeclaration() == null) { - // root ns + if (isRootNs(ns)) { return; } - new NamespacePrefixSerializer(sb).serialize(ns.getContainingDeclaration()); + if (ns.getContainingDeclaration() != null) { + new NamespacePrefixSerializer(sb).serialize(ns.getContainingDeclaration()); + } sb.append(ns.getName()); } @@ -356,6 +363,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 { public NamespacePrefixSerializer(StringBuilder sb) { @@ -364,11 +376,10 @@ class NamespaceComparator { @Override public void serialize(NamespaceDescriptor ns) { - if (ns.getContainingDeclaration() == null) { - // root ns + super.serialize(ns); + if (isRootNs(ns)) { return; } - super.serialize(ns); sb.append("."); } From 4ded2e79ad3709a051a856be6ed636049d242d9b Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 18 Jan 2012 12:01:00 +0400 Subject: [PATCH 3/7] refactor java descriptor resolver --- .../resolve/java/JavaClassMembersScope.java | 63 +- .../resolve/java/JavaDescriptorResolver.java | 554 ++++++------------ .../java/JavaDescriptorResolverHelper.java | 173 ++++++ .../lang/resolve/java/MembersForProperty.java | 15 + .../jet/lang/resolve/java/NamedMembers.java | 41 ++ .../lang/resolve/java/PsiClassWrapper.java | 59 ++ .../lang/resolve/java/PsiFieldWrapper.java | 10 + .../lang/resolve/java/PsiMethodWrapper.java | 11 + 8 files changed, 526 insertions(+), 400 deletions(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/NamedMembers.java create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassWrapper.java diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java index 80c8b72a9c9..636682c0838 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaClassMembersScope.java @@ -2,15 +2,26 @@ package org.jetbrains.jet.lang.resolve.java; import com.google.common.collect.Maps; import com.google.common.collect.Sets; -import com.intellij.psi.*; +import com.intellij.psi.HierarchicalMethodSignature; +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import com.intellij.psi.PsiModifier; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; -import org.jetbrains.jet.lang.descriptors.*; -import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassDescriptor; +import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor; +import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.NamespaceDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.resolve.scopes.JetScope; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.TypeSubstitutor; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Map; +import java.util.Set; /** * @author abreslav @@ -20,8 +31,6 @@ public class JavaClassMembersScope implements JetScope { private final JavaSemanticServices semanticServices; private final boolean staticMembers; private final DeclarationDescriptor containingDeclaration; - private final Map> functionGroups = Maps.newHashMap(); - private final Map> variables = Maps.newHashMap(); private final Map classifiers = Maps.newHashMap(); private Collection allDescriptors; @@ -76,7 +85,7 @@ public class JavaClassMembersScope implements JetScope { if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) { continue; } - FunctionDescriptor functionDescriptor = semanticServices.getDescriptorResolver().resolveMethodToFunctionDescriptor(containingDeclaration, psiClass, substitutorForGenericSupertypes, method); + FunctionDescriptor functionDescriptor = semanticServices.getDescriptorResolver().resolveMethodToFunctionDescriptor(containingDeclaration, psiClass, substitutorForGenericSupertypes, new PsiMethodWrapper(method)); if (functionDescriptor != null) { allDescriptors.add(functionDescriptor); } @@ -117,14 +126,7 @@ public class JavaClassMembersScope implements JetScope { @NotNull @Override public Set getProperties(@NotNull String name) { - Set variableDescriptor = variables.get(name); - if (variableDescriptor == null) { - variableDescriptor = doGetVariable(name); - if (variableDescriptor != null) { - variables.put(name, variableDescriptor); - } - } - return variableDescriptor != null ? variableDescriptor : Collections.emptySet(); + return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDeclaration, psiClass, name, staticMembers); } @Override @@ -132,32 +134,15 @@ public class JavaClassMembersScope implements JetScope { return null; } - @Nullable - private Set doGetVariable(String name) { - PsiField field = psiClass.findFieldByName(name, true); - if (field == null) return null; - if (field.hasModifierProperty(PsiModifier.STATIC) != staticMembers) { - return null; - } - - //return semanticServices.getDescriptorResolver().resolveFieldToVariableDescriptor(containingDeclaration, field); - return semanticServices.getDescriptorResolver().resolveFieldGroupByName(containingDeclaration, psiClass, name, staticMembers); - } - @NotNull @Override public Set getFunctions(@NotNull String name) { - Set functionGroup = functionGroups.get(name); - if (functionGroup == null) { - functionGroup = semanticServices.getDescriptorResolver().resolveFunctionGroup( - containingDeclaration, - psiClass, - staticMembers ? null : (ClassDescriptor) containingDeclaration, - name, - staticMembers); - functionGroups.put(name, functionGroup); - } - return functionGroup; + return semanticServices.getDescriptorResolver().resolveFunctionGroup( + containingDeclaration, + psiClass, + staticMembers ? null : (ClassDescriptor) containingDeclaration, + name, + staticMembers); } @Override diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index 55480befad2..f5b85afcc20 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -4,15 +4,12 @@ import com.google.common.collect.Lists; import com.google.common.collect.Maps; import com.google.common.collect.Sets; import com.intellij.openapi.project.Project; -import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VirtualFile; -import com.intellij.psi.HierarchicalMethodSignature; import com.intellij.psi.JavaPsiFacade; import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClassType; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiEllipsisType; -import com.intellij.psi.PsiField; import com.intellij.psi.PsiJavaFile; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifier; @@ -63,6 +60,7 @@ import org.jetbrains.jet.rt.signature.JetSignatureVisitor; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; +import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -128,11 +126,12 @@ public class JavaDescriptorResolver { this.lowerBoundsForKotlin = lowerBoundsForKotlin; } } - + + private static abstract class ResolverScopeData { - @Nullable - private Set properties; protected boolean kotlin; + + private Map namedMembersMap; } private static class ResolverClassData extends ResolverScopeData { @@ -159,7 +158,6 @@ public class JavaDescriptorResolver { private final Map typeParameterDescriptorCache = Maps.newHashMap(); protected final Map methodDescriptorCache = Maps.newHashMap(); - protected final Map fieldDescriptorCache = Maps.newHashMap(); protected final JavaPsiFacade javaFacade; protected final GlobalSearchScope javaSearchScope; protected final JavaSemanticServices semanticServices; @@ -781,217 +779,174 @@ public class JavaDescriptorResolver { } } - /* - public VariableDescriptor resolveFieldToVariableDescriptor(DeclarationDescriptor containingDeclaration, PsiField field) { - VariableDescriptor variableDescriptor = fieldDescriptorCache.get(field); - if (variableDescriptor != null) { - return variableDescriptor; - } - JetType type = semanticServices.getTypeTransformer().transformToType(field.getType()); - boolean isFinal = field.hasModifierProperty(PsiModifier.FINAL); - PropertyDescriptor propertyDescriptor = new PropertyDescriptor( - containingDeclaration, - Collections.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 getMembersForProperties(@NotNull PsiClass clazz, boolean staticMembers, boolean kotlin) { - Map 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 resolveFieldGroupByName(@NotNull DeclarationDescriptor owner, PsiClass psiClass, String fieldName, boolean staticMembers) { - Set r = Sets.newHashSet(); - // TODO: slow - Set variables = resolveFieldGroup(owner, psiClass, staticMembers); - for (VariableDescriptor variable : variables) { - if (variable.getName().equals(fieldName)) { - r.add(variable); - } - } - return r; - } + ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass)); + NamedMembers namedMembers = scopeData.namedMembersMap.get(fieldName); + if (namedMembers == null) { + return Collections.emptySet(); + } + + resolveNamedGroupProperties(owner, staticMembers, namedMembers, fieldName); + + return namedMembers.propertyDescriptors; + } + @NotNull public Set resolveFieldGroup(@NotNull DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers) { + + ResolverScopeData scopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass)); + Set descriptors = Sets.newHashSet(); + Map membersForProperties = scopeData.namedMembersMap; + for (Map.Entry 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; + } + + PsiType propertyType = namedMembers.properties.type; + PsiType receiverType = namedMembers.properties.receiverType; + MembersForProperty members = namedMembers.properties; + + boolean isFinal; + if (members.setter == null && members.getter == null) { + isFinal = false; + } else if (members.getter != null) { + isFinal = members.getter.isFinal(); + } else if (members.setter != null) { + isFinal = members.setter.isFinal(); + } else { + isFinal = false; + } + + 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.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.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false); + } + if (members.setter != null) { + setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false); + } + + propertyDescriptor.initialize(getterDescriptor, setterDescriptor); + + final List classTypeParameters; + if (anyMember instanceof PsiMethodWrapper && !anyMember.isStatic()) { + classTypeParameters = ((ClassDescriptor) owner).getTypeConstructor().getParameters(); + } else { + classTypeParameters = new ArrayList(0); + } + TypeParameterListTypeVariableResolver typeVariableResolver = new TypeParameterListTypeVariableResolver(classTypeParameters); + + List typeParameters = new ArrayList(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); + namedMembers.propertyDescriptors = Collections.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 functionDescriptors = new HashSet(namedMembers.methods.size()); + for (PsiMethodWrapper method : namedMembers.methods) { + functionDescriptors.add(resolveMethodToFunctionDescriptor(owner, psiClass, typeSubstitutorForGenericSuperclasses, method)); + } + namedMembers.functionDescriptors = functionDescriptors; + } + + private ResolverScopeData getResolverScopeData(DeclarationDescriptor owner, PsiClassWrapper psiClass) { ResolverScopeData scopeData; + boolean staticMembers; if (owner instanceof JavaNamespaceDescriptor) { scopeData = namespaceDescriptorCacheByFqn.get(((JavaNamespaceDescriptor) owner).getQualifiedName()); + staticMembers = true; } else if (owner instanceof ClassDescriptor) { scopeData = classDescriptorCache.get(psiClass.getQualifiedName()); + staticMembers = false; } else { throw new IllegalStateException(); } @@ -999,151 +954,29 @@ public class JavaDescriptorResolver { throw new IllegalStateException(); } - if (scopeData.properties != null) { - return scopeData.properties; + if (scopeData.namedMembersMap == null) { + scopeData.namedMembersMap = JavaDescriptorResolverHelper.getNamedMembers(psiClass, staticMembers, scopeData.kotlin); } - Set descriptors = Sets.newHashSet(); - Map membersForProperties = getMembersForProperties(psiClass, staticMembers, scopeData.kotlin); - for (Map.Entry 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.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.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false); - } - if (members.setter != null) { - setterDescriptor = new PropertySetterDescriptor(propertyDescriptor, Collections.emptyList(), Modality.OPEN, Visibility.PUBLIC, true, false); - } - - propertyDescriptor.initialize(getterDescriptor, setterDescriptor); - - final List classTypeParameters; - if (anyMember instanceof PsiMethodWrapper && !anyMember.isStatic()) { - classTypeParameters = ((ClassDescriptor) owner).getTypeConstructor().getParameters(); - } else { - classTypeParameters = new ArrayList(0); - } - TypeParameterListTypeVariableResolver typeVariableResolver = new TypeParameterListTypeVariableResolver(classTypeParameters); - - List typeParameters = new ArrayList(0); - - if (members.setter != null) { - // call ugly code with side effects - typeParameters = resolveMethodTypeParameters(members.setter, propertyDescriptor.getSetter(), typeVariableResolver); - } - if (members.getter != null) { - // call ugly code with side effects - typeParameters = resolveMethodTypeParameters(members.getter, propertyDescriptor.getGetter(), typeVariableResolver); - } - - JetType receiverJetType; - if (receiverType == null) { - receiverJetType = null; - } else { - receiverJetType = semanticServices.getTypeTransformer().transformToType(receiverType); - } - - JetType type = semanticServices.getTypeTransformer().transformToType(propertyType); - - propertyDescriptor.setType( - type, - typeParameters, - DescriptorUtils.getExpectedThisObjectIfNeeded(owner), - receiverJetType - ); - if (getterDescriptor != null) { - getterDescriptor.initialize(type); - } - if (setterDescriptor != null) { - // TODO: initialize - } - - semanticServices.getTrace().record(BindingContext.VARIABLE, anyMember.psiMember, propertyDescriptor); - //fieldDescriptorCache.put(field, propertyDescriptor); - descriptors.add(propertyDescriptor); - } - scopeData.properties = descriptors; - return descriptors; + return scopeData; } @NotNull public Set resolveFunctionGroup(@NotNull DeclarationDescriptor owner, @NotNull PsiClass psiClass, @Nullable ClassDescriptor classDescriptor, @NotNull String methodName, boolean staticMembers) { - Set writableFunctionGroup = Sets.newLinkedHashSet(); - final Collection signatures = psiClass.getVisibleSignatures(); + + ResolverScopeData resolverScopeData = getResolverScopeData(owner, new PsiClassWrapper(psiClass)); + + Map namedMembersMap = resolverScopeData.namedMembersMap; + + NamedMembers namedMembers = namedMembersMap.get(methodName); + if (namedMembers == null || namedMembers.methods == null) { + return Collections.emptySet(); + } + TypeSubstitutor typeSubstitutor = createSubstitutorForGenericSupertypes(classDescriptor); - for (HierarchicalMethodSignature signature: signatures) { - if (!methodName.equals(signature.getName())) { - continue; - } - - FunctionDescriptor substitutedFunctionDescriptor = resolveHierarchicalSignatureToFunction(owner, psiClass, staticMembers, typeSubstitutor, signature); - if (substitutedFunctionDescriptor != null) { - writableFunctionGroup.add(substitutedFunctionDescriptor); - } - } - return writableFunctionGroup; - } - - @Nullable - private FunctionDescriptor resolveHierarchicalSignatureToFunction(DeclarationDescriptor owner, PsiClass psiClass, boolean staticMembers, TypeSubstitutor typeSubstitutor, HierarchicalMethodSignature signature) { - PsiMethod method = signature.getMethod(); - if (method.hasModifierProperty(PsiModifier.STATIC) != staticMembers) { - return null; - } - FunctionDescriptor functionDescriptor = resolveMethodToFunctionDescriptor(owner, psiClass, typeSubstitutor, method); -// if (functionDescriptor != null && !staticMembers) { -// for (HierarchicalMethodSignature superSignature : signature.getSuperSignatures()) { -// ((FunctionDescriptorImpl) functionDescriptor).addOverriddenFunction(resolveHierarchicalSignatureToFunction(owner, superSignature.getMethod().getContainingClass(), false, typeSubstitutor, superSignature)); -// } -// } - return functionDescriptor; + resolveNamedGroupFunctions(owner, psiClass, typeSubstitutor, staticMembers, namedMembers, methodName); + + return namedMembers.functionDescriptors; } public TypeSubstitutor createSubstitutorForGenericSupertypes(ClassDescriptor classDescriptor) { @@ -1178,16 +1011,15 @@ public class JavaDescriptorResolver { } @Nullable - public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethod psiMethod) { - PsiMethodWrapper method = new PsiMethodWrapper(psiMethod); + public FunctionDescriptor resolveMethodToFunctionDescriptor(DeclarationDescriptor owner, PsiClass psiClass, TypeSubstitutor typeSubstitutorForGenericSuperclasses, PsiMethodWrapper method) { - PsiType returnType = psiMethod.getReturnType(); + PsiType returnType = method.getReturnType(); if (returnType == null) { return null; } - FunctionDescriptor functionDescriptor = methodDescriptorCache.get(psiMethod); + FunctionDescriptor functionDescriptor = methodDescriptorCache.get(method.getPsiMethod()); if (functionDescriptor != null) { - if (psiMethod.getContainingClass() != psiClass) { + if (method.getPsiMethod().getContainingClass() != psiClass) { functionDescriptor = functionDescriptor.substitute(typeSubstitutorForGenericSuperclasses); } return functionDescriptor; @@ -1238,11 +1070,11 @@ public class JavaDescriptorResolver { DeclarationDescriptor classDescriptor; final List classTypeParameters; if (method.isStatic()) { - classDescriptor = resolveNamespace(psiMethod.getContainingClass()); + classDescriptor = resolveNamespace(method.getPsiMethod().getContainingClass()); classTypeParameters = Collections.emptyList(); } else { - ClassDescriptor classClassDescriptor = resolveClass(psiMethod.getContainingClass()); + ClassDescriptor classClassDescriptor = resolveClass(method.getPsiMethod().getContainingClass()); classDescriptor = classClassDescriptor; classTypeParameters = classClassDescriptor.getTypeConstructor().getParameters(); } @@ -1252,14 +1084,14 @@ public class JavaDescriptorResolver { NamedFunctionDescriptorImpl functionDescriptorImpl = new NamedFunctionDescriptorImpl( owner, Collections.emptyList(), // TODO - psiMethod.getName() + method.getName() ); - methodDescriptorCache.put(psiMethod, functionDescriptorImpl); + methodDescriptorCache.put(method.getPsiMethod(), functionDescriptorImpl); // TODO: add outer classes TypeParameterListTypeVariableResolver typeVariableResolverForParameters = new TypeParameterListTypeVariableResolver(classTypeParameters); - final List methodTypeParameters = resolveMethodTypeParameters(new PsiMethodWrapper(psiMethod), functionDescriptorImpl, typeVariableResolverForParameters); + final List methodTypeParameters = resolveMethodTypeParameters(method, functionDescriptorImpl, typeVariableResolverForParameters); class MethodTypeVariableResolver implements TypeVariableResolver { @@ -1288,12 +1120,12 @@ public class JavaDescriptorResolver { methodTypeParameters, valueParameterDescriptors.descriptors, makeReturnType(returnType, method, new MethodTypeVariableResolver()), - Modality.convertFromFlags(psiMethod.hasModifierProperty(PsiModifier.ABSTRACT), !psiMethod.hasModifierProperty(PsiModifier.FINAL)), - resolveVisibilityFromPsiModifiers(psiMethod) + Modality.convertFromFlags(method.getPsiMethod().hasModifierProperty(PsiModifier.ABSTRACT), !method.isFinal()), + resolveVisibilityFromPsiModifiers(method.getPsiMethod()) ); - semanticServices.getTrace().record(BindingContext.FUNCTION, psiMethod, functionDescriptorImpl); + semanticServices.getTrace().record(BindingContext.FUNCTION, method.getPsiMethod(), functionDescriptorImpl); FunctionDescriptor substitutedFunctionDescriptor = functionDescriptorImpl; - if (psiMethod.getContainingClass() != psiClass) { + if (method.getPsiMethod().getContainingClass() != psiClass) { substitutedFunctionDescriptor = functionDescriptorImpl.substitute(typeSubstitutorForGenericSuperclasses); } return substitutedFunctionDescriptor; @@ -1400,7 +1232,7 @@ public class JavaDescriptorResolver { ownerOwner = classDescriptor; substitutorForGenericSupertypes = semanticServices.getDescriptorResolver().createSubstitutorForGenericSupertypes(classDescriptor); } - FunctionDescriptor functionDescriptor = resolveMethodToFunctionDescriptor(ownerOwner, containingClass, substitutorForGenericSupertypes, psiMethod); + FunctionDescriptor functionDescriptor = resolveMethodToFunctionDescriptor(ownerOwner, containingClass, substitutorForGenericSupertypes, new PsiMethodWrapper(psiMethod)); return resolveTypeParameter(functionDescriptor, typeParameter); } throw new IllegalStateException("Unknown parent type: " + owner); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java new file mode 100644 index 00000000000..c56fb65b37c --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java @@ -0,0 +1,173 @@ +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.HierarchicalMethodSignature; +import com.intellij.psi.PsiType; +import org.jetbrains.annotations.NotNull; + +import java.util.HashMap; +import java.util.Map; + +/** + * @author Stepan Koltsov + */ +class JavaDescriptorResolverHelper { + + + private static class Builder { + private final PsiClassWrapper psiClass; + private final boolean staticMembers; + private final boolean kotlin; + + private Map namedMembersMap = new HashMap(); + + private Builder(PsiClassWrapper psiClass, boolean staticMembers, boolean kotlin) { + this.psiClass = psiClass; + this.staticMembers = staticMembers; + this.kotlin = kotlin; + } + + public void run() { + processFields(); + processMethods(); + } + + private NamedMembers getNamedMembers(String name) { + NamedMembers r = namedMembersMap.get(name); + if (r == null) { + r = new NamedMembers(); + r.name = name; + namedMembersMap.put(name, r); + } + return r; + } + + private void processFields() { + if (!kotlin) { + for (PsiFieldWrapper field : psiClass.getFields()) { + if (field.isStatic() != staticMembers) { + continue; + } + + if (field.isPrivate()) { + continue; + } + + NamedMembers namedMembers = getNamedMembers(field.getName()); + + MembersForProperty members = new MembersForProperty(); + members.field = field; + members.type = field.getType(); + + namedMembers.properties = members; + } + } + } + + private void processMethods() { + for (HierarchicalMethodSignature method0 : psiClass.getPsiClass().getVisibleSignatures()) { + + PsiMethodWrapper method = new PsiMethodWrapper(method0.getMethod()); + + if (method.isStatic() != staticMembers) { + continue; + } + + if (method.isPrivate()) { + continue; + } + + // TODO: "is" prefix + // TODO: remove getJavaClass + if (method.getName().startsWith(JvmAbi.GETTER_PREFIX)) { + + // TODO: some java properties too + if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) { + + if (method.getName().equals(JvmStdlibNames.JET_OBJECT_GET_TYPEINFO_METHOD)) { + continue; + } + + int i = 0; + + PsiType receiverType; + if (i < method.getParameters().size() && method.getParameter(i).getJetValueParameter().receiver()) { + receiverType = method.getParameter(i).getPsiParameter().getType(); + ++i; + } else { + receiverType = null; + } + + while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) { + // TODO: store is reified + ++i; + } + + if (i != method.getParameters().size()) { + // TODO: report error properly + throw new IllegalStateException(); + } + + String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.GETTER_PREFIX.length())); + NamedMembers members = getNamedMembers(propertyName); + members.getForProperty().getter = method; + + // TODO: check conflicts with setter + // TODO: what if returnType == null? + members.getForProperty().type = method.getReturnType(); + members.getForProperty().receiverType = receiverType; + } + } else if (method.getName().startsWith(JvmAbi.SETTER_PREFIX)) { + + if (method.getJetMethod().kind() == JvmStdlibNames.JET_METHOD_KIND_PROPERTY) { + if (method.getParameters().size() == 0) { + // TODO: report error properly + throw new IllegalStateException(); + } + + int i = 0; + + PsiType receiverType = null; + PsiParameterWrapper p1 = method.getParameter(0); + if (p1.getJetValueParameter().receiver()) { + receiverType = p1.getPsiParameter().getType(); + ++i; + } + + while (i < method.getParameters().size() && method.getParameter(i).getJetTypeParameter().isDefined()) { + ++i; + } + + if (i + 1 != method.getParameters().size()) { + throw new IllegalStateException(); + } + + PsiType propertyType = method.getParameter(i).getPsiParameter().getType(); + + String propertyName = StringUtil.decapitalize(method.getName().substring(JvmAbi.SETTER_PREFIX.length())); + NamedMembers members = getNamedMembers(propertyName); + members.getForProperty().setter = method; + + // TODO: check conflicts with getter + members.getForProperty().type = propertyType; + members.getForProperty().receiverType = receiverType; + } + } + + if (method.getJetMethod().kind() != JvmStdlibNames.JET_METHOD_KIND_PROPERTY) { + NamedMembers namedMembers = getNamedMembers(method.getName()); + namedMembers.addMethod(method); + } + } + } + } + + + static Map getNamedMembers(@NotNull PsiClassWrapper psiClass, boolean staticMembers, boolean kotlin) { + Builder builder = new Builder(psiClass, staticMembers, kotlin); + builder.run(); + return builder.namedMembersMap; + } + + +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java new file mode 100644 index 00000000000..db363b87c82 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java @@ -0,0 +1,15 @@ +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.psi.PsiType; + +/** +* @author Stepan Koltsov +*/ +class MembersForProperty { + PsiFieldWrapper field; + PsiMethodWrapper setter; + PsiMethodWrapper getter; + + PsiType type; + PsiType receiverType; +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/NamedMembers.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/NamedMembers.java new file mode 100644 index 00000000000..7da0943b814 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/NamedMembers.java @@ -0,0 +1,41 @@ +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiMethod; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; +import org.jetbrains.jet.lang.descriptors.PropertyDescriptor; +import org.jetbrains.jet.lang.descriptors.VariableDescriptor; + +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + +/** +* @author Stepan Koltsov +*/ +class NamedMembers { + String name; + List methods; + @Nullable + MembersForProperty properties; + @Nullable + private PsiClass nestedClasses; + + Set propertyDescriptors; + Set functionDescriptors; + + MembersForProperty getForProperty() { + if (properties == null) { + properties = new MembersForProperty(); + } + return properties; + } + + void addMethod(PsiMethodWrapper method) { + if (methods == null) { + methods = new ArrayList(); + } + methods.add(method); + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassWrapper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassWrapper.java new file mode 100644 index 00000000000..0eb52048fa3 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiClassWrapper.java @@ -0,0 +1,59 @@ +package org.jetbrains.jet.lang.resolve.java; + +import com.intellij.psi.PsiClass; +import com.intellij.psi.PsiField; +import com.intellij.psi.PsiMethod; +import org.jetbrains.annotations.NotNull; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Stepan Koltsov + */ +public class PsiClassWrapper { + + @NotNull + private final PsiClass psiClass; + + public PsiClassWrapper(@NotNull PsiClass psiClass) { + this.psiClass = psiClass; + } + + private List methods; + @NotNull + public List getMethods() { + if (methods == null) { + PsiMethod[] psiMethods = psiClass.getMethods(); + List methods = new ArrayList(psiMethods.length); + for (PsiMethod psiMethod : psiMethods) { + methods.add(new PsiMethodWrapper(psiMethod)); + } + this.methods = methods; + } + return methods; + } + + private List fields; + @NotNull + public List getFields() { + if (fields == null) { + PsiField[] psiFields = psiClass.getFields(); + List fields = new ArrayList(psiFields.length); + for (PsiField psiField : psiFields) { + fields.add(new PsiFieldWrapper(psiField)); + } + this.fields = fields; + } + return fields; + } + + public String getQualifiedName() { + return psiClass.getQualifiedName(); + } + + @NotNull + public PsiClass getPsiClass() { + return psiClass; + } +} diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiFieldWrapper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiFieldWrapper.java index 75ad3e13860..a896d42e1c7 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiFieldWrapper.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiFieldWrapper.java @@ -1,6 +1,8 @@ package org.jetbrains.jet.lang.resolve.java; +import com.intellij.psi.PsiField; import com.intellij.psi.PsiMember; +import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; /** @@ -10,4 +12,12 @@ public class PsiFieldWrapper extends PsiMemberWrapper { public PsiFieldWrapper(@NotNull PsiMember psiMember) { super(psiMember); } + + public PsiField getPsiField() { + return (PsiField) psiMember; + } + + public PsiType getType() { + return getPsiField().getType(); + } } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiMethodWrapper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiMethodWrapper.java index 0f67274a018..66b1df1f991 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiMethodWrapper.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/PsiMethodWrapper.java @@ -3,7 +3,9 @@ package org.jetbrains.jet.lang.resolve.java; import com.intellij.psi.PsiMethod; import com.intellij.psi.PsiModifier; import com.intellij.psi.PsiParameter; +import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.resolve.java.kt.JetConstructorAnnotation; import org.jetbrains.jet.lang.resolve.java.kt.JetMethodAnnotation; @@ -55,8 +57,17 @@ public class PsiMethodWrapper extends PsiMemberWrapper { return jetConstructor; } + public boolean isAbstract() { + return psiMember.hasModifierProperty(PsiModifier.ABSTRACT); + } + @NotNull public PsiMethod getPsiMethod() { return (PsiMethod) psiMember; } + + @Nullable + public PsiType getReturnType() { + return getPsiMethod().getReturnType(); + } } From 0229e725ab3eeb39997555fff88611e36a625bf8 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 18 Jan 2012 12:03:23 +0400 Subject: [PATCH 4/7] read class data: resolve Function* types --- .../java/JetTypeJetSignatureReader.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java index d45e3db6c8f..c25d29a9360 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java @@ -17,6 +17,8 @@ import org.jetbrains.jet.rt.signature.JetSignatureVisitor; import java.util.ArrayList; import java.util.Collections; import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; /** * @author Stepan Koltsov @@ -74,11 +76,27 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd String ourName = name.replace('/', '.'); this.classDescriptor = this.javaSemanticServices.getTypeTransformer().getPrimitiveWrappersClassDescriptorMap().get(ourName); - + if (this.classDescriptor == null && ourName.equals("java.lang.Object")) { this.classDescriptor = JetStandardClasses.getAny(); } + if (classDescriptor == null) { + // TODO: this is the worst code in Kotlin project + Matcher matcher = Pattern.compile("jet\\.Function(\\d+)").matcher(ourName); + if (matcher.matches()) { + classDescriptor = JetStandardClasses.getFunction(Integer.parseInt(matcher.group(1))); + } + } + + if (classDescriptor == null) { + Matcher matcher = Pattern.compile("jet\\.Tuple(\\d+)").matcher(ourName); + if (matcher.matches()) { + classDescriptor = JetStandardClasses.getTuple(Integer.parseInt(matcher.group(1))); + } + } + + if (this.classDescriptor == null) { this.classDescriptor = javaDescriptorResolver.resolveClass(ourName); } From 6ceb6816be018a280a3b6a7773712c0770a3bb2d Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 18 Jan 2012 12:03:42 +0400 Subject: [PATCH 5/7] ReadKotlinBinaryClassTest: List<*> --- .../jet/codegen/BothSignatureWriter.java | 17 +++++++++-- .../jetbrains/jet/codegen/JetTypeMapper.java | 2 +- .../java/JetTypeJetSignatureReader.java | 15 +++++----- .../prop/CollectionSize.kt | 6 ++++ .../readKotlinBinaryClass/type/ListOfStar.kt | 5 ++++ .../testData/writeSignature/ListOfStar.kt | 8 +++++ stdlib/src/jet/typeinfo/TypeInfoVariance.java | 12 +++++--- .../org/jetbrains/jet/rt/TypeInfoParser.java | 13 ++++---- .../jet/rt/signature/JetSignatureAdapter.java | 2 +- .../JetSignatureExceptionsAdapter.java | 2 +- .../jet/rt/signature/JetSignatureReader.java | 4 +-- .../rt/signature/JetSignatureVariance.java | 30 +++++++++++++++++++ .../jet/rt/signature/JetSignatureVisitor.java | 2 +- .../jet/rt/signature/JetSignatureWriter.java | 6 ++-- 14 files changed, 95 insertions(+), 29 deletions(-) create mode 100644 compiler/testData/readKotlinBinaryClass/prop/CollectionSize.kt create mode 100644 compiler/testData/readKotlinBinaryClass/type/ListOfStar.kt create mode 100644 compiler/testData/writeSignature/ListOfStar.kt create mode 100644 stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVariance.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java b/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java index 66273168bdc..807971b9501 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/BothSignatureWriter.java @@ -6,6 +6,7 @@ import org.jetbrains.jet.lang.resolve.java.JetSignatureUtils; import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.rt.signature.JetSignatureAdapter; import org.jetbrains.jet.rt.signature.JetSignatureReader; +import org.jetbrains.jet.rt.signature.JetSignatureVariance; import org.jetbrains.jet.rt.signature.JetSignatureWriter; import org.objectweb.asm.Type; import org.objectweb.asm.commons.Method; @@ -203,10 +204,20 @@ public class BothSignatureWriter { public void writeArrayEnd() { pop(); } + + private static JetSignatureVariance toJetSignatureVariance(Variance variance) { + switch (variance) { + case INVARIANT: return JetSignatureVariance.INVARIANT; + case IN_VARIANCE: return JetSignatureVariance.IN; + case OUT_VARIANCE: return JetSignatureVariance.OUT; + default: throw new IllegalStateException(); + } + } - public void writeTypeArgument(char c) { - push(signatureVisitor().visitTypeArgument(c)); - jetSignatureWriter.visitTypeArgument(c); + public void writeTypeArgument(Variance variance) { + JetSignatureVariance jsVariance = toJetSignatureVariance(variance); + push(signatureVisitor().visitTypeArgument(jsVariance.getC())); + jetSignatureWriter.visitTypeArgument(jsVariance); generic = true; } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java index ad5724d9ee8..5cd899e6ce6 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/JetTypeMapper.java @@ -298,7 +298,7 @@ public class JetTypeMapper { signatureVisitor.writeClassBegin(asmType.getInternalName(), jetType.isNullable()); for (TypeProjection proj : jetType.getArguments()) { // TODO: +- - signatureVisitor.writeTypeArgument('='); + signatureVisitor.writeTypeArgument(proj.getProjectionKind()); mapType(proj.getType(), kind, signatureVisitor, true); signatureVisitor.writeTypeArgumentEnd(); } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java index c25d29a9360..687cb47eaa0 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JetTypeJetSignatureReader.java @@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.types.TypeProjection; import org.jetbrains.jet.lang.types.TypeUtils; import org.jetbrains.jet.lang.types.Variance; import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter; +import org.jetbrains.jet.rt.signature.JetSignatureVariance; import org.jetbrains.jet.rt.signature.JetSignatureVisitor; import java.util.ArrayList; @@ -108,22 +109,22 @@ public abstract class JetTypeJetSignatureReader extends JetSignatureExceptionsAd this.typeArguments = new ArrayList(); } - private static Variance parseVariance(char wildcard) { - switch (wildcard) { - case '=': return Variance.INVARIANT; - case '+': return Variance.OUT_VARIANCE; - case '-': return Variance.IN_VARIANCE; + private static Variance parseVariance(JetSignatureVariance variance) { + switch (variance) { + case INVARIANT: return Variance.INVARIANT; + case OUT: return Variance.OUT_VARIANCE; + case IN: return Variance.IN_VARIANCE; default: throw new IllegalStateException(); } } @Override - public JetSignatureVisitor visitTypeArgument(final char wildcard) { + public JetSignatureVisitor visitTypeArgument(final JetSignatureVariance variance) { return new JetTypeJetSignatureReader(javaSemanticServices, jetStandardLibrary, typeVariableResolver) { @Override protected void done(@NotNull JetType jetType) { - typeArguments.add(new TypeProjection(parseVariance(wildcard), jetType)); + typeArguments.add(new TypeProjection(parseVariance(variance), jetType)); } }; } diff --git a/compiler/testData/readKotlinBinaryClass/prop/CollectionSize.kt b/compiler/testData/readKotlinBinaryClass/prop/CollectionSize.kt new file mode 100644 index 00000000000..8ab57de53f1 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/prop/CollectionSize.kt @@ -0,0 +1,6 @@ +package test + +import java.util.Collection + +val Collection<*>.anotherSize : Int + get() = size() diff --git a/compiler/testData/readKotlinBinaryClass/type/ListOfStar.kt b/compiler/testData/readKotlinBinaryClass/type/ListOfStar.kt new file mode 100644 index 00000000000..572fa54fff4 --- /dev/null +++ b/compiler/testData/readKotlinBinaryClass/type/ListOfStar.kt @@ -0,0 +1,5 @@ +package test + +import java.util.List + +fun listOfStar(): List<*> = throw Exception() diff --git a/compiler/testData/writeSignature/ListOfStar.kt b/compiler/testData/writeSignature/ListOfStar.kt new file mode 100644 index 00000000000..41d0aa3c844 --- /dev/null +++ b/compiler/testData/writeSignature/ListOfStar.kt @@ -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;>; diff --git a/stdlib/src/jet/typeinfo/TypeInfoVariance.java b/stdlib/src/jet/typeinfo/TypeInfoVariance.java index 647bb6693a9..ed35747dc35 100644 --- a/stdlib/src/jet/typeinfo/TypeInfoVariance.java +++ b/stdlib/src/jet/typeinfo/TypeInfoVariance.java @@ -1,17 +1,21 @@ package jet.typeinfo; +import org.jetbrains.jet.rt.signature.JetSignatureVariance; + /** * @author alex.tkachman */ public enum TypeInfoVariance { - INVARIANT("") , - IN("in"), - OUT("out"); + INVARIANT("", JetSignatureVariance.INVARIANT) , + IN("in", JetSignatureVariance.IN), + OUT("out", JetSignatureVariance.OUT); private final String label; + private final JetSignatureVariance variance; - TypeInfoVariance(String label) { + TypeInfoVariance(String label, JetSignatureVariance variance) { this.label = label; + this.variance = variance; } @Override diff --git a/stdlib/src/org/jetbrains/jet/rt/TypeInfoParser.java b/stdlib/src/org/jetbrains/jet/rt/TypeInfoParser.java index 72003cd7b1e..b2075b7f4bc 100644 --- a/stdlib/src/org/jetbrains/jet/rt/TypeInfoParser.java +++ b/stdlib/src/org/jetbrains/jet/rt/TypeInfoParser.java @@ -6,6 +6,7 @@ import jet.typeinfo.TypeInfoProjection; import jet.typeinfo.TypeInfoVariance; import org.jetbrains.jet.rt.signature.JetSignatureExceptionsAdapter; import org.jetbrains.jet.rt.signature.JetSignatureReader; +import org.jetbrains.jet.rt.signature.JetSignatureVariance; import org.jetbrains.jet.rt.signature.JetSignatureVisitor; import java.lang.reflect.TypeVariable; @@ -176,17 +177,17 @@ class TypeInfoParser { this.projections = new ArrayList(); } - private static TypeInfoVariance parseVariance(char wildcard) { - switch (wildcard) { - case '=': return TypeInfoVariance.INVARIANT; - case '+': return TypeInfoVariance.OUT; - case '-': return TypeInfoVariance.IN; + private static TypeInfoVariance parseVariance(JetSignatureVariance variance) { + switch (variance) { + case INVARIANT: return TypeInfoVariance.INVARIANT; + case OUT: return TypeInfoVariance.OUT; + case IN: return TypeInfoVariance.IN; default: throw new IllegalStateException(); } } @Override - public JetSignatureVisitor visitTypeArgument(final char wildcard) { + public JetSignatureVisitor visitTypeArgument(final JetSignatureVariance wildcard) { final TypeInfoVariance variance = parseVariance(wildcard); return new SignatureParserJetSignatureAdapter(classLoader, signature) { @Override diff --git a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureAdapter.java b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureAdapter.java index 5d9878b3110..1f80071f63f 100644 --- a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureAdapter.java +++ b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureAdapter.java @@ -76,7 +76,7 @@ public class JetSignatureAdapter implements JetSignatureVisitor { } @Override - public JetSignatureVisitor visitTypeArgument(char wildcard) { + public JetSignatureVisitor visitTypeArgument(JetSignatureVariance wildcard) { return this; } diff --git a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureExceptionsAdapter.java b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureExceptionsAdapter.java index 1d6be28930f..f65c34c6806 100644 --- a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureExceptionsAdapter.java +++ b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureExceptionsAdapter.java @@ -82,7 +82,7 @@ public class JetSignatureExceptionsAdapter implements JetSignatureVisitor { } @Override - public JetSignatureVisitor visitTypeArgument(char wildcard) { + public JetSignatureVisitor visitTypeArgument(JetSignatureVariance wildcard) { throw new IllegalStateException(); } diff --git a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureReader.java b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureReader.java index 900ec35d2e0..af581935e75 100644 --- a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureReader.java +++ b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureReader.java @@ -194,12 +194,12 @@ public class JetSignatureReader { case '-': pos = parseType(signature, pos + 1, - v.visitTypeArgument(c)); + v.visitTypeArgument(JetSignatureVariance.parseVariance(c))); break; default: pos = parseType(signature, pos, - v.visitTypeArgument('=')); + v.visitTypeArgument(JetSignatureVariance.INVARIANT)); break; } } diff --git a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVariance.java b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVariance.java new file mode 100644 index 00000000000..2adec59f1ef --- /dev/null +++ b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVariance.java @@ -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(); + } + } +} diff --git a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVisitor.java b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVisitor.java index 2a16f087c1c..a3548d8ce53 100644 --- a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVisitor.java +++ b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureVisitor.java @@ -134,7 +134,7 @@ public interface JetSignatureVisitor { * @param wildcard '+', '-' or '='. * @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. diff --git a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureWriter.java b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureWriter.java index 9db334ccefb..f7c6086fac9 100644 --- a/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureWriter.java +++ b/stdlib/src/org/jetbrains/jet/rt/signature/JetSignatureWriter.java @@ -171,13 +171,13 @@ public class JetSignatureWriter implements JetSignatureVisitor { } @Override - public JetSignatureWriter visitTypeArgument(final char wildcard) { + public JetSignatureWriter visitTypeArgument(JetSignatureVariance variance) { if (argumentStack % 2 == 0) { ++argumentStack; buf.append('<'); } - if (wildcard != '=') { - buf.append(wildcard); + if (variance.getC() != '=') { + buf.append(variance.getC()); } return this; } From 106846e86853f468a788a1f44855d3392b5f9954 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 18 Jan 2012 12:03:58 +0400 Subject: [PATCH 6/7] ReadKotlinBinaryClassTest: nullability --- .../jet/codegen/FunctionCodegen.java | 3 ++ .../resolve/java/JavaDescriptorResolver.java | 40 ++++++++++++------- .../java/JavaDescriptorResolverHelper.java | 21 +++++----- .../lang/resolve/java/MembersForProperty.java | 6 +-- .../jet/lang/resolve/java/TypeSource.java | 30 ++++++++++++++ .../jet/lang/types/JetStandardLibrary.java | 19 +++++++++ .../jetbrains/jet/NamespaceComparator.java | 3 ++ 7 files changed, 94 insertions(+), 28 deletions(-) create mode 100644 compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeSource.java diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java index 77eff97f2d8..9c7c3da8894 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/FunctionCodegen.java @@ -124,6 +124,9 @@ public class FunctionCodegen { av.visit(JvmStdlibNames.JET_VALUE_PARAMETER_NULLABLE_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(); } for (final TypeParameterDescriptor typeParameterDescriptor : typeParameters) { diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java index f5b85afcc20..82527060e2a 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolver.java @@ -735,15 +735,6 @@ public class JavaDescriptorResolver { PsiType psiType = parameter.getPsiParameter().getType(); - JetType varargElementType; - if (psiType instanceof PsiEllipsisType) { - PsiEllipsisType psiEllipsisType = (PsiEllipsisType) psiType; - varargElementType = semanticServices.getTypeTransformer().transformToType(psiEllipsisType.getComponentType()); - } - else { - varargElementType = null; - } - boolean nullable = parameter.getJetValueParameter().nullable(); // TODO: must be very slow, make it lazy? @@ -763,6 +754,14 @@ public class JavaDescriptorResolver { } else { outType = semanticServices.getTypeTransformer().transformToType(psiType); } + + JetType varargElementType; + if (psiType instanceof PsiEllipsisType) { + varargElementType = semanticServices.getJetSemanticServices().getStandardLibrary().getArrayElementType(outType); + } else { + varargElementType = null; + } + if (receiver) { return JvmMethodParameterMeaning.receiver(outType); } else { @@ -823,8 +822,8 @@ public class JavaDescriptorResolver { return; } - PsiType propertyType = namedMembers.properties.type; - PsiType receiverType = namedMembers.properties.receiverType; + TypeSource propertyType = namedMembers.properties.type; + TypeSource receiver = namedMembers.properties.receiverType; MembersForProperty members = namedMembers.properties; boolean isFinal; @@ -894,15 +893,28 @@ public class JavaDescriptorResolver { // call ugly code with side effects typeParameters = resolveMethodTypeParameters(members.getter, propertyDescriptor.getGetter(), typeVariableResolver); } + + List typeParametersForReceiver = new ArrayList(); + typeParametersForReceiver.addAll(classTypeParameters); + typeParametersForReceiver.addAll(typeParameters); + TypeParameterListTypeVariableResolver typeVariableResolverForPropertyInternals = new TypeParameterListTypeVariableResolver(typeParametersForReceiver); + JetType receiverJetType; - if (receiverType == null) { + if (receiver == null) { receiverJetType = null; + } else if (receiver.getTypeString().length() > 0) { + receiverJetType = semanticServices.getTypeTransformer().transformToType(receiver.getTypeString(), typeVariableResolverForPropertyInternals); } else { - receiverJetType = semanticServices.getTypeTransformer().transformToType(receiverType); + receiverJetType = semanticServices.getTypeTransformer().transformToType(receiver.getPsiType()); } - JetType type = semanticServices.getTypeTransformer().transformToType(propertyType); + JetType type; + if (propertyType.getTypeString().length() > 0) { + type = semanticServices.getTypeTransformer().transformToType(propertyType.getTypeString(), typeVariableResolverForPropertyInternals); + } else { + type = semanticServices.getTypeTransformer().transformToType(propertyType.getPsiType()); + } propertyDescriptor.setType( type, diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java index c56fb65b37c..ad6a89d8e78 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/JavaDescriptorResolverHelper.java @@ -2,7 +2,6 @@ package org.jetbrains.jet.lang.resolve.java; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.HierarchicalMethodSignature; -import com.intellij.psi.PsiType; import org.jetbrains.annotations.NotNull; import java.util.HashMap; @@ -12,8 +11,8 @@ import java.util.Map; * @author Stepan Koltsov */ class JavaDescriptorResolverHelper { - - + + private static class Builder { private final PsiClassWrapper psiClass; private final boolean staticMembers; @@ -57,7 +56,7 @@ class JavaDescriptorResolverHelper { MembersForProperty members = new MembersForProperty(); members.field = field; - members.type = field.getType(); + members.type = new TypeSource("", field.getType()); namedMembers.properties = members; } @@ -90,9 +89,10 @@ class JavaDescriptorResolverHelper { int i = 0; - PsiType receiverType; + TypeSource receiverType; if (i < method.getParameters().size() && method.getParameter(i).getJetValueParameter().receiver()) { - receiverType = method.getParameter(i).getPsiParameter().getType(); + PsiParameterWrapper receiverParameter = method.getParameter(i); + receiverType = new TypeSource(receiverParameter.getJetValueParameter().type(), receiverParameter.getPsiParameter().getType()); ++i; } else { receiverType = null; @@ -114,7 +114,7 @@ class JavaDescriptorResolverHelper { // TODO: check conflicts with setter // TODO: what if returnType == null? - members.getForProperty().type = method.getReturnType(); + members.getForProperty().type = new TypeSource(method.getJetMethod().propertyType(), method.getReturnType()); members.getForProperty().receiverType = receiverType; } } else if (method.getName().startsWith(JvmAbi.SETTER_PREFIX)) { @@ -127,10 +127,10 @@ class JavaDescriptorResolverHelper { int i = 0; - PsiType receiverType = null; + TypeSource receiverType = null; PsiParameterWrapper p1 = method.getParameter(0); if (p1.getJetValueParameter().receiver()) { - receiverType = p1.getPsiParameter().getType(); + receiverType = new TypeSource(p1.getJetValueParameter().type(), p1.getPsiParameter().getType()); ++i; } @@ -142,7 +142,8 @@ class JavaDescriptorResolverHelper { throw new IllegalStateException(); } - PsiType propertyType = method.getParameter(i).getPsiParameter().getType(); + 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); diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java index db363b87c82..99728ccecc1 100644 --- a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/MembersForProperty.java @@ -1,7 +1,5 @@ package org.jetbrains.jet.lang.resolve.java; -import com.intellij.psi.PsiType; - /** * @author Stepan Koltsov */ @@ -10,6 +8,6 @@ class MembersForProperty { PsiMethodWrapper setter; PsiMethodWrapper getter; - PsiType type; - PsiType receiverType; + TypeSource type; + TypeSource receiverType; } diff --git a/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeSource.java b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeSource.java new file mode 100644 index 00000000000..b7dc71e3891 --- /dev/null +++ b/compiler/frontend.java/src/org/jetbrains/jet/lang/resolve/java/TypeSource.java @@ -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; + } +} diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java index c79b0c9fc3f..54f781bc7fb 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java @@ -78,6 +78,7 @@ public class JetStandardLibrary { private EnumMap primitiveTypeToArrayJetType; private EnumMap primitiveTypeToNullableArrayJetType; private Map primitiveJetTypeToJetArrayType; + private Map jetArrayTypeToPrimitiveJetType; private JetStandardLibrary(@NotNull Project project) { // TODO : review @@ -147,6 +148,7 @@ public class JetStandardLibrary { primitiveTypeToArrayJetType = new EnumMap(PrimitiveType.class); primitiveTypeToNullableArrayJetType = new EnumMap(PrimitiveType.class); primitiveJetTypeToJetArrayType = new HashMap(); + jetArrayTypeToPrimitiveJetType = new HashMap(); for (PrimitiveType primitive : PrimitiveType.values()) { makePrimitive(primitive); @@ -167,6 +169,7 @@ public class JetStandardLibrary { primitiveTypeToArrayJetType.put(primitiveType, arrayType); primitiveTypeToNullableArrayJetType.put(primitiveType, TypeUtils.makeNullable(arrayType)); primitiveJetTypeToJetArrayType.put(type, arrayType); + jetArrayTypeToPrimitiveJetType.put(arrayType, type); } @NotNull @@ -334,6 +337,22 @@ public class JetStandardLibrary { getArray().getMemberScope(types) ); } + + @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 public JetType getIterableType(@NotNull JetType argument) { diff --git a/compiler/tests/org/jetbrains/jet/NamespaceComparator.java b/compiler/tests/org/jetbrains/jet/NamespaceComparator.java index 7a7dfb7daf5..0a2d6e7bb62 100644 --- a/compiler/tests/org/jetbrains/jet/NamespaceComparator.java +++ b/compiler/tests/org/jetbrains/jet/NamespaceComparator.java @@ -274,6 +274,9 @@ class NamespaceComparator { } sb.append(">"); } + if (type.isNullable()) { + sb.append("?"); + } } public void serializeCommaSeparated(List list) { From e7daae880407998c2c151afb98085927d2da53f6 Mon Sep 17 00:00:00 2001 From: Stepan Koltsov Date: Wed, 18 Jan 2012 12:04:16 +0400 Subject: [PATCH 7/7] fix ext prop type param output of ReadKotlinClassDataTest --- compiler/tests/org/jetbrains/jet/NamespaceComparator.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/tests/org/jetbrains/jet/NamespaceComparator.java b/compiler/tests/org/jetbrains/jet/NamespaceComparator.java index 0a2d6e7bb62..cb8a526d41a 100644 --- a/compiler/tests/org/jetbrains/jet/NamespaceComparator.java +++ b/compiler/tests/org/jetbrains/jet/NamespaceComparator.java @@ -218,7 +218,13 @@ class NamespaceComparator { } else { sb.append("val "); } + if (!prop.getTypeParameters().isEmpty()) { + sb.append(" <"); + new Serializer(sb).serializeCommaSeparated(prop.getTypeParameters()); + sb.append("> "); + } if (prop.getReceiverParameter().exists()) { + // TODO: print only name for type parameter new Serializer(sb).serialize(prop.getReceiverParameter().getType()); sb.append("."); }