Supporting function literals as selectors

This commit is contained in:
Andrey Breslav
2011-11-03 22:23:26 +03:00
parent 4012fc8a5f
commit 73292bd4d6
5 changed files with 50 additions and 4 deletions
@@ -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<String> 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");
@@ -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<JetExpression> getFunctionLiteralArguments() {
JetExpression calleeExpression = getCalleeExpression();
if (calleeExpression instanceof JetFunctionLiteralExpression) {
List<JetExpression> result = new SmartList<JetExpression>();
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);
}
@@ -187,9 +187,10 @@ public class CallResolver {
return null;
}
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(scope.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), "for expression " + calleeExpression.getText());
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(scope.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), "[for expression " + calleeExpression.getText() + "]");
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType);
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
resolvedCall.setReceiverArgument(call.getExplicitReceiver());
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(
Collections.singleton(resolvedCall), call, dataFlowInfo));
functionReference = new JetReferenceExpression(calleeExpression.getNode()) {
@@ -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;
}
@@ -47,4 +47,26 @@ fun main(args : Array<String>) {
<!CALLEE_NOT_A_FUNCTION!>1<!>()
<!CALLEE_NOT_A_FUNCTION!>1<!>{}
<!CALLEE_NOT_A_FUNCTION!>1<!>(){}
}
}
fun f() : fun Int.() : Unit = {}
fun main1(args : Array<String>) {
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.<!CALLEE_NOT_A_FUNCTION!>"sdf"<!>()
1.<!ILLEGAL_SELECTOR!>"sdf"<!>
1.<!ILLEGAL_SELECTOR!>{}<!>
1.<!ILLEGAL_SELECTOR!>if (true) {}<!>
}