Basic overload resolution supported
This commit is contained in:
@@ -1,7 +1,9 @@
|
|||||||
package org.jetbrains.jet.lang;
|
package org.jetbrains.jet.lang;
|
||||||
|
|
||||||
import com.intellij.lang.ASTNode;
|
import com.intellij.lang.ASTNode;
|
||||||
|
import org.jetbrains.jet.lang.psi.JetExpression;
|
||||||
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
|
||||||
|
import org.jetbrains.jet.lang.types.Type;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
@@ -18,6 +20,11 @@ public class ErrorHandler {
|
|||||||
public void structuralError(ASTNode node, String errorMessage) {
|
public void structuralError(ASTNode node, String errorMessage) {
|
||||||
throw new IllegalStateException(errorMessage);
|
throw new IllegalStateException(errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void typeMismatch(JetExpression expression, Type expectedType, Type actualType) {
|
||||||
|
throw new IllegalStateException("Type mismatch: inferred type is " + actualType + " but " + expectedType + " was expected");
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public void unresolvedReference(JetReferenceExpression referenceExpression) {
|
public void unresolvedReference(JetReferenceExpression referenceExpression) {
|
||||||
@@ -25,4 +32,7 @@ public class ErrorHandler {
|
|||||||
|
|
||||||
public void structuralError(ASTNode node, String errorMessage) {
|
public void structuralError(ASTNode node, String errorMessage) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void typeMismatch(JetExpression expression, Type expectedType, Type actualType) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,9 +1,12 @@
|
|||||||
package org.jetbrains.jet.lang;
|
package org.jetbrains.jet.lang;
|
||||||
|
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver;
|
import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver;
|
||||||
|
import org.jetbrains.jet.lang.resolve.OverloadResolver;
|
||||||
import org.jetbrains.jet.lang.types.BindingTrace;
|
import org.jetbrains.jet.lang.types.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
import org.jetbrains.jet.lang.types.JetStandardLibrary;
|
||||||
|
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||||
import org.jetbrains.jet.lang.types.JetTypeInferrer;
|
import org.jetbrains.jet.lang.types.JetTypeInferrer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -20,6 +23,8 @@ public class JetSemanticServices {
|
|||||||
|
|
||||||
private final JetTypeInferrer typeInferrer;
|
private final JetTypeInferrer typeInferrer;
|
||||||
private final JetStandardLibrary standardLibrary;
|
private final JetStandardLibrary standardLibrary;
|
||||||
|
private final JetTypeChecker typeChecker;
|
||||||
|
private final OverloadResolver overloadResolver;
|
||||||
|
|
||||||
private final ErrorHandler errorHandler;
|
private final ErrorHandler errorHandler;
|
||||||
|
|
||||||
@@ -27,25 +32,42 @@ public class JetSemanticServices {
|
|||||||
this.standardLibrary = standardLibrary;
|
this.standardLibrary = standardLibrary;
|
||||||
this.errorHandler = errorHandler;
|
this.errorHandler = errorHandler;
|
||||||
this.typeInferrer = new JetTypeInferrer(BindingTrace.DUMMY, this);
|
this.typeInferrer = new JetTypeInferrer(BindingTrace.DUMMY, this);
|
||||||
|
this.typeChecker = new JetTypeChecker(standardLibrary);
|
||||||
|
this.overloadResolver = new OverloadResolver(typeChecker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public JetStandardLibrary getStandardLibrary() {
|
public JetStandardLibrary getStandardLibrary() {
|
||||||
return standardLibrary;
|
return standardLibrary;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public JetTypeInferrer getTypeInferrer() {
|
public JetTypeInferrer getTypeInferrer() {
|
||||||
return typeInferrer;
|
return typeInferrer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public ClassDescriptorResolver getClassDescriptorResolver(BindingTrace trace) {
|
public ClassDescriptorResolver getClassDescriptorResolver(BindingTrace trace) {
|
||||||
return new ClassDescriptorResolver(this, trace);
|
return new ClassDescriptorResolver(this, trace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public JetTypeInferrer getTypeInferrer(BindingTrace trace) {
|
public JetTypeInferrer getTypeInferrer(BindingTrace trace) {
|
||||||
return new JetTypeInferrer(trace, this);
|
return new JetTypeInferrer(trace, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
public ErrorHandler getErrorHandler() {
|
public ErrorHandler getErrorHandler() {
|
||||||
return errorHandler;
|
return errorHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public JetTypeChecker getTypeChecker() {
|
||||||
|
return typeChecker;
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public OverloadResolver getOverloadResolver() {
|
||||||
|
return overloadResolver;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package org.jetbrains.jet.lang.annotations;
|
package org.jetbrains.jet.lang.annotations;
|
||||||
|
|
||||||
|
import com.intellij.lang.ASTNode;
|
||||||
import com.intellij.lang.annotation.AnnotationHolder;
|
import com.intellij.lang.annotation.AnnotationHolder;
|
||||||
import com.intellij.lang.annotation.Annotator;
|
import com.intellij.lang.annotation.Annotator;
|
||||||
import com.intellij.openapi.project.Project;
|
import com.intellij.openapi.project.Project;
|
||||||
@@ -29,6 +30,16 @@ public class JetPsiChecker implements Annotator {
|
|||||||
public void unresolvedReference(JetReferenceExpression referenceExpression) {
|
public void unresolvedReference(JetReferenceExpression referenceExpression) {
|
||||||
holder.createErrorAnnotation(referenceExpression, "Unresolved");
|
holder.createErrorAnnotation(referenceExpression, "Unresolved");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void structuralError(ASTNode node, String errorMessage) {
|
||||||
|
holder.createErrorAnnotation(node, errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void typeMismatch(JetExpression expression, Type expectedType, Type actualType) {
|
||||||
|
holder.createErrorAnnotation(expression, "Type mismatch: inferred type is " + actualType + " but " + expectedType + " was expected");
|
||||||
|
}
|
||||||
});
|
});
|
||||||
file.getRootNamespace().accept(new JetVisitor() {
|
file.getRootNamespace().accept(new JetVisitor() {
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -4,19 +4,18 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.*;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
public class OverloadResolver {
|
public class OverloadResolver {
|
||||||
|
|
||||||
public static final OverloadResolver INSTANCE = new OverloadResolver();
|
private final JetTypeChecker typeChecker;
|
||||||
|
|
||||||
private OverloadResolver() {}
|
public OverloadResolver(JetTypeChecker typeChecker) {
|
||||||
|
this.typeChecker = typeChecker;
|
||||||
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public OverloadDomain getOverloadDomain(Type receiverType, @NotNull JetScope outerScope, @NotNull String name) {
|
public OverloadDomain getOverloadDomain(Type receiverType, @NotNull JetScope outerScope, @NotNull String name) {
|
||||||
@@ -54,7 +53,7 @@ public class OverloadResolver {
|
|||||||
Type argumentType = positionedValueArgumentTypes.get(i);
|
Type argumentType = positionedValueArgumentTypes.get(i);
|
||||||
Type parameterType = parameters.get(i).getType();
|
Type parameterType = parameters.get(i).getType();
|
||||||
// TODO : handle vararg cases here
|
// TODO : handle vararg cases here
|
||||||
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, parameterType)) {
|
if (!typeChecker.isConvertibleTo(argumentType, parameterType)) {
|
||||||
continue descLoop;
|
continue descLoop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,14 +63,14 @@ public class OverloadResolver {
|
|||||||
for (int i = 0; i < nonVarargs; i++) {
|
for (int i = 0; i < nonVarargs; i++) {
|
||||||
Type argumentType = positionedValueArgumentTypes.get(i);
|
Type argumentType = positionedValueArgumentTypes.get(i);
|
||||||
Type parameterType = parameters.get(i).getType();
|
Type parameterType = parameters.get(i).getType();
|
||||||
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, parameterType)) {
|
if (!typeChecker.isConvertibleTo(argumentType, parameterType)) {
|
||||||
continue descLoop;
|
continue descLoop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Type varArgType = parameters.get(nonVarargs).getType();
|
Type varArgType = parameters.get(nonVarargs).getType();
|
||||||
for (int i = nonVarargs, args = positionedValueArgumentTypes.size(); i < args; i++) {
|
for (int i = nonVarargs, args = positionedValueArgumentTypes.size(); i < args; i++) {
|
||||||
Type argumentType = positionedValueArgumentTypes.get(i);
|
Type argumentType = positionedValueArgumentTypes.get(i);
|
||||||
if (!JetTypeChecker.INSTANCE.isConvertibleTo(argumentType, varArgType)) {
|
if (!typeChecker.isConvertibleTo(argumentType, varArgType)) {
|
||||||
continue descLoop;
|
continue descLoop;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -84,6 +83,23 @@ public class OverloadResolver {
|
|||||||
} else if (applicable.size() == 1) {
|
} else if (applicable.size() == 1) {
|
||||||
return applicable.get(0);
|
return applicable.get(0);
|
||||||
} else {
|
} else {
|
||||||
|
// TODO : varargs
|
||||||
|
|
||||||
|
List<FunctionDescriptor> maximallySpecific = new ArrayList<FunctionDescriptor>();
|
||||||
|
meLoop:
|
||||||
|
for (FunctionDescriptor me : applicable) {
|
||||||
|
for (FunctionDescriptor other : applicable) {
|
||||||
|
if (other == me) continue;
|
||||||
|
if (!moreSpecific(me, other) || moreSpecific(other, me)) continue meLoop;
|
||||||
|
}
|
||||||
|
maximallySpecific.add(me);
|
||||||
|
}
|
||||||
|
if (maximallySpecific.isEmpty()) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (maximallySpecific.size() == 1) {
|
||||||
|
return maximallySpecific.get(0);
|
||||||
|
}
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -95,4 +111,22 @@ public class OverloadResolver {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean moreSpecific(FunctionDescriptor f, FunctionDescriptor g) {
|
||||||
|
List<ValueParameterDescriptor> fParams = f.getUnsubstitutedValueParameters();
|
||||||
|
List<ValueParameterDescriptor> gParams = g.getUnsubstitutedValueParameters();
|
||||||
|
|
||||||
|
int fSize = fParams.size();
|
||||||
|
if (fSize != gParams.size()) return false;
|
||||||
|
for (int i = 0; i < fSize; i++) {
|
||||||
|
Type fParamType = fParams.get(i).getType();
|
||||||
|
Type gParamType = gParams.get(i).getType();
|
||||||
|
|
||||||
|
// TODO : maybe isSubtypeOf is sufficient?
|
||||||
|
if (!typeChecker.isConvertibleTo(fParamType, gParamType)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,76 +36,78 @@ public class TypeResolver {
|
|||||||
|
|
||||||
private Type resolveTypeElement(final JetScope scope, final List<Attribute> attributes, JetTypeElement typeElement, final boolean nullable) {
|
private Type resolveTypeElement(final JetScope scope, final List<Attribute> attributes, JetTypeElement typeElement, final boolean nullable) {
|
||||||
final Type[] result = new Type[1];
|
final Type[] result = new Type[1];
|
||||||
typeElement.accept(new JetVisitor() {
|
if (typeElement != null) {
|
||||||
@Override
|
typeElement.accept(new JetVisitor() {
|
||||||
public void visitUserType(JetUserType type) {
|
@Override
|
||||||
ClassDescriptor classDescriptor = resolveClass(scope, type);
|
public void visitUserType(JetUserType type) {
|
||||||
if (classDescriptor != null) {
|
ClassDescriptor classDescriptor = resolveClass(scope, type);
|
||||||
trace.recordReferenceResolution(type.getReferenceExpression(), classDescriptor);
|
if (classDescriptor != null) {
|
||||||
TypeConstructor typeConstructor = classDescriptor.getTypeConstructor();
|
trace.recordReferenceResolution(type.getReferenceExpression(), classDescriptor);
|
||||||
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments());
|
TypeConstructor typeConstructor = classDescriptor.getTypeConstructor();
|
||||||
result[0] = new TypeImpl(
|
List<TypeProjection> arguments = resolveTypeProjections(scope, typeConstructor, type.getTypeArguments());
|
||||||
attributes,
|
|
||||||
typeConstructor,
|
|
||||||
nullable,
|
|
||||||
arguments,
|
|
||||||
classDescriptor.getMemberScope(arguments)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
else if (type.getTypeArguments().isEmpty()) {
|
|
||||||
TypeParameterDescriptor typeParameterDescriptor = scope.getTypeParameter(type.getReferencedName());
|
|
||||||
if (typeParameterDescriptor != null) {
|
|
||||||
trace.recordReferenceResolution(type.getReferenceExpression(), typeParameterDescriptor);
|
|
||||||
result[0] = new TypeImpl(
|
result[0] = new TypeImpl(
|
||||||
attributes,
|
attributes,
|
||||||
typeParameterDescriptor.getTypeConstructor(),
|
typeConstructor,
|
||||||
nullable || hasNullableBound(typeParameterDescriptor),
|
nullable,
|
||||||
Collections.<TypeProjection>emptyList(),
|
arguments,
|
||||||
// TODO : joint domain
|
classDescriptor.getMemberScope(arguments)
|
||||||
JetStandardClasses.STUB
|
|
||||||
);
|
);
|
||||||
} else {
|
}
|
||||||
|
else if (type.getTypeArguments().isEmpty()) {
|
||||||
|
TypeParameterDescriptor typeParameterDescriptor = scope.getTypeParameter(type.getReferencedName());
|
||||||
|
if (typeParameterDescriptor != null) {
|
||||||
|
trace.recordReferenceResolution(type.getReferenceExpression(), typeParameterDescriptor);
|
||||||
|
result[0] = new TypeImpl(
|
||||||
|
attributes,
|
||||||
|
typeParameterDescriptor.getTypeConstructor(),
|
||||||
|
nullable || hasNullableBound(typeParameterDescriptor),
|
||||||
|
Collections.<TypeProjection>emptyList(),
|
||||||
|
// TODO : joint domain
|
||||||
|
JetStandardClasses.STUB
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
semanticServices.getErrorHandler().unresolvedReference(type.getReferenceExpression());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
semanticServices.getErrorHandler().unresolvedReference(type.getReferenceExpression());
|
semanticServices.getErrorHandler().unresolvedReference(type.getReferenceExpression());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
semanticServices.getErrorHandler().unresolvedReference(type.getReferenceExpression());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void visitNullableType(JetNullableType nullableType) {
|
public void visitNullableType(JetNullableType nullableType) {
|
||||||
result[0] = resolveTypeElement(scope, attributes, nullableType.getInnerType(), true);
|
result[0] = resolveTypeElement(scope, attributes, nullableType.getInnerType(), true);
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitTupleType(JetTupleType type) {
|
|
||||||
// TODO labels
|
|
||||||
result[0] = JetStandardClasses.getTupleType(resolveTypes(scope, type.getComponentTypeRefs()));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void visitFunctionType(JetFunctionType type) {
|
|
||||||
JetTypeReference receiverTypeRef = type.getReceiverTypeRef();
|
|
||||||
Type receiverType = receiverTypeRef == null ? null : resolveType(scope, receiverTypeRef);
|
|
||||||
|
|
||||||
List<Type> parameterTypes = new ArrayList<Type>();
|
|
||||||
for (JetParameter parameter : type.getParameters()) {
|
|
||||||
parameterTypes.add(resolveType(scope, parameter.getTypeReference()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Type returnType = resolveType(scope, type.getReturnTypeRef());
|
@Override
|
||||||
|
public void visitTupleType(JetTupleType type) {
|
||||||
|
// TODO labels
|
||||||
|
result[0] = JetStandardClasses.getTupleType(resolveTypes(scope, type.getComponentTypeRefs()));
|
||||||
|
}
|
||||||
|
|
||||||
result[0] = JetStandardClasses.getFunctionType(attributes, receiverType, parameterTypes, returnType);
|
@Override
|
||||||
}
|
public void visitFunctionType(JetFunctionType type) {
|
||||||
|
JetTypeReference receiverTypeRef = type.getReceiverTypeRef();
|
||||||
|
Type receiverType = receiverTypeRef == null ? null : resolveType(scope, receiverTypeRef);
|
||||||
|
|
||||||
@Override
|
List<Type> parameterTypes = new ArrayList<Type>();
|
||||||
public void visitJetElement(JetElement elem) {
|
for (JetParameter parameter : type.getParameters()) {
|
||||||
throw new IllegalArgumentException("Unsupported type: " + elem);
|
parameterTypes.add(resolveType(scope, parameter.getTypeReference()));
|
||||||
}
|
}
|
||||||
});
|
|
||||||
|
Type returnType = resolveType(scope, type.getReturnTypeRef());
|
||||||
|
|
||||||
|
result[0] = JetStandardClasses.getFunctionType(attributes, receiverType, parameterTypes, returnType);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void visitJetElement(JetElement elem) {
|
||||||
|
throw new IllegalArgumentException("Unsupported type: " + elem);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
if (result[0] == null) {
|
if (result[0] == null) {
|
||||||
return ErrorType.createErrorType(typeElement.getText());
|
return ErrorType.createErrorType(typeElement == null ? "No type element": typeElement.getText());
|
||||||
}
|
}
|
||||||
return result[0];
|
return result[0];
|
||||||
}
|
}
|
||||||
@@ -137,7 +139,7 @@ public class TypeResolver {
|
|||||||
Type type;
|
Type type;
|
||||||
if (projectionKind == JetProjectionKind.STAR) {
|
if (projectionKind == JetProjectionKind.STAR) {
|
||||||
Set<Type> upperBounds = constructor.getParameters().get(i).getUpperBounds();
|
Set<Type> upperBounds = constructor.getParameters().get(i).getUpperBounds();
|
||||||
arguments.add(new TypeProjection(Variance.OUT_VARIANCE, TypeUtils.intersect(upperBounds)));
|
arguments.add(new TypeProjection(Variance.OUT_VARIANCE, TypeUtils.intersect(semanticServices.getTypeChecker(), upperBounds)));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// TODO : handle the Foo<in *> case
|
// TODO : handle the Foo<in *> case
|
||||||
|
|||||||
@@ -61,6 +61,6 @@ public class WritableFunctionGroup implements FunctionGroup {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isEmpty() {
|
public boolean isEmpty() {
|
||||||
return functionDescriptors.isEmpty();
|
return functionDescriptors == null || functionDescriptors.isEmpty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -160,6 +160,7 @@ public class WritableScope extends JetScopeAdapter {
|
|||||||
public void addClassAlias(String name, ClassDescriptor classDescriptor) {
|
public void addClassAlias(String name, ClassDescriptor classDescriptor) {
|
||||||
Map<String, ClassDescriptor> classDescriptors = getClassDescriptors();
|
Map<String, ClassDescriptor> classDescriptors = getClassDescriptors();
|
||||||
if (classDescriptors.put(name, classDescriptor) != null) {
|
if (classDescriptors.put(name, classDescriptor) != null) {
|
||||||
|
|
||||||
throw new UnsupportedOperationException("Class redeclared: " + classDescriptor.getName());
|
throw new UnsupportedOperationException("Class redeclared: " + classDescriptor.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,22 +72,22 @@ public class JavaClassMembersScope implements JetScope {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ExtensionDescriptor getExtension(@NotNull String name) {
|
public ExtensionDescriptor getExtension(@NotNull String name) {
|
||||||
throw new UnsupportedOperationException(); // TODO
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NamespaceDescriptor getNamespace(@NotNull String name) {
|
public NamespaceDescriptor getNamespace(@NotNull String name) {
|
||||||
throw new UnsupportedOperationException(); // TODO
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypeParameterDescriptor getTypeParameter(@NotNull String name) {
|
public TypeParameterDescriptor getTypeParameter(@NotNull String name) {
|
||||||
throw new UnsupportedOperationException(); // TODO
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public Type getThisType() {
|
public Type getThisType() {
|
||||||
throw new UnsupportedOperationException(); // TODO
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -59,13 +59,29 @@ public class JavaDescriptorResolver {
|
|||||||
modifierList == null ? false : modifierList.hasModifierProperty(PsiModifier.FINAL),
|
modifierList == null ? false : modifierList.hasModifierProperty(PsiModifier.FINAL),
|
||||||
name,
|
name,
|
||||||
Collections.<TypeParameterDescriptor>emptyList(),
|
Collections.<TypeParameterDescriptor>emptyList(),
|
||||||
Collections.<Type>emptyList(),
|
getSupertypes(psiClass),
|
||||||
new JavaClassMembersScope(psiClass, semanticServices, false)
|
new JavaClassMembersScope(psiClass, semanticServices, false)
|
||||||
);
|
);
|
||||||
semanticServices.getTrace().recordDeclarationResolution(psiClass, classDescriptor);
|
semanticServices.getTrace().recordDeclarationResolution(psiClass, classDescriptor);
|
||||||
return classDescriptor;
|
return classDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Collection<? extends Type> getSupertypes(PsiClass psiClass) {
|
||||||
|
List<Type> result = new ArrayList<Type>();
|
||||||
|
result.add(JetStandardClasses.getAnyType());
|
||||||
|
transformSupertypeList(result, psiClass.getExtendsListTypes());
|
||||||
|
transformSupertypeList(result, psiClass.getImplementsListTypes());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void transformSupertypeList(List<Type> result, PsiClassType[] extendsListTypes) {
|
||||||
|
for (PsiClassType type : extendsListTypes) {
|
||||||
|
Type transform = semanticServices.getTypeTransformer().transform(type);
|
||||||
|
|
||||||
|
result.add(TypeUtils.makeNotNullable(transform));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public NamespaceDescriptor resolveNamespace(String qualifiedName) {
|
public NamespaceDescriptor resolveNamespace(String qualifiedName) {
|
||||||
NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(qualifiedName);
|
NamespaceDescriptor namespaceDescriptor = namespaceDescriptorCache.get(qualifiedName);
|
||||||
if (namespaceDescriptor == null) {
|
if (namespaceDescriptor == null) {
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ import com.intellij.psi.*;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -23,13 +25,25 @@ public class JavaTypeTransformer {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public Type transform(PsiType javaType) {
|
public Type transform(PsiType javaType) {
|
||||||
Type result = javaType.accept(new PsiTypeVisitor<Type>() {
|
return javaType.accept(new PsiTypeVisitor<Type>() {
|
||||||
@Override
|
@Override
|
||||||
public Type visitClassType(PsiClassType classType) {
|
public Type visitClassType(PsiClassType classType) {
|
||||||
PsiClass psiClass = classType.resolveGenerics().getElement();
|
PsiClass psiClass = classType.resolveGenerics().getElement();
|
||||||
|
if (psiClass == null) {
|
||||||
|
return ErrorType.createErrorType("Unresolved java class: " + classType.getPresentableText());
|
||||||
|
}
|
||||||
|
if ("java.lang.Object".equals(psiClass.getQualifiedName())) {
|
||||||
|
return JetStandardClasses.getNullableAnyType();
|
||||||
|
}
|
||||||
ClassDescriptor descriptor = resolver.resolveClass(psiClass);
|
ClassDescriptor descriptor = resolver.resolveClass(psiClass);
|
||||||
// TODO : parameters
|
// TODO : arguments & raw types
|
||||||
return new TypeImpl(descriptor);
|
List<TypeProjection> arguments = Collections.<TypeProjection>emptyList(); // TODO
|
||||||
|
return new TypeImpl(
|
||||||
|
Collections.<Attribute>emptyList(),
|
||||||
|
descriptor.getTypeConstructor(),
|
||||||
|
true,
|
||||||
|
arguments,
|
||||||
|
descriptor.getMemberScope(arguments));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -42,10 +56,10 @@ public class JavaTypeTransformer {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Type visitArrayType(PsiArrayType arrayType) {
|
public Type visitArrayType(PsiArrayType arrayType) {
|
||||||
return JetStandardClasses.getUnitType(); // TODO!!!
|
Type type = transform(arrayType.getComponentType());
|
||||||
|
return TypeUtils.makeNullable(standardLibrary.getArrayType(type));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<String, Type> getPrimitiveTypesMap() {
|
public Map<String, Type> getPrimitiveTypesMap() {
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
package org.jetbrains.jet.lang.types;
|
package org.jetbrains.jet.lang.types;
|
||||||
|
|
||||||
|
import org.jetbrains.jet.resolve.DescriptorUtil;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -28,4 +30,9 @@ public abstract class DeclarationDescriptorImpl extends AnnotatedImpl implements
|
|||||||
public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
|
public void acceptVoid(DeclarationDescriptorVisitor<Void, Void> visitor) {
|
||||||
accept(visitor, null);
|
accept(visitor, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return DescriptorUtil.renderPresentableText(this) + "[" + getClass().getCanonicalName()+ "]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,9 +10,57 @@ import java.util.*;
|
|||||||
*/
|
*/
|
||||||
public class JetTypeChecker {
|
public class JetTypeChecker {
|
||||||
|
|
||||||
public static final JetTypeChecker INSTANCE = new JetTypeChecker();
|
private final Map<TypeConstructor, Set<TypeConstructor>> conversionMap = new HashMap<TypeConstructor, Set<TypeConstructor>>();
|
||||||
|
private final JetStandardLibrary standardLibrary;
|
||||||
|
|
||||||
private JetTypeChecker() {}
|
public JetTypeChecker(JetStandardLibrary standardLibrary) {
|
||||||
|
this.standardLibrary = standardLibrary;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<TypeConstructor, Set<TypeConstructor>> getConversionMap() {
|
||||||
|
if (conversionMap.size() == 0) {
|
||||||
|
addConversion(standardLibrary.getByte(),
|
||||||
|
standardLibrary.getShort(),
|
||||||
|
standardLibrary.getInt(),
|
||||||
|
standardLibrary.getLong(),
|
||||||
|
standardLibrary.getFloat(),
|
||||||
|
standardLibrary.getDouble());
|
||||||
|
|
||||||
|
addConversion(standardLibrary.getShort(),
|
||||||
|
standardLibrary.getInt(),
|
||||||
|
standardLibrary.getLong(),
|
||||||
|
standardLibrary.getFloat(),
|
||||||
|
standardLibrary.getDouble());
|
||||||
|
|
||||||
|
addConversion(standardLibrary.getChar(),
|
||||||
|
standardLibrary.getInt(),
|
||||||
|
standardLibrary.getLong(),
|
||||||
|
standardLibrary.getFloat(),
|
||||||
|
standardLibrary.getDouble());
|
||||||
|
|
||||||
|
addConversion(standardLibrary.getInt(),
|
||||||
|
standardLibrary.getLong(),
|
||||||
|
standardLibrary.getFloat(),
|
||||||
|
standardLibrary.getDouble());
|
||||||
|
|
||||||
|
addConversion(standardLibrary.getLong(),
|
||||||
|
standardLibrary.getFloat(),
|
||||||
|
standardLibrary.getDouble());
|
||||||
|
|
||||||
|
addConversion(standardLibrary.getFloat(),
|
||||||
|
standardLibrary.getDouble());
|
||||||
|
}
|
||||||
|
return conversionMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addConversion(ClassDescriptor actual, ClassDescriptor... convertedTo) {
|
||||||
|
TypeConstructor[] constructors = new TypeConstructor[convertedTo.length];
|
||||||
|
for (int i = 0, convertedToLength = convertedTo.length; i < convertedToLength; i++) {
|
||||||
|
ClassDescriptor classDescriptor = convertedTo[i];
|
||||||
|
constructors[i] = classDescriptor.getTypeConstructor();
|
||||||
|
}
|
||||||
|
conversionMap.put(actual.getTypeConstructor(), new HashSet<TypeConstructor>(Arrays.asList(constructors)));
|
||||||
|
}
|
||||||
|
|
||||||
public Type commonSupertype(Collection<Type> types) {
|
public Type commonSupertype(Collection<Type> types) {
|
||||||
Collection<Type> typeSet = new HashSet<Type>(types);
|
Collection<Type> typeSet = new HashSet<Type>(types);
|
||||||
@@ -121,7 +169,7 @@ public class JetTypeChecker {
|
|||||||
|
|
||||||
if (ins != null) {
|
if (ins != null) {
|
||||||
Variance projectionKind = variance == Variance.IN_VARIANCE ? Variance.INVARIANT : Variance.IN_VARIANCE;
|
Variance projectionKind = variance == Variance.IN_VARIANCE ? Variance.INVARIANT : Variance.IN_VARIANCE;
|
||||||
Type intersection = TypeUtils.intersect(ins);
|
Type intersection = TypeUtils.intersect(this, ins);
|
||||||
if (intersection == null) {
|
if (intersection == null) {
|
||||||
return new TypeProjection(Variance.OUT_VARIANCE, commonSupertype(parameterDescriptor.getUpperBounds()));
|
return new TypeProjection(Variance.OUT_VARIANCE, commonSupertype(parameterDescriptor.getUpperBounds()));
|
||||||
}
|
}
|
||||||
@@ -230,8 +278,19 @@ public class JetTypeChecker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public boolean isConvertibleTo(Type actual, Type expected) {
|
public boolean isConvertibleTo(Type actual, Type expected) {
|
||||||
// TODO
|
if (isSubtypeOf(actual, expected)) return true;
|
||||||
return isSubtypeOf(actual, expected);
|
if (expected.getConstructor() == JetStandardClasses.getTuple(0).getTypeConstructor()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (actual.getArguments().isEmpty()) {
|
||||||
|
TypeConstructor actualConstructor = actual.getConstructor();
|
||||||
|
TypeConstructor constructor = expected.getConstructor();
|
||||||
|
Set<TypeConstructor> convertibleTo = getConversionMap().get(actualConstructor);
|
||||||
|
if (convertibleTo != null) {
|
||||||
|
return convertibleTo.contains(constructor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isSubtypeOf(Type subtype, Type supertype) {
|
public boolean isSubtypeOf(Type subtype, Type supertype) {
|
||||||
|
|||||||
@@ -170,13 +170,12 @@ public class JetTypeInferrer {
|
|||||||
if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.COLON) {
|
if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.COLON) {
|
||||||
Type actualType = getType(scope, expression.getLeft(), false);
|
Type actualType = getType(scope, expression.getLeft(), false);
|
||||||
Type expectedType = typeResolver.resolveType(scope, expression.getRight());
|
Type expectedType = typeResolver.resolveType(scope, expression.getRight());
|
||||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(actualType, expectedType)) {
|
if (!semanticServices.getTypeChecker().isSubtypeOf(actualType, expectedType)) {
|
||||||
result[0] = expectedType;
|
// TODO
|
||||||
return;
|
semanticServices.getErrorHandler().typeMismatch(expression.getLeft(), expectedType, actualType);
|
||||||
} else {
|
|
||||||
// TODO
|
|
||||||
throw new UnsupportedOperationException("Type mismatch: expected " + expectedType + " but found " + actualType);
|
|
||||||
}
|
}
|
||||||
|
result[0] = expectedType;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
}
|
}
|
||||||
@@ -192,7 +191,7 @@ public class JetTypeInferrer {
|
|||||||
} else {
|
} else {
|
||||||
Type thenType = getType(scope, expression.getThen(), true);
|
Type thenType = getType(scope, expression.getThen(), true);
|
||||||
Type elseType = getType(scope, elseBranch, true);
|
Type elseType = getType(scope, elseBranch, true);
|
||||||
result[0] = JetTypeChecker.INSTANCE.commonSupertype(Arrays.asList(thenType, elseType));
|
result[0] = semanticServices.getTypeChecker().commonSupertype(Arrays.asList(thenType, elseType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -201,7 +200,7 @@ public class JetTypeInferrer {
|
|||||||
// TODO :change scope according to the bound value in the when header
|
// TODO :change scope according to the bound value in the when header
|
||||||
List<Type> expressions = new ArrayList<Type>();
|
List<Type> expressions = new ArrayList<Type>();
|
||||||
collectAllReturnTypes(expression, scope, expressions);
|
collectAllReturnTypes(expression, scope, expressions);
|
||||||
result[0] = JetTypeChecker.INSTANCE.commonSupertype(expressions);
|
result[0] = semanticServices.getTypeChecker().commonSupertype(expressions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -219,7 +218,7 @@ public class JetTypeInferrer {
|
|||||||
types.add(getType(scope, finallyBlock.getFinalExpression(), true));
|
types.add(getType(scope, finallyBlock.getFinalExpression(), true));
|
||||||
}
|
}
|
||||||
types.add(getType(scope, tryBlock, true));
|
types.add(getType(scope, tryBlock, true));
|
||||||
result[0] = JetTypeChecker.INSTANCE.commonSupertype(types);
|
result[0] = semanticServices.getTypeChecker().commonSupertype(types);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -366,8 +365,11 @@ public class JetTypeInferrer {
|
|||||||
JetExpression left = expression.getLeft();
|
JetExpression left = expression.getLeft();
|
||||||
Type leftType = getType(scope, left, false);
|
Type leftType = getType(scope, left, false);
|
||||||
JetExpression right = expression.getRight();
|
JetExpression right = expression.getRight();
|
||||||
|
if (right == null) {
|
||||||
|
return ErrorType.createErrorType("No right argument");
|
||||||
|
}
|
||||||
Type rightType = getType(scope, right, false);
|
Type rightType = getType(scope, right, false);
|
||||||
OverloadDomain overloadDomain = OverloadResolver.INSTANCE.getOverloadDomain(leftType, scope, name);
|
OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(leftType, scope, name);
|
||||||
overloadDomain = wrapForTracing(overloadDomain, operationSign);
|
overloadDomain = wrapForTracing(overloadDomain, operationSign);
|
||||||
FunctionDescriptor functionDescriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<Type>emptyList(), Collections.singletonList(rightType));
|
FunctionDescriptor functionDescriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<Type>emptyList(), Collections.singletonList(rightType));
|
||||||
if (functionDescriptor != null) {
|
if (functionDescriptor != null) {
|
||||||
@@ -409,7 +411,7 @@ public class JetTypeInferrer {
|
|||||||
|
|
||||||
Type receiverType = getType(scope, expression.getReceiverExpression(), false);
|
Type receiverType = getType(scope, expression.getReceiverExpression(), false);
|
||||||
if (receiverType != null) {
|
if (receiverType != null) {
|
||||||
result[0] = OverloadResolver.INSTANCE.getOverloadDomain(receiverType, scope, referenceExpression.getReferencedName());
|
result[0] = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, referenceExpression.getReferencedName());
|
||||||
reference[0] = referenceExpression;
|
reference[0] = referenceExpression;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -420,7 +422,7 @@ public class JetTypeInferrer {
|
|||||||
@Override
|
@Override
|
||||||
public void visitReferenceExpression(JetReferenceExpression expression) {
|
public void visitReferenceExpression(JetReferenceExpression expression) {
|
||||||
// a -- create a hierarchical lookup domain for this.a
|
// a -- create a hierarchical lookup domain for this.a
|
||||||
result[0] = OverloadResolver.INSTANCE.getOverloadDomain(null, scope, expression.getReferencedName());
|
result[0] = semanticServices.getOverloadResolver().getOverloadDomain(null, scope, expression.getReferencedName());
|
||||||
reference[0] = expression;
|
reference[0] = expression;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,8 +18,15 @@ public class TypeUtils {
|
|||||||
return new TypeImpl(type.getAttributes(), type.getConstructor(), true, type.getArguments(), type.getMemberScope());
|
return new TypeImpl(type.getAttributes(), type.getConstructor(), true, type.getArguments(), type.getMemberScope());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Type makeNotNullable(Type type) {
|
||||||
|
if (!type.isNullable()) {
|
||||||
|
return type;
|
||||||
|
}
|
||||||
|
return new TypeImpl(type.getAttributes(), type.getConstructor(), false, type.getArguments(), type.getMemberScope());
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public static Type intersect(Set<Type> types) {
|
public static Type intersect(JetTypeChecker typeChecker, Set<Type> types) {
|
||||||
assert !types.isEmpty();
|
assert !types.isEmpty();
|
||||||
|
|
||||||
if (types.size() == 1) {
|
if (types.size() == 1) {
|
||||||
@@ -31,9 +38,9 @@ public class TypeUtils {
|
|||||||
for (Iterator<Type> iterator = types.iterator(); iterator.hasNext();) {
|
for (Iterator<Type> iterator = types.iterator(); iterator.hasNext();) {
|
||||||
Type type = iterator.next();
|
Type type = iterator.next();
|
||||||
|
|
||||||
if (!canHaveSubtypes(type)) {
|
if (!canHaveSubtypes(typeChecker, type)) {
|
||||||
for (Type other : types) {
|
for (Type other : types) {
|
||||||
if (type != other || !JetTypeChecker.INSTANCE.isSubtypeOf(type, other)) {
|
if (type != other || !typeChecker.isSubtypeOf(type, other)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -58,7 +65,7 @@ public class TypeUtils {
|
|||||||
JetStandardClasses.STUB);
|
JetStandardClasses.STUB);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean canHaveSubtypes(Type type) {
|
private static boolean canHaveSubtypes(JetTypeChecker typeChecker, Type type) {
|
||||||
if (type.isNullable()) {
|
if (type.isNullable()) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -78,17 +85,17 @@ public class TypeUtils {
|
|||||||
case INVARIANT:
|
case INVARIANT:
|
||||||
switch (projectionKind) {
|
switch (projectionKind) {
|
||||||
case INVARIANT:
|
case INVARIANT:
|
||||||
if (lowerThanBound(argument, parameterDescriptor) || canHaveSubtypes(argument)) {
|
if (lowerThanBound(typeChecker, argument, parameterDescriptor) || canHaveSubtypes(typeChecker, argument)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case IN_VARIANCE:
|
case IN_VARIANCE:
|
||||||
if (lowerThanBound(argument, parameterDescriptor)) {
|
if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OUT_VARIANCE:
|
case OUT_VARIANCE:
|
||||||
if (canHaveSubtypes(argument)) {
|
if (canHaveSubtypes(typeChecker, argument)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -96,22 +103,22 @@ public class TypeUtils {
|
|||||||
break;
|
break;
|
||||||
case IN_VARIANCE:
|
case IN_VARIANCE:
|
||||||
if (projectionKind != Variance.OUT_VARIANCE) {
|
if (projectionKind != Variance.OUT_VARIANCE) {
|
||||||
if (lowerThanBound(argument, parameterDescriptor)) {
|
if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (canHaveSubtypes(argument)) {
|
if (canHaveSubtypes(typeChecker, argument)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case OUT_VARIANCE:
|
case OUT_VARIANCE:
|
||||||
if (projectionKind != Variance.IN_VARIANCE) {
|
if (projectionKind != Variance.IN_VARIANCE) {
|
||||||
if (canHaveSubtypes(argument)) {
|
if (canHaveSubtypes(typeChecker, argument)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (lowerThanBound(argument, parameterDescriptor)) {
|
if (lowerThanBound(typeChecker, argument, parameterDescriptor)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -121,9 +128,9 @@ public class TypeUtils {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static boolean lowerThanBound(Type argument, TypeParameterDescriptor parameterDescriptor) {
|
private static boolean lowerThanBound(JetTypeChecker typeChecker, Type argument, TypeParameterDescriptor parameterDescriptor) {
|
||||||
for (Type bound : parameterDescriptor.getUpperBounds()) {
|
for (Type bound : parameterDescriptor.getUpperBounds()) {
|
||||||
if (JetTypeChecker.INSTANCE.isSubtypeOf(argument, bound)) {
|
if (typeChecker.isSubtypeOf(argument, bound)) {
|
||||||
if (!argument.getConstructor().equals(bound.getConstructor())) {
|
if (!argument.getConstructor().equals(bound.getConstructor())) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,4 +33,17 @@ class B : `java::java.lang.Object`Object {
|
|||||||
fun barrr() : `std::Int`Int {
|
fun barrr() : `std::Int`Int {
|
||||||
`foo`foo(new `A`A())
|
`foo`foo(new `A`A())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
~c~fun c(~x~x : `java::java.lang.Number`Number) {
|
||||||
|
`x`x.`java::java.lang.Number.intValue()`intValue()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun <T> t(t : T) : T {
|
||||||
|
`c`c(new java.lang.Integer(1))
|
||||||
|
System.out.`java::java.io.PrintStream.print(Object)`print(t)
|
||||||
|
System.out.`java::java.io.PrintStream.print(char[])`print(null : Array<Char>?)
|
||||||
|
System.out.`java::java.io.PrintStream.print(Object)`print(null : Object?)
|
||||||
|
System.out.`java::java.io.PrintStream.print(Int)`print(1)
|
||||||
|
System.out.`java::java.io.PrintStream.print(Double)`print(1.0)
|
||||||
|
}
|
||||||
|
|||||||
@@ -36,18 +36,25 @@ public class JetResolveTest extends ExtensibleResolveTestCase {
|
|||||||
nameToDescriptor.put("std::Array.set(Int, Int)", descriptorForSet.getOriginal());
|
nameToDescriptor.put("std::Array.set(Int, Int)", descriptorForSet.getOriginal());
|
||||||
|
|
||||||
Map<String,PsiElement> nameToDeclaration = new HashMap<String, PsiElement>();
|
Map<String,PsiElement> nameToDeclaration = new HashMap<String, PsiElement>();
|
||||||
nameToDeclaration.put("java::java.util.Collections.emptyList()", findMethod(findClass("java.util.Collections"), "emptyList"));
|
PsiClass java_util_Collections = findClass("java.util.Collections");
|
||||||
nameToDeclaration.put("java::java.util.Collections", findClass("java.util.Collections"));
|
nameToDeclaration.put("java::java.util.Collections.emptyList()", findMethod(java_util_Collections, "emptyList"));
|
||||||
|
nameToDeclaration.put("java::java.util.Collections", java_util_Collections);
|
||||||
nameToDeclaration.put("java::java.util.List", findClass("java.util.List"));
|
nameToDeclaration.put("java::java.util.List", findClass("java.util.List"));
|
||||||
nameToDeclaration.put("java::java", findPackage("java"));
|
nameToDeclaration.put("java::java", findPackage("java"));
|
||||||
nameToDeclaration.put("java::java.util", findPackage("java.util"));
|
nameToDeclaration.put("java::java.util", findPackage("java.util"));
|
||||||
nameToDeclaration.put("java::java.lang", findPackage("java.lang"));
|
nameToDeclaration.put("java::java.lang", findPackage("java.lang"));
|
||||||
nameToDeclaration.put("java::java.lang.Object", findClass("java.lang.Object"));
|
nameToDeclaration.put("java::java.lang.Object", findClass("java.lang.Object"));
|
||||||
nameToDeclaration.put("java::java.lang.System", findClass("java.lang.System"));
|
PsiClass java_lang_System = findClass("java.lang.System");
|
||||||
|
nameToDeclaration.put("java::java.lang.System", java_lang_System);
|
||||||
PsiMethod[] methods = findClass("java.io.PrintStream").findMethodsByName("print", true);
|
PsiMethod[] methods = findClass("java.io.PrintStream").findMethodsByName("print", true);
|
||||||
nameToDeclaration.put("java::java.io.PrintStream.print(Object)", methods[8]);
|
nameToDeclaration.put("java::java.io.PrintStream.print(Object)", methods[8]);
|
||||||
nameToDeclaration.put("java::java.io.PrintStream.print(Int)", methods[2]);
|
nameToDeclaration.put("java::java.io.PrintStream.print(Int)", methods[2]);
|
||||||
nameToDeclaration.put("java::java.lang.System.out", findClass("java.lang.System").findFieldByName("out", true));
|
nameToDeclaration.put("java::java.io.PrintStream.print(char[])", methods[6]);
|
||||||
|
nameToDeclaration.put("java::java.io.PrintStream.print(Double)", methods[5]);
|
||||||
|
nameToDeclaration.put("java::java.lang.System.out", java_lang_System.findFieldByName("out", true));
|
||||||
|
PsiClass java_lang_Number = findClass("java.lang.Number");
|
||||||
|
nameToDeclaration.put("java::java.lang.Number", java_lang_Number);
|
||||||
|
nameToDeclaration.put("java::java.lang.Number.intValue()", java_lang_Number.findMethodsByName("intValue", true)[0]);
|
||||||
|
|
||||||
return new ExpectedResolveData(nameToDescriptor, nameToDeclaration);
|
return new ExpectedResolveData(nameToDescriptor, nameToDeclaration);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -342,7 +342,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
|||||||
assertType("new Functions<String>().f()", "Unit");
|
assertType("new Functions<String>().f()", "Unit");
|
||||||
assertType("new Functions<String>().f(1)", "Int");
|
assertType("new Functions<String>().f(1)", "Int");
|
||||||
assertType("new Functions<String>().f(1d)", (String) null);
|
assertType("new Functions<String>().f(1d)", (String) null);
|
||||||
assertType("new Functions<Double>().f(())", "Double");
|
assertType("new Functions<Double>().f((1, 1))", "Double");
|
||||||
assertType("new Functions<Double>().f(1d)", "Any");
|
assertType("new Functions<Double>().f(1d)", "Any");
|
||||||
assertType("new Functions<Byte>().f<String>(\"\")", "Byte");
|
assertType("new Functions<Byte>().f<String>(\"\")", "Byte");
|
||||||
assertType("new Functions<Byte>().f<String>(1)", (String) null);
|
assertType("new Functions<Byte>().f<String>(1)", (String) null);
|
||||||
@@ -418,14 +418,14 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
|||||||
for (String type : types) {
|
for (String type : types) {
|
||||||
subtypes.add(makeType(type));
|
subtypes.add(makeType(type));
|
||||||
}
|
}
|
||||||
Type result = JetTypeChecker.INSTANCE.commonSupertype(subtypes);
|
Type result = semanticServices.getTypeChecker().commonSupertype(subtypes);
|
||||||
assertTrue(result + " != " + expected, TypeImpl.equalTypes(result, makeType(expected)));
|
assertTrue(result + " != " + expected, TypeImpl.equalTypes(result, makeType(expected)));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertSubtypingRelation(String type1, String type2, boolean expected) {
|
private void assertSubtypingRelation(String type1, String type2, boolean expected) {
|
||||||
Type typeNode1 = makeType(type1);
|
Type typeNode1 = makeType(type1);
|
||||||
Type typeNode2 = makeType(type2);
|
Type typeNode2 = makeType(type2);
|
||||||
boolean result = JetTypeChecker.INSTANCE.isSubtypeOf(
|
boolean result = semanticServices.getTypeChecker().isSubtypeOf(
|
||||||
typeNode1,
|
typeNode1,
|
||||||
typeNode2);
|
typeNode2);
|
||||||
String modifier = expected ? "not " : "";
|
String modifier = expected ? "not " : "";
|
||||||
@@ -436,14 +436,14 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
|||||||
JetExpression jetExpression = JetChangeUtil.createExpression(getProject(), expression);
|
JetExpression jetExpression = JetChangeUtil.createExpression(getProject(), expression);
|
||||||
assertTrue(
|
assertTrue(
|
||||||
expression + " must be convertible to " + type,
|
expression + " must be convertible to " + type,
|
||||||
JetTypeChecker.INSTANCE.isConvertibleTo(jetExpression, type));
|
semanticServices.getTypeChecker().isConvertibleTo(jetExpression, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertNotConvertibleTo(String expression, Type type) {
|
private void assertNotConvertibleTo(String expression, Type type) {
|
||||||
JetExpression jetExpression = JetChangeUtil.createExpression(getProject(), expression);
|
JetExpression jetExpression = JetChangeUtil.createExpression(getProject(), expression);
|
||||||
assertFalse(
|
assertFalse(
|
||||||
expression + " must not be convertible to " + type,
|
expression + " must not be convertible to " + type,
|
||||||
JetTypeChecker.INSTANCE.isConvertibleTo(jetExpression, type));
|
semanticServices.getTypeChecker().isConvertibleTo(jetExpression, type));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertType(String expression, Type expectedType) {
|
private void assertType(String expression, Type expectedType) {
|
||||||
@@ -509,7 +509,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
|||||||
"fun f() : Unit {} " +
|
"fun f() : Unit {} " +
|
||||||
"fun f(a : Int) : Int {} " +
|
"fun f(a : Int) : Int {} " +
|
||||||
"fun f(a : T) : Any {} " +
|
"fun f(a : T) : Any {} " +
|
||||||
"fun f(a : Unit) : T {} " +
|
"fun f(a : (Int, Int)) : T {} " +
|
||||||
"fun f<E>(a : E) : T {} " +
|
"fun f<E>(a : E) : T {} " +
|
||||||
"}"
|
"}"
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user