diff --git a/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java b/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java index d040a5115bc..0387abc4ab5 100644 --- a/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java +++ b/idea/src/org/jetbrains/jet/lang/JetSemanticServices.java @@ -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) { diff --git a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java index 6a6903d35ee..ad2d9d71a72 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/BindingContext.java @@ -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); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java index 86cb4eaec1e..7311d51d3cf 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ClassDescriptorResolver.java @@ -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.singleton(JetStandardClasses.getAnyType()) - : Collections.singleton(TypeResolver.INSTANCE.resolveType(extensibleScope, extendsBound)) + : Collections.singleton(typeResolver.resolveType(extensibleScope, extendsBound)) ); extensibleScope.addTypeParameterDescriptor(typeParameterDescriptor); return typeParameterDescriptor; } - public static Collection resolveTypes(WritableScope extensibleScope, List delegationSpecifiers) { + public Collection resolveTypes(WritableScope extensibleScope, List 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( diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 9d01900976a..95a3249a39d 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -20,9 +20,27 @@ public class TopDownAnalyzer { private Map resolutionResults = new HashMap(); private final JetSemanticServices semanticServices; + private Map types = new HashMap(); + 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 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 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); } diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 8b7a2d413f2..392a2a8d09a 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -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 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 attributes, JetTypeElement typeElement, final boolean nullable) { diff --git a/idea/src/org/jetbrains/jet/lang/types/BindingTrace.java b/idea/src/org/jetbrains/jet/lang/types/BindingTrace.java index 9424815ee84..2026c5dd9ef 100644 --- a/idea/src/org/jetbrains/jet/lang/types/BindingTrace.java +++ b/idea/src/org/jetbrains/jet/lang/types/BindingTrace.java @@ -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); } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index f121c6e5683..fee9a913d99 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -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 supertypes = thisType.getConstructor().getSupertypes(); Map 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 types = new ArrayList(); 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 valueArgumentTypes = new ArrayList(); @@ -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); diff --git a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java index 1c16bea3266..ec3eeb240f6 100644 --- a/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java +++ b/idea/tests/org/jetbrains/jet/resolve/JetResolveTest.java @@ -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); diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 9e0123d2d20..601293090eb 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -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); }