BindingContext remembers types

This commit is contained in:
Andrey Breslav
2011-02-28 20:52:42 +03:00
parent 304644db1b
commit 8454058b21
9 changed files with 84 additions and 34 deletions
@@ -11,12 +11,10 @@ import org.jetbrains.jet.lang.types.JetTypeInferrer;
public class JetSemanticServices {
private final JetStandardLibrary standardLibrary;
private final JetTypeInferrer typeInferrer;
private final ClassDescriptorResolver classDescriptorResolver;
public JetSemanticServices(JetStandardLibrary standardLibrary) {
this.standardLibrary = standardLibrary;
this.typeInferrer = new JetTypeInferrer(BindingTrace.DUMMY, this);
this.classDescriptorResolver = new ClassDescriptorResolver(this);
}
public JetStandardLibrary getStandardLibrary() {
@@ -27,8 +25,8 @@ public class JetSemanticServices {
return typeInferrer;
}
public ClassDescriptorResolver getClassDescriptorResolver() {
return classDescriptorResolver;
public ClassDescriptorResolver getClassDescriptorResolver(BindingTrace trace) {
return new ClassDescriptorResolver(this, trace);
}
public JetTypeInferrer getTypeInferrer(BindingTrace trace) {
@@ -12,6 +12,7 @@ public interface BindingContext {
FunctionDescriptor getFunctionDescriptor(JetFunction declaration);
PropertyDescriptor getPropertyDescriptor(JetProperty declaration);
Type getType(JetTypeReference typeReference);
Type getExpressionType(JetExpression expression);
DeclarationDescriptor resolve(JetReferenceExpression referenceExpression);
@@ -15,9 +15,11 @@ import java.util.*;
public class ClassDescriptorResolver {
private final JetSemanticServices semanticServices;
private final TypeResolver typeResolver;
public ClassDescriptorResolver(JetSemanticServices semanticServices) {
public ClassDescriptorResolver(JetSemanticServices semanticServices, BindingTrace trace) {
this.semanticServices = semanticServices;
this.typeResolver = new TypeResolver(trace);
}
@Nullable
@@ -124,7 +126,7 @@ public class ClassDescriptorResolver {
Type returnType;
JetTypeReference returnTypeRef = function.getReturnTypeRef();
if (returnTypeRef != null) {
returnType = TypeResolver.INSTANCE.resolveType(parameterScope, returnTypeRef);
returnType = typeResolver.resolveType(parameterScope, returnTypeRef);
// TODO : CHeck type of body
} else {
JetExpression bodyExpression = function.getBodyExpression();
@@ -155,7 +157,7 @@ public class ClassDescriptorResolver {
valueParameter,
AttributeResolver.INSTANCE.resolveAttributes(valueParameter.getModifierList()),
valueParameter.getName(),
TypeResolver.INSTANCE.resolveType(parameterScope, typeReference),
typeResolver.resolveType(parameterScope, typeReference),
valueParameter.getDefaultValue() != null,
false // TODO : varargs
);
@@ -177,7 +179,7 @@ public class ClassDescriptorResolver {
return result;
}
private static TypeParameterDescriptor resolveTypeParameter(WritableScope extensibleScope, JetTypeParameter typeParameter) {
private TypeParameterDescriptor resolveTypeParameter(WritableScope extensibleScope, JetTypeParameter typeParameter) {
JetTypeReference extendsBound = typeParameter.getExtendsBound();
TypeParameterDescriptor typeParameterDescriptor = new TypeParameterDescriptor(
typeParameter,
@@ -186,13 +188,13 @@ public class ClassDescriptorResolver {
typeParameter.getName(),
extendsBound == null
? Collections.<Type>singleton(JetStandardClasses.getAnyType())
: Collections.singleton(TypeResolver.INSTANCE.resolveType(extensibleScope, extendsBound))
: Collections.singleton(typeResolver.resolveType(extensibleScope, extendsBound))
);
extensibleScope.addTypeParameterDescriptor(typeParameterDescriptor);
return typeParameterDescriptor;
}
public static Collection<? extends Type> resolveTypes(WritableScope extensibleScope, List<JetDelegationSpecifier> delegationSpecifiers) {
public Collection<? extends Type> resolveTypes(WritableScope extensibleScope, List<JetDelegationSpecifier> delegationSpecifiers) {
if (delegationSpecifiers.isEmpty()) {
return Collections.emptyList();
}
@@ -203,9 +205,9 @@ public class ClassDescriptorResolver {
return result;
}
private static Type resolveType(JetScope scope, JetDelegationSpecifier delegationSpecifier) {
private Type resolveType(JetScope scope, JetDelegationSpecifier delegationSpecifier) {
JetTypeReference typeReference = delegationSpecifier.getTypeReference(); // TODO : make it not null
return TypeResolver.INSTANCE.resolveType(scope, typeReference);
return typeResolver.resolveType(scope, typeReference);
}
@NotNull
@@ -214,7 +216,7 @@ public class ClassDescriptorResolver {
parameter,
AttributeResolver.INSTANCE.resolveAttributes(parameter.getModifierList()),
parameter.getName(),
TypeResolver.INSTANCE.resolveType(scope, parameter.getTypeReference()));
typeResolver.resolveType(scope, parameter.getTypeReference()));
}
public PropertyDescriptor resolvePropertyDescriptor(@NotNull JetScope scope, JetProperty property) {
@@ -228,7 +230,7 @@ public class ClassDescriptorResolver {
// TODO : ??? Fix-point here: what if we have something like "val a = foo {a.bar()}"
type = semanticServices.getTypeInferrer().getType(scope, initializer, false);
} else {
type = TypeResolver.INSTANCE.resolveType(scope, propertyTypeRef);
type = typeResolver.resolveType(scope, propertyTypeRef);
}
return new PropertyDescriptorImpl(
@@ -20,9 +20,27 @@ public class TopDownAnalyzer {
private Map<JetReferenceExpression,DeclarationDescriptor> resolutionResults = new HashMap<JetReferenceExpression, DeclarationDescriptor>();
private final JetSemanticServices semanticServices;
private Map<JetTypeReference, Type> types = new HashMap<JetTypeReference, Type>();
private final ClassDescriptorResolver classDescriptorResolver;
public TopDownAnalyzer(JetSemanticServices semanticServices) {
this.semanticServices = semanticServices;
this.classDescriptorResolver = new ClassDescriptorResolver(semanticServices, new BindingTrace() {
@Override
public void recordExpressionType(JetExpression expression, Type type) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public void recordResolutionResult(JetReferenceExpression expression, DeclarationDescriptor descriptor) {
throw new UnsupportedOperationException(); // TODO
}
@Override
public void recordTypeResoltion(JetTypeReference typeReference, Type type) {
types.put(typeReference, type);
}
});
}
public BindingContext process(@NotNull JetScope outerScope, @NotNull List<JetDeclaration> declarations) {
@@ -53,6 +71,11 @@ public class TopDownAnalyzer {
return properties.get(declaration);
}
@Override
public Type getType(JetTypeReference typeReference) {
return types.get(typeReference);
}
@Override
public Type getExpressionType(JetExpression expression) {
return expressionTypes.get(expression);
@@ -119,7 +142,7 @@ public class TopDownAnalyzer {
for (Map.Entry<JetClass, MutableClassDescriptor> entry : classes.entrySet()) {
JetClass jetClass = entry.getKey();
MutableClassDescriptor descriptor = entry.getValue();
semanticServices.getClassDescriptorResolver().resolveMutableClassDescriptor(declaringScopes.get(jetClass), jetClass, descriptor);
classDescriptorResolver.resolveMutableClassDescriptor(declaringScopes.get(jetClass), jetClass, descriptor);
}
}
@@ -165,14 +188,14 @@ public class TopDownAnalyzer {
private void processFunction(@NotNull WritableScope declaringScope, JetFunction function) {
declaringScopes.put(function, declaringScope);
FunctionDescriptor descriptor = semanticServices.getClassDescriptorResolver().resolveFunctionDescriptor(declaringScope, function);
FunctionDescriptor descriptor = classDescriptorResolver.resolveFunctionDescriptor(declaringScope, function);
declaringScope.addFunctionDescriptor(descriptor);
functions.put(function, descriptor);
}
private void processProperty(WritableScope declaringScope, JetProperty property) {
declaringScopes.put(property, declaringScope);
PropertyDescriptor descriptor = semanticServices.getClassDescriptorResolver().resolvePropertyDescriptor(declaringScope, property);
PropertyDescriptor descriptor = classDescriptorResolver.resolvePropertyDescriptor(declaringScope, property);
declaringScope.addPropertyDescriptor(descriptor);
properties.put(property, descriptor);
}
@@ -217,6 +240,11 @@ public class TopDownAnalyzer {
public void recordResolutionResult(JetReferenceExpression expression, DeclarationDescriptor descriptor) {
resolutionResults.put(expression, descriptor);
}
@Override
public void recordTypeResoltion(JetTypeReference typeReference, Type type) {
types.put(typeReference, type);
}
}).getType(scope, expression, preferBlock);
}
@@ -15,17 +15,20 @@ import java.util.Set;
*/
public class TypeResolver {
@NotNull
public static final TypeResolver INSTANCE = new TypeResolver();
private final BindingTrace trace;
private TypeResolver() {}
public TypeResolver(BindingTrace trace) {
this.trace = trace;
}
@NotNull
public Type resolveType(@NotNull final JetScope scope, @NotNull final JetTypeReference typeReference) {
final List<Attribute> attributes = AttributeResolver.INSTANCE.resolveAttributes(typeReference.getAttributes());
JetTypeElement typeElement = typeReference.getTypeElement();
return resolveTypeElement(scope, attributes, typeElement, false);
Type type = resolveTypeElement(scope, attributes, typeElement, false);
trace.recordTypeResoltion(typeReference, type);
return type;
}
private Type resolveTypeElement(final JetScope scope, final List<Attribute> attributes, JetTypeElement typeElement, final boolean nullable) {
@@ -2,6 +2,7 @@ package org.jetbrains.jet.lang.types;
import org.jetbrains.jet.lang.psi.JetExpression;
import org.jetbrains.jet.lang.psi.JetReferenceExpression;
import org.jetbrains.jet.lang.psi.JetTypeReference;
/**
* @author abreslav
@@ -16,9 +17,16 @@ public interface BindingTrace {
public void recordResolutionResult(JetReferenceExpression expression, DeclarationDescriptor descriptor) {
}
@Override
public void recordTypeResoltion(JetTypeReference typeReference, Type type) {
}
};
void recordExpressionType(JetExpression expression, Type type);
void recordResolutionResult(JetReferenceExpression expression, DeclarationDescriptor descriptor);
void recordTypeResoltion(JetTypeReference typeReference, Type type);
}
@@ -18,10 +18,14 @@ public class JetTypeInferrer {
private final BindingTrace trace;
private final JetSemanticServices semanticServices;
private final TypeResolver typeResolver;
private final ClassDescriptorResolver classDescriptorResolver;
public JetTypeInferrer(BindingTrace trace, JetSemanticServices semanticServices) {
this.trace = trace;
this.semanticServices = semanticServices;
this.typeResolver = new TypeResolver(trace);
this.classDescriptorResolver = new ClassDescriptorResolver(semanticServices, trace);
}
/*
@@ -64,7 +68,7 @@ public class JetTypeInferrer {
JetTypeReference receiverTypeRef = expression.getReceiverTypeRef();
final Type receiverType;
if (receiverTypeRef != null) {
receiverType = TypeResolver.INSTANCE.resolveType(scope, receiverTypeRef);
receiverType = typeResolver.resolveType(scope, receiverTypeRef);
} else {
receiverType = scope.getThisType();
}
@@ -77,13 +81,13 @@ public class JetTypeInferrer {
if (typeReference == null) {
throw new UnsupportedOperationException("Type inference for parameters is not implemented yet");
}
PropertyDescriptor propertyDescriptor = semanticServices.getClassDescriptorResolver().resolvePropertyDescriptor(scope, parameter);
PropertyDescriptor propertyDescriptor = classDescriptorResolver.resolvePropertyDescriptor(scope, parameter);
parameterDescriptors.put(parameter.getName(), propertyDescriptor);
parameterTypes.add(propertyDescriptor.getType());
}
Type returnType;
if (returnTypeRef != null) {
returnType = TypeResolver.INSTANCE.resolveType(scope, returnTypeRef);
returnType = typeResolver.resolveType(scope, returnTypeRef);
} else {
WritableScope writableScope = new WritableScope(scope);
for (PropertyDescriptor propertyDescriptor : parameterDescriptors.values()) {
@@ -159,7 +163,7 @@ public class JetTypeInferrer {
public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) {
if (expression.getOperationSign() == JetTokens.COLON) {
Type actualType = getType(scope, expression.getLeft(), false);
Type expectedType = TypeResolver.INSTANCE.resolveType(scope, expression.getRight());
Type expectedType = typeResolver.resolveType(scope, expression.getRight());
if (JetTypeChecker.INSTANCE.isSubtypeOf(actualType, expectedType)) {
result[0] = expectedType;
return;
@@ -231,7 +235,7 @@ public class JetTypeInferrer {
if (superTypeQualifier != null) {
// This cast must be safe (assuming the PSI doesn't contain errors)
JetUserType typeElement = (JetUserType) superTypeQualifier.getTypeElement();
ClassDescriptor superclass = TypeResolver.INSTANCE.resolveClass(scope, typeElement);
ClassDescriptor superclass = typeResolver.resolveClass(scope, typeElement);
Collection<? extends Type> supertypes = thisType.getConstructor().getSupertypes();
Map<TypeConstructor, TypeProjection> substitutionContext = TypeSubstitutor.INSTANCE.getSubstitutionContext(thisType);
for (Type declaredSupertype : supertypes) {
@@ -260,7 +264,7 @@ public class JetTypeInferrer {
public void visitNewExpression(JetNewExpression expression) {
// TODO : type argument inference
JetTypeReference typeReference = expression.getTypeReference();
result[0] = TypeResolver.INSTANCE.resolveType(scope, typeReference);
result[0] = typeResolver.resolveType(scope, typeReference);
}
@Override
@@ -314,7 +318,7 @@ public class JetTypeInferrer {
List<Type> types = new ArrayList<Type>();
for (JetTypeProjection projection : typeArguments) {
// TODO : check that there's no projection
types.add(TypeResolver.INSTANCE.resolveType(scope, projection.getTypeReference()));
types.add(typeResolver.resolveType(scope, projection.getTypeReference()));
}
List<Type> valueArgumentTypes = new ArrayList<Type>();
@@ -414,7 +418,7 @@ public class JetTypeInferrer {
// TODO: consider other declarations
if (statement instanceof JetProperty) {
JetProperty property = (JetProperty) statement;
scope.addPropertyDescriptor(semanticServices.getClassDescriptorResolver().resolvePropertyDescriptor(scope, property));
scope.addPropertyDescriptor(classDescriptorResolver.resolvePropertyDescriptor(scope, property));
}
}
JetElement lastElement = block.get(block.size() - 1);
@@ -95,6 +95,10 @@ public class JetResolveTest extends LightDaemonAnalyzerTestCase {
JetProperty aDecl = (JetProperty) classADecl.getDeclarations().get(5);
PropertyDescriptor mustBeA = bindingContext.getPropertyDescriptor(aDecl);
assertSame(a, mustBeA);
JetTypeReference propertyTypeRef = aDecl.getPropertyTypeRef();
Type type = bindingContext.getType(propertyTypeRef);
assertEquals(library.getIntType(), type);
}
JetClass classCDecl = (JetClass) declarations.get(1);
@@ -23,9 +23,10 @@ import java.util.Map;
*/
public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
private JetStandardLibrary library;
private JetStandardLibrary library;
private JetSemanticServices semanticServices;
private ClassDefinitions classDefinitions;
private ClassDefinitions classDefinitions;
private ClassDescriptorResolver classDescriptorResolver;
@Override
public void setUp() throws Exception {
@@ -33,6 +34,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
library = new JetStandardLibrary(getProject());
semanticServices = new JetSemanticServices(library);
classDefinitions = new ClassDefinitions();
classDescriptorResolver = semanticServices.getClassDescriptorResolver(BindingTrace.DUMMY);
}
@Override
@@ -486,7 +488,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
}
private static Type makeType(JetScope scope, String typeStr) {
return TypeResolver.INSTANCE.resolveType(scope, JetChangeUtil.createType(getProject(), typeStr));
return new TypeResolver(BindingTrace.DUMMY).resolveType(scope, JetChangeUtil.createType(getProject(), typeStr));
}
private class ClassDefinitions {
@@ -523,7 +525,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
if (CLASSES.isEmpty()) {
for (String classDeclaration : CLASS_DECLARATIONS) {
JetClass classElement = JetChangeUtil.createClass(getProject(), classDeclaration);
ClassDescriptor classDescriptor = semanticServices.getClassDescriptorResolver().resolveClassDescriptor(this, classElement);
ClassDescriptor classDescriptor = classDescriptorResolver.resolveClassDescriptor(this, classElement);
CLASSES.put(classDescriptor.getName(), classDescriptor);
}
}
@@ -539,7 +541,7 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
public FunctionGroup getFunctionGroup(@NotNull String name) {
WritableFunctionGroup writableFunctionGroup = new WritableFunctionGroup(name);
for (String funDecl : FUNCTION_DECLARATIONS) {
FunctionDescriptor functionDescriptor = semanticServices.getClassDescriptorResolver().resolveFunctionDescriptor(this, JetChangeUtil.createFunction(getProject(), funDecl));
FunctionDescriptor functionDescriptor = classDescriptorResolver.resolveFunctionDescriptor(this, JetChangeUtil.createFunction(getProject(), funDecl));
if (name.equals(functionDescriptor.getName())) {
writableFunctionGroup.addFunction(functionDescriptor);
}