Introduce Type Alias: Suggest initial name based on extracted type

This commit is contained in:
Alexey Sedunov
2016-07-19 18:08:29 +03:00
parent 0769d47f4b
commit 0a8490a068
7 changed files with 47 additions and 5 deletions
@@ -114,6 +114,27 @@ object KotlinNameSuggester {
return result
}
fun suggestTypeAliasNameByPsi(typeElement: KtTypeElement, validator: (String) -> Boolean): String {
fun KtTypeElement.render(): String {
return when (this) {
is KtNullableType -> "Nullable${innerType?.render() ?: ""}"
is KtFunctionType -> {
val arguments = listOf(receiverTypeReference).filterNotNull() + parameters.mapNotNull { it.typeReference }
val argText = arguments.joinToString(separator = "") { it.typeElement?.render() ?: "" }
val returnText = returnTypeReference?.typeElement?.render() ?: "Unit"
"${argText}To$returnText"
}
is KtUserType -> {
val argText = typeArguments.joinToString(separator = "") { it.typeReference?.typeElement?.render() ?: "" }
"$argText${referenceExpression?.text ?: ""}"
}
else -> text.capitalize()
}
}
return suggestNameByName(typeElement.render(), validator)
}
/**
* Validates name, and slightly improves it by adding number to name in case of conflicts
* @param name to check it in scope
@@ -105,7 +105,13 @@ fun IntroduceTypeAliasData.analyze(): IntroduceTypeAliasAnalysisResult {
return IntroduceTypeAliasAnalysisResult.Error("Type alias cannot refer to types which aren't accessible in the scope where it's defined")
}
return IntroduceTypeAliasAnalysisResult.Success(IntroduceTypeAliasDescriptor(this, "", null, typeParameters))
val descriptor = IntroduceTypeAliasDescriptor(this, "Dummy", null, typeParameters)
val initialName = KotlinNameSuggester.suggestTypeAliasNameByPsi(descriptor.generateTypeAlias(true).getTypeReference()!!.typeElement!!) {
targetScope.findClassifier(Name.identifier(it), NoLookupLocation.FROM_IDE) == null
}
return IntroduceTypeAliasAnalysisResult.Success(descriptor.copy(name = initialName))
}
fun IntroduceTypeAliasData.getApplicableVisibilities(): List<KtModifierKeywordToken>{
@@ -21,7 +21,6 @@ import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.ui.NameSuggestionsField;
import com.intellij.ui.TitledSeparator;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.MultiMap;
import kotlin.Unit;
import kotlin.jvm.functions.Function0;
@@ -143,7 +142,7 @@ public class KotlinIntroduceTypeAliasDialog extends DialogWrapper {
}
);
aliasNameField = new NameSuggestionsField(ArrayUtil.EMPTY_STRING_ARRAY, project, KotlinFileType.INSTANCE);
aliasNameField = new NameSuggestionsField(new String[]{originalDescriptor.getName()}, project, KotlinFileType.INSTANCE);
aliasNameField.addDataChangedListener(
new NameSuggestionsField.DataChanged() {
@Override
@@ -0,0 +1,4 @@
// SIBLING:
fun foo(list: <caret>List<(String?) -> Boolean>) {
}
@@ -0,0 +1,6 @@
typealias NullableStringToBooleanList = List<(String?) -> Boolean>
// SIBLING:
fun foo(list: NullableStringToBooleanList) {
}
@@ -320,14 +320,14 @@ abstract class AbstractExtractionTest() : KotlinLightCodeInsightFixtureTestCase(
val explicitPreviousSibling = file.findElementByCommentPrefix("// SIBLING:")
val fileText = file.text
val aliasName = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// NAME:")!!
val aliasName = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// NAME:")
val aliasVisibility = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// VISIBILITY:")?.let {
KtPsiFactory(project).createModifierList(it).firstChild.node.elementType as KtModifierKeywordToken
}
val editor = fixture.editor
KotlinIntroduceTypeAliasHandler.selectElements(editor, file) { elements, previousSibling ->
KotlinIntroduceTypeAliasHandler.doInvoke(project, editor, elements, explicitPreviousSibling ?: previousSibling) {
it.copy(name = aliasName, visibility = aliasVisibility ?: it.visibility)
it.copy(name = aliasName ?: it.name, visibility = aliasVisibility ?: it.visibility)
}
}
}
@@ -4078,6 +4078,12 @@ public class ExtractionTestGenerated extends AbstractExtractionTest {
doIntroduceTypeAliasTest(fileName);
}
@TestMetadata("suggestedName.kt")
public void testSuggestedName() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceTypeAlias/suggestedName.kt");
doIntroduceTypeAliasTest(fileName);
}
@TestMetadata("topLevelTypeAlias.kt")
public void testTopLevelTypeAlias() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/introduceTypeAlias/topLevelTypeAlias.kt");