"Create class from usage": add visibility to primary constructor if needed

#KT-29844 Fixed
This commit is contained in:
Toshiaki Kameyama
2020-01-24 15:28:49 +09:00
committed by igoriakovlev
parent b1e8238ea2
commit efa981db36
11 changed files with 84 additions and 6 deletions
@@ -531,7 +531,8 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
}
}
CallableKind.CLASS_WITH_PRIMARY_CONSTRUCTOR -> {
with((callableInfo as ClassWithPrimaryConstructorInfo).classInfo) {
val classWithPrimaryConstructorInfo = callableInfo as ClassWithPrimaryConstructorInfo
with(classWithPrimaryConstructorInfo.classInfo) {
val classBody = when (kind) {
ClassKind.ANNOTATION_CLASS, ClassKind.ENUM_ENTRY -> ""
else -> "{\n\n}"
@@ -551,8 +552,10 @@ class CallableBuilder(val config: CallableBuilderConfiguration) {
ClassKind.PLAIN_CLASS, ClassKind.INTERFACE -> "<>"
else -> ""
}
val ctor =
classWithPrimaryConstructorInfo.primaryConstructorVisibility?.name?.let { " $it constructor" } ?: ""
psiFactory.createDeclaration<KtClassOrObject>(
"$openMod$innerMod${kind.keyword} $safeName$typeParamList$paramList$returnTypeString $classBody"
"$openMod$innerMod${kind.keyword} $safeName$typeParamList$ctor$paramList$returnTypeString $classBody"
)
}
}
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder
import com.intellij.psi.PsiElement
import com.intellij.util.ArrayUtil
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny
import org.jetbrains.kotlin.idea.core.KotlinNameSuggester
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass.ClassInfo
@@ -215,7 +216,8 @@ class FunctionInfo(
class ClassWithPrimaryConstructorInfo(
val classInfo: ClassInfo,
expectedTypeInfo: TypeInfo,
modifierList: KtModifierList? = null
modifierList: KtModifierList? = null,
val primaryConstructorVisibility: Visibility? = null
) : CallableInfo(
classInfo.name,
TypeInfo.Empty,
@@ -5,8 +5,11 @@
package org.jetbrains.kotlin.idea.quickfix.createFromUsage.createClass
import org.jetbrains.kotlin.descriptors.ClassConstructorDescriptor
import org.jetbrains.kotlin.descriptors.Visibilities
import org.jetbrains.kotlin.diagnostics.Diagnostic
import org.jetbrains.kotlin.idea.caches.resolve.analyzeAndGetResult
import org.jetbrains.kotlin.idea.intentions.getCallableDescriptor
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.ParameterInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.TypeInfo
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.getTypeInfoForTypeArguments
@@ -88,13 +91,23 @@ object CreateClassFromConstructorCallActionFactory : CreateClassFromUsageFactory
val typeArgumentInfos = if (inAnnotationEntry) Collections.emptyList() else callExpr.getTypeInfoForTypeArguments()
val argumentClassVisibilities = valueArguments.mapNotNull {
(it.getArgumentExpression()?.getCallableDescriptor() as? ClassConstructorDescriptor)?.containingDeclaration?.visibility
}
val primaryConstructorVisibility = when {
Visibilities.PRIVATE in argumentClassVisibilities -> Visibilities.PRIVATE
Visibilities.INTERNAL in argumentClassVisibilities -> Visibilities.INTERNAL
else -> null
}
return ClassInfo(
name = name,
targetParents = filteredParents,
expectedTypeInfo = expectedTypeInfo,
inner = inner,
typeArguments = typeArgumentInfos,
parameterInfos = parameterInfos
parameterInfos = parameterInfos,
primaryConstructorVisibility = primaryConstructorVisibility
)
}
}
@@ -16,6 +16,7 @@ import com.intellij.openapi.ui.DialogWrapper
import com.intellij.psi.*
import org.jetbrains.annotations.Nls
import org.jetbrains.annotations.NonNls
import org.jetbrains.kotlin.descriptors.Visibility
import org.jetbrains.kotlin.idea.KotlinBundle
import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.core.getFqNameWithImplicitPrefix
@@ -67,7 +68,8 @@ data class ClassInfo(
val inner: Boolean = false,
val open: Boolean = false,
val typeArguments: List<TypeInfo> = Collections.emptyList(),
val parameterInfos: List<ParameterInfo> = Collections.emptyList()
val parameterInfos: List<ParameterInfo> = Collections.emptyList(),
val primaryConstructorVisibility: Visibility? = null
) {
val applicableParents by lazy {
targetParents.filter {
@@ -221,7 +223,8 @@ open class CreateClassFromUsageFix<E : KtElement> protected constructor(
val constructorInfo = ClassWithPrimaryConstructorInfo(
classInfo,
// Need for #KT-22137
if (expectedTypeInfo.isUnit) TypeInfo.Empty else expectedTypeInfo
if (expectedTypeInfo.isUnit) TypeInfo.Empty else expectedTypeInfo,
primaryConstructorVisibility = classInfo.primaryConstructorVisibility
)
val builder = CallableBuilderConfiguration(
Collections.singletonList(constructorInfo),
@@ -0,0 +1,5 @@
// "Create class 'Bar'" "true"
// DISABLE-ERRORS
internal class Foo
val bar = <caret>Bar(Foo())
@@ -0,0 +1,9 @@
// "Create class 'Bar'" "true"
// DISABLE-ERRORS
internal class Foo
val bar = Bar(Foo())
class Bar internal constructor(foo: Foo) {
}
@@ -0,0 +1,5 @@
// "Create class 'Bar'" "true"
// DISABLE-ERRORS
private class Foo
val bar = <caret>Bar(Foo())
@@ -0,0 +1,9 @@
// "Create class 'Bar'" "true"
// DISABLE-ERRORS
private class Foo
val bar = Bar(Foo())
class Bar private constructor(foo: Foo) {
}
@@ -0,0 +1,5 @@
// "Create class 'Bar'" "true"
// DISABLE-ERRORS
class Foo
val bar = <caret>Bar(Foo())
@@ -0,0 +1,9 @@
// "Create class 'Bar'" "true"
// DISABLE-ERRORS
class Foo
val bar = Bar(Foo())
class Bar(foo: Foo) {
}
@@ -3294,6 +3294,21 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest {
runTest("idea/testData/quickfix/createFromUsage/createClass/callExpression/notApplicableInReturn.kt");
}
@TestMetadata("parameterClassIsInternal.kt")
public void testParameterClassIsInternal() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createClass/callExpression/parameterClassIsInternal.kt");
}
@TestMetadata("parameterClassIsPrivate.kt")
public void testParameterClassIsPrivate() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createClass/callExpression/parameterClassIsPrivate.kt");
}
@TestMetadata("parameterClassIsPublic.kt")
public void testParameterClassIsPublic() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createClass/callExpression/parameterClassIsPublic.kt");
}
@TestMetadata("quotedName.kt")
public void testQuotedName() throws Exception {
runTest("idea/testData/quickfix/createFromUsage/createClass/callExpression/quotedName.kt");