mirror of
https://github.com/jlengrand/kotlin.git
synced 2026-03-15 08:31:27 +00:00
KT-9839 related, secondary constructor to primary: inspection for the single constructor
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
<html>
|
||||
<body>
|
||||
This inspection reports secondary constructor that can be replaced with more concise primary constructor
|
||||
</body>
|
||||
</html>
|
||||
@@ -1771,6 +1771,14 @@
|
||||
language="kotlin"
|
||||
/>
|
||||
|
||||
<localInspection implementationClass="org.jetbrains.kotlin.idea.intentions.ConvertSecondaryConstructorToPrimaryInspection"
|
||||
displayName="Convert to primary constructor"
|
||||
groupName="Kotlin"
|
||||
enabledByDefault="true"
|
||||
level="WARNING"
|
||||
language="kotlin"
|
||||
/>
|
||||
|
||||
<referenceImporter implementation="org.jetbrains.kotlin.idea.quickfix.KotlinReferenceImporter"/>
|
||||
|
||||
<fileType.fileViewProviderFactory filetype="KJSM" implementationClass="com.intellij.psi.ClassFileViewProviderFactory"/>
|
||||
|
||||
@@ -17,17 +17,26 @@
|
||||
package org.jetbrains.kotlin.idea.intentions
|
||||
|
||||
import com.intellij.openapi.editor.Editor
|
||||
import com.intellij.openapi.util.TextRange
|
||||
import org.jetbrains.kotlin.descriptors.*
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
|
||||
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
|
||||
import org.jetbrains.kotlin.idea.util.CommentSaver
|
||||
import org.jetbrains.kotlin.lexer.KtTokens
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClass
|
||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||
import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
|
||||
|
||||
class ConvertSecondaryConstructorToPrimaryIntention : SelfTargetingIntention<KtSecondaryConstructor>(
|
||||
class ConvertSecondaryConstructorToPrimaryInspection : IntentionBasedInspection<KtSecondaryConstructor>(
|
||||
ConvertSecondaryConstructorToPrimaryIntention::class,
|
||||
{ constructor -> constructor.containingClass()?.getSecondaryConstructors()?.size == 1 }
|
||||
) {
|
||||
override fun inspectionTarget(element: KtSecondaryConstructor) = element.getConstructorKeyword()
|
||||
}
|
||||
|
||||
class ConvertSecondaryConstructorToPrimaryIntention : SelfTargetingRangeIntention<KtSecondaryConstructor>(
|
||||
KtSecondaryConstructor::class.java,
|
||||
"Convert to primary constructor"
|
||||
) {
|
||||
@@ -41,22 +50,22 @@ class ConvertSecondaryConstructorToPrimaryIntention : SelfTargetingIntention<KtS
|
||||
return isReachableByDelegationFrom(delegationDescriptor, context, visited + constructor)
|
||||
}
|
||||
|
||||
override fun isApplicableTo(element: KtSecondaryConstructor, caretOffset: Int): Boolean {
|
||||
override fun applicabilityRange(element: KtSecondaryConstructor): TextRange? {
|
||||
val delegationCall = element.getDelegationCall()
|
||||
if (delegationCall.isCallToThis) return false
|
||||
val klass = element.containingClassOrObject ?: return false
|
||||
if (klass.hasPrimaryConstructor()) return false
|
||||
if (delegationCall.isCallToThis) return null
|
||||
val klass = element.containingClassOrObject ?: return null
|
||||
if (klass.hasPrimaryConstructor()) return null
|
||||
|
||||
val context = klass.analyze()
|
||||
val classDescriptor = context[BindingContext.CLASS, klass] ?: return false
|
||||
val elementDescriptor = context[BindingContext.CONSTRUCTOR, element] ?: return false
|
||||
val context = klass.analyzeFully()
|
||||
val classDescriptor = context[BindingContext.CLASS, klass] ?: return null
|
||||
val elementDescriptor = context[BindingContext.CONSTRUCTOR, element] ?: return null
|
||||
|
||||
for (constructorDescriptor in classDescriptor.constructors) {
|
||||
if (constructorDescriptor == elementDescriptor) continue
|
||||
if (!elementDescriptor.isReachableByDelegationFrom(constructorDescriptor, context)) return false
|
||||
if (!elementDescriptor.isReachableByDelegationFrom(constructorDescriptor, context)) return null
|
||||
}
|
||||
|
||||
return true
|
||||
return element.textRange
|
||||
}
|
||||
|
||||
private fun KtExpression.tryConvertToPropertyByParameterInitialization(
|
||||
|
||||
10
idea/testData/inspections/convertSecondaryToPrimary/inspectionData/expected.xml
vendored
Normal file
10
idea/testData/inspections/convertSecondaryToPrimary/inspectionData/expected.xml
vendored
Normal file
@@ -0,0 +1,10 @@
|
||||
<problems>
|
||||
<problem>
|
||||
<file>test.kt</file>
|
||||
<line>5</line>
|
||||
<module>light_idea_test_case</module>
|
||||
<entry_point TYPE="file" FQNAME="temp:///src/test.kt" />
|
||||
<problem_class severity="WARNING" attribute_key="WARNING_ATTRIBUTES">Convert to primary constructor</problem_class>
|
||||
<description>Convert to primary constructor</description>
|
||||
</problem>
|
||||
</problems>
|
||||
1
idea/testData/inspections/convertSecondaryToPrimary/inspectionData/inspections.test
vendored
Normal file
1
idea/testData/inspections/convertSecondaryToPrimary/inspectionData/inspections.test
vendored
Normal file
@@ -0,0 +1 @@
|
||||
// INSPECTION_CLASS: org.jetbrains.kotlin.idea.intentions.ConvertSecondaryConstructorToPrimaryInspection
|
||||
19
idea/testData/inspections/convertSecondaryToPrimary/test.kt
vendored
Normal file
19
idea/testData/inspections/convertSecondaryToPrimary/test.kt
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
class Single {
|
||||
|
||||
val x: Int
|
||||
|
||||
constructor(x: Int) {
|
||||
this.x = x
|
||||
}
|
||||
}
|
||||
|
||||
class NotSingle {
|
||||
|
||||
val x: Int
|
||||
|
||||
constructor(): this(42)
|
||||
|
||||
constructor(x: Int) {
|
||||
this.x = x
|
||||
}
|
||||
}
|
||||
@@ -154,6 +154,12 @@ public class InspectionTestGenerated extends AbstractInspectionTest {
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("convertSecondaryToPrimary/inspectionData/inspections.test")
|
||||
public void testConvertSecondaryToPrimary_inspectionData_Inspections_test() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspections/convertSecondaryToPrimary/inspectionData/inspections.test");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("equalsAndHashCode/inspectionData/inspections.test")
|
||||
public void testEqualsAndHashCode_inspectionData_Inspections_test() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/inspections/equalsAndHashCode/inspectionData/inspections.test");
|
||||
|
||||
Reference in New Issue
Block a user