Highlight dynamic calls in the editor

This commit is contained in:
Andrey Breslav
2014-11-19 18:58:17 +03:00
parent 52f1e037c1
commit 7f0df032b4
13 changed files with 84 additions and 17 deletions
@@ -23,18 +23,16 @@ import com.intellij.psi.tree.TokenSet;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.JetNodeTypes;
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor;
import org.jetbrains.jet.lang.diagnostics.Diagnostic;
import org.jetbrains.jet.lang.diagnostics.DiagnosticFactory;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
import org.jetbrains.jet.lang.resolve.calls.tasks.TasksPackage;
import org.jetbrains.jet.lang.types.ErrorUtils;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypesPackage;
import org.jetbrains.jet.lexer.JetTokens;
import java.util.Collection;
@@ -119,12 +117,8 @@ public class DebugInfoUtil {
if (declarationDescriptor != null) {
target = declarationDescriptor.toString();
if (declarationDescriptor instanceof CallableDescriptor) {
CallableDescriptor callableDescriptor = (CallableDescriptor) declarationDescriptor;
ReceiverParameterDescriptor dispatchReceiverParameter = callableDescriptor.getDispatchReceiverParameter();
if (dispatchReceiverParameter != null && TypesPackage.isDynamic(dispatchReceiverParameter.getReturnType())) {
debugInfoReporter.reportDynamicCall(expression);
}
if (TasksPackage.isDynamic(declarationDescriptor)) {
debugInfoReporter.reportDynamicCall(expression);
}
}
if (target == null) {
@@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.descriptors.impl.ValueParameterDescriptorImpl
import org.jetbrains.jet.lang.types.JetType
import kotlin.platform.platformStatic
import org.jetbrains.jet.lang.resolve.scopes.receivers.TransientReceiver
import org.jetbrains.jet.lang.types.isDynamic
object DynamicCallableDescriptors {
@@ -123,4 +124,11 @@ object DynamicCallableDescriptors {
SourceElement.NO_SOURCE
)
}
}
}
fun DeclarationDescriptor.isDynamic(): Boolean {
if (this !is CallableDescriptor) return false
val dispatchReceiverParameter = getDispatchReceiverParameter()
return dispatchReceiverParameter != null && dispatchReceiverParameter.getType().isDynamic()
}
@@ -159,9 +159,11 @@ options.kotlin.attribute.descriptor.package.property=Package-level property
options.kotlin.attribute.descriptor.property.with.backing=Property with backing field
options.kotlin.attribute.descriptor.backing.field.access=Backing field access
options.kotlin.attribute.descriptor.extension.property=Extension property
options.kotlin.attribute.descriptor.dynamic.property=Dynamic property
options.kotlin.attribute.descriptor.it=Function literal default parameter
options.kotlin.attribute.descriptor.fun=Function declaration
options.kotlin.attribute.descriptor.fun.call=Function call
options.kotlin.attribute.descriptor.dynamic.fun.call=Dynamic function call
options.kotlin.attribute.descriptor.package.fun.call=Package-level function call
options.kotlin.attribute.descriptor.extension.fun.call=Extension function call
options.kotlin.attribute.descriptor.constructor.call=Constructor call
@@ -19,16 +19,14 @@ package org.jetbrains.jet.plugin.highlighter;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ConstructorDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
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.callUtil.CallUtilPackage;
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.model.VariableAsFunctionResolvedCall;
import org.jetbrains.jet.lang.resolve.calls.tasks.TasksPackage;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.TypeUtils;
import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
@@ -69,8 +67,12 @@ public class FunctionsHighlightingVisitor extends AfterAnalysisHighlightingVisit
JetExpression callee = expression.getCalleeExpression();
ResolvedCall<?> resolvedCall = CallUtilPackage.getResolvedCall(expression, bindingContext);
if (callee instanceof JetReferenceExpression && resolvedCall != null) {
DeclarationDescriptor calleeDescriptor = resolvedCall.getResultingDescriptor();
if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
CallableDescriptor calleeDescriptor = resolvedCall.getResultingDescriptor();
if (TasksPackage.isDynamic(calleeDescriptor)) {
JetPsiChecker.highlightName(holder, callee, JetHighlightingColors.DYNAMIC_FUNCTION_CALL);
}
else if (resolvedCall instanceof VariableAsFunctionResolvedCall) {
JetPsiChecker.highlightName(holder, callee, containedInFunctionClassOrSubclass(calleeDescriptor)
? JetHighlightingColors.VARIABLE_AS_FUNCTION_CALL
: JetHighlightingColors.VARIABLE_AS_FUNCTION_LIKE_CALL);
@@ -66,6 +66,7 @@ public class JetHighlightingColors {
public static final TextAttributesKey PROPERTY_WITH_BACKING_FIELD = createTextAttributesKey("KOTLIN_PROPERTY_WITH_BACKING_FIELD");
public static final TextAttributesKey BACKING_FIELD_ACCESS = createTextAttributesKey("KOTLIN_BACKING_FIELD_ACCESS");
public static final TextAttributesKey EXTENSION_PROPERTY = createTextAttributesKey("KOTLIN_EXTENSION_PROPERTY");
public static final TextAttributesKey DYNAMIC_PROPERTY_CALL = createTextAttributesKey("KOTLIN_DYNAMIC_PROPERTY_CALL");
// functions
public static final TextAttributesKey FUNCTION_LITERAL_DEFAULT_PARAMETER = createTextAttributesKey("KOTLIN_CLOSURE_DEFAULT_PARAMETER");
@@ -74,6 +75,7 @@ public class JetHighlightingColors {
public static final TextAttributesKey PACKAGE_FUNCTION_CALL = createTextAttributesKey("KOTLIN_PACKAGE_FUNCTION_CALL", CodeInsightColors.STATIC_METHOD_ATTRIBUTES);
public static final TextAttributesKey EXTENSION_FUNCTION_CALL = createTextAttributesKey("KOTLIN_EXTENSION_FUNCTION_CALL");
public static final TextAttributesKey CONSTRUCTOR_CALL = createTextAttributesKey("KOTLIN_CONSTRUCTOR", CodeInsightColors.CONSTRUCTOR_CALL_ATTRIBUTES);
public static final TextAttributesKey DYNAMIC_FUNCTION_CALL = createTextAttributesKey("KOTLIN_DYNAMIC_FUNCTION_CALL");
public static final TextAttributesKey VARIABLE_AS_FUNCTION_CALL = createTextAttributesKey("KOTLIN_VARIABLE_AS_FUNCTION");
public static final TextAttributesKey VARIABLE_AS_FUNCTION_LIKE_CALL = createTextAttributesKey("KOTLIN_VARIABLE_AS_FUNCTION_LIKE");
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.psi.JetSimpleNameExpression;
import org.jetbrains.jet.lang.psi.JetThisExpression;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
import org.jetbrains.jet.lang.resolve.calls.tasks.TasksPackage;
import org.jetbrains.jet.lexer.JetTokens;
class PropertiesHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
@@ -82,6 +83,11 @@ class PropertiesHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
@NotNull PropertyDescriptor descriptor,
boolean withBackingField
) {
if (TasksPackage.isDynamic(descriptor)) {
JetPsiChecker.highlightName(holder, elementToHighlight, JetHighlightingColors.DYNAMIC_PROPERTY_CALL);
return;
}
boolean isStatic = DescriptorUtils.isStaticDeclaration(descriptor);
JetPsiChecker.highlightName(
holder, elementToHighlight,
@@ -81,6 +81,11 @@ class TypeKindHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
super.visitClass(klass);
}
@Override
public void visitDynamicType(@NotNull JetDynamicType type) {
// Do nothing: 'dynamic' is highlighted as a keyword
}
private void highlightName(@NotNull PsiElement whatToHighlight, @NotNull TextAttributesKey textAttributesKey) {
JetPsiChecker.highlightName(holder, whatToHighlight, textAttributesKey);
}
@@ -25,6 +25,7 @@ import org.jetbrains.jet.lang.descriptors.VariableDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.LocalVariableDescriptor;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.lang.resolve.calls.tasks.TasksPackage;
import org.jetbrains.jet.lang.types.JetType;
import org.jetbrains.jet.lang.types.expressions.CaptureKind;
import org.jetbrains.jet.renderer.DescriptorRenderer;
@@ -87,6 +88,12 @@ class VariablesHighlightingVisitor extends AfterAnalysisHighlightingVisitor {
private void highlightVariable(@NotNull PsiElement elementToHighlight, @NotNull DeclarationDescriptor descriptor) {
if (descriptor instanceof VariableDescriptor) {
VariableDescriptor variableDescriptor = (VariableDescriptor) descriptor;
if (TasksPackage.isDynamic(variableDescriptor)) {
JetPsiChecker.highlightName(holder, elementToHighlight, JetHighlightingColors.DYNAMIC_PROPERTY_CALL);
return;
}
if (variableDescriptor.isVar()) {
JetPsiChecker.highlightName(holder, elementToHighlight, JetHighlightingColors.MUTABLE_VARIABLE);
}
@@ -30,6 +30,18 @@
<option name="FOREGROUND" value="467cda" />
</value>
</option>
<option name="KOTLIN_DYNAMIC_FUNCTION_CALL">
<value>
<option name="FONT_TYPE" value="3" />
<option name="EFFECT_TYPE" value="0" />
</value>
</option>
<option name="KOTLIN_DYNAMIC_PROPERTY_CALL">
<value>
<option name="FONT_TYPE" value="3" />
<option name="EFFECT_TYPE" value="0" />
</value>
</option>
<option name="KOTLIN_DEBUG_INFO">
<value>
<option name="EFFECT_COLOR" value="ffffff"/>
@@ -30,6 +30,18 @@
<option name="FOREGROUND" value="4a86e8" />
</value>
</option>
<option name="KOTLIN_DYNAMIC_FUNCTION_CALL">
<value>
<option name="FONT_TYPE" value="3" />
<option name="EFFECT_TYPE" value="0" />
</value>
</option>
<option name="KOTLIN_DYNAMIC_PROPERTY_CALL">
<value>
<option name="FONT_TYPE" value="3" />
<option name="EFFECT_TYPE" value="0" />
</value>
</option>
<option name="KOTLIN_DEBUG_INFO">
<value>
<option name="EFFECT_COLOR" value="000000"/>
@@ -58,7 +58,7 @@ public class JetColorSettingsPage implements ColorSettingsPage {
" */\n" +
"[<ANNOTATION>Deprecated</ANNOTATION>]\n" +
"<BUILTIN_ANNOTATION>public</BUILTIN_ANNOTATION> class <CLASS>MyClass</CLASS><<BUILTIN_ANNOTATION>out</BUILTIN_ANNOTATION> <TYPE_PARAMETER>T</TYPE_PARAMETER> : <TRAIT>Iterable</TRAIT><<TYPE_PARAMETER>T</TYPE_PARAMETER>>>(var <INSTANCE_PROPERTY><MUTABLE_VARIABLE>prop1</MUTABLE_VARIABLE></INSTANCE_PROPERTY> : Int) {\n" +
" fun <FUNCTION_DECLARATION>foo</FUNCTION_DECLARATION>(<PARAMETER>nullable</PARAMETER> : String?, <PARAMETER>r</PARAMETER> : <TRAIT>Runnable</TRAIT>, <PARAMETER>f</PARAMETER> : () -> Int, <PARAMETER>fl</PARAMETER> : <TRAIT>FunctionLike</TRAIT>) {\n" +
" fun <FUNCTION_DECLARATION>foo</FUNCTION_DECLARATION>(<PARAMETER>nullable</PARAMETER> : String?, <PARAMETER>r</PARAMETER> : <TRAIT>Runnable</TRAIT>, <PARAMETER>f</PARAMETER> : () -> Int, <PARAMETER>fl</PARAMETER> : <TRAIT>FunctionLike</TRAIT>, dyn: dynamic) {\n" +
" <FUNCTION_CALL><PACKAGE_FUNCTION_CALL>println</PACKAGE_FUNCTION_CALL></FUNCTION_CALL>(\"length\\nis ${<PARAMETER>nullable</PARAMETER><SAFE_ACCESS>?.</SAFE_ACCESS><INSTANCE_PROPERTY>length</INSTANCE_PROPERTY>} <INVALID_STRING_ESCAPE><STRING_ESCAPE>\\e</STRING_ESCAPE></INVALID_STRING_ESCAPE>\")\n" +
" val <LOCAL_VARIABLE>ints</LOCAL_VARIABLE> = java.util.<CONSTRUCTOR_CALL>ArrayList</CONSTRUCTOR_CALL><Int?>(2)\n" +
" <LOCAL_VARIABLE>ints</LOCAL_VARIABLE>[0] = 102 + <PARAMETER><VARIABLE_AS_FUNCTION_CALL>f</VARIABLE_AS_FUNCTION_CALL></PARAMETER>() + <PARAMETER><VARIABLE_AS_FUNCTION_LIKE_CALL>fl</VARIABLE_AS_FUNCTION_LIKE_CALL></PARAMETER>()\n" +
@@ -70,6 +70,8 @@ public class JetColorSettingsPage implements ColorSettingsPage {
" <FUNCTION_CALL><PACKAGE_FUNCTION_CALL>println</PACKAGE_FUNCTION_CALL></FUNCTION_CALL>(<FUNCTION_LITERAL_DEFAULT_PARAMETER><SMART_CAST_VALUE>it</SMART_CAST_VALUE></FUNCTION_LITERAL_DEFAULT_PARAMETER> + <LOCAL_VARIABLE><MUTABLE_VARIABLE><WRAPPED_INTO_REF>ref</WRAPPED_INTO_REF></MUTABLE_VARIABLE></LOCAL_VARIABLE>)\n" +
" <FUNCTION_LITERAL_BRACES_AND_ARROW>}</FUNCTION_LITERAL_BRACES_AND_ARROW>\n" +
" }\n" +
" dyn.<DYNAMIC_FUNCTION_CALL>dynamicCall</DYNAMIC_FUNCTION_CALL>()\n" +
" dyn.<DYNAMIC_PROPERTY_CALL>dynamicProp</DYNAMIC_PROPERTY_CALL> = 5\n" +
" }\n" +
"}\n" +
"\n" +
@@ -147,10 +149,12 @@ public class JetColorSettingsPage implements ColorSettingsPage {
new AttributesDescriptor(JetBundle.message("options.kotlin.attribute.descriptor.property.with.backing"), JetHighlightingColors.PROPERTY_WITH_BACKING_FIELD),
new AttributesDescriptor(JetBundle.message("options.kotlin.attribute.descriptor.backing.field.access"), JetHighlightingColors.BACKING_FIELD_ACCESS),
new AttributesDescriptor(JetBundle.message("options.kotlin.attribute.descriptor.extension.property"), JetHighlightingColors.EXTENSION_PROPERTY),
new AttributesDescriptor(JetBundle.message("options.kotlin.attribute.descriptor.dynamic.property"), JetHighlightingColors.DYNAMIC_PROPERTY_CALL),
new AttributesDescriptor(JetBundle.message("options.kotlin.attribute.descriptor.it"), JetHighlightingColors.FUNCTION_LITERAL_DEFAULT_PARAMETER),
new AttributesDescriptor(JetBundle.message("options.kotlin.attribute.descriptor.fun"), JetHighlightingColors.FUNCTION_DECLARATION),
new AttributesDescriptor(JetBundle.message("options.kotlin.attribute.descriptor.fun.call"), JetHighlightingColors.FUNCTION_CALL),
new AttributesDescriptor(JetBundle.message("options.kotlin.attribute.descriptor.dynamic.fun.call"), JetHighlightingColors.DYNAMIC_FUNCTION_CALL),
new AttributesDescriptor(JetBundle.message("options.kotlin.attribute.descriptor.package.fun.call"), JetHighlightingColors.PACKAGE_FUNCTION_CALL),
new AttributesDescriptor(JetBundle.message("options.kotlin.attribute.descriptor.extension.fun.call"), JetHighlightingColors.EXTENSION_FUNCTION_CALL),
new AttributesDescriptor(JetBundle.message("options.kotlin.attribute.descriptor.constructor.call"), JetHighlightingColors.CONSTRUCTOR_CALL),
+7
View File
@@ -0,0 +1,7 @@
package testing
fun <info textAttributesKey="KOTLIN_FUNCTION_DECLARATION">tst</info>(<info textAttributesKey="KOTLIN_PARAMETER">d</info>: <error>dynamic</error>) {
<info textAttributesKey="KOTLIN_PARAMETER">d</info>.<info textAttributesKey="KOTLIN_DYNAMIC_FUNCTION_CALL">foo</info>()
<info textAttributesKey="KOTLIN_PARAMETER">d</info>.<info textAttributesKey="KOTLIN_DYNAMIC_PROPERTY_CALL">foo</info>
<info textAttributesKey="KOTLIN_PARAMETER">d</info>.<info textAttributesKey="KOTLIN_DYNAMIC_PROPERTY_CALL">foo</info> = 1
}
@@ -37,6 +37,12 @@ public class HighlightingTestGenerated extends AbstractHighlightingTest {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/highlighter"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("Dynamic.kt")
public void testDynamic() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/highlighter/Dynamic.kt");
doTest(fileName);
}
@TestMetadata("Enums.kt")
public void testEnums() throws Exception {
String fileName = JetTestUtils.navigationMetadata("idea/testData/highlighter/Enums.kt");