Changed synthetic properties naming for getters starting with "is"
This commit is contained in:
+31
-10
@@ -45,7 +45,9 @@ interface SyntheticJavaPropertyDescriptor : PropertyDescriptor {
|
|||||||
companion object {
|
companion object {
|
||||||
fun findByGetterOrSetter(getterOrSetter: FunctionDescriptor, resolutionScope: JetScope): SyntheticJavaPropertyDescriptor? {
|
fun findByGetterOrSetter(getterOrSetter: FunctionDescriptor, resolutionScope: JetScope): SyntheticJavaPropertyDescriptor? {
|
||||||
val name = getterOrSetter.getName()
|
val name = getterOrSetter.getName()
|
||||||
if (propertyNameByGetMethodName(name) == null && propertyNameBySetMethodName(name) == null) return null // optimization
|
if (name.isSpecial()) return null
|
||||||
|
val identifier = name.getIdentifier()
|
||||||
|
if (!identifier.startsWith("get") && !identifier.startsWith("is") && !identifier.startsWith("set")) return null // optimization
|
||||||
|
|
||||||
val owner = getterOrSetter.getContainingDeclaration()
|
val owner = getterOrSetter.getContainingDeclaration()
|
||||||
if (owner !is JavaClassDescriptor) return null
|
if (owner !is JavaClassDescriptor) return null
|
||||||
@@ -56,15 +58,22 @@ interface SyntheticJavaPropertyDescriptor : PropertyDescriptor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun propertyNameByGetMethodName(methodName: Name): Name?
|
fun propertyNameByGetMethodName(methodName: Name): Name?
|
||||||
= propertyNameFromAccessorMethodName(methodName, "get") ?: propertyNameFromAccessorMethodName(methodName, "is")
|
= propertyNameFromAccessorMethodName(methodName, "get") ?: propertyNameFromAccessorMethodName(methodName, "is", removePrefix = false)
|
||||||
|
|
||||||
fun propertyNameBySetMethodName(methodName: Name): Name?
|
fun propertyNameBySetMethodName(methodName: Name, withIsPrefix: Boolean): Name?
|
||||||
= propertyNameFromAccessorMethodName(methodName, "set")
|
= propertyNameFromAccessorMethodName(methodName, "set", addPrefix = if (withIsPrefix) "is" else null)
|
||||||
|
|
||||||
private fun propertyNameFromAccessorMethodName(methodName: Name, prefix: String): Name? {
|
private fun propertyNameFromAccessorMethodName(methodName: Name, prefix: String, removePrefix: Boolean = true, addPrefix: String? = null): Name? {
|
||||||
if (methodName.isSpecial()) return null
|
if (methodName.isSpecial()) return null
|
||||||
val identifier = methodName.getIdentifier()
|
val identifier = methodName.getIdentifier()
|
||||||
if (!identifier.startsWith(prefix)) return null
|
if (!identifier.startsWith(prefix)) return null
|
||||||
|
|
||||||
|
if (addPrefix != null) {
|
||||||
|
assert(removePrefix)
|
||||||
|
return Name.identifier(addPrefix + identifier.removePrefix(prefix))
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!removePrefix) return methodName
|
||||||
val name = Introspector.decapitalize(identifier.removePrefix(prefix))
|
val name = Introspector.decapitalize(identifier.removePrefix(prefix))
|
||||||
if (!Name.isValidIdentifier(name)) return null
|
if (!Name.isValidIdentifier(name)) return null
|
||||||
return Name.identifier(name)
|
return Name.identifier(name)
|
||||||
@@ -103,7 +112,7 @@ class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by
|
|||||||
.singleOrNull { isGoodGetMethod(it) } ?: return null
|
.singleOrNull { isGoodGetMethod(it) } ?: return null
|
||||||
|
|
||||||
val propertyType = getMethod.getReturnType() ?: return null
|
val propertyType = getMethod.getReturnType() ?: return null
|
||||||
val setMethod = memberScope.getFunctions(possibleSetMethodName(name)).singleOrNull { isGoodSetMethod(it, propertyType) }
|
val setMethod = memberScope.getFunctions(setMethodName(getMethod.getName())).singleOrNull { isGoodSetMethod(it, propertyType) }
|
||||||
|
|
||||||
return MyPropertyDescriptor(javaClass, getMethod, setMethod, name, propertyType, type)
|
return MyPropertyDescriptor(javaClass, getMethod, setMethod, name, propertyType, type)
|
||||||
}
|
}
|
||||||
@@ -177,12 +186,24 @@ class JavaSyntheticExtensionsScope(storageManager: StorageManager) : JetScope by
|
|||||||
//TODO: reuse code with generation?
|
//TODO: reuse code with generation?
|
||||||
|
|
||||||
private fun possibleGetMethodNames(propertyName: Name): Collection<Name> {
|
private fun possibleGetMethodNames(propertyName: Name): Collection<Name> {
|
||||||
val capitalized = propertyName.getIdentifier().capitalize()
|
val identifier = propertyName.getIdentifier()
|
||||||
return listOf(Name.identifier("get" + capitalized), Name.identifier("is" + capitalized))
|
val getPrefixName = Name.identifier("get" + identifier.capitalize())
|
||||||
|
if (identifier.startsWith("is")) {
|
||||||
|
return listOf(propertyName, getPrefixName)
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return listOf(getPrefixName)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun possibleSetMethodName(propertyName: Name): Name {
|
private fun setMethodName(getMethodName: Name): Name {
|
||||||
return Name.identifier("set" + propertyName.getIdentifier().capitalize())
|
val identifier = getMethodName.getIdentifier()
|
||||||
|
val prefix = when {
|
||||||
|
identifier.startsWith("get") -> "get"
|
||||||
|
identifier.startsWith("is") -> "is"
|
||||||
|
else -> throw IllegalArgumentException()
|
||||||
|
}
|
||||||
|
return Name.identifier("set" + identifier.removePrefix(prefix).capitalize())
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MyPropertyDescriptor(
|
private class MyPropertyDescriptor(
|
||||||
|
|||||||
@@ -1,13 +1,30 @@
|
|||||||
// FILE: KotlinFile.kt
|
// FILE: KotlinFile.kt
|
||||||
fun foo(javaClass: JavaClass) {
|
fun foo(javaClass: JavaClass) {
|
||||||
javaClass.something = !javaClass.something
|
javaClass.isSomething = !javaClass.isSomething
|
||||||
|
javaClass.isSomething2 = !javaClass.isSomething2
|
||||||
|
|
||||||
|
javaClass.<!UNRESOLVED_REFERENCE!>something<!>
|
||||||
|
javaClass.<!FUNCTION_CALL_EXPECTED!>isSomethingWrong<!>
|
||||||
javaClass.<!UNRESOLVED_REFERENCE!>somethingWrong<!>
|
javaClass.<!UNRESOLVED_REFERENCE!>somethingWrong<!>
|
||||||
}
|
}
|
||||||
|
|
||||||
// FILE: JavaClass.java
|
// FILE: JavaClass.java
|
||||||
public class JavaClass {
|
public class JavaClass {
|
||||||
public boolean isSomething() { return true; }
|
public boolean isSomething() {
|
||||||
public void setSomething(boolean value) { }
|
return true;
|
||||||
public int isSomethingWrong() { return 1; }
|
}
|
||||||
|
|
||||||
|
public void setSomething(boolean value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean getIsSomething2() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIsSomething2(boolean value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
public int isSomethingWrong() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -5,9 +5,11 @@ internal fun foo(/*0*/ javaClass: JavaClass): kotlin.Unit
|
|||||||
public open class JavaClass {
|
public open class JavaClass {
|
||||||
public constructor JavaClass()
|
public constructor JavaClass()
|
||||||
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
|
||||||
|
public open fun getIsSomething2(): kotlin.Boolean
|
||||||
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
|
||||||
public open fun isSomething(): kotlin.Boolean
|
public open fun isSomething(): kotlin.Boolean
|
||||||
public open fun isSomethingWrong(): kotlin.Int
|
public open fun isSomethingWrong(): kotlin.Int
|
||||||
|
public open fun setIsSomething2(/*0*/ value: kotlin.Boolean): kotlin.Unit
|
||||||
public open fun setSomething(/*0*/ value: kotlin.Boolean): kotlin.Unit
|
public open fun setSomething(/*0*/ value: kotlin.Boolean): kotlin.Unit
|
||||||
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
|
||||||
}
|
}
|
||||||
|
|||||||
+9
-4
@@ -21,11 +21,12 @@ import com.intellij.psi.PsiElement
|
|||||||
import com.intellij.util.SmartList
|
import com.intellij.util.SmartList
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.JetNameReferenceExpression
|
import org.jetbrains.kotlin.psi.JetNameReferenceExpression
|
||||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.startOffset
|
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
import org.jetbrains.kotlin.resolve.BindingContext
|
||||||
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor
|
||||||
import org.jetbrains.kotlin.utils.addIfNotNull
|
import org.jetbrains.kotlin.utils.addIfNotNull
|
||||||
|
|
||||||
@@ -56,10 +57,14 @@ sealed class SyntheticPropertyAccessorReference(expression: JetNameReferenceExpr
|
|||||||
if (!Name.isValidIdentifier(newElementName!!)) return expression
|
if (!Name.isValidIdentifier(newElementName!!)) return expression
|
||||||
|
|
||||||
val newNameAsName = Name.identifier(newElementName)
|
val newNameAsName = Name.identifier(newElementName)
|
||||||
val newName = if (getter)
|
val newName = if (getter) {
|
||||||
SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(newNameAsName)
|
SyntheticJavaPropertyDescriptor.propertyNameByGetMethodName(newNameAsName)
|
||||||
else
|
}
|
||||||
SyntheticJavaPropertyDescriptor.propertyNameBySetMethodName(newNameAsName)
|
else {
|
||||||
|
val propertyDescriptor = super.getTargetDescriptors(expression.analyze(BodyResolveMode.PARTIAL))
|
||||||
|
.singleOrNull { it is SyntheticJavaPropertyDescriptor } ?: return expression
|
||||||
|
SyntheticJavaPropertyDescriptor.propertyNameBySetMethodName(newNameAsName, withIsPrefix = propertyDescriptor.getName().asString().startsWith("is"))
|
||||||
|
}
|
||||||
if (newName == null) return expression //TODO: handle the case when get/set becomes ordinary method
|
if (newName == null) return expression //TODO: handle the case when get/set becomes ordinary method
|
||||||
|
|
||||||
val nameIdentifier = JetPsiFactory(expression).createNameIdentifier(newName.getIdentifier())
|
val nameIdentifier = JetPsiFactory(expression).createNameIdentifier(newName.getIdentifier())
|
||||||
|
|||||||
+2
-2
@@ -5,10 +5,10 @@ fun Thread.foo(urlConnection: java.net.URLConnection) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// EXIST_JAVA_ONLY: { lookupString: "priority", itemText: "priority", tailText: " (from getPriority()/setPriority())", typeText: "Int" }
|
// EXIST_JAVA_ONLY: { lookupString: "priority", itemText: "priority", tailText: " (from getPriority()/setPriority())", typeText: "Int" }
|
||||||
// EXIST_JAVA_ONLY: { lookupString: "daemon", itemText: "daemon", tailText: " (from isDaemon()/setDaemon())", typeText: "Boolean" }
|
// EXIST_JAVA_ONLY: { lookupString: "isDaemon", itemText: "isDaemon", tailText: " (from isDaemon()/setDaemon())", typeText: "Boolean" }
|
||||||
// EXIST_JAVA_ONLY: { lookupString: "URL", itemText: "URL", tailText: " (from getURL())", typeText: "URL!" }
|
// EXIST_JAVA_ONLY: { lookupString: "URL", itemText: "URL", tailText: " (from getURL())", typeText: "URL!" }
|
||||||
// ABSENT: getPriority
|
// ABSENT: getPriority
|
||||||
// ABSENT: setPriority
|
// ABSENT: setPriority
|
||||||
// ABSENT: isDaemon
|
// ABSENT: { itemText: "isDaemon", tailText: "()" }
|
||||||
// ABSENT: setDaemon
|
// ABSENT: setDaemon
|
||||||
// ABSENT: getURL
|
// ABSENT: getURL
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun foo(thread: Thread) {
|
||||||
|
thread.<caret>isDaemon()
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun foo(thread: Thread) {
|
||||||
|
thread.<caret>isDaemon
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun foo(thread: Thread) {
|
||||||
|
thread.<caret>setDaemon(true)
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
// WITH_RUNTIME
|
||||||
|
fun foo(thread: Thread) {
|
||||||
|
thread.<caret>isDaemon = true
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import testing.JavaClass
|
||||||
|
|
||||||
|
fun usages(javaClass: JavaClass) {
|
||||||
|
javaClass.isSomethingNew = !javaClass.isSomething
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package testing;
|
||||||
|
|
||||||
|
public class JavaClass {
|
||||||
|
public boolean isSomething() { return true; }
|
||||||
|
public void setSomethingNew(boolean value) {}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
import testing.JavaClass
|
||||||
|
|
||||||
|
fun usages(javaClass: JavaClass) {
|
||||||
|
javaClass.isSomething = !javaClass.isSomething
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
package testing;
|
||||||
|
|
||||||
|
public class JavaClass {
|
||||||
|
public boolean isSomething() { return true; }
|
||||||
|
public void setSomething(boolean value) {}
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"type": "JAVA_METHOD",
|
||||||
|
"classId": "testing/JavaClass",
|
||||||
|
"methodSignature": "void setSomething(boolean value)",
|
||||||
|
"newName": "setSomethingNew"
|
||||||
|
}
|
||||||
@@ -7433,6 +7433,18 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("isGet.kt")
|
||||||
|
public void testIsGet() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/usePropertyAccessSyntax/isGet.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("isSet.kt")
|
||||||
|
public void testIsSet() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/usePropertyAccessSyntax/isSet.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("set.kt")
|
@TestMetadata("set.kt")
|
||||||
public void testSet() throws Exception {
|
public void testSet() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/usePropertyAccessSyntax/set.kt");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/intentions/usePropertyAccessSyntax/set.kt");
|
||||||
|
|||||||
@@ -382,4 +382,10 @@ public class RenameTestGenerated extends AbstractRenameTest {
|
|||||||
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/rename/syntheticPropertyUsages2/renameSetMethod.test");
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/rename/syntheticPropertyUsages2/renameSetMethod.test");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("syntheticPropertyUsages3/renameSetMethod.test")
|
||||||
|
public void testSyntheticPropertyUsages3_RenameSetMethod() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("idea/testData/refactoring/rename/syntheticPropertyUsages3/renameSetMethod.test");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user