diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties
index f0eb6b1fa3a..5b3239298a4 100644
--- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties
+++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties
@@ -116,6 +116,7 @@ options.jet.attribute.descriptor.namespace.fun.call=Package-level function call
options.jet.attribute.descriptor.extension.fun.call=Extension function call
options.jet.attribute.descriptor.constructor.call=Constructor call
options.jet.attribute.descriptor.variable.as.function.call=Variable as function call
+options.jet.attribute.descriptor.variable.as.function.like.call=Variable as function-like call
options.jet.attribute.descriptor.auto.casted=Smart-cast value
options.jet.attribute.descriptor.label=Label
change.to.function.invocation=Change to function invocation
diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/FunctionsHighlightingVisitor.java b/idea/src/org/jetbrains/jet/plugin/highlighter/FunctionsHighlightingVisitor.java
index 6a27a905708..b396ff14a15 100644
--- a/idea/src/org/jetbrains/jet/plugin/highlighter/FunctionsHighlightingVisitor.java
+++ b/idea/src/org/jetbrains/jet/plugin/highlighter/FunctionsHighlightingVisitor.java
@@ -22,6 +22,11 @@ import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
+import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
+import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
+import org.jetbrains.jet.lang.types.JetType;
+import org.jetbrains.jet.lang.types.TypeUtils;
+import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
public class FunctionsHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
public FunctionsHighlightingVisitor(AnnotationHolder holder, BindingContext bindingContext) {
@@ -58,33 +63,72 @@ public class FunctionsHighlightingVisitor extends AfterAnalysisHighlightingVisit
public void visitCallExpression(JetCallExpression expression) {
JetExpression callee = expression.getCalleeExpression();
if (callee instanceof JetReferenceExpression) {
- DeclarationDescriptor calleeDescriptor = bindingContext.get(BindingContext.REFERENCE_TARGET, (JetReferenceExpression)callee);
- if (calleeDescriptor != null) {
- if (calleeDescriptor instanceof ConstructorDescriptor) {
- JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.CONSTRUCTOR_CALL);
+ ResolvedCall extends CallableDescriptor> resolvedCall =
+ bindingContext.get(BindingContext.RESOLVED_CALL, (JetReferenceExpression) callee);
+ if (resolvedCall != null) {
+ if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
+ highlightVariableAsFunctionCall(callee, (VariableAsFunctionResolvedCall) resolvedCall);
}
- else if (calleeDescriptor instanceof FunctionDescriptor) {
- FunctionDescriptor fun = (FunctionDescriptor)calleeDescriptor;
- JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.FUNCTION_CALL);
- if (DescriptorUtils.isTopLevelDeclaration(fun)) {
- JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.NAMESPACE_FUNCTION_CALL);
+ else {
+ DeclarationDescriptor calleeDescriptor = resolvedCall.getResultingDescriptor();
+ if (calleeDescriptor instanceof ConstructorDescriptor) {
+ JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.CONSTRUCTOR_CALL);
}
- if (fun.getReceiverParameter() != null) {
- JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.EXTENSION_FUNCTION_CALL);
+ else if (calleeDescriptor instanceof FunctionDescriptor) {
+ FunctionDescriptor fun = (FunctionDescriptor) calleeDescriptor;
+ JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.FUNCTION_CALL);
+ if (DescriptorUtils.isTopLevelDeclaration(fun)) {
+ JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.NAMESPACE_FUNCTION_CALL);
+ }
+ if (fun.getReceiverParameter() != null) {
+ JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.EXTENSION_FUNCTION_CALL);
+ }
}
}
- else if (calleeDescriptor instanceof VariableDescriptor) {
- String kind = calleeDescriptor instanceof ValueParameterDescriptor
- ? "parameter"
- : calleeDescriptor instanceof PropertyDescriptor
- ? "property"
- : "variable";
- holder.createInfoAnnotation(callee, "Calling " + kind + " as function").setTextAttributes(
- JetHighlightingColors.VARIABLE_AS_FUNCTION_CALL);
- }
}
}
super.visitCallExpression(expression);
}
+
+ private void highlightVariableAsFunctionCall(JetExpression callee, VariableAsFunctionResolvedCall resolvedCall) {
+ VariableDescriptor variableDescriptor = resolvedCall.getVariableCall().getResultingDescriptor();
+
+ String kind = variableDescriptor instanceof ValueParameterDescriptor
+ ? "parameter"
+ : variableDescriptor instanceof PropertyDescriptor
+ ? "property"
+ : "variable";
+
+ if (containedInFunctionClassOrSubclass(resolvedCall.getFunctionCall().getResultingDescriptor())) {
+ holder.createInfoAnnotation(callee, "Calling " + kind + " as function").setTextAttributes(
+ JetHighlightingColors.VARIABLE_AS_FUNCTION_CALL);
+ }
+ else {
+ holder.createInfoAnnotation(callee, "Calling " + kind + " as function-like").setTextAttributes(
+ JetHighlightingColors.VARIABLE_AS_FUNCTION_LIKE_CALL);
+ }
+ }
+
+ private static boolean containedInFunctionClassOrSubclass(DeclarationDescriptor calleeDescriptor) {
+ DeclarationDescriptor parent = calleeDescriptor.getContainingDeclaration();
+ if (!(parent instanceof ClassDescriptor)) {
+ return false;
+ }
+
+ KotlinBuiltIns builtIns = KotlinBuiltIns.getInstance();
+ JetType defaultType = ((ClassDescriptor) parent).getDefaultType();
+
+ if (builtIns.isFunctionOrExtensionFunctionType(defaultType)) {
+ return true;
+ }
+
+ for (JetType supertype : TypeUtils.getAllSupertypes(defaultType)) {
+ if (builtIns.isFunctionOrExtensionFunctionType(supertype)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
}
diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/JetColorSettingsPage.java b/idea/src/org/jetbrains/jet/plugin/highlighter/JetColorSettingsPage.java
index 814d761199f..4e55276ed3b 100644
--- a/idea/src/org/jetbrains/jet/plugin/highlighter/JetColorSettingsPage.java
+++ b/idea/src/org/jetbrains/jet/plugin/highlighter/JetColorSettingsPage.java
@@ -58,10 +58,10 @@ public class JetColorSettingsPage implements ColorSettingsPage {
" */\n" +
"[Deprecated]\n" +
"public class MyClass<out T : Iterable<T>>(var prop1 : Int) {\n" +
- " fun foo(nullable : String?, r : Runnable, f : () -> Int) {\n" +
+ " fun foo(nullable : String?, r : Runnable, f : () -> Int, fl : FunctionLike) {\n" +
" println(\"length\\nis ${nullable?.length} \\e\")\n" +
" val ints = java.util.ArrayList(2)\n" +
- " ints[0] = 102 + f()\n" +
+ " ints[0] = 102 + f() + fl()\n" +
" val myFun = { -> \"\" };\n" +
" var ref = ints.size()\n" +
" if (!ints.empty) {\n" +
@@ -156,6 +156,7 @@ public class JetColorSettingsPage implements ColorSettingsPage {
new AttributesDescriptor(JetBundle.message("options.jet.attribute.descriptor.extension.fun.call"), JetHighlightingColors.EXTENSION_FUNCTION_CALL),
new AttributesDescriptor(JetBundle.message("options.jet.attribute.descriptor.constructor.call"), JetHighlightingColors.CONSTRUCTOR_CALL),
new AttributesDescriptor(JetBundle.message("options.jet.attribute.descriptor.variable.as.function.call"), JetHighlightingColors.VARIABLE_AS_FUNCTION_CALL),
+ new AttributesDescriptor(JetBundle.message("options.jet.attribute.descriptor.variable.as.function.like.call"), JetHighlightingColors.VARIABLE_AS_FUNCTION_LIKE_CALL),
new AttributesDescriptor(OptionsBundle.message("options.java.attribute.descriptor.bad.character"), JetHighlightingColors.BAD_CHARACTER),
diff --git a/idea/src/org/jetbrains/jet/plugin/highlighter/JetHighlightingColors.java b/idea/src/org/jetbrains/jet/plugin/highlighter/JetHighlightingColors.java
index f9c81757ccb..2f769c9354d 100644
--- a/idea/src/org/jetbrains/jet/plugin/highlighter/JetHighlightingColors.java
+++ b/idea/src/org/jetbrains/jet/plugin/highlighter/JetHighlightingColors.java
@@ -241,6 +241,11 @@ public class JetHighlightingColors {
new TextAttributes()
);
+ public static final TextAttributesKey VARIABLE_AS_FUNCTION_LIKE_CALL = TextAttributesKey.createTextAttributesKey(
+ "KOTLIN_VARIABLE_AS_FUNCTION_LIKE",
+ new TextAttributes()
+ );
+
public static final TextAttributesKey BAD_CHARACTER = TextAttributesKey.createTextAttributesKey(
"KOTLIN_BAD_CHARACTER",
HighlighterColors.BAD_CHARACTER.getDefaultAttributes()
diff --git a/idea/testData/checker/infos/VariableAsFunction.kt b/idea/testData/checker/infos/VariableAsFunction.kt
index 129e3656184..04104a1a7bf 100644
--- a/idea/testData/checker/infos/VariableAsFunction.kt
+++ b/idea/testData/checker/infos/VariableAsFunction.kt
@@ -7,7 +7,7 @@ val property = {}
fun foo(param: (Int) -> Int, functionLike: FunctionLike) {
param(1)
- functionLike()
+ functionLike()
val v1 = param
var v2 = param
@@ -15,5 +15,7 @@ fun foo(param: (Int) -> Int, functionLike: FunctionLike) {
v1(1)
v2(1)
- property()
+ property();
+
+ {}() //should not be highlighted as "calling variable as function"
}
\ No newline at end of file