From 0afddb4d9eeab10bbbd0b026eeceabbff18cab1e Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 20 May 2011 18:06:59 +0400 Subject: [PATCH] Resolve for receiver-properties (generic arguments are not supported) --- .../jet/lang/resolve/ScopeWithReceiver.java | 18 ++++++++++++++++-- .../jet/lang/resolve/TopDownAnalyzer.java | 16 ++++++++++++++-- .../jet/lang/types/JetTypeInferrer.java | 5 +++++ idea/testData/resolve/ExtensionFunctions.jet | 12 +++++++++++- 4 files changed, 46 insertions(+), 5 deletions(-) diff --git a/idea/src/org/jetbrains/jet/lang/resolve/ScopeWithReceiver.java b/idea/src/org/jetbrains/jet/lang/resolve/ScopeWithReceiver.java index e3edd82e091..b3d67fdeb41 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/ScopeWithReceiver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/ScopeWithReceiver.java @@ -36,6 +36,7 @@ public class ScopeWithReceiver extends JetScopeImpl { if (functionReceiverType == null) { return false; } + // TODO : in case of inferred type arguments, substitute the receiver type first return typeChecker.isSubtypeOf(receiverTypeScope.getThisType(), functionReceiverType); } }); @@ -50,8 +51,21 @@ public class ScopeWithReceiver extends JetScopeImpl { @Override public VariableDescriptor getVariable(@NotNull String name) { - return receiverTypeScope.getVariable(name); - // TODO : extension properties + VariableDescriptor variable = receiverTypeScope.getVariable(name); + if (variable != null) { + return variable; + } + variable = outerScope.getVariable(name); + if (variable instanceof PropertyDescriptor) { + PropertyDescriptor propertyDescriptor = (PropertyDescriptor) variable; + JetType receiverType = propertyDescriptor.getReceiverType(); + // TODO : in case of type arguments, substitute the receiver type first + if (receiverType != null + && typeChecker.isSubtypeOf(receiverTypeScope.getThisType(), receiverType)) { + return variable; + } + } + return null; } @Override diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 486677fcda6..4200d1378ff 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -583,10 +583,22 @@ public class TopDownAnalyzer { } } + private JetScope getPropertyDeclarationInnerScope(@NotNull JetScope outerScope, @NotNull PropertyDescriptor propertyDescriptor) { + WritableScopeImpl result = new WritableScopeImpl(outerScope, propertyDescriptor, trace.getErrorHandler()); + for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParemeters()) { + result.addTypeParameterDescriptor(typeParameterDescriptor); + } + JetType receiverType = propertyDescriptor.getReceiverType(); + if (receiverType != null) { + result.setThisType(receiverType); + } + return result; + } + private void resolvePropertyAccessors(JetProperty property, PropertyDescriptor propertyDescriptor, JetScope declaringScope) { BindingTraceAdapter fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor); - WritableScope accessorScope = new WritableScopeImpl(declaringScope, declaringScope.getContainingDeclaration(), trace.getErrorHandler()); + WritableScope accessorScope = new WritableScopeImpl(getPropertyDeclarationInnerScope(declaringScope, propertyDescriptor), declaringScope.getContainingDeclaration(), trace.getErrorHandler()); accessorScope.addPropertyDescriptorByFieldName("$" + propertyDescriptor.getName(), propertyDescriptor); JetPropertyAccessor getter = property.getGetter(); @@ -628,7 +640,7 @@ public class TopDownAnalyzer { private void resolvePropertyInitializer(JetProperty property, PropertyDescriptor propertyDescriptor, JetExpression initializer, JetScope scope) { JetFlowInformationProvider flowInformationProvider = classDescriptorResolver.computeFlowData(property, initializer); // TODO : flow JET-15 JetTypeInferrer typeInferrer = semanticServices.getTypeInferrer(traceForConstructors, flowInformationProvider); - JetType type = typeInferrer.getType(scope, initializer, false); + JetType type = typeInferrer.getType(getPropertyDeclarationInnerScope(scope, propertyDescriptor), initializer, false); JetType expectedType; PropertySetterDescriptor setter = propertyDescriptor.getSetter(); diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 2e830f0600d..a8d1fe84111 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -1730,6 +1730,11 @@ public class JetTypeInferrer { @Override public void visitProperty(JetProperty property) { + JetTypeReference receiverTypeRef = property.getReceiverTypeRef(); + if (receiverTypeRef != null) { + trace.getErrorHandler().genericError(receiverTypeRef.getNode(), "Local receiver-properties are not allowed"); + } + JetPropertyAccessor getter = property.getGetter(); if (getter != null) { trace.getErrorHandler().genericError(getter.getNode(), "Local variables are not allowed to have getters"); diff --git a/idea/testData/resolve/ExtensionFunctions.jet b/idea/testData/resolve/ExtensionFunctions.jet index e6e86872ad5..0634aa0d053 100644 --- a/idea/testData/resolve/ExtensionFunctions.jet +++ b/idea/testData/resolve/ExtensionFunctions.jet @@ -18,4 +18,14 @@ fun <~T~T, ~E~E> `T`T.foo(x : `E`E, y : `A`A) : `T`T { 1 } -~-~fun T.minus(t : T) : Int = 1 \ No newline at end of file +~-~fun T.minus(t : T) : Int = 1 + +fun test() { + val y = 1.`abs`abs +} +~abs~val Int.abs : Int + get() = if (this`:std::Int` > 0) this else -this`:std::Int`; + +val <~TT~T> `TT`T.foo : `TT`T + +fun Int.foo() = this`:std::Int` \ No newline at end of file