Properties with custom property declarations highlighting rule.

Added support for package and class-level properties with custom PD.
Java syntethic extensions are ignored from this rule.

 #KT-30806 Fixed
This commit is contained in:
Vladimir Ilmov
2019-11-07 12:09:46 +03:00
parent bf37572b93
commit e2b91cfec7
11 changed files with 114 additions and 10 deletions
@@ -82,7 +82,9 @@ options.kotlin.attribute.descriptor.var=Properties and Variables//Var (mutable v
options.kotlin.attribute.descriptor.local.variable=Properties and Variables//Local variable or value
options.kotlin.attribute.descriptor.captured.variable=Properties and Variables//Variables and values captured in a closure
options.kotlin.attribute.descriptor.instance.property=Properties and Variables//Instance property
options.kotlin.attribute.descriptor.instance.property.custom.property.declaration=Properties and Variables//Instance property with custom property declarations
options.kotlin.attribute.descriptor.package.property=Properties and Variables//Package-level property
options.kotlin.attribute.descriptor.package.property.custom.property.declaration=Properties and Variables//Package-level property with custom property declarations
options.kotlin.attribute.descriptor.field=Properties and Variables//Backing field variable
options.kotlin.attribute.descriptor.extension.property=Properties and Variables//Extension property
options.kotlin.attribute.descriptor.synthetic.extension.property=Properties and Variables//Synthetic extension property
@@ -75,6 +75,8 @@ public class KotlinHighlightingColors {
public static final TextAttributesKey SYNTHETIC_EXTENSION_PROPERTY = createTextAttributesKey("KOTLIN_SYNTHETIC_EXTENSION_PROPERTY", EXTENSION_PROPERTY);
public static final TextAttributesKey DYNAMIC_PROPERTY_CALL = createTextAttributesKey("KOTLIN_DYNAMIC_PROPERTY_CALL");
public static final TextAttributesKey ANDROID_EXTENSIONS_PROPERTY_CALL = createTextAttributesKey("KOTLIN_ANDROID_EXTENSIONS_PROPERTY_CALL");
public static final TextAttributesKey INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION = createTextAttributesKey("KOTLIN_INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION", INSTANCE_PROPERTY);
public static final TextAttributesKey PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION = createTextAttributesKey("KOTLIN_PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION", PACKAGE_PROPERTY);
// functions
public static final TextAttributesKey FUNCTION_LITERAL_DEFAULT_PARAMETER = createTextAttributesKey("KOTLIN_CLOSURE_DEFAULT_PARAMETER");
@@ -18,6 +18,8 @@ package org.jetbrains.kotlin.idea.highlighter
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.idea.caches.project.NotUnderContentRootModuleInfo
import org.jetbrains.kotlin.idea.caches.project.getModuleInfo
import org.jetbrains.kotlin.idea.core.script.IdeScriptReportSink
@@ -79,4 +81,17 @@ object KotlinHighlightingUtil {
return ProjectRootsUtil.isInProjectSource(ktFile, includeScriptsOutsideSourceRoots = true)
}
fun hasCustomPropertyDeclaration(descriptor: PropertyDescriptor): Boolean {
var hasCustomPropertyDeclaration = false
if (!hasExtensionReceiverParameter(descriptor)) {
if (descriptor.getter?.isDefault == false || descriptor.setter?.isDefault == false)
hasCustomPropertyDeclaration = true
}
return hasCustomPropertyDeclaration
}
fun hasExtensionReceiverParameter(descriptor: PropertyDescriptor): Boolean {
return descriptor.extensionReceiverParameter != null
}
}
@@ -97,14 +97,20 @@ internal class PropertiesHighlightingVisitor(holder: AnnotationHolder, bindingCo
// The property is set in VariablesHighlightingVisitor
null
descriptor.extensionReceiverParameter != null ->
KotlinHighlightingUtil.hasExtensionReceiverParameter(descriptor) ->
if (descriptor.isSynthesized) SYNTHETIC_EXTENSION_PROPERTY else EXTENSION_PROPERTY
DescriptorUtils.isStaticDeclaration(descriptor) ->
PACKAGE_PROPERTY
if(KotlinHighlightingUtil.hasCustomPropertyDeclaration(descriptor))
PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION
else
PACKAGE_PROPERTY
else ->
INSTANCE_PROPERTY
if (KotlinHighlightingUtil.hasCustomPropertyDeclaration(descriptor))
INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION
else
INSTANCE_PROPERTY
}
}
}
@@ -20,6 +20,7 @@ import com.intellij.lang.annotation.AnnotationHolder
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiNameIdentifierOwner
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.BindingContext.*
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.calls.smartcasts.MultipleSmartCasts
import org.jetbrains.kotlin.resolve.calls.tasks.isDynamic
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
@@ -166,6 +168,15 @@ internal class VariablesHighlightingVisitor(holder: AnnotationHolder, bindingCon
if (descriptor is ValueParameterDescriptor) {
highlightName(elementToHighlight, PARAMETER)
}
if (descriptor is PropertyDescriptor && KotlinHighlightingUtil.hasCustomPropertyDeclaration(descriptor)) {
val isStaticDeclaration = DescriptorUtils.isStaticDeclaration(descriptor)
highlightName(elementToHighlight,
if (isStaticDeclaration)
PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION
else
INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION)
}
}
}
}
@@ -78,10 +78,14 @@ fun Int?.bar() {
}
}
var <PACKAGE_PROPERTY><MUTABLE_VARIABLE>globalCounter</MUTABLE_VARIABLE></PACKAGE_PROPERTY> : Int = <NUMBER>5</NUMBER>
<KEYWORD>get</KEYWORD> = <LOCAL_VARIABLE><MUTABLE_VARIABLE><BACKING_FIELD_VARIABLE>field</BACKING_FIELD_VARIABLE></MUTABLE_VARIABLE></LOCAL_VARIABLE>
var <PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION><MUTABLE_VARIABLE>globalCounter</MUTABLE_VARIABLE></PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION> : Int = <NUMBER>5</NUMBER>
<KEYWORD>get</KEYWORD>() = <LOCAL_VARIABLE><MUTABLE_VARIABLE><BACKING_FIELD_VARIABLE>field</BACKING_FIELD_VARIABLE></MUTABLE_VARIABLE></LOCAL_VARIABLE>
<KEYWORD>abstract</KEYWORD> class <ABSTRACT_CLASS>Abstract</ABSTRACT_CLASS> {
val <INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION>bar</INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION> <KEYWORD>get</KEYWORD>() = 1
fun <FUNCTION_DECLARATION>test</FUNCTION_DECLARATION>() {
<INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION>bar</INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION>
}
}
<KEYWORD>object</KEYWORD> <OBJECT>Obj</OBJECT>
@@ -159,6 +163,8 @@ var <PACKAGE_PROPERTY><MUTABLE_VARIABLE>globalCounter</MUTABLE_VARIABLE></PACKAG
OptionsBundle.message("options.java.attribute.descriptor.parameter") to KotlinHighlightingColors.PARAMETER,
KotlinBundle.message("options.kotlin.attribute.descriptor.captured.variable") to KotlinHighlightingColors.WRAPPED_INTO_REF,
KotlinBundle.message("options.kotlin.attribute.descriptor.instance.property") to KotlinHighlightingColors.INSTANCE_PROPERTY,
KotlinBundle.message("options.kotlin.attribute.descriptor.instance.property.custom.property.declaration") to KotlinHighlightingColors.INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION,
KotlinBundle.message("options.kotlin.attribute.descriptor.package.property.custom.property.declaration") to KotlinHighlightingColors.PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION,
KotlinBundle.message("options.kotlin.attribute.descriptor.package.property") to KotlinHighlightingColors.PACKAGE_PROPERTY,
KotlinBundle.message("options.kotlin.attribute.descriptor.field") to KotlinHighlightingColors.BACKING_FIELD_VARIABLE,
KotlinBundle.message("options.kotlin.attribute.descriptor.extension.property") to KotlinHighlightingColors.EXTENSION_PROPERTY,
+2 -2
View File
@@ -1,13 +1,13 @@
// EXPECTED_DUPLICATED_HIGHLIGHTING
// FALSE_POSITIVE
var <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE">my</info></info> = 0
var <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE">my</info></info> = 0
<info textAttributesKey="KOTLIN_KEYWORD">get</info>() = <info textAttributesKey="KOTLIN_BACKING_FIELD_VARIABLE"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE">field</info></info>
<info textAttributesKey="KOTLIN_KEYWORD">set</info>(<info textAttributesKey="KOTLIN_PARAMETER">arg</info>) {
<info textAttributesKey="KOTLIN_BACKING_FIELD_VARIABLE"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE">field</info></info> = <info textAttributesKey="KOTLIN_PARAMETER">arg</info> + 1
}
fun <info textAttributesKey="KOTLIN_FUNCTION_DECLARATION">foo</info>(): <info textAttributesKey="KOTLIN_CLASS">Int</info> {
val <info textAttributesKey="KOTLIN_LOCAL_VARIABLE">field</info> = <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE">my</info></info>
val <info textAttributesKey="KOTLIN_LOCAL_VARIABLE">field</info> = <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE">my</info></info>
return <info textAttributesKey="KOTLIN_LOCAL_VARIABLE">field</info>
}
@@ -0,0 +1,42 @@
// EXPECTED_DUPLICATED_HIGHLIGHTING
val <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY">packageSize</info> = 0
val <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION"><info textAttributesKey="KOTLIN_PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION">packageSizeGetter</info></info>
<info textAttributesKey="KOTLIN_KEYWORD">get</info>() = <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY">packageSize</info> * 2
var <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE"><info textAttributesKey="KOTLIN_PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION">packageSizeSetter</info></info></info> = 5
<info textAttributesKey="KOTLIN_KEYWORD">set</info>(<info textAttributesKey="KOTLIN_PARAMETER">value</info>) {
<info textAttributesKey="KOTLIN_BACKING_FIELD_VARIABLE"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE">field</info></info> = <info textAttributesKey="KOTLIN_PARAMETER">value</info> * 2
}
var <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION"><info textAttributesKey="KOTLIN_PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE">packageSizeBean</info></info></info> = 5
<info textAttributesKey="KOTLIN_KEYWORD">get</info>() = <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY">packageSize</info> * 2
<info textAttributesKey="KOTLIN_KEYWORD">set</info>(<info textAttributesKey="KOTLIN_PARAMETER">value</info>) {
<info textAttributesKey="KOTLIN_MUTABLE_VARIABLE"><info textAttributesKey="KOTLIN_BACKING_FIELD_VARIABLE">field</info></info> = <info textAttributesKey="KOTLIN_PARAMETER">value</info> * 2
}
class <info textAttributesKey="KOTLIN_CLASS">test</info>() {
// no highlighting check
val <info textAttributesKey="KOTLIN_INSTANCE_PROPERTY">size</info> = 0
val <info textAttributesKey="KOTLIN_INSTANCE_PROPERTY">classSize</info> = 0
val <info textAttributesKey="KOTLIN_INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION"><info textAttributesKey="KOTLIN_INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION">classSizeGetter</info></info>
<info textAttributesKey="KOTLIN_KEYWORD">get</info>() = <info textAttributesKey="KOTLIN_INSTANCE_PROPERTY">classSize</info> * 2
var <info textAttributesKey="KOTLIN_INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION"><info textAttributesKey="KOTLIN_INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE">classSizeSetter</info></info></info> = 5
<info textAttributesKey="KOTLIN_KEYWORD">set</info>(<info textAttributesKey="KOTLIN_PARAMETER">value</info>) {
<info textAttributesKey="KOTLIN_BACKING_FIELD_VARIABLE"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE">field</info></info> = <info textAttributesKey="KOTLIN_PARAMETER">value</info> * 2
}
var <info textAttributesKey="KOTLIN_INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE"><info textAttributesKey="KOTLIN_INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION">classSizeBean</info></info></info> = 5
<info textAttributesKey="KOTLIN_KEYWORD">get</info>() = <info textAttributesKey="KOTLIN_INSTANCE_PROPERTY">classSize</info> * 2
<info textAttributesKey="KOTLIN_KEYWORD">set</info>(<info textAttributesKey="KOTLIN_PARAMETER">value</info>) {
<info textAttributesKey="KOTLIN_MUTABLE_VARIABLE"><info textAttributesKey="KOTLIN_BACKING_FIELD_VARIABLE">field</info></info> = <info textAttributesKey="KOTLIN_PARAMETER">value</info> * 2
}
fun <info textAttributesKey="KOTLIN_FUNCTION_DECLARATION">callCustomPD</info>() {
<info textAttributesKey="KOTLIN_MUTABLE_VARIABLE"><info textAttributesKey="KOTLIN_INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION"><info textAttributesKey="KOTLIN_INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION">classSizeBean</info></info></info> = 30
}
}
+15
View File
@@ -0,0 +1,15 @@
<info textAttributesKey="KOTLIN_BUILTIN_ANNOTATION">suspend</info> fun <info textAttributesKey="KOTLIN_FUNCTION_DECLARATION">letsDoSuspendLambda</info>(<info textAttributesKey="KOTLIN_PARAMETER">block</info>: <info textAttributesKey="KOTLIN_BUILTIN_ANNOTATION">suspend</info> () -> <info textAttributesKey="KOTLIN_OBJECT">Unit</info>) {
val <info textAttributesKey="KOTLIN_LOCAL_VARIABLE">res</info> : <info textAttributesKey="KOTLIN_BUILTIN_ANNOTATION">suspend</info> (<info textAttributesKey="KOTLIN_CLASS">Int</info>) -> <info textAttributesKey="KOTLIN_CLASS">Int</info> = { <info textAttributesKey="KOTLIN_PARAMETER"><info textAttributesKey="KOTLIN_CLOSURE_DEFAULT_PARAMETER" descr=Automatically declared based on the expected type>it</info></info> + 1 };
<info textAttributesKey="KOTLIN_SUSPEND_FUNCTION_CALL">letsDoSomething</info> { <warning textAttributesKey="WARNING_ATTRIBUTES" descr=[UNUSED_EXPRESSION] The expression is unused><info textAttributesKey="KOTLIN_WRAPPED_INTO_REF" descr=Value captured in a closure>block</info></warning> }
<info textAttributesKey="KOTLIN_LOCAL_VARIABLE"><info textAttributesKey="KOTLIN_SUSPEND_FUNCTION_CALL">res</info></info>(5)
<info textAttributesKey="KOTLIN_WRAPPED_INTO_REF" descr=Value captured in a closure><info textAttributesKey="KOTLIN_SUSPEND_FUNCTION_CALL">block</info></info>()
}
<info textAttributesKey="KOTLIN_BUILTIN_ANNOTATION">suspend</info> fun <info textAttributesKey="KOTLIN_FUNCTION_DECLARATION">letsDoSomething</info>(<info textAttributesKey="KOTLIN_PARAMETER">block</info>: <info textAttributesKey="KOTLIN_BUILTIN_ANNOTATION">suspend</info> () -> <info textAttributesKey="KOTLIN_OBJECT">Unit</info>) {
<info textAttributesKey="KOTLIN_SUSPEND_FUNCTION_CALL">doSomething</info>()
<info textAttributesKey="KOTLIN_SUSPEND_FUNCTION_CALL"><info textAttributesKey="KOTLIN_PARAMETER">block</info></info>()
}
<info textAttributesKey="KOTLIN_BUILTIN_ANNOTATION">suspend</info> fun <info textAttributesKey="KOTLIN_FUNCTION_DECLARATION">doSomething</info>() {
}
+3 -3
View File
@@ -7,7 +7,7 @@ val <info textAttributesKey="KOTLIN_CLASS">Int</info>.<info textAttributesKey="K
return this * this
}
val <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY">y</info> : <info textAttributesKey="KOTLIN_CLASS">Int</info> = 1
val <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY_CUSTOM_PROPERTY_DECLARATION">y</info> : <info textAttributesKey="KOTLIN_CLASS">Int</info> = 1
<info textAttributesKey="KOTLIN_KEYWORD">get</info>() {
return 5.<info textAttributesKey="KOTLIN_EXTENSION_PROPERTY">sq</info> + <info textAttributesKey="KOTLIN_BACKING_FIELD_VARIABLE">field</info> + <info textAttributesKey="KOTLIN_PACKAGE_PROPERTY"><info textAttributesKey="KOTLIN_MUTABLE_VARIABLE">x</info></info>
}
@@ -17,13 +17,13 @@ class <info textAttributesKey="KOTLIN_CLASS">Foo</info>(
<info textAttributesKey="KOTLIN_PARAMETER">b</info> : <info textAttributesKey="KOTLIN_CLASS">String</info>,
var <info textAttributesKey="KOTLIN_MUTABLE_VARIABLE"><info textAttributesKey="KOTLIN_INSTANCE_PROPERTY">c</info></info> : <info textAttributesKey="KOTLIN_CLASS">String</info>
) {
<info>init</info> {
<info textAttributesKey="KOTLIN_KEYWORD">init</info> {
<info textAttributesKey="KOTLIN_PARAMETER">b</info>
}
fun <info textAttributesKey="KOTLIN_FUNCTION_DECLARATION">f</info>(<info textAttributesKey="KOTLIN_PARAMETER">p</info> : <info textAttributesKey="KOTLIN_CLASS">Int</info> = <info textAttributesKey="KOTLIN_INSTANCE_PROPERTY">a</info>) {}
var <info textAttributesKey="KOTLIN_MUTABLE_VARIABLE"><info textAttributesKey="KOTLIN_INSTANCE_PROPERTY">v</info></info> : <info textAttributesKey="KOTLIN_CLASS">Int</info>
var <info textAttributesKey="KOTLIN_MUTABLE_VARIABLE"><info textAttributesKey="KOTLIN_INSTANCE_PROPERTY_CUSTOM_PROPERTY_DECLARATION">v</info></info> : <info textAttributesKey="KOTLIN_CLASS">Int</info>
<info textAttributesKey="KOTLIN_KEYWORD">get</info>() {
return 1;
}
@@ -143,6 +143,11 @@ public class HighlightingTestGenerated extends AbstractHighlightingTest {
runTest("idea/testData/highlighter/VariablesAsFunctions.kt");
}
@TestMetadata("PropertiesWithPropertyDeclarations.kt")
public void testPropertiesWithPropertyDeclarations() throws Exception {
runTest("idea/testData/highlighter/PropertiesWithPropertyDeclarations.kt");
}
@TestMetadata("idea/testData/highlighter/deprecated")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)