From 447114f063bbea66ff1802d16f8ff5247ac00e36 Mon Sep 17 00:00:00 2001 From: Evgeny Gerashchenko Date: Thu, 9 Feb 2012 21:45:43 +0400 Subject: [PATCH] Added utility method to check if variable is iterable. --- .../ControlStructureTypingVisitor.java | 8 +++--- .../expressions/ExpressionTypingUtils.java | 26 +++++++++++++++++++ 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java index 3e7e260c9a2..7b2f20bcb68 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ControlStructureTypingVisitor.java @@ -264,7 +264,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { } @Nullable - private JetType checkIterableConvention(@NotNull ExpressionReceiver loopRange, ExpressionTypingContext context) { + /*package*/ static JetType checkIterableConvention(@NotNull ExpressionReceiver loopRange, ExpressionTypingContext context) { JetExpression loopRangeExpression = loopRange.getExpression(); // Make a fake call loopRange.iterator(), and try to resolve it @@ -328,7 +328,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { return null; } - private OverloadResolutionResults resolveFakeCall(ExpressionReceiver receiver, ExpressionTypingContext context, String name) { + private static OverloadResolutionResults resolveFakeCall(ExpressionReceiver receiver, ExpressionTypingContext context, String name) { JetReferenceExpression fake = JetPsiFactory.createSimpleName(context.getProject(), "fake"); BindingTrace fakeTrace = new BindingTraceContext(); Call call = CallMaker.makeCall(fake, receiver, null, fake, Collections.emptyList()); @@ -336,7 +336,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { } @Nullable - private FunctionDescriptor checkHasNextFunctionSupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, ExpressionTypingContext context) { + private static FunctionDescriptor checkHasNextFunctionSupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, ExpressionTypingContext context) { OverloadResolutionResults hasNextResolutionResults = context.resolveExactSignature(new TransientReceiver(iteratorType), "hasNext", Collections.emptyList()); if (hasNextResolutionResults.isAmbiguity()) { context.trace.report(HAS_NEXT_FUNCTION_AMBIGUITY.on(loopRange)); @@ -353,7 +353,7 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { } @Nullable - private VariableDescriptor checkHasNextPropertySupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, ExpressionTypingContext context) { + private static VariableDescriptor checkHasNextPropertySupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, ExpressionTypingContext context) { VariableDescriptor hasNextProperty = DescriptorUtils.filterNonExtensionProperty(iteratorType.getMemberScope().getProperties("hasNext")); if (hasNextProperty == null) { return null; diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java index ced28ae91e2..ce937e59f51 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingUtils.java @@ -11,16 +11,24 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.JetExpression; +import org.jetbrains.jet.lang.psi.JetPattern; import org.jetbrains.jet.lang.psi.JetPsiFactory; import org.jetbrains.jet.lang.psi.JetSimpleNameExpression; import org.jetbrains.jet.lang.resolve.BindingContextUtils; import org.jetbrains.jet.lang.resolve.BindingTrace; +import org.jetbrains.jet.lang.resolve.BindingTraceContext; import org.jetbrains.jet.lang.resolve.TraceBasedRedeclarationHandler; +import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; +import org.jetbrains.jet.lang.resolve.scopes.JetScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScope; import org.jetbrains.jet.lang.resolve.scopes.WritableScopeImpl; import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver; import org.jetbrains.jet.lang.types.JetStandardClasses; import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.lang.types.TypeUtils; + +import java.util.HashMap; +import java.util.List; import static org.jetbrains.jet.lang.diagnostics.Errors.RESULT_TYPE_MISMATCH; import static org.jetbrains.jet.lang.resolve.BindingContext.*; @@ -126,4 +134,22 @@ public class ExpressionTypingUtils { trace.record(EXPRESSION_TYPE, expression, type); return expression; } + + public static boolean isVariableIterable(@NotNull Project project, @NotNull VariableDescriptor variableDescriptor, @NotNull JetScope scope) { + JetExpression expression = JetPsiFactory.createExpression(project, "fake"); + ExpressionReceiver expressionReceiver = new ExpressionReceiver(expression, variableDescriptor.getOutType()); + ExpressionTypingContext context = ExpressionTypingContext.newContext( + JetSemanticServices.createSemanticServices(project), + new HashMap(), + new HashMap>(), + new LabelResolver(), + new BindingTraceContext(), + scope, + DataFlowInfo.EMPTY, + TypeUtils.NO_EXPECTED_TYPE, + TypeUtils.NO_EXPECTED_TYPE, + false + ); + return ControlStructureTypingVisitor.checkIterableConvention(expressionReceiver, context) != null; + } }