Introduce JavaType and subclasses

Use JavaType instead of PsiType whenever possible.

In this commit the logic of checking whether a loaded parameter is a vararg
changed: instead of checking if the corresponding PsiType is PsiEllipsisType we
now check if the containing method has the ACC_VARARG modifier
This commit is contained in:
Alexander Udalov
2013-07-30 22:33:48 +04:00
parent 998e598846
commit f669771b7e
15 changed files with 246 additions and 53 deletions
@@ -17,8 +17,6 @@
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.google.common.collect.Lists;
import com.intellij.psi.PsiArrayType;
import com.intellij.psi.PsiType;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -34,8 +32,10 @@ import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JavaVisibilities;
import org.jetbrains.jet.lang.resolve.java.TypeVariableResolver;
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeMethodSignatureData;
import org.jetbrains.jet.lang.resolve.java.structure.JavaArrayType;
import org.jetbrains.jet.lang.resolve.java.structure.JavaClass;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
import org.jetbrains.jet.lang.types.JetType;
import javax.inject.Inject;
@@ -147,14 +147,14 @@ public final class JavaConstructorResolver {
JavaMethod method = iterator.next();
assert method.getValueParameters().isEmpty() : "Annotation method can't have parameters: " + method;
PsiType returnType = method.getPsi().getReturnType();
JavaType returnType = method.getReturnType();
assert returnType != null : "Annotation method has no return type: " + method;
// We take the following heuristic convention:
// if the last method of the @interface is an array, we convert it into a vararg
JetType varargElementType = null;
if (!iterator.hasNext() && returnType instanceof PsiArrayType) {
PsiType componentType = ((PsiArrayType) returnType).getComponentType();
if (!iterator.hasNext() && returnType instanceof JavaArrayType) {
JavaType componentType = ((JavaArrayType) returnType).getComponentType();
varargElementType = typeTransformer.transformToType(componentType, typeVariableResolver);
}
@@ -201,7 +201,7 @@ public final class JavaConstructorResolver {
List<TypeParameterDescriptor> typeParameters = classDescriptor.getTypeConstructor().getParameters();
JavaDescriptorResolver.ValueParameterDescriptors valueParameterDescriptors = valueParameterResolver.resolveParameterDescriptors(
constructorDescriptor, constructor.getValueParameters(),
constructorDescriptor, constructor,
new TypeVariableResolver(typeParameters, classDescriptor, "constructor of class " + javaClass.getFqName())
);
@@ -20,7 +20,6 @@ import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import com.intellij.psi.util.PsiFormatUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
@@ -36,6 +35,7 @@ import org.jetbrains.jet.lang.resolve.java.kotlinSignature.SignaturesPropagation
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.SignaturesUtil;
import org.jetbrains.jet.lang.resolve.java.provider.NamedMembers;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
import org.jetbrains.jet.lang.types.*;
@@ -103,13 +103,14 @@ public final class JavaFunctionResolver {
return null;
}
PsiMethod psiMethod = method.getPsi();
PsiType returnPsiType = psiMethod.getReturnType();
if (returnPsiType == null) {
JavaType returnJavaType = method.getReturnType();
if (returnJavaType == null) {
// This means that the method is a constructor
return null;
}
PsiMethod psiMethod = method.getPsi();
SimpleFunctionDescriptor alreadyResolved = trace.get(BindingContext.FUNCTION, psiMethod);
if (alreadyResolved != null) {
return alreadyResolved;
@@ -128,8 +129,8 @@ public final class JavaFunctionResolver {
methodTypeParameters, functionDescriptorImpl, "method " + method.getName() + " in class " + method.getContainingClass());
JavaDescriptorResolver.ValueParameterDescriptors valueParameterDescriptors = parameterResolver
.resolveParameterDescriptors(functionDescriptorImpl, method.getValueParameters(), methodTypeVariableResolver);
JetType returnType = makeReturnType(returnPsiType, method, methodTypeVariableResolver);
.resolveParameterDescriptors(functionDescriptorImpl, method, methodTypeVariableResolver);
JetType returnType = makeReturnType(returnJavaType, method, methodTypeVariableResolver);
List<String> signatureErrors = Lists.newArrayList();
@@ -362,7 +363,7 @@ public final class JavaFunctionResolver {
@NotNull
private JetType makeReturnType(
@NotNull PsiType returnType,
@NotNull JavaType returnType,
@NotNull JavaMethod method,
@NotNull TypeVariableResolver typeVariableResolver
) {
@@ -27,7 +27,10 @@ import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorForObjectImpl;
import org.jetbrains.jet.lang.descriptors.impl.PropertyDescriptorImpl;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.DescriptorResolverUtils;
import org.jetbrains.jet.lang.resolve.java.JavaBindingContext;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.java.TypeVariableResolver;
import org.jetbrains.jet.lang.resolve.java.kotlinSignature.AlternativeFieldSignatureData;
import org.jetbrains.jet.lang.resolve.java.provider.NamedMembers;
import org.jetbrains.jet.lang.resolve.java.structure.JavaField;
@@ -226,7 +229,7 @@ public final class JavaPropertyResolver {
@NotNull
private JetType getPropertyType(@NotNull JavaField field, @NotNull TypeVariableResolver typeVariableResolver) {
JetType propertyType = typeTransformer.transformToType(field.getPsi().getType(), typeVariableResolver);
JetType propertyType = typeTransformer.transformToType(field.getType(), typeVariableResolver);
boolean hasNotNullAnnotation = JavaAnnotationResolver.findAnnotationWithExternal(
field.getPsi(),
@@ -17,7 +17,6 @@
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.google.common.collect.Lists;
import com.intellij.psi.PsiClassType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
@@ -106,8 +105,7 @@ public final class JavaSignatureResolver {
}
else {
for (JavaClassType upperBound : upperBounds) {
PsiClassType psiClassType = upperBound.getPsi();
JetType transformedType = typeTransformer.transformToType(psiClassType, TypeUsage.UPPER_BOUND, typeVariableByPsiResolver);
JetType transformedType = typeTransformer.transformToType(upperBound, TypeUsage.UPPER_BOUND, typeVariableByPsiResolver);
typeParameterDescriptor.addUpperBound(transformedType);
}
}
@@ -125,7 +125,7 @@ public final class JavaSupertypeResolver {
}
}
JetType transformed = typeTransformer.transformToType(type.getPsi(), TypeUsage.SUPERTYPE, typeVariableResolver);
JetType transformed = typeTransformer.transformToType(type, TypeUsage.SUPERTYPE, typeVariableResolver);
if (!ErrorUtils.isErrorType(transformed)) {
result.add(TypeUtils.makeNotNullable(transformed));
}
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.java.TypeUsage;
import org.jetbrains.jet.lang.resolve.java.TypeVariableResolver;
import org.jetbrains.jet.lang.resolve.java.mapping.JavaToKotlinClassMap;
import org.jetbrains.jet.lang.resolve.java.structure.JavaType;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.types.*;
import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
@@ -75,25 +76,25 @@ public class JavaTypeTransformer {
PsiType bound = wildcardType.getBound();
assert bound != null;
return new TypeProjection(variance, transformToType(bound, UPPER_BOUND, typeVariableByPsiResolver));
return new TypeProjection(variance, transformToType(JavaType.create(bound), UPPER_BOUND, typeVariableByPsiResolver));
}
@Override
public TypeProjection visitType(PsiType type) {
return new TypeProjection(transformToType(type, howThisTypeIsUsed, typeVariableByPsiResolver));
return new TypeProjection(transformToType(JavaType.create(type), howThisTypeIsUsed, typeVariableByPsiResolver));
}
});
}
@NotNull
public JetType transformToType(@NotNull PsiType javaType, @NotNull TypeVariableResolver typeVariableResolver) {
public JetType transformToType(@NotNull JavaType javaType, @NotNull TypeVariableResolver typeVariableResolver) {
return transformToType(javaType, TypeUsage.MEMBER_SIGNATURE_INVARIANT, typeVariableResolver);
}
@NotNull
public JetType transformToType(@NotNull PsiType javaType, @NotNull final TypeUsage howThisTypeIsUsed,
public JetType transformToType(@NotNull JavaType javaType, @NotNull final TypeUsage howThisTypeIsUsed,
@NotNull final TypeVariableResolver typeVariableResolver) {
return javaType.accept(new PsiTypeVisitor<JetType>() {
return javaType.getPsi().accept(new PsiTypeVisitor<JetType>() {
@Override
public JetType visitClassType(PsiClassType classType) {
PsiClass psiClass = classType.resolve();
@@ -110,7 +111,7 @@ public class JavaTypeTransformer {
if (psiMethod.isConstructor()) {
Set<JetType> supertypesJet = Sets.newHashSet();
for (PsiClassType supertype : typeParameter.getExtendsListTypes()) {
supertypesJet.add(transformToType(supertype, UPPER_BOUND, typeVariableResolver));
supertypesJet.add(transformToType(JavaType.create(supertype), UPPER_BOUND, typeVariableResolver));
}
return TypeUtils.intersect(JetTypeChecker.INSTANCE, supertypesJet);
}
@@ -227,7 +228,7 @@ public class JavaTypeTransformer {
Variance projectionKind = arrayElementTypeProjectionKind(vararg);
TypeUsage howArgumentTypeIsUsed = vararg ? MEMBER_SIGNATURE_CONTRAVARIANT : TYPE_ARGUMENT;
JetType type = transformToType(componentType, howArgumentTypeIsUsed, typeVariableResolver);
JetType type = transformToType(JavaType.create(componentType), howArgumentTypeIsUsed, typeVariableResolver);
return TypeUtils.makeNullable(KotlinBuiltIns.getInstance().getArrayType(projectionKind, type));
}
@@ -17,15 +17,16 @@
package org.jetbrains.jet.lang.resolve.java.resolver;
import com.intellij.psi.PsiAnnotation;
import com.intellij.psi.PsiEllipsisType;
import com.intellij.psi.PsiParameter;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl;
import org.jetbrains.jet.lang.resolve.java.*;
import org.jetbrains.jet.lang.resolve.java.JavaDescriptorResolver;
import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames;
import org.jetbrains.jet.lang.resolve.java.TypeUsage;
import org.jetbrains.jet.lang.resolve.java.TypeVariableResolver;
import org.jetbrains.jet.lang.resolve.java.structure.JavaMethod;
import org.jetbrains.jet.lang.resolve.java.structure.JavaValueParameter;
import org.jetbrains.jet.lang.resolve.name.Name;
import org.jetbrains.jet.lang.types.JetType;
@@ -33,10 +34,7 @@ import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
import javax.inject.Inject;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.*;
public final class JavaValueParameterResolver {
private JavaTypeTransformer typeTransformer;
@@ -49,21 +47,19 @@ public final class JavaValueParameterResolver {
@NotNull DeclarationDescriptor containingDeclaration,
int i,
@NotNull JavaValueParameter parameter,
@NotNull TypeVariableResolver typeVariableResolver
@NotNull TypeVariableResolver typeVariableResolver,
boolean isVararg
) {
PsiParameter psiParameter = parameter.getPsi();
PsiType psiType = psiParameter.getType();
// TODO: must be very slow, make it lazy?
Name name = getParameterName(i, parameter);
TypeUsage typeUsage = JavaTypeTransformer
.adjustTypeUsageWithMutabilityAnnotations(psiParameter, TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT);
JetType outType = typeTransformer.transformToType(psiType, typeUsage, typeVariableResolver);
.adjustTypeUsageWithMutabilityAnnotations(parameter.getPsi(), TypeUsage.MEMBER_SIGNATURE_CONTRAVARIANT);
JetType outType = typeTransformer.transformToType(parameter.getType(), typeUsage, typeVariableResolver);
JetType varargElementType;
if (psiType instanceof PsiEllipsisType) {
if (isVararg) {
// TODO: test this code
varargElementType = KotlinBuiltIns.getInstance().getArrayElementType(TypeUtils.makeNotNullable(outType));
outType = TypeUtils.makeNotNullable(outType);
}
@@ -73,7 +69,7 @@ public final class JavaValueParameterResolver {
JetType transformedType;
PsiAnnotation notNullAnnotation = JavaAnnotationResolver
.findAnnotationWithExternal(psiParameter, JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION);
.findAnnotationWithExternal(parameter.getPsi(), JvmAnnotationNames.JETBRAINS_NOT_NULL_ANNOTATION);
if (notNullAnnotation != null) {
transformedType = TypeUtils.makeNullableAsSpecified(outType, false);
}
@@ -105,14 +101,18 @@ public final class JavaValueParameterResolver {
@NotNull
public JavaDescriptorResolver.ValueParameterDescriptors resolveParameterDescriptors(
@NotNull DeclarationDescriptor container,
@NotNull Collection<JavaValueParameter> parameters,
@NotNull JavaMethod method,
@NotNull TypeVariableResolver typeVariableResolver
) {
Collection<JavaValueParameter> parameters = method.getValueParameters();
List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(parameters.size());
int index = 0;
for (JavaValueParameter parameter : parameters) {
ValueParameterDescriptor parameterDescriptor = resolveParameterDescriptor(container, index, parameter, typeVariableResolver);
result.add(parameterDescriptor);
for (Iterator<JavaValueParameter> iterator = parameters.iterator(); iterator.hasNext(); ) {
JavaValueParameter parameter = iterator.next();
boolean isVararg = method.isVararg() && !iterator.hasNext();
ValueParameterDescriptor descriptor = resolveParameterDescriptor(container, index, parameter, typeVariableResolver, isVararg);
result.add(descriptor);
index++;
}
return new JavaDescriptorResolver.ValueParameterDescriptors(null, result);
@@ -0,0 +1,37 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import com.intellij.psi.PsiArrayType;
import org.jetbrains.annotations.NotNull;
public class JavaArrayType extends JavaType {
public JavaArrayType(@NotNull PsiArrayType psiArrayType) {
super(psiArrayType);
}
@NotNull
@Override
public PsiArrayType getPsi() {
return (PsiArrayType) super.getPsi();
}
@NotNull
public JavaType getComponentType() {
return JavaType.create(getPsi().getComponentType());
}
}
@@ -27,16 +27,15 @@ import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class JavaClassType {
private final PsiClassType psiClassType;
public class JavaClassType extends JavaType {
public JavaClassType(@NotNull PsiClassType psiClassType) {
this.psiClassType = psiClassType;
super(psiClassType);
}
@NotNull
@Override
public PsiClassType getPsi() {
return psiClassType;
return (PsiClassType) super.getPsi();
}
@Nullable
@@ -43,4 +43,9 @@ public class JavaField extends JavaMemberImpl {
public boolean isEnumEntry() {
return getPsi() instanceof PsiEnumConstant;
}
@NotNull
public JavaType getType() {
return JavaType.create(getPsi().getType());
}
}
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve.java.structure;
import com.intellij.psi.PsiAnnotationMethod;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiMethod;
import com.intellij.psi.PsiType;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -72,4 +73,14 @@ public class JavaMethod extends JavaMemberImpl implements JavaTypeParameterListO
}
return null;
}
@Nullable
public JavaType getReturnType() {
PsiType psiType = getPsi().getReturnType();
return psiType == null ? null : JavaType.create(psiType);
}
public boolean isVararg() {
return getPsi().isVarArgs();
}
}
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import com.intellij.psi.PsiPrimitiveType;
import org.jetbrains.annotations.NotNull;
public class JavaPrimitiveType extends JavaType {
public JavaPrimitiveType(@NotNull PsiPrimitiveType psiPrimitiveType) {
super(psiPrimitiveType);
}
@NotNull
@Override
public PsiPrimitiveType getPsi() {
return (PsiPrimitiveType) super.getPsi();
}
}
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class JavaType {
private final PsiType psiType;
public JavaType(@NotNull PsiType psiType) {
this.psiType = psiType;
}
@NotNull
public PsiType getPsi() {
return psiType;
}
@NotNull
public static JavaType create(@NotNull PsiType psiType) {
return psiType.accept(new PsiTypeVisitor<JavaType>() {
@Nullable
@Override
public JavaType visitType(PsiType type) {
throw new UnsupportedOperationException("Unsupported PsiType: " + type);
}
@Nullable
@Override
public JavaType visitPrimitiveType(PsiPrimitiveType primitiveType) {
return new JavaPrimitiveType(primitiveType);
}
@Nullable
@Override
public JavaType visitArrayType(PsiArrayType arrayType) {
return new JavaArrayType(arrayType);
}
@Nullable
@Override
public JavaType visitClassType(PsiClassType classType) {
return new JavaClassType(classType);
}
@Nullable
@Override
public JavaType visitWildcardType(PsiWildcardType wildcardType) {
return new JavaWildcardType(wildcardType);
}
});
}
}
@@ -37,4 +37,9 @@ public class JavaValueParameter extends JavaElementImpl {
String name = getPsi().getName();
return name == null ? null : Name.identifier(name);
}
@NotNull
public JavaType getType() {
return JavaType.create(getPsi().getType());
}
}
@@ -0,0 +1,32 @@
/*
* Copyright 2010-2013 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.jet.lang.resolve.java.structure;
import com.intellij.psi.PsiWildcardType;
import org.jetbrains.annotations.NotNull;
public class JavaWildcardType extends JavaType {
public JavaWildcardType(@NotNull PsiWildcardType psiWildcardType) {
super(psiWildcardType);
}
@NotNull
@Override
public PsiWildcardType getPsi() {
return (PsiWildcardType) super.getPsi();
}
}