Support for function-valued expressions
This commit is contained in:
@@ -83,4 +83,13 @@ public class FunctionDescriptorUtil {
|
|||||||
return parameterScope;
|
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.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
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 org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -15,9 +13,8 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
|
|||||||
public static VariableAsFunctionDescriptor create(@NotNull VariableDescriptor variableDescriptor) {
|
public static VariableAsFunctionDescriptor create(@NotNull VariableDescriptor variableDescriptor) {
|
||||||
JetType outType = variableDescriptor.getOutType();
|
JetType outType = variableDescriptor.getOutType();
|
||||||
assert outType != null;
|
assert outType != null;
|
||||||
assert JetStandardClasses.isFunctionType(outType);
|
|
||||||
VariableAsFunctionDescriptor result = new VariableAsFunctionDescriptor(variableDescriptor);
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,7 +22,6 @@ public class VariableAsFunctionDescriptor extends FunctionDescriptorImpl {
|
|||||||
|
|
||||||
private VariableAsFunctionDescriptor(VariableDescriptor variableDescriptor) {
|
private VariableAsFunctionDescriptor(VariableDescriptor variableDescriptor) {
|
||||||
super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName());
|
super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName());
|
||||||
// super(variableDescriptor.getContainingDeclaration(), Collections.<AnnotationDescriptor>emptyList(), variableDescriptor.getName());
|
|
||||||
this.variableDescriptor = variableDescriptor;
|
this.variableDescriptor = variableDescriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -196,6 +196,7 @@ public interface Errors {
|
|||||||
AmbiguousDescriptorDiagnosticFactory ITERATOR_AMBIGUITY = AmbiguousDescriptorDiagnosticFactory.create("Method 'iterator()' is ambiguous for this expression: {0}");
|
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> 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 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 ('{...}')");
|
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.annotations.Nullable;
|
||||||
import org.jetbrains.jet.lang.JetSemanticServices;
|
import org.jetbrains.jet.lang.JetSemanticServices;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
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.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.*;
|
import org.jetbrains.jet.lang.resolve.*;
|
||||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
|
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));
|
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 {
|
else {
|
||||||
trace.report(UNSUPPORTED.on(call.getCallNode(), "Type argument inference is not supported for this callee: " + calleeExpression));
|
checkTypesWithNoCallee(trace, scope, call);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -233,7 +255,15 @@ public class CallResolver {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter) {
|
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
|
@Override
|
||||||
|
|||||||
@@ -16,6 +16,6 @@ class C : T {
|
|||||||
super.foo() // OK
|
super.foo() // OK
|
||||||
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>.bar() // Error
|
<!SUPER_IS_NOT_AN_EXPRESSION!>super<!>.bar() // Error
|
||||||
super.buzz() // OK, resolved to a member
|
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!>""<!>)
|
foo(1, "", <!TOO_MANY_ARGUMENTS!>""<!>)
|
||||||
|
|
||||||
bar(z = "")
|
bar(z = "")
|
||||||
<!NO_VALUE_FOR_PARAMETER!>bar<!>()
|
bar<!NO_VALUE_FOR_PARAMETER!>()<!>
|
||||||
<!NO_VALUE_FOR_PARAMETER!>bar<!>("")
|
bar<!NO_VALUE_FOR_PARAMETER!>("")<!>
|
||||||
bar(1, 1, "")
|
bar(1, 1, "")
|
||||||
bar(1, 1, "")
|
bar(1, 1, "")
|
||||||
bar(1, <!MIXING_NAMED_AND_POSITIONED_ARGUMENTS!>z<!> = "")
|
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 : Float) { System.out?.println(message) }
|
||||||
fun println(message : Double) { 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...
|
private var stdin : BufferedReader? = null // This may introduce leaks of system.in objects...
|
||||||
|
|
||||||
fun readLine() : String? {
|
fun readLine() : String? {
|
||||||
|
|||||||
Reference in New Issue
Block a user