BindingContext remembers types
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user