From fba7829ab87616c1248286ea481502ff3b71ce20 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Fri, 3 Feb 2012 14:57:16 +0400 Subject: [PATCH] KT-274 Add Enumeration.iterator () method in global namespace Looking up iterator() via generic extensions' too --- .../jetbrains/jet/lang/psi/JetPsiFactory.java | 13 +++++++-- .../jet/lang/types/JetStandardLibrary.java | 9 +++++++ .../ControlStructureTypingVisitor.java | 27 ++++++++++++++++--- .../expressions/ExpressionTypingContext.java | 11 ++++++-- 4 files changed, 52 insertions(+), 8 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java index 43159fc432c..509bf51ef04 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetPsiFactory.java @@ -6,6 +6,7 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFileFactory; import com.intellij.util.LocalTimeCounter; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lexer.JetKeywordToken; import org.jetbrains.jet.plugin.JetFileType; @@ -54,11 +55,15 @@ public class JetPsiFactory { return (JetFile) PsiFileFactory.getInstance(project).createFileFromText(fileName, JetFileType.INSTANCE, text, LocalTimeCounter.currentTime(), true); } - public static JetProperty createProperty(Project project, String name, String type, boolean isVar) { - String text = (isVar ? "var " : "val ") + name + (type != null ? ":" + type : ""); + public static JetProperty createProperty(Project project, String name, String type, boolean isVar, @Nullable String initializer) { + String text = (isVar ? "var " : "val ") + name + (type != null ? ":" + type : "") + (initializer == null ? "" : " = " + initializer); return createProperty(project, text); } + public static JetProperty createProperty(Project project, String name, String type, boolean isVar) { + return createProperty(project, name, type, isVar, null); + } + public static JetProperty createProperty(Project project, String text) { return createDeclaration(project, text, JetProperty.class); } @@ -76,6 +81,10 @@ public class JetPsiFactory { return createProperty(project, name, null, false).getNameIdentifier(); } + public static JetSimpleNameExpression createSimpleName(Project project, String name) { + return (JetSimpleNameExpression) createProperty(project, name, null, false, name).getInitializer(); + } + public static JetNamedFunction createFunction(Project project, String funDecl) { return createDeclaration(project, funDecl, JetNamedFunction.class); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java index f6ac9c69ba9..06c9efd51e5 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/JetStandardLibrary.java @@ -52,6 +52,8 @@ public class JetStandardLibrary { // return standardLibrary; } + private final Project project; + private JetScope libraryScope; private ClassDescriptor numberClass; @@ -90,6 +92,8 @@ public class JetStandardLibrary { private Map jetArrayTypeToPrimitiveJetType; private JetStandardLibrary(@NotNull Project project) { + this.project = project; + // TODO : review List libraryFiles = Arrays.asList( "Library.jet", @@ -129,6 +133,11 @@ public class JetStandardLibrary { } } + @NotNull + public Project getProject() { + return project; + } + public JetScope getLibraryScope() { initStdClasses(); return libraryScope; 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 2343a383dba..db9e7c054f4 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 @@ -8,9 +8,8 @@ import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; -import org.jetbrains.jet.lang.resolve.BindingContext; -import org.jetbrains.jet.lang.resolve.BindingContextUtils; -import org.jetbrains.jet.lang.resolve.DescriptorUtils; +import org.jetbrains.jet.lang.resolve.*; +import org.jetbrains.jet.lang.resolve.calls.CallMaker; import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -265,7 +264,20 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { @Nullable private JetType checkIterableConvention(@NotNull ExpressionReceiver loopRange, ExpressionTypingContext context) { JetExpression loopRangeExpression = loopRange.getExpression(); - OverloadResolutionResults iteratorResolutionResults = context.resolveExactSignature(loopRange, "iterator", Collections.emptyList()); + + // Make a fake call loopRange.iterator(), and try to resolve it + String iterator = "iterator"; + OverloadResolutionResults iteratorResolutionResults = resolveFakeCall(loopRange, context, iterator); + + // We allow the loop range to be null (nothing happens), so we make the receiver type non-null + if (!iteratorResolutionResults.isSuccess()) { + ExpressionReceiver nonNullReceiver = new ExpressionReceiver(loopRange.getExpression(), TypeUtils.makeNotNullable(loopRange.getType())); + OverloadResolutionResults iteratorResolutionResultsWithNonNullReceiver = resolveFakeCall(nonNullReceiver, context, iterator); + if (iteratorResolutionResultsWithNonNullReceiver.isSuccess()) { + iteratorResolutionResults = iteratorResolutionResultsWithNonNullReceiver; + } + } + if (iteratorResolutionResults.isSuccess()) { FunctionDescriptor iteratorFunction = iteratorResolutionResults.getResultingCall().getResultingDescriptor(); @@ -314,6 +326,13 @@ public class ControlStructureTypingVisitor extends ExpressionTypingVisitor { return null; } + private 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()); + return context.replaceBindingTrace(fakeTrace).resolveCallWithGivenName(call, fake, name); + } + @Nullable private FunctionDescriptor checkHasNextFunctionSupport(@NotNull JetExpression loopRange, @NotNull JetType iteratorType, ExpressionTypingContext context) { OverloadResolutionResults hasNextResolutionResults = context.resolveExactSignature(new TransientReceiver(iteratorType), "hasNext", Collections.emptyList()); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java index 00cd93ac445..f5b77e98e29 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ExpressionTypingContext.java @@ -1,17 +1,19 @@ package org.jetbrains.jet.lang.types.expressions; import com.intellij.lang.ASTNode; +import com.intellij.openapi.project.Project; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.JetSemanticServices; -import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.FunctionDescriptor; import org.jetbrains.jet.lang.descriptors.VariableDescriptor; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingTrace; import org.jetbrains.jet.lang.resolve.DescriptorResolver; import org.jetbrains.jet.lang.resolve.TypeResolver; -import org.jetbrains.jet.lang.resolve.calls.*; +import org.jetbrains.jet.lang.resolve.calls.CallMaker; +import org.jetbrains.jet.lang.resolve.calls.CallResolver; +import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults; import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo; import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver; import org.jetbrains.jet.lang.resolve.scopes.JetScope; @@ -198,4 +200,9 @@ import java.util.Map; public OverloadResolutionResults resolveExactSignature(@NotNull ReceiverDescriptor receiver, @NotNull String name, @NotNull List parameterTypes) { return getCallResolver().resolveExactSignature(scope, receiver, name, parameterTypes); } + + @NotNull + public Project getProject() { + return semanticServices.getStandardLibrary().getProject(); + } }