From 73292bd4d682ff96a2178a8546cda653153241e3 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Thu, 3 Nov 2011 22:23:26 +0300 Subject: [PATCH] Supporting function literals as selectors --- .../jet/lang/diagnostics/Errors.java | 2 ++ .../jet/lang/psi/JetCallExpression.java | 22 +++++++++++++++++ .../jet/lang/resolve/calls/CallResolver.java | 3 ++- .../BasicExpressionTypingVisitor.java | 3 +-- .../quick/FunctionCalleeExpressions.jet | 24 ++++++++++++++++++- 5 files changed, 50 insertions(+), 4 deletions(-) diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java index fbec7d4bf64..6a0a441497f 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/diagnostics/Errors.java @@ -228,6 +228,8 @@ public interface Errors { SimpleDiagnosticFactory SUPERTYPE_APPEARS_TWICE = SimpleDiagnosticFactory.create(ERROR, "A supertype appears twice"); SimpleDiagnosticFactory FINAL_SUPERTYPE = SimpleDiagnosticFactory.create(ERROR, "This type is final, so it cannot be inherited from"); + ParameterizedDiagnosticFactory1 ILLEGAL_SELECTOR = ParameterizedDiagnosticFactory1.create(ERROR, "Expression ''{0}'' cannot be a selector (occur after a dot)"); + SimpleDiagnosticFactory REF_PARAMETER_WITH_VAL_OR_VAR = SimpleDiagnosticFactory.create(ERROR, "'val' and 'var' are not allowed on ref-parameters"); SimpleDiagnosticFactory VALUE_PARAMETER_WITH_NO_TYPE_ANNOTATION = SimpleDiagnosticFactory.create(ERROR, "A type annotation is required on a value parameter"); SimpleDiagnosticFactory BREAK_OR_CONTINUE_OUTSIDE_A_LOOP = SimpleDiagnosticFactory.create(ERROR, "'break' and 'continue' are only allowed inside a loop"); diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java index 79eef89077e..3d208f266a2 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/psi/JetCallExpression.java @@ -1,6 +1,8 @@ package org.jetbrains.jet.lang.psi; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.util.SmartList; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.JetNodeTypes; @@ -46,6 +48,26 @@ public class JetCallExpression extends JetExpression implements JetCallElement { @Override @NotNull public List getFunctionLiteralArguments() { + JetExpression calleeExpression = getCalleeExpression(); + if (calleeExpression instanceof JetFunctionLiteralExpression) { + List result = new SmartList(); + ASTNode treeNext = calleeExpression.getNode().getTreeNext(); + while (treeNext != null) { + PsiElement psi = treeNext.getPsi(); + if (psi instanceof JetFunctionLiteralExpression) { + result.add((JetFunctionLiteralExpression) psi); + } + else if (psi instanceof JetLabelQualifiedExpression) { + JetLabelQualifiedExpression labelQualifiedExpression = (JetLabelQualifiedExpression) psi; + JetExpression labeledExpression = labelQualifiedExpression.getLabeledExpression(); + if (labeledExpression instanceof JetFunctionLiteralExpression) { + result.add(labeledExpression); + } + } + treeNext = treeNext.getTreeNext(); + } + return result; + } return findChildrenByType(JetNodeTypes.FUNCTION_LITERAL_EXPRESSION); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java index 231bf7a3e0f..707d4d3c2df 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/resolve/calls/CallResolver.java @@ -187,9 +187,10 @@ public class CallResolver { return null; } - FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(scope.getContainingDeclaration(), Collections.emptyList(), "for expression " + calleeExpression.getText()); + FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(scope.getContainingDeclaration(), Collections.emptyList(), "[for expression " + calleeExpression.getText() + "]"); FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType); ResolvedCallImpl resolvedCall = ResolvedCallImpl.create(functionDescriptor); + resolvedCall.setReceiverArgument(call.getExplicitReceiver()); prioritizedTasks = Collections.singletonList(new ResolutionTask( Collections.singleton(resolvedCall), call, dataFlowInfo)); functionReference = new JetReferenceExpression(calleeExpression.getNode()) { diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java index 2255ebe885d..f00ecc3cce7 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/BasicExpressionTypingVisitor.java @@ -525,8 +525,7 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor { } } else { - // TODO : not a simple name -> resolve in scope, expect property type or a function type - context.trace.report(UNSUPPORTED.on(selectorExpression, "getSelectorReturnType")); + context.trace.report(ILLEGAL_SELECTOR.on(selectorExpression, selectorExpression.getText())); } return null; } diff --git a/compiler/testData/checkerWithErrorTypes/quick/FunctionCalleeExpressions.jet b/compiler/testData/checkerWithErrorTypes/quick/FunctionCalleeExpressions.jet index 581493762d3..271e8533305 100644 --- a/compiler/testData/checkerWithErrorTypes/quick/FunctionCalleeExpressions.jet +++ b/compiler/testData/checkerWithErrorTypes/quick/FunctionCalleeExpressions.jet @@ -47,4 +47,26 @@ fun main(args : Array) { 1() 1{} 1(){} -} \ No newline at end of file +} + +fun f() : fun Int.() : Unit = {} + +fun main1(args : Array) { + 1.{Int.() => 1}(); + {1}() + {(x : Int) => x}(1) + 1.{Int.(x : Int) => x}(1) + @l{1}() + 1.({Int.() => 1})() + 1.(f())() + 1.if(true){f()}else{f()}() + 1.if(true){Int.() => 1}else{f()}() + 1.if(true){Int.() => 1}else{Int.() => 1}() + + 1."sdf"() + + 1."sdf" + 1.{} + 1.if (true) {} +} +