提交 eb7ac0cf 编写于 作者: A Andrey Breslav

Basic checks for base initializers in constructors.

Working on Java generics support.
上级 aba13415
......@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import java.util.Collections;
......@@ -10,7 +11,7 @@ import java.util.List;
/**
* @author max
*/
public class JetDelegatorToSuperCall extends JetDelegationSpecifier {
public class JetDelegatorToSuperCall extends JetDelegationSpecifier implements JetCall {
public JetDelegatorToSuperCall(@NotNull ASTNode node) {
super(node);
}
......@@ -20,12 +21,20 @@ public class JetDelegatorToSuperCall extends JetDelegationSpecifier {
visitor.visitDelegationToSuperCallSpecifier(this);
}
public JetArgumentList getArgumentList() {
@Nullable
public JetArgumentList getValueArgumentList() {
return (JetArgumentList) findChildByType(JetNodeTypes.VALUE_ARGUMENT_LIST);
}
public List<JetArgument> getArguments() {
JetArgumentList list = getArgumentList();
@NotNull
public List<JetArgument> getValueArguments() {
JetArgumentList list = getValueArgumentList();
return list != null ? list.getArguments() : Collections.<JetArgument>emptyList();
}
@NotNull
@Override
public List<JetExpression> getFunctionLiteralArguments() {
return Collections.emptyList();
}
}
......@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.psi;
import com.intellij.lang.ASTNode;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.JetNodeTypes;
import java.util.Collections;
......@@ -10,7 +11,7 @@ import java.util.List;
/**
* @author max
*/
public class JetDelegatorToThisCall extends JetDelegationSpecifier {
public class JetDelegatorToThisCall extends JetDelegationSpecifier implements JetCall {
public JetDelegatorToThisCall(@NotNull ASTNode node) {
super(node);
}
......@@ -20,12 +21,20 @@ public class JetDelegatorToThisCall extends JetDelegationSpecifier {
visitor.visitDelegationToThisCall(this);
}
public JetArgumentList getArgumentList() {
@Nullable
public JetArgumentList getValueArgumentList() {
return (JetArgumentList) findChildByType(JetNodeTypes.VALUE_ARGUMENT_LIST);
}
public List<JetArgument> getArguments() {
JetArgumentList list = getArgumentList();
@NotNull
public List<JetArgument> getValueArguments() {
JetArgumentList list = getValueArgumentList();
return list != null ? list.getArguments() : Collections.<JetArgument>emptyList();
}
@NotNull
@Override
public List<JetExpression> getFunctionLiteralArguments() {
return Collections.emptyList();
}
}
......@@ -50,7 +50,7 @@ public class ClassDescriptorResolver {
// TODO : assuming that the hierarchy is acyclic
Collection<? extends JetType> superclasses = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType())
: resolveTypes(parameterScope, delegationSpecifiers);
: resolveDelegationSpecifiers(parameterScope, delegationSpecifiers);
boolean open = classElement.hasModifier(JetTokens.OPEN_KEYWORD);
WritableScope members = resolveMembers(classDescriptor, classElement, typeParameters, scope, parameterScope, superclasses);
......@@ -98,7 +98,7 @@ public class ClassDescriptorResolver {
// TODO : assuming that the hierarchy is acyclic
Collection<? extends JetType> superclasses = delegationSpecifiers.isEmpty()
? Collections.singleton(JetStandardClasses.getAnyType())
: resolveTypes(parameterScope, delegationSpecifiers);
: resolveDelegationSpecifiers(parameterScope, delegationSpecifiers);
// TODO : UGLY HACK
supertypes.addAll(superclasses);
......@@ -260,7 +260,7 @@ public class ClassDescriptorResolver {
return typeParameterDescriptor;
}
public Collection<? extends JetType> resolveTypes(WritableScope extensibleScope, List<JetDelegationSpecifier> delegationSpecifiers) {
public Collection<? extends JetType> resolveDelegationSpecifiers(WritableScope extensibleScope, List<JetDelegationSpecifier> delegationSpecifiers) {
if (delegationSpecifiers.isEmpty()) {
return Collections.emptyList();
}
......
......@@ -296,18 +296,55 @@ public class TopDownAnalyzer {
}
}
private void resolveConstructorBody(JetConstructor declaration, FunctionDescriptor descriptor, WritableScope declaringScope) {
private void resolveConstructorBody(JetConstructor declaration, FunctionDescriptor descriptor, final WritableScope declaringScope) {
WritableScope constructorScope = semanticServices.createWritableScope(declaringScope, declaringScope.getContainingDeclaration());
for (PropertyDescriptor propertyDescriptor : declaringScopesToProperties.get(descriptor.getContainingDeclaration())) {
constructorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor);
}
final JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(constructorScope, descriptor, semanticServices);
final JetTypeInferrer typeInferrerForInitializers = semanticServices.getTypeInferrer(traceForConstructors, JetFlowInformationProvider.NONE);
for (JetDelegationSpecifier initializer : declaration.getInitializers()) {
// TODO : check that the type being referenced is actually a supertype
initializer.accept(new JetVisitor() {
@Override
public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
JetTypeReference typeReference = call.getTypeReference();
if (typeReference != null) {
typeInferrerForInitializers.getTypeForConstructorCall(functionInnerScope, typeReference, call);
}
}
@Override
public void visitDelegationToThisCall(JetDelegatorToThisCall call) {
JetTypeReference typeReference = call.getTypeReference(); // TODO : use explicit type here
if (typeReference != null) {
typeInferrerForInitializers.getTypeForConstructorCall(functionInnerScope, typeReference, call);
}
}
@Override
public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) {
semanticServices.getErrorHandler().genericError(specifier.getNode(), "'by'-clause is only supported for primary constructors");
}
@Override
public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) {
semanticServices.getErrorHandler().genericError(specifier.getNode(), "Constructor parameters required");
}
@Override
public void visitDelegationSpecifier(JetDelegationSpecifier specifier) {
throw new IllegalStateException();
}
});
}
JetExpression bodyExpression = declaration.getBodyExpression();
if (bodyExpression != null) {
computeFlowData(declaration, bodyExpression);
JetFlowInformationProvider flowInformationProvider = computeFlowData(declaration, bodyExpression);
JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider);
WritableScope constructorScope = semanticServices.createWritableScope(declaringScope, declaringScope.getContainingDeclaration());
for (PropertyDescriptor propertyDescriptor : declaringScopesToProperties.get(descriptor.getContainingDeclaration())) {
constructorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor);
}
typeInferrer.getType(FunctionDescriptorUtil.getFunctionInnerScope(constructorScope, descriptor, semanticServices), bodyExpression, true);
typeInferrer.getType(functionInnerScope, bodyExpression, true);
}
}
......
......@@ -68,8 +68,15 @@ public class TypeResolver {
trace.recordReferenceResolution(referenceExpression, classifierDescriptor);
TypeConstructor typeConstructor = classifierDescriptor.getTypeConstructor();
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments());
if (arguments.size() != typeConstructor.getParameters().size()) {
semanticServices.getErrorHandler().genericError(type.getNode(), typeConstructor.getParameters().size() + " type parameters expected"); // TODO : message
int expectedArgumentCount = typeConstructor.getParameters().size();
int actualArgumentCount = arguments.size();
if (actualArgumentCount != expectedArgumentCount) {
String errorMessage = (expectedArgumentCount == 0 ? "No" : expectedArgumentCount) + " type arguments expected";
if (actualArgumentCount == 0) {
semanticServices.getErrorHandler().genericError(type.getNode(), errorMessage);
} else if (expectedArgumentCount == 0) {
semanticServices.getErrorHandler().genericError(type.getTypeArgumentList().getNode(), errorMessage);
}
} else {
result[0] = new JetTypeImpl(
attributes,
......
package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import com.intellij.openapi.project.Project;
import com.intellij.psi.*;
import com.intellij.psi.search.GlobalSearchScope;
......@@ -77,7 +79,7 @@ public class JavaDescriptorResolver {
classDescriptor.initialize(
// TODO
modifierList == null ? false : modifierList.hasModifierProperty(PsiModifier.FINAL),
Collections.<TypeParameterDescriptor>emptyList(),
resolveTypeParameters(psiClass, classDescriptor),
getSupertypes(psiClass),
new JavaClassMembersScope(classDescriptor, psiClass, semanticServices, false),
constructors
......@@ -101,6 +103,41 @@ public class JavaDescriptorResolver {
return classDescriptor;
}
private List<TypeParameterDescriptor> resolveTypeParameters(@NotNull PsiClass psiClass, @NotNull ClassDescriptor classDescriptor) {
if (1 < 2) return Collections.emptyList(); // TODO
List<TypeParameterDescriptor> result = Lists.newArrayList();
PsiTypeParameter[] typeParameters = psiClass.getTypeParameters();
for (PsiTypeParameter typeParameter : typeParameters) {
PsiClassType[] referencedTypes = typeParameter.getExtendsList().getReferencedTypes();
Set<JetType> upperBounds;
JetType boundsAsType;
if (referencedTypes.length == 0){
boundsAsType = JetStandardClasses.getNullableAnyType();
upperBounds = Collections.singleton(boundsAsType);
}
else if (referencedTypes.length == 1) {
boundsAsType = semanticServices.getTypeTransformer().transform(referencedTypes[0]);
upperBounds = Collections.singleton(boundsAsType);
}
else {
upperBounds = Sets.newLinkedHashSet();
for (PsiClassType referencedType : referencedTypes) {
upperBounds.add(semanticServices.getTypeTransformer().transform(referencedType));
}
boundsAsType = TypeUtils.safeIntersect(semanticServices.getTypeChecker(), upperBounds);
}
result.add(new TypeParameterDescriptor(
classDescriptor,
Collections.<Attribute>emptyList(), // TODO
Variance.INVARIANT,
typeParameter.getName(),
upperBounds,
boundsAsType
));
}
return result;
}
private Collection<? extends JetType> getSupertypes(PsiClass psiClass) {
List<JetType> result = new ArrayList<JetType>();
result.add(JetStandardClasses.getAnyType());
......
......@@ -4,6 +4,7 @@ import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.JetSemanticServices;
import org.jetbrains.jet.lang.types.BindingTrace;
import org.jetbrains.jet.lang.types.JetTypeChecker;
/**
* @author abreslav
......@@ -12,11 +13,13 @@ public class JavaSemanticServices {
private final JavaTypeTransformer typeTransformer;
private final JavaDescriptorResolver descriptorResolver;
private final BindingTrace trace;
private final JetTypeChecker typeChecker;
public JavaSemanticServices(Project project, JetSemanticServices jetSemanticServices, BindingTrace trace) {
this.trace = trace;
this.descriptorResolver = new JavaDescriptorResolver(project, this);
this.typeTransformer = new JavaTypeTransformer(jetSemanticServices.getStandardLibrary(), descriptorResolver);
this.typeChecker = new JetTypeChecker(jetSemanticServices.getStandardLibrary());
}
@NotNull
......@@ -24,11 +27,18 @@ public class JavaSemanticServices {
return typeTransformer;
}
@NotNull
public JavaDescriptorResolver getDescriptorResolver() {
return descriptorResolver;
}
@NotNull
public BindingTrace getTrace() {
return trace;
}
@NotNull
public JetTypeChecker getTypeChecker() {
return typeChecker;
}
}
package org.jetbrains.jet.lang.resolve.java;
import com.google.common.collect.Lists;
import com.intellij.psi.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.types.*;
......@@ -29,7 +30,8 @@ public class JavaTypeTransformer {
return javaType.accept(new PsiTypeVisitor<JetType>() {
@Override
public JetType visitClassType(PsiClassType classType) {
PsiClass psiClass = classType.resolveGenerics().getElement();
PsiClassType.ClassResolveResult classResolveResult = classType.resolveGenerics();
PsiClass psiClass = classResolveResult.getElement();
if (psiClass == null) {
return ErrorUtils.createErrorType("Unresolved java class: " + classType.getPresentableText());
}
......@@ -40,8 +42,19 @@ public class JavaTypeTransformer {
}
ClassDescriptor descriptor = resolver.resolveClass(psiClass);
// TODO : arguments & raw types
List<TypeProjection> arguments = Collections.<TypeProjection>emptyList(); // TODO
List<TypeProjection> arguments = Lists.newArrayList();
if (classType.isRaw()) { // TODO
// List<TypeParameterDescriptor> parameters = descriptor.getTypeConstructor().getParameters();
// for (TypeParameterDescriptor parameter : parameters) {
// arguments.add(TypeUtils.makeStarProjection(parameter));
// }
} else { // TODO
// PsiType[] psiArguments = classType.getParameters();
// for (PsiType psiArgument : psiArguments) {
// arguments.add(new TypeProjection(transform(psiArgument)));
// }
}
return new JetTypeImpl(
Collections.<Attribute>emptyList(),
descriptor.getTypeConstructor(),
......@@ -64,6 +77,12 @@ public class JavaTypeTransformer {
return TypeUtils.makeNullable(standardLibrary.getArrayType(type));
}
@Override
public JetType visitWildcardType(PsiWildcardType wildcardType) {
System.out.println("!!!");
return JetStandardClasses.getNullableAnyType(); // TODO
}
@Override
public JetType visitType(PsiType type) {
throw new UnsupportedOperationException("Unsupported type: " + type.getPresentableText()); // TODO
......
......@@ -44,7 +44,7 @@ public class ClassDescriptorImpl extends DeclarationDescriptorImpl implements Cl
@Override
@NotNull
public JetScope getMemberScope(List<TypeProjection> typeArguments) {
assert typeArguments.size() == typeConstructor.getParameters().size();
assert typeArguments.size() == typeConstructor.getParameters().size() : typeArguments;
if (typeConstructor.getParameters().isEmpty()) {
return memberDeclarations;
}
......
......@@ -379,6 +379,171 @@ public class JetTypeInferrer {
}
}
@Nullable
private JetType resolveOverloads(JetScope scope, JetCallExpression expression, OverloadDomain overloadDomain) {
List<JetTypeProjection> typeArguments = expression.getTypeArguments();
List<JetArgument> valueArguments = expression.getValueArguments();
List<JetExpression> functionLiteralArguments = expression.getFunctionLiteralArguments();
return resolveOverloads(scope, overloadDomain, typeArguments, valueArguments, functionLiteralArguments);
}
@Nullable
private JetType resolveOverloads(
@NotNull JetScope scope,
@NotNull OverloadDomain overloadDomain,
@NotNull List<JetTypeProjection> typeArguments,
@NotNull List<JetArgument> valueArguments,
@NotNull List<JetExpression> functionLiteralArguments) {
// 1) ends with a name -> (scope, name) to look up
// 2) ends with something else -> just check types
for (JetTypeProjection typeArgument : typeArguments) {
if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
semanticServices.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
}
}
boolean someNamed = false;
for (JetArgument argument : valueArguments) {
if (argument.isNamed()) {
someNamed = true;
break;
}
}
// JetExpression functionLiteralArgument = functionLiteralArguments.isEmpty() ? null : functionLiteralArguments.get(0);
// TODO : must be a check
assert functionLiteralArguments.size() <= 1;
if (someNamed) {
// TODO : check that all are named
throw new UnsupportedOperationException(); // TODO
// result = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArguments, functionLiteralArgument);
} else {
List<JetType> types = new ArrayList<JetType>();
for (JetTypeProjection projection : typeArguments) {
// TODO : check that there's no projection
JetTypeReference typeReference = projection.getTypeReference();
if (typeReference != null) {
types.add(typeResolver.resolveType(scope, typeReference));
}
}
List<JetExpression> positionedValueArguments = new ArrayList<JetExpression>();
for (JetArgument argument : valueArguments) {
JetExpression argumentExpression = argument.getArgumentExpression();
if (argumentExpression != null) {
positionedValueArguments.add(argumentExpression);
}
}
positionedValueArguments.addAll(functionLiteralArguments);
List<JetType> valueArgumentTypes = new ArrayList<JetType>();
for (JetExpression valueArgument : positionedValueArguments) {
valueArgumentTypes.add(safeGetType(scope, valueArgument, false));
}
OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes);
if (resolutionResult.isSuccess()) {
return resolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
}
}
return null;
}
@Nullable
public JetType getTypeForConstructorCall(JetScope scope, @NotNull JetTypeReference typeReference, @NotNull JetCall call) {
JetTypeElement typeElement = typeReference.getTypeElement();
if (typeElement instanceof JetUserType) {
JetUserType userType = (JetUserType) typeElement;
// TODO : to infer constructor parameters, one will need to
// 1) resolve a _class_ from the typeReference
// 2) rely on the overload domain of constructors of this class to infer type arguments
// For now we assume that the type arguments are provided, and thus the typeReference can be
// resolved into a valid type
JetType receiverType = typeResolver.resolveType(scope, typeReference);
DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
for (JetTypeProjection typeProjection : userType.getTypeArguments()) {
switch (typeProjection.getProjectionKind()) {
case IN:
case OUT:
case STAR:
// TODO : Bug in the editor
semanticServices.getErrorHandler().genericError(typeProjection.getProjectionNode(), "Projections are not allowed in constructor type arguments");
break;
case NONE:
break;
}
}
JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
if (referenceExpression != null) {
// When one writes 'new Array<in T>(...)' this does not make much sense, and an instance
// of 'Array<T>' must be created anyway.
// Thus, we should either prohibit projections in type arguments in such contexts,
// or treat them as an automatic upcast to the desired type, i.e. for the user not
// to be forced to write
// val a : Array<in T> = new Array<T>(...)
// NOTE: Array may be a bad example here, some classes may have substantial functionality
// not involving their type parameters
//
// The code below upcasts the type automatically
List<TypeProjection> typeArguments = receiverType.getArguments();
List<TypeProjection> projectionsStripped = new ArrayList<TypeProjection>();
for (TypeProjection typeArgument : typeArguments) {
if (typeArgument.getProjectionKind() != Variance.INVARIANT) {
projectionsStripped.add(new TypeProjection(typeArgument.getType()));
}
else
projectionsStripped.add(typeArgument);
}
FunctionGroup constructors = classDescriptor.getConstructors(projectionsStripped);
OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(constructors);
JetType constructorReturnedType = resolveOverloads(
scope,
wrapForTracing(constructorsOverloadDomain, referenceExpression, call.getValueArgumentList(), false),
Collections.<JetTypeProjection>emptyList(),
call.getValueArguments(),
call.getFunctionLiteralArguments());
if (constructorReturnedType == null && !ErrorUtils.isErrorType(receiverType)) {
trace.recordReferenceResolution(referenceExpression, receiverType.getConstructor().getDeclarationDescriptor());
// TODO : more helpful message
JetArgumentList argumentList = call.getValueArgumentList();
if (argumentList != null) {
semanticServices.getErrorHandler().genericError(argumentList.getNode(), "Cannot find an overload for these arguments");
}
constructorReturnedType = receiverType;
}
// If no upcast needed:
return constructorReturnedType;
// Automatic upcast:
// result = receiverType;
}
}
else {
semanticServices.getErrorHandler().genericError(((JetElement) call).getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : review the message
}
}
else {
if (typeElement != null) {
semanticServices.getErrorHandler().genericError(typeElement.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : Better message
}
}
return null;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
private class TypeInferrerVisitor extends JetVisitor {
private final JetScope scope;
private final boolean preferBlock;
......@@ -968,89 +1133,7 @@ public class JetTypeInferrer {
// TODO : type argument inference
JetTypeReference typeReference = expression.getTypeReference();
if (typeReference != null) {
JetTypeElement typeElement = typeReference.getTypeElement();
if (typeElement instanceof JetUserType) {
JetUserType userType = (JetUserType) typeElement;
// TODO : to infer constructor parameters, one will need to
// 1) resolve a _class_ from the typeReference
// 2) rely on the overload domain of constructors of this class to infer type arguments
// For now we assume that the type arguments are provided, and thus the typeReference can be
// resolved into a valid type
JetType receiverType = typeResolver.resolveType(scope, typeReference);
DeclarationDescriptor declarationDescriptor = receiverType.getConstructor().getDeclarationDescriptor();
if (declarationDescriptor instanceof ClassDescriptor) {
ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
for (JetTypeProjection typeProjection : userType.getTypeArguments()) {
switch (typeProjection.getProjectionKind()) {
case IN:
case OUT:
case STAR:
// TODO : Bug in the editor
semanticServices.getErrorHandler().genericError(typeProjection.getProjectionNode(), "Projections are not allowed in constructor type arguments");
break;
case NONE:
break;
}
}
JetSimpleNameExpression referenceExpression = userType.getReferenceExpression();
if (referenceExpression != null) {
// When one writes 'new Array<in T>(...)' this does not make much sense, and an instance
// of 'Array<T>' must be created anyway.
// Thus, we should either prohibit projections in type arguments in such contexts,
// or treat them as an automatic upcast to the desired type, i.e. for the user not
// to be forced to write
// val a : Array<in T> = new Array<T>(...)
// NOTE: Array may be a bad example here, some classes may have substantial functionality
// not involving their type parameters
//
// The code below upcasts the type automatically
List<TypeProjection> typeArguments = receiverType.getArguments();
List<TypeProjection> projectionsStripped = new ArrayList<TypeProjection>();
for (TypeProjection typeArgument : typeArguments) {
if (typeArgument.getProjectionKind() != Variance.INVARIANT) {
projectionsStripped.add(new TypeProjection(typeArgument.getType()));
}
else
projectionsStripped.add(typeArgument);
}
FunctionGroup constructors = classDescriptor.getConstructors(projectionsStripped);
OverloadDomain constructorsOverloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(constructors);
JetType constructorReturnedType = resolveOverloads(
scope,
wrapForTracing(constructorsOverloadDomain, referenceExpression, expression.getValueArgumentList(), false),
Collections.<JetTypeProjection>emptyList(),
expression.getValueArguments(),
expression.getFunctionLiteralArguments());
if (constructorReturnedType == null && !ErrorUtils.isErrorType(receiverType)) {
trace.recordReferenceResolution(referenceExpression, receiverType.getConstructor().getDeclarationDescriptor());
// TODO : more helpful message
JetArgumentList argumentList = expression.getValueArgumentList();
if (argumentList != null) {
semanticServices.getErrorHandler().genericError(argumentList.getNode(), "Cannot find an overload for these arguments");
}
constructorReturnedType = receiverType;
}
// If no upcast needed:
result = constructorReturnedType;
// Automatic upcast:
// result = receiverType;
}
}
else {
semanticServices.getErrorHandler().genericError(expression.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : review the message
}
}
else {
if (typeElement != null) {
semanticServices.getErrorHandler().genericError(typeElement.getNode(), "Calling a constructor is only supported for ordinary classes"); // TODO : Better message
}
}
result = getTypeForConstructorCall(scope, typeReference, expression);
}
}
......@@ -1108,80 +1191,6 @@ public class JetTypeInferrer {
result = resolveOverloads(scope, expression, overloadDomain);
}
@Nullable
private JetType resolveOverloads(JetScope scope, JetCallExpression expression, OverloadDomain overloadDomain) {
List<JetTypeProjection> typeArguments = expression.getTypeArguments();
List<JetArgument> valueArguments = expression.getValueArguments();
List<JetExpression> functionLiteralArguments = expression.getFunctionLiteralArguments();
return resolveOverloads(scope, overloadDomain, typeArguments, valueArguments, functionLiteralArguments);
}
@Nullable
private JetType resolveOverloads(
@NotNull JetScope scope,
@NotNull OverloadDomain overloadDomain,
@NotNull List<JetTypeProjection> typeArguments,
@NotNull List<JetArgument> valueArguments,
@NotNull List<JetExpression> functionLiteralArguments) {
// 1) ends with a name -> (scope, name) to look up
// 2) ends with something else -> just check types
for (JetTypeProjection typeArgument : typeArguments) {
if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
semanticServices.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
}
}
boolean someNamed = false;
for (JetArgument argument : valueArguments) {
if (argument.isNamed()) {
someNamed = true;
break;
}
}
// JetExpression functionLiteralArgument = functionLiteralArguments.isEmpty() ? null : functionLiteralArguments.get(0);
// TODO : must be a check
assert functionLiteralArguments.size() <= 1;
if (someNamed) {
// TODO : check that all are named
throw new UnsupportedOperationException(); // TODO
// result = overloadDomain.getFunctionDescriptorForNamedArguments(typeArguments, valueArguments, functionLiteralArgument);
} else {
List<JetType> types = new ArrayList<JetType>();
for (JetTypeProjection projection : typeArguments) {
// TODO : check that there's no projection
JetTypeReference typeReference = projection.getTypeReference();
if (typeReference != null) {
types.add(typeResolver.resolveType(scope, typeReference));
}
}
List<JetExpression> positionedValueArguments = new ArrayList<JetExpression>();
for (JetArgument argument : valueArguments) {
JetExpression argumentExpression = argument.getArgumentExpression();
if (argumentExpression != null) {
positionedValueArguments.add(argumentExpression);
}
}
positionedValueArguments.addAll(functionLiteralArguments);
List<JetType> valueArgumentTypes = new ArrayList<JetType>();
for (JetExpression valueArgument : positionedValueArguments) {
valueArgumentTypes.add(safeGetType(scope, valueArgument, false));
}
OverloadResolutionResult resolutionResult = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes);
if (resolutionResult.isSuccess()) {
return resolutionResult.getFunctionDescriptor().getUnsubstitutedReturnType();
}
}
return null;
}
@Override
public void visitIsExpression(JetIsExpression expression) {
// TODO : patterns and everything
......
......@@ -27,6 +27,13 @@ public class TypeUtils {
return new JetTypeImpl(type.getAttributes(), type.getConstructor(), nullable, type.getArguments(), type.getMemberScope());
}
@NotNull
public static JetType safeIntersect(JetTypeChecker typeChecker, Set<JetType> types) {
JetType intersection = intersect(typeChecker, types);
if (intersection == null) return ErrorUtils.createErrorType("No intersection for " + types); // TODO : message
return intersection;
}
@Nullable
public static JetType intersect(JetTypeChecker typeChecker, Set<JetType> types) {
assert !types.isEmpty();
......@@ -212,12 +219,11 @@ public class TypeUtils {
}
}
@NotNull
public static Set<JetType> getAllSupertypes(@NotNull JetType type) {
Set<JetType> result = Sets.newLinkedHashSet();
collectAllSupertypes(type, result);
return result;
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册