Code Insight: Preserve identifier quotes in "Generate equals()/hashCode()/toString()" actions
#KT-15883 Fixed
This commit is contained in:
+4
-2
@@ -21,12 +21,14 @@ import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.CollectingNameValidator
|
||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.core.insertMembersAfter
|
||||
@@ -154,7 +156,7 @@ class KotlinGenerateEqualsAndHashcodeAction : KotlinGenerateMemberActionBase<Kot
|
||||
append('\n')
|
||||
|
||||
variablesForEquals.forEach {
|
||||
val propName = it.name.asString()
|
||||
val propName = (DescriptorToSourceUtilsIde.getAnyDeclaration(project, it) as PsiNameIdentifierOwner).nameIdentifier!!.text
|
||||
val notEquals = when {
|
||||
KotlinBuiltIns.isArray(it.type) || KotlinBuiltIns.isPrimitiveArray(it.type) ->
|
||||
"!java.util.Arrays.equals($propName, $paramName.$propName)"
|
||||
@@ -178,7 +180,7 @@ class KotlinGenerateEqualsAndHashcodeAction : KotlinGenerateMemberActionBase<Kot
|
||||
|
||||
private fun generateHashCode(project: Project, info: Info): KtNamedFunction? {
|
||||
fun VariableDescriptor.genVariableHashCode(parenthesesNeeded: Boolean): String {
|
||||
val ref = name.asString().quoteIfNeeded()
|
||||
val ref = (DescriptorToSourceUtilsIde.getAnyDeclaration(project, this) as PsiNameIdentifierOwner).nameIdentifier!!.text
|
||||
val isNullable = TypeUtils.isNullableType(type)
|
||||
|
||||
val builtIns = builtIns
|
||||
|
||||
+11
-7
@@ -23,6 +23,7 @@ import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.DialogWrapper
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.PsiNameIdentifierOwner
|
||||
import com.intellij.util.IncorrectOperationException
|
||||
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
|
||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||
@@ -30,11 +31,11 @@ import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
|
||||
import org.jetbrains.kotlin.idea.core.insertMembersAfter
|
||||
import org.jetbrains.kotlin.idea.core.quoteIfNeeded
|
||||
import org.jetbrains.kotlin.idea.core.util.DescriptorMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.util.application.runWriteAction
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
@@ -57,7 +58,8 @@ class KotlinGenerateToStringAction : KotlinGenerateMemberActionBase<KotlinGenera
|
||||
data class Info(val classDescriptor: ClassDescriptor,
|
||||
val variablesToUse: List<VariableDescriptor>,
|
||||
val generateSuperCall: Boolean,
|
||||
val generator: Generator)
|
||||
val generator: Generator,
|
||||
val project: Project)
|
||||
|
||||
enum class Generator(val text: String) {
|
||||
SINGLE_TEMPLATE("Single template") {
|
||||
@@ -67,7 +69,7 @@ class KotlinGenerateToStringAction : KotlinGenerateMemberActionBase<KotlinGenera
|
||||
return buildString {
|
||||
append("return \"${className.quoteIfNeeded()}(")
|
||||
info.variablesToUse.joinTo(this) {
|
||||
val ref = it.name.asString().quoteIfNeeded()
|
||||
val ref = (DescriptorToSourceUtilsIde.getAnyDeclaration(info.project, it) as PsiNameIdentifierOwner).nameIdentifier!!.text
|
||||
"$ref=${renderVariableValue(it, ref)}"
|
||||
}
|
||||
append(")")
|
||||
@@ -89,7 +91,7 @@ class KotlinGenerateToStringAction : KotlinGenerateMemberActionBase<KotlinGenera
|
||||
val varIterator = info.variablesToUse.iterator()
|
||||
while (varIterator.hasNext()) {
|
||||
val it = varIterator.next()
|
||||
val ref = it.name.asString().quoteIfNeeded()
|
||||
val ref = (DescriptorToSourceUtilsIde.getAnyDeclaration(info.project, it) as PsiNameIdentifierOwner).nameIdentifier!!.text
|
||||
append("\"$ref=${renderVariableValue(it, ref)}")
|
||||
if (varIterator.hasNext()) {
|
||||
append(',')
|
||||
@@ -152,7 +154,8 @@ class KotlinGenerateToStringAction : KotlinGenerateMemberActionBase<KotlinGenera
|
||||
val info = Info(classDescriptor,
|
||||
properties.map { context[BindingContext.DECLARATION_TO_DESCRIPTOR, it] as VariableDescriptor },
|
||||
false,
|
||||
Generator.SINGLE_TEMPLATE)
|
||||
Generator.SINGLE_TEMPLATE,
|
||||
project)
|
||||
return klass.adjuster?.let { it(info) } ?: info
|
||||
}
|
||||
|
||||
@@ -172,7 +175,8 @@ class KotlinGenerateToStringAction : KotlinGenerateMemberActionBase<KotlinGenera
|
||||
return Info(classDescriptor,
|
||||
chooser.selectedElements?.map { it.descriptor as VariableDescriptor } ?: emptyList(),
|
||||
headerPanel.isGenerateSuperCall,
|
||||
headerPanel.selectedGenerator)
|
||||
headerPanel.selectedGenerator,
|
||||
project)
|
||||
}
|
||||
|
||||
private fun generateToString(project: Project, info: Info): KtNamedFunction? {
|
||||
|
||||
@@ -22,8 +22,10 @@ import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.ui.Messages
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
||||
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.OverrideMemberChooserObject
|
||||
import org.jetbrains.kotlin.idea.core.overrideImplement.generateMember
|
||||
import org.jetbrains.kotlin.idea.core.quoteIfNeeded
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
@@ -56,6 +58,8 @@ fun getPropertiesToUseInGeneratedMember(classOrObject: KtClassOrObject): List<Kt
|
||||
else -> false
|
||||
}
|
||||
}
|
||||
}.filter {
|
||||
KotlinNameSuggester.isIdentifier(it.name?.quoteIfNeeded())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
class Example(val `in`: String, val `cl ass`: String, val `valid`: Boolean) {
|
||||
<caret>
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
class Example(val `in`: String, val `cl ass`: String, val `valid`: Boolean) {
|
||||
override fun equals(other: Any?): Boolean {
|
||||
if (this === other) return true
|
||||
if (other?.javaClass != javaClass) return false
|
||||
|
||||
other as Example
|
||||
|
||||
if (`in` != other.`in`) return false
|
||||
if (`cl ass` != other.`cl ass`) return false
|
||||
if (`valid` != other.`valid`) return false
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
override fun hashCode(): Int {
|
||||
var result = `in`.hashCode()
|
||||
result = 31 * result + `cl ass`.hashCode()
|
||||
result = 31 * result + `valid`.hashCode()
|
||||
return result
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
// GENERATOR: MULTIPLE_TEMPLATES
|
||||
class Example(val `in`: String, val `cl ass`: String, val `valid`: Boolean) {
|
||||
<caret>
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
// GENERATOR: MULTIPLE_TEMPLATES
|
||||
class Example(val `in`: String, val `cl ass`: String, val `valid`: Boolean) {
|
||||
override fun toString(): String {
|
||||
return "Example(" +
|
||||
"`in`='$`in`'," +
|
||||
"`cl ass`='$`cl ass`'," +
|
||||
"`valid`=$`valid`" +
|
||||
")"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
class Example(val `in`: String, val `cl ass`: String, val `valid`: Boolean) {
|
||||
<caret>
|
||||
}
|
||||
+5
@@ -0,0 +1,5 @@
|
||||
class Example(val `in`: String, val `cl ass`: String, val `valid`: Boolean) {
|
||||
override fun toString(): String {
|
||||
return "Example(`in`='$`in`', `cl ass`='$`cl ass`', `valid`=$`valid`)"
|
||||
}
|
||||
}
|
||||
+6
@@ -90,6 +90,12 @@ public class GenerateHashCodeAndEqualsActionTestGenerated extends AbstractGenera
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("keepQuotes.kt")
|
||||
public void testKeepQuotes() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/keepQuotes.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleVars.kt")
|
||||
public void testMultipleVars() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/generate/equalsWithHashCode/multipleVars.kt");
|
||||
|
||||
+12
@@ -89,6 +89,12 @@ public class GenerateToStringActionTestGenerated extends AbstractGenerateToStrin
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("keepQuotes.kt")
|
||||
public void testKeepQuotes() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/generate/toString/multipeTemplates/keepQuotes.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleVars.kt")
|
||||
public void testMultipleVars() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/generate/toString/multipeTemplates/multipleVars.kt");
|
||||
@@ -152,6 +158,12 @@ public class GenerateToStringActionTestGenerated extends AbstractGenerateToStrin
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("keepQuotes.kt")
|
||||
public void testKeepQuotes() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/generate/toString/singleTemplate/keepQuotes.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("multipleVars.kt")
|
||||
public void testMultipleVars() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/codeInsight/generate/toString/singleTemplate/multipleVars.kt");
|
||||
|
||||
Reference in New Issue
Block a user