Support for function-valued expressions
This commit is contained in:
@@ -83,4 +83,13 @@ public class FunctionDescriptorUtil {
|
||||
return parameterScope;
|
||||
}
|
||||
|
||||
public static void initializeFromFunctionType(@NotNull FunctionDescriptorImpl functionDescriptor, @NotNull JetType functionType) {
|
||||
assert JetStandardClasses.isFunctionType(functionType);
|
||||
functionDescriptor.initialize(JetStandardClasses.getReceiverType(functionType),
|
||||
ReceiverDescriptor.NO_RECEIVER,
|
||||
Collections.<TypeParameterDescriptor>emptyList(),
|
||||
JetStandardClasses.getValueParameters(functionDescriptor, functionType),
|
||||
JetStandardClasses.getReturnType(functionType),
|
||||
Modality.FINAL, Visibility.LOCAL);
|
||||
}
|
||||
}
|
||||
|
||||
+1
-5
@@ -2,8 +2,6 @@ package org.jetbrains.jet.lang.descriptors;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -15,9 +13,8 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
|
||||
public static VariableAsFunctionDescriptor create(@NotNull VariableDescriptor variableDescriptor) {
|
||||
JetType outType = variableDescriptor.getOutType();
|
||||
assert outType != null;
|
||||
assert JetStandardClasses.isFunctionType(outType);
|
||||
VariableAsFunctionDescriptor result = new VariableAsFunctionDescriptor(variableDescriptor);
|
||||
result.initialize(JetStandardClasses.getReceiverType(outType), ReceiverDescriptor.NO_RECEIVER, Collections.<TypeParameterDescriptor>emptyList(), JetStandardClasses.getValueParameters(result, outType), JetStandardClasses.getReturnType(outType), Modality.FINAL, Visibility.LOCAL);
|
||||
FunctionDescriptorUtil.initializeFromFunctionType(result, outType);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -25,7 +22,6 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
|
||||
|
||||
private VariableAsFunctionDescriptor(VariableDescriptor variableDescriptor) {
|
||||
super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName());
|
||||
// super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName());
|
||||
this.variableDescriptor = variableDescriptor;
|
||||
}
|
||||
|
||||
|
||||
@@ -196,6 +196,7 @@ public interface Errors {
|
||||
AmbiguousDescriptorDiagnosticFactory ITERATOR_AMBIGUITY = AmbiguousDescriptorDiagnosticFactory.create("Method 'iterator()' is ambiguous for this expression: {0}");
|
||||
|
||||
ParameterizedDiagnosticFactory1<JetType> COMPARE_TO_TYPE_MISMATCH = ParameterizedDiagnosticFactory1.create(ERROR, "compareTo() must return Int, but returns {0}");
|
||||
ParameterizedDiagnosticFactory1<JetType> CALLEE_NOT_A_FUNCTION = ParameterizedDiagnosticFactory1.create(ERROR, "Expecting a function type, but found {0}");
|
||||
|
||||
SimpleDiagnosticFactory RETURN_IN_FUNCTION_WITH_EXPRESSION_BODY = SimpleDiagnosticFactory.create(ERROR, "Returns are not allowed for functions with expression body. Use block body in '{...}'");
|
||||
SimpleDiagnosticFactory NO_RETURN_IN_FUNCTION_WITH_BLOCK_BODY = SimpleDiagnosticFactory.create(ERROR, "A 'return' expression required in a function with a block body ('{...}')");
|
||||
|
||||
@@ -9,6 +9,7 @@ import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
|
||||
@@ -173,8 +174,29 @@ public class CallResolver {
|
||||
}
|
||||
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(ResolvedCallImpl.convertCollection(constructors), call, DataFlowInfo.EMPTY));
|
||||
}
|
||||
else if (calleeExpression != null) {
|
||||
// Here we handle the case where the callee expression must be something of type function, e.g. (foo.bar())(1, 2)
|
||||
ExpressionTypingServices typingServices = new ExpressionTypingServices(semanticServices, trace);
|
||||
JetType calleeType = typingServices.safeGetType(scope, calleeExpression, NO_EXPECTED_TYPE);// We are actually expecting a function, but there seems to be no easy way of expressing this
|
||||
|
||||
if (!JetStandardClasses.isFunctionType(calleeType)) {
|
||||
checkTypesWithNoCallee(trace, scope, call);
|
||||
if (!ErrorUtils.isErrorType(calleeType)) {
|
||||
trace.report(CALLEE_NOT_A_FUNCTION.on(calleeExpression, calleeType));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
FunctionDescriptorImpl functionDescriptor = new FunctionDescriptorImpl(scope.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), "for expression " + calleeExpression.getText());
|
||||
FunctionDescriptorUtil.initializeFromFunctionType(functionDescriptor, calleeType);
|
||||
ResolvedCallImpl<FunctionDescriptor> resolvedCall = ResolvedCallImpl.<FunctionDescriptor>create(functionDescriptor);
|
||||
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(
|
||||
Collections.singleton(resolvedCall), call, dataFlowInfo));
|
||||
functionReference = new JetReferenceExpression(calleeExpression.getNode()) {
|
||||
};
|
||||
}
|
||||
else {
|
||||
trace.report(UNSUPPORTED.on(call.getCallNode(), "Type argument inference is not supported for this callee: " + calleeExpression));
|
||||
checkTypesWithNoCallee(trace, scope, call);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -233,7 +255,15 @@ public class CallResolver {
|
||||
|
||||
@Override
|
||||
public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
|
||||
trace.report(NO_VALUE_FOR_PARAMETER.on(reference, valueParameter));
|
||||
PsiElement reportOn;
|
||||
JetValueArgumentList valueArgumentList = call.getValueArgumentList();
|
||||
if (valueArgumentList != null) {
|
||||
reportOn = valueArgumentList;
|
||||
}
|
||||
else {
|
||||
reportOn = reference;
|
||||
}
|
||||
trace.report(NO_VALUE_FOR_PARAMETER.on(reportOn, valueParameter));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -16,6 +16,6 @@ class C : T {
|
||||
super.foo() // OK
|
||||
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>.bar() // Error
|
||||
super.buzz() // OK, resolved to a member
|
||||
super.<!NO_VALUE_FOR_PARAMETER!>buzz1<!>() // Resolved to a member, but error: no parameter passed where required
|
||||
super.buzz1<!NO_VALUE_FOR_PARAMETER!>()<!> // Resolved to a member, but error: no parameter passed where required
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
namespace foo
|
||||
|
||||
fun Any.foo() : fun() : Unit {
|
||||
return {}
|
||||
}
|
||||
|
||||
fun Any.foo1() : fun(i : Int) : Unit {
|
||||
return {}
|
||||
}
|
||||
|
||||
fun foo2() : fun(i : fun()) : Unit {
|
||||
return {}
|
||||
}
|
||||
|
||||
fun fooT1<T>(t : T) : fun() : T {
|
||||
return {t}
|
||||
}
|
||||
|
||||
fun fooT2<T>() : fun(t : T) : T {
|
||||
return {it}
|
||||
}
|
||||
|
||||
fun main(args : Array<String>) {
|
||||
args.foo()()
|
||||
args.foo1()<!NO_VALUE_FOR_PARAMETER!>()<!>
|
||||
<!UNRESOLVED_REFERENCE!>a<!>.foo1()()
|
||||
<!UNRESOLVED_REFERENCE!>a<!>.foo1()(<!UNRESOLVED_REFERENCE!>a<!>)
|
||||
|
||||
args.foo1()(1)
|
||||
args.foo1()(<!TYPE_MISMATCH!>"1"<!>)
|
||||
<!UNRESOLVED_REFERENCE!>a<!>.foo1()("1")
|
||||
<!UNRESOLVED_REFERENCE!>a<!>.foo1()(<!UNRESOLVED_REFERENCE!>a<!>)
|
||||
|
||||
foo2()({})
|
||||
foo2()<!TOO_MANY_ARGUMENTS!>{}<!>
|
||||
(foo2()){}
|
||||
(foo2())<!TYPE_MISMATCH!>{<!CANNOT_INFER_PARAMETER_TYPE!>x<!> => }<!>
|
||||
foo2()(<!TYPE_MISMATCH!>{<!CANNOT_INFER_PARAMETER_TYPE!>x<!> => }<!>)
|
||||
|
||||
val a = fooT1(1)()
|
||||
a : Int
|
||||
|
||||
val b = fooT2<Int>()(1)
|
||||
b : Int
|
||||
fooT2()(1) // : Any?
|
||||
|
||||
<!CALLEE_NOT_A_FUNCTION!>1<!>()
|
||||
<!CALLEE_NOT_A_FUNCTION!>1<!>{}
|
||||
<!CALLEE_NOT_A_FUNCTION!>1<!>(){}
|
||||
}
|
||||
@@ -14,10 +14,10 @@ fun test() {
|
||||
foo(1, "", <!TOO_MANY_ARGUMENTS!>""<!>)
|
||||
|
||||
bar(z = "")
|
||||
<!NO_VALUE_FOR_PARAMETER!>bar<!>()
|
||||
<!NO_VALUE_FOR_PARAMETER!>bar<!>("")
|
||||
bar<!NO_VALUE_FOR_PARAMETER!>()<!>
|
||||
bar<!NO_VALUE_FOR_PARAMETER!>("")<!>
|
||||
bar(1, 1, "")
|
||||
bar(1, 1, "")
|
||||
bar(1, <!MIXING_NAMED_AND_POSITIONED_ARGUMENTS!>z<!> = "")
|
||||
<!NO_VALUE_FOR_PARAMETER!>bar<!>(1, <!UNRESOLVED_REFERENCE, MIXING_NAMED_AND_POSITIONED_ARGUMENTS!>zz<!> = "", <!MIXING_NAMED_AND_POSITIONED_ARGUMENTS!><!UNRESOLVED_REFERENCE!>zz<!>.foo<!>)
|
||||
bar<!NO_VALUE_FOR_PARAMETER!>(1, <!UNRESOLVED_REFERENCE, MIXING_NAMED_AND_POSITIONED_ARGUMENTS!>zz<!> = "", <!MIXING_NAMED_AND_POSITIONED_ARGUMENTS!><!UNRESOLVED_REFERENCE!>zz<!>.foo<!>)<!>
|
||||
}
|
||||
@@ -26,7 +26,7 @@ namespace io {
|
||||
fun println(message : Float) { System.out?.println(message) }
|
||||
fun println(message : Double) { System.out?.println(message) }
|
||||
|
||||
private var systemIn : InputStream? = null // Unfortunately, System.in may change Yt pf xn
|
||||
private var systemIn : InputStream? = null // Unfortunately, System.in may change
|
||||
private var stdin : BufferedReader? = null // This may introduce leaks of system.in objects...
|
||||
|
||||
fun readLine() : String? {
|
||||
|
||||
Reference in New Issue
Block a user